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