| # r0, r4-r6 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: |
| ldi32 0x7fffc,sp ; TODO -- what's a good value for this? |
| ldi32 0xffc00,r0 |
| mov r0,tbr ; defined in manual |
| mov sp,usp |
| mov sp,ssp |
| .endm |
| |
| ; Exit with return code |
| .macro exit rc |
| ldi32 \rc,r4 |
| ldi32 #1,r0 |
| int #10 |
| .endm |
| |
| ; Pass the test case |
| .macro pass |
| ldi32 #5,r6 |
| ldi32 #passmsg,r5 |
| ldi32 #1,r4 |
| ldi32 #5,r0 |
| int #10 |
| exit #0 |
| .endm |
| |
| ; Fail the testcase |
| .macro fail |
| ldi32 #5,r6 |
| ldi32 #failmsg,r5 |
| ldi32 #1,r4 |
| ldi32 #5,r0 |
| int #10 |
| exit #1 |
| .endm |
| |
| ; Load an immediate value into a general register |
| ; TODO: use minimal sized insn |
| .macro mvi_h_gr val reg |
| ldi32 \val,\reg |
| .endm |
| |
| ; Load an immediate value into a dedicated register |
| .macro mvi_h_dr val reg |
| ldi32 \val,r0 |
| mov r0,\reg |
| .endm |
| |
| ; Load a general register into another general register |
| .macro mvr_h_gr src targ |
| mov \src,\targ |
| .endm |
| |
| ; Store an immediate into a word in memory |
| .macro mvi_h_mem val addr |
| mvi_h_gr \val r4 |
| mvr_h_mem r4,\addr |
| .endm |
| |
| ; Store a register into a word in memory |
| .macro mvr_h_mem reg addr |
| st \reg,@\addr |
| .endm |
| |
| ; Store the current ps on the stack |
| .macro save_ps |
| st ps,@-r15 |
| .endm |
| |
| ; Load a word value from memory |
| .macro ldmem_h_gr addr reg |
| ld @\addr,\reg |
| .endm |
| |
| ; Add 2 general registers |
| .macro add_h_gr reg1 reg2 |
| add \reg1,\reg2 |
| .endm |
| |
| ; Increment a register by and immediate |
| .macro inci_h_gr inc reg |
| mvi_h_gr \inc,r4 |
| add r4,\reg |
| .endm |
| |
| ; Test the value of an immediate against a general register |
| .macro test_h_gr val reg |
| .if (\val >= 0) && (\val <= 15) |
| cmp \val,\reg |
| .else |
| .if (\val < 0) && (\val >= -16) |
| cmp2 \val,\reg |
| .else |
| ldi32 \val,r4 |
| cmp r4,\reg |
| .endif |
| .endif |
| beq test_gr\@ |
| fail |
| test_gr\@: |
| .endm |
| |
| ; compare two general registers |
| .macro testr_h_gr reg1 reg2 |
| cmp \reg1,\reg2 |
| beq testr_gr\@ |
| fail |
| testr_gr\@: |
| .endm |
| |
| ; Test the value of an immediate against a dedicated register |
| .macro test_h_dr val reg |
| mov \reg,r5 |
| test_h_gr \val r5 |
| .endm |
| |
| ; Test the value of an general register against a dedicated register |
| .macro testr_h_dr gr dr |
| mov \dr,r5 |
| testr_h_gr \gr r5 |
| .endm |
| |
| ; Compare an immediate with word in memory |
| .macro test_h_mem val addr |
| ldmem_h_gr \addr r5 |
| test_h_gr \val r5 |
| .endm |
| |
| ; Compare a general register with word in memory |
| .macro testr_h_mem reg addr |
| ldmem_h_gr \addr r5 |
| testr_h_gr \reg r5 |
| .endm |
| |
| ; Set the condition codes |
| .macro set_cc mask |
| andccr 0xf0 |
| orccr \mask |
| .endm |
| |
| ; Set the stack mode |
| .macro set_s_user |
| orccr 0x20 |
| .endm |
| |
| .macro set_s_system |
| andccr 0x1f |
| .endm |
| |
| ; Test the stack mode |
| .macro test_s_user |
| mvr_h_gr ps,r0 |
| mvi_h_gr 0x20,r4 |
| and r4,r0 |
| test_h_gr 0x20,r0 |
| .endm |
| |
| .macro test_s_system |
| mvr_h_gr ps,r0 |
| mvi_h_gr 0x20,r4 |
| and r4,r0 |
| test_h_gr 0x0,r0 |
| .endm |
| |
| ; Set the interrupt bit |
| .macro set_i val |
| .if (\val == 1) |
| orccr 0x10 |
| .else |
| andccr 0x2f |
| .endif |
| .endm |
| |
| ; Test the stack mode |
| .macro test_i val |
| mvr_h_gr ps,r0 |
| mvi_h_gr 0x10,r4 |
| and r4,r0 |
| .if (\val == 1) |
| test_h_gr 0x10,r0 |
| .else |
| test_h_gr 0x0,r0 |
| .endif |
| .endm |
| |
| ; Set the ilm |
| .macro set_ilm val |
| stilm \val |
| .endm |
| |
| ; Test the ilm |
| .macro test_ilm val |
| mvr_h_gr ps,r0 |
| mvi_h_gr 0x1f0000,r4 |
| and r4,r0 |
| mvi_h_gr \val,r5 |
| mvi_h_gr 0x1f,r4 |
| and r4,r5 |
| lsl 15,r5 |
| lsl 1,r5 |
| testr_h_gr r0,r5 |
| .endm |
| |
| ; Test the condition codes |
| .macro test_cc N Z V C |
| .if (\N == 1) |
| bp fail\@ |
| .else |
| bn fail\@ |
| .endif |
| .if (\Z == 1) |
| bne fail\@ |
| .else |
| beq fail\@ |
| .endif |
| .if (\V == 1) |
| bnv fail\@ |
| .else |
| bv fail\@ |
| .endif |
| .if (\C == 1) |
| bnc fail\@ |
| .else |
| bc fail\@ |
| .endif |
| bra test_cc\@ |
| fail\@: |
| fail |
| test_cc\@: |
| .endm |
| |
| ; Set the division bits |
| .macro set_dbits val |
| mvr_h_gr ps,r5 |
| mvi_h_gr 0xfffff8ff,r4 |
| and r4,r5 |
| mvi_h_gr \val,r0 |
| mvi_h_gr 3,r4 |
| and r4,r0 |
| lsl 9,r0 |
| or r0,r5 |
| mvr_h_gr r5,ps |
| .endm |
| |
| ; Test the division bits |
| .macro test_dbits val |
| mvr_h_gr ps,r0 |
| lsr 9,r0 |
| mvi_h_gr 3,r4 |
| and r4,r0 |
| test_h_gr \val,r0 |
| .endm |
| |
| ; Save the return pointer |
| .macro save_rp |
| st rp,@-R15 |
| .ENDM |
| |
| ; restore the return pointer |
| .macro restore_rp |
| ld @R15+,rp |
| .endm |
| |
| ; Ensure branch taken |
| .macro take_branch opcode |
| \opcode take_br\@ |
| fail |
| take_br\@: |
| .endm |
| |
| .macro take_branch_d opcode val |
| \opcode take_brd\@ |
| ldi:8 \val,r0 |
| fail |
| take_brd\@: |
| test_h_gr \val,r0 |
| .endm |
| |
| ; Ensure branch not taken |
| .macro no_branch opcode |
| \opcode no_brf\@ |
| bra no_brs\@ |
| no_brf\@: |
| fail |
| no_brs\@: |
| .endm |
| |
| .macro no_branch_d opcode val |
| \opcode no_brdf\@ |
| ldi:8 \val,r0 |
| bra no_brds\@ |
| no_brdf\@: |
| fail |
| no_brds\@: |
| test_h_gr \val,r0 |
| .endm |
| |