| # Support macros for the Hitachi H8 assembly test cases. | |
| ; Set up a minimal machine state | |
| .macro start | |
| .equ h8300, 0 | |
| .equ h8300h, 1 | |
| .equ h8300s, 2 | |
| .equ h8sx, 3 | |
| .if (sim_cpu == h8300s) | |
| .h8300s | |
| .else | |
| .if (sim_cpu == h8300h) | |
| .h8300h | |
| .else | |
| .if (sim_cpu == h8sx) | |
| .h8300sx | |
| .endif | |
| .endif | |
| .endif | |
| .text | |
| .align 2 | |
| .global _start | |
| _start: | |
| jmp _main | |
| .data | |
| .align 2 | |
| .global pass_str | |
| .global fail_str | |
| .global ok_str | |
| .global pass_loc | |
| .global fail_loc | |
| .global ok_loc | |
| pass_str: | |
| .ascii "pass\n" | |
| fail_str: | |
| .ascii "fail\n" | |
| ok_str: | |
| .ascii "ok\n" | |
| pass_loc16: | |
| .word pass_str | |
| pass_loc32: | |
| .long pass_str | |
| fail_loc16: | |
| .word fail_str | |
| fail_loc32: | |
| .long fail_str | |
| ok_loc16: | |
| .word ok_str | |
| ok_loc32: | |
| .long ok_str | |
| .text | |
| .global _write_and_exit | |
| _write_and_exit: | |
| ;ssize_t write(int fd, const void *buf, size_t count); | |
| ;Integer arguments have to be zero extended. | |
| .if (sim_cpu) | |
| #if __INT_MAX__ == 32767 | |
| extu.l er0 | |
| #endif | |
| .endif | |
| jsr @@0xc7 | |
| mov #0, r0 | |
| jmp _exit | |
| .global _exit | |
| _exit: | |
| mov.b r0l, r0h | |
| mov.w #0xdead, r1 | |
| mov.w #0xbeef, r2 | |
| sleep | |
| .global _main | |
| _main: | |
| .endm | |
| ; Exit with an exit code | |
| .macro exit code | |
| mov.w #\code, r0 | |
| jmp _exit | |
| .endm | |
| ; Output "pass\n" | |
| .macro pass | |
| mov.w #0, r0 ; fd == stdout | |
| .if (sim_cpu == h8300) | |
| mov.w #pass_str, r1 ; buf == "pass\n" | |
| mov.w #5, r2 ; len == 5 | |
| .else | |
| mov.l #pass_str, er1 ; buf == "pass\n" | |
| mov.l #5, er2 ; len == 5 | |
| .endif | |
| jmp _write_and_exit | |
| .endm | |
| ; Output "fail\n" | |
| .macro fail | |
| mov.w #0, r0 ; fd == stdout | |
| .if (sim_cpu == h8300) | |
| mov.w #fail_str, r1 ; buf == "fail\n" | |
| mov.w #5, r2 ; len == 5 | |
| .else | |
| mov.l #fail_str, er1 ; buf == "fail\n" | |
| mov.l #5, er2 ; len == 5 | |
| .endif | |
| jmp _write_and_exit | |
| .endm | |
| ; Load an 8-bit immediate value into a general register | |
| ; (reg must be r0l - r7l or r0h - r7h) | |
| .macro mvi_h_gr8 val reg | |
| mov.b #\val, \reg | |
| .endm | |
| ; Load a 16-bit immediate value into a general register | |
| ; (reg must be r0 - r7) | |
| .macro mvi_h_gr16 val reg | |
| mov.w #\val, \reg | |
| .endm | |
| ; Load a 32-bit immediate value into a general register | |
| ; (reg must be er0 - er7) | |
| .macro mvi_h_gr32 val reg | |
| mov.l #\val, \reg | |
| .endm | |
| ; Test the value of an 8-bit immediate against a general register | |
| ; (reg must be r0l - r7l or r0h - r7h) | |
| .macro test_h_gr8 val reg | |
| cmp.b #\val, \reg | |
| beq .Ltest_gr8\@ | |
| fail | |
| .Ltest_gr8\@: | |
| .endm | |
| ; Test the value of a 16-bit immediate against a general register | |
| ; (reg must be r0 - r7) | |
| .macro test_h_gr16 val reg h=h l=l | |
| .if (sim_cpu == h8300) | |
| test_h_gr8 (\val >> 8) \reg\h | |
| test_h_gr8 (\val & 0xff) \reg\l | |
| .else | |
| cmp.w #\val, \reg | |
| beq .Ltest_gr16\@ | |
| fail | |
| .Ltest_gr16\@: | |
| .endif | |
| .endm | |
| ; Test the value of a 32-bit immediate against a general register | |
| ; (reg must be er0 - er7) | |
| .macro test_h_gr32 val reg | |
| cmp.l #\val, \reg | |
| beq .Ltest_gr32\@ | |
| fail | |
| .Ltest_gr32\@: | |
| .endm | |
| ; Set a general register to the fixed pattern 'a5a5a5a5' | |
| .macro set_gr_a5a5 reg | |
| .if (sim_cpu == 0) | |
| ; h8300 | |
| mov.w #0xa5a5, r\reg | |
| .else | |
| mov.l #0xa5a5a5a5, er\reg | |
| .endif | |
| .endm | |
| ; Set all general registers to the fixed pattern 'a5a5a5a5' | |
| .macro set_grs_a5a5 | |
| .if (sim_cpu == 0) | |
| ; h8300 | |
| mov.w #0xa5a5, r0 | |
| mov.w #0xa5a5, r1 | |
| mov.w #0xa5a5, r2 | |
| mov.w #0xa5a5, r3 | |
| mov.w #0xa5a5, r4 | |
| mov.w #0xa5a5, r5 | |
| mov.w #0xa5a5, r6 | |
| mov.w #0xa5a5, r7 | |
| .else | |
| mov.l #0xa5a5a5a5, er0 | |
| mov.l #0xa5a5a5a5, er1 | |
| mov.l #0xa5a5a5a5, er2 | |
| mov.l #0xa5a5a5a5, er3 | |
| mov.l #0xa5a5a5a5, er4 | |
| mov.l #0xa5a5a5a5, er5 | |
| mov.l #0xa5a5a5a5, er6 | |
| mov.l #0xa5a5a5a5, er7 | |
| .endif | |
| .endm | |
| ; Test that a general register contains the fixed pattern 'a5a5a5a5' | |
| .macro test_gr_a5a5 reg | |
| .if (sim_cpu == 0) | |
| ; h8300 | |
| test_h_gr16 0xa5a5 r\reg | |
| .else | |
| test_h_gr32 0xa5a5a5a5 er\reg | |
| .endif | |
| .endm | |
| ; Test that all general regs contain the fixed pattern 'a5a5a5a5' | |
| .macro test_grs_a5a5 | |
| test_gr_a5a5 0 | |
| test_gr_a5a5 1 | |
| test_gr_a5a5 2 | |
| test_gr_a5a5 3 | |
| test_gr_a5a5 4 | |
| test_gr_a5a5 5 | |
| test_gr_a5a5 6 | |
| test_gr_a5a5 7 | |
| .endm | |
| ; Set condition code register to an explicit value | |
| .macro set_ccr val | |
| ldc #\val, ccr | |
| .endm | |
| ; Set all condition code flags to zero | |
| .macro set_ccr_zero | |
| ldc #0, ccr | |
| .endm | |
| ; Set carry flag true | |
| .macro set_carry_flag | |
| orc #1, ccr | |
| .endm | |
| ; Clear carry flag | |
| .macro clear_carry_flag | |
| andc 0xfe, ccr | |
| .endm | |
| ; Set zero flag true | |
| .macro set_zero_flag | |
| orc #4, ccr | |
| .endm | |
| ; Clear zero flag | |
| .macro clear_zero_flag | |
| andc 0xfb, ccr | |
| .endm | |
| ; Set neg flag true | |
| .macro set_neg_flag | |
| orc #8, ccr | |
| .endm | |
| ; Clear neg flag | |
| .macro clear_neg_flag | |
| andc 0xf7, ccr | |
| .endm | |
| ; Test that carry flag is clear | |
| .macro test_carry_clear | |
| bcc .Lcc\@ | |
| fail ; carry flag not clear | |
| .Lcc\@: | |
| .endm | |
| ; Test that carry flag is set | |
| .macro test_carry_set | |
| bcs .Lcs\@ | |
| fail ; carry flag not clear | |
| .Lcs\@: | |
| .endm | |
| ; Test that overflow flag is clear | |
| .macro test_ovf_clear | |
| bvc .Lvc\@ | |
| fail ; overflow flag not clear | |
| .Lvc\@: | |
| .endm | |
| ; Test that overflow flag is set | |
| .macro test_ovf_set | |
| bvs .Lvs\@ | |
| fail ; overflow flag not clear | |
| .Lvs\@: | |
| .endm | |
| ; Test that zero flag is clear | |
| .macro test_zero_clear | |
| bne .Lne\@ | |
| fail ; zero flag not clear | |
| .Lne\@: | |
| .endm | |
| ; Test that zero flag is set | |
| .macro test_zero_set | |
| beq .Leq\@ | |
| fail ; zero flag not clear | |
| .Leq\@: | |
| .endm | |
| ; Test that neg flag is clear | |
| .macro test_neg_clear | |
| bpl .Lneg\@ | |
| fail ; negative flag not clear | |
| .Lneg\@: | |
| .endm | |
| ; Test that neg flag is set | |
| .macro test_neg_set | |
| bmi .Lneg\@ | |
| fail ; negative flag not clear | |
| .Lneg\@: | |
| .endm | |
| ; Test ccr against an explicit value | |
| .macro test_ccr val | |
| .data | |
| tccr\@: .byte 0 | |
| .text | |
| mov.b r0l, @tccr\@ | |
| stc ccr, r0l | |
| cmp.b #\val, r0l | |
| bne .Ltcc\@ | |
| fail | |
| .Ltcc\@: | |
| mov.b @tccr\@, r0l | |
| .endm | |
| ; Test that all (accessable) condition codes are clear | |
| .macro test_cc_clear | |
| test_carry_clear | |
| test_ovf_clear | |
| test_zero_clear | |
| test_neg_clear | |
| ; leaves H, I, U, and UI untested | |
| .endm | |
| ; Compare memory, fail if not equal (h8sx only, len > 0). | |
| .macro memcmp src dst len | |
| mov.l #\src, er5 | |
| mov.l #\dst, er6 | |
| mov.l #\len, er4 | |
| .Lmemcmp_\@: | |
| cmp.b @er5+, @er6+ | |
| beq .Lmemcmp2_\@ | |
| fail | |
| .Lmemcmp2_\@: | |
| dec.l #1, er4 | |
| bne .Lmemcmp_\@ | |
| .endm | |