Method prologue and epilogues, add missing x86 functionality.
Enables compiling and running a number of JNI internal managed code
methods on the host.
Change-Id: I56fceb813d0cb24637bc784ba57f2d1d16911d48
diff --git a/src/compiler/codegen/x86/X86LIR.h b/src/compiler/codegen/x86/X86LIR.h
index 31449e0..65f07cf 100644
--- a/src/compiler/codegen/x86/X86LIR.h
+++ b/src/compiler/codegen/x86/X86LIR.h
@@ -118,6 +118,7 @@
#define LOWREG(x) ((x & 0x1f) == x)
#define DOUBLEREG(x) ((x & FP_DOUBLE) == FP_DOUBLE)
#define SINGLEREG(x) (FPREG(x) && !DOUBLEREG(x))
+
/*
* Note: the low register of a floating point pair is sufficient to
* create the name of a double, but require both names to be passed to
@@ -133,10 +134,9 @@
/* non-existant physical register */
#define rNone (-1)
-/* RegisterLocation templates return values (r0, or r0/r1) */
-#define LOC_C_RETURN {kLocPhysReg, 0, 0, 0, 0, 0, 1, rAX, INVALID_REG,\
- INVALID_SREG}
-#define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 1, rAX, rDX, INVALID_SREG}
+/* RegisterLocation templates return values (rAX, or rAX/rDX) */
+#define LOC_C_RETURN {kLocPhysReg, 0, 0, 0, 0, 0, 1, rAX, INVALID_REG, INVALID_SREG}
+#define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 1, rAX, rDX, INVALID_SREG}
enum ResourceEncodingPos {
kGPReg0 = 0,
@@ -177,15 +177,16 @@
enum NativeRegisterPool {
r0 = 0,
- rAX = r0,
+ rAX = r0,
r1 = 1,
- rCX = r1,
+ rCX = r1,
r2 = 2,
rDX = r2,
r3 = 3,
rBX = r3,
r4sp = 4,
- rSP =r4sp,
+ rSP = r4sp,
+ r4sib_no_index = r4sp,
r5 = 5,
rBP = r5,
r6 = 6,
@@ -230,6 +231,53 @@
#define isPseudoOpcode(opCode) ((int)(opCode) < 0)
+/* X86 condition encodings */
+enum X86ConditionCode {
+ kX86CondO = 0x0, // overflow
+ kX86CondNo = 0x1, // not overflow
+
+ kX86CondB = 0x2, // below
+ kX86CondNae = kX86CondB, // not-above-equal
+ kX86CondC = kX86CondB, // carry
+
+ kX86CondNb = 0x3, // not-below
+ kX86CondAe = kX86CondNb, // above-equal
+ kX86CondNc = kX86CondNb, // not-carry
+
+ kX86CondZ = 0x4, // zero
+ kX86CondEq = kX86CondZ, // equal
+
+ kX86CondNz = 0x5, // not-zero
+ kX86CondNe = kX86CondNz, // not-equal
+
+ kX86CondBe = 0x6, // below-equal
+ kX86CondNa = kX86CondBe, // not-above
+
+ kX86CondNbe = 0x7, // not-below-equal
+ kX86CondA = kX86CondNbe,// above
+
+ kX86CondS = 0x8, // sign
+ kX86CondNs = 0x9, // not-sign
+
+ kX86CondP = 0xA, // 8-bit parity even
+ kX86CondPE = kX86CondP,
+
+ kX86CondNp = 0xB, // 8-bit parity odd
+ kX86CondPo = kX86CondNp,
+
+ kX86CondL = 0xC, // less-than
+ kX86CondNge = kX86CondL, // not-greater-equal
+
+ kX86CondNl = 0xD, // not-less-than
+ kX86CondGe = kX86CondL, // not-greater-equal
+
+ kX86CondLe = 0xE, // less-than-equal
+ kX86CondNg = kX86CondLe, // not-greater
+
+ kX86CondNle = 0xF, // not-less-than
+ kX86CondG = kX86CondNle,// greater
+};
+
/*
* The following enum defines the list of supported X86 instructions by the
* assembler. Their corresponding EncodingMap positions will be defined in
@@ -253,78 +301,182 @@
kPseudoNormalBlockLabel = -1,
kX86First,
kX8632BitData = kX86First, /* data [31..0] */
+ kX86Bkpt,
+ kX86Nop,
// Define groups of binary operations
- // RI - Register Immediate - opcode reg, #immediate
- // - lir operands - 0: reg, 1: immediate
- // MI - Memory Immediate - opcode [base + disp], #immediate
- // - lir operands - 0: base, 1: disp, 2: immediate
- // AI - Array Immediate - opcode [base + index * scale + disp], #immediate
- // - lir operands - 0: base, 1: index, 2: scale, 3: disp 4: immediate
+ // MR - Memory Register - opcode [base + disp], reg
+ // - lir operands - 0: base, 1: disp, 2: reg
+ // AR - Array Register - opcode [base + index * scale + disp], reg
+ // - lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: reg
+ // TR - Thread Register - opcode fs:[disp], reg - where fs: is equal to Thread::Current()
+ // - lir operands - 0: disp, 1: reg
// RR - Register Register - opcode reg1, reg2
// - lir operands - 0: reg1, 1: reg2
// RM - Register Memory - opcode reg, [base + disp]
// - lir operands - 0: reg, 1: base, 2: disp
// RA - Register Array - opcode reg, [base + index * scale + disp]
// - lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: disp
- // MR - Memory Register - opcode [base + disp], reg
- // - lir operands - 0: base, 1: disp, 2: reg
- // AR - Array Register - opcode [base + index * scale + disp], reg
- // - lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: reg
+ // RT - Register Thread - opcode reg, fs:[disp] - where fs: is equal to Thread::Current()
+ // - lir operands - 0: reg, 1: disp
+ // RI - Register Immediate - opcode reg, #immediate
+ // - lir operands - 0: reg, 1: immediate
+ // MI - Memory Immediate - opcode [base + disp], #immediate
+ // - lir operands - 0: base, 1: disp, 2: immediate
+ // AI - Array Immediate - opcode [base + index * scale + disp], #immediate
+ // - lir operands - 0: base, 1: index, 2: scale, 3: disp 4: immediate
+ // TI - Thread Register - opcode fs:[disp], imm - where fs: is equal to Thread::Current()
+ // - lir operands - 0: disp, 1: imm
#define BinaryOpCode(opcode) \
- opcode ## RI, opcode ## MI, opcode ##AI, \
- opcode ## RR, opcode ## RM, opcode ##RA, \
- opcode ## MR, opcode ## AR
- BinaryOpCode(kOpAdd),
- BinaryOpCode(kOpOr),
- BinaryOpCode(kOpAdc),
- BinaryOpCode(kOpSbb),
- BinaryOpCode(kOpAnd),
- BinaryOpCode(kOpSub),
- BinaryOpCode(kOpXor),
- BinaryOpCode(kOpCmp),
- BinaryOpCode(kOpMov),
+ opcode ## 8MR, opcode ## 8AR, opcode ## 8TR, \
+ opcode ## 8RR, opcode ## 8RM, opcode ## 8RA, opcode ## 8RT, \
+ opcode ## 8RI, opcode ## 8MI, opcode ## 8AI, opcode ## 8TI, \
+ opcode ## 16MR, opcode ## 16AR, opcode ## 16TR, \
+ opcode ## 16RR, opcode ## 16RM, opcode ## 16RA, opcode ## 16RT, \
+ opcode ## 16RI, opcode ## 16MI, opcode ## 16AI, opcode ## 16TI, \
+ opcode ## 16RI8, opcode ## 16MI8, opcode ## 16AI8, opcode ## 16TI8, \
+ opcode ## 32MR, opcode ## 32AR, opcode ## 32TR, \
+ opcode ## 32RR, opcode ## 32RM, opcode ## 32RA, opcode ## 32RT, \
+ opcode ## 32RI, opcode ## 32MI, opcode ## 32AI, opcode ## 32TI, \
+ opcode ## 32RI8, opcode ## 32MI8, opcode ## 32AI8, opcode ## 32TI8
+ BinaryOpCode(kX86Add),
+ BinaryOpCode(kX86Or),
+ BinaryOpCode(kX86Adc),
+ BinaryOpCode(kX86Sbb),
+ BinaryOpCode(kX86And),
+ BinaryOpCode(kX86Sub),
+ BinaryOpCode(kX86Xor),
+ BinaryOpCode(kX86Cmp),
#undef BinaryOpCode
+ kX86Imul16RRI, kX86Imul16RMI, kX86Imul16RAI,
+ kX86Imul32RRI, kX86Imul32RMI, kX86Imul32RAI,
+ kX86Imul32RRI8, kX86Imul32RMI8, kX86Imul32RAI8,
+ kX86Mov8MR, kX86Mov8AR, kX86Mov8TR,
+ kX86Mov8RR, kX86Mov8RM, kX86Mov8RA, kX86Mov8RT,
+ kX86Mov8RI, kX86Mov8MI, kX86Mov8AI, kX86Mov8TI,
+ kX86Mov16MR, kX86Mov16AR, kX86Mov16TR,
+ kX86Mov16RR, kX86Mov16RM, kX86Mov16RA, kX86Mov16RT,
+ kX86Mov16RI, kX86Mov16MI, kX86Mov16AI, kX86Mov16TI,
+ kX86Mov32MR, kX86Mov32AR, kX86Mov32TR,
+ kX86Mov32RR, kX86Mov32RM, kX86Mov32RA, kX86Mov32RT,
+ kX86Mov32RI, kX86Mov32MI, kX86Mov32AI, kX86Mov32TI,
+ kX86Lea32RA,
+ // RC - Register CL - opcode reg, CL
+ // - lir operands - 0: reg, 1: CL
+ // MC - Memory CL - opcode [base + disp], CL
+ // - lir operands - 0: base, 1: disp, 2: CL
+ // AC - Array CL - opcode [base + index * scale + disp], CL
+ // - lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: CL
+#define BinaryShiftOpCode(opcode) \
+ opcode ## 8RI, opcode ## 8MI, opcode ## 8AI, \
+ opcode ## 8RC, opcode ## 8MC, opcode ## 8AC, \
+ opcode ## 16RI, opcode ## 16MI, opcode ## 16AI, \
+ opcode ## 16RC, opcode ## 16MC, opcode ## 16AC, \
+ opcode ## 32RI, opcode ## 32MI, opcode ## 32AI, \
+ opcode ## 32RC, opcode ## 32MC, opcode ## 32AC
+ BinaryShiftOpCode(kX86Rol),
+ BinaryShiftOpCode(kX86Ror),
+ BinaryShiftOpCode(kX86Rcl),
+ BinaryShiftOpCode(kX86Rcr),
+ BinaryShiftOpCode(kX86Sal),
+ BinaryShiftOpCode(kX86Shl),
+ BinaryShiftOpCode(kX86Shr),
+ BinaryShiftOpCode(kX86Sar),
+#undef BinaryShiftOpcode
+#define UnaryOpcode(opcode, reg, mem, array) \
+ opcode ## 8 ## reg, opcode ## 8 ## mem, opcode ## 8 ## array, \
+ opcode ## 16 ## reg, opcode ## 16 ## mem, opcode ## 16 ## array, \
+ opcode ## 32 ## reg, opcode ## 32 ## mem, opcode ## 32 ## array
+ UnaryOpcode(kX86Test, RI, MI, AI),
+ UnaryOpcode(kX86Not, R, M, A),
+ UnaryOpcode(kX86Neg, R, M, A),
+ UnaryOpcode(kX86Mul, DaR, DaM, DaA),
+ UnaryOpcode(kX86Imul, DaR, DaM, DaA),
+ UnaryOpcode(kX86Divmod, DaR, DaM, DaA),
+ UnaryOpcode(kX86Idivmod, DaR, DaM, DaA),
+#undef UnaryOpcode
+#define Binary0fOpCode(opcode) \
+ opcode ## RR, opcode ## RM, opcode ## RA
+ Binary0fOpCode(kX86Movsd),
+ kX86MovsdMR,
+ kX86MovsdAR,
+ Binary0fOpCode(kX86Movss),
+ kX86MovssMR,
+ kX86MovssAR,
+ Binary0fOpCode(kX86Cvtsi2sd), // int to double
+ Binary0fOpCode(kX86Cvtsi2ss), // int to float
+ Binary0fOpCode(kX86Cvttsd2si), // truncating double to int
+ Binary0fOpCode(kX86Cvttss2si), // truncating float to int
+ Binary0fOpCode(kX86Cvtsd2si), // rounding double to int
+ Binary0fOpCode(kX86Cvtss2si), // rounding float to int
+ Binary0fOpCode(kX86Ucomisd), // unordered double compare
+ Binary0fOpCode(kX86Ucomiss), // unordered float compare
+ Binary0fOpCode(kX86Comisd), // double compare
+ Binary0fOpCode(kX86Comiss), // float compare
+ Binary0fOpCode(kX86Addsd), // double add
+ Binary0fOpCode(kX86Addss), // float add
+ Binary0fOpCode(kX86Mulsd), // double multiply
+ Binary0fOpCode(kX86Mulss), // float multiply
+ Binary0fOpCode(kX86Cvtss2sd), // float to double
+ Binary0fOpCode(kX86Cvtsd2ss), // double to float
+ Binary0fOpCode(kX86Subsd), // double subtract
+ Binary0fOpCode(kX86Subss), // float subtract
+ Binary0fOpCode(kX86Divsd), // double subtract
+ Binary0fOpCode(kX86Divss), // float subtract
+ Binary0fOpCode(kX86Movdxr), // move into xmm from gpr
+ Binary0fOpCode(kX86Movdrx), // move into reg from xmm
+ kX86Set8R, kX86Set8M, kX86Set8A,// set byte depending on condition operand
+ Binary0fOpCode(kX86Imul16), // 16bit multiply
+ Binary0fOpCode(kX86Imul32), // 32bit multiply
+ Binary0fOpCode(kX86Movzx8), // zero-extend 8-bit value
+ Binary0fOpCode(kX86Movzx16), // zero-extend 16-bit value
+ Binary0fOpCode(kX86Movsx8), // sign-extend 8-bit value
+ Binary0fOpCode(kX86Movsx16), // sign-extend 16-bit value
+#undef Binary0fOpCode
+ kX86Jcc, // jCC rel; lir operands - 0: rel, 1: CC, target assigned
+ kX86Jmp, // jmp rel; lir operands - 0: rel, target assigned
+ kX86CallR, // call reg; lir operands - 0: reg
+ kX86CallM, // call [base + disp]; lir operands - 0: base, 1: disp
+ kX86CallA, // call [base + index * scale + disp]
+ // lir operands - 0: base, 1: index, 2: scale, 3: disp
+ kX86Ret, // ret; no lir operands
kX86Last
};
/* Instruction assembly fieldLoc kind */
enum X86EncodingKind {
- kData, // Special case for raw data
- kRegImm, kMemImm, kArrayImm, // RI, MI, AI instruction kinds
- kRegReg, kRegMem, kRegArray, // RR, RM, RA instruction kinds
- kMemReg, kArrayReg, // MR and AR instruction kinds
+ kData, // Special case for raw data.
+ kNop, // Special case for variable length nop.
+ kNullary, // Opcode that takes no arguments.
+ kReg, kMem, kArray, // R, M and A instruction kinds.
+ kMemReg, kArrayReg, kThreadReg, // MR, AR and TR instruction kinds.
+ kRegReg, kRegMem, kRegArray, kRegThread, // RR, RM, RA and RT instruction kinds.
+ kRegImm, kMemImm, kArrayImm, kThreadImm, // RI, MI, AI and TI instruction kinds.
+ kRegRegImm, kRegMemImm, kRegArrayImm, // RRI, RMI and RAI instruction kinds.
+ kMovRegImm, // Shorter form move RI.
+ kShiftRegImm, kShiftMemImm, kShiftArrayImm, // Shift opcode with immediate.
+ kShiftRegCl, kShiftMemCl, kShiftArrayCl, // Shift opcode with register CL.
+ kRegRegReg, kRegRegMem, kRegRegArray, // RRR, RRM, RRA instruction kinds.
+ kRegCond, kMemCond, kArrayCond, // R, M, A instruction kinds following by a condition.
+ kJmp, kJcc, kCall, // Branch instruction kinds.
kUnimplemented // Encoding used when an instruction isn't yet implemented.
};
-/* A form of instruction with an opcode byte and a secondary opcode within the modrm byte */
-struct OpcodeModRMOpcode {
- uint8_t opcode; // 1 byte opcode
- uint8_t modrm_opcode; // 3 bit opcode that gets encoded in the register bits of the modrm byte
-};
-
/* Struct used to define the EncodingMap positions for each X86 opcode */
struct X86EncodingMap {
X86OpCode opcode; // e.g. kOpAddRI
X86EncodingKind kind; // Used to discriminate in the union below
int flags;
- union {
- struct {
- uint8_t rax8_i8_opcode;
- uint8_t rax32_i32_opcode;
- OpcodeModRMOpcode rm8_i8_opcode;
- OpcodeModRMOpcode rm32_i32_opcode;
- OpcodeModRMOpcode rm32_i8_opcode;
- } RegMem_Immediate; // kind: kRegImm, kMemImm, kArrayImm
- struct {
- uint8_t r8_rm8_opcode;
- uint8_t r32_rm32_opcode;
- } Reg_RegMem; // kind: kRegReg, kRegMem, kRegArray
- struct {
- uint8_t rm8_r8_opcode;
- uint8_t rm32_r32_opcode;
- } RegMem_Reg; // kind: kMemReg, kArrayReg
- // This is a convenience for static initialization where the kind doesn't require opcode data.
- int unused; // kind: kData, kUnimplemented
+ struct {
+ uint8_t prefix1; // non-zero => a prefix byte
+ uint8_t prefix2; // non-zero => a second prefix byte
+ uint8_t opcode; // 1 byte opcode
+ uint8_t extra_opcode1; // possible extra opcode byte
+ uint8_t extra_opcode2; // possible second extra opcode byte
+ // 3bit opcode that gets encoded in the register bits of the modrm byte, use determined by the
+ // encoding kind
+ uint8_t modrm_opcode;
+ uint8_t ax_opcode; // non-zero => shorter encoding for AX as a destination
+ uint8_t immediate_bytes; // number of bytes of immediate
} skeleton;
const char *name;
const char* fmt;
@@ -356,6 +508,8 @@
kIsBinaryOp,
kIsTertiaryOp,
kIsQuadOp,
+ kIsQuinOp,
+ kIsSextupleOp,
kIsIT,
kSetsCCodes,
kUsesCCodes,
@@ -387,10 +541,12 @@
#define IS_BINARY_OP (1 << kIsBinaryOp)
#define IS_TERTIARY_OP (1 << kIsTertiaryOp)
#define IS_QUAD_OP (1 << kIsQuadOp)
+#define IS_QUIN_OP (1 << kIsQuinOp)
+#define IS_SEXTUPLE_OP (1 << kIsSextupleOp)
#define IS_IT (1 << kIsIT)
#define SETS_CCODES (1 << kSetsCCodes)
#define USES_CCODES (1 << kUsesCCodes)
-#define NEEDS_FIXUP (1 << kPCRelFixup)
+#define NEEDS_FIXUP (1 << kPCRelFixup)
/* attributes, included for compatibility */
#define REG_DEF_FPCS_LIST0 (0)
@@ -416,8 +572,15 @@
kMaxHoistDistance,
};
+/* Offsets of high and low halves of a 64bit value */
+#define LOWORD_OFFSET 0
+#define HIWORD_OFFSET 4
+
+/* Segment override instruction prefix used for quick TLS access to Thread::Current() */
+#define THREAD_PREFIX 0x64
#define IS_SIMM8(v) ((-128 <= (v)) && ((v) <= 127))
+#define IS_SIMM16(v) ((-32768 <= (v)) && ((v) <= 32767))
} // namespace art