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