# gr28-gr31, fr31, icc3, fcc3 are used as tmps. # consider them call clobbered by these macros. .macro start .data failmsg: .ascii "fail\n" passmsg: .ascii "pass\n" .text .global _start _start: ; enable data and insn caches in copy-back mode ; Also enable all registers or_spr_immed 0xc80003c0,hsr0 and_spr_immed 0xfffff3ff,hsr0 ; turn on psr.nem, psr.cm, psr.ef, psr.em, psr.esr, ; disable external interrupts or_spr_immed 0x69f8,psr ; If fsr exists, enable all fp_exceptions except inexact movsg psr,gr28 srli gr28,28,gr28 subicc gr28,0x2,gr0,icc3 ; is fr400? beq icc3,0,nofsr0 or_spr_immed 0x3d000000,fsr0 nofsr0: ; Set the stack pointer sethi.p 0x7,sp setlo 0xfffc,sp ; TODO -- what's a good value for this? ; Set the TBR address sethi.p 0xf,gr28 setlo 0xf000,gr28 movgs gr28,tbr ; TODO -- what's a good value for this? ; Go to user mode -- causes too many problems ;and_spr_immed 0xfffffffb,psr .endm ; Set GR with another GR .macro set_gr_gr src targ addi \src,0,\targ .endm ; Set GR with immediate value .macro set_gr_immed val reg .if (\val >= -32768) && (\val <= 23767) setlos \val,\reg .else setlo.p %lo(\val),\reg sethi %hi(\val),\reg .endif .endm .macro set_gr_limmed valh vall reg sethi.p \valh,\reg setlo \vall,\reg .endm ; Set GR with address value .macro set_gr_addr addr reg sethi.p %hi(\addr),\reg setlo %lo(\addr),\reg .endm ; Set GR with SPR .macro set_gr_spr src targ movsg \src,\targ .endm ; Set GR with a value from memory .macro set_gr_mem addr reg set_gr_addr \addr,gr28 ldi @(gr28,0),\reg .endm ; Increment GR with immediate value .macro inc_gr_immed val reg .if (\val >= -2048) && (\val <= 2047) addi \reg,\val,\reg .else set_gr_immed \val,gr28 add \reg,gr28,\reg .endif .endm ; AND GR with immediate value .macro and_gr_immed val reg .if (\val >= -2048) && (\val <= 2047) andi \reg,\val,\reg .else set_gr_immed \val,gr28 and \reg,gr28,\reg .endif .endm ; OR GR with immediate value .macro or_gr_immed val reg .if (\val >= -2048) && (\val <= 2047) ori \reg,\val,\reg .else set_gr_immed \val,gr28 or \reg,gr28,\reg .endif .endm ; Set FR with another FR .macro set_fr_fr src targ fmovs \src,\targ .endm ; Set FR with integer immediate value .macro set_fr_iimmed valh vall reg set_gr_limmed \valh,\vall,gr28 movgf gr28,\reg .endm ; Set FR with integer immediate value .macro set_fr_immed val reg set_gr_immed \val,gr28 movgf gr28,\reg .endm ; Set FR with a value from memory .macro set_fr_mem addr reg set_gr_addr \addr,gr28 ldfi @(gr28,0),\reg .endm ; Set double FR with another double FR .macro set_dfr_dfr src targ fmovd \src,\targ .endm ; Set double FR with a value from memory .macro set_dfr_mem addr reg set_gr_addr \addr,gr28 lddfi @(gr28,0),\reg .endm ; Set CPR with immediate value .macro set_cpr_immed val reg addi sp,-4,gr28 set_gr_immed \val,gr29 st gr29,@(gr28,gr0) ldc @(gr28,gr0),\reg .endm .macro set_cpr_limmed valh vall reg addi sp,-4,gr28 set_gr_limmed \valh,\vall,gr29 st gr29,@(gr28,gr0) ldc @(gr28,gr0),\reg .endm ; Set SPR with immediate value .macro set_spr_immed val reg set_gr_immed \val,gr28 movgs gr28,\reg .endm .macro set_spr_limmed valh vall reg set_gr_limmed \valh,\vall,gr28 movgs gr28,\reg .endm .macro set_spr_addr addr reg set_gr_addr \addr,gr28 movgs gr28,\reg .endm ; increment SPR with immediate value .macro inc_spr_immed val reg movsg \reg,gr28 inc_gr_immed \val,gr28 movgs gr28,\reg .endm ; OR spr with immediate value .macro or_spr_immed val reg movsg \reg,gr28 set_gr_immed \val,gr29 or gr28,gr29,gr28 movgs gr28,\reg .endm ; AND spr with immediate value .macro and_spr_immed val reg movsg \reg,gr28 set_gr_immed \val,gr29 and gr28,gr29,gr28 movgs gr28,\reg .endm ; Set accumulator with immediate value .macro set_acc_immed val reg set_fr_immed \val,fr31 mwtacc fr31,\reg .endm ; Set accumulator guard with immediate value .macro set_accg_immed val reg set_fr_immed \val,fr31 mwtaccg fr31,\reg .endm ; Set memory with immediate value .macro set_mem_immed val base set_gr_immed \val,gr28 sti gr28,@(\base,0) .endm .macro set_mem_limmed valh vall base set_gr_limmed \valh,\vall,gr28 sti gr28,@(\base,0) .endm ; Set memory with GR value .macro set_mem_gr reg addr set_gr_addr \addr,gr28 sti \reg,@(gr28,0) .endm ; Test the value of a general register against another general register .macro test_gr_gr reg1 reg2 subcc \reg1,\reg2,gr0,icc3 beq icc3,0,test_gr\@ fail test_gr\@: .endm ; Test the value of an immediate against a general register .macro test_gr_immed val reg .if (\val >= -512) && (\val <= 511) subicc \reg,\val,gr0,icc3 .else set_gr_immed \val,gr28 subcc \reg,gr28,gr0,icc3 .endif beq icc3,0,test_gr\@ fail test_gr\@: .endm .macro test_gr_limmed valh vall reg set_gr_limmed \valh,\vall,gr28 subcc \reg,gr28,gr0,icc3 beq icc3,0,test_gr\@ fail test_gr\@: .endm ; Test the value of an floating register against an integer immediate .macro test_fr_limmed valh vall reg movfg \reg,gr29 set_gr_limmed \valh,\vall,gr28 subcc gr29,gr28,gr0,icc3 beq icc3,0,test_gr\@ fail test_gr\@: .endm .macro test_fr_iimmed val reg movfg \reg,gr29 set_gr_immed \val,gr28 subcc gr29,gr28,gr0,icc3 beq icc3,0,test_gr\@ fail test_gr\@: .endm ; Test the value of a floating register against another floating point register .macro test_fr_fr reg1 reg2 fcmps \reg1,\reg2,fcc3 fbeq fcc3,0,test_gr\@ fail test_gr\@: .endm ; Test the value of a double floating register against another ; double floating point register .macro test_dfr_dfr reg1 reg2 fcmpd \reg1,\reg2,fcc3 fbeq fcc3,0,test_gr\@ fail test_gr\@: .endm ; Test the value of a special purpose register against an integer immediate .macro test_spr_immed val reg movsg \reg,gr29 set_gr_immed \val,gr28 subcc gr29,gr28,gr0,icc3 beq icc3,0,test_gr\@ fail test_gr\@: .endm .macro test_spr_limmed valh vall reg movsg \reg,gr29 set_gr_limmed \valh,\vall,gr28 subcc gr29,gr28,gr0,icc3 beq icc3,0,test_gr\@ fail test_gr\@: .endm .macro test_spr_gr spr gr movsg \spr,gr28 test_gr_gr \gr,gr28 .endm .macro test_spr_addr addr reg movsg \reg,gr29 set_gr_addr \addr,gr28 test_gr_gr gr28,gr29 .endm ; Test spr bits masked and shifted against the given value .macro test_spr_bits mask,shift,val,reg movsg \reg,gr28 set_gr_immed \mask,gr29 and gr28,gr29,gr28 srli gr28,\shift,gr29 test_gr_immed \val,gr29 .endm ; Test the value of an accumulator against an integer immediate .macro test_acc_immed val reg mrdacc \reg,fr31 test_fr_iimmed \val,fr31 .endm ; Test the value of an accumulator against an integer immediate .macro test_acc_limmed valh vall reg mrdacc \reg,fr31 test_fr_limmed \valh,\vall,fr31 .endm ; Test the value of an accumulator guard against an integer immediate .macro test_accg_immed val reg mrdaccg \reg,fr31 test_fr_iimmed \val,fr31 .endm ; Test CPR agains an immediate value .macro test_cpr_limmed valh vall reg addi sp,-4,gr31 stc \reg,@(gr31,gr0) test_mem_limmed \valh,\vall,gr31 .endm ; Test the value of an immediate against memory .macro test_mem_immed val base ldi @(\base,0),gr29 .if (\val >= -512) && (\val <= 511) subicc gr29,\val,gr0,icc3 .else set_gr_immed \val,gr28 subcc gr29,gr28,gr0,icc3 .endif beq icc3,0,test_gr\@ fail test_gr\@: .endm .macro test_mem_limmed valh vall base ldi @(\base,0),gr29 set_gr_limmed \valh,\vall,gr28 subcc gr29,gr28,gr0,icc3 beq icc3,0,test_gr\@ fail test_gr\@: .endm ; Set an integer condition code .macro set_icc mask iccno set_gr_immed 4,gr29 smuli gr29,\iccno,gr30 addi gr31,16,gr31 set_gr_immed 0xf,gr28 sll gr28,gr31,gr28 not gr28,gr28 movsg ccr,gr29 and gr28,gr29,gr29 set_gr_immed \mask,gr28 sll gr28,gr31,gr28 or gr28,gr29,gr29 movgs gr29,ccr .endm ; started here ; Test the condition codes .macro test_icc N Z V C iccno .if (\N == 1) bp \iccno,0,fail\@ .else bn \iccno,0,fail\@ .endif .if (\Z == 1) bne \iccno,0,fail\@ .else beq \iccno,0,fail\@ .endif .if (\V == 1) bnv \iccno,0,fail\@ .else bv \iccno,0,fail\@ .endif .if (\C == 1) bnc \iccno,0,fail\@ .else bc \iccno,0,fail\@ .endif bra test_cc\@ fail\@: fail test_cc\@: .endm ; Set an floating point condition code .macro set_fcc mask fccno set_gr_immed 4,gr29 smuli gr29,\fccno,gr30 set_gr_immed 0xf,gr28 sll gr28,gr31,gr28 not gr28,gr28 movsg ccr,gr29 and gr28,gr29,gr29 set_gr_immed \mask,gr28 sll gr28,gr31,gr28 or gr28,gr29,gr29 movgs gr29,ccr .endm ; Test the condition codes .macro test_fcc val fccno set_gr_immed 4,gr29 smuli gr29,\fccno,gr30 movsg ccr,gr29 srl gr29,gr31,gr29 andi gr29,0xf,gr29 test_gr_immed \val,gr29 .endm ; Set PSR.ET .macro set_psr_et val movsg psr,gr28 .if (\val == 1) ori gr28,1,gr28 ; Turn on SPR.ET .else andi gr28,0xfffffffe,gr28 ; Turn off SPR.ET .endif movgs gr28,psr .endm ; Floating point constants .macro float_constants f0: .float 0.0 f1: .float 1.0 f2: .float 2.0 f3: .float 3.0 f6: .float 6.0 f9: .float 9.0 fn0: .float -0.0 fn1: .float -1.0 finf: .long 0x7f800000 fninf: .long 0xff800000 fmax: .long 0x7f7fffff fmin: .long 0xff7fffff feps: .long 0x00400000 fneps: .long 0x80400000 fnan1: .long 0x7fc00000 fnan2: .long 0x7f800001 .endm .macro double_constants d0: .double 0.0 d1: .double 1.0 d2: .double 2.0 d3: .double 3.0 d6: .double 6.0 d9: .double 9.0 dn0: .double -0.0 dn1: .double -1.0 dinf: .long 0x7ff00000 .long 0x00000000 dninf: .long 0xfff00000 .long 0x00000000 dmax: .long 0x7fefffff .long 0xffffffff dmin: .long 0xffefffff .long 0xffffffff deps: .long 0x00080000 .long 0x00000000 dneps: .long 0x80080000 .long 0x00000000 dnan1: .long 0x7ff80000 .long 0x00000000 dnan2: .long 0x7ff00000 .long 0x00000001 .endm ; Load floating point constants .macro load_float_constants set_fr_mem fninf,fr0 set_fr_mem fmin,fr4 set_fr_mem fn1,fr8 set_fr_mem fneps,fr12 set_fr_mem fn0,fr16 set_fr_mem f0,fr20 set_fr_mem feps,fr24 set_fr_mem f1,fr28 set_fr_mem f2,fr32 set_fr_mem f3,fr36 set_fr_mem f6,fr40 set_fr_mem f9,fr44 set_fr_mem fmax,fr48 set_fr_mem finf,fr52 set_fr_mem fnan1,fr56 set_fr_mem fnan2,fr60 .endm .macro load_float_constants1 set_fr_mem fninf,fr1 set_fr_mem fmin,fr5 set_fr_mem fn1,fr9 set_fr_mem fneps,fr13 set_fr_mem fn0,fr17 set_fr_mem f0,fr21 set_fr_mem feps,fr25 set_fr_mem f1,fr29 set_fr_mem f2,fr33 set_fr_mem f3,fr37 set_fr_mem f6,fr41 set_fr_mem f9,fr45 set_fr_mem fmax,fr49 set_fr_mem finf,fr53 set_fr_mem fnan1,fr57 set_fr_mem fnan2,fr61 .endm .macro load_float_constants2 set_fr_mem fninf,fr2 set_fr_mem fmin,fr6 set_fr_mem fn1,fr10 set_fr_mem fneps,fr14 set_fr_mem fn0,fr18 set_fr_mem f0,fr22 set_fr_mem feps,fr26 set_fr_mem f1,fr30 set_fr_mem f2,fr34 set_fr_mem f3,fr38 set_fr_mem f6,fr42 set_fr_mem f9,fr46 set_fr_mem fmax,fr50 set_fr_mem finf,fr54 set_fr_mem fnan1,fr58 set_fr_mem fnan2,fr62 .endm .macro load_float_constants3 set_fr_mem fninf,fr3 set_fr_mem fmin,fr7 set_fr_mem fn1,fr11 set_fr_mem fneps,fr15 set_fr_mem fn0,fr19 set_fr_mem f0,fr23 set_fr_mem feps,fr27 set_fr_mem f1,fr31 set_fr_mem f2,fr35 set_fr_mem f3,fr39 set_fr_mem f6,fr43 set_fr_mem f9,fr47 set_fr_mem fmax,fr51 set_fr_mem finf,fr55 set_fr_mem fnan1,fr59 set_fr_mem fnan2,fr63 .endm .macro load_double_constants set_dfr_mem dninf,fr0 set_dfr_mem dmin,fr4 set_dfr_mem dn1,fr8 set_dfr_mem dneps,fr12 set_dfr_mem dn0,fr16 set_dfr_mem d0,fr20 set_dfr_mem deps,fr24 set_dfr_mem d1,fr28 set_dfr_mem d2,fr32 set_dfr_mem d3,fr36 set_dfr_mem d6,fr40 set_dfr_mem d9,fr44 set_dfr_mem dmax,fr48 set_dfr_mem dinf,fr52 set_dfr_mem dnan1,fr56 set_dfr_mem dnan2,fr60 .endm ; Lock the insn cache at the given address .macro lock_insn_cache address icpl \address,gr0,1 .endm ; Lock the data cache at the given address .macro lock_data_cache address dcpl \address,gr0,1 .endm ; Invalidate the data cache at the given address .macro invalidate_data_cache address dci @(\address,gr0) .endm ; Flush the data cache at the given address .macro flush_data_cache address dcf @(\address,gr0) .endm ; Write a bctrlr 0,0 insn at the address contained in the given register .macro set_bctrlr_0_0 address set_mem_immed 0x80382000,\address ; bctrlr 0,0 flush_data_cache \address .endm ; Exit with return code .macro exit rc setlos #1,gr7 set_gr_immed \rc,gr8 tira gr0,#0 .endm ; Pass the test case .macro pass pass\@: setlos.p #5,gr10 setlos #1,gr8 setlos #5,gr7 set_gr_addr passmsg,gr9 tira gr0,#0 exit #0 .endm ; Fail the testcase .macro fail fail\@: setlos.p #5,gr10 setlos #1,gr8 setlos #5,gr7 set_gr_addr failmsg,gr9 tira gr0,#0 exit #1 .endm