blob: 7523d6f6aa5f6717c2786877dfc9dc5199882141 [file] [log] [blame]
# 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