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