source: webkit/trunk/JavaScriptCore/assembler/X86Assembler.h@ 38839

Last change on this file since 38839 was 38839, checked in by [email protected], 16 years ago

2008-11-29 Gavin Barraclough <[email protected]>

Reviewed by Camron Zwarich.

Add the class MacroAssembler to provide some abstraction of code generation,
and change WREC to make use of this class, rather than directly accessing
the X86Assembler.

This patch also allows WREC to be compiled without the rest of the JIT enabled.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • assembler/MacroAssembler.h: Added. (JSC::MacroAssembler::): (JSC::MacroAssembler::MacroAssembler): (JSC::MacroAssembler::copyCode): (JSC::MacroAssembler::Address::Address): (JSC::MacroAssembler::ImplicitAddress::ImplicitAddress): (JSC::MacroAssembler::BaseIndex::BaseIndex): (JSC::MacroAssembler::Label::Label): (JSC::MacroAssembler::Jump::Jump): (JSC::MacroAssembler::Jump::link): (JSC::MacroAssembler::Jump::linkTo): (JSC::MacroAssembler::JumpList::link): (JSC::MacroAssembler::JumpList::linkTo): (JSC::MacroAssembler::JumpList::append): (JSC::MacroAssembler::Imm32::Imm32): (JSC::MacroAssembler::add32): (JSC::MacroAssembler::or32): (JSC::MacroAssembler::sub32): (JSC::MacroAssembler::loadPtr): (JSC::MacroAssembler::load32): (JSC::MacroAssembler::load16): (JSC::MacroAssembler::storePtr): (JSC::MacroAssembler::store32): (JSC::MacroAssembler::pop): (JSC::MacroAssembler::push): (JSC::MacroAssembler::peek): (JSC::MacroAssembler::poke): (JSC::MacroAssembler::move): (JSC::MacroAssembler::compareImm32ForBranch): (JSC::MacroAssembler::compareImm32ForBranchEquality): (JSC::MacroAssembler::jae32): (JSC::MacroAssembler::je32): (JSC::MacroAssembler::je16): (JSC::MacroAssembler::jg32): (JSC::MacroAssembler::jge32): (JSC::MacroAssembler::jl32): (JSC::MacroAssembler::jle32): (JSC::MacroAssembler::jne32): (JSC::MacroAssembler::jump): (JSC::MacroAssembler::breakpoint): (JSC::MacroAssembler::ret):
  • assembler/X86Assembler.h: (JSC::X86Assembler::cmpw_rm):
  • interpreter/Interpreter.cpp: (JSC::Interpreter::Interpreter):
  • interpreter/Interpreter.h: (JSC::Interpreter::assemblerBuffer):
  • runtime/RegExp.cpp: (JSC::RegExp::RegExp):
  • wrec/WREC.cpp: (JSC::WREC::Generator::compileRegExp):
  • wrec/WREC.h:
  • wrec/WRECFunctors.cpp: (JSC::WREC::GeneratePatternCharacterFunctor::generateAtom): (JSC::WREC::GenerateCharacterClassFunctor::generateAtom): (JSC::WREC::GenerateBackreferenceFunctor::generateAtom): (JSC::WREC::GenerateParenthesesNonGreedyFunctor::generateAtom):
  • wrec/WRECFunctors.h: (JSC::WREC::GenerateParenthesesNonGreedyFunctor::GenerateParenthesesNonGreedyFunctor):
  • wrec/WRECGenerator.cpp: (JSC::WREC::Generator::generateEnter): (JSC::WREC::Generator::generateReturnSuccess): (JSC::WREC::Generator::generateSaveIndex): (JSC::WREC::Generator::generateIncrementIndex): (JSC::WREC::Generator::generateLoadCharacter): (JSC::WREC::Generator::generateJumpIfEndOfInput): (JSC::WREC::Generator::generateJumpIfNotEndOfInput): (JSC::WREC::Generator::generateReturnFailure): (JSC::WREC::Generator::generateBacktrack1): (JSC::WREC::Generator::generateBacktrackBackreference): (JSC::WREC::Generator::generateBackreferenceQuantifier): (JSC::WREC::Generator::generateNonGreedyQuantifier): (JSC::WREC::Generator::generateGreedyQuantifier): (JSC::WREC::Generator::generatePatternCharacter): (JSC::WREC::Generator::generateCharacterClassInvertedRange): (JSC::WREC::Generator::generateCharacterClassInverted): (JSC::WREC::Generator::generateCharacterClass): (JSC::WREC::Generator::generateParentheses): (JSC::WREC::Generator::generateParenthesesNonGreedy): (JSC::WREC::Generator::generateParenthesesResetTrampoline): (JSC::WREC::Generator::generateAssertionBOL): (JSC::WREC::Generator::generateAssertionEOL): (JSC::WREC::Generator::generateAssertionWordBoundary): (JSC::WREC::Generator::generateBackreference): (JSC::WREC::Generator::terminateAlternative): (JSC::WREC::Generator::terminateDisjunction):
  • wrec/WRECGenerator.h: (JSC::WREC::Generator::Generator):
  • wrec/WRECParser.cpp: (JSC::WREC::Parser::parsePatternCharacterQualifier): (JSC::WREC::Parser::parseCharacterClassQuantifier): (JSC::WREC::Parser::parseBackreferenceQuantifier): (JSC::WREC::Parser::parseParentheses): (JSC::WREC::Parser::parseCharacterClass): (JSC::WREC::Parser::parseOctalEscape): (JSC::WREC::Parser::parseEscape): (JSC::WREC::Parser::parseTerm): (JSC::WREC::Parser::parseDisjunction):
  • wrec/WRECParser.h: (JSC::WREC::Parser::Parser): (JSC::WREC::Parser::parsePattern): (JSC::WREC::Parser::parseAlternative):
  • wtf/Platform.h:
File size: 30.8 KB
Line 
1/*
2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef X86Assembler_h
27#define X86Assembler_h
28
29#include <wtf/Platform.h>
30
31#if ENABLE(ASSEMBLER) && PLATFORM(X86)
32
33#include "AssemblerBuffer.h"
34#include <stdint.h>
35#include <wtf/Assertions.h>
36#include <wtf/Vector.h>
37
38namespace JSC {
39
40#define MODRM(type, reg, rm) ((type << 6) | (reg << 3) | (rm))
41#define SIB(type, reg, rm) MODRM(type, reg, rm)
42#define CAN_SIGN_EXTEND_8_32(value) (value == ((int)(signed char)value))
43
44namespace X86 {
45 typedef enum {
46 eax,
47 ecx,
48 edx,
49 ebx,
50 esp,
51 ebp,
52 esi,
53 edi,
54
55 noBase = ebp,
56 hasSib = esp,
57 noScale = esp,
58 } RegisterID;
59
60 typedef enum {
61 xmm0,
62 xmm1,
63 xmm2,
64 xmm3,
65 xmm4,
66 xmm5,
67 xmm6,
68 xmm7,
69 } XMMRegisterID;
70}
71
72class X86Assembler {
73public:
74 typedef X86::RegisterID RegisterID;
75 typedef X86::XMMRegisterID XMMRegisterID;
76
77 typedef enum {
78 OP_ADD_EvGv = 0x01,
79 OP_ADD_GvEv = 0x03,
80 OP_OR_EvGv = 0x09,
81 OP_OR_GvEv = 0x0B,
82 OP_2BYTE_ESCAPE = 0x0F,
83 OP_AND_EvGv = 0x21,
84 OP_SUB_EvGv = 0x29,
85 OP_SUB_GvEv = 0x2B,
86 PRE_PREDICT_BRANCH_NOT_TAKEN = 0x2E,
87 OP_XOR_EvGv = 0x31,
88 OP_CMP_EvGv = 0x39,
89 OP_CMP_GvEv = 0x3B,
90 OP_PUSH_EAX = 0x50,
91 OP_POP_EAX = 0x58,
92 PRE_OPERAND_SIZE = 0x66,
93 PRE_SSE_66 = 0x66,
94 OP_PUSH_Iz = 0x68,
95 OP_IMUL_GvEvIz = 0x69,
96 OP_GROUP1_EvIz = 0x81,
97 OP_GROUP1_EvIb = 0x83,
98 OP_TEST_EvGv = 0x85,
99 OP_MOV_EvGv = 0x89,
100 OP_MOV_GvEv = 0x8B,
101 OP_LEA = 0x8D,
102 OP_GROUP1A_Ev = 0x8F,
103 OP_CDQ = 0x99,
104 OP_SETE = 0x94,
105 OP_SETNE = 0x95,
106 OP_GROUP2_EvIb = 0xC1,
107 OP_RET = 0xC3,
108 OP_GROUP11_EvIz = 0xC7,
109 OP_INT3 = 0xCC,
110 OP_GROUP2_Ev1 = 0xD1,
111 OP_GROUP2_EvCL = 0xD3,
112 OP_CALL_rel32 = 0xE8,
113 OP_JMP_rel32 = 0xE9,
114 PRE_SSE_F2 = 0xF2,
115 OP_HLT = 0xF4,
116 OP_GROUP3_Ev = 0xF7,
117 OP_GROUP3_EvIz = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test.
118 OP_GROUP5_Ev = 0xFF,
119
120 OP2_MOVSD_VsdWsd = 0x10,
121 OP2_MOVSD_WsdVsd = 0x11,
122 OP2_CVTSI2SD_VsdEd = 0x2A,
123 OP2_CVTTSD2SI_GdWsd = 0x2C,
124 OP2_UCOMISD_VsdWsd = 0x2E,
125 OP2_XORPD_VsdWsd = 0x57,
126 OP2_ADDSD_VsdWsd = 0x58,
127 OP2_MULSD_VsdWsd = 0x59,
128 OP2_SUBSD_VsdWsd = 0x5C,
129 OP2_MOVD_EdVd = 0x7E,
130 OP2_JO_rel32 = 0x80,
131 OP2_JB_rel32 = 0x82,
132 OP2_JAE_rel32 = 0x83,
133 OP2_JE_rel32 = 0x84,
134 OP2_JNE_rel32 = 0x85,
135 OP2_JBE_rel32 = 0x86,
136 OP2_JA_rel32 = 0x87,
137 OP2_JS_rel32 = 0x88,
138 OP2_JP_rel32 = 0x8A,
139 OP2_JL_rel32 = 0x8C,
140 OP2_JGE_rel32 = 0x8D,
141 OP2_JLE_rel32 = 0x8E,
142 OP2_JG_rel32 = 0x8F,
143 OP2_IMUL_GvEv = 0xAF,
144 OP2_MOVZX_GvEb = 0xB6,
145 OP2_MOVZX_GvEw = 0xB7,
146 OP2_PEXTRW_GdUdIb = 0xC5,
147
148 GROUP1_OP_ADD = 0,
149 GROUP1_OP_OR = 1,
150 GROUP1_OP_AND = 4,
151 GROUP1_OP_SUB = 5,
152 GROUP1_OP_XOR = 6,
153 GROUP1_OP_CMP = 7,
154
155 GROUP1A_OP_POP = 0,
156
157 GROUP2_OP_SHL = 4,
158 GROUP2_OP_SAR = 7,
159
160 GROUP3_OP_TEST = 0,
161 GROUP3_OP_NEG = 3,
162 GROUP3_OP_IDIV = 7,
163
164 GROUP5_OP_CALLN = 2,
165 GROUP5_OP_JMPN = 4,
166 GROUP5_OP_PUSH = 6,
167
168 GROUP11_MOV = 0,
169 } OpcodeID;
170
171 // Opaque label types
172
173 class JmpSrc {
174 friend class X86Assembler;
175 public:
176 JmpSrc()
177 : m_offset(-1)
178 {
179 }
180
181 private:
182 JmpSrc(int offset)
183 : m_offset(offset)
184 {
185 }
186
187 int m_offset;
188 };
189
190 class JmpDst {
191 friend class X86Assembler;
192 public:
193 JmpDst()
194 : m_offset(-1)
195 {
196 }
197
198 private:
199 JmpDst(int offset)
200 : m_offset(offset)
201 {
202 }
203
204 int m_offset;
205 };
206
207 static const int maxInstructionSize = 16;
208
209 X86Assembler(AssemblerBuffer* m_buffer)
210 : m_buffer(m_buffer)
211 {
212 m_buffer->reset();
213 }
214
215 void int3()
216 {
217 m_buffer->putByte(OP_INT3);
218 }
219
220 void pushl_r(RegisterID reg)
221 {
222 m_buffer->putByte(OP_PUSH_EAX + reg);
223 }
224
225 void pushl_m(int offset, RegisterID base)
226 {
227 m_buffer->putByte(OP_GROUP5_Ev);
228 modRm_opm(GROUP5_OP_PUSH, base, offset);
229 }
230
231 void pushl_i32(int imm)
232 {
233 m_buffer->putByte(OP_PUSH_Iz);
234 m_buffer->putInt(imm);
235 }
236
237 void popl_r(RegisterID reg)
238 {
239 m_buffer->putByte(OP_POP_EAX + reg);
240 }
241
242 void popl_m(int offset, RegisterID base)
243 {
244 m_buffer->putByte(OP_GROUP1A_Ev);
245 modRm_opm(GROUP1A_OP_POP, base, offset);
246 }
247
248 void movl_rr(RegisterID src, RegisterID dst)
249 {
250 m_buffer->putByte(OP_MOV_EvGv);
251 modRm_rr(src, dst);
252 }
253
254 void addl_rr(RegisterID src, RegisterID dst)
255 {
256 m_buffer->putByte(OP_ADD_EvGv);
257 modRm_rr(src, dst);
258 }
259
260 void addl_i8r(int imm, RegisterID dst)
261 {
262 m_buffer->putByte(OP_GROUP1_EvIb);
263 modRm_opr(GROUP1_OP_ADD, dst);
264 m_buffer->putByte(imm);
265 }
266
267 void addl_i8m(int imm, void* addr)
268 {
269 m_buffer->putByte(OP_GROUP1_EvIb);
270 modRm_opm(GROUP1_OP_ADD, addr);
271 m_buffer->putByte(imm);
272 }
273
274 void addl_i32r(int imm, RegisterID dst)
275 {
276 m_buffer->putByte(OP_GROUP1_EvIz);
277 modRm_opr(GROUP1_OP_ADD, dst);
278 m_buffer->putInt(imm);
279 }
280
281 void addl_mr(int offset, RegisterID base, RegisterID dst)
282 {
283 m_buffer->putByte(OP_ADD_GvEv);
284 modRm_rm(dst, base, offset);
285 }
286
287 void andl_rr(RegisterID src, RegisterID dst)
288 {
289 m_buffer->putByte(OP_AND_EvGv);
290 modRm_rr(src, dst);
291 }
292
293 void andl_i32r(int imm, RegisterID dst)
294 {
295 m_buffer->putByte(OP_GROUP1_EvIz);
296 modRm_opr(GROUP1_OP_AND, dst);
297 m_buffer->putInt(imm);
298 }
299
300 void cmpl_i8r(int imm, RegisterID dst)
301 {
302 m_buffer->putByte(OP_GROUP1_EvIb);
303 modRm_opr(GROUP1_OP_CMP, dst);
304 m_buffer->putByte(imm);
305 }
306
307 void cmpl_rr(RegisterID src, RegisterID dst)
308 {
309 m_buffer->putByte(OP_CMP_EvGv);
310 modRm_rr(src, dst);
311 }
312
313 void cmpl_rm(RegisterID src, int offset, RegisterID base)
314 {
315 m_buffer->putByte(OP_CMP_EvGv);
316 modRm_rm(src, base, offset);
317 }
318
319 void cmpl_mr(int offset, RegisterID base, RegisterID dst)
320 {
321 m_buffer->putByte(OP_CMP_GvEv);
322 modRm_rm(dst, base, offset);
323 }
324
325 void cmpl_i32r(int imm, RegisterID dst)
326 {
327 m_buffer->putByte(OP_GROUP1_EvIz);
328 modRm_opr(GROUP1_OP_CMP, dst);
329 m_buffer->putInt(imm);
330 }
331
332 void cmpl_i32m(int imm, RegisterID dst)
333 {
334 m_buffer->putByte(OP_GROUP1_EvIz);
335 modRm_opm(GROUP1_OP_CMP, dst);
336 m_buffer->putInt(imm);
337 }
338
339 void cmpl_i32m(int imm, int offset, RegisterID dst)
340 {
341 m_buffer->putByte(OP_GROUP1_EvIz);
342 modRm_opm(GROUP1_OP_CMP, dst, offset);
343 m_buffer->putInt(imm);
344 }
345
346 void cmpl_i32m(int imm, void* addr)
347 {
348 m_buffer->putByte(OP_GROUP1_EvIz);
349 modRm_opm(GROUP1_OP_CMP, addr);
350 m_buffer->putInt(imm);
351 }
352
353 void cmpl_i8m(int imm, int offset, RegisterID base, RegisterID index, int scale)
354 {
355 m_buffer->putByte(OP_GROUP1_EvIb);
356 modRm_opmsib(GROUP1_OP_CMP, base, index, scale, offset);
357 m_buffer->putByte(imm);
358 }
359
360 void cmpw_rm(RegisterID src, RegisterID base, RegisterID index, int scale)
361 {
362 m_buffer->putByte(PRE_OPERAND_SIZE);
363 m_buffer->putByte(OP_CMP_EvGv);
364 modRm_rmsib(src, base, index, scale);
365 }
366
367 void cmpw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
368 {
369 m_buffer->putByte(PRE_OPERAND_SIZE);
370 m_buffer->putByte(OP_CMP_EvGv);
371 modRm_rmsib(src, base, index, scale, offset);
372 }
373
374 void sete_r(RegisterID dst)
375 {
376 m_buffer->putByte(OP_2BYTE_ESCAPE);
377 m_buffer->putByte(OP_SETE);
378 m_buffer->putByte(MODRM(3, 0, dst));
379 }
380
381 void setz_r(RegisterID dst)
382 {
383 sete_r(dst);
384 }
385
386 void setne_r(RegisterID dst)
387 {
388 m_buffer->putByte(OP_2BYTE_ESCAPE);
389 m_buffer->putByte(OP_SETNE);
390 m_buffer->putByte(MODRM(3, 0, dst));
391 }
392
393 void setnz_r(RegisterID dst)
394 {
395 setne_r(dst);
396 }
397
398 void orl_rr(RegisterID src, RegisterID dst)
399 {
400 m_buffer->putByte(OP_OR_EvGv);
401 modRm_rr(src, dst);
402 }
403
404 void orl_mr(int offset, RegisterID base, RegisterID dst)
405 {
406 m_buffer->putByte(OP_OR_GvEv);
407 modRm_rm(dst, base, offset);
408 }
409
410 void orl_i32r(int imm, RegisterID dst)
411 {
412 m_buffer->putByte(OP_GROUP1_EvIb);
413 modRm_opr(GROUP1_OP_OR, dst);
414 m_buffer->putByte(imm);
415 }
416
417 void subl_rr(RegisterID src, RegisterID dst)
418 {
419 m_buffer->putByte(OP_SUB_EvGv);
420 modRm_rr(src, dst);
421 }
422
423 void subl_i8r(int imm, RegisterID dst)
424 {
425 m_buffer->putByte(OP_GROUP1_EvIb);
426 modRm_opr(GROUP1_OP_SUB, dst);
427 m_buffer->putByte(imm);
428 }
429
430 void subl_i8m(int imm, void* addr)
431 {
432 m_buffer->putByte(OP_GROUP1_EvIb);
433 modRm_opm(GROUP1_OP_SUB, addr);
434 m_buffer->putByte(imm);
435 }
436
437 void subl_i32r(int imm, RegisterID dst)
438 {
439 m_buffer->putByte(OP_GROUP1_EvIz);
440 modRm_opr(GROUP1_OP_SUB, dst);
441 m_buffer->putInt(imm);
442 }
443
444 void subl_mr(int offset, RegisterID base, RegisterID dst)
445 {
446 m_buffer->putByte(OP_SUB_GvEv);
447 modRm_rm(dst, base, offset);
448 }
449
450 void testl_i32r(int imm, RegisterID dst)
451 {
452 m_buffer->ensureSpace(maxInstructionSize);
453 m_buffer->putByteUnchecked(OP_GROUP3_EvIz);
454 modRm_opr_Unchecked(GROUP3_OP_TEST, dst);
455 m_buffer->putIntUnchecked(imm);
456 }
457
458 void testl_i32m(int imm, RegisterID dst)
459 {
460 m_buffer->putByte(OP_GROUP3_EvIz);
461 modRm_opm(GROUP3_OP_TEST, dst);
462 m_buffer->putInt(imm);
463 }
464
465 void testl_i32m(int imm, int offset, RegisterID dst)
466 {
467 m_buffer->putByte(OP_GROUP3_EvIz);
468 modRm_opm(GROUP3_OP_TEST, dst, offset);
469 m_buffer->putInt(imm);
470 }
471
472 void testl_rr(RegisterID src, RegisterID dst)
473 {
474 m_buffer->putByte(OP_TEST_EvGv);
475 modRm_rr(src, dst);
476 }
477
478 void xorl_i8r(int imm, RegisterID dst)
479 {
480 m_buffer->putByte(OP_GROUP1_EvIb);
481 modRm_opr(GROUP1_OP_XOR, dst);
482 m_buffer->putByte(imm);
483 }
484
485 void xorl_rr(RegisterID src, RegisterID dst)
486 {
487 m_buffer->putByte(OP_XOR_EvGv);
488 modRm_rr(src, dst);
489 }
490
491 void sarl_i8r(int imm, RegisterID dst)
492 {
493 if (imm == 1) {
494 m_buffer->putByte(OP_GROUP2_Ev1);
495 modRm_opr(GROUP2_OP_SAR, dst);
496 } else {
497 m_buffer->putByte(OP_GROUP2_EvIb);
498 modRm_opr(GROUP2_OP_SAR, dst);
499 m_buffer->putByte(imm);
500 }
501 }
502
503 void sarl_CLr(RegisterID dst)
504 {
505 m_buffer->putByte(OP_GROUP2_EvCL);
506 modRm_opr(GROUP2_OP_SAR, dst);
507 }
508
509 void shl_i8r(int imm, RegisterID dst)
510 {
511 if (imm == 1) {
512 m_buffer->putByte(OP_GROUP2_Ev1);
513 modRm_opr(GROUP2_OP_SHL, dst);
514 } else {
515 m_buffer->putByte(OP_GROUP2_EvIb);
516 modRm_opr(GROUP2_OP_SHL, dst);
517 m_buffer->putByte(imm);
518 }
519 }
520
521 void shll_CLr(RegisterID dst)
522 {
523 m_buffer->putByte(OP_GROUP2_EvCL);
524 modRm_opr(GROUP2_OP_SHL, dst);
525 }
526
527 void imull_rr(RegisterID src, RegisterID dst)
528 {
529 m_buffer->putByte(OP_2BYTE_ESCAPE);
530 m_buffer->putByte(OP2_IMUL_GvEv);
531 modRm_rr(dst, src);
532 }
533
534 void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
535 {
536 m_buffer->putByte(OP_IMUL_GvEvIz);
537 modRm_rr(dst, src);
538 m_buffer->putInt(value);
539 }
540
541 void idivl_r(RegisterID dst)
542 {
543 m_buffer->putByte(OP_GROUP3_Ev);
544 modRm_opr(GROUP3_OP_IDIV, dst);
545 }
546
547 void negl_r(RegisterID dst)
548 {
549 m_buffer->putByte(OP_GROUP3_Ev);
550 modRm_opr(GROUP3_OP_NEG, dst);
551 }
552
553 void cdq()
554 {
555 m_buffer->putByte(OP_CDQ);
556 }
557
558 void movl_mr(RegisterID base, RegisterID dst)
559 {
560 m_buffer->putByte(OP_MOV_GvEv);
561 modRm_rm(dst, base);
562 }
563
564 void movl_mr(int offset, RegisterID base, RegisterID dst)
565 {
566 m_buffer->ensureSpace(maxInstructionSize);
567 m_buffer->putByteUnchecked(OP_MOV_GvEv);
568 modRm_rm_Unchecked(dst, base, offset);
569 }
570
571 void movl_mr(void* addr, RegisterID dst)
572 {
573 m_buffer->putByte(OP_MOV_GvEv);
574 modRm_rm(dst, addr);
575 }
576
577 void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
578 {
579 m_buffer->putByte(OP_MOV_GvEv);
580 modRm_rmsib(dst, base, index, scale, offset);
581 }
582
583 void movzbl_rr(RegisterID src, RegisterID dst)
584 {
585 m_buffer->putByte(OP_2BYTE_ESCAPE);
586 m_buffer->putByte(OP2_MOVZX_GvEb);
587 modRm_rr(dst, src);
588 }
589
590 void movzwl_mr(int offset, RegisterID base, RegisterID dst)
591 {
592 m_buffer->putByte(OP_2BYTE_ESCAPE);
593 m_buffer->putByte(OP2_MOVZX_GvEw);
594 modRm_rm(dst, base, offset);
595 }
596
597 void movzwl_mr(RegisterID base, RegisterID index, int scale, RegisterID dst)
598 {
599 m_buffer->putByte(OP_2BYTE_ESCAPE);
600 m_buffer->putByte(OP2_MOVZX_GvEw);
601 modRm_rmsib(dst, base, index, scale);
602 }
603
604 void movzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
605 {
606 m_buffer->putByte(OP_2BYTE_ESCAPE);
607 m_buffer->putByte(OP2_MOVZX_GvEw);
608 modRm_rmsib(dst, base, index, scale, offset);
609 }
610
611 void movl_rm(RegisterID src, RegisterID base)
612 {
613 m_buffer->putByte(OP_MOV_EvGv);
614 modRm_rm(src, base);
615 }
616
617 void movl_rm(RegisterID src, int offset, RegisterID base)
618 {
619 m_buffer->ensureSpace(maxInstructionSize);
620 m_buffer->putByteUnchecked(OP_MOV_EvGv);
621 modRm_rm_Unchecked(src, base, offset);
622 }
623
624 void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
625 {
626 m_buffer->putByte(OP_MOV_EvGv);
627 modRm_rmsib(src, base, index, scale, offset);
628 }
629
630 void movl_i32r(int imm, RegisterID dst)
631 {
632 m_buffer->putByte(OP_GROUP11_EvIz);
633 modRm_opr(GROUP11_MOV, dst);
634 m_buffer->putInt(imm);
635 }
636
637 void movl_i32m(int imm, int offset, RegisterID base)
638 {
639 m_buffer->ensureSpace(maxInstructionSize);
640 m_buffer->putByteUnchecked(OP_GROUP11_EvIz);
641 modRm_opm_Unchecked(GROUP11_MOV, base, offset);
642 m_buffer->putIntUnchecked(imm);
643 }
644
645 void movl_i32m(int imm, void* addr)
646 {
647 m_buffer->putByte(OP_GROUP11_EvIz);
648 modRm_opm(GROUP11_MOV, addr);
649 m_buffer->putInt(imm);
650 }
651
652 void leal_mr(int offset, RegisterID base, RegisterID dst)
653 {
654 m_buffer->putByte(OP_LEA);
655 modRm_rm(dst, base, offset);
656 }
657
658 void leal_mr(int offset, RegisterID index, int scale, RegisterID dst)
659 {
660 m_buffer->putByte(OP_LEA);
661 modRm_rmsib(dst, X86::noBase, index, scale, offset);
662 }
663
664 void ret()
665 {
666 m_buffer->putByte(OP_RET);
667 }
668
669 void jmp_r(RegisterID dst)
670 {
671 m_buffer->putByte(OP_GROUP5_Ev);
672 modRm_opr(GROUP5_OP_JMPN, dst);
673 }
674
675 void jmp_m(int offset, RegisterID base)
676 {
677 m_buffer->putByte(OP_GROUP5_Ev);
678 modRm_opm(GROUP5_OP_JMPN, base, offset);
679 }
680
681 void movsd_mr(int offset, RegisterID base, XMMRegisterID dst)
682 {
683 m_buffer->putByte(PRE_SSE_F2);
684 m_buffer->putByte(OP_2BYTE_ESCAPE);
685 m_buffer->putByte(OP2_MOVSD_VsdWsd);
686 modRm_rm((RegisterID)dst, base, offset);
687 }
688
689 void xorpd_mr(void* addr, XMMRegisterID dst)
690 {
691 m_buffer->putByte(PRE_SSE_66);
692 m_buffer->putByte(OP_2BYTE_ESCAPE);
693 m_buffer->putByte(OP2_XORPD_VsdWsd);
694 modRm_rm((RegisterID)dst, addr);
695 }
696
697 void movsd_rm(XMMRegisterID src, int offset, RegisterID base)
698 {
699 m_buffer->putByte(PRE_SSE_F2);
700 m_buffer->putByte(OP_2BYTE_ESCAPE);
701 m_buffer->putByte(OP2_MOVSD_WsdVsd);
702 modRm_rm((RegisterID)src, base, offset);
703 }
704
705 void movd_rr(XMMRegisterID src, RegisterID dst)
706 {
707 m_buffer->putByte(PRE_SSE_66);
708 m_buffer->putByte(OP_2BYTE_ESCAPE);
709 m_buffer->putByte(OP2_MOVD_EdVd);
710 modRm_rr((RegisterID)src, dst);
711 }
712
713 void cvtsi2sd_rr(RegisterID src, XMMRegisterID dst)
714 {
715 m_buffer->putByte(PRE_SSE_F2);
716 m_buffer->putByte(OP_2BYTE_ESCAPE);
717 m_buffer->putByte(OP2_CVTSI2SD_VsdEd);
718 modRm_rr((RegisterID)dst, src);
719 }
720
721 void cvttsd2si_rr(XMMRegisterID src, RegisterID dst)
722 {
723 m_buffer->putByte(PRE_SSE_F2);
724 m_buffer->putByte(OP_2BYTE_ESCAPE);
725 m_buffer->putByte(OP2_CVTTSD2SI_GdWsd);
726 modRm_rr(dst, (RegisterID)src);
727 }
728
729 void addsd_mr(int offset, RegisterID base, XMMRegisterID dst)
730 {
731 m_buffer->putByte(PRE_SSE_F2);
732 m_buffer->putByte(OP_2BYTE_ESCAPE);
733 m_buffer->putByte(OP2_ADDSD_VsdWsd);
734 modRm_rm((RegisterID)dst, base, offset);
735 }
736
737 void subsd_mr(int offset, RegisterID base, XMMRegisterID dst)
738 {
739 m_buffer->putByte(PRE_SSE_F2);
740 m_buffer->putByte(OP_2BYTE_ESCAPE);
741 m_buffer->putByte(OP2_SUBSD_VsdWsd);
742 modRm_rm((RegisterID)dst, base, offset);
743 }
744
745 void mulsd_mr(int offset, RegisterID base, XMMRegisterID dst)
746 {
747 m_buffer->putByte(PRE_SSE_F2);
748 m_buffer->putByte(OP_2BYTE_ESCAPE);
749 m_buffer->putByte(OP2_MULSD_VsdWsd);
750 modRm_rm((RegisterID)dst, base, offset);
751 }
752
753 void addsd_rr(XMMRegisterID src, XMMRegisterID dst)
754 {
755 m_buffer->putByte(PRE_SSE_F2);
756 m_buffer->putByte(OP_2BYTE_ESCAPE);
757 m_buffer->putByte(OP2_ADDSD_VsdWsd);
758 modRm_rr((RegisterID)dst, (RegisterID)src);
759 }
760
761 void subsd_rr(XMMRegisterID src, XMMRegisterID dst)
762 {
763 m_buffer->putByte(PRE_SSE_F2);
764 m_buffer->putByte(OP_2BYTE_ESCAPE);
765 m_buffer->putByte(OP2_SUBSD_VsdWsd);
766 modRm_rr((RegisterID)dst, (RegisterID)src);
767 }
768
769 void mulsd_rr(XMMRegisterID src, XMMRegisterID dst)
770 {
771 m_buffer->putByte(PRE_SSE_F2);
772 m_buffer->putByte(OP_2BYTE_ESCAPE);
773 m_buffer->putByte(OP2_MULSD_VsdWsd);
774 modRm_rr((RegisterID)dst, (RegisterID)src);
775 }
776
777 void ucomis_rr(XMMRegisterID src, XMMRegisterID dst)
778 {
779 m_buffer->putByte(PRE_SSE_66);
780 m_buffer->putByte(OP_2BYTE_ESCAPE);
781 m_buffer->putByte(OP2_UCOMISD_VsdWsd);
782 modRm_rr((RegisterID)dst, (RegisterID)src);
783 }
784
785 void pextrw_irr(int whichWord, XMMRegisterID src, RegisterID dst)
786 {
787 m_buffer->putByte(PRE_SSE_66);
788 m_buffer->putByte(OP_2BYTE_ESCAPE);
789 m_buffer->putByte(OP2_PEXTRW_GdUdIb);
790 modRm_rr(dst, (RegisterID)src);
791 m_buffer->putByte(whichWord);
792 }
793
794 JmpSrc call()
795 {
796 m_buffer->putByte(OP_CALL_rel32);
797 m_buffer->putInt(0); // FIXME: make this point to a global label, linked later.
798 return JmpSrc(m_buffer->size());
799 }
800
801 JmpSrc call(RegisterID dst)
802 {
803 m_buffer->putByte(OP_GROUP5_Ev);
804 modRm_opr(GROUP5_OP_CALLN, dst);
805 return JmpSrc(m_buffer->size());
806 }
807
808 JmpDst label()
809 {
810 return JmpDst(m_buffer->size());
811 }
812
813 JmpDst align(int alignment)
814 {
815 while (!m_buffer->isAligned(alignment))
816 m_buffer->putByte(OP_HLT);
817
818 return label();
819 }
820
821 JmpSrc jmp()
822 {
823 m_buffer->putByte(OP_JMP_rel32);
824 m_buffer->putInt(0);
825 return JmpSrc(m_buffer->size());
826 }
827
828 JmpSrc jne()
829 {
830 m_buffer->putByte(OP_2BYTE_ESCAPE);
831 m_buffer->putByte(OP2_JNE_rel32);
832 m_buffer->putInt(0);
833 return JmpSrc(m_buffer->size());
834 }
835
836 JmpSrc jnz()
837 {
838 return jne();
839 }
840
841 JmpSrc je()
842 {
843 m_buffer->ensureSpace(maxInstructionSize);
844 m_buffer->putByteUnchecked(OP_2BYTE_ESCAPE);
845 m_buffer->putByteUnchecked(OP2_JE_rel32);
846 m_buffer->putIntUnchecked(0);
847 return JmpSrc(m_buffer->size());
848 }
849
850 JmpSrc jl()
851 {
852 m_buffer->putByte(OP_2BYTE_ESCAPE);
853 m_buffer->putByte(OP2_JL_rel32);
854 m_buffer->putInt(0);
855 return JmpSrc(m_buffer->size());
856 }
857
858 JmpSrc jb()
859 {
860 m_buffer->putByte(OP_2BYTE_ESCAPE);
861 m_buffer->putByte(OP2_JB_rel32);
862 m_buffer->putInt(0);
863 return JmpSrc(m_buffer->size());
864 }
865
866 JmpSrc jle()
867 {
868 m_buffer->putByte(OP_2BYTE_ESCAPE);
869 m_buffer->putByte(OP2_JLE_rel32);
870 m_buffer->putInt(0);
871 return JmpSrc(m_buffer->size());
872 }
873
874 JmpSrc jbe()
875 {
876 m_buffer->putByte(OP_2BYTE_ESCAPE);
877 m_buffer->putByte(OP2_JBE_rel32);
878 m_buffer->putInt(0);
879 return JmpSrc(m_buffer->size());
880 }
881
882 JmpSrc jge()
883 {
884 m_buffer->putByte(OP_2BYTE_ESCAPE);
885 m_buffer->putByte(OP2_JGE_rel32);
886 m_buffer->putInt(0);
887 return JmpSrc(m_buffer->size());
888 }
889
890 JmpSrc jg()
891 {
892 m_buffer->putByte(OP_2BYTE_ESCAPE);
893 m_buffer->putByte(OP2_JG_rel32);
894 m_buffer->putInt(0);
895 return JmpSrc(m_buffer->size());
896 }
897
898 JmpSrc ja()
899 {
900 m_buffer->putByte(OP_2BYTE_ESCAPE);
901 m_buffer->putByte(OP2_JA_rel32);
902 m_buffer->putInt(0);
903 return JmpSrc(m_buffer->size());
904 }
905
906 JmpSrc jae()
907 {
908 m_buffer->putByte(OP_2BYTE_ESCAPE);
909 m_buffer->putByte(OP2_JAE_rel32);
910 m_buffer->putInt(0);
911 return JmpSrc(m_buffer->size());
912 }
913
914 JmpSrc jo()
915 {
916 m_buffer->putByte(OP_2BYTE_ESCAPE);
917 m_buffer->putByte(OP2_JO_rel32);
918 m_buffer->putInt(0);
919 return JmpSrc(m_buffer->size());
920 }
921
922 JmpSrc jp()
923 {
924 m_buffer->putByte(OP_2BYTE_ESCAPE);
925 m_buffer->putByte(OP2_JP_rel32);
926 m_buffer->putInt(0);
927 return JmpSrc(m_buffer->size());
928 }
929
930 JmpSrc js()
931 {
932 m_buffer->putByte(OP_2BYTE_ESCAPE);
933 m_buffer->putByte(OP2_JS_rel32);
934 m_buffer->putInt(0);
935 return JmpSrc(m_buffer->size());
936 }
937
938 void predictNotTaken()
939 {
940 m_buffer->putByte(PRE_PREDICT_BRANCH_NOT_TAKEN);
941 }
942
943 void link(JmpSrc from, JmpDst to)
944 {
945 ASSERT(to.m_offset != -1);
946 ASSERT(from.m_offset != -1);
947
948 reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(m_buffer->data()) + from.m_offset)[-1] = to.m_offset - from.m_offset;
949 }
950
951 static void linkAbsoluteAddress(void* code, JmpDst useOffset, JmpDst address)
952 {
953 ASSERT(useOffset.m_offset != -1);
954 ASSERT(address.m_offset != -1);
955
956 reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(code) + useOffset.m_offset)[-1] = reinterpret_cast<ptrdiff_t>(code) + address.m_offset;
957 }
958
959 static void link(void* code, JmpSrc from, void* to)
960 {
961 ASSERT(from.m_offset != -1);
962
963 reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(code) + from.m_offset)[-1] = reinterpret_cast<ptrdiff_t>(to) - (reinterpret_cast<ptrdiff_t>(code) + from.m_offset);
964 }
965
966 static void* getRelocatedAddress(void* code, JmpSrc jump)
967 {
968 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
969 }
970
971 static void* getRelocatedAddress(void* code, JmpDst jump)
972 {
973 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
974 }
975
976 static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
977 {
978 return dst.m_offset - src.m_offset;
979 }
980
981 static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
982 {
983 return dst.m_offset - src.m_offset;
984 }
985
986 static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
987 {
988 return dst.m_offset - src.m_offset;
989 }
990
991 static void repatchImmediate(intptr_t where, int32_t value)
992 {
993 reinterpret_cast<int32_t*>(where)[-1] = value;
994 }
995
996 static void repatchDisplacement(intptr_t where, intptr_t value)
997 {
998 reinterpret_cast<intptr_t*>(where)[-1] = value;
999 }
1000
1001 static void repatchBranchOffset(intptr_t where, void* destination)
1002 {
1003 reinterpret_cast<intptr_t*>(where)[-1] = (reinterpret_cast<intptr_t>(destination) - where);
1004 }
1005
1006 void* executableCopy()
1007 {
1008 void* copy = m_buffer->executableCopy();
1009 ASSERT(copy);
1010 return copy;
1011 }
1012
1013#if USE(CTI_ARGUMENT)
1014 void restoreArgumentReference()
1015 {
1016#if USE(FAST_CALL_CTI_ARGUMENT)
1017 movl_rr(X86::esp, X86::ecx);
1018#else
1019 movl_rm(X86::esp, 0, X86::esp);
1020#endif
1021 }
1022
1023 void restoreArgumentReferenceForTrampoline()
1024 {
1025#if USE(FAST_CALL_CTI_ARGUMENT)
1026 movl_rr(X86::esp, X86::ecx);
1027 addl_i32r(4, X86::ecx);
1028#endif
1029 }
1030#else
1031 void restoreArgumentReference() {}
1032 void restoreArgumentReferenceForTrampoline() {}
1033#endif
1034
1035private:
1036 void modRm_rr(RegisterID reg, RegisterID rm)
1037 {
1038 m_buffer->ensureSpace(maxInstructionSize);
1039 modRm_rr_Unchecked(reg, rm);
1040 }
1041
1042 void modRm_rr_Unchecked(RegisterID reg, RegisterID rm)
1043 {
1044 m_buffer->putByteUnchecked(MODRM(3, reg, rm));
1045 }
1046
1047 void modRm_rm(RegisterID reg, void* addr)
1048 {
1049 m_buffer->putByte(MODRM(0, reg, X86::noBase));
1050 m_buffer->putInt((int)addr);
1051 }
1052
1053 void modRm_rm(RegisterID reg, RegisterID base)
1054 {
1055 if (base == X86::esp) {
1056 m_buffer->putByte(MODRM(0, reg, X86::hasSib));
1057 m_buffer->putByte(SIB(0, X86::noScale, X86::esp));
1058 } else
1059 m_buffer->putByte(MODRM(0, reg, base));
1060 }
1061
1062 void modRm_rm_Unchecked(RegisterID reg, RegisterID base, int offset)
1063 {
1064 if (base == X86::esp) {
1065 if (CAN_SIGN_EXTEND_8_32(offset)) {
1066 m_buffer->putByteUnchecked(MODRM(1, reg, X86::hasSib));
1067 m_buffer->putByteUnchecked(SIB(0, X86::noScale, X86::esp));
1068 m_buffer->putByteUnchecked(offset);
1069 } else {
1070 m_buffer->putByteUnchecked(MODRM(2, reg, X86::hasSib));
1071 m_buffer->putByteUnchecked(SIB(0, X86::noScale, X86::esp));
1072 m_buffer->putIntUnchecked(offset);
1073 }
1074 } else {
1075 if (CAN_SIGN_EXTEND_8_32(offset)) {
1076 m_buffer->putByteUnchecked(MODRM(1, reg, base));
1077 m_buffer->putByteUnchecked(offset);
1078 } else {
1079 m_buffer->putByteUnchecked(MODRM(2, reg, base));
1080 m_buffer->putIntUnchecked(offset);
1081 }
1082 }
1083 }
1084
1085 void modRm_rm(RegisterID reg, RegisterID base, int offset)
1086 {
1087 m_buffer->ensureSpace(maxInstructionSize);
1088 modRm_rm_Unchecked(reg, base, offset);
1089 }
1090
1091 void modRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale)
1092 {
1093 int shift = 0;
1094 while (scale >>= 1)
1095 shift++;
1096
1097 m_buffer->putByte(MODRM(0, reg, X86::hasSib));
1098 m_buffer->putByte(SIB(shift, index, base));
1099 }
1100
1101 void modRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale, int offset)
1102 {
1103 int shift = 0;
1104 while (scale >>= 1)
1105 shift++;
1106
1107 if (CAN_SIGN_EXTEND_8_32(offset)) {
1108 m_buffer->putByte(MODRM(1, reg, X86::hasSib));
1109 m_buffer->putByte(SIB(shift, index, base));
1110 m_buffer->putByte(offset);
1111 } else {
1112 m_buffer->putByte(MODRM(2, reg, X86::hasSib));
1113 m_buffer->putByte(SIB(shift, index, base));
1114 m_buffer->putInt(offset);
1115 }
1116 }
1117
1118 void modRm_opr(OpcodeID opcodeID, RegisterID rm)
1119 {
1120 m_buffer->ensureSpace(maxInstructionSize);
1121 modRm_opr_Unchecked(opcodeID, rm);
1122 }
1123
1124 void modRm_opr_Unchecked(OpcodeID opcodeID, RegisterID rm)
1125 {
1126 modRm_rr_Unchecked(static_cast<RegisterID>(opcodeID), rm);
1127 }
1128
1129 void modRm_opm(OpcodeID opcodeID, RegisterID base)
1130 {
1131 modRm_rm(static_cast<RegisterID>(opcodeID), base);
1132 }
1133
1134 void modRm_opm_Unchecked(OpcodeID opcodeID, RegisterID base, int offset)
1135 {
1136 modRm_rm_Unchecked(static_cast<RegisterID>(opcodeID), base, offset);
1137 }
1138
1139 void modRm_opm(OpcodeID opcodeID, RegisterID base, int offset)
1140 {
1141 modRm_rm(static_cast<RegisterID>(opcodeID), base, offset);
1142 }
1143
1144 void modRm_opm(OpcodeID opcodeID, void* addr)
1145 {
1146 modRm_rm(static_cast<RegisterID>(opcodeID), addr);
1147 }
1148
1149 void modRm_opmsib(OpcodeID opcodeID, RegisterID base, RegisterID index, int scale, int offset)
1150 {
1151 modRm_rmsib(static_cast<RegisterID>(opcodeID), base, index, scale, offset);
1152 }
1153
1154 AssemblerBuffer* m_buffer;
1155};
1156
1157} // namespace JSC
1158
1159#endif // ENABLE(ASSEMBLER) && PLATFORM(X86)
1160
1161#endif // X86Assembler_h
Note: See TracBrowser for help on using the repository browser.