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