1# r0, r4-r6 are used as tmps, consider them call clobbered by these macros. 2 3 .macro start 4 .data 5failmsg: 6 .ascii "fail\n" 7passmsg: 8 .ascii "pass\n" 9 .text 10 .global _start 11_start: 12 ldi32 0x7fffc,sp ; TODO -- what's a good value for this? 13 ldi32 0xffc00,r0 14 mov r0,tbr ; defined in manual 15 mov sp,usp 16 mov sp,ssp 17 .endm 18 19; Exit with return code 20 .macro exit rc 21 ldi32 \rc,r4 22 ldi32 #1,r0 23 int #10 24 .endm 25 26; Pass the test case 27 .macro pass 28 ldi32 #5,r6 29 ldi32 #passmsg,r5 30 ldi32 #1,r4 31 ldi32 #5,r0 32 int #10 33 exit #0 34 .endm 35 36; Fail the testcase 37 .macro fail 38 ldi32 #5,r6 39 ldi32 #failmsg,r5 40 ldi32 #1,r4 41 ldi32 #5,r0 42 int #10 43 exit #1 44 .endm 45 46; Load an immediate value into a general register 47; TODO: use minimal sized insn 48 .macro mvi_h_gr val reg 49 ldi32 \val,\reg 50 .endm 51 52; Load an immediate value into a dedicated register 53 .macro mvi_h_dr val reg 54 ldi32 \val,r0 55 mov r0,\reg 56 .endm 57 58; Load a general register into another general register 59 .macro mvr_h_gr src targ 60 mov \src,\targ 61 .endm 62 63; Store an immediate into a word in memory 64 .macro mvi_h_mem val addr 65 mvi_h_gr \val r4 66 mvr_h_mem r4,\addr 67 .endm 68 69; Store a register into a word in memory 70 .macro mvr_h_mem reg addr 71 st \reg,@\addr 72 .endm 73 74; Store the current ps on the stack 75 .macro save_ps 76 st ps,@-r15 77 .endm 78 79; Load a word value from memory 80 .macro ldmem_h_gr addr reg 81 ld @\addr,\reg 82 .endm 83 84; Add 2 general registers 85 .macro add_h_gr reg1 reg2 86 add \reg1,\reg2 87 .endm 88 89; Increment a register by and immediate 90 .macro inci_h_gr inc reg 91 mvi_h_gr \inc,r4 92 add r4,\reg 93 .endm 94 95; Test the value of an immediate against a general register 96 .macro test_h_gr val reg 97 .if (\val >= 0) && (\val <= 15) 98 cmp \val,\reg 99 .else 100 .if (\val < 0) && (\val >= -16) 101 cmp2 \val,\reg 102 .else 103 ldi32 \val,r4 104 cmp r4,\reg 105 .endif 106 .endif 107 beq test_gr\@ 108 fail 109test_gr\@: 110 .endm 111 112; compare two general registers 113 .macro testr_h_gr reg1 reg2 114 cmp \reg1,\reg2 115 beq testr_gr\@ 116 fail 117testr_gr\@: 118 .endm 119 120; Test the value of an immediate against a dedicated register 121 .macro test_h_dr val reg 122 mov \reg,r5 123 test_h_gr \val r5 124 .endm 125 126; Test the value of an general register against a dedicated register 127 .macro testr_h_dr gr dr 128 mov \dr,r5 129 testr_h_gr \gr r5 130 .endm 131 132; Compare an immediate with word in memory 133 .macro test_h_mem val addr 134 ldmem_h_gr \addr r5 135 test_h_gr \val r5 136 .endm 137 138; Compare a general register with word in memory 139 .macro testr_h_mem reg addr 140 ldmem_h_gr \addr r5 141 testr_h_gr \reg r5 142 .endm 143 144; Set the condition codes 145 .macro set_cc mask 146 andccr 0xf0 147 orccr \mask 148 .endm 149 150; Set the stack mode 151 .macro set_s_user 152 orccr 0x20 153 .endm 154 155 .macro set_s_system 156 andccr 0x1f 157 .endm 158 159; Test the stack mode 160 .macro test_s_user 161 mvr_h_gr ps,r0 162 mvi_h_gr 0x20,r4 163 and r4,r0 164 test_h_gr 0x20,r0 165 .endm 166 167 .macro test_s_system 168 mvr_h_gr ps,r0 169 mvi_h_gr 0x20,r4 170 and r4,r0 171 test_h_gr 0x0,r0 172 .endm 173 174; Set the interrupt bit 175 .macro set_i val 176 .if (\val == 1) 177 orccr 0x10 178 .else 179 andccr 0x2f 180 .endif 181 .endm 182 183; Test the stack mode 184 .macro test_i val 185 mvr_h_gr ps,r0 186 mvi_h_gr 0x10,r4 187 and r4,r0 188 .if (\val == 1) 189 test_h_gr 0x10,r0 190 .else 191 test_h_gr 0x0,r0 192 .endif 193 .endm 194 195; Set the ilm 196 .macro set_ilm val 197 stilm \val 198 .endm 199 200; Test the ilm 201 .macro test_ilm val 202 mvr_h_gr ps,r0 203 mvi_h_gr 0x1f0000,r4 204 and r4,r0 205 mvi_h_gr \val,r5 206 mvi_h_gr 0x1f,r4 207 and r4,r5 208 lsl 15,r5 209 lsl 1,r5 210 testr_h_gr r0,r5 211 .endm 212 213; Test the condition codes 214 .macro test_cc N Z V C 215 .if (\N == 1) 216 bp fail\@ 217 .else 218 bn fail\@ 219 .endif 220 .if (\Z == 1) 221 bne fail\@ 222 .else 223 beq fail\@ 224 .endif 225 .if (\V == 1) 226 bnv fail\@ 227 .else 228 bv fail\@ 229 .endif 230 .if (\C == 1) 231 bnc fail\@ 232 .else 233 bc fail\@ 234 .endif 235 bra test_cc\@ 236fail\@: 237 fail 238test_cc\@: 239 .endm 240 241; Set the division bits 242 .macro set_dbits val 243 mvr_h_gr ps,r5 244 mvi_h_gr 0xfffff8ff,r4 245 and r4,r5 246 mvi_h_gr \val,r0 247 mvi_h_gr 3,r4 248 and r4,r0 249 lsl 9,r0 250 or r0,r5 251 mvr_h_gr r5,ps 252 .endm 253 254; Test the division bits 255 .macro test_dbits val 256 mvr_h_gr ps,r0 257 lsr 9,r0 258 mvi_h_gr 3,r4 259 and r4,r0 260 test_h_gr \val,r0 261 .endm 262 263; Save the return pointer 264 .macro save_rp 265 st rp,@-R15 266 .ENDM 267 268; restore the return pointer 269 .macro restore_rp 270 ld @R15+,rp 271 .endm 272 273; Ensure branch taken 274 .macro take_branch opcode 275 \opcode take_br\@ 276 fail 277take_br\@: 278 .endm 279 280 .macro take_branch_d opcode val 281 \opcode take_brd\@ 282 ldi:8 \val,r0 283 fail 284take_brd\@: 285 test_h_gr \val,r0 286 .endm 287 288; Ensure branch not taken 289 .macro no_branch opcode 290 \opcode no_brf\@ 291 bra no_brs\@ 292no_brf\@: 293 fail 294no_brs\@: 295 .endm 296 297 .macro no_branch_d opcode val 298 \opcode no_brdf\@ 299 ldi:8 \val,r0 300 bra no_brds\@ 301no_brdf\@: 302 fail 303no_brds\@: 304 test_h_gr \val,r0 305 .endm 306 307