PageRenderTime 22ms CodeModel.GetById 9ms app.highlight 7ms RepoModel.GetById 2ms app.codeStats 0ms

/js/src/nanojit/Nativei386.h

http://github.com/zpao/v8monkey
C++ Header | 490 lines | 413 code | 30 blank | 47 comment | 10 complexity | 310baad48d435374c3b5d30c699cf5b8 MD5 | raw file
  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
  5 *
  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/
 10 *
 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
 14 * License.
 15 *
 16 * The Original Code is [Open Source Virtual Machine].
 17 *
 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.
 22 *
 23 * Contributor(s):
 24 *   Adobe AS3 Team
 25 *
 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.
 37 *
 38 * ***** END LICENSE BLOCK ***** */
 39
 40
 41#ifndef __nanojit_Nativei386__
 42#define __nanojit_Nativei386__
 43
 44#include "NativeCommon.h"
 45
 46#ifdef PERFM
 47#define DOPROF
 48#include "../vprof/vprof.h"
 49#define count_instr() _nvprof("x86",1)
 50#define count_ret() _nvprof("x86-ret",1); count_instr();
 51#define count_push() _nvprof("x86-push",1); count_instr();
 52#define count_pop() _nvprof("x86-pop",1); count_instr();
 53#define count_st() _nvprof("x86-st",1); count_instr();
 54#define count_stq() _nvprof("x86-stq",1); count_instr();
 55#define count_ld() _nvprof("x86-ld",1); count_instr();
 56#define count_ldq() _nvprof("x86-ldq",1); count_instr();
 57#define count_call() _nvprof("x86-call",1); count_instr();
 58#define count_calli() _nvprof("x86-calli",1); count_instr();
 59#define count_prolog() _nvprof("x86-prolog",1); count_instr();
 60#define count_alu() _nvprof("x86-alu",1); count_instr();
 61#define count_mov() _nvprof("x86-mov",1); count_instr();
 62#define count_fpu() _nvprof("x86-fpu",1); count_instr();
 63#define count_jmp() _nvprof("x86-jmp",1); count_instr();
 64#define count_jcc() _nvprof("x86-jcc",1); count_instr();
 65#define count_fpuld() _nvprof("x86-ldq",1); _nvprof("x86-fpu",1); count_instr()
 66#define count_aluld() _nvprof("x86-ld",1); _nvprof("x86-alu",1); count_instr()
 67#define count_alust() _nvprof("x86-ld",1); _nvprof("x86-alu",1); _nvprof("x86-st",1); count_instr()
 68#define count_pushld() _nvprof("x86-ld",1); _nvprof("x86-push",1); count_instr()
 69#define count_imt() _nvprof("x86-imt",1) count_instr()
 70#else
 71#define count_instr()
 72#define count_ret()
 73#define count_push()
 74#define count_pop()
 75#define count_st()
 76#define count_stq()
 77#define count_ld()
 78#define count_ldq()
 79#define count_call()
 80#define count_calli()
 81#define count_prolog()
 82#define count_alu()
 83#define count_mov()
 84#define count_fpu()
 85#define count_jmp()
 86#define count_jcc()
 87#define count_fpuld()
 88#define count_aluld()
 89#define count_alust()
 90#define count_pushld()
 91#define count_imt()
 92#endif
 93
 94namespace nanojit
 95{
 96    const int NJ_MAX_REGISTERS = 24; // gpregs, x87 regs, xmm regs
 97
 98    #define NJ_MAX_STACK_ENTRY           4096
 99    #define NJ_MAX_PARAMETERS               1
100
101    #define NJ_USES_IMMD_POOL          1
102
103    #define NJ_JTBL_SUPPORTED               1
104    #define NJ_EXPANDED_LOADSTORE_SUPPORTED 1
105    #define NJ_F2I_SUPPORTED                1
106    #define NJ_SOFTFLOAT_SUPPORTED          0
107    #define NJ_DIVI_SUPPORTED               1
108    
109        // Preserve a 16-byte stack alignment, to support the use of
110        // SSE instructions like MOVDQA (if not by Tamarin itself,
111        // then by the C functions it calls).
112    const int NJ_ALIGN_STACK = 16;
113
114    const int32_t LARGEST_UNDERRUN_PROT = 32;  // largest value passed to underrunProtect
115
116    typedef uint8_t NIns;
117
118    // Bytes of icache to flush after patch
119    const size_t LARGEST_BRANCH_PATCH = 16 * sizeof(NIns);
120
121    static const Register
122        // General purpose 32 bit registers.  The names are rEAX, rEBX, etc,
123        // because EAX, EBX, et al clash with <sys/regset.h> on Solaris (sigh).
124        // See bug 570726 for details.
125        rEAX = { 0 }, // return value, scratch
126        rECX = { 1 }, // this/arg0, scratch
127        rEDX = { 2 }, // arg1, return-msw, scratch
128        rEBX = { 3 },
129        rESP = { 4 }, // stack pointer
130        rEBP = { 5 }, // frame pointer
131        rESI = { 6 },
132        rEDI = { 7 },
133
134        SP = rESP,    // alias SP to ESP for convenience
135        FP = rEBP,    // alias FP to EBP for convenience
136
137        // SSE regs come before X87 so we prefer them
138        XMM0 = { 8 },
139        XMM1 = { 9 },
140        XMM2 = { 10 },
141        XMM3 = { 11 },
142        XMM4 = { 12 },
143        XMM5 = { 13 },
144        XMM6 = { 14 },
145        XMM7 = { 15 },
146
147        // X87 regs
148        FST0 = { 16 },
149
150        deprecated_UnknownReg = { 17 }, // XXX: remove eventually, see bug 538924
151        UnspecifiedReg = { 17 };
152
153    static const uint32_t FirstRegNum = 0;
154    static const uint32_t LastRegNum = 16;
155
156    typedef int RegisterMask;
157
158    static const int NumSavedRegs = 3;
159    static const RegisterMask SavedRegs   = 1<<REGNUM(rEBX) | 1<<REGNUM(rEDI) | 1<<REGNUM(rESI);
160    static const RegisterMask GpRegs      = SavedRegs | 1<<REGNUM(rEAX) | 1<<REGNUM(rECX) |
161                                                        1<<REGNUM(rEDX);
162    static const RegisterMask XmmRegs     = 1<<REGNUM(XMM0) | 1<<REGNUM(XMM1) | 1<<REGNUM(XMM2) |
163                                            1<<REGNUM(XMM3) | 1<<REGNUM(XMM4) | 1<<REGNUM(XMM5) |
164                                            1<<REGNUM(XMM6) | 1<<REGNUM(XMM7);
165    static const RegisterMask x87Regs     = 1<<REGNUM(FST0);
166    static const RegisterMask FpRegs      = x87Regs | XmmRegs;
167    static const RegisterMask ScratchRegs = 1<<REGNUM(rEAX) | 1<<REGNUM(rECX) | 1<<REGNUM(rEDX) |
168                                            FpRegs;
169
170    static const RegisterMask AllowableByteRegs = 1<<REGNUM(rEAX) | 1<<REGNUM(rECX) |
171                                                  1<<REGNUM(rEDX) | 1<<REGNUM(rEBX);
172
173    static inline bool IsGpReg(Register r) {
174        return ((1<<REGNUM(r)) & GpRegs) != 0;
175    }
176    static inline bool IsXmmReg(Register r) {
177        return ((1<<REGNUM(r)) & XmmRegs) != 0;
178    }
179
180    verbose_only( extern const char* regNames[]; )
181
182    #define DECLARE_PLATFORM_STATS()
183
184    #define DECLARE_PLATFORM_REGALLOC()
185
186    #define JCC32 0x0f
187    #define JMP8  0xeb
188    #define JMP32 0xe9
189
190    #define DECLARE_PLATFORM_ASSEMBLER()    \
191        const static Register argRegs[2], retRegs[2]; \
192        int32_t max_stk_args;\
193        debug_only( int32_t _fpuStkDepth; ) \
194        debug_only( int32_t _sv_fpuStkDepth; ) \
195        void nativePageReset();\
196        void nativePageSetup();\
197        void underrunProtect(int);\
198        bool hardenNopInsertion(const Config& c) { return c.harden_nop_insertion; } \
199        void asm_immi(Register r, int32_t val, bool canClobberCCs);\
200        void asm_stkarg(LIns* p, int32_t& stkd);\
201        void asm_farg(LIns*, int32_t& stkd);\
202        void asm_arg(ArgType ty, LIns* p, Register r, int32_t& stkd);\
203        void asm_pusharg(LIns*);\
204        void asm_cmp(LIns *cond); \
205        void asm_cmpi(LIns *cond); \
206        void asm_cmpd(LIns *cond);\
207        Branches asm_branch_helper(bool, LIns* cond, NIns*);\
208        Branches asm_branchi_helper(bool, LIns* cond, NIns*);\
209        Branches asm_branchd_helper(bool, LIns* cond, NIns*);\
210        void asm_div_mod(LIns *cond); \
211        void asm_load(int d, Register r); \
212        void asm_immd(Register r, uint64_t q, double d, bool canClobberCCs); \
213        \
214        /* These function generate fragments of instructions. */ \
215        void IMM8(int32_t i) { /* Length: 1 byte. */ \
216            _nIns -= 1; \
217            *((int8_t*)_nIns) = int8_t(i); \
218        }; \
219        void IMM16(int32_t i) { /* Length: 2 bytes. */ \
220            _nIns -= 2; \
221            *((int16_t*)_nIns) = int16_t(i); \
222        }; \
223        void IMM32(int32_t i) { /* Length: 4 bytes. */ \
224            _nIns -= 4; \
225            *((int32_t*)_nIns) = int32_t(i); \
226        }; \
227        void OPCODE(int32_t opc) { /* Length: 1 byte.  */ \
228            NanoAssert(unsigned(opc) <= 0xff); \
229            *(--_nIns) = uint8_t(opc); \
230        } \
231        void OPCODE2(int32_t opc2) { /* Length: 2 bytes.  */ \
232            NanoAssert(unsigned(opc2) <= 0xffff); \
233            *(--_nIns) = uint8_t(opc2); \
234            *(--_nIns) = uint8_t(opc2 >> 8); \
235        } \
236        void OPCODE3(int32_t opc3) { /* Length: 3 bytes.  */ \
237            NanoAssert(unsigned(opc3) <= 0xffffff); \
238            *(--_nIns) = uint8_t(opc3); \
239            *(--_nIns) = uint8_t(opc3 >> 8); \
240            *(--_nIns) = uint8_t(opc3 >> 16); \
241        } \
242        void MODRM(int32_t mod, int32_t ro, int32_t rm) { /* Length: 1 byte. */ \
243            NanoAssert(unsigned(mod) < 4 && unsigned(ro) < 8 && unsigned(rm) < 8); \
244            *(--_nIns) = uint8_t(mod << 6 | ro << 3 | rm); \
245        } \
246        void SIB(int32_t s, int32_t i, int32_t b) { /* Length: 1 byte. */ \
247            NanoAssert(unsigned(s) < 4 && unsigned(i) < 8 && unsigned(b) < 8); \
248            *(--_nIns) = uint8_t(s << 6 | i << 3 | b); \
249        } \
250        void MODRMr(int32_t d, int32_t s) { /* Length: 1 byte. */ \
251            NanoAssert(unsigned(d) < 8 && unsigned(s) < 8); \
252            MODRM(3, d, s); \
253        }; \
254        void MODRMm(int32_t r, int32_t d, Register b); \
255        void MODRMsib(int32_t r, Register b, Register i, int32_t s, int32_t d); \
256        void MODRMdm(int32_t r, int32_t addr); \
257        \
258        /* These functions generate entire instructions. */ \
259        void ALU0(int32_t o); \
260        void ALUm(int32_t c, int32_t r, int32_t d, Register b); \
261        void ALUdm(int32_t c, Register r, int32_t addr); \
262        void ALUsib(int32_t c, Register r, Register base, Register index, int32_t scale, int32_t disp); \
263        void ALUsib16(int32_t c, Register r, Register base, Register index, int32_t scale, int32_t disp); \
264        void ALUm16(int32_t c, int32_t r, int32_t d, Register b); \
265        void ALU2dm(int32_t c, Register r, int32_t addr); \
266        void ALU2m(int32_t c, Register r, int32_t d, Register b); \
267        void ALU2sib(int32_t c, Register r, Register base, Register index, int32_t scale, int32_t disp); \
268        void ALU(int32_t opc, int32_t d, Register s) { \
269            underrunProtect(2); \
270            MODRMr(d, REGNUM(s)); \
271            OPCODE(opc); \
272        }; \
273        void ALUi(int32_t c, Register r, int32_t i); \
274        void ALUmi(int32_t c, int32_t d, Register b, int32_t i); \
275        void ALU2(int32_t c, Register d, Register s); \
276        Register AL2AHReg(Register r); \
277        void OR(Register l, Register r); \
278        void AND(Register l, Register r); \
279        void AND8R(Register r); \
280        void XOR(Register l, Register r); \
281        void ADD(Register l, Register r); \
282        void SUB(Register l, Register r); \
283        void IMUL(Register l, Register r); \
284        void DIV(Register r); \
285        void NOT(Register r); \
286        void NEG(Register r); \
287        void SHR(Register r, Register s); \
288        void SAR(Register r, Register s); \
289        void SHL(Register r, Register s); \
290        void SHIFTi(int32_t c, Register r, int32_t i); \
291        void SHLi(Register r, int32_t i); \
292        void SHRi(Register r, int32_t i); \
293        void SARi(Register r, int32_t i); \
294        void MOVZX8(Register d, Register s); \
295        void SUBi(Register r, int32_t i); \
296        void ADDi(Register r, int32_t i); \
297        void ANDi(Register r, int32_t i); \
298        void ORi(Register r, int32_t i); \
299        void XORi(Register r, int32_t i); \
300        void ADDmi(int32_t d, Register b, int32_t i); \
301        void TEST(Register d, Register s); \
302        void CMP(Register l, Register r); \
303        void CMPi(Register r, int32_t i); \
304        void MR(Register d, Register s) { \
305            count_mov(); \
306            ALU(0x8b, REGNUM(d), s); \
307            asm_output("mov %s,%s", gpn(d), gpn(s)); \
308        }; \
309        void LEA(Register r, int32_t d, Register b); \
310        void LEAmi4(Register r, int32_t d, Register i); \
311        void CDQ(); \
312        void INCLi(int32_t p); \
313        void SETE( Register r); \
314        void SETNP(Register r); \
315        void SETNPH(Register r); \
316        void SETL( Register r); \
317        void SETLE(Register r); \
318        void SETG( Register r); \
319        void SETGE(Register r); \
320        void SETB( Register r); \
321        void SETBE(Register r); \
322        void SETA( Register r); \
323        void SETAE(Register r); \
324        void SETO( Register r); \
325        void MREQ(Register d, Register s); \
326        void MRNE(Register d, Register s); \
327        void MRL( Register d, Register s); \
328        void MRLE(Register d, Register s); \
329        void MRG( Register d, Register s); \
330        void MRGE(Register d, Register s); \
331        void MRB( Register d, Register s); \
332        void MRBE(Register d, Register s); \
333        void MRA( Register d, Register s); \
334        void MRAE(Register d, Register s); \
335        void MRNO(Register d, Register s); \
336        void LD(Register reg, int32_t disp, Register base); \
337        void LDdm(Register reg, int32_t addr); \
338        void LDsib(Register reg, int32_t disp, Register base, Register index, int32_t scale); \
339        void LD16S(Register r, int32_t d, Register b); \
340        void LD16Sdm(Register r, int32_t addr); \
341        void LD16Ssib(Register r, int32_t disp, Register base, Register index, int32_t scale); \
342        void LD16Z(Register r, int32_t d, Register b); \
343        void LD16Zdm(Register r, int32_t addr); \
344        void LD16Zsib(Register r, int32_t disp, Register base, Register index, int32_t scale); \
345        void LD8Z(Register r, int32_t d, Register b); \
346        void LD8Zdm(Register r, int32_t addr); \
347        void LD8Zsib(Register r, int32_t disp, Register base, Register index, int32_t scale); \
348        void LD8S(Register r, int32_t d, Register b); \
349        void LD8Sdm(Register r, int32_t addr); \
350        void LD8Ssib(Register r, int32_t disp, Register base, Register index, int32_t scale); \
351        void LDi(Register r, int32_t i); \
352        void ST8(Register base, int32_t disp, Register reg); \
353        void ST8sib(int32_t disp, Register base, Register index, int32_t scale, Register reg); \
354        void ST16(Register base, int32_t disp, Register reg); \
355        void ST16sib(int32_t disp, Register base, Register index, int32_t scale, Register reg); \
356        void ST(Register base, int32_t disp, Register reg); \
357        void STsib(int32_t disp, Register base, Register index, int32_t scale, Register reg); \
358        void ST8i(Register base, int32_t disp, int32_t imm); \
359        void ST8isib(int32_t disp, Register base, Register index, int32_t scale, int32_t imm); \
360        void ST16i(Register base, int32_t disp, int32_t imm); \
361        void ST16isib(int32_t disp, Register base, Register index, int32_t scale, int32_t imm); \
362        void STi(Register base, int32_t disp, int32_t imm); \
363        void STisib(int32_t disp, Register base, Register index, int32_t scale, int32_t imm); \
364        void RET(); \
365        void NOP(); \
366        void INT3(); \
367        void PUSHi(int32_t i); \
368        void PUSHr(Register r); \
369        void PUSHm(int32_t d, Register b); \
370        void POPr(Register r); \
371        void JCC(int32_t o, NIns* t, const char* n); \
372        void JMP_long(NIns* t); \
373        void JMP(NIns* t) { \
374            count_jmp(); \
375            underrunProtect(5); \
376            intptr_t tt = t ? (intptr_t)t - (intptr_t)_nIns : 0; \
377            if (t && isS8(tt)) { \
378                *(--_nIns) = uint8_t(tt & 0xff); \
379                *(--_nIns) = JMP8; \
380            } else { \
381                IMM32(tt); \
382                *(--_nIns) = JMP32; \
383            } \
384            asm_output("jmp %p", t); \
385        }; \
386        void JMP_indirect(Register r); \
387        void JMP_indexed(Register x, int32_t ss, NIns** addr); \
388        void JE(NIns* t); \
389        void JNE(NIns* t); \
390        void JP(NIns* t); \
391        void JNP(NIns* t); \
392        void JB(NIns* t); \
393        void JNB(NIns* t); \
394        void JBE(NIns* t); \
395        void JNBE(NIns* t); \
396        void JA(NIns* t); \
397        void JNA(NIns* t); \
398        void JAE(NIns* t); \
399        void JNAE(NIns* t); \
400        void JL(NIns* t); \
401        void JNL(NIns* t); \
402        void JLE(NIns* t); \
403        void JNLE(NIns* t); \
404        void JG(NIns* t); \
405        void JNG(NIns* t); \
406        void JGE(NIns* t); \
407        void JNGE(NIns* t); \
408        void JO(NIns* t); \
409        void JNO(NIns* t); \
410        void SSE(int32_t c, Register d, Register s); \
411        void SSEm(int32_t c, Register r, int32_t d, Register b); \
412        void SSEsib(int32_t c, Register rr, int32_t d, Register rb, Register ri, int32_t scale); \
413        void LDSDm(Register r, const double* addr); \
414        void SSE_LDQ( Register r, int32_t d, Register b); \
415        void SSE_LDSS(Register r, int32_t d, Register b); \
416        void SSE_LDQsib(Register r, int32_t d, Register rb, Register ri, int32_t scale); \
417        void SSE_LDSSsib(Register r, int32_t d, Register rb, Register ri, int32_t scale); \
418        void SSE_STSD(int32_t d, Register b, Register r); \
419        void SSE_STQ( int32_t d, Register b, Register r); \
420        void SSE_STSS(int32_t d, Register b, Register r); \
421        void SSE_STQsib(int32_t d, Register rb, Register ri, int32_t scale, Register rv); \
422        void SSE_CVTSI2SD(Register xr, Register gr); \
423        void SSE_CVTSD2SI(Register gr, Register xr); \
424        void SSE_CVTTSD2SI(Register gr, Register xr); \
425        void SSE_CVTSD2SS(Register xr, Register gr); \
426        void SSE_CVTSS2SD(Register xr, Register gr); \
427        void SSE_CVTDQ2PD(Register d, Register r); \
428        void SSE_MOVD(Register d, Register s); \
429        void SSE_MOVSD(Register rd, Register rs); \
430        void SSE_ADDSD(Register rd, Register rs); \
431        void SSE_ADDSDm(Register r, const double* addr); \
432        void SSE_SUBSD(Register rd, Register rs); \
433        void SSE_MULSD(Register rd, Register rs); \
434        void SSE_DIVSD(Register rd, Register rs); \
435        void SSE_UCOMISD(Register rl, Register rr); \
436        void SSE_XORPD(Register r, const uint32_t* maskaddr); \
437        void SSE_XORPDr(Register rd, Register rs); \
438        void fpu_push(); \
439        void fpu_pop(); \
440        void FPUc(int32_t o); \
441        void FPU(int32_t o, Register r) { \
442            underrunProtect(2); \
443            *(--_nIns) = uint8_t((uint8_t(o) & 0xff) | (REGNUM(r) & 7)); \
444            *(--_nIns) = uint8_t((o >> 8) & 0xff); \
445        }; \
446        void FPUm(int32_t o, int32_t d, Register b); \
447        void FPUdm(int32_t o, const double* const m); \
448        void TEST_AH(int32_t i); \
449        void FNSTSW_AX(); \
450        void FCHS(); \
451        void FLD1(); \
452        void FLDZ(); \
453        void FST32(bool p, int32_t d, Register b); \
454        void FSTQ(bool p, int32_t d, Register b); \
455        void FSTPQ(int32_t d, Register b); \
456        void FCOM(bool p, int32_t d, Register b); \
457        void FCOMdm(bool p, const double* dm); \
458        void FLD32(int32_t d, Register b); \
459        void FLDQ(int32_t d, Register b); \
460        void FLDQdm(const double* dm); \
461        void FILDQ(int32_t d, Register b); \
462        void FILD(int32_t d, Register b); \
463        void FIST(bool p, int32_t d, Register b); \
464        void FADD( int32_t d, Register b); \
465        void FSUB( int32_t d, Register b); \
466        void FSUBR(int32_t d, Register b); \
467        void FMUL( int32_t d, Register b); \
468        void FDIV( int32_t d, Register b); \
469        void FDIVR(int32_t d, Register b); \
470        void FADDdm( const double *dm); \
471        void FSUBRdm(const double* dm); \
472        void FMULdm( const double* dm); \
473        void FDIVRdm(const double* dm); \
474        void FSTP(Register r) { \
475            count_fpu(); \
476            FPU(0xddd8, r); \
477            asm_output("fstp %s", gpn(r)); \
478            fpu_pop(); \
479        }; \
480        void FCOMP(); \
481        void FCOMPP(); \
482        void FLDr(Register r); \
483        void EMMS(); \
484        void CALL(const CallInfo* ci); \
485        void CALLr(const CallInfo* ci, Register r);
486}
487
488
489
490#endif // __nanojit_Nativei386__