# frv testcase to generate fp_exception
# mach: fr500
	.include "testutils.inc"

	float_constants
	start
	load_float_constants

	.global align
align:
	; clear the packing bit if the insn at 'pack:'. We can't simply use
	; '.p' because the assembler will catch the error.
	set_gr_mem	pack,gr10
	and_gr_immed	0x7fffffff,gr10
	set_mem_gr	gr10,pack
	set_gr_addr	pack,gr10
	flush_data_cache gr10

	; Make the the source register number odd at badst. We can't simply
	; code an odd register number because the assembler will catch the
	; error.
	set_gr_mem	badst,gr10
	or_gr_immed	0x02000000,gr10
	set_mem_gr	gr10,badst
	set_gr_addr	badst,gr10
	flush_data_cache gr10

	; Make the the dest register number odd at ld. We can't simply
	; code an odd register number because the assembler will catch the
	; error.
	set_gr_mem	badld,gr10
	or_gr_immed	0x02000000,gr10
	set_mem_gr	gr10,badld
	set_gr_addr	badld,gr10
	flush_data_cache gr10

	and_spr_immed	-4081,tbr		; clear tbr.tt
	set_gr_spr	tbr,gr17
	inc_gr_immed	0x070,gr17		; address of exception handler
	set_bctrlr_0_0  gr17
	inc_gr_immed	0x060,gr17		; address of exception handler
	set_bctrlr_0_0  gr17
	set_spr_immed	128,lcr
	set_spr_addr	ok1,lr
	set_psr_et	1
	inc_gr_immed	-4,sp		; for alignment

	set_gr_immed	0,gr20		; PC increment
	set_gr_immed	0,gr15

	set_spr_addr	ok3,lr
badst:	stdfi		fr0,@(sp,0)	; misaligned reg -- slot I0
	test_gr_immed	1,gr15

	set_spr_addr	ok4,lr
	nop.p
badld:	lddfi		@(sp,0),fr8	; misaligned reg -- slot I1
	test_gr_immed	2,gr15

	set_spr_addr	ok5,lr
	fnegs.p		fr9,fr9
pack:	fnegs		fr10,fr10
	fnegs		fr10,fr11	; packing violation
	test_gr_immed	3,gr15

	set_spr_addr	ok1,lr
	set_gr_immed	4,gr20		; PC increment
bad:	.word		0x83e502c4	; fmadds fr16,fr4,fr1 (unimplemented)
	test_gr_immed	4,gr15

	and_spr_immed	0xfbffffff,fsr0		; disable div/0 fp_exception
	set_fr_iimmed	0x7f7f,0xffff,fr0
	set_fr_iimmed	0x0000,0x0000,fr1
	fdivs		fr0,fr1,fr2		; div/0 -- no exception
	test_spr_bits	0x100000,20,0x1,fsr0	; fsr0.qne is still set
	test_spr_bits	0xfc00,10,0x4,fsr0	; fsr0.aexc is still set
	test_spr_bits	0xe0000,17,0x0,fsr0	; fsr0.ftt is clear
	and_spr_immed	0xffefffff,fsr0		; Clear fsr0.qne

	set_spr_addr	ok2,lr
	set_gr_immed	0,gr20			; PC increment
	or_spr_immed	0x04000000,fsr0		; enable div/0 fp_exception
	set_fr_iimmed	0xdead,0xbeef,fr2
	fdivs		fr0,fr1,fr2		; fp_exception - div/0
	test_fr_iimmed	0xdeadbeef,fr2		; fr2 not updated
	test_gr_immed	5,gr15

	and_spr_immed	0xfdffffff,fsr0		; disable inexact fp_exception
	fsqrts		fr32,fr2		; inexact -- no exception
	test_spr_bits	0x100000,20,0x1,fsr0	; fsr0.qne is still set
	test_spr_bits	0xfc00,10,0x6,fsr0	; fsr0.aexc is set
	test_spr_bits	0xe0000,17,0x0,fsr0	; fsr0.ftt is clear

	set_fr_fr	fr2,fr3			; sqrt 2
	set_fr_iimmed	0xdead,0xbeef,fr2
	set_spr_addr	ok6,lr
	or_spr_immed	0x02000000,fsr0		; enable inexact fp_exception
	fsqrts		fr32,fr2		; fp_exception - inexact
	test_gr_immed	6,gr15			; handler called
	test_fr_fr	fr2,fr3			; fr2 updated

	set_fr_iimmed	0xdead,0xbeef,fr2
	set_spr_addr	ok7,lr
	fsqrts		fr32,fr2		; fp_exception - inexact again
	test_gr_immed	7,gr15			; handler called
	test_fr_fr	fr2,fr3			; fr2 updated

	pass

; exception handler 1 -- bad insn
ok1:
	test_spr_immed	1,esfr1			; esr0 active
	test_spr_bits	0x3e,1,0x5,esr0		; esr0.ec is set
	test_spr_bits	0x1,0,0x1,esr0		; esr0.valid is set
	test_spr_addr	bad,epcr0
	bra		ret

; exception handler 2 - fp_exception: divide by 0
ok2:
	test_spr_bits	0x100000,20,0x1,fsr0	; fsr0.qne is set
	test_spr_bits	0xe0000,17,0x1,fsr0	; fsr0.ftt is set
	test_spr_bits	0xfc00,10,0x4,fsr0	; fsr0.aexc is still set

	test_spr_bits	0x80000000,31,0x0,fqst2	; fq2.miv is set
	test_spr_bits	0x18000,15,0x0,fqst2	; fq2.sie is set
	test_spr_bits	0x380,7,0x1,fqst2	; fq2.ftt is set
	test_spr_bits	0x7e,1,0x4,fqst2	; fq2.cexc is set
	test_spr_bits	0x1,0,0x1,fqst2		; fq2.valid is set
	test_spr_immed	0x85e40241,fqop2	; fq2.opc
	bra		ret

; exception handler 3 - fp_exception: register exception
ok3:
	test_spr_bits	0x100000,20,0x1,fsr0	; fsr0.qne is set
	test_spr_bits	0xe0000,17,0x6,fsr0	; fsr0.ftt is set
	test_spr_bits	0xfc00,10,0x0,fsr0	; fsr0.aexc is clear

	test_spr_bits	0x80000000,31,0x0,fqst2	; fq2.miv is set
	test_spr_bits	0x18000,15,0x0,fqst2	; fq2.sie is set
	test_spr_bits	0x380,7,0x6,fqst2	; fq2.ftt is set
	test_spr_bits	0x7e,1,0x0,fqst2	; fq2.cexc is set
	test_spr_bits	0x1,0,0x1,fqst2		; fq2.valid is set
	test_spr_immed	0x83581000,fqop2	; fq2.opc
	bra		ret

; exception handler 4 - fp_exception: another register exception
ok4:
	test_spr_bits	0x100000,20,0x1,fsr0	; fsr0.qne is set
	test_spr_bits	0xe0000,17,0x6,fsr0	; fsr0.ftt is set
	test_spr_bits	0xfc00,10,0x0,fsr0	; fsr0.aexc is still clear

	test_spr_bits	0x80000000,31,0x0,fqst3	; fq3.miv is set
	test_spr_bits	0x18000,15,0x0,fqst3	; fq3.sie is set
	test_spr_bits	0x380,7,0x6,fqst3	; fq3.ftt is set
	test_spr_bits	0x7e,1,0x0,fqst3	; fq3.cexc is set
	test_spr_bits	0x1,0,0x1,fqst3		; fq3.valid is set
	test_spr_immed	0x92ec1000,fqop3	; fq3.opc
	bra		ret

; exception handler 5 - fp_exception: sequence violation
ok5:
	test_spr_bits	0x100000,20,0x1,fsr0	; fsr0.qne is set
	test_spr_bits	0xe0000,17,0x4,fsr0	; fsr0.ftt is set
	test_spr_bits	0xfc00,10,0x0,fsr0	; fsr0.aexc is still clear

	test_spr_bits	0x80000000,31,0x0,fqst3	; fq3.miv is set
	test_spr_bits	0x18000,15,0x0,fqst3	; fq3.sie is set
	test_spr_bits	0x380,7,0x4,fqst3	; fq3.ftt is set
	test_spr_bits	0x7e,1,0x0,fqst3	; fq3.cexc is set
	test_spr_bits	0x1,0,0x1,fqst3		; fq3.valid is set
	test_spr_immed	0x97e400ca,fqop3	; fq3.opc
	bra		ret

; exception handler 6 - fp_exception: inexact
ok6:
	test_spr_bits	0x100000,20,0x1,fsr0	; fsr0.qne is set
	test_spr_bits	0xe0000,17,0x1,fsr0	; fsr0.ftt is set
	test_spr_bits	0xfc00,10,0x6,fsr0	; fsr0.aexc is still set

	test_spr_bits	0x80000000,31,0x0,fqst0	; fq0.miv is set
	test_spr_bits	0x18000,15,0x0,fqst0	; fq0.sie is set
	test_spr_bits	0x380,7,0x1,fqst0	; fq0.ftt is set
	test_spr_bits	0x7e,1,0x2,fqst0	; fq0.cexc is set
	test_spr_bits	0x1,0,0x1,fqst0		; fq0.valid is set
	test_spr_immed	0x85e40160,fqop0	; fq0.opc
	bra		ret

; exception handler 7 - fp_exception: inexact again
ok7:
	test_spr_bits	0x100000,20,0x1,fsr0	; fsr0.qne is set
	test_spr_bits	0xe0000,17,0x1,fsr0	; fsr0.ftt is set
	test_spr_bits	0xfc00,10,0x6,fsr0	; fsr0.aexc is still set

	test_spr_bits	0x80000000,31,0x0,fqst1	; fq1.miv is set
	test_spr_bits	0x18000,15,0x0,fqst1	; fq1.sie is set
	test_spr_bits	0x380,7,0x1,fqst1	; fq1.ftt is set
	test_spr_bits	0x7e,1,0x2,fqst1	; fq1.cexc is set
	test_spr_bits	0x1,0,0x1,fqst1		; fq1.valid is set
	test_spr_immed	0x85e40160,fqop1	; fq1.opc
	bra		ret

ret:
	inc_gr_immed	1,gr15
	movsg		pcsr,gr60
	add		gr60,gr20,gr60
	movgs		gr60,pcsr
	rett		0
	fail

