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