]> git.saurik.com Git - apple/javascriptcore.git/blame - offlineasm/x86.rb
JavaScriptCore-1097.13.tar.gz
[apple/javascriptcore.git] / offlineasm / x86.rb
CommitLineData
6fe7ccc8
A
1# Copyright (C) 2012 Apple Inc. All rights reserved.
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions
5# are met:
6# 1. Redistributions of source code must retain the above copyright
7# notice, this list of conditions and the following disclaimer.
8# 2. Redistributions in binary form must reproduce the above copyright
9# notice, this list of conditions and the following disclaimer in the
10# documentation and/or other materials provided with the distribution.
11#
12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
22# THE POSSIBILITY OF SUCH DAMAGE.
23
24def isX64
25 case $activeBackend
26 when "X86"
27 false
28 when "X86_64"
29 true
30 else
31 raise "bad value for $activeBackend: #{$activeBackend}"
32 end
33end
34
35class SpecialRegister < NoChildren
36 def x86Operand(kind)
37 raise unless @name =~ /^r/
38 raise unless isX64
39 case kind
40 when :half
41 "%" + @name + "w"
42 when :int
43 "%" + @name + "d"
44 when :ptr
45 "%" + @name
46 else
47 raise
48 end
49 end
50 def x86CallOperand(kind)
51 "*#{x86Operand(kind)}"
52 end
53end
54
55X64_SCRATCH_REGISTER = SpecialRegister.new("r11")
56
57class RegisterID
58 def supports8BitOnX86
59 case name
60 when "t0", "a0", "r0", "t1", "a1", "r1", "t2", "t3"
61 true
62 when "cfr", "ttnr", "tmr"
63 false
64 when "t4", "t5"
65 isX64
66 else
67 raise
68 end
69 end
70
71 def x86Operand(kind)
72 case name
73 when "t0", "a0", "r0"
74 case kind
75 when :byte
76 "%al"
77 when :half
78 "%ax"
79 when :int
80 "%eax"
81 when :ptr
82 isX64 ? "%rax" : "%eax"
83 else
84 raise
85 end
86 when "t1", "a1", "r1"
87 case kind
88 when :byte
89 "%dl"
90 when :half
91 "%dx"
92 when :int
93 "%edx"
94 when :ptr
95 isX64 ? "%rdx" : "%edx"
96 else
97 raise
98 end
99 when "t2"
100 case kind
101 when :byte
102 "%cl"
103 when :half
104 "%cx"
105 when :int
106 "%ecx"
107 when :ptr
108 isX64 ? "%rcx" : "%ecx"
109 else
110 raise
111 end
112 when "t3"
113 case kind
114 when :byte
115 "%bl"
116 when :half
117 "%bx"
118 when :int
119 "%ebx"
120 when :ptr
121 isX64 ? "%rbx" : "%ebx"
122 else
123 raise
124 end
125 when "t4"
126 case kind
127 when :byte
128 "%sil"
129 when :half
130 "%si"
131 when :int
132 "%esi"
133 when :ptr
134 isX64 ? "%rsi" : "%esi"
135 else
136 raise
137 end
138 when "cfr"
139 if isX64
140 case kind
141 when :half
142 "%r13w"
143 when :int
144 "%r13d"
145 when :ptr
146 "%r13"
147 else
148 raise
149 end
150 else
151 case kind
152 when :byte
153 "%dil"
154 when :half
155 "%di"
156 when :int
157 "%edi"
158 when :ptr
159 "%edi"
160 else
161 raise
162 end
163 end
164 when "sp"
165 case kind
166 when :byte
167 "%spl"
168 when :half
169 "%sp"
170 when :int
171 "%esp"
172 when :ptr
173 isX64 ? "%rsp" : "%esp"
174 else
175 raise
176 end
177 when "t5"
178 raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
179 case kind
180 when :byte
181 "%dil"
182 when :half
183 "%di"
184 when :int
185 "%edi"
186 when :ptr
187 "%rdi"
188 end
189 when "t6"
190 raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
191 case kind
192 when :half
193 "%r10w"
194 when :int
195 "%r10d"
196 when :ptr
197 "%r10"
198 end
199 when "csr1"
200 raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
201 case kind
202 when :half
203 "%r14w"
204 when :int
205 "%r14d"
206 when :ptr
207 "%r14"
208 end
209 when "csr2"
210 raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
211 case kind
212 when :half
213 "%r15w"
214 when :int
215 "%r15d"
216 when :ptr
217 "%r15"
218 end
219 else
220 raise "Bad register #{name} for X86 at #{codeOriginString}"
221 end
222 end
223 def x86CallOperand(kind)
224 "*#{x86Operand(kind)}"
225 end
226end
227
228class FPRegisterID
229 def x86Operand(kind)
230 raise unless kind == :double
231 case name
232 when "ft0", "fa0", "fr"
233 "%xmm0"
234 when "ft1", "fa1"
235 "%xmm1"
236 when "ft2", "fa2"
237 "%xmm2"
238 when "ft3", "fa3"
239 "%xmm3"
240 when "ft4"
241 "%xmm4"
242 when "ft5"
243 "%xmm5"
244 else
245 raise "Bad register #{name} for X86 at #{codeOriginString}"
246 end
247 end
248 def x86CallOperand(kind)
249 "*#{x86Operand(kind)}"
250 end
251end
252
253class Immediate
254 def validX86Immediate?
255 if isX64
256 value >= -0x80000000 and value <= 0x7fffffff
257 else
258 true
259 end
260 end
261 def x86Operand(kind)
262 "$#{value}"
263 end
264 def x86CallOperand(kind)
265 "#{value}"
266 end
267end
268
269class Address
270 def supports8BitOnX86
271 true
272 end
273
274 def x86AddressOperand(addressKind)
275 "#{offset.value}(#{base.x86Operand(addressKind)})"
276 end
277 def x86Operand(kind)
278 x86AddressOperand(:ptr)
279 end
280 def x86CallOperand(kind)
281 "*#{x86Operand(kind)}"
282 end
283end
284
285class BaseIndex
286 def supports8BitOnX86
287 true
288 end
289
290 def x86AddressOperand(addressKind)
291 "#{offset.value}(#{base.x86Operand(addressKind)}, #{index.x86Operand(addressKind)}, #{scale})"
292 end
293
294 def x86Operand(kind)
295 x86AddressOperand(:ptr)
296 end
297
298 def x86CallOperand(kind)
299 "*#{x86Operand(kind)}"
300 end
301end
302
303class AbsoluteAddress
304 def supports8BitOnX86
305 true
306 end
307
308 def x86AddressOperand(addressKind)
309 "#{address.value}"
310 end
311
312 def x86Operand(kind)
313 "#{address.value}"
314 end
315
316 def x86CallOperand(kind)
317 "*#{address.value}"
318 end
319end
320
321class LabelReference
322 def x86CallOperand(kind)
323 asmLabel
324 end
325end
326
327class LocalLabelReference
328 def x86CallOperand(kind)
329 asmLabel
330 end
331end
332
333class Sequence
334 def getModifiedListX86_64
335 newList = []
336
337 @list.each {
338 | node |
339 newNode = node
340 if node.is_a? Instruction
341 unless node.opcode == "move"
342 usedScratch = false
343 newOperands = node.operands.map {
344 | operand |
345 if operand.immediate? and not operand.validX86Immediate?
346 if usedScratch
347 raise "Attempt to use scratch register twice at #{operand.codeOriginString}"
348 end
349 newList << Instruction.new(operand.codeOrigin, "move", [operand, X64_SCRATCH_REGISTER])
350 usedScratch = true
351 X64_SCRATCH_REGISTER
352 else
353 operand
354 end
355 }
356 newNode = Instruction.new(node.codeOrigin, node.opcode, newOperands)
357 end
358 else
359 unless node.is_a? Label or
360 node.is_a? LocalLabel or
361 node.is_a? Skip
362 raise "Unexpected #{node.inspect} at #{node.codeOrigin}"
363 end
364 end
365 if newNode
366 newList << newNode
367 end
368 }
369
370 return newList
371 end
372end
373
374class Instruction
375 def x86Operands(*kinds)
376 raise unless kinds.size == operands.size
377 result = []
378 kinds.size.times {
379 | idx |
380 result << operands[idx].x86Operand(kinds[idx])
381 }
382 result.join(", ")
383 end
384
385 def x86Suffix(kind)
386 case kind
387 when :byte
388 "b"
389 when :half
390 "w"
391 when :int
392 "l"
393 when :ptr
394 isX64 ? "q" : "l"
395 when :double
396 "sd"
397 else
398 raise
399 end
400 end
401
402 def x86Bytes(kind)
403 case kind
404 when :byte
405 1
406 when :half
407 2
408 when :int
409 4
410 when :ptr
411 isX64 ? 8 : 4
412 when :double
413 8
414 else
415 raise
416 end
417 end
418
419 def handleX86OpWithNumOperands(opcode, kind, numOperands)
420 if numOperands == 3
421 if operands[0] == operands[2]
422 $asm.puts "#{opcode} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
423 elsif operands[1] == operands[2]
424 $asm.puts "#{opcode} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
425 else
426 $asm.puts "mov#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
427 $asm.puts "#{opcode} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
428 end
429 else
430 $asm.puts "#{opcode} #{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}"
431 end
432 end
433
434 def handleX86Op(opcode, kind)
435 handleX86OpWithNumOperands(opcode, kind, operands.size)
436 end
437
438 def handleX86Shift(opcode, kind)
439 if operands[0].is_a? Immediate or operands[0] == RegisterID.forName(nil, "t2")
440 $asm.puts "#{opcode} #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(kind)}"
441 else
442 cx = RegisterID.forName(nil, "t2")
443 $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}"
444 $asm.puts "#{opcode} %cl, #{operands[1].x86Operand(kind)}"
445 $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}"
446 end
447 end
448
449 def handleX86DoubleBranch(branchOpcode, mode)
450 case mode
451 when :normal
452 $asm.puts "ucomisd #{operands[1].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
453 when :reverse
454 $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
455 else
456 raise mode.inspect
457 end
458 $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
459 end
460
461 def handleX86IntCompare(opcodeSuffix, kind)
462 if operands[0].is_a? Immediate and operands[0].value == 0 and operands[1].is_a? RegisterID and (opcodeSuffix == "e" or opcodeSuffix == "ne")
463 $asm.puts "test#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}"
464 elsif operands[1].is_a? Immediate and operands[1].value == 0 and operands[0].is_a? RegisterID and (opcodeSuffix == "e" or opcodeSuffix == "ne")
465 $asm.puts "test#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}"
466 else
467 $asm.puts "cmp#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[0].x86Operand(kind)}"
468 end
469 end
470
471 def handleX86IntBranch(branchOpcode, kind)
472 handleX86IntCompare(branchOpcode[1..-1], kind)
473 $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
474 end
475
476 def handleX86Set(setOpcode, operand)
477 if operand.supports8BitOnX86
478 $asm.puts "#{setOpcode} #{operand.x86Operand(:byte)}"
479 $asm.puts "movzbl #{operand.x86Operand(:byte)}, #{operand.x86Operand(:int)}"
480 else
481 ax = RegisterID.new(nil, "t0")
482 $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}"
483 $asm.puts "#{setOpcode} %al"
484 $asm.puts "movzbl %al, %eax"
485 $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}"
486 end
487 end
488
489 def handleX86IntCompareSet(setOpcode, kind)
490 handleX86IntCompare(setOpcode[3..-1], kind)
491 handleX86Set(setOpcode, operands[2])
492 end
493
494 def handleX86Test(kind)
495 value = operands[0]
496 case operands.size
497 when 2
498 mask = Immediate.new(codeOrigin, -1)
499 when 3
500 mask = operands[1]
501 else
502 raise "Expected 2 or 3 operands, but got #{operands.size} at #{codeOriginString}"
503 end
504
505 if mask.is_a? Immediate and mask.value == -1
506 if value.is_a? RegisterID
507 $asm.puts "test#{x86Suffix(kind)} #{value.x86Operand(kind)}, #{value.x86Operand(kind)}"
508 else
509 $asm.puts "cmp#{x86Suffix(kind)} $0, #{value.x86Operand(kind)}"
510 end
511 else
512 $asm.puts "test#{x86Suffix(kind)} #{mask.x86Operand(kind)}, #{value.x86Operand(kind)}"
513 end
514 end
515
516 def handleX86BranchTest(branchOpcode, kind)
517 handleX86Test(kind)
518 $asm.puts "#{branchOpcode} #{operands.last.asmLabel}"
519 end
520
521 def handleX86SetTest(setOpcode, kind)
522 handleX86Test(kind)
523 handleX86Set(setOpcode, operands.last)
524 end
525
526 def handleX86OpBranch(opcode, branchOpcode, kind)
527 handleX86OpWithNumOperands(opcode, kind, operands.size - 1)
528 case operands.size
529 when 4
530 jumpTarget = operands[3]
531 when 3
532 jumpTarget = operands[2]
533 else
534 raise self.inspect
535 end
536 $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}"
537 end
538
539 def handleX86SubBranch(branchOpcode, kind)
540 if operands.size == 4 and operands[1] == operands[2]
541 $asm.puts "neg#{x86Suffix(kind)} #{operands[2].x86Operand(kind)}"
542 $asm.puts "add#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
543 else
544 handleX86OpWithNumOperands("sub#{x86Suffix(kind)}", kind, operands.size - 1)
545 end
546 case operands.size
547 when 4
548 jumpTarget = operands[3]
549 when 3
550 jumpTarget = operands[2]
551 else
552 raise self.inspect
553 end
554 $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}"
555 end
556
557 def handleX86Add(kind)
558 if operands.size == 3 and operands[0].is_a? Immediate
559 raise unless operands[1].is_a? RegisterID
560 raise unless operands[2].is_a? RegisterID
561 if operands[0].value == 0
562 unless operands[1] == operands[2]
563 $asm.puts "mov#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
564 end
565 else
566 $asm.puts "lea#{x86Suffix(kind)} #{operands[0].value}(#{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}"
567 end
568 elsif operands.size == 3 and operands[0].is_a? RegisterID
569 raise unless operands[1].is_a? RegisterID
570 raise unless operands[2].is_a? RegisterID
571 $asm.puts "lea#{x86Suffix(kind)} (#{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}"
572 else
573 unless Immediate.new(nil, 0) == operands[0]
574 $asm.puts "add#{x86Suffix(kind)} #{x86Operands(kind, kind)}"
575 end
576 end
577 end
578
579 def handleX86Sub(kind)
580 if operands.size == 3 and operands[1] == operands[2]
581 $asm.puts "neg#{x86Suffix(kind)} #{operands[2].x86Operand(kind)}"
582 $asm.puts "add#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
583 else
584 handleX86Op("sub#{x86Suffix(kind)}", kind)
585 end
586 end
587
588 def handleX86Mul(kind)
589 if operands.size == 3 and operands[0].is_a? Immediate
590 $asm.puts "imul#{x86Suffix(kind)} #{x86Operands(kind, kind, kind)}"
591 else
592 # FIXME: could do some peephole in case the left operand is immediate and it's
593 # a power of two.
594 handleX86Op("imul#{x86Suffix(kind)}", kind)
595 end
596 end
597
598 def handleMove
599 if Immediate.new(nil, 0) == operands[0] and operands[1].is_a? RegisterID
600 $asm.puts "xor#{x86Suffix(:ptr)} #{operands[1].x86Operand(:ptr)}, #{operands[1].x86Operand(:ptr)}"
601 elsif operands[0] != operands[1]
602 $asm.puts "mov#{x86Suffix(:ptr)} #{x86Operands(:ptr, :ptr)}"
603 end
604 end
605
606 def lowerX86
607 raise unless $activeBackend == "X86"
608 lowerX86Common
609 end
610
611 def lowerX86_64
612 raise unless $activeBackend == "X86_64"
613 lowerX86Common
614 end
615
616 def lowerX86Common
617 $asm.comment codeOriginString
618 case opcode
619 when "addi"
620 handleX86Add(:int)
621 when "addp"
622 handleX86Add(:ptr)
623 when "andi"
624 handleX86Op("andl", :int)
625 when "andp"
626 handleX86Op("and#{x86Suffix(:ptr)}", :ptr)
627 when "lshifti"
628 handleX86Shift("sall", :int)
629 when "lshiftp"
630 handleX86Shift("sal#{x86Suffix(:ptr)}", :ptr)
631 when "muli"
632 handleX86Mul(:int)
633 when "mulp"
634 handleX86Mul(:ptr)
635 when "negi"
636 $asm.puts "negl #{x86Operands(:int)}"
637 when "negp"
638 $asm.puts "neg#{x86Suffix(:ptr)} #{x86Operands(:ptr)}"
639 when "noti"
640 $asm.puts "notl #{x86Operands(:int)}"
641 when "ori"
642 handleX86Op("orl", :int)
643 when "orp"
644 handleX86Op("or#{x86Suffix(:ptr)}", :ptr)
645 when "rshifti"
646 handleX86Shift("sarl", :int)
647 when "rshiftp"
648 handleX86Shift("sar#{x86Suffix(:ptr)}", :ptr)
649 when "urshifti"
650 handleX86Shift("shrl", :int)
651 when "urshiftp"
652 handleX86Shift("shr#{x86Suffix(:ptr)}", :ptr)
653 when "subi"
654 handleX86Sub(:int)
655 when "subp"
656 handleX86Sub(:ptr)
657 when "xori"
658 handleX86Op("xorl", :int)
659 when "xorp"
660 handleX86Op("xor#{x86Suffix(:ptr)}", :ptr)
661 when "loadi", "storei"
662 $asm.puts "movl #{x86Operands(:int, :int)}"
663 when "loadis"
664 if isX64
665 $asm.puts "movslq #{x86Operands(:int, :ptr)}"
666 else
667 $asm.puts "movl #{x86Operands(:int, :int)}"
668 end
669 when "loadp", "storep"
670 $asm.puts "mov#{x86Suffix(:ptr)} #{x86Operands(:ptr, :ptr)}"
671 when "loadb"
672 $asm.puts "movzbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
673 when "loadbs"
674 $asm.puts "movsbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
675 when "loadh"
676 $asm.puts "movzwl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}"
677 when "loadhs"
678 $asm.puts "movswl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}"
679 when "storeb"
680 $asm.puts "movb #{x86Operands(:byte, :byte)}"
681 when "loadd", "moved", "stored"
682 $asm.puts "movsd #{x86Operands(:double, :double)}"
683 when "addd"
684 $asm.puts "addsd #{x86Operands(:double, :double)}"
685 when "divd"
686 $asm.puts "divsd #{x86Operands(:double, :double)}"
687 when "subd"
688 $asm.puts "subsd #{x86Operands(:double, :double)}"
689 when "muld"
690 $asm.puts "mulsd #{x86Operands(:double, :double)}"
691 when "sqrtd"
692 $asm.puts "sqrtsd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
693 when "ci2d"
694 $asm.puts "cvtsi2sd #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:double)}"
695 when "bdeq"
696 isUnordered = LocalLabel.unique("bdeq")
697 $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
698 $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
699 $asm.puts "je #{LabelReference.new(codeOrigin, operands[2]).asmLabel}"
700 isUnordered.lower("X86")
701 when "bdneq"
702 handleX86DoubleBranch("jne", :normal)
703 when "bdgt"
704 handleX86DoubleBranch("ja", :normal)
705 when "bdgteq"
706 handleX86DoubleBranch("jae", :normal)
707 when "bdlt"
708 handleX86DoubleBranch("ja", :reverse)
709 when "bdlteq"
710 handleX86DoubleBranch("jae", :reverse)
711 when "bdequn"
712 handleX86DoubleBranch("je", :normal)
713 when "bdnequn"
714 isUnordered = LocalLabel.unique("bdnequn")
715 isEqual = LocalLabel.unique("bdnequn")
716 $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
717 $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
718 $asm.puts "je #{LabelReference.new(codeOrigin, isEqual).asmLabel}"
719 isUnordered.lower("X86")
720 $asm.puts "jmp #{operands[2].asmLabel}"
721 isEqual.lower("X86")
722 when "bdgtun"
723 handleX86DoubleBranch("jb", :reverse)
724 when "bdgtequn"
725 handleX86DoubleBranch("jbe", :reverse)
726 when "bdltun"
727 handleX86DoubleBranch("jb", :normal)
728 when "bdltequn"
729 handleX86DoubleBranch("jbe", :normal)
730 when "btd2i"
731 $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
732 $asm.puts "cmpl $0x80000000 #{operands[1].x86Operand(:int)}"
733 $asm.puts "je #{operands[2].asmLabel}"
734 when "td2i"
735 $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
736 when "bcd2i"
737 $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
738 $asm.puts "testl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
739 $asm.puts "je #{operands[2].asmLabel}"
740 $asm.puts "cvtsi2sd #{operands[1].x86Operand(:int)}, %xmm7"
741 $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, %xmm7"
742 $asm.puts "jp #{operands[2].asmLabel}"
743 $asm.puts "jne #{operands[2].asmLabel}"
744 when "movdz"
745 $asm.puts "xorpd #{operands[0].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
746 when "pop"
747 $asm.puts "pop #{operands[0].x86Operand(:ptr)}"
748 when "push"
749 $asm.puts "push #{operands[0].x86Operand(:ptr)}"
750 when "move"
751 handleMove
752 when "sxi2p"
753 if isX64
754 $asm.puts "movslq #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:ptr)}"
755 else
756 handleMove
757 end
758 when "zxi2p"
759 if isX64
760 $asm.puts "movl #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
761 else
762 handleMove
763 end
764 when "nop"
765 $asm.puts "nop"
766 when "bieq"
767 handleX86IntBranch("je", :int)
768 when "bpeq"
769 handleX86IntBranch("je", :ptr)
770 when "bineq"
771 handleX86IntBranch("jne", :int)
772 when "bpneq"
773 handleX86IntBranch("jne", :ptr)
774 when "bia"
775 handleX86IntBranch("ja", :int)
776 when "bpa"
777 handleX86IntBranch("ja", :ptr)
778 when "biaeq"
779 handleX86IntBranch("jae", :int)
780 when "bpaeq"
781 handleX86IntBranch("jae", :ptr)
782 when "bib"
783 handleX86IntBranch("jb", :int)
784 when "bpb"
785 handleX86IntBranch("jb", :ptr)
786 when "bibeq"
787 handleX86IntBranch("jbe", :int)
788 when "bpbeq"
789 handleX86IntBranch("jbe", :ptr)
790 when "bigt"
791 handleX86IntBranch("jg", :int)
792 when "bpgt"
793 handleX86IntBranch("jg", :ptr)
794 when "bigteq"
795 handleX86IntBranch("jge", :int)
796 when "bpgteq"
797 handleX86IntBranch("jge", :ptr)
798 when "bilt"
799 handleX86IntBranch("jl", :int)
800 when "bplt"
801 handleX86IntBranch("jl", :ptr)
802 when "bilteq"
803 handleX86IntBranch("jle", :int)
804 when "bplteq"
805 handleX86IntBranch("jle", :ptr)
806 when "bbeq"
807 handleX86IntBranch("je", :byte)
808 when "bbneq"
809 handleX86IntBranch("jne", :byte)
810 when "bba"
811 handleX86IntBranch("ja", :byte)
812 when "bbaeq"
813 handleX86IntBranch("jae", :byte)
814 when "bbb"
815 handleX86IntBranch("jb", :byte)
816 when "bbbeq"
817 handleX86IntBranch("jbe", :byte)
818 when "bbgt"
819 handleX86IntBranch("jg", :byte)
820 when "bbgteq"
821 handleX86IntBranch("jge", :byte)
822 when "bblt"
823 handleX86IntBranch("jl", :byte)
824 when "bblteq"
825 handleX86IntBranch("jlteq", :byte)
826 when "btio"
827 handleX86BranchTest("jo", :int)
828 when "btpo"
829 handleX86BranchTest("jo", :ptr)
830 when "btis"
831 handleX86BranchTest("js", :int)
832 when "btps"
833 handleX86BranchTest("js", :ptr)
834 when "btiz"
835 handleX86BranchTest("jz", :int)
836 when "btpz"
837 handleX86BranchTest("jz", :ptr)
838 when "btinz"
839 handleX86BranchTest("jnz", :int)
840 when "btpnz"
841 handleX86BranchTest("jnz", :ptr)
842 when "btbo"
843 handleX86BranchTest("jo", :byte)
844 when "btbs"
845 handleX86BranchTest("js", :byte)
846 when "btbz"
847 handleX86BranchTest("jz", :byte)
848 when "btbnz"
849 handleX86BranchTest("jnz", :byte)
850 when "jmp"
851 $asm.puts "jmp #{operands[0].x86CallOperand(:ptr)}"
852 when "baddio"
853 handleX86OpBranch("addl", "jo", :int)
854 when "baddpo"
855 handleX86OpBranch("add#{x86Suffix(:ptr)}", "jo", :ptr)
856 when "baddis"
857 handleX86OpBranch("addl", "js", :int)
858 when "baddps"
859 handleX86OpBranch("add#{x86Suffix(:ptr)}", "js", :ptr)
860 when "baddiz"
861 handleX86OpBranch("addl", "jz", :int)
862 when "baddpz"
863 handleX86OpBranch("add#{x86Suffix(:ptr)}", "jz", :ptr)
864 when "baddinz"
865 handleX86OpBranch("addl", "jnz", :int)
866 when "baddpnz"
867 handleX86OpBranch("add#{x86Suffix(:ptr)}", "jnz", :ptr)
868 when "bsubio"
869 handleX86SubBranch("jo", :int)
870 when "bsubis"
871 handleX86SubBranch("js", :int)
872 when "bsubiz"
873 handleX86SubBranch("jz", :int)
874 when "bsubinz"
875 handleX86SubBranch("jnz", :int)
876 when "bmulio"
877 handleX86OpBranch("imull", "jo", :int)
878 when "bmulis"
879 handleX86OpBranch("imull", "js", :int)
880 when "bmuliz"
881 handleX86OpBranch("imull", "jz", :int)
882 when "bmulinz"
883 handleX86OpBranch("imull", "jnz", :int)
884 when "borio"
885 handleX86OpBranch("orl", "jo", :int)
886 when "boris"
887 handleX86OpBranch("orl", "js", :int)
888 when "boriz"
889 handleX86OpBranch("orl", "jz", :int)
890 when "borinz"
891 handleX86OpBranch("orl", "jnz", :int)
892 when "break"
893 $asm.puts "int $3"
894 when "call"
895 $asm.puts "call #{operands[0].x86CallOperand(:ptr)}"
896 when "ret"
897 $asm.puts "ret"
898 when "cieq"
899 handleX86IntCompareSet("sete", :int)
900 when "cbeq"
901 handleX86IntCompareSet("sete", :byte)
902 when "cpeq"
903 handleX86IntCompareSet("sete", :ptr)
904 when "cineq"
905 handleX86IntCompareSet("setne", :int)
906 when "cbneq"
907 handleX86IntCompareSet("setne", :byte)
908 when "cpneq"
909 handleX86IntCompareSet("setne", :ptr)
910 when "cia"
911 handleX86IntCompareSet("seta", :int)
912 when "cba"
913 handleX86IntCompareSet("seta", :byte)
914 when "cpa"
915 handleX86IntCompareSet("seta", :ptr)
916 when "ciaeq"
917 handleX86IntCompareSet("setae", :int)
918 when "cbaeq"
919 handleX86IntCompareSet("setae", :byte)
920 when "cpaeq"
921 handleX86IntCompareSet("setae", :ptr)
922 when "cib"
923 handleX86IntCompareSet("setb", :int)
924 when "cbb"
925 handleX86IntCompareSet("setb", :byte)
926 when "cpb"
927 handleX86IntCompareSet("setb", :ptr)
928 when "cibeq"
929 handleX86IntCompareSet("setbe", :int)
930 when "cbbeq"
931 handleX86IntCompareSet("setbe", :byte)
932 when "cpbeq"
933 handleX86IntCompareSet("setbe", :ptr)
934 when "cigt"
935 handleX86IntCompareSet("setg", :int)
936 when "cbgt"
937 handleX86IntCompareSet("setg", :byte)
938 when "cpgt"
939 handleX86IntCompareSet("setg", :ptr)
940 when "cigteq"
941 handleX86IntCompareSet("setge", :int)
942 when "cbgteq"
943 handleX86IntCompareSet("setge", :byte)
944 when "cpgteq"
945 handleX86IntCompareSet("setge", :ptr)
946 when "cilt"
947 handleX86IntCompareSet("setl", :int)
948 when "cblt"
949 handleX86IntCompareSet("setl", :byte)
950 when "cplt"
951 handleX86IntCompareSet("setl", :ptr)
952 when "cilteq"
953 handleX86IntCompareSet("setle", :int)
954 when "cblteq"
955 handleX86IntCompareSet("setle", :byte)
956 when "cplteq"
957 handleX86IntCompareSet("setle", :ptr)
958 when "tio"
959 handleX86SetTest("seto", :int)
960 when "tis"
961 handleX86SetTest("sets", :int)
962 when "tiz"
963 handleX86SetTest("setz", :int)
964 when "tinz"
965 handleX86SetTest("setnz", :int)
966 when "tpo"
967 handleX86SetTest("seto", :ptr)
968 when "tps"
969 handleX86SetTest("sets", :ptr)
970 when "tpz"
971 handleX86SetTest("setz", :ptr)
972 when "tpnz"
973 handleX86SetTest("setnz", :ptr)
974 when "tbo"
975 handleX86SetTest("seto", :byte)
976 when "tbs"
977 handleX86SetTest("sets", :byte)
978 when "tbz"
979 handleX86SetTest("setz", :byte)
980 when "tbnz"
981 handleX86SetTest("setnz", :byte)
982 when "peek"
983 sp = RegisterID.new(nil, "sp")
984 $asm.puts "mov#{x86Suffix(:ptr)} #{operands[0].value * x86Bytes(:ptr)}(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:ptr)}"
985 when "poke"
986 sp = RegisterID.new(nil, "sp")
987 $asm.puts "mov#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{operands[1].value * x86Bytes(:ptr)}(#{sp.x86Operand(:ptr)})"
988 when "cdqi"
989 $asm.puts "cdq"
990 when "idivi"
991 $asm.puts "idivl #{operands[0].x86Operand(:int)}"
992 when "fii2d"
993 $asm.puts "movd #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:double)}"
994 $asm.puts "movd #{operands[1].x86Operand(:int)}, %xmm7"
995 $asm.puts "psllq $32, %xmm7"
996 $asm.puts "por %xmm7, #{operands[2].x86Operand(:double)}"
997 when "fd2ii"
998 $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
999 $asm.puts "movsd #{operands[0].x86Operand(:double)}, %xmm7"
1000 $asm.puts "psrlq $32, %xmm7"
1001 $asm.puts "movsd %xmm7, #{operands[2].x86Operand(:int)}"
1002 when "fp2d"
1003 $asm.puts "movd #{operands[0].x86Operand(:ptr)}, #{operands[1].x86Operand(:double)}"
1004 when "fd2p"
1005 $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:ptr)}"
1006 when "bo"
1007 $asm.puts "jo #{operands[0].asmLabel}"
1008 when "bs"
1009 $asm.puts "js #{operands[0].asmLabel}"
1010 when "bz"
1011 $asm.puts "jz #{operands[0].asmLabel}"
1012 when "bnz"
1013 $asm.puts "jnz #{operands[0].asmLabel}"
1014 when "leai"
1015 $asm.puts "leal #{operands[0].x86AddressOperand(:int)}, #{operands[1].x86Operand(:int)}"
1016 when "leap"
1017 $asm.puts "lea#{x86Suffix(:ptr)} #{operands[0].x86AddressOperand(:ptr)}, #{operands[1].x86Operand(:ptr)}"
1018 else
1019 raise "Bad opcode: #{opcode}"
1020 end
1021 end
1022end
1023