2823a4c8 |
1 | /* |
2 | * arm-codegen.h |
3 | * |
4 | * Copyright (c) 2002 Wild West Software |
5 | * Copyright (c) 2001, 2002 Sergey Chaban |
6 | * |
7 | * Permission is hereby granted, free of charge, to any person |
8 | * obtaining a copy of this software and associated documentation |
9 | * files (the "Software"), to deal in the Software without restriction, |
10 | * including without limitation the rights to use, copy, modify, merge, |
11 | * publish, distribute, sublicense, and/or sell copies of the Software, |
12 | * and to permit persons to whom the Software is furnished to do so, |
13 | * subject to the following conditions: |
14 | * |
15 | * The above copyright notice and this permission notice shall be included |
16 | * in all copies or substantial portions of the Software. |
17 | * |
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE |
24 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
25 | * |
26 | */ |
27 | |
28 | |
29 | #ifndef ARM_CG_H |
30 | #define ARM_CG_H |
31 | |
32 | typedef unsigned long arminstr_t; |
33 | typedef unsigned long armword_t; |
34 | |
35 | /* Helper functions */ |
36 | /*void arm_emit_std_prologue(cg_segment_t * segment, unsigned int local_size); |
37 | void arm_emit_std_epilogue(cg_segment_t * segment, unsigned int local_size, int pop_regs); |
38 | void arm_emit_lean_prologue(cg_segment_t * segment, unsigned int local_size, int push_regs); |
39 | int arm_is_power_of_2(armword_t val); |
40 | int calc_arm_mov_const_shift(armword_t val); |
41 | int is_arm_const(armword_t val); |
42 | int arm_bsf(armword_t val); |
43 | void arm_mov_reg_imm32_cond(cg_segment_t * segment, int reg, armword_t imm32, int cond); |
44 | void arm_mov_reg_imm32(cg_segment_t * segment, int reg, armword_t imm32);*/ |
45 | |
46 | |
47 | //*** check for correctness *** |
48 | //extern u32* x86Ptr; |
49 | |
50 | void write_to_file(u32 val); |
51 | |
52 | //#define write32(val) { *(u32 *)translation_ptr = val; write_to_file(*(u32 *)translation_ptr); translation_ptr += 4; } |
53 | |
54 | //#define write32(val) { if( g_PcWatch.IsReset == RECRESET_OFF ) { *(u32*)pCurPage->pCodeCurrent = val; pCurPage->pCodeCurrent +=4; if( (u32)pCurPage->pCodeCurrent >= (u32)pCurPage->pCodeEnd ) { g_PcWatch.IsReset = RECRESET_START; recResize(); g_PcWatch.IsReset = RECRESET_END; return; } }else{ if( g_PcWatch.IsReset == RECRESET_END ){ g_PcWatch.IsReset = RECRESET_OFF; return; } } } |
55 | //#define write32_ret(val) { if( g_PcWatch.IsReset == RECRESET_OFF ) { *(u32*)pCurPage->pCodeCurrent = val; pCurPage->pCodeCurrent +=4; if( (u32)pCurPage->pCodeCurrent >= (u32)pCurPage->pCodeEnd ) { g_PcWatch.IsReset = RECRESET_START; recResize(); g_PcWatch.IsReset = RECRESET_END; return 0; } }else{ if( g_PcWatch.IsReset == RECRESET_END ){ g_PcWatch.IsReset = RECRESET_OFF; return 0; } } } |
56 | //#define write32(val) { *(u32*)pCurPage->pCodeCurrent = val; pCurPage->pCodeCurrent +=4; } |
57 | |
58 | #define ARM_EMIT(p, i) write32(i); |
59 | //write32(i); |
60 | /*{ *(u32*)translation_ptr = (i); translation_ptr += 4; } */ |
61 | |
62 | #if defined(GIZMONDO) || defined(POCKETPC) /* Implemented but not working right yet for PPC */ |
63 | |
64 | // -------------------------------------------------------------------------- |
65 | // These declarations for coredll are extracted from platform builder |
66 | // source code |
67 | // -------------------------------------------------------------------------- |
68 | |
69 | /* Flags for CacheSync/CacheRangeFlush */ |
70 | #define CACHE_SYNC_DISCARD 0x001 /* write back & discard all cached data */ |
71 | #define CACHE_SYNC_INSTRUCTIONS 0x002 /* discard all cached instructions */ |
72 | #define CACHE_SYNC_WRITEBACK 0x004 /* write back but don't discard data cache*/ |
73 | #define CACHE_SYNC_FLUSH_I_TLB 0x008 /* flush I-TLB */ |
74 | #define CACHE_SYNC_FLUSH_D_TLB 0x010 /* flush D-TLB */ |
75 | #define CACHE_SYNC_FLUSH_TLB (CACHE_SYNC_FLUSH_I_TLB|CACHE_SYNC_FLUSH_D_TLB) /* flush all TLB */ |
76 | #define CACHE_SYNC_L2_WRITEBACK 0x020 /* write-back L2 Cache */ |
77 | #define CACHE_SYNC_L2_DISCARD 0x040 /* discard L2 Cache */ |
78 | |
79 | #define CACHE_SYNC_ALL 0x07F /* sync and discard everything in Cache/TLB */ |
80 | |
81 | extern "C" { |
82 | void CacheSync(int flags); |
83 | } |
84 | #define CLEAR_INSN_CACHE(BEG, END) CacheSync(CACHE_SYNC_INSTRUCTIONS | CACHE_SYNC_WRITEBACK); |
85 | |
86 | #else |
87 | |
88 | #if 0 |
89 | #define CLEAR_INSN_CACHE(BEG, END) \ |
90 | { \ |
91 | register unsigned long _beg __asm ("a1") = (unsigned long) (BEG); \ |
92 | register unsigned long _end __asm ("a2") = (unsigned long) (END); \ |
93 | register unsigned long _flg __asm ("a3") = 0; \ |
94 | register unsigned long _scno __asm ("r7") = 0xf0002; \ |
95 | __asm __volatile ("swi 0x9f0002 @ sys_cacheflush" \ |
96 | : "=r" (_beg) \ |
97 | : "0" (_beg), "r" (_end), "r" (_flg), "r" (_scno)); \ |
98 | } |
99 | |
100 | #endif |
101 | |
102 | #endif |
103 | |
104 | #if defined(_MSC_VER) && !defined(ARM_NOIASM) |
105 | # define ARM_IASM(_expr) __easfdmit (_expr) |
106 | #else |
107 | # define ARM_IASM(_expr) |
108 | #endif |
109 | |
110 | /* even_scale = rot << 1 */ |
111 | #define ARM_SCALE(imm8, even_scale) ( ((imm8) >> (even_scale)) | ((imm8) << (32 - even_scale)) ) |
112 | |
113 | |
114 | |
115 | typedef enum { |
116 | ARMREG_R0 = 0, |
117 | ARMREG_R1, |
118 | ARMREG_R2, |
119 | ARMREG_R3, |
120 | ARMREG_R4, |
121 | ARMREG_R5, |
122 | ARMREG_R6, |
123 | ARMREG_R7, |
124 | ARMREG_R8, |
125 | ARMREG_R9, |
126 | ARMREG_R10, |
127 | ARMREG_R11, |
128 | ARMREG_R12, |
129 | ARMREG_R13, |
130 | ARMREG_R14, |
131 | ARMREG_R15, |
132 | |
133 | |
134 | /* aliases */ |
135 | /* args */ |
136 | ARMREG_A1 = ARMREG_R0, |
137 | ARMREG_A2 = ARMREG_R1, |
138 | ARMREG_A3 = ARMREG_R2, |
139 | ARMREG_A4 = ARMREG_R3, |
140 | |
141 | /* local vars */ |
142 | ARMREG_V1 = ARMREG_R4, |
143 | ARMREG_V2 = ARMREG_R5, |
144 | ARMREG_V3 = ARMREG_R6, |
145 | ARMREG_V4 = ARMREG_R7, |
146 | ARMREG_V5 = ARMREG_R8, |
147 | ARMREG_V6 = ARMREG_R9, |
148 | ARMREG_V7 = ARMREG_R10, |
149 | |
150 | ARMREG_FP = ARMREG_R11, |
151 | ARMREG_IP = ARMREG_R12, |
152 | ARMREG_SP = ARMREG_R13, |
153 | ARMREG_LR = ARMREG_R14, |
154 | ARMREG_PC = ARMREG_R15, |
155 | |
156 | /* FPU */ |
157 | ARMREG_F0 = 0, |
158 | ARMREG_F1, |
159 | ARMREG_F2, |
160 | ARMREG_F3, |
161 | ARMREG_F4, |
162 | ARMREG_F5, |
163 | ARMREG_F6, |
164 | ARMREG_F7, |
165 | |
166 | /* co-processor */ |
167 | ARMREG_CR0 = 0, |
168 | ARMREG_CR1, |
169 | ARMREG_CR2, |
170 | ARMREG_CR3, |
171 | ARMREG_CR4, |
172 | ARMREG_CR5, |
173 | ARMREG_CR6, |
174 | ARMREG_CR7, |
175 | ARMREG_CR8, |
176 | ARMREG_CR9, |
177 | ARMREG_CR10, |
178 | ARMREG_CR11, |
179 | ARMREG_CR12, |
180 | ARMREG_CR13, |
181 | ARMREG_CR14, |
182 | ARMREG_CR15, |
183 | |
184 | /* XScale: acc0 on CP0 */ |
185 | ARMREG_ACC0 = ARMREG_CR0, |
186 | |
187 | ARMREG_MAX = ARMREG_R15, |
188 | |
189 | /* flags */ |
190 | ARMREG_CPSR = 0, |
191 | ARMREG_SPSR = 1 |
192 | } ARMReg; |
193 | |
194 | typedef enum { |
195 | ARM_FCONST_0_0 = 8, |
196 | ARM_FCONST_1_0, |
197 | ARM_FCONST_2_0, |
198 | ARM_FCONST_3_0, |
199 | ARM_FCONST_4_0, |
200 | ARM_FCONST_5_0, |
201 | ARM_FCONST_0_5, |
202 | ARM_FCONST_10_0 |
203 | } ARMFPUConst; |
204 | |
205 | /* number of argument registers */ |
206 | #define ARM_NUM_ARG_REGS 4 |
207 | |
208 | /* number of non-argument registers */ |
209 | #define ARM_NUM_VARIABLE_REGS 7 |
210 | |
211 | /* number of global registers */ |
212 | #define ARM_NUM_GLOBAL_REGS 5 |
213 | |
214 | /* bitvector for all argument regs (A1-A4) */ |
215 | #define ARM_ALL_ARG_REGS \ |
216 | (1 << ARMREG_A1) | (1 << ARMREG_A2) | (1 << ARMREG_A3) | (1 << ARMREG_A4) |
217 | |
218 | |
219 | typedef enum { |
220 | ARMCOND_EQ = 0x0, /* Equal; Z = 1 */ |
221 | ARMCOND_NE = 0x1, /* Not equal, or unordered; Z = 0 */ |
222 | ARMCOND_CS = 0x2, /* Carry set; C = 1 */ |
223 | ARMCOND_HS = ARMCOND_CS, /* Unsigned higher or same; */ |
224 | ARMCOND_CC = 0x3, /* Carry clear; C = 0 */ |
225 | ARMCOND_LO = ARMCOND_CC, /* Unsigned lower */ |
226 | ARMCOND_MI = 0x4, /* Negative; N = 1 */ |
227 | ARMCOND_PL = 0x5, /* Positive or zero; N = 0 */ |
228 | ARMCOND_VS = 0x6, /* Overflow; V = 1 */ |
229 | ARMCOND_VC = 0x7, /* No overflow; V = 0 */ |
230 | ARMCOND_HI = 0x8, /* Unsigned higher; C = 1 && Z = 0 */ |
231 | ARMCOND_LS = 0x9, /* Unsigned lower or same; C = 0 || Z = 1 */ |
232 | ARMCOND_GE = 0xA, /* Signed greater than or equal; N = V */ |
233 | ARMCOND_LT = 0xB, /* Signed less than; N != V */ |
234 | ARMCOND_GT = 0xC, /* Signed greater than; Z = 0 && N = V */ |
235 | ARMCOND_LE = 0xD, /* Signed less than or equal; Z = 1 && N != V */ |
236 | ARMCOND_AL = 0xE, /* Always */ |
237 | ARMCOND_NV = 0xF, /* Never */ |
238 | |
239 | ARMCOND_SHIFT = 28 |
240 | } ARMCond; |
241 | |
242 | #define ARMCOND_MASK (ARMCOND_NV << ARMCOND_SHIFT) |
243 | |
244 | #define ARM_DEF_COND(cond) (((cond) & 0xF) << ARMCOND_SHIFT) |
245 | |
246 | |
247 | |
248 | typedef enum { |
249 | ARMSHIFT_LSL = 0, |
250 | ARMSHIFT_LSR = 1, |
251 | ARMSHIFT_ASR = 2, |
252 | ARMSHIFT_ROR = 3, |
253 | |
254 | ARMSHIFT_ASL = ARMSHIFT_LSL |
255 | /* rrx = (ror, 1) */ |
256 | } ARMShiftType; |
257 | |
258 | |
259 | typedef struct { |
260 | armword_t PSR_c : 8; |
261 | armword_t PSR_x : 8; |
262 | armword_t PSR_s : 8; |
263 | armword_t PSR_f : 8; |
264 | } ARMPSR; |
265 | |
266 | typedef enum { |
267 | ARMOP_AND = 0x0, |
268 | ARMOP_EOR = 0x1, |
269 | ARMOP_SUB = 0x2, |
270 | ARMOP_RSB = 0x3, |
271 | ARMOP_ADD = 0x4, |
272 | ARMOP_ADC = 0x5, |
273 | ARMOP_SBC = 0x6, |
274 | ARMOP_RSC = 0x7, |
275 | ARMOP_TST = 0x8, |
276 | ARMOP_TEQ = 0x9, |
277 | ARMOP_CMP = 0xa, |
278 | ARMOP_CMN = 0xb, |
279 | ARMOP_ORR = 0xc, |
280 | ARMOP_MOV = 0xd, |
281 | ARMOP_BIC = 0xe, |
282 | ARMOP_MVN = 0xf, |
283 | |
284 | |
285 | /* not really opcodes */ |
286 | |
287 | ARMOP_STR = 0x0, |
288 | ARMOP_LDR = 0x1, |
289 | |
290 | /* ARM2+ */ |
291 | ARMOP_MUL = 0x0, /* Rd := Rm*Rs */ |
292 | ARMOP_MLA = 0x1, /* Rd := (Rm*Rs)+Rn */ |
293 | |
294 | /* ARM3M+ */ |
295 | ARMOP_UMULL = 0x4, |
296 | ARMOP_UMLAL = 0x5, |
297 | ARMOP_SMULL = 0x6, |
298 | ARMOP_SMLAL = 0x7, |
299 | |
300 | /* for data transfers with register offset */ |
301 | ARM_UP = 1, |
302 | ARM_DOWN = 0 |
303 | } ARMOpcode; |
304 | |
305 | typedef enum { |
306 | THUMBOP_AND = 0, |
307 | THUMBOP_EOR = 1, |
308 | THUMBOP_LSL = 2, |
309 | THUMBOP_LSR = 3, |
310 | THUMBOP_ASR = 4, |
311 | THUMBOP_ADC = 5, |
312 | THUMBOP_SBC = 6, |
313 | THUMBOP_ROR = 7, |
314 | THUMBOP_TST = 8, |
315 | THUMBOP_NEG = 9, |
316 | THUMBOP_CMP = 10, |
317 | THUMBOP_CMN = 11, |
318 | THUMBOP_ORR = 12, |
319 | THUMBOP_MUL = 13, |
320 | THUMBOP_BIC = 14, |
321 | THUMBOP_MVN = 15, |
322 | THUMBOP_MOV = 16, |
323 | THUMBOP_CMPI = 17, |
324 | THUMBOP_ADD = 18, |
325 | THUMBOP_SUB = 19, |
326 | THUMBOP_CMPH = 19, |
327 | THUMBOP_MOVH = 20 |
328 | } ThumbOpcode; |
329 | |
330 | |
331 | /* Generic form - all ARM instructions are conditional. */ |
332 | typedef struct { |
333 | arminstr_t icode : 28; |
334 | arminstr_t cond : 4; |
335 | } ARMInstrGeneric; |
336 | |
337 | |
338 | |
339 | /* Branch or Branch with Link instructions. */ |
340 | typedef struct { |
341 | arminstr_t offset : 24; |
342 | arminstr_t link : 1; |
343 | arminstr_t tag : 3; /* 1 0 1 */ |
344 | arminstr_t cond : 4; |
345 | } ARMInstrBR; |
346 | |
347 | #define ARM_BR_ID 5 |
348 | #define ARM_BR_MASK 7 << 25 |
349 | #define ARM_BR_TAG ARM_BR_ID << 25 |
350 | |
351 | #define ARM_DEF_BR(offs, l, cond) ((offs) | ((l) << 24) | (ARM_BR_TAG) | (cond << ARMCOND_SHIFT)) |
352 | |
353 | /* branch */ |
354 | #define ARM_B_COND(p, cond, offset) ARM_EMIT(p, ARM_DEF_BR(offset, 0, cond)) |
355 | #define ARM_B(p, offs) ARM_B_COND((p), ARMCOND_AL, (offs)) |
356 | /* branch with link */ |
357 | #define ARM_BL_COND(p, cond, offset) ARM_EMIT(p, ARM_DEF_BR(offset, 1, cond)) |
358 | #define ARM_BL(p, offs) ARM_BL_COND((p), ARMCOND_AL, (offs)) |
359 | |
360 | /* branch to register and exchange */ |
361 | #define ARM_BX_COND(p, cond, reg) ARM_EMIT(p, ((cond << ARMCOND_SHIFT) | (reg) | 0x12FFF10)) |
362 | #define ARM_BX(p, reg) ARM_BX_COND((p), ARMCOND_AL, (reg)) |
363 | |
364 | /* branch to register with link */ |
365 | #define ARM_BLX_COND(p, cond, reg) ARM_EMIT(p, ((cond << ARMCOND_SHIFT) | (reg) | 0x12FFF30)) |
366 | #define ARM_BLX(p, reg) ARM_BLX_COND((p), ARMCOND_AL, (reg)) |
367 | |
368 | |
369 | /* Data Processing Instructions - there are 3 types. */ |
370 | |
371 | typedef struct { |
372 | arminstr_t imm : 8; |
373 | arminstr_t rot : 4; |
374 | } ARMDPI_op2_imm; |
375 | |
376 | typedef struct { |
377 | arminstr_t rm : 4; |
378 | arminstr_t tag : 1; /* 0 - immediate shift, 1 - reg shift */ |
379 | arminstr_t type : 2; /* shift type - logical, arithmetic, rotate */ |
380 | } ARMDPI_op2_reg_shift; |
381 | |
382 | |
383 | /* op2 is reg shift by imm */ |
384 | typedef union { |
385 | ARMDPI_op2_reg_shift r2; |
386 | struct { |
387 | arminstr_t _dummy_r2 : 7; |
388 | arminstr_t shift : 5; |
389 | } imm; |
390 | } ARMDPI_op2_reg_imm; |
391 | |
392 | /* op2 is reg shift by reg */ |
393 | typedef union { |
394 | ARMDPI_op2_reg_shift r2; |
395 | struct { |
396 | arminstr_t _dummy_r2 : 7; |
397 | arminstr_t pad : 1; /* always 0, to differentiate from HXFER etc. */ |
398 | arminstr_t rs : 4; |
399 | } reg; |
400 | } ARMDPI_op2_reg_reg; |
401 | |
402 | /* Data processing instrs */ |
403 | typedef union { |
404 | ARMDPI_op2_imm op2_imm; |
405 | |
406 | ARMDPI_op2_reg_shift op2_reg; |
407 | ARMDPI_op2_reg_imm op2_reg_imm; |
408 | ARMDPI_op2_reg_reg op2_reg_reg; |
409 | |
410 | struct { |
411 | arminstr_t op2 : 12; /* raw operand 2 */ |
412 | arminstr_t rd : 4; /* destination reg */ |
413 | arminstr_t rn : 4; /* first operand reg */ |
414 | arminstr_t s : 1; /* S-bit controls PSR update */ |
415 | arminstr_t opcode : 4; /* arithmetic/logic operation */ |
416 | arminstr_t type : 1; /* type of op2, 0 = register, 1 = immediate */ |
417 | arminstr_t tag : 2; /* 0 0 */ |
418 | arminstr_t cond : 4; |
419 | } all; |
420 | } ARMInstrDPI; |
421 | |
422 | #define ARM_DPI_ID 0 |
423 | #define ARM_DPI_MASK 3 << 26 |
424 | #define ARM_DPI_TAG ARM_DPI_ID << 26 |
425 | |
426 | #define ARM_DEF_DPI_IMM_COND(imm8, rot, rd, rn, s, op, cond) \ |
427 | ((imm8) & 0xFF) | \ |
428 | (((rot) & 0xF) << 8) | \ |
429 | ((rd) << 12) | \ |
430 | ((rn) << 16) | \ |
431 | ((s) << 20) | \ |
432 | ((op) << 21) | \ |
433 | (1 << 25) | \ |
434 | (ARM_DPI_TAG) | \ |
435 | ARM_DEF_COND(cond) |
436 | |
437 | |
438 | #define ARM_DEF_DPI_IMM(imm8, rot, rd, rn, s, op) \ |
439 | ARM_DEF_DPI_IMM_COND(imm8, rot, rd, rn, s, op, ARMCOND_AL) |
440 | |
441 | /* codegen */ |
442 | #define ARM_DPIOP_REG_IMM8ROT_COND(p, op, rd, rn, imm8, rot, cond) \ |
443 | ARM_EMIT(p, ARM_DEF_DPI_IMM_COND((imm8), ((rot) >> 1), (rd), (rn), 0, (op), cond)) |
444 | #define ARM_DPIOP_S_REG_IMM8ROT_COND(p, op, rd, rn, imm8, rot, cond) \ |
445 | ARM_EMIT(p, ARM_DEF_DPI_IMM_COND((imm8), ((rot) >> 1), (rd), (rn), 1, (op), cond)) |
446 | |
447 | /* inline */ |
448 | #define ARM_IASM_DPIOP_REG_IMM8ROT_COND(p, op, rd, rn, imm8, rot, cond) \ |
449 | ARM_IASM(ARM_DEF_DPI_IMM_COND((imm8), ((rot) >> 1), (rd), (rn), 0, (op), cond)) |
450 | #define ARM_IASM_DPIOP_S_REG_IMM8ROT_COND(p, op, rd, rn, imm8, rot, cond) \ |
451 | ARM_IASM(ARM_DEF_DPI_IMM_COND((imm8), ((rot) >> 1), (rd), (rn), 1, (op), cond)) |
452 | |
453 | |
454 | |
455 | #define ARM_DEF_DPI_REG_IMMSHIFT_COND(rm, shift_type, imm_shift, rd, rn, s, op, cond) \ |
456 | (rm) | \ |
457 | ((shift_type & 3) << 5) | \ |
458 | (((imm_shift) & 0x1F) << 7) | \ |
459 | ((rd) << 12) | \ |
460 | ((rn) << 16) | \ |
461 | ((s) << 20) | \ |
462 | ((op) << 21) | \ |
463 | (ARM_DPI_TAG) | \ |
464 | ARM_DEF_COND(cond) |
465 | |
466 | /* codegen */ |
467 | #define ARM_DPIOP_REG_IMMSHIFT_COND(p, op, rd, rn, rm, shift_type, imm_shift, cond) \ |
468 | ARM_EMIT(p, ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), shift_type, imm_shift, (rd), (rn), 0, (op), cond)) |
469 | |
470 | #define ARM_DPIOP_S_REG_IMMSHIFT_COND(p, op, rd, rn, rm, shift_type, imm_shift, cond) \ |
471 | ARM_EMIT(p, ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), shift_type, imm_shift, (rd), (rn), 1, (op), cond)) |
472 | |
473 | #define ARM_DPIOP_REG_REG_COND(p, op, rd, rn, rm, cond) \ |
474 | ARM_EMIT(p, ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), ARMSHIFT_LSL, 0, (rd), (rn), 0, (op), cond)) |
475 | |
476 | #define ARM_DPIOP_S_REG_REG_COND(p, op, rd, rn, rm, cond) \ |
477 | ARM_EMIT(p, ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), ARMSHIFT_LSL, 0, (rd), (rn), 1, (op), cond)) |
478 | |
479 | /* inline */ |
480 | #define ARM_IASM_DPIOP_REG_IMMSHIFT_COND(p, op, rd, rn, rm, shift_type, imm_shift, cond) \ |
481 | ARM_IASM(ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), shift_type, imm_shift, (rd), (rn), 0, (op), cond)) |
482 | |
483 | #define ARM_IASM_DPIOP_S_REG_IMMSHIFT_COND(p, op, rd, rn, rm, shift_type, imm_shift, cond) \ |
484 | ARM_IASM(ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), shift_type, imm_shift, (rd), (rn), 1, (op), cond)) |
485 | |
486 | #define ARM_IASM_DPIOP_REG_REG_COND(p, op, rd, rn, rm, cond) \ |
487 | ARM_IASM(ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), ARMSHIFT_LSL, 0, (rd), (rn), 0, (op), cond)) |
488 | |
489 | #define ARM_IASM_DPIOP_S_REG_REG_COND(p, op, rd, rn, rm, cond) \ |
490 | ARM_IASM_EMIT(ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), ARMSHIFT_LSL, 0, (rd), (rn), 1, (op), cond)) |
491 | |
492 | |
493 | /* Rd := Rn op (Rm shift_type Rs) */ |
494 | #define ARM_DEF_DPI_REG_REGSHIFT_COND(rm, shift_type, rs, rd, rn, s, op, cond) \ |
495 | (rm) | \ |
496 | (1 << 4) | \ |
497 | ((shift_type & 3) << 5) | \ |
498 | ((rs) << 8) | \ |
499 | ((rd) << 12) | \ |
500 | ((rn) << 16) | \ |
501 | ((s) << 20) | \ |
502 | ((op) << 21) | \ |
503 | (ARM_DPI_TAG) | \ |
504 | ARM_DEF_COND(cond) |
505 | |
506 | /* codegen */ |
507 | #define ARM_DPIOP_REG_REGSHIFT_COND(p, op, rd, rn, rm, shift_type, rs, cond) \ |
508 | ARM_EMIT(p, ARM_DEF_DPI_REG_REGSHIFT_COND((rm), shift_type, (rs), (rd), (rn), 0, (op), cond)) |
509 | |
510 | #define ARM_DPIOP_S_REG_REGSHIFT_COND(p, op, rd, rn, rm, shift_type, rs, cond) \ |
511 | ARM_EMIT(p, ARM_DEF_DPI_REG_REGSHIFT_COND((rm), shift_type, (rs), (rd), (rn), 1, (op), cond)) |
512 | |
513 | /* inline */ |
514 | #define ARM_IASM_DPIOP_REG_REGSHIFT_COND(p, op, rd, rn, rm, shift_type, rs, cond) \ |
515 | ARM_IASM(ARM_DEF_DPI_REG_REGSHIFT_COND((rm), shift_type, (rs), (rd), (rn), 0, (op), cond)) |
516 | |
517 | #define ARM_IASM_DPIOP_S_REG_REGSHIFT_COND(p, op, rd, rn, rm, shift_type, rs, cond) \ |
518 | ARM_IASM(ARM_DEF_DPI_REG_REGSHIFT_COND((rm), shift_type, (rs), (rd), (rn), 1, (op), cond)) |
519 | |
520 | |
521 | |
522 | /* Multiple register transfer. */ |
523 | typedef struct { |
524 | arminstr_t reg_list : 16; /* bitfield */ |
525 | arminstr_t rn : 4; /* base reg */ |
526 | arminstr_t ls : 1; /* load(1)/store(0) */ |
527 | arminstr_t wb : 1; /* write-back "!" */ |
528 | arminstr_t s : 1; /* restore PSR, force user bit */ |
529 | arminstr_t u : 1; /* up/down */ |
530 | arminstr_t p : 1; /* pre(1)/post(0) index */ |
531 | arminstr_t tag : 3; /* 1 0 0 */ |
532 | arminstr_t cond : 4; |
533 | } ARMInstrMRT; |
534 | |
535 | #define ARM_MRT_ID 4 |
536 | #define ARM_MRT_MASK 7 << 25 |
537 | #define ARM_MRT_TAG ARM_MRT_ID << 25 |
538 | |
539 | #define ARM_DEF_MRT(regs, rn, l, w, s, u, p, cond) \ |
540 | (regs) | \ |
541 | (rn << 16) | \ |
542 | (l << 20) | \ |
543 | (w << 21) | \ |
544 | (s << 22) | \ |
545 | (u << 23) | \ |
546 | (p << 24) | \ |
547 | (ARM_MRT_TAG) | \ |
548 | ARM_DEF_COND(cond) |
549 | |
550 | #define ARM_STMDB(p, rbase, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, rbase, 0, 0, 0, 0, 1, ARMCOND_AL)) |
551 | #define ARM_LDMDB(p, rbase, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, rbase, 1, 0, 0, 0, 1, ARMCOND_AL)) |
552 | #define ARM_STMDB_WB(p, rbase, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, rbase, 0, 1, 0, 0, 1, ARMCOND_AL)) |
553 | #define ARM_LDMIA_WB(p, rbase, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, rbase, 1, 1, 0, 1, 0, ARMCOND_AL)) |
554 | #define ARM_LDMIA(p, rbase, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, rbase, 1, 0, 0, 1, 0, ARMCOND_AL)) |
555 | #define ARM_STMIA(p, rbase, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, rbase, 0, 0, 0, 1, 0, ARMCOND_AL)) |
556 | #define ARM_STMIA_WB(p, rbase, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, rbase, 0, 1, 0, 1, 0, ARMCOND_AL)) |
557 | |
558 | #define ARM_LDMIA_WB_PC_S(p, rbase, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, rbase, 1, 1, 1, 1, 0, ARMCOND_AL)) |
559 | |
560 | /* THUMB |
561 | #define ARM_POP_OP(p) ARM_EMIT(p, 0xFF01BD17) |
562 | #define ARM_PUSH_OP(p) ARM_EMIT(p, 0xFF02B497) |
563 | */ |
564 | |
565 | /* stmdb sp!, {regs} */ |
566 | #define ARM_PUSH(p, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, ARMREG_SP, 0, 1, 0, 0, 1, ARMCOND_AL)) |
567 | #define ARM_IASM_PUSH(regs) ARM_IASM(ARM_DEF_MRT(regs, ARMREG_SP, 0, 1, 0, 0, 1, ARMCOND_AL)) |
568 | |
569 | /* ldmia sp!, {regs} */ |
570 | #define ARM_POP(p, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, ARMREG_SP, 1, 1, 0, 1, 0, ARMCOND_AL)) |
571 | #define ARM_IASM_POP(regs) ARM_IASM_EMIT(ARM_DEF_MRT(regs, ARMREG_SP, 1, 1, 0, 1, 0, ARMCOND_AL)) |
572 | |
573 | /* ldmia sp, {regs} ; (no write-back) */ |
574 | #define ARM_POP_NWB(p, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, ARMREG_SP, 1, 0, 0, 1, 0, ARMCOND_AL)) |
575 | #define ARM_IASM_POP_NWB(regs) ARM_IASM_EMIT(ARM_DEF_MRT(regs, ARMREG_SP, 1, 0, 0, 1, 0, ARMCOND_AL)) |
576 | |
577 | #define ARM_PUSH1(p, r1) ARM_PUSH(p, (1 << r1)) |
578 | #define ARM_PUSH2(p, r1, r2) ARM_PUSH(p, (1 << r1) | (1 << r2)) |
579 | #define ARM_PUSH3(p, r1, r2, r3) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3)) |
580 | #define ARM_PUSH4(p, r1, r2, r3, r4) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4)) |
581 | #define ARM_PUSH5(p, r1, r2, r3, r4, r5) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5)) |
582 | #define ARM_PUSH6(p, r1, r2, r3, r4, r5, r6) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5) | (1 << r6)) |
583 | #define ARM_PUSH7(p, r1, r2, r3, r4, r5, r6, r7) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5) | (1 << r6) | (1 << r7)) |
584 | #define ARM_PUSH8(p, r1, r2, r3, r4, r5, r6, r7, r8) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5) | (1 << r6) | (1 << r7) | (1 << r8)) |
585 | #define ARM_PUSH9(p, r1, r2, r3, r4, r5, r6, r7, r8, r9) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5) | (1 << r6) | (1 << r7) | (1 << r8) | (1 << r9)) |
586 | |
587 | #define ARM_POP9(p, r1, r2, r3, r4, r5, r6, r7, r8, r9) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5) | (1 << r6) | (1 << r7) | (1 << r8) | (1 << r9)) |
588 | #define ARM_POP8(p, r1, r2, r3, r4, r5, r6, r7, r8) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5) | (1 << r6) | (1 << r7) | (1 << r8)) |
589 | #define ARM_POP7(p, r1, r2, r3, r4, r5, r6, r7) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5) | (1 << r6) | (1 << r7)) |
590 | #define ARM_POP6(p, r1, r2, r3, r4, r5, r6) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5) | (1 << r6)) |
591 | #define ARM_POP5(p, r1, r2, r3, r4, r5) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5)) |
592 | #define ARM_POP4(p, r1, r2, r3, r4) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4)) |
593 | #define ARM_POP3(p, r1, r2, r3) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3)) |
594 | #define ARM_POP2(p, r1, r2) ARM_POP(p, (1 << r1) | (1 << r2)) |
595 | #define ARM_POP1(p, r1) ARM_POP(p, (1 << r1)) |
596 | |
597 | |
598 | /* Multiply instructions */ |
599 | typedef struct { |
600 | arminstr_t rm : 4; |
601 | arminstr_t tag2 : 4; /* 9 */ |
602 | arminstr_t rs : 4; |
603 | arminstr_t rn : 4; |
604 | arminstr_t rd : 4; |
605 | arminstr_t s : 1; |
606 | arminstr_t opcode : 3; |
607 | arminstr_t tag : 4; |
608 | arminstr_t cond : 4; |
609 | } ARMInstrMul; |
610 | |
611 | #define ARM_MUL_ID 0 |
612 | #define ARM_MUL_ID2 9 |
613 | #define ARM_MUL_MASK ((0xF << 24) | (0xF << 4)) |
614 | #define ARM_MUL_TAG ((ARM_MUL_ID << 24) | (ARM_MUL_ID2 << 4)) |
615 | |
616 | #define ARM_DEF_MUL_COND(op, rd, rm, rs, rn, s, cond) \ |
617 | (rm) | \ |
618 | ((rs) << 8) | \ |
619 | ((rn) << 12) | \ |
620 | ((rd) << 16) | \ |
621 | (((s) & 1) << 20) | \ |
622 | (((op) & 7) << 21) | \ |
623 | ARM_MUL_TAG | \ |
624 | ARM_DEF_COND(cond) |
625 | |
626 | /* Rd := (Rm * Rs)[31:0]; 32 x 32 -> 32 */ |
627 | #define ARM_MUL_COND(p, rd, rm, rs, cond) \ |
628 | ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 0, cond)) |
629 | #define ARM_MUL(p, rd, rm, rs) \ |
630 | ARM_MUL_COND(p, rd, rm, rs, ARMCOND_AL) |
631 | #define ARM_MULS_COND(p, rd, rm, rs, cond) \ |
632 | ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 1, cond)) |
633 | #define ARM_MULS(p, rd, rm, rs) \ |
634 | ARM_MULS_COND(p, rd, rm, rs, ARMCOND_AL) |
635 | #define ARM_MUL_REG_REG(p, rd, rm, rs) ARM_MUL(p, rd, rm, rs) |
636 | #define ARM_MULS_REG_REG(p, rd, rm, rs) ARM_MULS(p, rd, rm, rs) |
637 | |
638 | /* inline */ |
639 | #define ARM_IASM_MUL_COND(rd, rm, rs, cond) \ |
640 | ARM_IASM_EMIT(ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 0, cond)) |
641 | #define ARM_IASM_MUL(rd, rm, rs) \ |
642 | ARM_IASM_MUL_COND(rd, rm, rs, ARMCOND_AL) |
643 | #define ARM_IASM_MULS_COND(rd, rm, rs, cond) \ |
644 | ARM_IASM_EMIT(ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 1, cond)) |
645 | #define ARM_IASM_MULS(rd, rm, rs) \ |
646 | ARM_IASM_MULS_COND(rd, rm, rs, ARMCOND_AL) |
647 | |
648 | |
649 | /* Rd := (Rm * Rs) + Rn; 32x32+32->32 */ |
650 | #define ARM_MLA_COND(p, rd, rm, rs, rn, cond) \ |
651 | ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MLA, rd, rm, rs, rn, 0, cond)) |
652 | #define ARM_MLA(p, rd, rm, rs, rn) \ |
653 | ARM_MLA_COND(p, rd, rm, rs, rn, ARMCOND_AL) |
654 | #define ARM_MLAS_COND(p, rd, rm, rs, rn, cond) \ |
655 | ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MLA, rd, rm, rs, rn, 1, cond)) |
656 | #define ARM_MLAS(p, rd, rm, rs, rn) \ |
657 | ARM_MLAS_COND(p, rd, rm, rs, rn, ARMCOND_AL) |
658 | |
659 | /* inline */ |
660 | #define ARM_IASM_MLA_COND(rd, rm, rs, rn, cond) \ |
661 | ARM_IASM_EMIT(ARM_DEF_MUL_COND(ARMOP_MLA, rd, rm, rs, rn, 0, cond)) |
662 | #define ARM_IASM_MLA(rd, rm, rs, rn) \ |
663 | ARM_IASM_MLA_COND(rd, rm, rs, rn, ARMCOND_AL) |
664 | #define ARM_IASM_MLAS_COND(rd, rm, rs, rn, cond) \ |
665 | ARM_IASM_EMIT(ARM_DEF_MUL_COND(ARMOP_MLA, rd, rm, rs, rn, 1, cond)) |
666 | #define ARM_IASM_MLAS(rd, rm, rs, rn) \ |
667 | ARM_IASM_MLAS_COND(rd, rm, rs, rn, ARMCOND_AL) |
668 | |
669 | |
670 | #define ARM_SMULL_COND(p, rn, rd, rm, rs, cond) \ |
671 | ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_SMULL, rd, rm, rs, rn, 0, cond)) |
672 | #define ARM_SMULL(p, rn, rd, rm, rs) \ |
673 | ARM_SMULL_COND(p, rn, rd, rm, rs, ARMCOND_AL) |
674 | |
675 | #define ARM_SMLAL_COND(p, rn, rd, rm, rs, cond) \ |
676 | ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_SMLAL, rd, rm, rs, rn, 0, cond)) |
677 | #define ARM_SMLAL(p, rn, rd, rm, rs) \ |
678 | ARM_SMLAL_COND(p, rn, rd, rm, rs, ARMCOND_AL) |
679 | |
680 | #define ARM_UMULL_COND(p, rn, rd, rm, rs, cond) \ |
681 | ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_UMULL, rd, rm, rs, rn, 0, cond)) |
682 | #define ARM_UMULL(p, rn, rd, rm, rs) \ |
683 | ARM_UMULL_COND(p, rn, rd, rm, rs, ARMCOND_AL) |
684 | |
685 | #define ARM_UMLAL_COND(p, rn, rd, rm, rs, cond) \ |
686 | ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_UMLAL, rd, rm, rs, rn, 0, cond)) |
687 | #define ARM_UMLAL(p, rn, rd, rm, rs) \ |
688 | ARM_UMLAL_COND(p, rn, rd, rm, rs, ARMCOND_AL) |
689 | |
690 | |
691 | #define ARM_SMULLS_COND(p, rn, rd, rm, rs, cond) \ |
692 | ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_SMULL, rd, rm, rs, rn, 1, cond)) |
693 | #define ARM_SMULLS(p, rn, rd, rm, rs) \ |
694 | ARM_SMULLS_COND(p, rn, rd, rm, rs, ARMCOND_AL) |
695 | |
696 | #define ARM_SMLALS_COND(p, rn, rd, rm, rs, cond) \ |
697 | ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_SMLAL, rd, rm, rs, rn, 1, cond)) |
698 | #define ARM_SMLALS(p, rn, rd, rm, rs) \ |
699 | ARM_SMLALS_COND(p, rn, rd, rm, rs, ARMCOND_AL) |
700 | |
701 | #define ARM_UMULLS_COND(p, rn, rd, rm, rs, cond) \ |
702 | ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_UMULL, rd, rm, rs, rn, 1, cond)) |
703 | #define ARM_UMULLS(p, rn, rd, rm, rs) \ |
704 | ARM_UMULLS_COND(p, rn, rd, rm, rs, ARMCOND_AL) |
705 | |
706 | #define ARM_UMLALS_COND(p, rn, rd, rm, rs, cond) \ |
707 | ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_UMLAL, rd, rm, rs, rn, 1, cond)) |
708 | #define ARM_UMLALS(p, rn, rd, rm, rs) \ |
709 | ARM_UMLALS_COND(p, rn, rd, rm, rs, ARMCOND_AL) |
710 | |
711 | |
712 | |
713 | /* Word/byte transfer */ |
714 | typedef union { |
715 | ARMDPI_op2_reg_imm op2_reg_imm; |
716 | struct { |
717 | arminstr_t op2_imm : 12; |
718 | arminstr_t rd : 4; |
719 | arminstr_t rn : 4; |
720 | arminstr_t ls : 1; |
721 | arminstr_t wb : 1; |
722 | arminstr_t b : 1; |
723 | arminstr_t u : 1; /* down(0) / up(1) */ |
724 | arminstr_t p : 1; /* post-index(0) / pre-index(1) */ |
725 | arminstr_t type : 1; /* imm(0) / register(1) */ |
726 | arminstr_t tag : 2; /* 0 1 */ |
727 | arminstr_t cond : 4; |
728 | } all; |
729 | } ARMInstrWXfer; |
730 | |
731 | #define ARM_WXFER_ID 1 |
732 | #define ARM_WXFER_MASK 3 << 26 |
733 | #define ARM_WXFER_TAG ARM_WXFER_ID << 26 |
734 | |
735 | |
736 | /* |
737 | * ls : opcode, ARMOP_STR(0)/ARMOP_LDR(1) |
738 | * imm12 : immediate offset |
739 | * wb : write-back |
740 | * p : index mode, post-index (0, automatic write-back) |
741 | * or pre-index (1, calc effective address before memory access) |
742 | */ |
743 | #define ARM_DEF_WXFER_IMM(imm12, rd, rn, ls, wb, b, p, cond) \ |
744 | ((((int)(imm12)) < 0) ? -((int)(imm12)) : (imm12)) | \ |
745 | ((rd) << 12) | \ |
746 | ((rn) << 16) | \ |
747 | ((ls) << 20) | \ |
748 | ((wb) << 21) | \ |
749 | ((b) << 22) | \ |
750 | (((int)(imm12) >= 0) << 23) | \ |
751 | ((p) << 24) | \ |
752 | ARM_WXFER_TAG | \ |
753 | ARM_DEF_COND(cond) |
754 | |
755 | #define ARM_WXFER_MAX_OFFS 0xFFF |
756 | |
757 | /* this macro checks for imm12 bounds */ |
758 | #define ARM_EMIT_WXFER_IMM(ptr, imm12, rd, rn, ls, wb, b, p, cond) \ |
759 | do { \ |
760 | int _imm12 = (int)(imm12) < -ARM_WXFER_MAX_OFFS \ |
761 | ? -ARM_WXFER_MAX_OFFS \ |
762 | : (int)(imm12) > ARM_WXFER_MAX_OFFS \ |
763 | ? ARM_WXFER_MAX_OFFS \ |
764 | : (int)(imm12); \ |
765 | ARM_EMIT((ptr), \ |
766 | ARM_DEF_WXFER_IMM(_imm12, (rd), (rn), (ls), (wb), (b), (p), (cond))); \ |
767 | } while (0) |
768 | |
769 | |
770 | /* LDRx */ |
771 | /* immediate offset, post-index */ |
772 | #define ARM_LDR_IMM_POST_COND(p, rd, rn, imm, cond) \ |
773 | ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_LDR, 0, 0, 0, cond)) |
774 | |
775 | #define ARM_LDR_IMM_POST(p, rd, rn, imm) ARM_LDR_IMM_POST_COND(p, rd, rn, imm, ARMCOND_AL) |
776 | |
777 | #define ARM_LDRB_IMM_POST_COND(p, rd, rn, imm, cond) \ |
778 | ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_LDR, 0, 1, 0, cond)) |
779 | |
780 | #define ARM_LDRB_IMM_POST(p, rd, rn, imm) ARM_LDRB_IMM_POST_COND(p, rd, rn, imm, ARMCOND_AL) |
781 | |
782 | /* immediate offset, pre-index */ |
783 | #define ARM_LDR_IMM_COND(p, rd, rn, imm, cond) \ |
784 | ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_LDR, 0, 0, 1, cond)) |
785 | |
786 | #define ARM_LDR_IMM(p, rd, rn, imm) ARM_LDR_IMM_COND(p, rd, rn, imm, ARMCOND_AL) |
787 | |
788 | #define ARM_LDRB_IMM_COND(p, rd, rn, imm, cond) \ |
789 | ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_LDR, 0, 1, 1, cond)) |
790 | |
791 | #define ARM_LDRB_IMM(p, rd, rn, imm) ARM_LDRB_IMM_COND(p, rd, rn, imm, ARMCOND_AL) |
792 | |
793 | |
794 | /* STRx */ |
795 | /* immediate offset, post-index */ |
796 | #define ARM_STR_IMM_POST_COND(p, rd, rn, imm, cond) \ |
797 | ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_STR, 0, 0, 0, cond)) |
798 | |
799 | #define ARM_STR_IMM_POST(p, rd, rn, imm) ARM_STR_IMM_POST_COND(p, rd, rn, imm, ARMCOND_AL) |
800 | |
801 | #define ARM_STRB_IMM_POST_COND(p, rd, rn, imm, cond) \ |
802 | ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_STR, 0, 1, 0, cond)) |
803 | |
804 | #define ARM_STRB_IMM_POST(p, rd, rn, imm) ARM_STRB_IMM_POST_COND(p, rd, rn, imm, ARMCOND_AL) |
805 | |
806 | /* immediate offset, pre-index */ |
807 | #define ARM_STR_IMM_COND(p, rd, rn, imm, cond) \ |
808 | ARM_EMIT_WXFER_IMM(p, imm, rd, rn, ARMOP_STR, 0, 0, 1, cond) |
809 | /* ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_STR, 0, 0, 1, cond))*/ |
810 | /* ARM_EMIT_WXFER_IMM(p, imm, rd, rn, ARMOP_STR, 0, 0, 1, cond) */ |
811 | /* ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_STR, 0, 0, 1, cond)) */ |
812 | |
813 | #define ARM_STR_IMM(p, rd, rn, imm) ARM_STR_IMM_COND(p, rd, rn, imm, ARMCOND_AL) |
814 | |
815 | #define ARM_STRB_IMM_COND(p, rd, rn, imm, cond) \ |
816 | ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_STR, 0, 1, 1, cond)) |
817 | |
818 | #define ARM_STRB_IMM(p, rd, rn, imm) ARM_STRB_IMM_COND(p, rd, rn, imm, ARMCOND_AL) |
819 | |
820 | /* write-back */ |
821 | #define ARM_STR_IMM_WB_COND(p, rd, rn, imm, cond) \ |
822 | ARM_EMIT_WXFER_IMM(p, imm, rd, rn, ARMOP_STR, 1, 0, 1, cond) |
823 | #define ARM_STR_IMM_WB(p, rd, rn, imm) ARM_STR_IMM_WB_COND(p, rd, rn, imm, ARMCOND_AL) |
824 | |
825 | |
826 | /* |
827 | * wb : write-back |
828 | * u : down(0) / up(1) |
829 | * p : index mode, post-index (0, automatic write-back) or pre-index (1) |
830 | */ |
831 | #define ARM_DEF_WXFER_REG_REG_UPDOWN_COND(rm, shift_type, shift, rd, rn, ls, wb, b, u, p, cond) \ |
832 | (rm) | \ |
833 | ((shift_type) << 5) | \ |
834 | ((shift) << 7) | \ |
835 | ((rd) << 12) | \ |
836 | ((rn) << 16) | \ |
837 | ((ls) << 20) | \ |
838 | ((wb) << 21) | \ |
839 | ((b) << 22) | \ |
840 | ((u) << 23) | \ |
841 | ((p) << 24) | \ |
842 | (1 << 25) | \ |
843 | ARM_WXFER_TAG | \ |
844 | ARM_DEF_COND(cond) |
845 | |
846 | #define ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ls, wb, b, p, cond) \ |
847 | ARM_DEF_WXFER_REG_REG_UPDOWN_COND(rm, shift_type, shift, rd, rn, ls, wb, b, ARM_UP, p, cond) |
848 | #define ARM_DEF_WXFER_REG_MINUS_REG_COND(rm, shift_type, shift, rd, rn, ls, wb, b, p, cond) \ |
849 | ARM_DEF_WXFER_REG_REG_UPDOWN_COND(rm, shift_type, shift, rd, rn, ls, wb, b, ARM_DOWN, p, cond) |
850 | |
851 | |
852 | #define ARM_LDR_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, cond) \ |
853 | ARM_EMIT(p, ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ARMOP_LDR, 0, 0, 1, cond)) |
854 | #define ARM_LDR_REG_REG_SHIFT(p, rd, rn, rm, shift_type, shift) \ |
855 | ARM_LDR_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, ARMCOND_AL) |
856 | #define ARM_LDR_REG_REG(p, rd, rn, rm) \ |
857 | ARM_LDR_REG_REG_SHIFT(p, rd, rn, rm, ARMSHIFT_LSL, 0) |
858 | |
859 | #define ARM_LDRB_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, cond) \ |
860 | ARM_EMIT(p, ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ARMOP_LDR, 0, 1, 1, cond)) |
861 | #define ARM_LDRB_REG_REG_SHIFT(p, rd, rn, rm, shift_type, shift) \ |
862 | ARM_LDRB_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, ARMCOND_AL) |
863 | #define ARM_LDRB_REG_REG(p, rd, rn, rm) \ |
864 | ARM_LDRB_REG_REG_SHIFT(p, rd, rn, rm, ARMSHIFT_LSL, 0) |
865 | |
866 | #define ARM_STR_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, cond) \ |
867 | ARM_EMIT(p, ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ARMOP_STR, 0, 0, 1, cond)) |
868 | #define ARM_STR_REG_REG_SHIFT(p, rd, rn, rm, shift_type, shift) \ |
869 | ARM_STR_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, ARMCOND_AL) |
870 | #define ARM_STR_REG_REG(p, rd, rn, rm) \ |
871 | ARM_STR_REG_REG_SHIFT(p, rd, rn, rm, ARMSHIFT_LSL, 0) |
872 | |
873 | /* post-index */ |
874 | #define ARM_STR_REG_REG_SHIFT_POST_COND(p, rd, rn, rm, shift_type, shift, cond) \ |
875 | ARM_EMIT(p, ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ARMOP_STR, 0, 0, 0, cond)) |
876 | #define ARM_STR_REG_REG_SHIFT_POST(p, rd, rn, rm, shift_type, shift) \ |
877 | ARM_STR_REG_REG_SHIFT_POST_COND(p, rd, rn, rm, shift_type, shift, ARMCOND_AL) |
878 | #define ARM_STR_REG_REG_POST(p, rd, rn, rm) \ |
879 | ARM_STR_REG_REG_SHIFT_POST(p, rd, rn, rm, ARMSHIFT_LSL, 0) |
880 | |
881 | /* zero-extend */ |
882 | #define ARM_STRB_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, cond) \ |
883 | ARM_EMIT(p, ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ARMOP_STR, 0, 1, 1, cond)) |
884 | #define ARM_STRB_REG_REG_SHIFT(p, rd, rn, rm, shift_type, shift) \ |
885 | ARM_STRB_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, ARMCOND_AL) |
886 | #define ARM_STRB_REG_REG(p, rd, rn, rm) \ |
887 | ARM_STRB_REG_REG_SHIFT(p, rd, rn, rm, ARMSHIFT_LSL, 0) |
888 | |
889 | |
890 | /* ARMv4+ */ |
891 | /* Half-word or byte (signed) transfer. */ |
892 | typedef struct { |
893 | arminstr_t rm : 4; /* imm_lo */ |
894 | arminstr_t tag3 : 1; /* 1 */ |
895 | arminstr_t h : 1; /* half-word or byte */ |
896 | arminstr_t s : 1; /* sign-extend or zero-extend */ |
897 | arminstr_t tag2 : 1; /* 1 */ |
898 | arminstr_t imm_hi : 4; |
899 | arminstr_t rd : 4; |
900 | arminstr_t rn : 4; |
901 | arminstr_t ls : 1; |
902 | arminstr_t wb : 1; |
903 | arminstr_t type : 1; /* imm(1) / reg(0) */ |
904 | arminstr_t u : 1; /* +- */ |
905 | arminstr_t p : 1; /* pre/post-index */ |
906 | arminstr_t tag : 3; |
907 | arminstr_t cond : 4; |
908 | } ARMInstrHXfer; |
909 | |
910 | #define ARM_HXFER_ID 0 |
911 | #define ARM_HXFER_ID2 1 |
912 | #define ARM_HXFER_ID3 1 |
913 | #define ARM_HXFER_MASK ((0x7 << 25) | (0x9 << 4)) |
914 | #define ARM_HXFER_TAG ((ARM_HXFER_ID << 25) | (ARM_HXFER_ID2 << 7) | (ARM_HXFER_ID3 << 4)) |
915 | |
916 | #define ARM_DEF_HXFER_IMM_COND(imm, h, s, rd, rn, ls, wb, p, cond) \ |
917 | (((int)(imm) >= 0 ? (imm) : -(int)(imm)) & 0xF) | \ |
918 | ((h) << 5) | \ |
919 | ((s) << 6) | \ |
920 | ((((int)(imm) >= 0 ? (imm) : -(int)(imm)) << 4) & (0xF << 8)) | \ |
921 | ((rd) << 12) | \ |
922 | ((rn) << 16) | \ |
923 | ((ls) << 20) | \ |
924 | ((wb) << 21) | \ |
925 | (1 << 22) | \ |
926 | (((int)(imm) >= 0) << 23) | \ |
927 | ((p) << 24) | \ |
928 | ARM_HXFER_TAG | \ |
929 | ARM_DEF_COND(cond) |
930 | |
931 | #define ARM_LDRH_IMM_COND(p, rd, rn, imm, cond) \ |
932 | ARM_EMIT(p, ARM_DEF_HXFER_IMM_COND(imm, 1, 0, rd, rn, ARMOP_LDR, 0, 1, cond)) |
933 | #define ARM_LDRH_IMM(p, rd, rn, imm) \ |
934 | ARM_LDRH_IMM_COND(p, rd, rn, imm, ARMCOND_AL) |
935 | #define ARM_LDRSH_IMM_COND(p, rd, rn, imm, cond) \ |
936 | ARM_EMIT(p, ARM_DEF_HXFER_IMM_COND(imm, 1, 1, rd, rn, ARMOP_LDR, 0, 1, cond)) |
937 | #define ARM_LDRSH_IMM(p, rd, rn, imm) \ |
938 | ARM_LDRSH_IMM_COND(p, rd, rn, imm, ARMCOND_AL) |
939 | #define ARM_LDRSB_IMM_COND(p, rd, rn, imm, cond) \ |
940 | ARM_EMIT(p, ARM_DEF_HXFER_IMM_COND(imm, 0, 1, rd, rn, ARMOP_LDR, 0, 1, cond)) |
941 | #define ARM_LDRSB_IMM(p, rd, rn, imm) \ |
942 | ARM_LDRSB_IMM_COND(p, rd, rn, imm, ARMCOND_AL) |
943 | |
944 | |
945 | #define ARM_STRH_IMM_COND(p, rd, rn, imm, cond) \ |
946 | ARM_EMIT(p, ARM_DEF_HXFER_IMM_COND(imm, 1, 0, rd, rn, ARMOP_STR, 0, 1, cond)) |
947 | #define ARM_STRH_IMM(p, rd, rn, imm) \ |
948 | ARM_STRH_IMM_COND(p, rd, rn, imm, ARMCOND_AL) |
949 | |
950 | #define ARM_STRH_IMM_POST_COND(p, rd, rn, imm, cond) \ |
951 | ARM_EMIT(p, ARM_DEF_HXFER_IMM_COND(imm, 1, 0, rd, rn, ARMOP_STR, 0, 0, cond)) |
952 | #define ARM_STRH_IMM_POST(p, rd, rn, imm) \ |
953 | ARM_STRH_IMM_POST_COND(p, rd, rn, imm, ARMCOND_AL) |
954 | |
955 | |
956 | #define ARM_DEF_HXFER_REG_REG_UPDOWN_COND(rm, h, s, rd, rn, ls, wb, u, p, cond) \ |
957 | ((rm) & 0xF) | \ |
958 | ((h) << 5) | \ |
959 | ((s) << 6) | \ |
960 | ((rd) << 12) | \ |
961 | ((rn) << 16) | \ |
962 | ((ls) << 20) | \ |
963 | ((wb) << 21) | \ |
964 | (0 << 22) | \ |
965 | ((u) << 23) | \ |
966 | ((p) << 24) | \ |
967 | ARM_HXFER_TAG | \ |
968 | ARM_DEF_COND(cond) |
969 | |
970 | #define ARM_DEF_HXFER_REG_REG_COND(rm, h, s, rd, rn, ls, wb, p, cond) \ |
971 | ARM_DEF_HXFER_REG_REG_UPDOWN_COND(rm, h, s, rd, rn, ls, wb, ARM_UP, p, cond) |
972 | #define ARM_DEF_HXFER_REG_MINUS_REG_COND(rm, h, s, rd, rn, ls, wb, p, cond) \ |
973 | ARM_DEF_HXFER_REG_REG_UPDOWN_COND(rm, h, s, rd, rn, ls, wb, ARM_DOWN, p, cond) |
974 | |
975 | #define ARM_LDRH_REG_REG_COND(p, rd, rn, rm, cond) \ |
976 | ARM_EMIT(p, ARM_DEF_HXFER_REG_REG_COND(rm, 1, 0, rd, rn, ARMOP_LDR, 0, 1, cond)) |
977 | #define ARM_LDRH_REG_REG(p, rd, rn, rm) \ |
978 | ARM_LDRH_REG_REG_COND(p, rd, rn, rm, ARMCOND_AL) |
979 | #define ARM_LDRSH_REG_REG_COND(p, rd, rn, rm, cond) \ |
980 | ARM_EMIT(p, ARM_DEF_HXFER_REG_REG_COND(rm, 1, 1, rd, rn, ARMOP_LDR, 0, 1, cond)) |
981 | #define ARM_LDRSH_REG_REG(p, rd, rn, rm) \ |
982 | ARM_LDRSH_REG_REG_COND(p, rd, rn, rm, ARMCOND_AL) |
983 | #define ARM_LDRSB_REG_REG_COND(p, rd, rn, rm, cond) \ |
984 | ARM_EMIT(p, ARM_DEF_HXFER_REG_REG_COND(rm, 0, 1, rd, rn, ARMOP_LDR, 0, 1, cond)) |
985 | #define ARM_LDRSB_REG_REG(p, rd, rn, rm) ARM_LDRSB_REG_REG_COND(p, rd, rn, rm, ARMCOND_AL) |
986 | |
987 | #define ARM_STRH_REG_REG_COND(p, rd, rn, rm, cond) \ |
988 | ARM_EMIT(p, ARM_DEF_HXFER_REG_REG_COND(rm, 1, 0, rd, rn, ARMOP_STR, 0, 1, cond)) |
989 | #define ARM_STRH_REG_REG(p, rd, rn, rm) \ |
990 | ARM_STRH_REG_REG_COND(p, rd, rn, rm, ARMCOND_AL) |
991 | |
992 | #define ARM_STRH_REG_REG_POST_COND(p, rd, rn, rm, cond) \ |
993 | ARM_EMIT(p, ARM_DEF_HXFER_REG_REG_COND(rm, 1, 0, rd, rn, ARMOP_STR, 0, 0, cond)) |
994 | #define ARM_STRH_REG_REG_POST(p, rd, rn, rm) \ |
995 | ARM_STRH_REG_REG_POST_COND(p, rd, rn, rm, ARMCOND_AL) |
996 | |
997 | |
998 | |
999 | /* Swap */ |
1000 | typedef struct { |
1001 | arminstr_t rm : 4; |
1002 | arminstr_t tag3 : 8; /* 0x9 */ |
1003 | arminstr_t rd : 4; |
1004 | arminstr_t rn : 4; |
1005 | arminstr_t tag2 : 2; |
1006 | arminstr_t b : 1; |
1007 | arminstr_t tag : 5; /* 0x2 */ |
1008 | arminstr_t cond : 4; |
1009 | } ARMInstrSwap; |
1010 | |
1011 | #define ARM_SWP_ID 2 |
1012 | #define ARM_SWP_ID2 9 |
1013 | #define ARM_SWP_MASK ((0x1F << 23) | (3 << 20) | (0xFF << 4)) |
1014 | #define ARM_SWP_TAG ((ARM_SWP_ID << 23) | (ARM_SWP_ID2 << 4)) |
1015 | |
1016 | |
1017 | |
1018 | /* Software interrupt */ |
1019 | typedef struct { |
1020 | arminstr_t num : 24; |
1021 | arminstr_t tag : 4; |
1022 | arminstr_t cond : 4; |
1023 | } ARMInstrSWI; |
1024 | |
1025 | #define ARM_SWI_ID 0xF |
1026 | #define ARM_SWI_MASK (0xF << 24) |
1027 | #define ARM_SWI_TAG (ARM_SWI_ID << 24) |
1028 | |
1029 | |
1030 | |
1031 | /* Co-processor Data Processing */ |
1032 | typedef struct { |
1033 | arminstr_t crm : 4; |
1034 | arminstr_t tag2 : 1; /* 0 */ |
1035 | arminstr_t op2 : 3; |
1036 | arminstr_t cpn : 4; /* CP number */ |
1037 | arminstr_t crd : 4; |
1038 | arminstr_t crn : 4; |
1039 | arminstr_t op : 4; |
1040 | arminstr_t tag : 4; /* 0xE */ |
1041 | arminstr_t cond : 4; |
1042 | } ARMInstrCDP; |
1043 | |
1044 | #define ARM_CDP_ID 0xE |
1045 | #define ARM_CDP_ID2 0 |
1046 | #define ARM_CDP_MASK ((0xF << 24) | (1 << 4)) |
1047 | #define ARM_CDP_TAG ((ARM_CDP_ID << 24) | (ARM_CDP_ID2 << 4)) |
1048 | |
1049 | |
1050 | /* Co-processor Data Transfer (ldc/stc) */ |
1051 | typedef struct { |
1052 | arminstr_t offs : 8; |
1053 | arminstr_t cpn : 4; |
1054 | arminstr_t crd : 4; |
1055 | arminstr_t rn : 4; |
1056 | arminstr_t ls : 1; |
1057 | arminstr_t wb : 1; |
1058 | arminstr_t n : 1; |
1059 | arminstr_t u : 1; |
1060 | arminstr_t p : 1; |
1061 | arminstr_t tag : 3; |
1062 | arminstr_t cond : 4; |
1063 | } ARMInstrCDT; |
1064 | |
1065 | #define ARM_CDT_ID 6 |
1066 | #define ARM_CDT_MASK (7 << 25) |
1067 | #define ARM_CDT_TAG (ARM_CDT_ID << 25) |
1068 | |
1069 | |
1070 | /* Co-processor Register Transfer (mcr/mrc) */ |
1071 | typedef struct { |
1072 | arminstr_t crm : 4; |
1073 | arminstr_t tag2 : 1; |
1074 | arminstr_t op2 : 3; |
1075 | arminstr_t cpn : 4; |
1076 | arminstr_t rd : 4; |
1077 | arminstr_t crn : 4; |
1078 | arminstr_t ls : 1; |
1079 | arminstr_t op1 : 3; |
1080 | arminstr_t tag : 4; |
1081 | arminstr_t cond : 4; |
1082 | } ARMInstrCRT; |
1083 | |
1084 | #define ARM_CRT_ID 0xE |
1085 | #define ARM_CRT_ID2 0x1 |
1086 | #define ARM_CRT_MASK ((0xF << 24) | (1 << 4)) |
1087 | #define ARM_CRT_TAG ((ARM_CRT_ID << 24) | (ARM_CRT_ID2 << 4)) |
1088 | |
1089 | /* |
1090 | * Move from co-processor register to CPU register |
1091 | * Rd := cRn {<op>cRm} |
1092 | * op{condition} CP#,CPOp,Rd,CRn,CRm{,CPOp2} |
1093 | */ |
1094 | #define ARM_DEF_MRC_COND(cpn, cpop, rd, crn, crm, cpop2, cond) \ |
1095 | ((crm) & 0xF) |\ |
1096 | ((cpop2) << 5) |\ |
1097 | ((cpn) << 8) |\ |
1098 | ((rd) << 12) |\ |
1099 | ((crn) << 16) |\ |
1100 | ((ARMOP_LDR) << 20) |\ |
1101 | ((cpop) << 21) |\ |
1102 | ARM_CRT_TAG |\ |
1103 | ARM_DEF_COND(cond) |
1104 | |
1105 | #define ARM_MRC_COND(p, cpn, cpop, rd, crn, crm, cpop2, cond) \ |
1106 | ARM_EMIT(p, ARM_DEF_MRC_COND(cpn, cpop, rd, crn, crm, cpop2, cond)) |
1107 | #define ARM_MRC(p, cpn, cpop, rd, crn, crm, cpop2) \ |
1108 | ARM_MRC_COND(p, cpn, cpop, rd, crn, crm, cpop2, ARMCOND_AL) |
1109 | |
1110 | |
1111 | |
1112 | /* Move register to PSR. */ |
1113 | typedef union { |
1114 | ARMDPI_op2_imm op2_imm; |
1115 | struct { |
1116 | arminstr_t rm : 4; |
1117 | arminstr_t pad : 8; /* 0 */ |
1118 | arminstr_t tag4 : 4; /* 0xF */ |
1119 | arminstr_t fld : 4; |
1120 | arminstr_t tag3 : 2; /* 0x2 */ |
1121 | arminstr_t sel : 1; |
1122 | arminstr_t tag2 : 2; /* 0x2 */ |
1123 | arminstr_t type : 1; |
1124 | arminstr_t tag : 2; /* 0 */ |
1125 | arminstr_t cond : 4; |
1126 | } all; |
1127 | } ARMInstrMSR; |
1128 | |
1129 | #define ARM_MSR_ID 0 |
1130 | #define ARM_MSR_ID2 2 |
1131 | #define ARM_MSR_ID3 2 |
1132 | #define ARM_MSR_ID4 0xF |
1133 | #define ARM_MSR_MASK ((3 << 26) | \ |
1134 | (3 << 23) | \ |
1135 | (3 << 20) | \ |
1136 | (0xF << 12)) |
1137 | #define ARM_MSR_TAG ((ARM_MSR_ID << 26) | \ |
1138 | (ARM_MSR_ID2 << 23) | \ |
1139 | (ARM_MSR_ID3 << 20) | \ |
1140 | (ARM_MSR_ID4 << 12)) |
1141 | |
1142 | #define ARM_DEF_MSR_REG_COND(mask, rm, r, cond) \ |
1143 | ARM_MSR_TAG | \ |
1144 | ARM_DEF_COND(cond) | \ |
1145 | ((rm) & 0xf) | \ |
1146 | (((r) & 1) << 22) | \ |
1147 | (((mask) & 0xf) << 16) |
1148 | |
1149 | #define ARM_MSR_REG_COND(p, mask, rm, r, cond) \ |
1150 | ARM_EMIT(p, ARM_DEF_MSR_REG_COND(mask, rm, r, cond)) |
1151 | |
1152 | #define ARM_MSR_REG(p, mask, rm, r) \ |
1153 | ARM_MSR_REG_COND(p, mask, rm, r, ARMCOND_AL) |
1154 | |
1155 | #define ARM_PSR_C 1 |
1156 | #define ARM_PSR_X 2 |
1157 | #define ARM_PSR_S 4 |
1158 | #define ARM_PSR_F 8 |
1159 | |
1160 | #define ARM_CPSR 0 |
1161 | #define ARM_SPSR 1 |
1162 | |
1163 | /* Move PSR to register. */ |
1164 | typedef struct { |
1165 | arminstr_t tag3 : 12; |
1166 | arminstr_t rd : 4; |
1167 | arminstr_t tag2 : 6; |
1168 | arminstr_t sel : 1; /* CPSR | SPSR */ |
1169 | arminstr_t tag : 5; |
1170 | arminstr_t cond : 4; |
1171 | } ARMInstrMRS; |
1172 | |
1173 | #define ARM_MRS_ID 2 |
1174 | #define ARM_MRS_ID2 0xF |
1175 | #define ARM_MRS_ID3 0 |
1176 | #define ARM_MRS_MASK ((0x1F << 23) | (0x3F << 16) | 0xFFF) |
1177 | #define ARM_MRS_TAG ((ARM_MRS_ID << 23) | (ARM_MRS_ID2 << 16) | ARM_MRS_ID3) |
1178 | |
1179 | #define ARM_DEF_MRS_COND(rd, r, cond) \ |
1180 | ARM_MRS_TAG | \ |
1181 | ARM_DEF_COND(cond) | \ |
1182 | (((r) & 1) << 22) | \ |
1183 | ((rd)& 0xf) << 12 |
1184 | |
1185 | #define ARM_MRS_COND(p, rd, r, cond) \ |
1186 | ARM_EMIT(p, ARM_DEF_MRS_COND(rd, r, cond)) |
1187 | |
1188 | #define ARM_MRS_CPSR_COND(p, rd, cond) \ |
1189 | ARM_MRS_COND(p, rd, ARM_CPSR, cond) |
1190 | |
1191 | #define ARM_MRS_CPSR(p, rd) \ |
1192 | ARM_MRS_CPSR_COND(p, rd, ARMCOND_AL) |
1193 | |
1194 | #define ARM_MRS_SPSR_COND(p, rd, cond) \ |
1195 | ARM_MRS_COND(p, rd, ARM_SPSR, cond) |
1196 | |
1197 | #define ARM_MRS_SPSR(p, rd) \ |
1198 | ARM_MRS_SPSR_COND(p, rd, ARMCOND_AL) |
1199 | |
1200 | |
1201 | #include "arm_dpimacros.h" |
1202 | |
1203 | #define ARM_NOP(p) ARM_MOV_REG_REG(p, ARMREG_R0, ARMREG_R0) |
1204 | |
1205 | |
1206 | #define ARM_SHL_IMM_COND(p, rd, rm, imm, cond) \ |
1207 | ARM_MOV_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_LSL, imm, cond) |
1208 | #define ARM_SHL_IMM(p, rd, rm, imm) \ |
1209 | ARM_SHL_IMM_COND(p, rd, rm, imm, ARMCOND_AL) |
1210 | #define ARM_SHLS_IMM_COND(p, rd, rm, imm, cond) \ |
1211 | ARM_MOVS_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_LSL, imm, cond) |
1212 | #define ARM_SHLS_IMM(p, rd, rm, imm) \ |
1213 | ARM_SHLS_IMM_COND(p, rd, rm, imm, ARMCOND_AL) |
1214 | |
1215 | #define ARM_SHR_IMM_COND(p, rd, rm, imm, cond) \ |
1216 | ARM_MOV_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_LSR, imm, cond) |
1217 | #define ARM_SHR_IMM(p, rd, rm, imm) \ |
1218 | ARM_SHR_IMM_COND(p, rd, rm, imm, ARMCOND_AL) |
1219 | #define ARM_SHRS_IMM_COND(p, rd, rm, imm, cond) \ |
1220 | ARM_MOVS_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_LSR, imm, cond) |
1221 | #define ARM_SHRS_IMM(p, rd, rm, imm) \ |
1222 | ARM_SHRS_IMM_COND(p, rd, rm, imm, ARMCOND_AL) |
1223 | |
1224 | #define ARM_SAR_IMM_COND(p, rd, rm, imm, cond) \ |
1225 | ARM_MOV_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_ASR, imm, cond) |
1226 | #define ARM_SAR_IMM(p, rd, rm, imm) \ |
1227 | ARM_SAR_IMM_COND(p, rd, rm, imm, ARMCOND_AL) |
1228 | #define ARM_SARS_IMM_COND(p, rd, rm, imm, cond) \ |
1229 | ARM_MOVS_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_ASR, imm, cond) |
1230 | #define ARM_SARS_IMM(p, rd, rm, imm) \ |
1231 | ARM_SARS_IMM_COND(p, rd, rm, imm, ARMCOND_AL) |
1232 | |
1233 | #define ARM_ROR_IMM_COND(p, rd, rm, imm, cond) \ |
1234 | ARM_MOV_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_ROR, imm, cond) |
1235 | #define ARM_ROR_IMM(p, rd, rm, imm) \ |
1236 | ARM_ROR_IMM_COND(p, rd, rm, imm, ARMCOND_AL) |
1237 | #define ARM_RORS_IMM_COND(p, rd, rm, imm, cond) \ |
1238 | ARM_MOVS_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_ROR, imm, cond) |
1239 | #define ARM_RORS_IMM(p, rd, rm, imm) \ |
1240 | ARM_RORS_IMM_COND(p, rd, rm, imm, ARMCOND_AL) |
1241 | |
1242 | #define ARM_SHL_REG_COND(p, rd, rm, rs, cond) \ |
1243 | ARM_MOV_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_LSL, rs, cond) |
1244 | #define ARM_SHL_REG(p, rd, rm, rs) \ |
1245 | ARM_SHL_REG_COND(p, rd, rm, rs, ARMCOND_AL) |
1246 | #define ARM_SHLS_REG_COND(p, rd, rm, rs, cond) \ |
1247 | ARM_MOVS_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_LSL, rs, cond) |
1248 | #define ARM_SHLS_REG(p, rd, rm, rs) \ |
1249 | ARM_SHLS_REG_COND(p, rd, rm, rs, ARMCOND_AL) |
1250 | #define ARM_SHLS_REG_REG(p, rd, rm, rs) ARM_SHLS_REG(p, rd, rm, rs) |
1251 | |
1252 | #define ARM_SHR_REG_COND(p, rd, rm, rs, cond) \ |
1253 | ARM_MOV_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_LSR, rs, cond) |
1254 | #define ARM_SHR_REG(p, rd, rm, rs) \ |
1255 | ARM_SHR_REG_COND(p, rd, rm, rs, ARMCOND_AL) |
1256 | #define ARM_SHRS_REG_COND(p, rd, rm, rs, cond) \ |
1257 | ARM_MOVS_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_LSR, rs, cond) |
1258 | #define ARM_SHRS_REG(p, rd, rm, rs) \ |
1259 | ARM_SHRS_REG_COND(p, rd, rm, rs, ARMCOND_AL) |
1260 | #define ARM_SHRS_REG_REG(p, rd, rm, rs) ARM_SHRS_REG(p, rd, rm, rs) |
1261 | |
1262 | #define ARM_SAR_REG_COND(p, rd, rm, rs, cond) \ |
1263 | ARM_MOV_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_ASR, rs, cond) |
1264 | #define ARM_SAR_REG(p, rd, rm, rs) \ |
1265 | ARM_SAR_REG_COND(p, rd, rm, rs, ARMCOND_AL) |
1266 | #define ARM_SARS_REG_COND(p, rd, rm, rs, cond) \ |
1267 | ARM_MOVS_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_ASR, rs, cond) |
1268 | #define ARM_SARS_REG(p, rd, rm, rs) \ |
1269 | ARM_SARS_REG_COND(p, rd, rm, rs, ARMCOND_AL) |
1270 | #define ARM_SARS_REG_REG(p, rd, rm, rs) ARM_SARS_REG(p, rd, rm, rs) |
1271 | |
1272 | #define ARM_ROR_REG_COND(p, rd, rm, rs, cond) \ |
1273 | ARM_MOV_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_ROR, rs, cond) |
1274 | #define ARM_ROR_REG(p, rd, rm, rs) \ |
1275 | ARM_ROR_REG_COND(p, rd, rm, rs, ARMCOND_AL) |
1276 | #define ARM_RORS_REG_COND(p, rd, rm, rs, cond) \ |
1277 | ARM_MOVS_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_ROR, rs, cond) |
1278 | #define ARM_RORS_REG(p, rd, rm, rs) \ |
1279 | ARM_RORS_REG_COND(p, rd, rm, rs, ARMCOND_AL) |
1280 | #define ARM_RORS_REG_REG(p, rd, rm, rs) ARM_RORS_REG(p, rd, rm, rs) |
1281 | |
1282 | #define ARM_DBRK(p) ARM_EMIT(p, 0xE6000010) |
1283 | #define ARM_IASM_DBRK() ARM_IASM_EMIT(0xE6000010) |
1284 | |
1285 | #define ARM_INC(p, reg) ARM_ADD_REG_IMM8(p, reg, reg, 1) |
1286 | #define ARM_DEC(p, reg) ARM_SUB_REG_IMM8(p, reg, reg, 1) |
1287 | |
1288 | |
1289 | /* ARM V5 */ |
1290 | |
1291 | /* Count leading zeros, CLZ{cond} Rd, Rm */ |
1292 | typedef struct { |
1293 | arminstr_t rm : 4; |
1294 | arminstr_t tag2 : 8; |
1295 | arminstr_t rd : 4; |
1296 | arminstr_t tag : 12; |
1297 | arminstr_t cond : 4; |
1298 | } ARMInstrCLZ; |
1299 | |
1300 | #define ARM_CLZ_ID 0x16F |
1301 | #define ARM_CLZ_ID2 0xF1 |
1302 | #define ARM_CLZ_MASK ((0xFFF << 16) | (0xFF < 4)) |
1303 | #define ARM_CLZ_TAG ((ARM_CLZ_ID << 16) | (ARM_CLZ_ID2 << 4)) |
1304 | |
1305 | #define ARM_DEF_CLZ_COND(rd, rm, cond) \ |
1306 | ARM_CLZ_TAG | \ |
1307 | ARM_DEF_COND(cond) | \ |
1308 | (((rm) & 0xf)) | \ |
1309 | ((rd) & 0xf) << 12 |
1310 | |
1311 | #define ARM_CLZ_COND(p, rd, rm, cond) \ |
1312 | ARM_EMIT(p, ARM_DEF_CLZ_COND(rd, rm, cond)) |
1313 | |
1314 | #define ARM_CLZ(p, rd, rm) \ |
1315 | ARM_EMIT(p, ARM_DEF_CLZ_COND(rd, rm, ARMCOND_AL)) |
1316 | |
1317 | /* |
1318 | * TAG p b wb ls |
1319 | * ARMCOND_NV | 0-1-0 | 0 | +/- | 1 | 0 | 1 | rn -|- 0xF | imm12 |
1320 | */ |
1321 | #define ARM_PLD_ID 0xF45 |
1322 | #define ARM_PLD_ID2 0xF /* rd */ |
1323 | #define ARM_PLD_MASK ((0xFC7 << 20) | (0xF << 12)) |
1324 | #define ARM_PLD_TAG ((ARM_PLD_ID << 20) | (ARM_PLD_ID2 << 12)) |
1325 | #define ARM_DEF_PLD_IMM(imm12, rn) \ |
1326 | ((((int)imm12) < 0) ? -(int)(imm12) : (imm12)) | \ |
1327 | ((0xF) << 12) | \ |
1328 | ((rn) << 16) | \ |
1329 | ((1) << 20) /* ls = load(1) */ | \ |
1330 | ((0) << 21) /* wb = 0 */ | \ |
1331 | ((1) << 22) /* b = 1 */ | \ |
1332 | (((int)(imm12) >= 0) << 23) | \ |
1333 | ((1) << 24) /* pre/post = pre(1) */ | \ |
1334 | ((2) << 25) /* tag */ | \ |
1335 | ARM_DEF_COND(ARMCOND_NV) |
1336 | |
1337 | #define ARM_PLD_IMM(p, rn, imm12) ARM_EMIT(p, ARM_DEF_PLD_IMM(imm12, rn)) |
1338 | |
1339 | #define ARM_DEF_PLD_REG_REG_UPDOWN_SHIFT(rn, shift_type, shift, rm, u) \ |
1340 | (rm) | \ |
1341 | ((shift_type) << 5) | \ |
1342 | ((shift) << 7) | \ |
1343 | (0xF << 12) /* rd = 0xF */ | \ |
1344 | ((rn) << 16) | \ |
1345 | (1 << 20) /* ls = load(1) */ | \ |
1346 | (0 << 21) /* wb = 0 */ | \ |
1347 | (1 << 22) /* b = 1 */ | \ |
1348 | ((u) << 23) | \ |
1349 | (1 << 24) /* pre(1) */ | \ |
1350 | (3 << 25) | \ |
1351 | ARM_DEF_COND(ARMCOND_NV) |
1352 | |
1353 | #define ARM_PLD_REG_REG_UPDOWN_SHIFT(p, rm, rn, u, shift_type, shift) \ |
1354 | ARM_EMIT(p, ARM_DEF_PLD_REG_REG_UPDOWN_SHIFT(rm, shift_type, shift, rn, u)) |
1355 | |
1356 | #define ARM_PLD_REG_PLUS_REG(p, rm, rn) \ |
1357 | ARM_PLD_REG_REG_UPDOWN_SHIFT(p, rm, rn, ARM_UP, ARMSHIFT_LSL, 0) |
1358 | |
1359 | #define ARM_PLD_REG_MINUS_REG(p, rm, rn) \ |
1360 | ARM_PLD_REG_REG_UPDOWN_SHIFT(p, rm, rn, ARM_DOWN, ARMSHIFT_LSL, 0) |
1361 | |
1362 | |
1363 | #define ARM_DEF_STF_IMM_COND(p, prec, freg_const, rd, imm8, rot, cond) \ |
1364 | ((imm8) & 0xFF) | \ |
1365 | (((rot) & 0xF) << 8) | \ |
1366 | ((freg_const) << 12) | \ |
1367 | (1 << 25) | \ |
1368 | ARM_DEF_COND(cond) |
1369 | |
1370 | |
1371 | typedef union { |
1372 | ARMInstrBR br; |
1373 | ARMInstrDPI dpi; |
1374 | ARMInstrMRT mrt; |
1375 | ARMInstrMul mul; |
1376 | ARMInstrWXfer wxfer; |
1377 | ARMInstrHXfer hxfer; |
1378 | ARMInstrSwap swp; |
1379 | ARMInstrCDP cdp; |
1380 | ARMInstrCDT cdt; |
1381 | ARMInstrCRT crt; |
1382 | ARMInstrSWI swi; |
1383 | ARMInstrMSR msr; |
1384 | ARMInstrMRS mrs; |
1385 | ARMInstrCLZ clz; |
1386 | |
1387 | ARMInstrGeneric generic; |
1388 | arminstr_t raw; |
1389 | } ARMInstr; |
1390 | |
1391 | #endif /* ARM_CG_H */ |
1392 | |