merge -r 61110:61111
[mono.git] / mono / arch / arm / arm-codegen.h
1 /*
2  * arm-codegen.h
3  * Copyright (c) 2002 Sergey Chaban <serge@wildwestsoftware.com>
4  */
5
6
7 #ifndef ARM_H
8 #define ARM_H
9
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13
14 typedef unsigned int arminstr_t;
15 typedef unsigned int armword_t;
16
17 /* Helper functions */
18 arminstr_t* arm_emit_std_prologue(arminstr_t* p, unsigned int local_size);
19 arminstr_t* arm_emit_std_epilogue(arminstr_t* p, unsigned int local_size, int pop_regs);
20 arminstr_t* arm_emit_lean_prologue(arminstr_t* p, unsigned int local_size, int push_regs);
21 int arm_is_power_of_2(armword_t val);
22 int calc_arm_mov_const_shift(armword_t val);
23 int is_arm_const(armword_t val);
24 int arm_bsf(armword_t val);
25 arminstr_t* arm_mov_reg_imm32_cond(arminstr_t* p, int reg, armword_t imm32, int cond);
26 arminstr_t* arm_mov_reg_imm32(arminstr_t* p, int reg, armword_t imm32);
27
28
29
30 #if defined(_MSC_VER) || defined(__CC_NORCROFT)
31         void __inline _arm_emit(arminstr_t** p, arminstr_t i) {**p = i; (*p)++;}
32 #       define ARM_EMIT(p, i) _arm_emit((arminstr_t**)&p, (arminstr_t)(i))
33 #else
34 #       define ARM_EMIT(p, i) do { arminstr_t *__ainstrp = (void*)(p); *__ainstrp = (arminstr_t)(i); (p) = (void*)(__ainstrp+1);} while (0)
35 #endif
36
37 #if defined(_MSC_VER) && !defined(ARM_NOIASM)
38 #       define ARM_IASM(_expr) __emit (_expr)
39 #else
40 #       define ARM_IASM(_expr) 
41 #endif
42
43 /* even_scale = rot << 1 */
44 #define ARM_SCALE(imm8, even_scale) ( ((imm8) >> (even_scale)) | ((imm8) << (32 - even_scale)) )
45
46
47
48 typedef enum {
49         ARMREG_R0 = 0,
50         ARMREG_R1,
51         ARMREG_R2,
52         ARMREG_R3,
53         ARMREG_R4,
54         ARMREG_R5,
55         ARMREG_R6,
56         ARMREG_R7,
57         ARMREG_R8,
58         ARMREG_R9,
59         ARMREG_R10,
60         ARMREG_R11,
61         ARMREG_R12,
62         ARMREG_R13,
63         ARMREG_R14,
64         ARMREG_R15,
65
66
67         /* aliases */
68         /* args */
69         ARMREG_A1 = ARMREG_R0,
70         ARMREG_A2 = ARMREG_R1,
71         ARMREG_A3 = ARMREG_R2,
72         ARMREG_A4 = ARMREG_R3,
73
74         /* local vars */
75         ARMREG_V1 = ARMREG_R4,
76         ARMREG_V2 = ARMREG_R5,
77         ARMREG_V3 = ARMREG_R6,
78         ARMREG_V4 = ARMREG_R7,
79         ARMREG_V5 = ARMREG_R8,
80         ARMREG_V6 = ARMREG_R9,
81         ARMREG_V7 = ARMREG_R10,
82
83         ARMREG_FP = ARMREG_R11,
84         ARMREG_IP = ARMREG_R12,
85         ARMREG_SP = ARMREG_R13,
86         ARMREG_LR = ARMREG_R14,
87         ARMREG_PC = ARMREG_R15,
88
89         /* co-processor */
90         ARMREG_CR0 = 0,
91         ARMREG_CR1,
92         ARMREG_CR2,
93         ARMREG_CR3,
94         ARMREG_CR4,
95         ARMREG_CR5,
96         ARMREG_CR6,
97         ARMREG_CR7,
98         ARMREG_CR8,
99         ARMREG_CR9,
100         ARMREG_CR10,
101         ARMREG_CR11,
102         ARMREG_CR12,
103         ARMREG_CR13,
104         ARMREG_CR14,
105         ARMREG_CR15,
106
107         /* XScale: acc0 on CP0 */
108         ARMREG_ACC0 = ARMREG_CR0,
109
110         ARMREG_MAX = ARMREG_R15
111 } ARMReg;
112
113 /* number of argument registers */
114 #define ARM_NUM_ARG_REGS 4
115
116 /* bitvector for all argument regs (A1-A4) */
117 #define ARM_ALL_ARG_REGS \
118         (1 << ARMREG_A1) | (1 << ARMREG_A2) | (1 << ARMREG_A3) | (1 << ARMREG_A4)
119
120
121 typedef enum {
122         ARMCOND_EQ = 0x0,          /* Equal; Z = 1 */
123         ARMCOND_NE = 0x1,          /* Not equal, or unordered; Z = 0 */
124         ARMCOND_CS = 0x2,          /* Carry set; C = 1 */
125         ARMCOND_HS = ARMCOND_CS,   /* Unsigned higher or same; */
126         ARMCOND_CC = 0x3,          /* Carry clear; C = 0 */
127         ARMCOND_LO = ARMCOND_CC,   /* Unsigned lower */
128         ARMCOND_MI = 0x4,          /* Negative; N = 1 */
129         ARMCOND_PL = 0x5,          /* Positive or zero; N = 0 */
130         ARMCOND_VS = 0x6,          /* Overflow; V = 1 */
131         ARMCOND_VC = 0x7,          /* No overflow; V = 0 */
132         ARMCOND_HI = 0x8,          /* Unsigned higher; C = 1 && Z = 0 */
133         ARMCOND_LS = 0x9,          /* Unsigned lower or same; C = 0 || Z = 1 */
134         ARMCOND_GE = 0xA,          /* Signed greater than or equal; N = V */
135         ARMCOND_LT = 0xB,          /* Signed less than; N != V */
136         ARMCOND_GT = 0xC,          /* Signed greater than; Z = 0 && N = V */
137         ARMCOND_LE = 0xD,          /* Signed less than or equal; Z = 1 && N != V */
138         ARMCOND_AL = 0xE,          /* Always */
139         ARMCOND_NV = 0xF,          /* Never */
140
141         ARMCOND_SHIFT = 28
142 } ARMCond;
143
144 #define ARMCOND_MASK (ARMCOND_NV << ARMCOND_SHIFT)
145
146 #define ARM_DEF_COND(cond) (((cond) & 0xF) << ARMCOND_SHIFT)
147
148
149
150 typedef enum {
151         ARMSHIFT_LSL = 0,
152         ARMSHIFT_LSR = 1,
153         ARMSHIFT_ASR = 2,
154         ARMSHIFT_ROR = 3,
155
156         ARMSHIFT_ASL = ARMSHIFT_LSL
157         /* rrx = (ror, 1) */
158 } ARMShiftType;
159
160
161 typedef struct {
162         armword_t PSR_c : 8;
163         armword_t PSR_x : 8;
164         armword_t PSR_s : 8;
165         armword_t PSR_f : 8;
166 } ARMPSR;
167
168 typedef enum {
169         ARMOP_AND = 0x0,
170         ARMOP_EOR = 0x1,
171         ARMOP_SUB = 0x2,
172         ARMOP_RSB = 0x3,
173         ARMOP_ADD = 0x4,
174         ARMOP_ADC = 0x5,
175         ARMOP_SBC = 0x6,
176         ARMOP_RSC = 0x7,
177         ARMOP_TST = 0x8,
178         ARMOP_TEQ = 0x9,
179         ARMOP_CMP = 0xa,
180         ARMOP_CMN = 0xb,
181         ARMOP_ORR = 0xc,
182         ARMOP_MOV = 0xd,
183         ARMOP_BIC = 0xe,
184         ARMOP_MVN = 0xf,
185
186
187         /* not really opcodes */
188
189         ARMOP_STR = 0x0,
190         ARMOP_LDR = 0x1,
191
192         /* ARM2+ */
193         ARMOP_MUL   = 0x0, /* Rd := Rm*Rs */
194         ARMOP_MLA   = 0x1, /* Rd := (Rm*Rs)+Rn */
195
196         /* ARM3M+ */
197         ARMOP_UMULL = 0x4,
198         ARMOP_UMLAL = 0x5,
199         ARMOP_SMULL = 0x6,
200         ARMOP_SMLAL = 0x7,
201
202         /* for data transfers with register offset */
203         ARM_UP   = 1,
204         ARM_DOWN = 0
205 } ARMOpcode;
206
207 typedef enum {
208         THUMBOP_AND  = 0,
209         THUMBOP_EOR  = 1,
210         THUMBOP_LSL  = 2,
211         THUMBOP_LSR  = 3,
212         THUMBOP_ASR  = 4,
213         THUMBOP_ADC  = 5,
214         THUMBOP_SBC  = 6,
215         THUMBOP_ROR  = 7,
216         THUMBOP_TST  = 8,
217         THUMBOP_NEG  = 9,
218         THUMBOP_CMP  = 10,
219         THUMBOP_CMN  = 11,
220         THUMBOP_ORR  = 12,
221         THUMBOP_MUL  = 13,
222         THUMBOP_BIC  = 14,
223         THUMBOP_MVN  = 15,
224         THUMBOP_MOV  = 16,
225         THUMBOP_CMPI = 17,
226         THUMBOP_ADD  = 18,
227         THUMBOP_SUB  = 19,
228         THUMBOP_CMPH = 19,
229         THUMBOP_MOVH = 20
230 } ThumbOpcode;
231
232
233 /* Generic form - all ARM instructions are conditional. */
234 typedef struct {
235         arminstr_t icode : 28;
236         arminstr_t cond  :  4;
237 } ARMInstrGeneric;
238
239
240
241 /* Branch or Branch with Link instructions. */
242 typedef struct {
243         arminstr_t offset : 24;
244         arminstr_t link   :  1;
245         arminstr_t tag    :  3; /* 1 0 1 */
246         arminstr_t cond   :  4;
247 } ARMInstrBR;
248
249 #define ARM_BR_ID 5
250 #define ARM_BR_MASK 7 << 25
251 #define ARM_BR_TAG ARM_BR_ID << 25
252
253 #define ARM_DEF_BR(offs, l, cond) ((offs) | ((l) << 24) | (ARM_BR_TAG) | (cond << ARMCOND_SHIFT))
254
255 /* branch */
256 #define ARM_B_COND(p, cond, offset) ARM_EMIT(p, ARM_DEF_BR(offset, 0, cond))
257 #define ARM_B(p, offs) ARM_B_COND((p), ARMCOND_AL, (offs))
258 /* branch with link */
259 #define ARM_BL_COND(p, cond, offset) ARM_EMIT(p, ARM_DEF_BR(offset, 1, cond))
260 #define ARM_BL(p, offs) ARM_BL_COND((p), ARMCOND_AL, (offs))
261
262
263
264 /* Data Processing Instructions - there are 3 types. */
265
266 typedef struct {
267         arminstr_t imm : 8;
268         arminstr_t rot : 4;
269 } ARMDPI_op2_imm;
270
271 typedef struct {
272         arminstr_t rm   : 4;
273         arminstr_t tag  : 1; /* 0 - immediate shift, 1 - reg shift */
274         arminstr_t type : 2; /* shift type - logical, arithmetic, rotate */
275 } ARMDPI_op2_reg_shift;
276
277
278 /* op2 is reg shift by imm */
279 typedef union {
280         ARMDPI_op2_reg_shift r2;
281         struct {
282                 arminstr_t _dummy_r2 : 7;
283                 arminstr_t shift : 5;
284         } imm;
285 } ARMDPI_op2_reg_imm;
286
287 /* op2 is reg shift by reg */
288 typedef union {
289         ARMDPI_op2_reg_shift r2;
290         struct {
291                 arminstr_t _dummy_r2 : 7;
292                 arminstr_t pad       : 1; /* always 0, to differentiate from HXFER etc. */
293                 arminstr_t rs        : 4;
294         } reg;
295 } ARMDPI_op2_reg_reg;
296
297 /* Data processing instrs */
298 typedef union {
299         ARMDPI_op2_imm op2_imm;
300
301         ARMDPI_op2_reg_shift op2_reg;
302         ARMDPI_op2_reg_imm op2_reg_imm;
303         ARMDPI_op2_reg_reg op2_reg_reg;
304
305         struct {
306                 arminstr_t op2    : 12; /* raw operand 2 */
307                 arminstr_t rd     :  4; /* destination reg */
308                 arminstr_t rn     :  4; /* first operand reg */
309                 arminstr_t s      :  1; /* S-bit controls PSR update */
310                 arminstr_t opcode :  4; /* arithmetic/logic operation */
311                 arminstr_t type   :  1; /* type of op2, 0 = register, 1 = immediate */
312                 arminstr_t tag    :  2; /* 0 0 */
313                 arminstr_t cond   :  4;
314         } all;
315 } ARMInstrDPI;
316
317 #define ARM_DPI_ID 0
318 #define ARM_DPI_MASK 3 << 26
319 #define ARM_DPI_TAG ARM_DPI_ID << 26
320
321 #define ARM_DEF_DPI_IMM_COND(imm8, rot, rd, rn, s, op, cond) \
322         ((imm8) & 0xFF)      | \
323         (((rot) & 0xF) << 8) | \
324         ((rd) << 12)         | \
325         ((rn) << 16)         | \
326         ((s) << 20)          | \
327         ((op) << 21)         | \
328         (1 << 25)            | \
329         (ARM_DPI_TAG)        | \
330         ARM_DEF_COND(cond)
331
332
333 #define ARM_DEF_DPI_IMM(imm8, rot, rd, rn, s, op) \
334         ARM_DEF_DPI_IMM_COND(imm8, rot, rd, rn, s, op, ARMCOND_AL)
335
336 /* codegen */
337 #define ARM_DPIOP_REG_IMM8ROT_COND(p, op, rd, rn, imm8, rot, cond) \
338         ARM_EMIT(p, ARM_DEF_DPI_IMM_COND((imm8), ((rot) >> 1), (rd), (rn), 0, (op), cond))
339 #define ARM_DPIOP_S_REG_IMM8ROT_COND(p, op, rd, rn, imm8, rot, cond) \
340         ARM_EMIT(p, ARM_DEF_DPI_IMM_COND((imm8), ((rot) >> 1), (rd), (rn), 1, (op), cond))
341
342 /* inline */
343 #define ARM_IASM_DPIOP_REG_IMM8ROT_COND(p, op, rd, rn, imm8, rot, cond) \
344         ARM_IASM(ARM_DEF_DPI_IMM_COND((imm8), ((rot) >> 1), (rd), (rn), 0, (op), cond))
345 #define ARM_IASM_DPIOP_S_REG_IMM8ROT_COND(p, op, rd, rn, imm8, rot, cond) \
346         ARM_IASM(ARM_DEF_DPI_IMM_COND((imm8), ((rot) >> 1), (rd), (rn), 1, (op), cond))
347
348
349
350 #define ARM_DEF_DPI_REG_IMMSHIFT_COND(rm, shift_type, imm_shift, rd, rn, s, op, cond) \
351         (rm)                        | \
352         ((shift_type & 3) << 5)     | \
353         (((imm_shift) & 0x1F) << 7) | \
354         ((rd) << 12)                | \
355         ((rn) << 16)                | \
356         ((s) << 20)                 | \
357         ((op) << 21)                | \
358         (ARM_DPI_TAG)               | \
359         ARM_DEF_COND(cond)
360
361 /* codegen */
362 #define ARM_DPIOP_REG_IMMSHIFT_COND(p, op, rd, rn, rm, shift_t, imm_shift, cond) \
363         ARM_EMIT(p, ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), shift_t, imm_shift, (rd), (rn), 0, (op), cond))
364
365 #define ARM_DPIOP_S_REG_IMMSHIFT_COND(p, op, rd, rn, rm, shift_t, imm_shift, cond) \
366         ARM_EMIT(p, ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), shift_t, imm_shift, (rd), (rn), 1, (op), cond))
367
368 #define ARM_DPIOP_REG_REG_COND(p, op, rd, rn, rm, cond) \
369         ARM_EMIT(p, ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), ARMSHIFT_LSL, 0, (rd), (rn), 0, (op), cond))
370
371 #define ARM_DPIOP_S_REG_REG_COND(p, op, rd, rn, rm, cond) \
372         ARM_EMIT(p, ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), ARMSHIFT_LSL, 0, (rd), (rn), 1, (op), cond))
373
374 /* inline */
375 #define ARM_IASM_DPIOP_REG_IMMSHIFT_COND(p, op, rd, rn, rm, shift_t, imm_shift, cond) \
376         ARM_IASM(ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), shift_t, imm_shift, (rd), (rn), 0, (op), cond))
377
378 #define ARM_IASM_DPIOP_S_REG_IMMSHIFT_COND(p, op, rd, rn, rm, shift_t, imm_shift, cond) \
379         ARM_IASM(ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), shift_t, imm_shift, (rd), (rn), 1, (op), cond))
380
381 #define ARM_IASM_DPIOP_REG_REG_COND(p, op, rd, rn, rm, cond) \
382         ARM_IASM(ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), ARMSHIFT_LSL, 0, (rd), (rn), 0, (op), cond))
383
384 #define ARM_IASM_DPIOP_S_REG_REG_COND(p, op, rd, rn, rm, cond) \
385         ARM_IASM_EMIT(ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), ARMSHIFT_LSL, 0, (rd), (rn), 1, (op), cond))
386
387
388 /* Rd := Rn op (Rm shift_type Rs) */
389 #define ARM_DEF_DPI_REG_REGSHIFT_COND(rm, shift_type, rs, rd, rn, s, op, cond) \
390         (rm)                        | \
391         (1 << 4)                    | \
392         ((shift_type & 3) << 5)     | \
393         ((rs) << 8)                 | \
394         ((rd) << 12)                | \
395         ((rn) << 16)                | \
396         ((s) << 20)                 | \
397         ((op) << 21)                | \
398         (ARM_DPI_TAG)               | \
399         ARM_DEF_COND(cond)
400
401 /* codegen */
402 #define ARM_DPIOP_REG_REGSHIFT_COND(p, op, rd, rn, rm, shift_t, rs, cond) \
403         ARM_EMIT(p, ARM_DEF_DPI_REG_REGSHIFT_COND((rm), shift_t, (rs), (rd), (rn), 0, (op), cond))
404
405 #define ARM_DPIOP_S_REG_REGSHIFT_COND(p, op, rd, rn, rm, shift_t, rs, cond) \
406         ARM_EMIT(p, ARM_DEF_DPI_REG_REGSHIFT_COND((rm), shift_t, (rs), (rd), (rn), 1, (op), cond))
407
408 /* inline */
409 #define ARM_IASM_DPIOP_REG_REGSHIFT_COND(p, op, rd, rn, rm, shift_t, rs, cond) \
410         ARM_IASM(ARM_DEF_DPI_REG_REGSHIFT_COND((rm), shift_t, (rs), (rd), (rn), 0, (op), cond))
411
412 #define ARM_IASM_DPIOP_S_REG_REGSHIFT_COND(p, op, rd, rn, rm, shift_t, rs, cond) \
413         ARM_IASM(ARM_DEF_DPI_REG_REGSHIFT_COND((rm), shift_t, (rs), (rd), (rn), 1, (op), cond))
414
415
416
417 /* Multiple register transfer. */
418 typedef struct {
419         arminstr_t reg_list : 16; /* bitfield */
420         arminstr_t rn       :  4; /* base reg */
421         arminstr_t ls       :  1; /* load(1)/store(0) */
422         arminstr_t wb       :  1; /* write-back "!" */
423         arminstr_t s        :  1; /* restore PSR, force user bit */
424         arminstr_t u        :  1; /* up/down */
425         arminstr_t p        :  1; /* pre(1)/post(0) index */
426         arminstr_t tag      :  3; /* 1 0 0 */
427         arminstr_t cond     :  4;
428 } ARMInstrMRT;
429
430 #define ARM_MRT_ID 4
431 #define ARM_MRT_MASK 7 << 25
432 #define ARM_MRT_TAG ARM_MRT_ID << 25
433
434 #define ARM_DEF_MRT(regs, rn, l, w, s, u, p, cond) \
435         (regs)        | \
436         (rn << 16)    | \
437         (l << 20)     | \
438         (w << 21)     | \
439         (s << 22)     | \
440         (u << 23)     | \
441         (p << 24)     | \
442         (ARM_MRT_TAG) | \
443         ARM_DEF_COND(cond)
444
445
446 #define ARM_LDMIA(p, base, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, base, 1, 0, 0, 1, 0, ARMCOND_AL))
447 #define ARM_STMIA(p, base, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, base, 0, 0, 0, 1, 0, ARMCOND_AL))
448
449 /* stmdb sp!, {regs} */
450 #define ARM_PUSH(p, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, ARMREG_SP, 0, 1, 0, 0, 1, ARMCOND_AL))
451 #define ARM_IASM_PUSH(regs) ARM_IASM(ARM_DEF_MRT(regs, ARMREG_SP, 0, 1, 0, 0, 1, ARMCOND_AL))
452
453 /* ldmia sp!, {regs} */
454 #define ARM_POP(p, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, ARMREG_SP, 1, 1, 0, 1, 0, ARMCOND_AL))
455 #define ARM_IASM_POP(regs) ARM_IASM_EMIT(ARM_DEF_MRT(regs, ARMREG_SP, 1, 1, 0, 1, 0, ARMCOND_AL))
456
457 /* ldmia sp, {regs} ; (no write-back) */
458 #define ARM_POP_NWB(p, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, ARMREG_SP, 1, 0, 0, 1, 0, ARMCOND_AL))
459 #define ARM_IASM_POP_NWB(regs) ARM_IASM_EMIT(ARM_DEF_MRT(regs, ARMREG_SP, 1, 0, 0, 1, 0, ARMCOND_AL))
460
461 #define ARM_PUSH1(p, r1) ARM_PUSH(p, (1 << r1))
462 #define ARM_PUSH2(p, r1, r2) ARM_PUSH(p, (1 << r1) | (1 << r2))
463 #define ARM_PUSH3(p, r1, r2, r3) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3))
464 #define ARM_PUSH4(p, r1, r2, r3, r4) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4))
465 #define ARM_PUSH5(p, r1, r2, r3, r4, r5) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5))
466 #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))
467 #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))
468 #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))
469
470 #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))
471 #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))
472 #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))
473 #define ARM_POP5(p, r1, r2, r3, r4, r5) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5))
474 #define ARM_POP4(p, r1, r2, r3, r4) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4))
475 #define ARM_POP3(p, r1, r2, r3) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3))
476 #define ARM_POP2(p, r1, r2) ARM_POP(p, (1 << r1) | (1 << r2))
477 #define ARM_POP1(p, r1) ARM_POP(p, (1 << r1))
478
479
480 /* Multiply instructions */
481 typedef struct {
482         arminstr_t rm     : 4;
483         arminstr_t tag2   : 4;   /* 9 */
484         arminstr_t rs     : 4;
485         arminstr_t rn     : 4;
486         arminstr_t rd     : 4;
487         arminstr_t s      : 1;
488         arminstr_t opcode : 3;
489         arminstr_t tag    : 4;
490         arminstr_t cond   : 4;
491 } ARMInstrMul;
492
493 #define ARM_MUL_ID 0
494 #define ARM_MUL_ID2 9
495 #define ARM_MUL_MASK ((0xF << 24) | (0xF << 4))
496 #define ARM_MUL_TAG ((ARM_MUL_ID << 24) | (ARM_MUL_ID2 << 4))
497
498 #define ARM_DEF_MUL_COND(op, rd, rm, rs, rn, s, cond) \
499         (rm)             | \
500         ((rs) << 8)      | \
501         ((rn) << 12)     | \
502         ((rd) << 16)     | \
503         ((s & 1) << 17)  | \
504         ((op & 7) << 18) | \
505         ARM_MUL_TAG      | \
506         ARM_DEF_COND(cond)
507
508 /* Rd := (Rm * Rs)[31:0]; 32 x 32 -> 32 */
509 #define ARM_MUL_COND(p, rd, rm, rs, cond) \
510         ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 0, cond))
511 #define ARM_MUL(p, rd, rm, rs) \
512         ARM_MUL_COND(p, rd, rm, rs, ARMCOND_AL)
513 #define ARM_MULS_COND(p, rd, rm, rs, cond) \
514         ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 1, cond))
515 #define ARM_MULS(p, rd, rm, rs) \
516         ARM_MULS_COND(p, rd, rm, rs, ARMCOND_AL)
517 #define ARM_MUL_REG_REG(p, rd, rm, rs) ARM_MUL(p, rd, rm, rs)
518 #define ARM_MULS_REG_REG(p, rd, rm, rs) ARM_MULS(p, rd, rm, rs)
519
520 /* inline */
521 #define ARM_IASM_MUL_COND(rd, rm, rs, cond) \
522         ARM_IASM_EMIT(ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 0, cond))
523 #define ARM_IASM_MUL(rd, rm, rs) \
524         ARM_IASM_MUL_COND(rd, rm, rs, ARMCOND_AL)
525 #define ARM_IASM_MULS_COND(rd, rm, rs, cond) \
526         ARM_IASM_EMIT(ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 1, cond))
527 #define ARM_IASM_MULS(rd, rm, rs) \
528         ARM_IASM_MULS_COND(rd, rm, rs, ARMCOND_AL)
529
530
531 /* Rd := (Rm * Rs) + Rn; 32x32+32->32 */
532 #define ARM_MLA_COND(p, rd, rm, rs, rn, cond) \
533         ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MLA, rd, rm, rs, rn, 0, cond))
534 #define ARM_MLA(p, rd, rm, rs, rn) \
535         ARM_MLA_COND(p, rd, rm, rs, rn, ARMCOND_AL)
536 #define ARM_MLAS_COND(p, rd, rm, rs, rn, cond) \
537         ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MLA, rd, rm, rs, rn, 1, cond))
538 #define ARM_MLAS(p, rd, rm, rs, rn) \
539         ARM_MLAS_COND(p, rd, rm, rs, rn, ARMCOND_AL)
540
541 /* inline */
542 #define ARM_IASM_MLA_COND(rd, rm, rs, rn, cond) \
543         ARM_IASM_EMIT(ARM_DEF_MUL_COND(ARMOP_MLA, rd, rm, rs, rn, 0, cond))
544 #define ARM_IASM_MLA(rd, rm, rs, rn) \
545         ARM_IASM_MLA_COND(rd, rm, rs, rn, ARMCOND_AL)
546 #define ARM_IASM_MLAS_COND(rd, rm, rs, rn, cond) \
547         ARM_IASM_EMIT(ARM_DEF_MUL_COND(ARMOP_MLA, rd, rm, rs, rn, 1, cond))
548 #define ARM_IASM_MLAS(rd, rm, rs, rn) \
549         ARM_IASM_MLAS_COND(rd, rm, rs, rn, ARMCOND_AL)
550
551
552
553 /*  Word/byte transfer */
554 typedef union {
555         ARMDPI_op2_reg_imm op2_reg_imm;
556         struct {
557                 arminstr_t op2_imm : 12;
558                 arminstr_t rd      :  4;
559                 arminstr_t rn      :  4;
560                 arminstr_t ls      :  1;
561                 arminstr_t wb      :  1;
562                 arminstr_t b       :  1;
563                 arminstr_t u       :  1; /* down(0) / up(1) */
564                 arminstr_t p       :  1; /* post-index(0) / pre-index(1) */
565                 arminstr_t type    :  1; /* imm(0) / register(1) */
566                 arminstr_t tag     :  2; /* 0 1 */
567                 arminstr_t cond    :  4;
568         } all;
569 } ARMInstrWXfer;
570
571 #define ARM_WXFER_ID 1
572 #define ARM_WXFER_MASK 3 << 26
573 #define ARM_WXFER_TAG ARM_WXFER_ID << 26
574
575
576 #define ARM_DEF_WXFER_IMM(imm12, rd, rn, ls, wb, b, p, cond) \
577         ((((int)imm12) < 0) ? -(int)(imm12) : (imm12)) | \
578         ((rd) << 12)                                   | \
579         ((rn) << 16)                                   | \
580         ((ls) << 20)                                   | \
581         ((wb) << 21)                                   | \
582         ((b)  << 22)                                   | \
583         (((int)(imm12) >= 0) << 23)                    | \
584         ((p) << 24)                                    | \
585         ARM_WXFER_TAG                                  | \
586         ARM_DEF_COND(cond)
587
588 #define ARM_WXFER_MAX_OFFS 0xFFF
589
590 /* this macro checks for imm12 bounds */
591 #define ARM_EMIT_WXFER_IMM(ptr, imm12, rd, rn, ls, wb, b, p, cond) \
592         do { \
593                 int _imm12 = (int)(imm12) < -ARM_WXFER_MAX_OFFS  \
594                              ? -ARM_WXFER_MAX_OFFS               \
595                              : (int)(imm12) > ARM_WXFER_MAX_OFFS \
596                              ? ARM_WXFER_MAX_OFFS                \
597                              : (int)(imm12);                     \
598                 ARM_EMIT((ptr), \
599                 ARM_DEF_WXFER_IMM(_imm12, (rd), (rn), (ls), (wb), (b), (p), (cond))); \
600         } while (0)
601
602
603 /* LDRx */
604 /* immediate offset, post-index */
605 #define ARM_LDR_IMM_POST_COND(p, rd, rn, imm, cond) \
606         ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_LDR, 0, 0, 0, cond))
607
608 #define ARM_LDR_IMM_POST(p, rd, rn, imm) ARM_LDR_IMM_POST_COND(p, rd, rn, imm, ARMCOND_AL)
609
610 #define ARM_LDRB_IMM_POST_COND(p, rd, rn, imm, cond) \
611         ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_LDR, 0, 1, 0, cond))
612
613 #define ARM_LDRB_IMM_POST(p, rd, rn, imm) ARM_LDRB_IMM_POST_COND(p, rd, rn, imm, ARMCOND_AL)
614
615 /* immediate offset, pre-index */
616 #define ARM_LDR_IMM_COND(p, rd, rn, imm, cond) \
617         ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_LDR, 0, 0, 1, cond))
618
619 #define ARM_LDR_IMM(p, rd, rn, imm) ARM_LDR_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
620
621 #define ARM_LDRB_IMM_COND(p, rd, rn, imm, cond) \
622         ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_LDR, 0, 1, 1, cond))
623
624 #define ARM_LDRB_IMM(p, rd, rn, imm) ARM_LDRB_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
625
626 /* STRx */
627 /* immediate offset, post-index */
628 #define ARM_STR_IMM_POST_COND(p, rd, rn, imm, cond) \
629         ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_STR, 0, 0, 0, cond))
630
631 #define ARM_STR_IMM_POST(p, rd, rn, imm) ARM_STR_IMM_POST_COND(p, rd, rn, imm, ARMCOND_AL)
632
633 #define ARM_STRB_IMM_POST_COND(p, rd, rn, imm, cond) \
634         ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_STR, 0, 1, 0, cond))
635
636 #define ARM_STRB_IMM_POST(p, rd, rn, imm) ARM_STRB_IMM_POST_COND(p, rd, rn, imm, ARMCOND_AL)
637
638 /* immediate offset, pre-index */
639 #define ARM_STR_IMM_COND(p, rd, rn, imm, cond) \
640         ARM_EMIT_WXFER_IMM(p, imm, rd, rn, ARMOP_STR, 0, 0, 1, cond)
641 /*      ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_STR, 0, 0, 1, cond)) */
642
643 #define ARM_STR_IMM(p, rd, rn, imm) ARM_STR_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
644
645 #define ARM_STRB_IMM_COND(p, rd, rn, imm, cond) \
646         ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_STR, 0, 1, 1, cond))
647
648 #define ARM_STRB_IMM(p, rd, rn, imm) ARM_STRB_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
649
650 /* write-back */
651 #define ARM_STR_IMM_WB_COND(p, rd, rn, imm, cond) \
652         ARM_EMIT_WXFER_IMM(p, imm, rd, rn, ARMOP_STR, 1, 0, 1, cond)
653 #define ARM_STR_IMM_WB(p, rd, rn, imm) ARM_STR_IMM_WB_COND(p, rd, rn, imm, ARMCOND_AL)
654
655
656 #define ARM_DEF_WXFER_REG_REG_UPDOWN_COND(rm, shift_type, shift, rd, rn, ls, wb, b, u, p, cond) \
657         (rm)                | \
658         ((shift_type) << 5) | \
659         ((shift) << 7)      | \
660         ((rd) << 12)        | \
661         ((rn) << 16)        | \
662         ((ls) << 20)        | \
663         ((wb) << 21)        | \
664         ((b)  << 22)        | \
665         ((u)  << 23)        | \
666         ((p)  << 24)        | \
667         (1    << 25)        | \
668         ARM_WXFER_TAG       | \
669         ARM_DEF_COND(cond)
670
671 #define ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ls, wb, b, p, cond) \
672         ARM_DEF_WXFER_REG_REG_UPDOWN_COND(rm, shift_type, shift, rd, rn, ls, wb, b, ARM_UP, p, cond)
673 #define ARM_DEF_WXFER_REG_MINUS_REG_COND(rm, shift_type, shift, rd, rn, ls, wb, b, p, cond) \
674         ARM_DEF_WXFER_REG_REG_UPDOWN_COND(rm, shift_type, shift, rd, rn, ls, wb, b, ARM_DOWN, p, cond)
675
676
677 #define ARM_LDR_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, cond) \
678         ARM_EMIT(p, ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ARMOP_LDR, 0, 0, 1, cond))
679 #define ARM_LDR_REG_REG_SHIFT(p, rd, rn, rm, shift_type, shift) \
680         ARM_LDR_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, ARMCOND_AL)
681 #define ARM_LDR_REG_REG(p, rd, rn, rm) \
682         ARM_LDR_REG_REG_SHIFT(p, rd, rn, rm, ARMSHIFT_LSL, 0)
683
684 #define ARM_LDRB_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, cond) \
685         ARM_EMIT(p, ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ARMOP_LDR, 0, 1, 1, cond))
686 #define ARM_LDRB_REG_REG_SHIFT(p, rd, rn, rm, shift_type, shift) \
687         ARM_LDRB_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, ARMCOND_AL)
688 #define ARM_LDRB_REG_REG(p, rd, rn, rm) \
689         ARM_LDRB_REG_REG_SHIFT(p, rd, rn, rm, ARMSHIFT_LSL, 0)
690
691 #define ARM_STR_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, cond) \
692         ARM_EMIT(p, ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ARMOP_STR, 0, 0, 1, cond))
693 #define ARM_STR_REG_REG_SHIFT(p, rd, rn, rm, shift_type, shift) \
694         ARM_STR_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, ARMCOND_AL)
695 #define ARM_STR_REG_REG(p, rd, rn, rm) \
696         ARM_STR_REG_REG_SHIFT(p, rd, rn, rm, ARMSHIFT_LSL, 0)
697
698 /* zero-extend */
699 #define ARM_STRB_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, cond) \
700         ARM_EMIT(p, ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ARMOP_STR, 0, 1, 1, cond))
701 #define ARM_STRB_REG_REG_SHIFT(p, rd, rn, rm, shift_type, shift) \
702         ARM_STRB_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, ARMCOND_AL)
703 #define ARM_STRB_REG_REG(p, rd, rn, rm) \
704         ARM_STRB_REG_REG_SHIFT(p, rd, rn, rm, ARMSHIFT_LSL, 0)
705
706
707 /* ARMv4+ */
708 /* Half-word or byte (signed) transfer. */
709 typedef struct {
710         arminstr_t rm     : 4; /* imm_lo */
711         arminstr_t tag3   : 1; /* 1 */
712         arminstr_t h      : 1; /* half-word or byte */
713         arminstr_t s      : 1; /* sign-extend or zero-extend */
714         arminstr_t tag2   : 1; /* 1 */
715         arminstr_t imm_hi : 4;
716         arminstr_t rd     : 4;
717         arminstr_t rn     : 4;
718         arminstr_t ls     : 1;
719         arminstr_t wb     : 1;
720         arminstr_t type   : 1; /* imm(1) / reg(0) */
721         arminstr_t u      : 1; /* +- */
722         arminstr_t p      : 1; /* pre/post-index */
723         arminstr_t tag    : 3;
724         arminstr_t cond   : 4;
725 } ARMInstrHXfer;
726
727 #define ARM_HXFER_ID 0
728 #define ARM_HXFER_ID2 1
729 #define ARM_HXFER_ID3 1
730 #define ARM_HXFER_MASK ((0x7 << 25) | (0x9 << 4))
731 #define ARM_HXFER_TAG ((ARM_HXFER_ID << 25) | (ARM_HXFER_ID2 << 7) | (ARM_HXFER_ID3 << 4))
732
733 #define ARM_DEF_HXFER_IMM_COND(imm, h, s, rd, rn, ls, wb, p, cond) \
734         ((imm) & 0xF)               | \
735         ((h) << 5)                  | \
736         ((s) << 6)                  | \
737         (((imm) << 4) & (0xF << 8)) | \
738         ((rd) << 12)                | \
739         ((rn) << 16)                | \
740         ((ls) << 20)                | \
741         ((wb) << 21)                | \
742         (1 << 22)                   | \
743         (((int)(imm) >= 0) << 23)   | \
744         ((p) << 24)                 | \
745         ARM_HXFER_TAG               | \
746         ARM_DEF_COND(cond)
747
748 #define ARM_LDRH_IMM_COND(p, rd, rn, imm, cond) \
749         ARM_EMIT(p, ARM_DEF_HXFER_IMM_COND(imm, 1, 0, rd, rn, ARMOP_LDR, 0, 1, cond))
750 #define ARM_LDRH_IMM(p, rd, rn, imm) \
751         ARM_LDRH_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
752 #define ARM_LDRSH_IMM_COND(p, rd, rn, imm, cond) \
753         ARM_EMIT(p, ARM_DEF_HXFER_IMM_COND(imm, 1, 1, rd, rn, ARMOP_LDR, 0, 1, cond))
754 #define ARM_LDRSH_IMM(p, rd, rn, imm) \
755         ARM_LDRSH_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
756 #define ARM_LDRSB_IMM_COND(p, rd, rn, imm, cond) \
757         ARM_EMIT(p, ARM_DEF_HXFER_IMM_COND(imm, 0, 1, rd, rn, ARMOP_LDR, 0, 1, cond))
758 #define ARM_LDRSB_IMM(p, rd, rn, imm) \
759         ARM_LDRSB_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
760
761
762 #define ARM_STRH_IMM_COND(p, rd, rn, imm, cond) \
763         ARM_EMIT(p, ARM_DEF_HXFER_IMM_COND(imm, 1, 0, rd, rn, ARMOP_STR, 0, 1, cond))
764 #define ARM_STRH_IMM(p, rd, rn, imm) \
765         ARM_STRH_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
766
767
768 #define ARM_DEF_HXFER_REG_REG_UPDOWN_COND(rm, h, s, rd, rn, ls, wb, u, p, cond) \
769         ((rm) & 0xF)                | \
770         ((h) << 5)                  | \
771         ((s) << 6)                  | \
772         ((rd) << 12)                | \
773         ((rn) << 16)                | \
774         ((ls) << 20)                | \
775         ((wb) << 21)                | \
776         (0 << 22)                   | \
777         ((u) << 23)                 | \
778         ((p) << 24)                 | \
779         ARM_HXFER_TAG               | \
780         ARM_DEF_COND(cond)
781
782 #define ARM_DEF_HXFER_REG_REG_COND(rm, h, s, rd, rn, ls, wb, p, cond) \
783         ARM_DEF_HXFER_REG_REG_UPDOWN_COND(rm, h, s, rd, rn, ls, wb, ARM_UP, p, cond)
784 #define ARM_DEF_HXFER_REG_MINUS_REG_COND(rm, h, s, rd, rn, ls, wb, p, cond) \
785         ARM_DEF_HXFER_REG_REG_UPDOWN_COND(rm, h, s, rd, rn, ls, wb, ARM_DOWN, p, cond)
786
787 #define ARM_LDRH_REG_REG_COND(p, rm, rd, rn, cond) \
788         ARM_EMIT(p, ARM_DEF_HXFER_REG_REG_COND(rm, 1, 0, rd, rn, ARMOP_LDR, 0, 1, cond))
789 #define ARM_LDRH_REG_REG(p, rm, rd, rn) \
790         ARM_LDRH_REG_REG_COND(p, rm, rd, rn, ARMCOND_AL)
791 #define ARM_LDRSH_REG_REG_COND(p, rm, rd, rn, cond) \
792         ARM_EMIT(p, ARM_DEF_HXFER_REG_REG_COND(rm, 1, 1, rd, rn, ARMOP_LDR, 0, 1, cond))
793 #define ARM_LDRSH_REG_REG(p, rm, rd, rn) \
794         ARM_LDRSH_REG_REG_COND(p, rm, rd, rn, ARMCOND_AL)
795 #define ARM_LDRSB_REG_REG_COND(p, rm, rd, rn, cond) \
796         ARM_EMIT(p, ARM_DEF_HXFER_REG_REG_COND(rm, 0, 1, rd, rn, ARMOP_LDR, 0, 1, cond))
797 #define ARM_LDRSB_REG_REG(p, rm, rd, rn) ARM_LDRSB_REG_REG_COND(p, rm, rd, rn, ARMCOND_AL)
798
799 #define ARM_STRH_REG_REG_COND(p, rm, rd, rn, cond) \
800         ARM_EMIT(p, ARM_DEF_HXFER_REG_REG_COND(rm, 1, 0, rd, rn, ARMOP_STR, 0, 1, cond))
801 #define ARM_STRH_REG_REG(p, rm, rd, rn) \
802         ARM_STRH_REG_REG_COND(p, rm, rd, rn, ARMCOND_AL)
803
804
805
806 /* Swap */
807 typedef struct {
808         arminstr_t rm   : 4;
809         arminstr_t tag3 : 8; /* 0x9 */
810         arminstr_t rd   : 4;
811         arminstr_t rn   : 4;
812         arminstr_t tag2 : 2;
813         arminstr_t b    : 1;
814         arminstr_t tag  : 5; /* 0x2 */
815         arminstr_t cond : 4;
816 } ARMInstrSwap;
817
818 #define ARM_SWP_ID 2
819 #define ARM_SWP_ID2 9
820 #define ARM_SWP_MASK ((0x1F << 23) | (3 << 20) | (0xFF << 4))
821 #define ARM_SWP_TAG ((ARM_SWP_ID << 23) | (ARM_SWP_ID2 << 4))
822
823
824
825 /* Software interrupt */
826 typedef struct {
827         arminstr_t num  : 24;
828         arminstr_t tag  :  4;
829         arminstr_t cond :  4;
830 } ARMInstrSWI;
831
832 #define ARM_SWI_ID 0xF
833 #define ARM_SWI_MASK (0xF << 24)
834 #define ARM_SWI_TAG (ARM_SWI_ID << 24)
835
836
837
838 /* Co-processor Data Processing */
839 typedef struct {
840         arminstr_t crm  : 4;
841         arminstr_t tag2 : 1; /* 0 */
842         arminstr_t op2  : 3;
843         arminstr_t cpn  : 4; /* CP number */
844         arminstr_t crd  : 4;
845         arminstr_t crn  : 4;
846         arminstr_t op   : 4;
847         arminstr_t tag  : 4; /* 0xE */
848         arminstr_t cond : 4;
849 } ARMInstrCDP;
850
851 #define ARM_CDP_ID 0xE
852 #define ARM_CDP_ID2 0
853 #define ARM_CDP_MASK ((0xF << 24) | (1 << 4))
854 #define ARM_CDP_TAG ((ARM_CDP_ID << 24) | (ARM_CDP_ID2 << 4))
855
856
857 /* Co-processor Data Transfer (ldc/stc) */
858 typedef struct {
859         arminstr_t offs : 8;
860         arminstr_t cpn  : 4;
861         arminstr_t crd  : 4;
862         arminstr_t rn   : 4;
863         arminstr_t ls   : 1;
864         arminstr_t wb   : 1;
865         arminstr_t n    : 1;
866         arminstr_t u    : 1;
867         arminstr_t p    : 1;
868         arminstr_t tag  : 3;
869         arminstr_t cond : 4;
870 } ARMInstrCDT;
871
872 #define ARM_CDT_ID 6
873 #define ARM_CDT_MASK (7 << 25)
874 #define ARM_CDT_TAG (ARM_CDT_ID << 25)
875
876
877 /* Co-processor Register Transfer (mcr/mrc) */
878 typedef struct {
879         arminstr_t crm  : 4;
880         arminstr_t tag2 : 1;
881         arminstr_t op2  : 3;
882         arminstr_t cpn  : 4;
883         arminstr_t rd   : 4;
884         arminstr_t crn  : 4;
885         arminstr_t ls   : 1;
886         arminstr_t op1  : 3;
887         arminstr_t tag  : 4;
888         arminstr_t cond : 4;
889 } ARMInstrCRT;
890
891 #define ARM_CRT_ID 0xE
892 #define ARM_CRT_ID2 0x1
893 #define ARM_CRT_MASK ((0xF << 24) | (1 << 4))
894 #define ARM_CRT_TAG ((ARM_CRT_ID << 24) | (ARM_CRT_ID2 << 4))
895
896 /* Move register to PSR. */
897 typedef union {
898         ARMDPI_op2_imm op2_imm;
899         struct {
900                 arminstr_t rm   : 4;
901                 arminstr_t pad  : 8; /* 0 */
902                 arminstr_t tag4 : 4; /* 0xF */
903                 arminstr_t fld  : 4;
904                 arminstr_t tag3 : 2; /* 0x2 */
905                 arminstr_t sel  : 1;
906                 arminstr_t tag2 : 2; /* 0x2 */
907                 arminstr_t type : 1;
908                 arminstr_t tag  : 2; /* 0 */
909                 arminstr_t cond : 4;
910         } all;
911 } ARMInstrMSR;
912
913 #define ARM_MSR_ID 0
914 #define ARM_MSR_ID2 2
915 #define ARM_MSR_ID3 2
916 #define ARM_MSR_ID4 0xF
917 #define ARM_MSR_MASK ((3 << 26) | \
918                       (3 << 23) | \
919                       (3 << 20) | \
920                       (0xF << 12))
921 #define ARM_MSR_TAG ((ARM_MSR_ID << 26)  | \
922                      (ARM_MSR_ID2 << 23) | \
923                      (ARM_MSR_ID3 << 20) | \
924                      (ARM_MSR_ID4 << 12))
925
926
927 /* Move PSR to register. */
928 typedef struct {
929         arminstr_t tag3 : 12;
930         arminstr_t rd   :  4;
931         arminstr_t tag2 :  6;
932         arminstr_t sel  :  1; /* CPSR | SPSR */
933         arminstr_t tag  :  5;
934         arminstr_t cond :  4;
935 } ARMInstrMRS;
936
937 #define ARM_MRS_ID 2
938 #define ARM_MRS_ID2 0xF
939 #define ARM_MRS_ID3 0
940 #define ARM_MRS_MASK ((0x1F << 23) | (0x3F << 16) | 0xFFF)
941 #define ARM_MRS_TAG ((ARM_MRS_ID << 23) | (ARM_MRS_ID2 << 16) | ARM_MRS_ID3)
942
943
944
945
946 #include "arm_dpimacros.h"
947
948 #define ARM_NOP(p) ARM_MOV_REG_REG(p, ARMREG_R0, ARMREG_R0)
949
950
951 #define ARM_SHL_IMM_COND(p, rd, rm, imm, cond) \
952         ARM_MOV_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_LSL, imm, cond)
953 #define ARM_SHL_IMM(p, rd, rm, imm) \
954         ARM_SHL_IMM_COND(p, rd, rm, imm, ARMCOND_AL)
955 #define ARM_SHLS_IMM_COND(p, rd, rm, imm, cond) \
956         ARM_MOVS_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_LSL, imm, cond)
957 #define ARM_SHLS_IMM(p, rd, rm, imm) \
958         ARM_SHLS_IMM_COND(p, rd, rm, imm, ARMCOND_AL)
959
960 #define ARM_SHR_IMM_COND(p, rd, rm, imm, cond) \
961         ARM_MOV_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_LSR, imm, cond)
962 #define ARM_SHR_IMM(p, rd, rm, imm) \
963         ARM_SHR_IMM_COND(p, rd, rm, imm, ARMCOND_AL)
964 #define ARM_SHRS_IMM_COND(p, rd, rm, imm, cond) \
965         ARM_MOVS_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_LSR, imm, cond)
966 #define ARM_SHRS_IMM(p, rd, rm, imm) \
967         ARM_SHRS_IMM_COND(p, rd, rm, imm, ARMCOND_AL)
968
969 #define ARM_SAR_IMM_COND(p, rd, rm, imm, cond) \
970         ARM_MOV_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_ASR, imm, cond)
971 #define ARM_SAR_IMM(p, rd, rm, imm) \
972         ARM_SAR_IMM_COND(p, rd, rm, imm, ARMCOND_AL)
973 #define ARM_SARS_IMM_COND(p, rd, rm, imm, cond) \
974         ARM_MOVS_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_ASR, imm, cond)
975 #define ARM_SARS_IMM(p, rd, rm, imm) \
976         ARM_SARS_IMM_COND(p, rd, rm, imm, ARMCOND_AL)
977
978 #define ARM_ROR_IMM_COND(p, rd, rm, imm, cond) \
979         ARM_MOV_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_ROR, imm, cond)
980 #define ARM_ROR_IMM(p, rd, rm, imm) \
981         ARM_ROR_IMM_COND(p, rd, rm, imm, ARMCOND_AL)
982 #define ARM_RORS_IMM_COND(p, rd, rm, imm, cond) \
983         ARM_MOVS_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_ROR, imm, cond)
984 #define ARM_RORS_IMM(p, rd, rm, imm) \
985         ARM_RORS_IMM_COND(p, rd, rm, imm, ARMCOND_AL)
986
987 #define ARM_SHL_REG_COND(p, rd, rm, rs, cond) \
988         ARM_MOV_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_LSL, rs, cond)
989 #define ARM_SHL_REG(p, rd, rm, rs) \
990         ARM_SHL_REG_COND(p, rd, rm, rs, ARMCOND_AL)
991 #define ARM_SHLS_REG_COND(p, rd, rm, rs, cond) \
992         ARM_MOVS_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_LSL, rs, cond)
993 #define ARM_SHLS_REG(p, rd, rm, rs) \
994         ARM_SHLS_REG_COND(p, rd, rm, rs, ARMCOND_AL)
995 #define ARM_SHLS_REG_REG(p, rd, rm, rs) ARM_SHLS_REG(p, rd, rm, rs)
996
997 #define ARM_SHR_REG_COND(p, rd, rm, rs, cond) \
998         ARM_MOV_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_LSR, rs, cond)
999 #define ARM_SHR_REG(p, rd, rm, rs) \
1000         ARM_SHR_REG_COND(p, rd, rm, rs, ARMCOND_AL)
1001 #define ARM_SHRS_REG_COND(p, rd, rm, rs, cond) \
1002         ARM_MOVS_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_LSR, rs, cond)
1003 #define ARM_SHRS_REG(p, rd, rm, rs) \
1004         ARM_SHRS_REG_COND(p, rd, rm, rs, ARMCOND_AL)
1005 #define ARM_SHRS_REG_REG(p, rd, rm, rs) ARM_SHRS_REG(p, rd, rm, rs)
1006
1007 #define ARM_SAR_REG_COND(p, rd, rm, rs, cond) \
1008         ARM_MOV_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_ASR, rs, cond)
1009 #define ARM_SAR_REG(p, rd, rm, rs) \
1010         ARM_SAR_REG_COND(p, rd, rm, rs, ARMCOND_AL)
1011 #define ARM_SARS_REG_COND(p, rd, rm, rs, cond) \
1012         ARM_MOVS_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_ASR, rs, cond)
1013 #define ARM_SARS_REG(p, rd, rm, rs) \
1014         ARM_SARS_REG_COND(p, rd, rm, rs, ARMCOND_AL)
1015 #define ARM_SARS_REG_REG(p, rd, rm, rs) ARM_SARS_REG(p, rd, rm, rs)
1016
1017 #define ARM_ROR_REG_COND(p, rd, rm, rs, cond) \
1018         ARM_MOV_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_ROR, rs, cond)
1019 #define ARM_ROR_REG(p, rd, rm, rs) \
1020         ARM_ROR_REG_COND(p, rd, rm, rs, ARMCOND_AL)
1021 #define ARM_RORS_REG_COND(p, rd, rm, rs, cond) \
1022         ARM_MOVS_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_ROR, rs, cond)
1023 #define ARM_RORS_REG(p, rd, rm, rs) \
1024         ARM_RORS_REG_COND(p, rd, rm, rs, ARMCOND_AL)
1025 #define ARM_RORS_REG_REG(p, rd, rm, rs) ARM_RORS_REG(p, rd, rm, rs)
1026
1027 #define ARM_DBRK(p) ARM_EMIT(p, 0xE6000010)
1028 #define ARM_IASM_DBRK() ARM_IASM_EMIT(0xE6000010)
1029
1030 #define ARM_INC(p, reg) ARM_ADD_REG_IMM8(p, reg, reg, 1)
1031 #define ARM_DEC(p, reg) ARM_SUB_REG_IMM8(p, reg, reg, 1)
1032
1033
1034 /* ARM V5 */
1035
1036 /* Count leading zeros, CLZ{cond} Rd, Rm */
1037 typedef struct {
1038         arminstr_t rm   :  4;
1039         arminstr_t tag2 :  8;
1040         arminstr_t rd   :  4;
1041         arminstr_t tag  :  12;
1042         arminstr_t cond :  4;
1043 } ARMInstrCLZ;
1044
1045 #define ARM_CLZ_ID 0x16F
1046 #define ARM_CLZ_ID2 0xF1
1047 #define ARM_CLZ_MASK ((0xFFF << 16) | (0xFF < 4))
1048 #define ARM_CLZ_TAG ((ARM_CLZ_ID << 16) | (ARM_CLZ_ID2 << 4))
1049
1050
1051
1052
1053 typedef union {
1054         ARMInstrBR    br;
1055         ARMInstrDPI   dpi;
1056         ARMInstrMRT   mrt;
1057         ARMInstrMul   mul;
1058         ARMInstrWXfer wxfer;
1059         ARMInstrHXfer hxfer;
1060         ARMInstrSwap  swp;
1061         ARMInstrCDP   cdp;
1062         ARMInstrCDT   cdt;
1063         ARMInstrCRT   crt;
1064         ARMInstrSWI   swi;
1065         ARMInstrMSR   msr;
1066         ARMInstrMRS   mrs;
1067         ARMInstrCLZ   clz;
1068
1069         ARMInstrGeneric generic;
1070         arminstr_t      raw;
1071 } ARMInstr;
1072
1073
1074 #ifdef __cplusplus
1075 }
1076 #endif
1077
1078 #endif /* ARM_H */
1079