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

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

2008-12-03 Sam Weinig <[email protected]>

Reviewed by Geoffrey Garen.

Remove shared AssemblerBuffer 1MB buffer and instead give AssemblerBuffer
an 256 byte inline capacity.

1% progression on Sunspider.

  • assembler/AssemblerBuffer.h: (JSC::AssemblerBuffer::AssemblerBuffer): (JSC::AssemblerBuffer::~AssemblerBuffer): (JSC::AssemblerBuffer::grow):
  • assembler/MacroAssembler.h: (JSC::MacroAssembler::MacroAssembler):
  • assembler/X86Assembler.h: (JSC::X86Assembler::X86Assembler):
  • interpreter/Interpreter.cpp: (JSC::Interpreter::Interpreter):
  • interpreter/Interpreter.h:
  • jit/JIT.cpp: (JSC::JIT::JIT):
  • parser/Nodes.cpp: (JSC::RegExpNode::emitBytecode):
  • runtime/RegExp.cpp: (JSC::RegExp::RegExp): (JSC::RegExp::create):
  • runtime/RegExp.h:
  • runtime/RegExpConstructor.cpp: (JSC::constructRegExp):
  • runtime/RegExpPrototype.cpp: (JSC::regExpProtoFuncCompile):
  • runtime/StringPrototype.cpp: (JSC::stringProtoFuncMatch): (JSC::stringProtoFuncSearch):
  • wrec/WREC.cpp: (JSC::WREC::Generator::compileRegExp):
  • wrec/WRECGenerator.h: (JSC::WREC::Generator::Generator):
  • wrec/WRECParser.h: (JSC::WREC::Parser::Parser):
File size: 32.2 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) || PLATFORM(X86_64))
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 REX_W = 0x48,
91 OP_PUSH_EAX = 0x50,
92 OP_POP_EAX = 0x58,
93 PRE_OPERAND_SIZE = 0x66,
94 PRE_SSE_66 = 0x66,
95 OP_PUSH_Iz = 0x68,
96 OP_IMUL_GvEvIz = 0x69,
97 OP_GROUP1_EvIz = 0x81,
98 OP_GROUP1_EvIb = 0x83,
99 OP_TEST_EvGv = 0x85,
100 OP_MOV_EvGv = 0x89,
101 OP_MOV_GvEv = 0x8B,
102 OP_LEA = 0x8D,
103 OP_GROUP1A_Ev = 0x8F,
104 OP_CDQ = 0x99,
105 OP_SETE = 0x94,
106 OP_SETNE = 0x95,
107 OP_GROUP2_EvIb = 0xC1,
108 OP_RET = 0xC3,
109 OP_GROUP11_EvIz = 0xC7,
110 OP_INT3 = 0xCC,
111 OP_GROUP2_Ev1 = 0xD1,
112 OP_GROUP2_EvCL = 0xD3,
113 OP_CALL_rel32 = 0xE8,
114 OP_JMP_rel32 = 0xE9,
115 PRE_SSE_F2 = 0xF2,
116 OP_HLT = 0xF4,
117 OP_GROUP3_Ev = 0xF7,
118 OP_GROUP3_EvIz = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test.
119 OP_GROUP5_Ev = 0xFF,
120
121 OP2_MOVSD_VsdWsd = 0x10,
122 OP2_MOVSD_WsdVsd = 0x11,
123 OP2_CVTSI2SD_VsdEd = 0x2A,
124 OP2_CVTTSD2SI_GdWsd = 0x2C,
125 OP2_UCOMISD_VsdWsd = 0x2E,
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_IDIV = 7,
162
163 GROUP5_OP_CALLN = 2,
164 GROUP5_OP_JMPN = 4,
165 GROUP5_OP_PUSH = 6,
166
167 GROUP11_MOV = 0,
168 } OpcodeID;
169
170 // Opaque label types
171
172 class JmpSrc {
173 friend class X86Assembler;
174 public:
175 JmpSrc()
176 : m_offset(-1)
177 {
178 }
179
180 private:
181 JmpSrc(int offset)
182 : m_offset(offset)
183 {
184 }
185
186 int m_offset;
187 };
188
189 class JmpDst {
190 friend class X86Assembler;
191 public:
192 JmpDst()
193 : m_offset(-1)
194 {
195 }
196
197 private:
198 JmpDst(int offset)
199 : m_offset(offset)
200 {
201 }
202
203 int m_offset;
204 };
205
206 static const int maxInstructionSize = 16;
207
208 X86Assembler()
209 {
210 }
211
212 void int3()
213 {
214 m_buffer.putByte(OP_INT3);
215 }
216
217#if PLATFORM(X86_64)
218 void pushq_r(RegisterID reg)
219 {
220 m_buffer.putByte(OP_PUSH_EAX + reg);
221 }
222
223 void popq_r(RegisterID reg)
224 {
225 m_buffer.putByte(OP_POP_EAX + reg);
226 }
227#else
228 void pushl_r(RegisterID reg)
229 {
230 m_buffer.putByte(OP_PUSH_EAX + reg);
231 }
232
233 void pushl_m(int offset, RegisterID base)
234 {
235 m_buffer.putByte(OP_GROUP5_Ev);
236 modRm_opm(GROUP5_OP_PUSH, base, offset);
237 }
238
239 void pushl_i32(int imm)
240 {
241 m_buffer.putByte(OP_PUSH_Iz);
242 m_buffer.putInt(imm);
243 }
244
245 void popl_r(RegisterID reg)
246 {
247 m_buffer.putByte(OP_POP_EAX + reg);
248 }
249
250 void popl_m(int offset, RegisterID base)
251 {
252 m_buffer.putByte(OP_GROUP1A_Ev);
253 modRm_opm(GROUP1A_OP_POP, base, offset);
254 }
255#endif
256
257 void movl_rr(RegisterID src, RegisterID dst)
258 {
259 m_buffer.putByte(OP_MOV_EvGv);
260 modRm_rr(src, dst);
261 }
262
263#if PLATFORM(X86_64)
264 void movq_rr(RegisterID src, RegisterID dst)
265 {
266 m_buffer.putByte(REX_W);
267 m_buffer.putByte(OP_MOV_EvGv);
268 modRm_rr(src, dst);
269 }
270#endif
271
272 void addl_rr(RegisterID src, RegisterID dst)
273 {
274 m_buffer.putByte(OP_ADD_EvGv);
275 modRm_rr(src, dst);
276 }
277
278#if !PLATFORM(X86_64)
279 void addl_i8m(int imm, void* addr)
280 {
281 m_buffer.putByte(OP_GROUP1_EvIb);
282 modRm_opm(GROUP1_OP_ADD, addr);
283 m_buffer.putByte(imm);
284 }
285#endif
286
287 void addl_i8r(int imm, RegisterID dst)
288 {
289 m_buffer.putByte(OP_GROUP1_EvIb);
290 modRm_opr(GROUP1_OP_ADD, dst);
291 m_buffer.putByte(imm);
292 }
293
294 void addl_i32r(int imm, RegisterID dst)
295 {
296 m_buffer.putByte(OP_GROUP1_EvIz);
297 modRm_opr(GROUP1_OP_ADD, dst);
298 m_buffer.putInt(imm);
299 }
300
301#if PLATFORM(X86_64)
302 void addq_i8r(int imm, RegisterID dst)
303 {
304 m_buffer.putByte(REX_W);
305 m_buffer.putByte(OP_GROUP1_EvIb);
306 modRm_opr(GROUP1_OP_ADD, dst);
307 m_buffer.putByte(imm);
308 }
309
310 void addq_i32r(int imm, RegisterID dst)
311 {
312 m_buffer.putByte(REX_W);
313 m_buffer.putByte(OP_GROUP1_EvIz);
314 modRm_opr(GROUP1_OP_ADD, dst);
315 m_buffer.putInt(imm);
316 }
317#endif
318
319 void addl_mr(int offset, RegisterID base, RegisterID dst)
320 {
321 m_buffer.putByte(OP_ADD_GvEv);
322 modRm_rm(dst, base, offset);
323 }
324
325 void andl_rr(RegisterID src, RegisterID dst)
326 {
327 m_buffer.putByte(OP_AND_EvGv);
328 modRm_rr(src, dst);
329 }
330
331 void andl_i32r(int imm, RegisterID dst)
332 {
333 m_buffer.putByte(OP_GROUP1_EvIz);
334 modRm_opr(GROUP1_OP_AND, dst);
335 m_buffer.putInt(imm);
336 }
337
338 void cmpl_i8r(int imm, RegisterID dst)
339 {
340 m_buffer.putByte(OP_GROUP1_EvIb);
341 modRm_opr(GROUP1_OP_CMP, dst);
342 m_buffer.putByte(imm);
343 }
344
345 void cmpl_rr(RegisterID src, RegisterID dst)
346 {
347 m_buffer.putByte(OP_CMP_EvGv);
348 modRm_rr(src, dst);
349 }
350
351 void cmpl_rm(RegisterID src, int offset, RegisterID base)
352 {
353 m_buffer.putByte(OP_CMP_EvGv);
354 modRm_rm(src, base, offset);
355 }
356
357 void cmpl_mr(int offset, RegisterID base, RegisterID dst)
358 {
359 m_buffer.putByte(OP_CMP_GvEv);
360 modRm_rm(dst, base, offset);
361 }
362
363 void cmpl_i32r(int imm, RegisterID dst)
364 {
365 m_buffer.putByte(OP_GROUP1_EvIz);
366 modRm_opr(GROUP1_OP_CMP, dst);
367 m_buffer.putInt(imm);
368 }
369
370 void cmpl_i32m(int imm, RegisterID dst)
371 {
372 m_buffer.putByte(OP_GROUP1_EvIz);
373 modRm_opm(GROUP1_OP_CMP, dst);
374 m_buffer.putInt(imm);
375 }
376
377 void cmpl_i32m(int imm, int offset, RegisterID dst)
378 {
379 m_buffer.putByte(OP_GROUP1_EvIz);
380 modRm_opm(GROUP1_OP_CMP, dst, offset);
381 m_buffer.putInt(imm);
382 }
383
384#if !PLATFORM(X86_64)
385 void cmpl_i32m(int imm, void* addr)
386 {
387 m_buffer.putByte(OP_GROUP1_EvIz);
388 modRm_opm(GROUP1_OP_CMP, addr);
389 m_buffer.putInt(imm);
390 }
391#endif
392
393 void cmpl_i8m(int imm, int offset, RegisterID base, RegisterID index, int scale)
394 {
395 m_buffer.putByte(OP_GROUP1_EvIb);
396 modRm_opmsib(GROUP1_OP_CMP, base, index, scale, offset);
397 m_buffer.putByte(imm);
398 }
399
400 void cmpw_rm(RegisterID src, RegisterID base, RegisterID index, int scale)
401 {
402 m_buffer.putByte(PRE_OPERAND_SIZE);
403 m_buffer.putByte(OP_CMP_EvGv);
404 modRm_rmsib(src, base, index, scale);
405 }
406
407 void cmpw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
408 {
409 m_buffer.putByte(PRE_OPERAND_SIZE);
410 m_buffer.putByte(OP_CMP_EvGv);
411 modRm_rmsib(src, base, index, scale, offset);
412 }
413
414 void sete_r(RegisterID dst)
415 {
416 m_buffer.putByte(OP_2BYTE_ESCAPE);
417 m_buffer.putByte(OP_SETE);
418 m_buffer.putByte(MODRM(3, 0, dst));
419 }
420
421 void setz_r(RegisterID dst)
422 {
423 sete_r(dst);
424 }
425
426 void setne_r(RegisterID dst)
427 {
428 m_buffer.putByte(OP_2BYTE_ESCAPE);
429 m_buffer.putByte(OP_SETNE);
430 m_buffer.putByte(MODRM(3, 0, dst));
431 }
432
433 void setnz_r(RegisterID dst)
434 {
435 setne_r(dst);
436 }
437
438 void orl_rr(RegisterID src, RegisterID dst)
439 {
440 m_buffer.putByte(OP_OR_EvGv);
441 modRm_rr(src, dst);
442 }
443
444 void orl_mr(int offset, RegisterID base, RegisterID dst)
445 {
446 m_buffer.putByte(OP_OR_GvEv);
447 modRm_rm(dst, base, offset);
448 }
449
450 void orl_i8r(int imm, RegisterID dst)
451 {
452 m_buffer.putByte(OP_GROUP1_EvIb);
453 modRm_opr(GROUP1_OP_OR, dst);
454 m_buffer.putByte(imm);
455 }
456
457 void orl_i32r(int imm, RegisterID dst)
458 {
459 m_buffer->putByte(OP_GROUP1_EvIz);
460 modRm_opr(GROUP1_OP_OR, dst);
461 m_buffer->putInt(imm);
462 }
463
464 void subl_rr(RegisterID src, RegisterID dst)
465 {
466 m_buffer.putByte(OP_SUB_EvGv);
467 modRm_rr(src, dst);
468 }
469
470 void subl_i8r(int imm, RegisterID dst)
471 {
472 m_buffer.putByte(OP_GROUP1_EvIb);
473 modRm_opr(GROUP1_OP_SUB, dst);
474 m_buffer.putByte(imm);
475 }
476
477#if !PLATFORM(X86_64)
478 void subl_i8m(int imm, void* addr)
479 {
480 m_buffer.putByte(OP_GROUP1_EvIb);
481 modRm_opm(GROUP1_OP_SUB, addr);
482 m_buffer.putByte(imm);
483 }
484#endif
485
486 void subl_i32r(int imm, RegisterID dst)
487 {
488 m_buffer.putByte(OP_GROUP1_EvIz);
489 modRm_opr(GROUP1_OP_SUB, dst);
490 m_buffer.putInt(imm);
491 }
492
493 void subl_mr(int offset, RegisterID base, RegisterID dst)
494 {
495 m_buffer.putByte(OP_SUB_GvEv);
496 modRm_rm(dst, base, offset);
497 }
498
499 void testl_i32r(int imm, RegisterID dst)
500 {
501 m_buffer.ensureSpace(maxInstructionSize);
502 m_buffer.putByteUnchecked(OP_GROUP3_EvIz);
503 modRm_opr_Unchecked(GROUP3_OP_TEST, dst);
504 m_buffer.putIntUnchecked(imm);
505 }
506
507 void testl_i32m(int imm, RegisterID dst)
508 {
509 m_buffer.putByte(OP_GROUP3_EvIz);
510 modRm_opm(GROUP3_OP_TEST, dst);
511 m_buffer.putInt(imm);
512 }
513
514 void testl_i32m(int imm, int offset, RegisterID dst)
515 {
516 m_buffer.putByte(OP_GROUP3_EvIz);
517 modRm_opm(GROUP3_OP_TEST, dst, offset);
518 m_buffer.putInt(imm);
519 }
520
521 void testl_rr(RegisterID src, RegisterID dst)
522 {
523 m_buffer.putByte(OP_TEST_EvGv);
524 modRm_rr(src, dst);
525 }
526
527 void xorl_i8r(int imm, RegisterID dst)
528 {
529 m_buffer.putByte(OP_GROUP1_EvIb);
530 modRm_opr(GROUP1_OP_XOR, dst);
531 m_buffer.putByte(imm);
532 }
533
534 void xorl_rr(RegisterID src, RegisterID dst)
535 {
536 m_buffer.putByte(OP_XOR_EvGv);
537 modRm_rr(src, dst);
538 }
539
540 void sarl_i8r(int imm, RegisterID dst)
541 {
542 if (imm == 1) {
543 m_buffer.putByte(OP_GROUP2_Ev1);
544 modRm_opr(GROUP2_OP_SAR, dst);
545 } else {
546 m_buffer.putByte(OP_GROUP2_EvIb);
547 modRm_opr(GROUP2_OP_SAR, dst);
548 m_buffer.putByte(imm);
549 }
550 }
551
552 void sarl_CLr(RegisterID dst)
553 {
554 m_buffer.putByte(OP_GROUP2_EvCL);
555 modRm_opr(GROUP2_OP_SAR, dst);
556 }
557
558 void shl_i8r(int imm, RegisterID dst)
559 {
560 if (imm == 1) {
561 m_buffer.putByte(OP_GROUP2_Ev1);
562 modRm_opr(GROUP2_OP_SHL, dst);
563 } else {
564 m_buffer.putByte(OP_GROUP2_EvIb);
565 modRm_opr(GROUP2_OP_SHL, dst);
566 m_buffer.putByte(imm);
567 }
568 }
569
570 void shll_CLr(RegisterID dst)
571 {
572 m_buffer.putByte(OP_GROUP2_EvCL);
573 modRm_opr(GROUP2_OP_SHL, dst);
574 }
575
576 void imull_rr(RegisterID src, RegisterID dst)
577 {
578 m_buffer.putByte(OP_2BYTE_ESCAPE);
579 m_buffer.putByte(OP2_IMUL_GvEv);
580 modRm_rr(dst, src);
581 }
582
583 void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
584 {
585 m_buffer.putByte(OP_IMUL_GvEvIz);
586 modRm_rr(dst, src);
587 m_buffer.putInt(value);
588 }
589
590 void idivl_r(RegisterID dst)
591 {
592 m_buffer.putByte(OP_GROUP3_Ev);
593 modRm_opr(GROUP3_OP_IDIV, dst);
594 }
595
596 void cdq()
597 {
598 m_buffer.putByte(OP_CDQ);
599 }
600
601 void movl_mr(RegisterID base, RegisterID dst)
602 {
603 m_buffer.putByte(OP_MOV_GvEv);
604 modRm_rm(dst, base);
605 }
606
607 void movl_mr(int offset, RegisterID base, RegisterID dst)
608 {
609 m_buffer.ensureSpace(maxInstructionSize);
610 m_buffer.putByteUnchecked(OP_MOV_GvEv);
611 modRm_rm_Unchecked(dst, base, offset);
612 }
613
614#if PLATFORM(X86_64)
615 void movq_mr(RegisterID base, RegisterID dst)
616 {
617 m_buffer.putByte(REX_W);
618 m_buffer.putByte(OP_MOV_GvEv);
619 modRm_rm(dst, base);
620 }
621
622 void movq_mr(int offset, RegisterID base, RegisterID dst)
623 {
624 m_buffer.ensureSpace(maxInstructionSize);
625 m_buffer.putByteUnchecked(REX_W);
626 m_buffer.putByteUnchecked(OP_MOV_GvEv);
627 modRm_rm_Unchecked(dst, base, offset);
628 }
629#endif
630
631#if !PLATFORM(X86_64)
632 void movl_mr(void* addr, RegisterID dst)
633 {
634 m_buffer.putByte(OP_MOV_GvEv);
635 modRm_rm(dst, addr);
636 }
637#endif
638
639 void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
640 {
641 m_buffer.putByte(OP_MOV_GvEv);
642 modRm_rmsib(dst, base, index, scale, offset);
643 }
644
645 void movzbl_rr(RegisterID src, RegisterID dst)
646 {
647 m_buffer.putByte(OP_2BYTE_ESCAPE);
648 m_buffer.putByte(OP2_MOVZX_GvEb);
649 modRm_rr(dst, src);
650 }
651
652 void movzwl_mr(int offset, RegisterID base, RegisterID dst)
653 {
654 m_buffer.putByte(OP_2BYTE_ESCAPE);
655 m_buffer.putByte(OP2_MOVZX_GvEw);
656 modRm_rm(dst, base, offset);
657 }
658
659 void movzwl_mr(RegisterID base, RegisterID index, int scale, RegisterID dst)
660 {
661 m_buffer.putByte(OP_2BYTE_ESCAPE);
662 m_buffer.putByte(OP2_MOVZX_GvEw);
663 modRm_rmsib(dst, base, index, scale);
664 }
665
666 void movzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
667 {
668 m_buffer.putByte(OP_2BYTE_ESCAPE);
669 m_buffer.putByte(OP2_MOVZX_GvEw);
670 modRm_rmsib(dst, base, index, scale, offset);
671 }
672
673 void movl_rm(RegisterID src, RegisterID base)
674 {
675 m_buffer.putByte(OP_MOV_EvGv);
676 modRm_rm(src, base);
677 }
678
679 void movl_rm(RegisterID src, int offset, RegisterID base)
680 {
681 m_buffer.ensureSpace(maxInstructionSize);
682 m_buffer.putByteUnchecked(OP_MOV_EvGv);
683 modRm_rm_Unchecked(src, base, offset);
684 }
685
686#if PLATFORM(X86_64)
687 void movq_rm(RegisterID src, RegisterID base)
688 {
689 m_buffer.putByte(REX_W);
690 m_buffer.putByte(OP_MOV_EvGv);
691 modRm_rm(src, base);
692 }
693
694 void movq_rm(RegisterID src, int offset, RegisterID base)
695 {
696 m_buffer.ensureSpace(maxInstructionSize);
697 m_buffer.putByteUnchecked(REX_W);
698 m_buffer.putByteUnchecked(OP_MOV_EvGv);
699 modRm_rm_Unchecked(src, base, offset);
700 }
701#endif
702
703 void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
704 {
705 m_buffer.putByte(OP_MOV_EvGv);
706 modRm_rmsib(src, base, index, scale, offset);
707 }
708
709 void movl_i32r(int imm, RegisterID dst)
710 {
711 m_buffer.putByte(OP_GROUP11_EvIz);
712 modRm_opr(GROUP11_MOV, dst);
713 m_buffer.putInt(imm);
714 }
715
716 void movl_i32m(int imm, int offset, RegisterID base)
717 {
718 m_buffer.ensureSpace(maxInstructionSize);
719 m_buffer.putByteUnchecked(OP_GROUP11_EvIz);
720 modRm_opm_Unchecked(GROUP11_MOV, base, offset);
721 m_buffer.putIntUnchecked(imm);
722 }
723
724#if !PLATFORM(X86_64)
725 void movl_i32m(int imm, void* addr)
726 {
727 m_buffer.putByte(OP_GROUP11_EvIz);
728 modRm_opm(GROUP11_MOV, addr);
729 m_buffer.putInt(imm);
730 }
731#endif
732
733 void leal_mr(int offset, RegisterID base, RegisterID dst)
734 {
735 m_buffer.putByte(OP_LEA);
736 modRm_rm(dst, base, offset);
737 }
738
739 void leal_mr(int offset, RegisterID index, int scale, RegisterID dst)
740 {
741 m_buffer.putByte(OP_LEA);
742 modRm_rmsib(dst, X86::noBase, index, scale, offset);
743 }
744
745 void ret()
746 {
747 m_buffer.putByte(OP_RET);
748 }
749
750 void jmp_r(RegisterID dst)
751 {
752 m_buffer.putByte(OP_GROUP5_Ev);
753 modRm_opr(GROUP5_OP_JMPN, dst);
754 }
755
756 void jmp_m(int offset, RegisterID base)
757 {
758 m_buffer.putByte(OP_GROUP5_Ev);
759 modRm_opm(GROUP5_OP_JMPN, base, offset);
760 }
761
762 void movsd_mr(int offset, RegisterID base, XMMRegisterID dst)
763 {
764 m_buffer.putByte(PRE_SSE_F2);
765 m_buffer.putByte(OP_2BYTE_ESCAPE);
766 m_buffer.putByte(OP2_MOVSD_VsdWsd);
767 modRm_rm((RegisterID)dst, base, offset);
768 }
769
770 void movsd_rm(XMMRegisterID src, int offset, RegisterID base)
771 {
772 m_buffer.putByte(PRE_SSE_F2);
773 m_buffer.putByte(OP_2BYTE_ESCAPE);
774 m_buffer.putByte(OP2_MOVSD_WsdVsd);
775 modRm_rm((RegisterID)src, base, offset);
776 }
777
778 void movd_rr(XMMRegisterID src, RegisterID dst)
779 {
780 m_buffer.putByte(PRE_SSE_66);
781 m_buffer.putByte(OP_2BYTE_ESCAPE);
782 m_buffer.putByte(OP2_MOVD_EdVd);
783 modRm_rr((RegisterID)src, dst);
784 }
785
786 void cvtsi2sd_rr(RegisterID src, XMMRegisterID dst)
787 {
788 m_buffer.putByte(PRE_SSE_F2);
789 m_buffer.putByte(OP_2BYTE_ESCAPE);
790 m_buffer.putByte(OP2_CVTSI2SD_VsdEd);
791 modRm_rr((RegisterID)dst, src);
792 }
793
794 void cvttsd2si_rr(XMMRegisterID src, RegisterID dst)
795 {
796 m_buffer.putByte(PRE_SSE_F2);
797 m_buffer.putByte(OP_2BYTE_ESCAPE);
798 m_buffer.putByte(OP2_CVTTSD2SI_GdWsd);
799 modRm_rr(dst, (RegisterID)src);
800 }
801
802 void addsd_mr(int offset, RegisterID base, XMMRegisterID dst)
803 {
804 m_buffer.putByte(PRE_SSE_F2);
805 m_buffer.putByte(OP_2BYTE_ESCAPE);
806 m_buffer.putByte(OP2_ADDSD_VsdWsd);
807 modRm_rm((RegisterID)dst, base, offset);
808 }
809
810 void subsd_mr(int offset, RegisterID base, XMMRegisterID dst)
811 {
812 m_buffer.putByte(PRE_SSE_F2);
813 m_buffer.putByte(OP_2BYTE_ESCAPE);
814 m_buffer.putByte(OP2_SUBSD_VsdWsd);
815 modRm_rm((RegisterID)dst, base, offset);
816 }
817
818 void mulsd_mr(int offset, RegisterID base, XMMRegisterID dst)
819 {
820 m_buffer.putByte(PRE_SSE_F2);
821 m_buffer.putByte(OP_2BYTE_ESCAPE);
822 m_buffer.putByte(OP2_MULSD_VsdWsd);
823 modRm_rm((RegisterID)dst, base, offset);
824 }
825
826 void addsd_rr(XMMRegisterID src, XMMRegisterID dst)
827 {
828 m_buffer.putByte(PRE_SSE_F2);
829 m_buffer.putByte(OP_2BYTE_ESCAPE);
830 m_buffer.putByte(OP2_ADDSD_VsdWsd);
831 modRm_rr((RegisterID)dst, (RegisterID)src);
832 }
833
834 void subsd_rr(XMMRegisterID src, XMMRegisterID dst)
835 {
836 m_buffer.putByte(PRE_SSE_F2);
837 m_buffer.putByte(OP_2BYTE_ESCAPE);
838 m_buffer.putByte(OP2_SUBSD_VsdWsd);
839 modRm_rr((RegisterID)dst, (RegisterID)src);
840 }
841
842 void mulsd_rr(XMMRegisterID src, XMMRegisterID dst)
843 {
844 m_buffer.putByte(PRE_SSE_F2);
845 m_buffer.putByte(OP_2BYTE_ESCAPE);
846 m_buffer.putByte(OP2_MULSD_VsdWsd);
847 modRm_rr((RegisterID)dst, (RegisterID)src);
848 }
849
850 void ucomis_rr(XMMRegisterID src, XMMRegisterID dst)
851 {
852 m_buffer.putByte(PRE_SSE_66);
853 m_buffer.putByte(OP_2BYTE_ESCAPE);
854 m_buffer.putByte(OP2_UCOMISD_VsdWsd);
855 modRm_rr((RegisterID)dst, (RegisterID)src);
856 }
857
858 void pextrw_irr(int whichWord, XMMRegisterID src, RegisterID dst)
859 {
860 m_buffer.putByte(PRE_SSE_66);
861 m_buffer.putByte(OP_2BYTE_ESCAPE);
862 m_buffer.putByte(OP2_PEXTRW_GdUdIb);
863 modRm_rr(dst, (RegisterID)src);
864 m_buffer.putByte(whichWord);
865 }
866
867 JmpSrc call()
868 {
869 m_buffer.putByte(OP_CALL_rel32);
870 m_buffer.putInt(0); // FIXME: make this point to a global label, linked later.
871 return JmpSrc(m_buffer.size());
872 }
873
874 JmpSrc call(RegisterID dst)
875 {
876 m_buffer.putByte(OP_GROUP5_Ev);
877 modRm_opr(GROUP5_OP_CALLN, dst);
878 return JmpSrc(m_buffer.size());
879 }
880
881 JmpDst label()
882 {
883 return JmpDst(m_buffer.size());
884 }
885
886 JmpDst align(int alignment)
887 {
888 while (!m_buffer.isAligned(alignment))
889 m_buffer.putByte(OP_HLT);
890
891 return label();
892 }
893
894 JmpSrc jmp()
895 {
896 m_buffer.putByte(OP_JMP_rel32);
897 m_buffer.putInt(0);
898 return JmpSrc(m_buffer.size());
899 }
900
901 JmpSrc jne()
902 {
903 m_buffer.putByte(OP_2BYTE_ESCAPE);
904 m_buffer.putByte(OP2_JNE_rel32);
905 m_buffer.putInt(0);
906 return JmpSrc(m_buffer.size());
907 }
908
909 JmpSrc jnz()
910 {
911 return jne();
912 }
913
914 JmpSrc je()
915 {
916 m_buffer.ensureSpace(maxInstructionSize);
917 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
918 m_buffer.putByteUnchecked(OP2_JE_rel32);
919 m_buffer.putIntUnchecked(0);
920 return JmpSrc(m_buffer.size());
921 }
922
923 JmpSrc jl()
924 {
925 m_buffer.putByte(OP_2BYTE_ESCAPE);
926 m_buffer.putByte(OP2_JL_rel32);
927 m_buffer.putInt(0);
928 return JmpSrc(m_buffer.size());
929 }
930
931 JmpSrc jb()
932 {
933 m_buffer.putByte(OP_2BYTE_ESCAPE);
934 m_buffer.putByte(OP2_JB_rel32);
935 m_buffer.putInt(0);
936 return JmpSrc(m_buffer.size());
937 }
938
939 JmpSrc jle()
940 {
941 m_buffer.putByte(OP_2BYTE_ESCAPE);
942 m_buffer.putByte(OP2_JLE_rel32);
943 m_buffer.putInt(0);
944 return JmpSrc(m_buffer.size());
945 }
946
947 JmpSrc jbe()
948 {
949 m_buffer.putByte(OP_2BYTE_ESCAPE);
950 m_buffer.putByte(OP2_JBE_rel32);
951 m_buffer.putInt(0);
952 return JmpSrc(m_buffer.size());
953 }
954
955 JmpSrc jge()
956 {
957 m_buffer.putByte(OP_2BYTE_ESCAPE);
958 m_buffer.putByte(OP2_JGE_rel32);
959 m_buffer.putInt(0);
960 return JmpSrc(m_buffer.size());
961 }
962
963 JmpSrc jg()
964 {
965 m_buffer.putByte(OP_2BYTE_ESCAPE);
966 m_buffer.putByte(OP2_JG_rel32);
967 m_buffer.putInt(0);
968 return JmpSrc(m_buffer.size());
969 }
970
971 JmpSrc ja()
972 {
973 m_buffer.putByte(OP_2BYTE_ESCAPE);
974 m_buffer.putByte(OP2_JA_rel32);
975 m_buffer.putInt(0);
976 return JmpSrc(m_buffer.size());
977 }
978
979 JmpSrc jae()
980 {
981 m_buffer.putByte(OP_2BYTE_ESCAPE);
982 m_buffer.putByte(OP2_JAE_rel32);
983 m_buffer.putInt(0);
984 return JmpSrc(m_buffer.size());
985 }
986
987 JmpSrc jo()
988 {
989 m_buffer.putByte(OP_2BYTE_ESCAPE);
990 m_buffer.putByte(OP2_JO_rel32);
991 m_buffer.putInt(0);
992 return JmpSrc(m_buffer.size());
993 }
994
995 JmpSrc jp()
996 {
997 m_buffer.putByte(OP_2BYTE_ESCAPE);
998 m_buffer.putByte(OP2_JP_rel32);
999 m_buffer.putInt(0);
1000 return JmpSrc(m_buffer.size());
1001 }
1002
1003 JmpSrc js()
1004 {
1005 m_buffer.putByte(OP_2BYTE_ESCAPE);
1006 m_buffer.putByte(OP2_JS_rel32);
1007 m_buffer.putInt(0);
1008 return JmpSrc(m_buffer.size());
1009 }
1010
1011 void predictNotTaken()
1012 {
1013 m_buffer.putByte(PRE_PREDICT_BRANCH_NOT_TAKEN);
1014 }
1015
1016 void link(JmpSrc from, JmpDst to)
1017 {
1018 ASSERT(to.m_offset != -1);
1019 ASSERT(from.m_offset != -1);
1020
1021 reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(m_buffer.data()) + from.m_offset)[-1] = to.m_offset - from.m_offset;
1022 }
1023
1024 static void linkAbsoluteAddress(void* code, JmpDst useOffset, JmpDst address)
1025 {
1026 ASSERT(useOffset.m_offset != -1);
1027 ASSERT(address.m_offset != -1);
1028
1029 reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(code) + useOffset.m_offset)[-1] = reinterpret_cast<ptrdiff_t>(code) + address.m_offset;
1030 }
1031
1032 static void link(void* code, JmpSrc from, void* to)
1033 {
1034 ASSERT(from.m_offset != -1);
1035
1036 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);
1037 }
1038
1039 static void* getRelocatedAddress(void* code, JmpSrc jump)
1040 {
1041 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
1042 }
1043
1044 static void* getRelocatedAddress(void* code, JmpDst jump)
1045 {
1046 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
1047 }
1048
1049 static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
1050 {
1051 return dst.m_offset - src.m_offset;
1052 }
1053
1054 static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
1055 {
1056 return dst.m_offset - src.m_offset;
1057 }
1058
1059 static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
1060 {
1061 return dst.m_offset - src.m_offset;
1062 }
1063
1064 static void repatchImmediate(intptr_t where, int32_t value)
1065 {
1066 reinterpret_cast<int32_t*>(where)[-1] = value;
1067 }
1068
1069 static void repatchDisplacement(intptr_t where, intptr_t value)
1070 {
1071 reinterpret_cast<intptr_t*>(where)[-1] = value;
1072 }
1073
1074 static void repatchBranchOffset(intptr_t where, void* destination)
1075 {
1076 reinterpret_cast<intptr_t*>(where)[-1] = (reinterpret_cast<intptr_t>(destination) - where);
1077 }
1078
1079 void* executableCopy()
1080 {
1081 void* copy = m_buffer.executableCopy();
1082 ASSERT(copy);
1083 return copy;
1084 }
1085
1086#if USE(CTI_ARGUMENT)
1087 void restoreArgumentReference()
1088 {
1089#if USE(FAST_CALL_CTI_ARGUMENT)
1090 movl_rr(X86::esp, X86::ecx);
1091#else
1092 movl_rm(X86::esp, 0, X86::esp);
1093#endif
1094 }
1095
1096 void restoreArgumentReferenceForTrampoline()
1097 {
1098#if USE(FAST_CALL_CTI_ARGUMENT)
1099 movl_rr(X86::esp, X86::ecx);
1100 addl_i32r(4, X86::ecx);
1101#endif
1102 }
1103#else
1104 void restoreArgumentReference() {}
1105 void restoreArgumentReferenceForTrampoline() {}
1106#endif
1107
1108private:
1109 void modRm_rr(RegisterID reg, RegisterID rm)
1110 {
1111 m_buffer.ensureSpace(maxInstructionSize);
1112 modRm_rr_Unchecked(reg, rm);
1113 }
1114
1115 void modRm_rr_Unchecked(RegisterID reg, RegisterID rm)
1116 {
1117 m_buffer.putByteUnchecked(MODRM(3, reg, rm));
1118 }
1119
1120#if !PLATFORM(X86_64)
1121 void modRm_rm(RegisterID reg, void* addr)
1122 {
1123 m_buffer.putByte(MODRM(0, reg, X86::noBase));
1124 m_buffer.putInt((int)addr);
1125 }
1126#endif
1127
1128 void modRm_rm(RegisterID reg, RegisterID base)
1129 {
1130 if (base == X86::esp) {
1131 m_buffer.putByte(MODRM(0, reg, X86::hasSib));
1132 m_buffer.putByte(SIB(0, X86::noScale, X86::esp));
1133 } else
1134 m_buffer.putByte(MODRM(0, reg, base));
1135 }
1136
1137 void modRm_rm_Unchecked(RegisterID reg, RegisterID base, int offset)
1138 {
1139 if (base == X86::esp) {
1140 if (CAN_SIGN_EXTEND_8_32(offset)) {
1141 m_buffer.putByteUnchecked(MODRM(1, reg, X86::hasSib));
1142 m_buffer.putByteUnchecked(SIB(0, X86::noScale, X86::esp));
1143 m_buffer.putByteUnchecked(offset);
1144 } else {
1145 m_buffer.putByteUnchecked(MODRM(2, reg, X86::hasSib));
1146 m_buffer.putByteUnchecked(SIB(0, X86::noScale, X86::esp));
1147 m_buffer.putIntUnchecked(offset);
1148 }
1149 } else {
1150 if (CAN_SIGN_EXTEND_8_32(offset)) {
1151 m_buffer.putByteUnchecked(MODRM(1, reg, base));
1152 m_buffer.putByteUnchecked(offset);
1153 } else {
1154 m_buffer.putByteUnchecked(MODRM(2, reg, base));
1155 m_buffer.putIntUnchecked(offset);
1156 }
1157 }
1158 }
1159
1160 void modRm_rm(RegisterID reg, RegisterID base, int offset)
1161 {
1162 m_buffer.ensureSpace(maxInstructionSize);
1163 modRm_rm_Unchecked(reg, base, offset);
1164 }
1165
1166 void modRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale)
1167 {
1168 int shift = 0;
1169 while (scale >>= 1)
1170 shift++;
1171
1172 m_buffer.putByte(MODRM(0, reg, X86::hasSib));
1173 m_buffer.putByte(SIB(shift, index, base));
1174 }
1175
1176 void modRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale, int offset)
1177 {
1178 int shift = 0;
1179 while (scale >>= 1)
1180 shift++;
1181
1182 if (CAN_SIGN_EXTEND_8_32(offset)) {
1183 m_buffer.putByte(MODRM(1, reg, X86::hasSib));
1184 m_buffer.putByte(SIB(shift, index, base));
1185 m_buffer.putByte(offset);
1186 } else {
1187 m_buffer.putByte(MODRM(2, reg, X86::hasSib));
1188 m_buffer.putByte(SIB(shift, index, base));
1189 m_buffer.putInt(offset);
1190 }
1191 }
1192
1193 void modRm_opr(OpcodeID opcodeID, RegisterID rm)
1194 {
1195 m_buffer.ensureSpace(maxInstructionSize);
1196 modRm_opr_Unchecked(opcodeID, rm);
1197 }
1198
1199 void modRm_opr_Unchecked(OpcodeID opcodeID, RegisterID rm)
1200 {
1201 modRm_rr_Unchecked(static_cast<RegisterID>(opcodeID), rm);
1202 }
1203
1204 void modRm_opm(OpcodeID opcodeID, RegisterID base)
1205 {
1206 modRm_rm(static_cast<RegisterID>(opcodeID), base);
1207 }
1208
1209 void modRm_opm_Unchecked(OpcodeID opcodeID, RegisterID base, int offset)
1210 {
1211 modRm_rm_Unchecked(static_cast<RegisterID>(opcodeID), base, offset);
1212 }
1213
1214 void modRm_opm(OpcodeID opcodeID, RegisterID base, int offset)
1215 {
1216 modRm_rm(static_cast<RegisterID>(opcodeID), base, offset);
1217 }
1218
1219#if !PLATFORM(X86_64)
1220 void modRm_opm(OpcodeID opcodeID, void* addr)
1221 {
1222 modRm_rm(static_cast<RegisterID>(opcodeID), addr);
1223 }
1224#endif
1225
1226 void modRm_opmsib(OpcodeID opcodeID, RegisterID base, RegisterID index, int scale, int offset)
1227 {
1228 modRm_rmsib(static_cast<RegisterID>(opcodeID), base, index, scale, offset);
1229 }
1230
1231 AssemblerBuffer m_buffer;
1232};
1233
1234} // namespace JSC
1235
1236#endif // ENABLE(ASSEMBLER) && PLATFORM(X86)
1237
1238#endif // X86Assembler_h
Note: See TracBrowser for help on using the repository browser.