| # 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 |