1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is [Open Source Virtual Machine].
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 2004-2007
21 * the Initial Developer. All Rights Reserved.
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
41 #ifndef __nanojit_Nativei386__
42 #define __nanojit_Nativei386__
46 #include "../vprof/vprof.h"
47 #define count_instr() _nvprof("x86",1)
48 #define count_ret() _nvprof("x86-ret",1); count_instr();
49 #define count_push() _nvprof("x86-push",1); count_instr();
50 #define count_pop() _nvprof("x86-pop",1); count_instr();
51 #define count_st() _nvprof("x86-st",1); count_instr();
52 #define count_stq() _nvprof("x86-stq",1); count_instr();
53 #define count_ld() _nvprof("x86-ld",1); count_instr();
54 #define count_ldq() _nvprof("x86-ldq",1); count_instr();
55 #define count_call() _nvprof("x86-call",1); count_instr();
56 #define count_calli() _nvprof("x86-calli",1); count_instr();
57 #define count_prolog() _nvprof("x86-prolog",1); count_instr();
58 #define count_alu() _nvprof("x86-alu",1); count_instr();
59 #define count_mov() _nvprof("x86-mov",1); count_instr();
60 #define count_fpu() _nvprof("x86-fpu",1); count_instr();
61 #define count_jmp() _nvprof("x86-jmp",1); count_instr();
62 #define count_jcc() _nvprof("x86-jcc",1); count_instr();
63 #define count_fpuld() _nvprof("x86-ldq",1); _nvprof("x86-fpu",1); count_instr()
64 #define count_aluld() _nvprof("x86-ld",1); _nvprof("x86-alu",1); count_instr()
65 #define count_alust() _nvprof("x86-ld",1); _nvprof("x86-alu",1); _nvprof("x86-st",1); count_instr()
66 #define count_pushld() _nvprof("x86-ld",1); _nvprof("x86-push",1); count_instr()
67 #define count_imt() _nvprof("x86-imt",1) count_instr()
79 #define count_prolog()
88 #define count_pushld()
94 const int NJ_MAX_REGISTERS
= 24; // gpregs, x87 regs, xmm regs
96 #define NJ_MAX_STACK_ENTRY 4096
97 #define NJ_MAX_PARAMETERS 1
99 #define NJ_USES_QUAD_CONSTANTS 1
101 #define NJ_JTBL_SUPPORTED 1
102 #define NJ_EXPANDED_LOADSTORE_SUPPORTED 1
103 #define NJ_F2I_SUPPORTED 1
104 #define NJ_SOFTFLOAT_SUPPORTED 0
106 // Preserve a 16-byte stack alignment, to support the use of
107 // SSE instructions like MOVDQA (if not by Tamarin itself,
108 // then by the C functions it calls).
109 const int NJ_ALIGN_STACK
= 16;
111 const int32_t LARGEST_UNDERRUN_PROT
= 32; // largest value passed to underrunProtect
113 typedef uint8_t NIns
;
115 // Bytes of icache to flush after patch
116 const size_t LARGEST_BRANCH_PATCH
= 16 * sizeof(NIns
);
118 // These are used as register numbers in various parts of the code
121 // general purpose 32bit regs
122 EAX
= 0, // return value, scratch
123 ECX
= 1, // this/arg0, scratch
124 EDX
= 2, // arg1, return-msw, scratch
126 ESP
= 4, // stack pointer
127 EBP
= 5, // frame pointer
131 SP
= ESP
, // alias SP to ESP for convenience
132 FP
= EBP
, // alias FP to EBP for convenience
134 // SSE regs come before X87 so we prefer them
149 deprecated_UnknownReg
= 17, // XXX: remove eventually, see bug 538924
154 typedef int RegisterMask
;
156 static const int NumSavedRegs
= 3;
157 static const RegisterMask SavedRegs
= 1<<EBX
| 1<<EDI
| 1<<ESI
;
158 static const RegisterMask GpRegs
= SavedRegs
| 1<<EAX
| 1<<ECX
| 1<<EDX
;
159 static const RegisterMask XmmRegs
= 1<<XMM0
|1<<XMM1
|1<<XMM2
|1<<XMM3
|1<<XMM4
|1<<XMM5
|1<<XMM6
|1<<XMM7
;
160 static const RegisterMask x87Regs
= 1<<FST0
;
161 static const RegisterMask FpRegs
= x87Regs
| XmmRegs
;
162 static const RegisterMask ScratchRegs
= 1<<EAX
| 1<<ECX
| 1<<EDX
| FpRegs
;
164 static const RegisterMask AllowableFlagRegs
= 1<<EAX
|1<<ECX
| 1<<EDX
| 1<<EBX
;
166 #define _rmask_(r) (1<<(r))
167 #define _is_xmm_reg_(r) ((_rmask_(r)&XmmRegs)!=0)
168 #define _is_x87_reg_(r) ((_rmask_(r)&x87Regs)!=0)
169 #define _is_fp_reg_(r) ((_rmask_(r)&FpRegs)!=0)
170 #define _is_gp_reg_(r) ((_rmask_(r)&GpRegs)!=0)
172 verbose_only( extern const char* regNames
[]; )
174 #define DECLARE_PLATFORM_STATS()
176 #define DECLARE_PLATFORM_REGALLOC()
182 #define DECLARE_PLATFORM_ASSEMBLER() \
183 const static Register argRegs[2], retRegs[2]; \
184 int32_t max_stk_args;\
185 void nativePageReset();\
186 void nativePageSetup();\
187 void underrunProtect(int);\
188 void asm_immi(Register r, int32_t val, bool canClobberCCs);\
189 void asm_stkarg(LInsp p, int32_t& stkd);\
190 void asm_farg(LInsp, int32_t& stkd);\
191 void asm_arg(ArgType ty, LInsp p, Register r, int32_t& stkd);\
192 void asm_pusharg(LInsp);\
193 void asm_fcmp(LIns *cond);\
194 NIns* asm_fbranch(bool, LIns*, NIns*);\
195 void asm_cmp(LIns *cond); \
196 void asm_div_mod(LIns *cond); \
197 void asm_load(int d, Register r); \
198 void asm_immf(Register r, uint64_t q, double d, bool canClobberCCs); \
199 void IMM8(int32_t i) { \
201 *((int8_t*)_nIns) = (int8_t)(i); \
203 void IMM16(int32_t i) { \
205 *((int16_t*)_nIns) = (int16_t)(i); \
207 void IMM32(int32_t i) { \
209 *((int32_t*)_nIns) = (int32_t)(i); \
211 void MODRMs(int32_t r, int32_t d, Register b, int32_t l, int32_t i); \
212 void MODRMm(int32_t r, int32_t d, Register b); \
213 void MODRMSIB(Register reg, Register base, int32_t index, int32_t scale, int32_t disp); \
214 void MODRMdm(int32_t r, int32_t addr); \
215 void MODRM(int32_t d, int32_t s) { \
216 NanoAssert((unsigned(d))<8 && (unsigned(s))<8); \
217 *(--_nIns) = (uint8_t) ( 3<<6 | d<<3 | s ); \
219 void ALU0(int32_t o); \
220 void ALUm(int32_t c, int32_t r, int32_t d, Register b); \
221 void ALUdm(int32_t c, int32_t r, int32_t addr); \
222 void ALUsib(int32_t c, Register r, Register base, int32_t index, int32_t scale, int32_t disp); \
223 void ALUm16(int32_t c, int32_t r, int32_t d, Register b); \
224 void ALU2dm(int32_t c, int32_t r, int32_t addr); \
225 void ALU2m(int32_t c, int32_t r, int32_t d, Register b); \
226 void ALU2sib(int32_t c, Register r, Register base, int32_t index, int32_t scale, int32_t disp); \
227 void ALU(int32_t c, int32_t d, int32_t s) { \
228 underrunProtect(2); \
230 *(--_nIns) = uint8_t(c); \
232 void ALUi(int32_t c, int32_t r, int32_t i); \
233 void ALUmi(int32_t c, int32_t d, Register b, int32_t i); \
234 void ALU2(int32_t c, int32_t d, int32_t s); \
237 void OR(Register l, Register r); \
238 void AND(Register l, Register r); \
239 void XOR(Register l, Register r); \
240 void ADD(Register l, Register r); \
241 void SUB(Register l, Register r); \
242 void MUL(Register l, Register r); \
243 void DIV(Register r); \
244 void NOT(Register r); \
245 void NEG(Register r); \
246 void SHR(Register r, Register s); \
247 void SAR(Register r, Register s); \
248 void SHL(Register r, Register s); \
249 void SHIFT(int32_t c, Register r, int32_t i); \
250 void SHLi(Register r, int32_t i); \
251 void SHRi(Register r, int32_t i); \
252 void SARi(Register r, int32_t i); \
253 void MOVZX8(Register d, Register s); \
254 void SUBi(Register r, int32_t i); \
255 void ADDi(Register r, int32_t i); \
256 void ANDi(Register r, int32_t i); \
257 void ORi(Register r, int32_t i); \
258 void XORi(Register r, int32_t i); \
259 void ADDmi(int32_t d, Register b, int32_t i); \
260 void TEST(Register d, Register s); \
261 void CMP(Register l, Register r); \
262 void CMPi(Register r, int32_t i); \
263 void MR(Register d, Register s) { \
266 asm_output("mov %s,%s",gpn(d),gpn(s)); \
268 void LEA(Register r, int32_t d, Register b); \
269 void LEAmi4(Register r, int32_t d, int32_t i); \
271 void INCLi(int32_t p); \
272 void SETE( Register r); \
273 void SETNP(Register r); \
274 void SETL( Register r); \
275 void SETLE(Register r); \
276 void SETG( Register r); \
277 void SETGE(Register r); \
278 void SETB( Register r); \
279 void SETBE(Register r); \
280 void SETA( Register r); \
281 void SETAE(Register r); \
282 void SETO( Register r); \
283 void MREQ(Register d, Register s); \
284 void MRNE(Register d, Register s); \
285 void MRL( Register d, Register s); \
286 void MRLE(Register d, Register s); \
287 void MRG( Register d, Register s); \
288 void MRGE(Register d, Register s); \
289 void MRB( Register d, Register s); \
290 void MRBE(Register d, Register s); \
291 void MRA( Register d, Register s); \
292 void MRAE(Register d, Register s); \
293 void MRNO(Register d, Register s); \
294 void LD(Register reg, int32_t disp, Register base); \
295 void LDdm(Register reg, int32_t addr); \
296 void LDsib(Register reg, int32_t disp, Register base, int32_t index, int32_t scale); \
297 void LD16S(Register r, int32_t d, Register b); \
298 void LD16Sdm(Register r, int32_t addr); \
299 void LD16Ssib(Register r, int32_t disp, Register base, int32_t index, int32_t scale); \
300 void LD16Z(Register r, int32_t d, Register b); \
301 void LD16Zdm(Register r, int32_t addr); \
302 void LD16Zsib(Register r, int32_t disp, Register base, int32_t index, int32_t scale); \
303 void LD8Z(Register r, int32_t d, Register b); \
304 void LD8Zdm(Register r, int32_t addr); \
305 void LD8Zsib(Register r, int32_t disp, Register base, int32_t ndex, int32_t scale); \
306 void LD8S(Register r, int32_t d, Register b); \
307 void LD8Sdm(Register r, int32_t addr); \
308 void LD8Ssib(Register r, int32_t disp, Register base, int32_t index, int32_t scale); \
309 void LDi(Register r, int32_t i); \
310 void ST8(Register base, int32_t disp, Register reg); \
311 void ST16(Register base, int32_t disp, Register reg); \
312 void ST(Register base, int32_t disp, Register reg); \
313 void ST8i(Register base, int32_t disp, int32_t imm); \
314 void ST16i(Register base, int32_t disp, int32_t imm); \
315 void STi(Register base, int32_t disp, int32_t imm); \
319 void PUSHi(int32_t i); \
320 void PUSHi32(int32_t i); \
321 void PUSHr(Register r); \
322 void PUSHm(int32_t d, Register b); \
323 void POPr(Register r); \
324 void JCC(int32_t o, NIns* t, const char* n); \
325 void JMP_long(NIns* t); \
326 void JMP(NIns* t) { \
328 underrunProtect(5); \
329 intptr_t tt = t ? (intptr_t)t - (intptr_t)_nIns : 0; \
330 if (t && isS8(tt)) { \
333 _nIns[1] = uint8_t(tt & 0xff); \
336 *(--_nIns) = JMP32; \
338 asm_output("jmp %p", t); \
340 void JMP_indirect(Register r); \
341 void JMP_indexed(Register x, int32_t ss, NIns** addr); \
349 void JNBE(NIns* t); \
353 void JNAE(NIns* t); \
357 void JNLE(NIns* t); \
361 void JNGE(NIns* t); \
364 void SSE(int32_t c, int32_t d, int32_t s); \
365 void SSEm(int32_t c, int32_t r, int32_t d, Register b); \
366 void LDSDm(Register r, const double* addr); \
367 void SSE_LDSD(Register r, int32_t d, Register b); \
368 void SSE_LDQ( Register r, int32_t d, Register b); \
369 void SSE_LDSS(Register r, int32_t d, Register b); \
370 void SSE_STSD(int32_t d, Register b, Register r); \
371 void SSE_STQ( int32_t d, Register b, Register r); \
372 void SSE_STSS(int32_t d, Register b, Register r); \
373 void SSE_CVTSI2SD(Register xr, Register gr); \
374 void SSE_CVTSD2SI(Register gr, Register xr); \
375 void SSE_CVTSD2SS(Register xr, Register gr); \
376 void SSE_CVTSS2SD(Register xr, Register gr); \
377 void SSE_CVTDQ2PD(Register d, Register r); \
378 void SSE_MOVD(Register d, Register s); \
379 void SSE_MOVSD(Register rd, Register rs); \
380 void SSE_MOVDm(Register d, Register b, Register xrs); \
381 void SSE_ADDSD(Register rd, Register rs); \
382 void SSE_ADDSDm(Register r, const double* addr); \
383 void SSE_SUBSD(Register rd, Register rs); \
384 void SSE_MULSD(Register rd, Register rs); \
385 void SSE_DIVSD(Register rd, Register rs); \
386 void SSE_UCOMISD(Register rl, Register rr); \
387 void SSE_CVTSI2SDm(Register xr, Register d, Register b); \
388 void SSE_XORPD(Register r, const uint32_t* maskaddr); \
389 void SSE_XORPDr(Register rd, Register rs); \
390 void FPUc(int32_t o); \
391 void FPU(int32_t o, Register r) { \
392 underrunProtect(2); \
393 *(--_nIns) = uint8_t(((uint8_t)(o)&0xff) | (r&7)); \
394 *(--_nIns) = (uint8_t)((o>>8)&0xff); \
396 void FPUm(int32_t o, int32_t d, Register b); \
397 void FPUdm(int32_t o, const double* const m); \
398 void TEST_AH(int32_t i); \
399 void TEST_AX(int32_t i); \
404 void FFREE(Register r); \
405 void FST32(bool p, int32_t d, Register b); \
406 void FSTQ(bool p, int32_t d, Register b); \
407 void FSTPQ(int32_t d, Register b); \
408 void FCOM(bool p, int32_t d, Register b); \
409 void FCOMdm(bool p, const double* dm); \
410 void FLD32(int32_t d, Register b); \
411 void FLDQ(int32_t d, Register b); \
412 void FLDQdm(const double* dm); \
413 void FILDQ(int32_t d, Register b); \
414 void FILD(int32_t d, Register b); \
415 void FIST(bool p, int32_t d, Register b); \
416 void FADD( int32_t d, Register b); \
417 void FSUB( int32_t d, Register b); \
418 void FSUBR(int32_t d, Register b); \
419 void FMUL( int32_t d, Register b); \
420 void FDIV( int32_t d, Register b); \
421 void FDIVR(int32_t d, Register b); \
422 void FADDdm( const double *dm); \
423 void FSUBRdm(const double* dm); \
424 void FMULdm( const double* dm); \
425 void FDIVRdm(const double* dm); \
427 void FSTP(Register r) { \
430 asm_output("fstp %s",gpn(r)); fpu_pop(); \
434 void FLDr(Register r); \
436 void CALL(const CallInfo* ci); \
437 void CALLr(const CallInfo* ci, Register r);
442 #endif // __nanojit_Nativei386__