]> git.saurik.com Git - apple/javascriptcore.git/blob - offlineasm/x86.rb
JavaScriptCore-1218.34.tar.gz
[apple/javascriptcore.git] / offlineasm / x86.rb
1 # Copyright (C) 2012 Apple Inc. All rights reserved.
2 # Copyright (C) 2013 Digia Plc. and/or its subsidiary(-ies)
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. AND ITS CONTRIBUTORS ``AS IS''
14 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 # THE POSSIBILITY OF SUCH DAMAGE.
24
25 require "config"
26
27 def isX64
28 case $activeBackend
29 when "X86"
30 false
31 when "X86_64"
32 true
33 else
34 raise "bad value for $activeBackend: #{$activeBackend}"
35 end
36 end
37
38 def useX87
39 case $activeBackend
40 when "X86"
41 true
42 when "X86_64"
43 false
44 else
45 raise "bad value for $activeBackend: #{$activeBackend}"
46 end
47 end
48
49 class SpecialRegister
50 def x86Operand(kind)
51 raise unless @name =~ /^r/
52 raise unless isX64
53 case kind
54 when :half
55 "%" + @name + "w"
56 when :int
57 "%" + @name + "d"
58 when :ptr
59 "%" + @name
60 when :quad
61 "%" + @name
62 else
63 raise
64 end
65 end
66 def x86CallOperand(kind)
67 # Call operands are not allowed to be partial registers.
68 "*#{x86Operand(:quad)}"
69 end
70 end
71
72 X64_SCRATCH_REGISTER = SpecialRegister.new("r11")
73
74 class RegisterID
75 def supports8BitOnX86
76 case name
77 when "t0", "a0", "r0", "t1", "a1", "r1", "t2", "t3"
78 true
79 when "cfr", "ttnr", "tmr"
80 false
81 when "t4", "t5"
82 isX64
83 else
84 raise
85 end
86 end
87
88 def x86Operand(kind)
89 case name
90 when "t0", "a0", "r0"
91 case kind
92 when :byte
93 "%al"
94 when :half
95 "%ax"
96 when :int
97 "%eax"
98 when :ptr
99 isX64 ? "%rax" : "%eax"
100 when :quad
101 isX64 ? "%rax" : raise
102 else
103 raise
104 end
105 when "t1", "a1", "r1"
106 case kind
107 when :byte
108 "%dl"
109 when :half
110 "%dx"
111 when :int
112 "%edx"
113 when :ptr
114 isX64 ? "%rdx" : "%edx"
115 when :quad
116 isX64 ? "%rdx" : raise
117 else
118 raise
119 end
120 when "t2"
121 case kind
122 when :byte
123 "%cl"
124 when :half
125 "%cx"
126 when :int
127 "%ecx"
128 when :ptr
129 isX64 ? "%rcx" : "%ecx"
130 when :quad
131 isX64 ? "%rcx" : raise
132 else
133 raise
134 end
135 when "t3"
136 case kind
137 when :byte
138 "%bl"
139 when :half
140 "%bx"
141 when :int
142 "%ebx"
143 when :ptr
144 isX64 ? "%rbx" : "%ebx"
145 when :quad
146 isX64 ? "%rbx" : raise
147 else
148 raise
149 end
150 when "t4"
151 case kind
152 when :byte
153 "%sil"
154 when :half
155 "%si"
156 when :int
157 "%esi"
158 when :ptr
159 isX64 ? "%rsi" : "%esi"
160 when :quad
161 isX64 ? "%rsi" : raise
162 else
163 raise
164 end
165 when "cfr"
166 if isX64
167 case kind
168 when :half
169 "%r13w"
170 when :int
171 "%r13d"
172 when :ptr
173 "%r13"
174 when :quad
175 "%r13"
176 else
177 raise
178 end
179 else
180 case kind
181 when :byte
182 "%dil"
183 when :half
184 "%di"
185 when :int
186 "%edi"
187 when :ptr
188 "%edi"
189 else
190 raise
191 end
192 end
193 when "sp"
194 case kind
195 when :byte
196 "%spl"
197 when :half
198 "%sp"
199 when :int
200 "%esp"
201 when :ptr
202 isX64 ? "%rsp" : "%esp"
203 when :quad
204 isX64 ? "%rsp" : raise
205 else
206 raise
207 end
208 when "t5"
209 raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
210 case kind
211 when :byte
212 "%dil"
213 when :half
214 "%di"
215 when :int
216 "%edi"
217 when :ptr
218 "%rdi"
219 when :quad
220 "%rdi"
221 end
222 when "t6"
223 raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
224 case kind
225 when :half
226 "%r10w"
227 when :int
228 "%r10d"
229 when :ptr
230 "%r10"
231 when :quad
232 "%r10"
233 end
234 when "csr1"
235 raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
236 case kind
237 when :half
238 "%r14w"
239 when :int
240 "%r14d"
241 when :ptr
242 "%r14"
243 when :quad
244 "%r14"
245 end
246 when "csr2"
247 raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
248 case kind
249 when :half
250 "%r15w"
251 when :int
252 "%r15d"
253 when :ptr
254 "%r15"
255 when :quad
256 "%r15"
257 end
258 else
259 raise "Bad register #{name} for X86 at #{codeOriginString}"
260 end
261 end
262 def x86CallOperand(kind)
263 isX64 ? "*#{x86Operand(:quad)}" : "*#{x86Operand(:ptr)}"
264 end
265 end
266
267 class FPRegisterID
268 def x86Operand(kind)
269 raise unless kind == :double
270 raise if useX87
271 case name
272 when "ft0", "fa0", "fr"
273 "%xmm0"
274 when "ft1", "fa1"
275 "%xmm1"
276 when "ft2", "fa2"
277 "%xmm2"
278 when "ft3", "fa3"
279 "%xmm3"
280 when "ft4"
281 "%xmm4"
282 when "ft5"
283 "%xmm5"
284 else
285 raise "Bad register #{name} for X86 at #{codeOriginString}"
286 end
287 end
288 def x87DefaultStackPosition
289 case name
290 when "ft0", "fr"
291 0
292 when "ft1"
293 1
294 when "ft2", "ft3", "ft4", "ft5"
295 raise "Unimplemented register #{name} for X86 at #{codeOriginString}"
296 else
297 raise "Bad register #{name} for X86 at #{codeOriginString}"
298 end
299 end
300 def x87Operand(offset)
301 raise unless useX87
302 raise unless offset == 0 or offset == 1
303 "%st(#{x87DefaultStackPosition + offset})"
304 end
305 def x86CallOperand(kind)
306 "*#{x86Operand(kind)}"
307 end
308 end
309
310 class Immediate
311 def validX86Immediate?
312 if isX64
313 value >= -0x80000000 and value <= 0x7fffffff
314 else
315 true
316 end
317 end
318 def x86Operand(kind)
319 "$#{value}"
320 end
321 def x86CallOperand(kind)
322 "#{value}"
323 end
324 end
325
326 class Address
327 def supports8BitOnX86
328 true
329 end
330
331 def x86AddressOperand(addressKind)
332 "#{offset.value}(#{base.x86Operand(addressKind)})"
333 end
334 def x86Operand(kind)
335 x86AddressOperand(:ptr)
336 end
337 def x86CallOperand(kind)
338 "*#{x86Operand(kind)}"
339 end
340 end
341
342 class BaseIndex
343 def supports8BitOnX86
344 true
345 end
346
347 def x86AddressOperand(addressKind)
348 "#{offset.value}(#{base.x86Operand(addressKind)}, #{index.x86Operand(addressKind)}, #{scale})"
349 end
350
351 def x86Operand(kind)
352 x86AddressOperand(:ptr)
353 end
354
355 def x86CallOperand(kind)
356 "*#{x86Operand(kind)}"
357 end
358 end
359
360 class AbsoluteAddress
361 def supports8BitOnX86
362 true
363 end
364
365 def x86AddressOperand(addressKind)
366 "#{address.value}"
367 end
368
369 def x86Operand(kind)
370 "#{address.value}"
371 end
372
373 def x86CallOperand(kind)
374 "*#{address.value}"
375 end
376 end
377
378 class LabelReference
379 def x86CallOperand(kind)
380 asmLabel
381 end
382 end
383
384 class LocalLabelReference
385 def x86CallOperand(kind)
386 asmLabel
387 end
388 end
389
390 class Sequence
391 def getModifiedListX86_64
392 newList = []
393
394 @list.each {
395 | node |
396 newNode = node
397 if node.is_a? Instruction
398 unless node.opcode == "move"
399 usedScratch = false
400 newOperands = node.operands.map {
401 | operand |
402 if operand.immediate? and not operand.validX86Immediate?
403 if usedScratch
404 raise "Attempt to use scratch register twice at #{operand.codeOriginString}"
405 end
406 newList << Instruction.new(operand.codeOrigin, "move", [operand, X64_SCRATCH_REGISTER])
407 usedScratch = true
408 X64_SCRATCH_REGISTER
409 else
410 operand
411 end
412 }
413 newNode = Instruction.new(node.codeOrigin, node.opcode, newOperands, node.annotation)
414 end
415 else
416 unless node.is_a? Label or
417 node.is_a? LocalLabel or
418 node.is_a? Skip
419 raise "Unexpected #{node.inspect} at #{node.codeOrigin}"
420 end
421 end
422 if newNode
423 newList << newNode
424 end
425 }
426
427 return newList
428 end
429 end
430
431 class Instruction
432 def x86Operands(*kinds)
433 raise unless kinds.size == operands.size
434 result = []
435 kinds.size.times {
436 | idx |
437 result << operands[idx].x86Operand(kinds[idx])
438 }
439 result.join(", ")
440 end
441
442 def x86Suffix(kind)
443 case kind
444 when :byte
445 "b"
446 when :half
447 "w"
448 when :int
449 "l"
450 when :ptr
451 isX64 ? "q" : "l"
452 when :quad
453 isX64 ? "q" : raise
454 when :double
455 not useX87 ? "sd" : raise
456 else
457 raise
458 end
459 end
460
461 def x86Bytes(kind)
462 case kind
463 when :byte
464 1
465 when :half
466 2
467 when :int
468 4
469 when :ptr
470 isX64 ? 8 : 4
471 when :quad
472 isX64 ? 8 : raise
473 when :double
474 8
475 else
476 raise
477 end
478 end
479
480 def handleX86OpWithNumOperands(opcode, kind, numOperands)
481 if numOperands == 3
482 if operands[0] == operands[2]
483 $asm.puts "#{opcode} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
484 elsif operands[1] == operands[2]
485 $asm.puts "#{opcode} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
486 else
487 $asm.puts "mov#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
488 $asm.puts "#{opcode} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
489 end
490 else
491 $asm.puts "#{opcode} #{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}"
492 end
493 end
494
495 def handleX86Op(opcode, kind)
496 handleX86OpWithNumOperands(opcode, kind, operands.size)
497 end
498
499 def handleX86Shift(opcode, kind)
500 if operands[0].is_a? Immediate or operands[0] == RegisterID.forName(nil, "t2")
501 $asm.puts "#{opcode} #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(kind)}"
502 else
503 cx = RegisterID.forName(nil, "t2")
504 $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}"
505 $asm.puts "#{opcode} %cl, #{operands[1].x86Operand(kind)}"
506 $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}"
507 end
508 end
509
510 def handleX86DoubleBranch(branchOpcode, mode)
511 if useX87
512 handleX87Compare(mode)
513 else
514 case mode
515 when :normal
516 $asm.puts "ucomisd #{operands[1].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
517 when :reverse
518 $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
519 else
520 raise mode.inspect
521 end
522 end
523 $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
524 end
525
526 def handleX86IntCompare(opcodeSuffix, kind)
527 if operands[0].is_a? Immediate and operands[0].value == 0 and operands[1].is_a? RegisterID and (opcodeSuffix == "e" or opcodeSuffix == "ne")
528 $asm.puts "test#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}"
529 elsif operands[1].is_a? Immediate and operands[1].value == 0 and operands[0].is_a? RegisterID and (opcodeSuffix == "e" or opcodeSuffix == "ne")
530 $asm.puts "test#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}"
531 else
532 $asm.puts "cmp#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[0].x86Operand(kind)}"
533 end
534 end
535
536 def handleX86IntBranch(branchOpcode, kind)
537 handleX86IntCompare(branchOpcode[1..-1], kind)
538 $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
539 end
540
541 def handleX86Set(setOpcode, operand)
542 if operand.supports8BitOnX86
543 $asm.puts "#{setOpcode} #{operand.x86Operand(:byte)}"
544 $asm.puts "movzbl #{operand.x86Operand(:byte)}, #{operand.x86Operand(:int)}"
545 else
546 ax = RegisterID.new(nil, "t0")
547 $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}"
548 $asm.puts "#{setOpcode} %al"
549 $asm.puts "movzbl %al, %eax"
550 $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}"
551 end
552 end
553
554 def handleX86IntCompareSet(setOpcode, kind)
555 handleX86IntCompare(setOpcode[3..-1], kind)
556 handleX86Set(setOpcode, operands[2])
557 end
558
559 def handleX86Test(kind)
560 value = operands[0]
561 case operands.size
562 when 2
563 mask = Immediate.new(codeOrigin, -1)
564 when 3
565 mask = operands[1]
566 else
567 raise "Expected 2 or 3 operands, but got #{operands.size} at #{codeOriginString}"
568 end
569
570 if mask.is_a? Immediate and mask.value == -1
571 if value.is_a? RegisterID
572 $asm.puts "test#{x86Suffix(kind)} #{value.x86Operand(kind)}, #{value.x86Operand(kind)}"
573 else
574 $asm.puts "cmp#{x86Suffix(kind)} $0, #{value.x86Operand(kind)}"
575 end
576 else
577 $asm.puts "test#{x86Suffix(kind)} #{mask.x86Operand(kind)}, #{value.x86Operand(kind)}"
578 end
579 end
580
581 def handleX86BranchTest(branchOpcode, kind)
582 handleX86Test(kind)
583 $asm.puts "#{branchOpcode} #{operands.last.asmLabel}"
584 end
585
586 def handleX86SetTest(setOpcode, kind)
587 handleX86Test(kind)
588 handleX86Set(setOpcode, operands.last)
589 end
590
591 def handleX86OpBranch(opcode, branchOpcode, kind)
592 handleX86OpWithNumOperands(opcode, kind, operands.size - 1)
593 case operands.size
594 when 4
595 jumpTarget = operands[3]
596 when 3
597 jumpTarget = operands[2]
598 else
599 raise self.inspect
600 end
601 $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}"
602 end
603
604 def handleX86SubBranch(branchOpcode, kind)
605 if operands.size == 4 and operands[1] == operands[2]
606 $asm.puts "neg#{x86Suffix(kind)} #{operands[2].x86Operand(kind)}"
607 $asm.puts "add#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
608 else
609 handleX86OpWithNumOperands("sub#{x86Suffix(kind)}", kind, operands.size - 1)
610 end
611 case operands.size
612 when 4
613 jumpTarget = operands[3]
614 when 3
615 jumpTarget = operands[2]
616 else
617 raise self.inspect
618 end
619 $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}"
620 end
621
622 def handleX86Add(kind)
623 if operands.size == 3 and operands[1] == operands[2]
624 unless Immediate.new(nil, 0) == operands[0]
625 $asm.puts "add#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
626 end
627 elsif operands.size == 3 and operands[0].is_a? Immediate
628 raise unless operands[1].is_a? RegisterID
629 raise unless operands[2].is_a? RegisterID
630 if operands[0].value == 0
631 unless operands[1] == operands[2]
632 $asm.puts "mov#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
633 end
634 else
635 $asm.puts "lea#{x86Suffix(kind)} #{operands[0].value}(#{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}"
636 end
637 elsif operands.size == 3 and operands[0].is_a? RegisterID
638 raise unless operands[1].is_a? RegisterID
639 raise unless operands[2].is_a? RegisterID
640 if operands[0] == operands[2]
641 $asm.puts "add#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
642 else
643 $asm.puts "lea#{x86Suffix(kind)} (#{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}"
644 end
645 else
646 unless Immediate.new(nil, 0) == operands[0]
647 $asm.puts "add#{x86Suffix(kind)} #{x86Operands(kind, kind)}"
648 end
649 end
650 end
651
652 def handleX86Sub(kind)
653 if operands.size == 3 and operands[1] == operands[2]
654 $asm.puts "neg#{x86Suffix(kind)} #{operands[2].x86Operand(kind)}"
655 $asm.puts "add#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
656 else
657 handleX86Op("sub#{x86Suffix(kind)}", kind)
658 end
659 end
660
661 def handleX86Mul(kind)
662 if operands.size == 3 and operands[0].is_a? Immediate
663 $asm.puts "imul#{x86Suffix(kind)} #{x86Operands(kind, kind, kind)}"
664 else
665 # FIXME: could do some peephole in case the left operand is immediate and it's
666 # a power of two.
667 handleX86Op("imul#{x86Suffix(kind)}", kind)
668 end
669 end
670
671 def handleMove
672 if Immediate.new(nil, 0) == operands[0] and operands[1].is_a? RegisterID
673 if isX64
674 $asm.puts "xor#{x86Suffix(:quad)} #{operands[1].x86Operand(:quad)}, #{operands[1].x86Operand(:quad)}"
675 else
676 $asm.puts "xor#{x86Suffix(:ptr)} #{operands[1].x86Operand(:ptr)}, #{operands[1].x86Operand(:ptr)}"
677 end
678 elsif operands[0] != operands[1]
679 if isX64
680 $asm.puts "mov#{x86Suffix(:quad)} #{x86Operands(:quad, :quad)}"
681 else
682 $asm.puts "mov#{x86Suffix(:ptr)} #{x86Operands(:ptr, :ptr)}"
683 end
684 end
685 end
686
687 def handleX87Compare(mode)
688 case mode
689 when :normal
690 if (operands[0].x87DefaultStackPosition == 0)
691 $asm.puts "fucomi #{operands[1].x87Operand(0)}"
692 else
693 $asm.puts "fld #{operands[0].x87Operand(0)}"
694 $asm.puts "fucomip #{operands[1].x87Operand(1)}"
695 end
696 when :reverse
697 if (operands[1].x87DefaultStackPosition == 0)
698 $asm.puts "fucomi #{operands[0].x87Operand(0)}"
699 else
700 $asm.puts "fld #{operands[1].x87Operand(0)}"
701 $asm.puts "fucomip #{operands[0].x87Operand(1)}"
702 end
703 else
704 raise mode.inspect
705 end
706 end
707
708 def handleX87BinOp(opcode, opcodereverse)
709 if (operands[1].x87DefaultStackPosition == 0)
710 $asm.puts "#{opcode} #{operands[0].x87Operand(0)}, %st"
711 elsif (operands[0].x87DefaultStackPosition == 0)
712 $asm.puts "#{opcodereverse} %st, #{operands[1].x87Operand(0)}"
713 else
714 $asm.puts "fld #{operands[0].x87Operand(0)}"
715 $asm.puts "#{opcodereverse}p %st, #{operands[1].x87Operand(1)}"
716 end
717 end
718
719 def lowerX86
720 raise unless $activeBackend == "X86"
721 lowerX86Common
722 end
723
724 def lowerX86_64
725 raise unless $activeBackend == "X86_64"
726 lowerX86Common
727 end
728
729 def lowerX86Common
730 $asm.codeOrigin codeOriginString if $enableCodeOriginComments
731 $asm.annotation annotation if $enableInstrAnnotations
732
733 case opcode
734 when "addi"
735 handleX86Add(:int)
736 when "addp"
737 handleX86Add(:ptr)
738 when "addq"
739 handleX86Add(:quad)
740 when "andi"
741 handleX86Op("andl", :int)
742 when "andp"
743 handleX86Op("and#{x86Suffix(:ptr)}", :ptr)
744 when "andq"
745 handleX86Op("and#{x86Suffix(:quad)}", :quad)
746 when "lshifti"
747 handleX86Shift("sall", :int)
748 when "lshiftp"
749 handleX86Shift("sal#{x86Suffix(:ptr)}", :ptr)
750 when "lshiftq"
751 handleX86Shift("sal#{x86Suffix(:quad)}", :quad)
752 when "muli"
753 handleX86Mul(:int)
754 when "mulp"
755 handleX86Mul(:ptr)
756 when "mulq"
757 handleX86Mul(:quad)
758 when "negi"
759 $asm.puts "negl #{x86Operands(:int)}"
760 when "negp"
761 $asm.puts "neg#{x86Suffix(:ptr)} #{x86Operands(:ptr)}"
762 when "negq"
763 $asm.puts "neg#{x86Suffix(:quad)} #{x86Operands(:quad)}"
764 when "noti"
765 $asm.puts "notl #{x86Operands(:int)}"
766 when "ori"
767 handleX86Op("orl", :int)
768 when "orp"
769 handleX86Op("or#{x86Suffix(:ptr)}", :ptr)
770 when "orq"
771 handleX86Op("or#{x86Suffix(:quad)}", :quad)
772 when "rshifti"
773 handleX86Shift("sarl", :int)
774 when "rshiftp"
775 handleX86Shift("sar#{x86Suffix(:ptr)}", :ptr)
776 when "rshiftq"
777 handleX86Shift("sar#{x86Suffix(:quad)}", :quad)
778 when "urshifti"
779 handleX86Shift("shrl", :int)
780 when "urshiftp"
781 handleX86Shift("shr#{x86Suffix(:ptr)}", :ptr)
782 when "urshiftq"
783 handleX86Shift("shr#{x86Suffix(:quad)}", :quad)
784 when "subi"
785 handleX86Sub(:int)
786 when "subp"
787 handleX86Sub(:ptr)
788 when "subq"
789 handleX86Sub(:quad)
790 when "xori"
791 handleX86Op("xorl", :int)
792 when "xorp"
793 handleX86Op("xor#{x86Suffix(:ptr)}", :ptr)
794 when "xorq"
795 handleX86Op("xor#{x86Suffix(:quad)}", :quad)
796 when "loadi", "storei"
797 $asm.puts "movl #{x86Operands(:int, :int)}"
798 when "loadis"
799 if isX64
800 $asm.puts "movslq #{x86Operands(:int, :quad)}"
801 else
802 $asm.puts "movl #{x86Operands(:int, :int)}"
803 end
804 when "loadp", "storep"
805 $asm.puts "mov#{x86Suffix(:ptr)} #{x86Operands(:ptr, :ptr)}"
806 when "loadq", "storeq"
807 $asm.puts "mov#{x86Suffix(:quad)} #{x86Operands(:quad, :quad)}"
808 when "loadb"
809 $asm.puts "movzbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
810 when "loadbs"
811 $asm.puts "movsbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
812 when "loadh"
813 $asm.puts "movzwl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}"
814 when "loadhs"
815 $asm.puts "movswl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}"
816 when "storeb"
817 $asm.puts "movb #{x86Operands(:byte, :byte)}"
818 when "loadd"
819 if useX87
820 $asm.puts "fldl #{operands[0].x86Operand(:double)}"
821 $asm.puts "fstp #{operands[1].x87Operand(1)}"
822 else
823 $asm.puts "movsd #{x86Operands(:double, :double)}"
824 end
825 when "moved"
826 if useX87
827 if (operands[0].x87DefaultStackPosition == 0)
828 $asm.puts "fst #{operands[1].x87Operand(0)}"
829 else
830 $asm.puts "fld #{operands[0].x87Operand(0)}"
831 $asm.puts "fstp #{operands[1].x87Operand(1)}"
832 end
833 else
834 $asm.puts "movsd #{x86Operands(:double, :double)}"
835 end
836 when "stored"
837 if useX87
838 if (operands[0].x87DefaultStackPosition == 0)
839 $asm.puts "fstl #{operands[1].x86Operand(:double)}"
840 else
841 $asm.puts "fld #{operands[0].x87Operand(0)}"
842 $asm.puts "fstpl #{operands[1].x86Operand(:double)}"
843 end
844 else
845 $asm.puts "movsd #{x86Operands(:double, :double)}"
846 end
847 when "addd"
848 if useX87
849 handleX87BinOp("fadd", "fadd")
850 else
851 $asm.puts "addsd #{x86Operands(:double, :double)}"
852 end
853 when "muld"
854 if useX87
855 handleX87BinOp("fmul", "fmul")
856 else
857 $asm.puts "mulsd #{x86Operands(:double, :double)}"
858 end
859 when "subd"
860 if useX87
861 handleX87BinOp("fsub", "fsubr")
862 else
863 $asm.puts "subsd #{x86Operands(:double, :double)}"
864 end
865 when "divd"
866 if useX87
867 handleX87BinOp("fdiv", "fdivr")
868 else
869 $asm.puts "divsd #{x86Operands(:double, :double)}"
870 end
871 when "sqrtd"
872 if useX87
873 $asm.puts "fld #{operands[0].x87Operand(0)}"
874 $asm.puts "fsqrtl"
875 $asm.puts "fstp #{operands[1].x87Operand(1)}"
876 else
877 $asm.puts "sqrtsd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
878 end
879 when "ci2d"
880 if useX87
881 sp = RegisterID.new(nil, "sp")
882 $asm.puts "movl #{operands[0].x86Operand(:int)}, -4(#{sp.x86Operand(:ptr)})"
883 $asm.puts "fildl -4(#{sp.x86Operand(:ptr)})"
884 $asm.puts "fstp #{operands[1].x87Operand(1)}"
885 else
886 $asm.puts "cvtsi2sd #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:double)}"
887 end
888 when "bdeq"
889 if useX87
890 handleX87Compare(:normal)
891 else
892 $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
893 end
894 if operands[0] == operands[1]
895 # This is just a jump ordered, which is a jnp.
896 $asm.puts "jnp #{operands[2].asmLabel}"
897 else
898 isUnordered = LocalLabel.unique("bdeq")
899 $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
900 $asm.puts "je #{LabelReference.new(codeOrigin, operands[2]).asmLabel}"
901 isUnordered.lower("X86")
902 end
903 when "bdneq"
904 handleX86DoubleBranch("jne", :normal)
905 when "bdgt"
906 handleX86DoubleBranch("ja", :normal)
907 when "bdgteq"
908 handleX86DoubleBranch("jae", :normal)
909 when "bdlt"
910 handleX86DoubleBranch("ja", :reverse)
911 when "bdlteq"
912 handleX86DoubleBranch("jae", :reverse)
913 when "bdequn"
914 handleX86DoubleBranch("je", :normal)
915 when "bdnequn"
916 if useX87
917 handleX87Compare(:normal)
918 else
919 $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
920 end
921 if operands[0] == operands[1]
922 # This is just a jump unordered, which is a jp.
923 $asm.puts "jp #{operands[2].asmLabel}"
924 else
925 isUnordered = LocalLabel.unique("bdnequn")
926 isEqual = LocalLabel.unique("bdnequn")
927 $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
928 $asm.puts "je #{LabelReference.new(codeOrigin, isEqual).asmLabel}"
929 isUnordered.lower("X86")
930 $asm.puts "jmp #{operands[2].asmLabel}"
931 isEqual.lower("X86")
932 end
933 when "bdgtun"
934 handleX86DoubleBranch("jb", :reverse)
935 when "bdgtequn"
936 handleX86DoubleBranch("jbe", :reverse)
937 when "bdltun"
938 handleX86DoubleBranch("jb", :normal)
939 when "bdltequn"
940 handleX86DoubleBranch("jbe", :normal)
941 when "btd2i"
942 # FIXME: unused and unimplemented for x87
943 raise if useX87
944 $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
945 $asm.puts "cmpl $0x80000000 #{operands[1].x86Operand(:int)}"
946 $asm.puts "je #{operands[2].asmLabel}"
947 when "td2i"
948 # FIXME: unused and unimplemented for x87
949 raise if useX87
950 $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
951 when "bcd2i"
952 if useX87
953 sp = RegisterID.new(nil, "sp")
954 if (operands[0].x87DefaultStackPosition == 0)
955 $asm.puts "fistl -4(#{sp.x86Operand(:ptr)})"
956 else
957 $asm.puts "fld #{operands[0].x87Operand(0)}"
958 $asm.puts "fistpl -4(#{sp.x86Operand(:ptr)})"
959 end
960 $asm.puts "movl -4(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:int)}"
961 $asm.puts "testl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
962 $asm.puts "je #{operands[2].asmLabel}"
963 $asm.puts "fildl -4(#{sp.x86Operand(:ptr)})"
964 $asm.puts "fucomip #{operands[0].x87Operand(1)}"
965 $asm.puts "jp #{operands[2].asmLabel}"
966 $asm.puts "jne #{operands[2].asmLabel}"
967 else
968 $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
969 $asm.puts "testl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
970 $asm.puts "je #{operands[2].asmLabel}"
971 $asm.puts "cvtsi2sd #{operands[1].x86Operand(:int)}, %xmm7"
972 $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, %xmm7"
973 $asm.puts "jp #{operands[2].asmLabel}"
974 $asm.puts "jne #{operands[2].asmLabel}"
975 end
976 when "movdz"
977 if useX87
978 $asm.puts "fldzl"
979 $asm.puts "fstp #{operands[0].x87Operand(1)}"
980 else
981 $asm.puts "xorpd #{operands[0].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
982 end
983 when "pop"
984 $asm.puts "pop #{operands[0].x86Operand(:ptr)}"
985 when "push"
986 $asm.puts "push #{operands[0].x86Operand(:ptr)}"
987 when "move"
988 handleMove
989 when "sxi2q"
990 $asm.puts "movslq #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:quad)}"
991 when "zxi2q"
992 $asm.puts "movl #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
993 when "nop"
994 $asm.puts "nop"
995 when "bieq"
996 handleX86IntBranch("je", :int)
997 when "bpeq"
998 handleX86IntBranch("je", :ptr)
999 when "bqeq"
1000 handleX86IntBranch("je", :quad)
1001 when "bineq"
1002 handleX86IntBranch("jne", :int)
1003 when "bpneq"
1004 handleX86IntBranch("jne", :ptr)
1005 when "bqneq"
1006 handleX86IntBranch("jne", :quad)
1007 when "bia"
1008 handleX86IntBranch("ja", :int)
1009 when "bpa"
1010 handleX86IntBranch("ja", :ptr)
1011 when "bqa"
1012 handleX86IntBranch("ja", :quad)
1013 when "biaeq"
1014 handleX86IntBranch("jae", :int)
1015 when "bpaeq"
1016 handleX86IntBranch("jae", :ptr)
1017 when "bqaeq"
1018 handleX86IntBranch("jae", :quad)
1019 when "bib"
1020 handleX86IntBranch("jb", :int)
1021 when "bpb"
1022 handleX86IntBranch("jb", :ptr)
1023 when "bqb"
1024 handleX86IntBranch("jb", :quad)
1025 when "bibeq"
1026 handleX86IntBranch("jbe", :int)
1027 when "bpbeq"
1028 handleX86IntBranch("jbe", :ptr)
1029 when "bqbeq"
1030 handleX86IntBranch("jbe", :quad)
1031 when "bigt"
1032 handleX86IntBranch("jg", :int)
1033 when "bpgt"
1034 handleX86IntBranch("jg", :ptr)
1035 when "bqgt"
1036 handleX86IntBranch("jg", :quad)
1037 when "bigteq"
1038 handleX86IntBranch("jge", :int)
1039 when "bpgteq"
1040 handleX86IntBranch("jge", :ptr)
1041 when "bqgteq"
1042 handleX86IntBranch("jge", :quad)
1043 when "bilt"
1044 handleX86IntBranch("jl", :int)
1045 when "bplt"
1046 handleX86IntBranch("jl", :ptr)
1047 when "bqlt"
1048 handleX86IntBranch("jl", :quad)
1049 when "bilteq"
1050 handleX86IntBranch("jle", :int)
1051 when "bplteq"
1052 handleX86IntBranch("jle", :ptr)
1053 when "bqlteq"
1054 handleX86IntBranch("jle", :quad)
1055 when "bbeq"
1056 handleX86IntBranch("je", :byte)
1057 when "bbneq"
1058 handleX86IntBranch("jne", :byte)
1059 when "bba"
1060 handleX86IntBranch("ja", :byte)
1061 when "bbaeq"
1062 handleX86IntBranch("jae", :byte)
1063 when "bbb"
1064 handleX86IntBranch("jb", :byte)
1065 when "bbbeq"
1066 handleX86IntBranch("jbe", :byte)
1067 when "bbgt"
1068 handleX86IntBranch("jg", :byte)
1069 when "bbgteq"
1070 handleX86IntBranch("jge", :byte)
1071 when "bblt"
1072 handleX86IntBranch("jl", :byte)
1073 when "bblteq"
1074 handleX86IntBranch("jlteq", :byte)
1075 when "btis"
1076 handleX86BranchTest("js", :int)
1077 when "btps"
1078 handleX86BranchTest("js", :ptr)
1079 when "btqs"
1080 handleX86BranchTest("js", :quad)
1081 when "btiz"
1082 handleX86BranchTest("jz", :int)
1083 when "btpz"
1084 handleX86BranchTest("jz", :ptr)
1085 when "btqz"
1086 handleX86BranchTest("jz", :quad)
1087 when "btinz"
1088 handleX86BranchTest("jnz", :int)
1089 when "btpnz"
1090 handleX86BranchTest("jnz", :ptr)
1091 when "btqnz"
1092 handleX86BranchTest("jnz", :quad)
1093 when "btbs"
1094 handleX86BranchTest("js", :byte)
1095 when "btbz"
1096 handleX86BranchTest("jz", :byte)
1097 when "btbnz"
1098 handleX86BranchTest("jnz", :byte)
1099 when "jmp"
1100 $asm.puts "jmp #{operands[0].x86CallOperand(:ptr)}"
1101 when "baddio"
1102 handleX86OpBranch("addl", "jo", :int)
1103 when "baddpo"
1104 handleX86OpBranch("add#{x86Suffix(:ptr)}", "jo", :ptr)
1105 when "baddqo"
1106 handleX86OpBranch("add#{x86Suffix(:quad)}", "jo", :quad)
1107 when "baddis"
1108 handleX86OpBranch("addl", "js", :int)
1109 when "baddps"
1110 handleX86OpBranch("add#{x86Suffix(:ptr)}", "js", :ptr)
1111 when "baddqs"
1112 handleX86OpBranch("add#{x86Suffix(:quad)}", "js", :quad)
1113 when "baddiz"
1114 handleX86OpBranch("addl", "jz", :int)
1115 when "baddpz"
1116 handleX86OpBranch("add#{x86Suffix(:ptr)}", "jz", :ptr)
1117 when "baddqz"
1118 handleX86OpBranch("add#{x86Suffix(:quad)}", "jz", :quad)
1119 when "baddinz"
1120 handleX86OpBranch("addl", "jnz", :int)
1121 when "baddpnz"
1122 handleX86OpBranch("add#{x86Suffix(:ptr)}", "jnz", :ptr)
1123 when "baddqnz"
1124 handleX86OpBranch("add#{x86Suffix(:quad)}", "jnz", :quad)
1125 when "bsubio"
1126 handleX86SubBranch("jo", :int)
1127 when "bsubis"
1128 handleX86SubBranch("js", :int)
1129 when "bsubiz"
1130 handleX86SubBranch("jz", :int)
1131 when "bsubinz"
1132 handleX86SubBranch("jnz", :int)
1133 when "bmulio"
1134 handleX86OpBranch("imull", "jo", :int)
1135 when "bmulis"
1136 handleX86OpBranch("imull", "js", :int)
1137 when "bmuliz"
1138 handleX86OpBranch("imull", "jz", :int)
1139 when "bmulinz"
1140 handleX86OpBranch("imull", "jnz", :int)
1141 when "borio"
1142 handleX86OpBranch("orl", "jo", :int)
1143 when "boris"
1144 handleX86OpBranch("orl", "js", :int)
1145 when "boriz"
1146 handleX86OpBranch("orl", "jz", :int)
1147 when "borinz"
1148 handleX86OpBranch("orl", "jnz", :int)
1149 when "break"
1150 $asm.puts "int $3"
1151 when "call"
1152 $asm.puts "call #{operands[0].x86CallOperand(:ptr)}"
1153 when "ret"
1154 $asm.puts "ret"
1155 when "cieq"
1156 handleX86IntCompareSet("sete", :int)
1157 when "cbeq"
1158 handleX86IntCompareSet("sete", :byte)
1159 when "cpeq"
1160 handleX86IntCompareSet("sete", :ptr)
1161 when "cqeq"
1162 handleX86IntCompareSet("sete", :quad)
1163 when "cineq"
1164 handleX86IntCompareSet("setne", :int)
1165 when "cbneq"
1166 handleX86IntCompareSet("setne", :byte)
1167 when "cpneq"
1168 handleX86IntCompareSet("setne", :ptr)
1169 when "cqneq"
1170 handleX86IntCompareSet("setne", :quad)
1171 when "cia"
1172 handleX86IntCompareSet("seta", :int)
1173 when "cba"
1174 handleX86IntCompareSet("seta", :byte)
1175 when "cpa"
1176 handleX86IntCompareSet("seta", :ptr)
1177 when "cqa"
1178 handleX86IntCompareSet("seta", :quad)
1179 when "ciaeq"
1180 handleX86IntCompareSet("setae", :int)
1181 when "cbaeq"
1182 handleX86IntCompareSet("setae", :byte)
1183 when "cpaeq"
1184 handleX86IntCompareSet("setae", :ptr)
1185 when "cqaeq"
1186 handleX86IntCompareSet("setae", :quad)
1187 when "cib"
1188 handleX86IntCompareSet("setb", :int)
1189 when "cbb"
1190 handleX86IntCompareSet("setb", :byte)
1191 when "cpb"
1192 handleX86IntCompareSet("setb", :ptr)
1193 when "cqb"
1194 handleX86IntCompareSet("setb", :quad)
1195 when "cibeq"
1196 handleX86IntCompareSet("setbe", :int)
1197 when "cbbeq"
1198 handleX86IntCompareSet("setbe", :byte)
1199 when "cpbeq"
1200 handleX86IntCompareSet("setbe", :ptr)
1201 when "cqbeq"
1202 handleX86IntCompareSet("setbe", :quad)
1203 when "cigt"
1204 handleX86IntCompareSet("setg", :int)
1205 when "cbgt"
1206 handleX86IntCompareSet("setg", :byte)
1207 when "cpgt"
1208 handleX86IntCompareSet("setg", :ptr)
1209 when "cqgt"
1210 handleX86IntCompareSet("setg", :quad)
1211 when "cigteq"
1212 handleX86IntCompareSet("setge", :int)
1213 when "cbgteq"
1214 handleX86IntCompareSet("setge", :byte)
1215 when "cpgteq"
1216 handleX86IntCompareSet("setge", :ptr)
1217 when "cqgteq"
1218 handleX86IntCompareSet("setge", :quad)
1219 when "cilt"
1220 handleX86IntCompareSet("setl", :int)
1221 when "cblt"
1222 handleX86IntCompareSet("setl", :byte)
1223 when "cplt"
1224 handleX86IntCompareSet("setl", :ptr)
1225 when "cqlt"
1226 handleX86IntCompareSet("setl", :quad)
1227 when "cilteq"
1228 handleX86IntCompareSet("setle", :int)
1229 when "cblteq"
1230 handleX86IntCompareSet("setle", :byte)
1231 when "cplteq"
1232 handleX86IntCompareSet("setle", :ptr)
1233 when "cqlteq"
1234 handleX86IntCompareSet("setle", :quad)
1235 when "tis"
1236 handleX86SetTest("sets", :int)
1237 when "tiz"
1238 handleX86SetTest("setz", :int)
1239 when "tinz"
1240 handleX86SetTest("setnz", :int)
1241 when "tps"
1242 handleX86SetTest("sets", :ptr)
1243 when "tpz"
1244 handleX86SetTest("setz", :ptr)
1245 when "tpnz"
1246 handleX86SetTest("setnz", :ptr)
1247 when "tqs"
1248 handleX86SetTest("sets", :quad)
1249 when "tqz"
1250 handleX86SetTest("setz", :quad)
1251 when "tqnz"
1252 handleX86SetTest("setnz", :quad)
1253 when "tbs"
1254 handleX86SetTest("sets", :byte)
1255 when "tbz"
1256 handleX86SetTest("setz", :byte)
1257 when "tbnz"
1258 handleX86SetTest("setnz", :byte)
1259 when "peek"
1260 sp = RegisterID.new(nil, "sp")
1261 $asm.puts "mov#{x86Suffix(:ptr)} #{operands[0].value * x86Bytes(:ptr)}(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:ptr)}"
1262 when "peekq"
1263 sp = RegisterID.new(nil, "sp")
1264 $asm.puts "mov#{x86Suffix(:quad)} #{operands[0].value * x86Bytes(:quad)}(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:quad)}"
1265 when "poke"
1266 sp = RegisterID.new(nil, "sp")
1267 $asm.puts "mov#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{operands[1].value * x86Bytes(:ptr)}(#{sp.x86Operand(:ptr)})"
1268 when "pokeq"
1269 sp = RegisterID.new(nil, "sp")
1270 $asm.puts "mov#{x86Suffix(:quad)} #{operands[0].x86Operand(:quad)}, #{operands[1].value * x86Bytes(:quad)}(#{sp.x86Operand(:ptr)})"
1271 when "cdqi"
1272 $asm.puts "cdq"
1273 when "idivi"
1274 $asm.puts "idivl #{operands[0].x86Operand(:int)}"
1275 when "fii2d"
1276 if useX87
1277 sp = RegisterID.new(nil, "sp")
1278 $asm.puts "movl #{operands[0].x86Operand(:int)}, -8(#{sp.x86Operand(:ptr)})"
1279 $asm.puts "movl #{operands[1].x86Operand(:int)}, -4(#{sp.x86Operand(:ptr)})"
1280 $asm.puts "fldl -8(#{sp.x86Operand(:ptr)})"
1281 $asm.puts "fstp #{operands[2].x87Operand(1)}"
1282 else
1283 $asm.puts "movd #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:double)}"
1284 $asm.puts "movd #{operands[1].x86Operand(:int)}, %xmm7"
1285 $asm.puts "psllq $32, %xmm7"
1286 $asm.puts "por %xmm7, #{operands[2].x86Operand(:double)}"
1287 end
1288 when "fd2ii"
1289 if useX87
1290 sp = RegisterID.new(nil, "sp")
1291 if (operands[0].x87DefaultStackPosition == 0)
1292 $asm.puts "fstl -8(#{sp.x86Operand(:ptr)})"
1293 else
1294 $asm.puts "fld #{operands[0].x87Operand(0)}"
1295 $asm.puts "fstpl -8(#{sp.x86Operand(:ptr)})"
1296 end
1297 $asm.puts "movl -8(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:int)}"
1298 $asm.puts "movl -4(#{sp.x86Operand(:ptr)}), #{operands[2].x86Operand(:int)}"
1299 else
1300 $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
1301 $asm.puts "movsd #{operands[0].x86Operand(:double)}, %xmm7"
1302 $asm.puts "psrlq $32, %xmm7"
1303 $asm.puts "movd %xmm7, #{operands[2].x86Operand(:int)}"
1304 end
1305 when "fq2d"
1306 if useX87
1307 sp = RegisterID.new(nil, "sp")
1308 $asm.puts "movq #{operands[0].x86Operand(:quad)}, -8(#{sp.x86Operand(:ptr)})"
1309 $asm.puts "fldl -8(#{sp.x86Operand(:ptr)})"
1310 $asm.puts "fstp #{operands[1].x87Operand(1)}"
1311 else
1312 $asm.puts "movq #{operands[0].x86Operand(:quad)}, #{operands[1].x86Operand(:double)}"
1313 end
1314 when "fd2q"
1315 if useX87
1316 sp = RegisterID.new(nil, "sp")
1317 if (operands[0].x87DefaultStackPosition == 0)
1318 $asm.puts "fstl -8(#{sp.x86Operand(:ptr)})"
1319 else
1320 $asm.puts "fld #{operands[0].x87Operand(0)}"
1321 $asm.puts "fstpl -8(#{sp.x86Operand(:ptr)})"
1322 end
1323 $asm.puts "movq -8(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:quad)}"
1324 else
1325 $asm.puts "movq #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:quad)}"
1326 end
1327 when "bo"
1328 $asm.puts "jo #{operands[0].asmLabel}"
1329 when "bs"
1330 $asm.puts "js #{operands[0].asmLabel}"
1331 when "bz"
1332 $asm.puts "jz #{operands[0].asmLabel}"
1333 when "bnz"
1334 $asm.puts "jnz #{operands[0].asmLabel}"
1335 when "leai"
1336 $asm.puts "leal #{operands[0].x86AddressOperand(:int)}, #{operands[1].x86Operand(:int)}"
1337 when "leap"
1338 $asm.puts "lea#{x86Suffix(:ptr)} #{operands[0].x86AddressOperand(:ptr)}, #{operands[1].x86Operand(:ptr)}"
1339 when "resetX87Stack"
1340 if useX87
1341 2.times {
1342 | offset |
1343 $asm.puts "ffree %st(#{offset})"
1344 }
1345 end
1346 else
1347 lowerDefault
1348 end
1349 end
1350 end
1351