/[jscoverage]/trunk/js/nanojit/Nativei386.h
ViewVC logotype

Contents of /trunk/js/nanojit/Nativei386.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 399 - (show annotations)
Tue Dec 9 03:37:47 2008 UTC (11 years ago) by siliconforks
File MIME type: text/plain
File size: 27447 byte(s)
Use SpiderMonkey from Firefox 3.1b2.

1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is [Open Source Virtual Machine].
16 *
17 * The Initial Developer of the Original Code is
18 * Adobe System Incorporated.
19 * Portions created by the Initial Developer are Copyright (C) 2004-2007
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 * Adobe AS3 Team
24 *
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
36 *
37 * ***** END LICENSE BLOCK ***** */
38
39
40 #ifndef __nanojit_Nativei386__
41 #define __nanojit_Nativei386__
42
43
44 namespace nanojit
45 {
46 const int NJ_LOG2_PAGE_SIZE = 12; // 4K
47 const int NJ_MAX_REGISTERS = 24; // gpregs, x87 regs, xmm regs
48 const int NJ_STACK_OFFSET = 0;
49
50 #define NJ_MAX_STACK_ENTRY 256
51 #define NJ_MAX_PARAMETERS 1
52
53 // Preserve a 16-byte stack alignment, to support the use of
54 // SSE instructions like MOVDQA (if not by Tamarin itself,
55 // then by the C functions it calls).
56 const int NJ_ALIGN_STACK = 16;
57
58 typedef uint8_t NIns;
59
60 // These are used as register numbers in various parts of the code
61 typedef enum
62 {
63 // general purpose 32bit regs
64 EAX = 0, // return value, scratch
65 ECX = 1, // this/arg0, scratch
66 EDX = 2, // arg1, return-msw, scratch
67 EBX = 3,
68 ESP = 4, // stack pointer
69 EBP = 5, // frame pointer
70 ESI = 6,
71 EDI = 7,
72
73 SP = ESP, // alias SP to ESP for convenience
74 FP = EBP, // alias FP to EBP for convenience
75
76 // SSE regs come before X87 so we prefer them
77 XMM0 = 8,
78 XMM1 = 9,
79 XMM2 = 10,
80 XMM3 = 11,
81 XMM4 = 12,
82 XMM5 = 13,
83 XMM6 = 14,
84 XMM7 = 15,
85
86 // X87 regs
87 FST0 = 16,
88 FST1 = 17,
89 FST2 = 18,
90 FST3 = 19,
91 FST4 = 20,
92 FST5 = 21,
93 FST6 = 22,
94 FST7 = 23,
95
96 FirstReg = 0,
97 LastReg = 23,
98 UnknownReg = 24
99 }
100 Register;
101
102 typedef int RegisterMask;
103
104 static const int NumSavedRegs = 3;
105 static const RegisterMask SavedRegs = 1<<EBX | 1<<EDI | 1<<ESI;
106 static const RegisterMask GpRegs = SavedRegs | 1<<EAX | 1<<ECX | 1<<EDX;
107 static const RegisterMask XmmRegs = 1<<XMM0|1<<XMM1|1<<XMM2|1<<XMM3|1<<XMM4|1<<XMM5|1<<XMM6|1<<XMM7;
108 static const RegisterMask x87Regs = 1<<FST0;
109 static const RegisterMask FpRegs = x87Regs | XmmRegs;
110 static const RegisterMask ScratchRegs = 1<<EAX | 1<<ECX | 1<<EDX | FpRegs;
111
112 static const RegisterMask AllowableFlagRegs = 1<<EAX |1<<ECX | 1<<EDX | 1<<EBX;
113
114 #define _rmask_(r) (1<<(r))
115 #define _is_xmm_reg_(r) ((_rmask_(r)&XmmRegs)!=0)
116 #define _is_x87_reg_(r) ((_rmask_(r)&x87Regs)!=0)
117 #define _is_fp_reg_(r) ((_rmask_(r)&FpRegs)!=0)
118 #define _is_gp_reg_(r) ((_rmask_(r)&GpRegs)!=0)
119
120 #define nextreg(r) Register(r+1)
121 #define prevreg(r) Register(r-1)
122 #define imm2register(c) (Register)(c)
123
124 verbose_only( extern const char* regNames[]; )
125
126 #define DECLARE_PLATFORM_STATS()
127
128 #define DECLARE_PLATFORM_REGALLOC()
129
130 #define DECLARE_PLATFORM_ASSEMBLER() \
131 const static Register argRegs[2], retRegs[2]; \
132 bool x87Dirty; \
133 bool pad[3];\
134 void nativePageReset();\
135 void nativePageSetup();\
136 void underrunProtect(int);\
137 void asm_farg(LInsp);\
138 void asm_align_code();
139
140 #define swapptrs() { NIns* _tins = _nIns; _nIns=_nExitIns; _nExitIns=_tins; }
141
142 #define IMM32(i) \
143 _nIns -= 4; \
144 *((int32_t*)_nIns) = (int32_t)(i)
145
146 #define MODRMs(r,d,b,l,i) \
147 NanoAssert(unsigned(r)<8 && unsigned(b)<8 && unsigned(i)<8); \
148 if ((d) == 0 && (b) != EBP) { \
149 _nIns -= 2; \
150 _nIns[0] = (uint8_t) ( 0<<6 | (r)<<3 | 4); \
151 _nIns[1] = (uint8_t) ((l)<<6 | (i)<<3 | (b)); \
152 } else if (isS8(d)) { \
153 _nIns -= 3; \
154 _nIns[0] = (uint8_t) ( 1<<6 | (r)<<3 | 4 ); \
155 _nIns[1] = (uint8_t) ( (l)<<6 | (i)<<3 | (b) ); \
156 _nIns[2] = (uint8_t) (d); \
157 } else { \
158 IMM32(d); \
159 *(--_nIns) = (uint8_t) ( (l)<<6 | (i)<<3 | (b) ); \
160 *(--_nIns) = (uint8_t) ( 2<<6 | (r)<<3 | 4 ); \
161 }
162
163 #define MODRMm(r,d,b) \
164 NanoAssert(unsigned(r)<8 && ((b)==UnknownReg || unsigned(b)<8)); \
165 if ((b) == UnknownReg) {\
166 IMM32(d);\
167 *(--_nIns) = (uint8_t) (0<<6 | (r)<<3 | 5);\
168 } else if ((b) == ESP) { \
169 MODRMs(r, d, b, 0, (Register)4); \
170 } \
171 else if ( (d) == 0 && (b) != EBP) { \
172 *(--_nIns) = (uint8_t) ( 0<<6 | (r)<<3 | (b) ); \
173 } else if (isS8(d)) { \
174 *(--_nIns) = (uint8_t) (d); \
175 *(--_nIns) = (uint8_t) ( 1<<6 | (r)<<3 | (b) ); \
176 } else { \
177 IMM32(d); \
178 *(--_nIns) = (uint8_t) ( 2<<6 | (r)<<3 | (b) ); \
179 }
180
181 #define MODRMSIB(reg,base,index,scale,disp) \
182 if (disp != 0 || base == EBP) { \
183 if (isS8(disp)) { \
184 *(--_nIns) = int8_t(disp); \
185 } else { \
186 IMM32(disp); \
187 } \
188 } \
189 *(--_nIns) = uint8_t((scale)<<6|(index)<<3|(base)); \
190 if (disp == 0 && base != EBP) { \
191 *(--_nIns) = uint8_t(((reg)<<3)|4); \
192 } else { \
193 if (isS8(disp)) \
194 *(--_nIns) = uint8_t((1<<6)|(reg<<3)|4); \
195 else \
196 *(--_nIns) = uint8_t((2<<6)|(reg<<3)|4); \
197 }
198
199 #define MODRMdm(r,addr) \
200 NanoAssert(unsigned(r)<8); \
201 IMM32(addr); \
202 *(--_nIns) = (uint8_t)( (r)<<3 | 5 );
203
204 #define MODRM(d,s) \
205 NanoAssert(((unsigned)(d))<8 && ((unsigned)(s))<8); \
206 *(--_nIns) = (uint8_t) ( 3<<6|(d)<<3|(s) )
207
208 #define ALU0(o) \
209 underrunProtect(1);\
210 *(--_nIns) = (uint8_t) (o)
211
212 #define ALUm(c,r,d,b) \
213 underrunProtect(8); \
214 MODRMm(r,d,b); \
215 *(--_nIns) = uint8_t(c)
216
217 #define ALUdm(c,r,addr) \
218 underrunProtect(6); \
219 MODRMdm(r,addr); \
220 *(--_nIns) = uint8_t(c)
221
222 #define ALUsib(c,r,base,index,scale,disp) \
223 underrunProtect(7); \
224 MODRMSIB(r,base,index,scale,disp); \
225 *(--_nIns) = uint8_t(c)
226
227 #define ALUm16(c,r,d,b) \
228 underrunProtect(9); \
229 MODRMm(r,d,b); \
230 *(--_nIns) = uint8_t(c);\
231 *(--_nIns) = 0x66
232
233 #define ALU2dm(c,r,addr) \
234 underrunProtect(7); \
235 MODRMdm(r,addr); \
236 *(--_nIns) = (uint8_t) (c);\
237 *(--_nIns) = (uint8_t) ((c)>>8)
238
239 #define ALU2m(c,r,d,b) \
240 underrunProtect(9); \
241 MODRMm(r,d,b); \
242 *(--_nIns) = (uint8_t) (c);\
243 *(--_nIns) = (uint8_t) ((c)>>8)
244
245 #define ALU2sib(c,r,base,index,scale,disp) \
246 underrunProtect(8); \
247 MODRMSIB(r,base,index,scale,disp); \
248 *(--_nIns) = (uint8_t) (c); \
249 *(--_nIns) = (uint8_t) ((c)>>8)
250
251 #define ALU(c,d,s) \
252 underrunProtect(2);\
253 MODRM(d,s); \
254 *(--_nIns) = (uint8_t) (c)
255
256 #define ALUi(c,r,i) \
257 underrunProtect(6); \
258 NanoAssert(unsigned(r)<8);\
259 if (isS8(i)) { \
260 *(--_nIns) = uint8_t(i); \
261 MODRM((c>>3),(r)); \
262 *(--_nIns) = uint8_t(0x83); \
263 } else { \
264 IMM32(i); \
265 if ( (r) == EAX) { \
266 *(--_nIns) = (uint8_t) (c); \
267 } else { \
268 MODRM((c>>3),(r)); \
269 *(--_nIns) = uint8_t(0x81); \
270 } \
271 }
272
273 #define ALUmi(c,d,b,i) \
274 underrunProtect(10); \
275 NanoAssert(((unsigned)b)<8); \
276 if (isS8(i)) { \
277 *(--_nIns) = uint8_t(i); \
278 MODRMm((c>>3),(d),(b)); \
279 *(--_nIns) = uint8_t(0x83); \
280 } else { \
281 IMM32(i); \
282 MODRMm((c>>3),(d),(b)); \
283 *(--_nIns) = uint8_t(0x81); \
284 }
285
286 #define ALU2(c,d,s) \
287 underrunProtect(3); \
288 MODRM((d),(s)); \
289 _nIns -= 2; \
290 _nIns[0] = (uint8_t) ( ((c)>>8) ); \
291 _nIns[1] = (uint8_t) ( (c) )
292
293 #define LAHF() do { ALU0(0x9F); asm_output("lahf"); } while(0)
294 #define SAHF() do { ALU0(0x9E); asm_output("sahf"); } while(0)
295 #define OR(l,r) do { ALU(0x0b, (l),(r)); asm_output2("or %s,%s",gpn(l),gpn(r)); } while(0)
296 #define AND(l,r) do { ALU(0x23, (l),(r)); asm_output2("and %s,%s",gpn(l),gpn(r)); } while(0)
297 #define XOR(l,r) do { ALU(0x33, (l),(r)); asm_output2("xor %s,%s",gpn(l),gpn(r)); } while(0)
298 #define ADD(l,r) do { ALU(0x03, (l),(r)); asm_output2("add %s,%s",gpn(l),gpn(r)); } while(0)
299 #define SUB(l,r) do { ALU(0x2b, (l),(r)); asm_output2("sub %s,%s",gpn(l),gpn(r)); } while(0)
300 #define MUL(l,r) do { ALU2(0x0faf,(l),(r)); asm_output2("mul %s,%s",gpn(l),gpn(r)); } while(0)
301 #define NOT(r) do { ALU(0xf7, (Register)2,(r)); asm_output1("not %s",gpn(r)); } while(0)
302 #define NEG(r) do { ALU(0xf7, (Register)3,(r)); asm_output1("neg %s",gpn(r)); } while(0)
303 #define SHR(r,s) do { ALU(0xd3, (Register)5,(r)); asm_output2("shr %s,%s",gpn(r),gpn(s)); } while(0)
304 #define SAR(r,s) do { ALU(0xd3, (Register)7,(r)); asm_output2("sar %s,%s",gpn(r),gpn(s)); } while(0)
305 #define SHL(r,s) do { ALU(0xd3, (Register)4,(r)); asm_output2("shl %s,%s",gpn(r),gpn(s)); } while(0)
306
307 #define SHIFT(c,r,i) \
308 underrunProtect(3);\
309 *--_nIns = (uint8_t)(i);\
310 MODRM((Register)c,r);\
311 *--_nIns = 0xc1;
312
313 #define SHLi(r,i) do { SHIFT(4,r,i); asm_output2("shl %s,%d", gpn(r),i); } while(0)
314 #define SHRi(r,i) do { SHIFT(5,r,i); asm_output2("shr %s,%d", gpn(r),i); } while(0)
315 #define SARi(r,i) do { SHIFT(7,r,i); asm_output2("sar %s,%d", gpn(r),i); } while(0)
316
317 #define MOVZX8(d,s) do { ALU2(0x0fb6,d,s); asm_output2("movzx %s,%s", gpn(d),gpn(s)); } while(0)
318
319 #define SUBi(r,i) do { ALUi(0x2d,r,i); asm_output2("sub %s,%d",gpn(r),i); } while(0)
320 #define ADDi(r,i) do { ALUi(0x05,r,i); asm_output2("add %s,%d",gpn(r),i); } while(0)
321 #define ANDi(r,i) do { ALUi(0x25,r,i); asm_output2("and %s,%d",gpn(r),i); } while(0)
322 #define ORi(r,i) do { ALUi(0x0d,r,i); asm_output2("or %s,%d",gpn(r),i); } while(0)
323 #define XORi(r,i) do { ALUi(0x35,r,i); asm_output2("xor %s,%d",gpn(r),i); } while(0)
324
325 #define ADDmi(d,b,i) do { ALUmi(0x05, d, b, i); asm_output3("add %d(%s), %d", d, gpn(b), i); } while(0)
326
327 #define TEST(d,s) do { ALU(0x85,d,s); asm_output2("test %s,%s",gpn(d),gpn(s)); } while(0)
328 #define CMP(l,r) do { ALU(0x3b, (l),(r)); asm_output2("cmp %s,%s",gpn(l),gpn(r)); } while(0)
329 #define CMPi(r,i) do { ALUi(0x3d,r,i); asm_output2("cmp %s,%d",gpn(r),i); } while(0)
330
331 #define MR(d,s) do { ALU(0x8b,d,s); asm_output2("mov %s,%s",gpn(d),gpn(s)); } while(0)
332 #define LEA(r,d,b) do { ALUm(0x8d, r,d,b); asm_output3("lea %s,%d(%s)",gpn(r),d,gpn(b)); } while(0)
333
334 #define SETE(r) do { ALU2(0x0f94,(r),(r)); asm_output1("sete %s",gpn(r)); } while(0)
335 #define SETNP(r) do { ALU2(0x0f9B,(r),(r)); asm_output1("setnp %s",gpn(r)); } while(0)
336 #define SETL(r) do { ALU2(0x0f9C,(r),(r)); asm_output1("setl %s",gpn(r)); } while(0)
337 #define SETLE(r) do { ALU2(0x0f9E,(r),(r)); asm_output1("setle %s",gpn(r)); } while(0)
338 #define SETG(r) do { ALU2(0x0f9F,(r),(r)); asm_output1("setg %s",gpn(r)); } while(0)
339 #define SETGE(r) do { ALU2(0x0f9D,(r),(r)); asm_output1("setge %s",gpn(r)); } while(0)
340 #define SETB(r) do { ALU2(0x0f92,(r),(r)); asm_output1("setb %s",gpn(r)); } while(0)
341 #define SETBE(r) do { ALU2(0x0f96,(r),(r)); asm_output1("setbe %s",gpn(r)); } while(0)
342 #define SETA(r) do { ALU2(0x0f97,(r),(r)); asm_output1("seta %s",gpn(r)); } while(0)
343 #define SETAE(r) do { ALU2(0x0f93,(r),(r)); asm_output1("setae %s",gpn(r)); } while(0)
344 #define SETC(r) do { ALU2(0x0f90,(r),(r)); asm_output1("setc %s",gpn(r)); } while(0)
345 #define SETO(r) do { ALU2(0x0f92,(r),(r)); asm_output1("seto %s",gpn(r)); } while(0)
346
347 #define MREQ(dr,sr) do { ALU2(0x0f44,dr,sr); asm_output2("cmove %s,%s", gpn(dr),gpn(sr)); } while(0)
348 #define MRNE(dr,sr) do { ALU2(0x0f45,dr,sr); asm_output2("cmovne %s,%s", gpn(dr),gpn(sr)); } while(0)
349 #define MRL(dr,sr) do { ALU2(0x0f4C,dr,sr); asm_output2("cmovl %s,%s", gpn(dr),gpn(sr)); } while(0)
350 #define MRLE(dr,sr) do { ALU2(0x0f4E,dr,sr); asm_output2("cmovle %s,%s", gpn(dr),gpn(sr)); } while(0)
351 #define MRG(dr,sr) do { ALU2(0x0f4F,dr,sr); asm_output2("cmovg %s,%s", gpn(dr),gpn(sr)); } while(0)
352 #define MRGE(dr,sr) do { ALU2(0x0f4D,dr,sr); asm_output2("cmovge %s,%s", gpn(dr),gpn(sr)); } while(0)
353 #define MRB(dr,sr) do { ALU2(0x0f42,dr,sr); asm_output2("cmovb %s,%s", gpn(dr),gpn(sr)); } while(0)
354 #define MRBE(dr,sr) do { ALU2(0x0f46,dr,sr); asm_output2("cmovbe %s,%s", gpn(dr),gpn(sr)); } while(0)
355 #define MRA(dr,sr) do { ALU2(0x0f47,dr,sr); asm_output2("cmova %s,%s", gpn(dr),gpn(sr)); } while(0)
356 #define MRNC(dr,sr) do { ALU2(0x0f43,dr,sr); asm_output2("cmovnc %s,%s", gpn(dr),gpn(sr)); } while(0)
357 #define MRAE(dr,sr) do { ALU2(0x0f43,dr,sr); asm_output2("cmovae %s,%s", gpn(dr),gpn(sr)); } while(0)
358 #define MRNO(dr,sr) do { ALU2(0x0f41,dr,sr); asm_output2("cmovno %s,%s", gpn(dr),gpn(sr)); } while(0)
359
360 // these aren't currently used but left in for reference
361 //#define LDEQ(r,d,b) do { ALU2m(0x0f44,r,d,b); asm_output3("cmove %s,%d(%s)", gpn(r),d,gpn(b)); } while(0)
362 //#define LDNEQ(r,d,b) do { ALU2m(0x0f45,r,d,b); asm_output3("cmovne %s,%d(%s)", gpn(r),d,gpn(b)); } while(0)
363
364 #define LD(reg,disp,base) do { \
365 ALUm(0x8b,reg,disp,base); \
366 asm_output3("mov %s,%d(%s)",gpn(reg),disp,gpn(base)); } while(0)
367
368 #define LDdm(reg,addr) do { \
369 ALUdm(0x8b,reg,addr); \
370 asm_output2("mov %s,0(%lx)",gpn(reg),addr); \
371 } while (0)
372
373
374 #define SIBIDX(n) "1248"[n]
375
376 #define LDsib(reg,disp,base,index,scale) do { \
377 ALUsib(0x8b,reg,base,index,scale,disp); \
378 asm_output5("mov %s,%d(%s+%s*%c)",gpn(reg),disp,gpn(base),gpn(index),SIBIDX(scale)); \
379 } while (0)
380
381 // load 16-bit, sign extend
382 #define LD16S(r,d,b) do { ALU2m(0x0fbf,r,d,b); asm_output3("movsx %s,%d(%s)", gpn(r),d,gpn(b)); } while(0)
383
384 // load 16-bit, zero extend
385 #define LD16Z(r,d,b) do { ALU2m(0x0fb7,r,d,b); asm_output3("movsz %s,%d(%s)", gpn(r),d,gpn(b)); } while(0)
386
387 #define LD16Zdm(r,addr) do { ALU2dm(0x0fb7,r,addr); asm_output2("movsz %s,0(%lx)", gpn(r),addr); } while (0)
388
389 #define LD16Zsib(r,disp,base,index,scale) do { \
390 ALU2sib(0x0fb7,r,base,index,scale,disp); \
391 asm_output5("movsz %s,%d(%s+%s*%c)",gpn(r),disp,gpn(base),gpn(index),SIBIDX(scale)); \
392 } while (0)
393
394 // load 8-bit, zero extend
395 // note, only 5-bit offsets (!) are supported for this, but that's all we need at the moment
396 // (movzx actually allows larger offsets mode but 5-bit gives us advantage in Thumb mode)
397 #define LD8Z(r,d,b) do { NanoAssert((d)>=0&&(d)<=31); ALU2m(0x0fb6,r,d,b); asm_output3("movzx %s,%d(%s)", gpn(r),d,gpn(b)); } while(0)
398
399 #define LD8Zdm(r,addr) do { \
400 NanoAssert((d)>=0&&(d)<=31); \
401 ALU2dm(0x0fb6,r,addr); \
402 asm_output2("movzx %s,0(%lx)", gpn(r),addr); \
403 } while(0)
404
405 #define LD8Zsib(r,disp,base,index,scale) do { \
406 NanoAssert((d)>=0&&(d)<=31); \
407 ALU2sib(0x0fb6,r,base,index,scale,disp); \
408 asm_output5("movzx %s,%d(%s+%s*%c)",gpn(r),disp,gpn(base),gpn(index),SIBIDX(scale)); \
409 } while(0)
410
411
412 #define LDi(r,i) do { \
413 underrunProtect(5); \
414 IMM32(i); \
415 NanoAssert(((unsigned)r)<8); \
416 *(--_nIns) = (uint8_t) (0xb8 | (r) ); \
417 asm_output2("mov %s,%d",gpn(r),i); } while(0)
418
419 #define ST(base,disp,reg) do { \
420 ALUm(0x89,reg,disp,base); \
421 asm_output3("mov %d(%s),%s",disp,base==UnknownReg?"0":gpn(base),gpn(reg)); } while(0)
422
423 #define STi(base,disp,imm) do { \
424 underrunProtect(12); \
425 IMM32(imm); \
426 MODRMm(0, disp, base); \
427 *(--_nIns) = 0xc7; \
428 asm_output3("mov %d(%s),%d",disp,gpn(base),imm); } while(0)
429
430 #define RET() do { ALU0(0xc3); asm_output("ret"); } while(0)
431 #define NOP() do { ALU0(0x90); asm_output("nop"); } while(0)
432 #define INT3() do { ALU0(0xcc); asm_output("int3"); } while(0)
433
434 #define PUSHi(i) do { \
435 if (isS8(i)) { \
436 underrunProtect(2); \
437 _nIns-=2; _nIns[0] = 0x6a; _nIns[1] = (uint8_t)(i); \
438 asm_output1("push %d",i); \
439 } else \
440 { PUSHi32(i); } } while(0)
441
442 #define PUSHi32(i) do { \
443 underrunProtect(5); \
444 IMM32(i); \
445 *(--_nIns) = 0x68; \
446 asm_output1("push %d",i); } while(0)
447
448 #define PUSHr(r) do { \
449 underrunProtect(1); \
450 NanoAssert(((unsigned)r)<8); \
451 *(--_nIns) = (uint8_t) ( 0x50 | (r) ); \
452 asm_output1("push %s",gpn(r)); } while(0)
453
454 #define PUSHm(d,b) do { \
455 ALUm(0xff, 6, d, b); \
456 asm_output2("push %d(%s)",d,gpn(b)); } while(0)
457
458 #define POPr(r) do { \
459 underrunProtect(1); \
460 NanoAssert(((unsigned)r)<8); \
461 *(--_nIns) = (uint8_t) ( 0x58 | (r) ); \
462 asm_output1("pop %s",gpn(r)); } while(0)
463
464 #define JCC32 0x0f
465 #define JMP8 0xeb
466 #define JMP32 0xe9
467
468 #define JCC(o,t,isfar,n) do { \
469 underrunProtect(6); \
470 intptr_t tt = (intptr_t)t - (intptr_t)_nIns; \
471 if (isS8(tt) && !isfar) { \
472 verbose_only( NIns* next = _nIns; (void)next; ) \
473 _nIns -= 2; \
474 _nIns[0] = (uint8_t) ( 0x70 | (o) ); \
475 _nIns[1] = (uint8_t) (tt); \
476 asm_output2("%s %p",(n),(next+tt)); \
477 } else { \
478 verbose_only( NIns* next = _nIns; ) \
479 IMM32(tt); \
480 _nIns -= 2; \
481 _nIns[0] = JCC32; \
482 _nIns[1] = (uint8_t) ( 0x80 | (o) ); \
483 asm_output2("%s %p",(n),(next+tt)); \
484 } } while(0)
485
486 #define JMP_long(t) do { \
487 underrunProtect(5); \
488 intptr_t tt = (intptr_t)t - (intptr_t)_nIns; \
489 JMP_long_nochk_offset(tt); \
490 verbose_only( verbose_outputf(" %p:",_nIns); ) \
491 } while(0)
492
493 #define JMP(t) do { \
494 underrunProtect(5); \
495 intptr_t tt = (intptr_t)t - (intptr_t)_nIns; \
496 if (isS8(tt)) { \
497 verbose_only( NIns* next = _nIns; (void)next; ) \
498 _nIns -= 2; \
499 _nIns[0] = JMP8; \
500 _nIns[1] = (uint8_t) ( (tt)&0xff ); \
501 asm_output1("jmp %p",(next+tt)); \
502 } else { \
503 JMP_long_nochk_offset(tt); \
504 } } while(0)
505
506 // this should only be used when you can guarantee there is enough room on the page
507 #define JMP_long_nochk_offset(o) do {\
508 verbose_only( NIns* next = _nIns; (void)next; ) \
509 IMM32((o)); \
510 *(--_nIns) = JMP32; \
511 asm_output1("jmp %p",(next+(o))); } while(0)
512
513 #define JE(t, isfar) JCC(0x04, t, isfar, "je")
514 #define JNE(t, isfar) JCC(0x05, t, isfar, "jne")
515 #define JP(t, isfar) JCC(0x0A, t, isfar, "jp")
516 #define JNP(t, isfar) JCC(0x0B, t, isfar, "jnp")
517
518 #define JB(t, isfar) JCC(0x02, t, isfar, "jb")
519 #define JNB(t, isfar) JCC(0x03, t, isfar, "jnb")
520 #define JBE(t, isfar) JCC(0x06, t, isfar, "jbe")
521 #define JNBE(t, isfar) JCC(0x07, t, isfar, "jnbe")
522
523 #define JA(t, isfar) JCC(0x07, t, isfar, "ja")
524 #define JNA(t, isfar) JCC(0x06, t, isfar, "jna")
525 #define JAE(t, isfar) JCC(0x03, t, isfar, "jae")
526 #define JNAE(t, isfar) JCC(0x02, t, isfar, "jnae")
527
528 #define JL(t, isfar) JCC(0x0C, t, isfar, "jl")
529 #define JNL(t, isfar) JCC(0x0D, t, isfar, "jnl")
530 #define JLE(t, isfar) JCC(0x0E, t, isfar, "jle")
531 #define JNLE(t, isfar) JCC(0x0F, t, isfar, "jnle")
532
533 #define JG(t, isfar) JCC(0x0F, t, isfar, "jg")
534 #define JNG(t, isfar) JCC(0x0E, t, isfar, "jng")
535 #define JGE(t, isfar) JCC(0x0D, t, isfar, "jge")
536 #define JNGE(t, isfar) JCC(0x0C, t, isfar, "jnge")
537
538 #define JC(t, isfar) JCC(0x02, t, isfar, "jc")
539 #define JNC(t, isfar) JCC(0x03, t, isfar, "jnc")
540 #define JO(t, isfar) JCC(0x00, t, isfar, "jo")
541 #define JNO(t, isfar) JCC(0x01, t, isfar, "jno")
542
543 // sse instructions
544 #define SSE(c,d,s) \
545 underrunProtect(9); \
546 MODRM((d),(s)); \
547 _nIns -= 3; \
548 _nIns[0] = (uint8_t)(((c)>>16)&0xff); \
549 _nIns[1] = (uint8_t)(((c)>>8)&0xff); \
550 _nIns[2] = (uint8_t)((c)&0xff)
551
552 #define SSEm(c,r,d,b) \
553 underrunProtect(9); \
554 MODRMm((r),(d),(b)); \
555 _nIns -= 3; \
556 _nIns[0] = (uint8_t)(((c)>>16)&0xff); \
557 _nIns[1] = (uint8_t)(((c)>>8)&0xff); \
558 _nIns[2] = (uint8_t)((c)&0xff)
559
560 #define LDSD(r,d,b)do { \
561 SSEm(0xf20f10, (r)&7, (d), (b)); \
562 asm_output3("movsd %s,%d(%s)",gpn(r),(d),gpn(b)); \
563 } while(0)
564
565 #define LDSDm(r,addr)do { \
566 underrunProtect(8); \
567 const double* daddr = addr; \
568 IMM32(int32_t(daddr));\
569 *(--_nIns) = uint8_t(((r)&7)<<3|5); \
570 *(--_nIns) = 0x10;\
571 *(--_nIns) = 0x0f;\
572 *(--_nIns) = 0xf2;\
573 asm_output3("movsd %s,(#%p) // =%f",gpn(r),(void*)daddr,*daddr); \
574 } while(0)
575
576 #define STSD(d,b,r)do { \
577 SSEm(0xf20f11, (r)&7, (d), (b)); \
578 asm_output3("movsd %d(%s),%s",(d),gpn(b),gpn(r)); \
579 } while(0)
580
581 #define SSE_LDQ(r,d,b)do { \
582 SSEm(0xf30f7e, (r)&7, (d), (b)); \
583 asm_output3("movq %s,%d(%s)",gpn(r),d,gpn(b)); \
584 } while(0)
585
586 #define SSE_STQ(d,b,r)do { \
587 SSEm(0x660fd6, (r)&7, (d), (b)); \
588 asm_output3("movq %d(%s),%s",(d),gpn(b),gpn(r)); \
589 } while(0)
590
591 #define SSE_CVTSI2SD(xr,gr) do{ \
592 SSE(0xf20f2a, (xr)&7, (gr)&7); \
593 asm_output2("cvtsi2sd %s,%s",gpn(xr),gpn(gr)); \
594 } while(0)
595
596 #define CVTDQ2PD(dstr,srcr) do{ \
597 SSE(0xf30fe6, (dstr)&7, (srcr)&7); \
598 asm_output2("cvtdq2pd %s,%s",gpn(dstr),gpn(srcr)); \
599 } while(0)
600
601 // move and zero-extend gpreg to xmm reg
602 #define SSE_MOVD(d,s) do{ \
603 if (_is_xmm_reg_(s)) { \
604 NanoAssert(_is_gp_reg_(d)); \
605 SSE(0x660f7e, (s)&7, (d)&7); \
606 } else { \
607 NanoAssert(_is_gp_reg_(s)); \
608 NanoAssert(_is_xmm_reg_(d)); \
609 SSE(0x660f6e, (d)&7, (s)&7); \
610 } \
611 asm_output2("movd %s,%s",gpn(d),gpn(s)); \
612 } while(0)
613
614 #define SSE_MOVSD(rd,rs) do{ \
615 NanoAssert(_is_xmm_reg_(rd) && _is_xmm_reg_(rs));\
616 SSE(0xf20f10, (rd)&7, (rs)&7); \
617 asm_output2("movsd %s,%s",gpn(rd),gpn(rs)); \
618 } while(0)
619
620 #define SSE_MOVDm(d,b,xrs) do {\
621 NanoAssert(_is_xmm_reg_(xrs) && _is_gp_reg_(b));\
622 SSEm(0x660f7e, (xrs)&7, d, b);\
623 asm_output3("movd %d(%s),%s", d, gpn(b), gpn(xrs));\
624 } while(0)
625
626 #define SSE_ADDSD(rd,rs) do{ \
627 NanoAssert(_is_xmm_reg_(rd) && _is_xmm_reg_(rs));\
628 SSE(0xf20f58, (rd)&7, (rs)&7); \
629 asm_output2("addsd %s,%s",gpn(rd),gpn(rs)); \
630 } while(0)
631
632 #define SSE_ADDSDm(r,addr)do { \
633 underrunProtect(8); \
634 NanoAssert(_is_xmm_reg_(r));\
635 const double* daddr = addr; \
636 IMM32(int32_t(daddr));\
637 *(--_nIns) = uint8_t(((r)&7)<<3|5); \
638 *(--_nIns) = 0x58;\
639 *(--_nIns) = 0x0f;\
640 *(--_nIns) = 0xf2;\
641 asm_output3("addsd %s,%p // =%f",gpn(r),(void*)daddr,*daddr); \
642 } while(0)
643
644 #define SSE_SUBSD(rd,rs) do{ \
645 NanoAssert(_is_xmm_reg_(rd) && _is_xmm_reg_(rs));\
646 SSE(0xf20f5c, (rd)&7, (rs)&7); \
647 asm_output2("subsd %s,%s",gpn(rd),gpn(rs)); \
648 } while(0)
649 #define SSE_MULSD(rd,rs) do{ \
650 NanoAssert(_is_xmm_reg_(rd) && _is_xmm_reg_(rs));\
651 SSE(0xf20f59, (rd)&7, (rs)&7); \
652 asm_output2("mulsd %s,%s",gpn(rd),gpn(rs)); \
653 } while(0)
654 #define SSE_DIVSD(rd,rs) do{ \
655 NanoAssert(_is_xmm_reg_(rd) && _is_xmm_reg_(rs));\
656 SSE(0xf20f5e, (rd)&7, (rs)&7); \
657 asm_output2("divsd %s,%s",gpn(rd),gpn(rs)); \
658 } while(0)
659 #define SSE_UCOMISD(rl,rr) do{ \
660 NanoAssert(_is_xmm_reg_(rl) && _is_xmm_reg_(rr));\
661 SSE(0x660f2e, (rl)&7, (rr)&7); \
662 asm_output2("ucomisd %s,%s",gpn(rl),gpn(rr)); \
663 } while(0)
664
665 #define CVTSI2SDm(xr,d,b) do{ \
666 NanoAssert(_is_xmm_reg_(xr) && _is_gp_reg_(b));\
667 SSEm(0xf20f2a, (xr)&7, (d), (b)); \
668 asm_output3("cvtsi2sd %s,%d(%s)",gpn(xr),(d),gpn(b)); \
669 } while(0)
670
671 #define SSE_XORPD(r, maskaddr) do {\
672 underrunProtect(8); \
673 IMM32(maskaddr);\
674 *(--_nIns) = uint8_t(((r)&7)<<3|5); \
675 *(--_nIns) = 0x57;\
676 *(--_nIns) = 0x0f;\
677 *(--_nIns) = 0x66;\
678 asm_output2("xorpd %s,[0x%p]",gpn(r),(void*)(maskaddr));\
679 } while(0)
680
681 #define SSE_XORPDr(rd,rs) do{ \
682 SSE(0x660f57, (rd)&7, (rs)&7); \
683 asm_output2("xorpd %s,%s",gpn(rd),gpn(rs)); \
684 } while(0)
685
686 // floating point unit
687 #define FPUc(o) \
688 underrunProtect(2); \
689 *(--_nIns) = ((uint8_t)(o)&0xff); \
690 *(--_nIns) = (uint8_t)(((o)>>8)&0xff)
691
692 #define FPU(o,r) \
693 underrunProtect(2); \
694 *(--_nIns) = uint8_t(((uint8_t)(o)&0xff) | r&7);\
695 *(--_nIns) = (uint8_t)(((o)>>8)&0xff)
696
697 #define FPUm(o,d,b) \
698 underrunProtect(7); \
699 MODRMm((uint8_t)(o), d, b); \
700 *(--_nIns) = (uint8_t)((o)>>8)
701
702 #define TEST_AH(i) do { \
703 underrunProtect(3); \
704 *(--_nIns) = ((uint8_t)(i)); \
705 *(--_nIns) = 0xc4; \
706 *(--_nIns) = 0xf6; \
707 asm_output1("test ah, %d",i); } while(0)
708
709 #define TEST_AX(i) do { \
710 underrunProtect(5); \
711 *(--_nIns) = (0); \
712 *(--_nIns) = ((uint8_t)(i)); \
713 *(--_nIns) = ((uint8_t)((i)>>8)); \
714 *(--_nIns) = (0); \
715 *(--_nIns) = 0xa9; \
716 asm_output1("test ax, %d",i); } while(0)
717
718 #define FNSTSW_AX() do { FPUc(0xdfe0); asm_output("fnstsw_ax"); } while(0)
719 #define FCHS() do { FPUc(0xd9e0); asm_output("fchs"); } while(0)
720 #define FLD1() do { FPUc(0xd9e8); asm_output("fld1"); fpu_push(); } while(0)
721 #define FLDZ() do { FPUc(0xd9ee); asm_output("fldz"); fpu_push(); } while(0)
722 #define FFREE(r) do { FPU(0xddc0, r); asm_output1("ffree %s",fpn(r)); } while(0)
723 #define FSTQ(p,d,b) do { FPUm(0xdd02|(p), d, b); asm_output3("fst%sq %d(%s)",((p)?"p":""),d,gpn(b)); if (p) fpu_pop(); } while(0)
724 #define FSTPQ(d,b) FSTQ(1,d,b)
725 #define FCOM(p,d,b) do { FPUm(0xdc02|(p), d, b); asm_output3("fcom%s %d(%s)",((p)?"p":""),d,gpn(b)); if (p) fpu_pop(); } while(0)
726 #define FLDQ(d,b) do { FPUm(0xdd00, d, b); asm_output2("fldq %d(%s)",d,gpn(b)); fpu_push();} while(0)
727 #define FILDQ(d,b) do { FPUm(0xdf05, d, b); asm_output2("fildq %d(%s)",d,gpn(b)); fpu_push(); } while(0)
728 #define FILD(d,b) do { FPUm(0xdb00, d, b); asm_output2("fild %d(%s)",d,gpn(b)); fpu_push(); } while(0)
729 #define FADD(d,b) do { FPUm(0xdc00, d, b); asm_output2("fadd %d(%s)",d,gpn(b)); } while(0)
730 #define FSUB(d,b) do { FPUm(0xdc04, d, b); asm_output2("fsub %d(%s)",d,gpn(b)); } while(0)
731 #define FSUBR(d,b) do { FPUm(0xdc05, d, b); asm_output2("fsubr %d(%s)",d,gpn(b)); } while(0)
732 #define FMUL(d,b) do { FPUm(0xdc01, d, b); asm_output2("fmul %d(%s)",d,gpn(b)); } while(0)
733 #define FDIV(d,b) do { FPUm(0xdc06, d, b); asm_output2("fdiv %d(%s)",d,gpn(b)); } while(0)
734 #define FDIVR(d,b) do { FPUm(0xdc07, d, b); asm_output2("fdivr %d(%s)",d,gpn(b)); } while(0)
735 #define FINCSTP() do { FPUc(0xd9f7); asm_output2("fincstp"); } while(0)
736 #define FSTP(r) do { FPU(0xddd8, r&7); asm_output1("fstp %s",fpn(r)); fpu_pop();} while(0)
737 #define FCOMP() do { FPUc(0xD8D9); asm_output("fcomp"); fpu_pop();} while(0)
738 #define FCOMPP() do { FPUc(0xDED9); asm_output("fcompp"); fpu_pop();fpu_pop();} while(0)
739 #define FLDr(r) do { FPU(0xd9c0,r); asm_output1("fld %s",fpn(r)); fpu_push(); } while(0)
740 #define EMMS() do { FPUc(0x0f77); asm_output("emms"); } while (0)
741
742 // standard direct call
743 #define CALL(c) do { \
744 underrunProtect(5); \
745 int offset = (c->_address) - ((int)_nIns); \
746 IMM32( (uint32_t)offset ); \
747 *(--_nIns) = 0xE8; \
748 verbose_only(asm_output1("call %s",(c->_name));) \
749 debug_only(if ((c->_argtypes&3)==ARGSIZE_F) fpu_push();)\
750 } while (0)
751
752 // indirect call thru register
753 #define CALLr(c,r) do { \
754 underrunProtect(2);\
755 ALU(0xff, 2, (r));\
756 verbose_only(asm_output1("call %s",gpn(r));) \
757 debug_only(if ((c->_argtypes&3)==ARGSIZE_F) fpu_push();)\
758 } while (0)
759
760
761 }
762 #endif // __nanojit_Nativei386__

  ViewVC Help
Powered by ViewVC 1.1.24