Merge pull request #2394 from Mailaender/patch-1
[mono.git] / mono / arch / arm / arm-codegen.h
index d8c293a5fc839ac34f7721056e2dcaed34ba6125..3ee083f8010ffdf7bad83cc527f8d32e078e6b00 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * arm-codegen.h
- * Copyright (c) 2002 Sergey Chaban <serge@wildwestsoftware.com>
+ * Copyright (c) 2002-2003 Sergey Chaban <serge@wildwestsoftware.com>
+ * Copyright 2005-2011 Novell Inc
+ * Copyright 2011 Xamarin Inc
  */
 
 
@@ -14,19 +16,6 @@ extern "C" {
 typedef unsigned int arminstr_t;
 typedef unsigned int armword_t;
 
-/* Helper functions */
-arminstr_t* arm_emit_std_prologue(arminstr_t* p, unsigned int local_size);
-arminstr_t* arm_emit_std_epilogue(arminstr_t* p, unsigned int local_size, int pop_regs);
-arminstr_t* arm_emit_lean_prologue(arminstr_t* p, unsigned int local_size, int push_regs);
-int arm_is_power_of_2(armword_t val);
-int calc_arm_mov_const_shift(armword_t val);
-int is_arm_const(armword_t val);
-int arm_bsf(armword_t val);
-arminstr_t* arm_mov_reg_imm32_cond(arminstr_t* p, int reg, armword_t imm32, int cond);
-arminstr_t* arm_mov_reg_imm32(arminstr_t* p, int reg, armword_t imm32);
-
-
-
 #if defined(_MSC_VER) || defined(__CC_NORCROFT)
        void __inline _arm_emit(arminstr_t** p, arminstr_t i) {**p = i; (*p)++;}
 #      define ARM_EMIT(p, i) _arm_emit((arminstr_t**)&p, (arminstr_t)(i))
@@ -449,8 +438,8 @@ typedef struct {
        ARM_DEF_COND(cond)
 
 
-#define ARM_LDMIA(p, base, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, base, 1, 0, 0, 1, 0, ARMCOND_AL))
-#define ARM_STMIA(p, base, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, base, 0, 0, 0, 1, 0, ARMCOND_AL))
+#define ARM_LDM(p, base, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, base, 1, 0, 0, 1, 0, ARMCOND_AL))
+#define ARM_STM(p, base, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, base, 0, 0, 0, 1, 0, ARMCOND_AL))
 
 /* stmdb sp!, {regs} */
 #define ARM_PUSH(p, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, ARMREG_SP, 0, 1, 0, 0, 1, ARMCOND_AL))
@@ -496,19 +485,15 @@ typedef struct {
        arminstr_t cond   : 4;
 } ARMInstrMul;
 
-#define ARM_MUL_ID 0
-#define ARM_MUL_ID2 9
-#define ARM_MUL_MASK ((0xF << 24) | (0xF << 4))
-#define ARM_MUL_TAG ((ARM_MUL_ID << 24) | (ARM_MUL_ID2 << 4))
-
+#define ARM_MUL_ID 9
 #define ARM_DEF_MUL_COND(op, rd, rm, rs, rn, s, cond) \
        (rm)             | \
+       ARM_MUL_ID << 4  | \
        ((rs) << 8)      | \
        ((rn) << 12)     | \
        ((rd) << 16)     | \
-       ((s & 1) << 17)  | \
-       ((op & 7) << 18) | \
-       ARM_MUL_TAG      | \
+       ((s & 1) << 20)  | \
+       ((op & 7) << 21) | \
        ARM_DEF_COND(cond)
 
 /* Rd := (Rm * Rs)[31:0]; 32 x 32 -> 32 */
@@ -790,22 +775,22 @@ typedef struct {
 #define ARM_DEF_HXFER_REG_MINUS_REG_COND(rm, h, s, rd, rn, ls, wb, p, cond) \
        ARM_DEF_HXFER_REG_REG_UPDOWN_COND(rm, h, s, rd, rn, ls, wb, ARM_DOWN, p, cond)
 
-#define ARM_LDRH_REG_REG_COND(p, rm, rd, rn, cond) \
+#define ARM_LDRH_REG_REG_COND(p, rd, rm, rn, cond) \
        ARM_EMIT(p, ARM_DEF_HXFER_REG_REG_COND(rm, 1, 0, rd, rn, ARMOP_LDR, 0, 1, cond))
-#define ARM_LDRH_REG_REG(p, rm, rd, rn) \
-       ARM_LDRH_REG_REG_COND(p, rm, rd, rn, ARMCOND_AL)
-#define ARM_LDRSH_REG_REG_COND(p, rm, rd, rn, cond) \
+#define ARM_LDRH_REG_REG(p, rd, rm, rn) \
+       ARM_LDRH_REG_REG_COND(p, rd, rm, rn, ARMCOND_AL)
+#define ARM_LDRSH_REG_REG_COND(p, rd, rm, rn, cond) \
        ARM_EMIT(p, ARM_DEF_HXFER_REG_REG_COND(rm, 1, 1, rd, rn, ARMOP_LDR, 0, 1, cond))
-#define ARM_LDRSH_REG_REG(p, rm, rd, rn) \
-       ARM_LDRSH_REG_REG_COND(p, rm, rd, rn, ARMCOND_AL)
-#define ARM_LDRSB_REG_REG_COND(p, rm, rd, rn, cond) \
+#define ARM_LDRSH_REG_REG(p, rd, rm, rn) \
+       ARM_LDRSH_REG_REG_COND(p, rd, rm, rn, ARMCOND_AL)
+#define ARM_LDRSB_REG_REG_COND(p, rd, rm, rn, cond) \
        ARM_EMIT(p, ARM_DEF_HXFER_REG_REG_COND(rm, 0, 1, rd, rn, ARMOP_LDR, 0, 1, cond))
-#define ARM_LDRSB_REG_REG(p, rm, rd, rn) ARM_LDRSB_REG_REG_COND(p, rm, rd, rn, ARMCOND_AL)
+#define ARM_LDRSB_REG_REG(p, rd, rm, rn) ARM_LDRSB_REG_REG_COND(p, rd, rm, rn, ARMCOND_AL)
 
-#define ARM_STRH_REG_REG_COND(p, rm, rd, rn, cond) \
+#define ARM_STRH_REG_REG_COND(p, rd, rm, rn, cond) \
        ARM_EMIT(p, ARM_DEF_HXFER_REG_REG_COND(rm, 1, 0, rd, rn, ARMOP_STR, 0, 1, cond))
-#define ARM_STRH_REG_REG(p, rm, rd, rn) \
-       ARM_STRH_REG_REG_COND(p, rm, rd, rn, ARMCOND_AL)
+#define ARM_STRH_REG_REG(p, rd, rm, rn) \
+       ARM_STRH_REG_REG_COND(p, rd, rm, rn, ARMCOND_AL)
 
 
 
@@ -948,8 +933,7 @@ typedef struct {
 
 
 
-
-#include "arm_dpimacros.h"
+#include "mono/arch/arm/arm_dpimacros.h"
 
 #define ARM_NOP(p) ARM_MOV_REG_REG(p, ARMREG_R0, ARMREG_R0)
 
@@ -1030,12 +1014,17 @@ typedef struct {
        ARM_RORS_REG_COND(p, rd, rm, rs, ARMCOND_AL)
 #define ARM_RORS_REG_REG(p, rd, rm, rs) ARM_RORS_REG(p, rd, rm, rs)
 
+#ifdef __native_client_codegen__
+#define ARM_DBRK(p) ARM_EMIT(p, 0xE7FEDEF0)
+#else
 #define ARM_DBRK(p) ARM_EMIT(p, 0xE6000010)
+#endif
 #define ARM_IASM_DBRK() ARM_IASM_EMIT(0xE6000010)
 
 #define ARM_INC(p, reg) ARM_ADD_REG_IMM8(p, reg, reg, 1)
 #define ARM_DEC(p, reg) ARM_SUB_REG_IMM8(p, reg, reg, 1)
 
+#define ARM_MLS(p, rd, rn, rm, ra) ARM_EMIT((p), (ARMCOND_AL << 28) | (0x6 << 20) | ((rd) << 16) | ((ra) << 12) | ((rm) << 8) | (0x9 << 4) | ((rn) << 0))
 
 /* ARM V5 */
 
@@ -1076,6 +1065,42 @@ typedef union {
        arminstr_t      raw;
 } ARMInstr;
 
+/* ARMv6t2 */
+
+#define ARM_MOVW_REG_IMM_COND(p, rd, imm16, cond) ARM_EMIT(p, (((cond) << 28) | (3 << 24) | (0 << 20) | ((((guint32)(imm16)) >> 12) << 16) | ((rd) << 12) | (((guint32)(imm16)) & 0xfff)))
+#define ARM_MOVW_REG_IMM(p, rd, imm16) ARM_MOVW_REG_IMM_COND ((p), (rd), (imm16), ARMCOND_AL)
+
+#define ARM_MOVT_REG_IMM_COND(p, rd, imm16, cond) ARM_EMIT(p, (((cond) << 28) | (3 << 24) | (4 << 20) | ((((guint32)(imm16)) >> 12) << 16) | ((rd) << 12) | (((guint32)(imm16)) & 0xfff)))
+#define ARM_MOVT_REG_IMM(p, rd, imm16) ARM_MOVT_REG_IMM_COND ((p), (rd), (imm16), ARMCOND_AL)
+
+/* MCR */
+#define ARM_DEF_MCR_COND(coproc, opc1, rt, crn, crm, opc2, cond)       \
+       ARM_DEF_COND ((cond)) | ((0xe << 24) | (((opc1) & 0x7) << 21) | (0 << 20) | (((crn) & 0xf) << 16) | (((rt) & 0xf) << 12) | (((coproc) & 0xf) << 8) | (((opc2) & 0x7) << 5) | (1 << 4) | (((crm) & 0xf) << 0))
+
+#define ARM_MCR_COND(p, coproc, opc1, rt, crn, crm, opc2, cond)        \
+       ARM_EMIT(p, ARM_DEF_MCR_COND ((coproc), (opc1), (rt), (crn), (crm), (opc2), (cond)))
+
+#define ARM_MCR(p, coproc, opc1, rt, crn, crm, opc2) \
+       ARM_MCR_COND ((p), (coproc), (opc1), (rt), (crn), (crm), (opc2), ARMCOND_AL)
+
+/* ARMv7VE */
+#define ARM_SDIV_COND(p, rd, rn, rm, cond) ARM_EMIT (p, (((cond) << 28) | (0xe << 23) | (0x1 << 20) | ((rd) << 16) | (0xf << 12) | ((rm) << 8) | (0x0 << 5) | (0x1 << 4) | ((rn) << 0)))
+#define ARM_SDIV(p, rd, rn, rm) ARM_SDIV_COND ((p), (rd), (rn), (rm), ARMCOND_AL)
+
+#define ARM_UDIV_COND(p, rd, rn, rm, cond) ARM_EMIT (p, (((cond) << 28) | (0xe << 23) | (0x3 << 20) | ((rd) << 16) | (0xf << 12) | ((rm) << 8) | (0x0 << 5) | (0x1 << 4) | ((rn) << 0)))
+#define ARM_UDIV(p, rd, rn, rm) ARM_UDIV_COND ((p), (rd), (rn), (rm), ARMCOND_AL)
+
+/* ARMv7 */
+
+typedef enum {
+       ARM_DMB_SY = 0xf,
+} ArmDmbFlags;
+
+#define ARM_DMB(p, option) ARM_EMIT ((p), ((0xf << 28) | (0x57 << 20) | (0xf << 16) | (0xf << 12) | (0x0 << 8) | (0x5 << 4) | ((option) << 0)))
+
+#define ARM_LDREX_REG(p, rt, rn) ARM_EMIT ((p), ((ARMCOND_AL << 28) | (0xc << 21) | (0x1 << 20) | ((rn) << 16) | ((rt) << 12)) | (0xf << 8) | (0x9 << 4) | 0xf << 0)
+
+#define ARM_STREX_REG(p, rd, rt, rn) ARM_EMIT ((p), ((ARMCOND_AL << 28) | (0xc << 21) | (0x0 << 20) | ((rn) << 16) | ((rd) << 12)) | (0xf << 8) | (0x9 << 4) | ((rt) << 0))
 
 #ifdef __cplusplus
 }