move platform-independent stuff out of /gp2x.
[gpsp.git] / arm / arm_codegen.h
CommitLineData
2823a4c8 1/*
2 * arm-codegen.h
3 *
4 * Copyright (c) 2002 Wild West Software
5 * Copyright (c) 2001, 2002 Sergey Chaban
6 *
7 * Permission is hereby granted, free of charge, to any person
8 * obtaining a copy of this software and associated documentation
9 * files (the "Software"), to deal in the Software without restriction,
10 * including without limitation the rights to use, copy, modify, merge,
11 * publish, distribute, sublicense, and/or sell copies of the Software,
12 * and to permit persons to whom the Software is furnished to do so,
13 * subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
24 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 */
27
28
29#ifndef ARM_CG_H
30#define ARM_CG_H
31
32typedef unsigned long arminstr_t;
33typedef unsigned long armword_t;
34
35/* Helper functions */
36/*void arm_emit_std_prologue(cg_segment_t * segment, unsigned int local_size);
37void arm_emit_std_epilogue(cg_segment_t * segment, unsigned int local_size, int pop_regs);
38void arm_emit_lean_prologue(cg_segment_t * segment, unsigned int local_size, int push_regs);
39int arm_is_power_of_2(armword_t val);
40int calc_arm_mov_const_shift(armword_t val);
41int is_arm_const(armword_t val);
42int arm_bsf(armword_t val);
43void arm_mov_reg_imm32_cond(cg_segment_t * segment, int reg, armword_t imm32, int cond);
44void arm_mov_reg_imm32(cg_segment_t * segment, int reg, armword_t imm32);*/
45
46
47//*** check for correctness ***
48//extern u32* x86Ptr;
49
50void 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
81extern "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
115typedef 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
194typedef 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
219typedef 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
248typedef 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
259typedef 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
266typedef 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
305typedef 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. */
332typedef struct {
333 arminstr_t icode : 28;
334 arminstr_t cond : 4;
335} ARMInstrGeneric;
336
337
338
339/* Branch or Branch with Link instructions. */
340typedef 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
371typedef struct {
372 arminstr_t imm : 8;
373 arminstr_t rot : 4;
374} ARMDPI_op2_imm;
375
376typedef 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 */
384typedef 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 */
393typedef 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 */
403typedef 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. */
523typedef 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 */
599typedef 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 */
714typedef 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. */
892typedef 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 */
1000typedef 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 */
1019typedef 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 */
1032typedef 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) */
1051typedef 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) */
1071typedef 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. */
1113typedef 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. */
1164typedef 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 */
1292typedef 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
1371typedef 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