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

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