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