diff options
author | Mike Pall <mike> | 2009-12-08 19:46:35 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2009-12-08 19:46:35 +0100 |
commit | 55b16959717084884fd4a0cbae6d19e3786c20c7 (patch) | |
tree | c8a07a43c13679751ed25a9d06796e9e7b2134a6 /src/lj_target_x86.h | |
download | luajit-2.0.0-beta1.tar.gz luajit-2.0.0-beta1.tar.bz2 luajit-2.0.0-beta1.zip |
RELEASE LuaJIT-2.0.0-beta1v2.0.0-beta1
Diffstat (limited to 'src/lj_target_x86.h')
-rw-r--r-- | src/lj_target_x86.h | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/src/lj_target_x86.h b/src/lj_target_x86.h new file mode 100644 index 00000000..3ee4fa00 --- /dev/null +++ b/src/lj_target_x86.h | |||
@@ -0,0 +1,257 @@ | |||
1 | /* | ||
2 | ** Definitions for x86 and x64 CPUs. | ||
3 | ** Copyright (C) 2005-2009 Mike Pall. See Copyright Notice in luajit.h | ||
4 | */ | ||
5 | |||
6 | #ifndef _LJ_TARGET_X86_H | ||
7 | #define _LJ_TARGET_X86_H | ||
8 | |||
9 | /* -- Registers IDs ------------------------------------------------------- */ | ||
10 | |||
11 | #if LJ_64 | ||
12 | #define GPRDEF(_) \ | ||
13 | _(EAX) _(ECX) _(EDX) _(EBX) _(ESP) _(EBP) _(ESI) _(EDI) \ | ||
14 | _(R8D) _(R9D) _(R10D) _(R11D) _(R12D) _(R13D) _(R14D) _(R15D) | ||
15 | #define FPRDEF(_) \ | ||
16 | _(XMM0) _(XMM1) _(XMM2) _(XMM3) _(XMM4) _(XMM5) _(XMM6) _(XMM7) \ | ||
17 | _(XMM8) _(XMM9) _(XMM10) _(XMM11) _(XMM12) _(XMM13) _(XMM14) _(XMM15) | ||
18 | #else | ||
19 | #define GPRDEF(_) \ | ||
20 | _(EAX) _(ECX) _(EDX) _(EBX) _(ESP) _(EBP) _(ESI) _(EDI) | ||
21 | #define FPRDEF(_) \ | ||
22 | _(XMM0) _(XMM1) _(XMM2) _(XMM3) _(XMM4) _(XMM5) _(XMM6) _(XMM7) | ||
23 | #endif | ||
24 | |||
25 | #define RIDENUM(name) RID_##name, | ||
26 | |||
27 | enum { | ||
28 | GPRDEF(RIDENUM) /* General-purpose registers (GPRs). */ | ||
29 | FPRDEF(RIDENUM) /* Floating-point registers (FPRs). */ | ||
30 | RID_MAX, | ||
31 | RID_MRM = RID_MAX, /* Pseudo-id for ModRM operand. */ | ||
32 | |||
33 | /* Calling conventions. */ | ||
34 | RID_RET = RID_EAX, | ||
35 | |||
36 | /* These definitions must match with the *.dasc file(s): */ | ||
37 | RID_BASE = RID_EDX, /* Interpreter BASE. */ | ||
38 | RID_PC = RID_ESI, /* Interpreter PC. */ | ||
39 | RID_DISPATCH = RID_EBX, /* Interpreter DISPATCH table. */ | ||
40 | |||
41 | /* Register ranges [min, max) and number of registers. */ | ||
42 | RID_MIN_GPR = RID_EAX, | ||
43 | RID_MIN_FPR = RID_XMM0, | ||
44 | RID_MAX_GPR = RID_MIN_FPR, | ||
45 | RID_MAX_FPR = RID_MAX, | ||
46 | RID_NUM_GPR = RID_MAX_GPR - RID_MIN_GPR, | ||
47 | RID_NUM_FPR = RID_MAX_FPR - RID_MIN_FPR, | ||
48 | }; | ||
49 | |||
50 | /* -- Register sets ------------------------------------------------------- */ | ||
51 | |||
52 | /* Make use of all registers, except the stack pointer. */ | ||
53 | #define RSET_GPR (RSET_RANGE(RID_MIN_GPR, RID_MAX_GPR)-RID2RSET(RID_ESP)) | ||
54 | #define RSET_FPR (RSET_RANGE(RID_MIN_FPR, RID_MAX_FPR)) | ||
55 | #define RSET_ALL (RSET_GPR|RSET_FPR) | ||
56 | |||
57 | #if LJ_64 | ||
58 | /* Note: this requires the use of FORCE_REX! */ | ||
59 | #define RSET_GPR8 RSET_GPR | ||
60 | #else | ||
61 | #define RSET_GPR8 (RSET_RANGE(RID_EAX, RID_EBX+1)) | ||
62 | #endif | ||
63 | |||
64 | /* ABI-specific register sets. */ | ||
65 | #define RSET_ACD (RID2RSET(RID_EAX)|RID2RSET(RID_ECX)|RID2RSET(RID_EDX)) | ||
66 | #if LJ_64 | ||
67 | #ifdef _WIN64 | ||
68 | /* Windows x64 ABI. */ | ||
69 | #define RSET_SCRATCH \ | ||
70 | (RSET_ACD|RSET_RANGE(RID_R8D, RID_R11D+1)|RSET_RANGE(RID_XMM0, RID_XMM5+1)) | ||
71 | #else | ||
72 | /* The rest of the civilized x64 world has a common ABI. */ | ||
73 | #define RSET_SCRATCH \ | ||
74 | (RSET_ACD|RSET_RANGE(RID_ESI, RID_R11D+1)|RSET_FPR) | ||
75 | #endif | ||
76 | #else | ||
77 | /* Common x86 ABI. */ | ||
78 | #define RSET_SCRATCH (RSET_ACD|RSET_FPR) | ||
79 | #endif | ||
80 | |||
81 | #if LJ_64 | ||
82 | /* Prefer the low 8 regs of each type to reduce REX prefixes. */ | ||
83 | #undef rset_picktop | ||
84 | #define rset_picktop(rs) (lj_fls(lj_bswap(rs)) ^ 0x18) | ||
85 | #endif | ||
86 | |||
87 | /* -- Spill slots --------------------------------------------------------- */ | ||
88 | |||
89 | /* Stack layout for the compiled machine code (after stack adjustment). */ | ||
90 | enum { | ||
91 | SPS_TEMP1, /* Temps (3*dword) for calls and asm_x87load. */ | ||
92 | SPS_TEMP2, | ||
93 | SPS_TEMP3, | ||
94 | SPS_FIRST, /* First spill slot for general use. */ | ||
95 | |||
96 | /* This definition must match with the *.dasc file(s). */ | ||
97 | SPS_FIXED = 6 /* Available fixed spill slots in interpreter frame. */ | ||
98 | }; | ||
99 | |||
100 | /* Spill slots are 32 bit wide. An even/odd pair is used for FPRs. */ | ||
101 | #define sps_scale(slot) (4 * (int32_t)(slot)) | ||
102 | #define sps_adjust(as) (sps_scale((as->evenspill-SPS_FIXED+3)&~3)) | ||
103 | |||
104 | /* -- Exit state ---------------------------------------------------------- */ | ||
105 | |||
106 | /* This definition must match with the *.dasc file(s). */ | ||
107 | typedef struct { | ||
108 | lua_Number fpr[RID_NUM_FPR]; /* Floating-point registers. */ | ||
109 | int32_t gpr[RID_NUM_GPR]; /* General-purpose registers. */ | ||
110 | int32_t spill[256]; /* Spill slots. */ | ||
111 | } ExitState; | ||
112 | |||
113 | /* -- x86 ModRM operand encoding ------------------------------------------ */ | ||
114 | |||
115 | typedef enum { | ||
116 | XM_OFS0 = 0x00, XM_OFS8 = 0x40, XM_OFS32 = 0x80, XM_REG = 0xc0, | ||
117 | XM_SCALE1 = 0x00, XM_SCALE2 = 0x40, XM_SCALE4 = 0x80, XM_SCALE8 = 0xc0, | ||
118 | XM_MASK = 0xc0 | ||
119 | } x86Mode; | ||
120 | |||
121 | /* Structure to hold variable ModRM operand. */ | ||
122 | typedef struct { | ||
123 | int32_t ofs; /* Offset. */ | ||
124 | uint8_t base; /* Base register or RID_NONE. */ | ||
125 | uint8_t idx; /* Index register or RID_NONE. */ | ||
126 | uint8_t scale; /* Index scale (XM_SCALE1 .. XM_SCALE8). */ | ||
127 | } x86ModRM; | ||
128 | |||
129 | /* -- Opcodes ------------------------------------------------------------- */ | ||
130 | |||
131 | /* Macros to construct variable-length x86 opcodes. -(len+1) is in LSB. */ | ||
132 | #define XO_(o) ((uint32_t)(0x0000fe + (0x##o<<24))) | ||
133 | #define XO_FPU(a,b) ((uint32_t)(0x00fd + (0x##a<<16)+(0x##b<<24))) | ||
134 | #define XO_0f(o) ((uint32_t)(0x0f00fd + (0x##o<<24))) | ||
135 | #define XO_66(o) ((uint32_t)(0x6600fd + (0x##o<<24))) | ||
136 | #define XO_660f(o) ((uint32_t)(0x0f66fc + (0x##o<<24))) | ||
137 | #define XO_f20f(o) ((uint32_t)(0x0ff2fc + (0x##o<<24))) | ||
138 | #define XO_f30f(o) ((uint32_t)(0x0ff3fc + (0x##o<<24))) | ||
139 | |||
140 | /* This list of x86 opcodes is not intended to be complete. Opcodes are only | ||
141 | ** included when needed. Take a look at DynASM or jit.dis_x86 to see the | ||
142 | ** whole mess. | ||
143 | */ | ||
144 | typedef enum { | ||
145 | /* Fixed length opcodes. XI_* prefix. */ | ||
146 | XI_NOP = 0x90, | ||
147 | XI_CALL = 0xe8, | ||
148 | XI_JMP = 0xe9, | ||
149 | XI_JMPs = 0xeb, | ||
150 | XI_JCCs = 0x70, /* Really 7x. */ | ||
151 | XI_JCCn = 0x80, /* Really 0f8x. */ | ||
152 | XI_LEA = 0x8d, | ||
153 | XI_MOVri = 0xb8, /* Really b8+r. */ | ||
154 | XI_ARITHib = 0x80, | ||
155 | XI_ARITHi = 0x81, | ||
156 | XI_ARITHi8 = 0x83, | ||
157 | XI_PUSHi8 = 0x6a, | ||
158 | XI_TEST = 0x85, | ||
159 | XI_MOVmi = 0xc7, | ||
160 | XI_BSWAP = 0xc8, /* Really 0fc8+r. */ | ||
161 | |||
162 | /* Note: little-endian byte-order! */ | ||
163 | XI_FLDZ = 0xeed9, | ||
164 | XI_FLD1 = 0xe8d9, | ||
165 | XI_FLDLG2 = 0xecd9, | ||
166 | XI_FLDLN2 = 0xedd9, | ||
167 | XI_FPOP = 0xd8dd, /* Really fstp st0. */ | ||
168 | XI_FPOP1 = 0xd9dd, /* Really fstp st1. */ | ||
169 | XI_FRNDINT = 0xfcd9, | ||
170 | XI_FSIN = 0xfed9, | ||
171 | XI_FCOS = 0xffd9, | ||
172 | XI_FPTAN = 0xf2d9, | ||
173 | XI_FPATAN = 0xf3d9, | ||
174 | XI_FSCALE = 0xfdd9, | ||
175 | XI_FYL2X = 0xf1d9, | ||
176 | |||
177 | /* Variable-length opcodes. XO_* prefix. */ | ||
178 | XO_MOV = XO_(8b), | ||
179 | XO_MOVto = XO_(89), | ||
180 | XO_MOVtow = XO_66(89), | ||
181 | XO_MOVtob = XO_(88), | ||
182 | XO_MOVmi = XO_(c7), | ||
183 | XO_MOVmib = XO_(c6), | ||
184 | XO_LEA = XO_(8d), | ||
185 | XO_ARITHib = XO_(80), | ||
186 | XO_ARITHi = XO_(81), | ||
187 | XO_ARITHi8 = XO_(83), | ||
188 | XO_SHIFTi = XO_(c1), | ||
189 | XO_SHIFT1 = XO_(d1), | ||
190 | XO_SHIFTcl = XO_(d3), | ||
191 | XO_IMULi8 = XO_(6b), | ||
192 | XO_CMP = XO_(3b), | ||
193 | XO_TEST = XO_(85), | ||
194 | XO_GROUP3b = XO_(f6), | ||
195 | XO_GROUP3 = XO_(f7), | ||
196 | XO_MOVZXb = XO_0f(b6), | ||
197 | XO_MOVZXw = XO_0f(b7), | ||
198 | XO_MOVSXb = XO_0f(be), | ||
199 | XO_MOVSXw = XO_0f(bf), | ||
200 | |||
201 | XO_MOVSD = XO_f20f(10), | ||
202 | XO_MOVSDto = XO_f20f(11), | ||
203 | XO_MOVLPD = XO_660f(12), | ||
204 | XO_MOVAPS = XO_0f(28), | ||
205 | XO_XORPS = XO_0f(57), | ||
206 | XO_ANDPS = XO_0f(54), | ||
207 | XO_ADDSD = XO_f20f(58), | ||
208 | XO_SUBSD = XO_f20f(5c), | ||
209 | XO_MULSD = XO_f20f(59), | ||
210 | XO_DIVSD = XO_f20f(5e), | ||
211 | XO_SQRTSD = XO_f20f(51), | ||
212 | XO_MINSD = XO_f20f(5d), | ||
213 | XO_MAXSD = XO_f20f(5f), | ||
214 | XO_ROUNDSD = 0x0b3a0ffc, /* Really 66 0f 3a 0b. See asm_fpmath. */ | ||
215 | XO_UCOMISD = XO_660f(2e), | ||
216 | XO_CVTSI2SD = XO_f20f(2a), | ||
217 | XO_CVTSD2SI = XO_f20f(2d), | ||
218 | XO_CVTTSD2SI= XO_f20f(2c), | ||
219 | XO_MOVDto = XO_660f(7e), | ||
220 | |||
221 | XO_FLDq = XO_(dd), XOg_FLDq = 0, | ||
222 | XO_FILDd = XO_(db), XOg_FILDd = 0, | ||
223 | XO_FSTPq = XO_(dd), XOg_FSTPq = 3, | ||
224 | XO_FISTPq = XO_(df), XOg_FISTPq = 7, | ||
225 | } x86Op; | ||
226 | |||
227 | /* x86 opcode groups. */ | ||
228 | typedef uint32_t x86Group; | ||
229 | |||
230 | #define XG_(i8, i, g) ((x86Group)(((i8) << 16) + ((i) << 8) + (g))) | ||
231 | #define XG_ARITHi(g) XG_(XI_ARITHi8, XI_ARITHi, g) | ||
232 | |||
233 | #define XO_ARITH(a) ((x86Op)(0x030000fe + ((a)<<27))) | ||
234 | |||
235 | typedef enum { | ||
236 | XOg_ADD, XOg_OR, XOg_ADC, XOg_SBB, XOg_AND, XOg_SUB, XOg_XOR, XOg_CMP | ||
237 | } x86Arith; | ||
238 | |||
239 | typedef enum { | ||
240 | XOg_ROL, XOg_ROR, XOg_RCL, XOg_RCR, XOg_SHL, XOg_SHR, XOg_SAL, XOg_SAR | ||
241 | } x86Shift; | ||
242 | |||
243 | typedef enum { | ||
244 | XOg_TEST, XOg_TEST_, XOg_NOT, XOg_NEG, XOg_MUL, XOg_IMUL, XOg_DIV, XOg_IDIV | ||
245 | } x86Group3; | ||
246 | |||
247 | /* x86 condition codes. */ | ||
248 | typedef enum { | ||
249 | CC_O, CC_NO, CC_B, CC_NB, CC_E, CC_NE, CC_BE, CC_NBE, | ||
250 | CC_S, CC_NS, CC_P, CC_NP, CC_L, CC_NL, CC_LE, CC_NLE, | ||
251 | CC_C = CC_B, CC_NAE = CC_C, CC_NC = CC_NB, CC_AE = CC_NB, | ||
252 | CC_Z = CC_E, CC_NZ = CC_NE, CC_NA = CC_BE, CC_A = CC_NBE, | ||
253 | CC_PE = CC_P, CC_PO = CC_NP, CC_NGE = CC_L, CC_GE = CC_NL, | ||
254 | CC_NG = CC_LE, CC_G = CC_NLE | ||
255 | } x86CC; | ||
256 | |||
257 | #endif | ||