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

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

2008-11-16 Geoffrey Garen <[email protected]>

Reviewed by Sam Weinig.


Moved masm => assembler and split "AssemblerBuffer.h" out of "X86Assembler.h".


Also renamed ENABLE_MASM to ENABLE_ASSEMBLER.

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