1 # Copyright (C) 2012 Apple Inc. All rights reserved.
2 # Copyright (C) 2013 Digia Plc. and/or its subsidiary(-ies)
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions
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.
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.
34 raise "bad value for $activeBackend: #{$activeBackend}"
45 raise "bad value for $activeBackend: #{$activeBackend}"
51 raise unless @name =~
/^r/
66 def x86CallOperand(kind
)
67 # Call operands are not allowed to be partial registers.
68 "*#{x86Operand(:quad)}"
72 X64_SCRATCH_REGISTER
= SpecialRegister
.new("r11")
77 when "t0", "a0", "r0", "t1", "a1", "r1", "t2", "t3"
79 when "cfr", "ttnr", "tmr"
99 isX64
? "%rax" : "%eax"
101 isX64
? "%rax" : raise
105 when "t1", "a1", "r1"
114 isX64
? "%rdx" : "%edx"
116 isX64
? "%rdx" : raise
129 isX64
? "%rcx" : "%ecx"
131 isX64
? "%rcx" : raise
144 isX64
? "%rbx" : "%ebx"
146 isX64
? "%rbx" : raise
159 isX64
? "%rsi" : "%esi"
161 isX64
? "%rsi" : raise
202 isX64
? "%rsp" : "%esp"
204 isX64
? "%rsp" : raise
209 raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
223 raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
235 raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
247 raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
259 raise "Bad register #{name} for X86 at #{codeOriginString}"
262 def x86CallOperand(kind
)
263 isX64
? "*#{x86Operand(:quad)}" : "*#{x86Operand(:ptr)}"
269 raise unless kind
== :double
272 when "ft0", "fa0", "fr"
285 raise "Bad register #{name} for X86 at #{codeOriginString}"
288 def x87DefaultStackPosition
294 when "ft2", "ft3", "ft4", "ft5"
295 raise "Unimplemented register #{name} for X86 at #{codeOriginString}"
297 raise "Bad register #{name} for X86 at #{codeOriginString}"
300 def x87Operand(offset
)
302 raise unless offset
== 0 or offset
== 1
303 "%st(#{x87DefaultStackPosition + offset})"
305 def x86CallOperand(kind
)
306 "*#{x86Operand(kind)}"
311 def validX86Immediate
?
313 value
>= -0x80000000 and value
<= 0x7fffffff
321 def x86CallOperand(kind
)
327 def supports8BitOnX86
331 def x86AddressOperand(addressKind
)
332 "#{offset.value}(#{base.x86Operand(addressKind)})"
335 x86AddressOperand(:ptr)
337 def x86CallOperand(kind
)
338 "*#{x86Operand(kind)}"
343 def supports8BitOnX86
347 def x86AddressOperand(addressKind
)
348 "#{offset.value}(#{base.x86Operand(addressKind)}, #{index.x86Operand(addressKind)}, #{scale})"
352 x86AddressOperand(:ptr)
355 def x86CallOperand(kind
)
356 "*#{x86Operand(kind)}"
360 class AbsoluteAddress
361 def supports8BitOnX86
365 def x86AddressOperand(addressKind
)
373 def x86CallOperand(kind
)
379 def x86CallOperand(kind
)
384 class LocalLabelReference
385 def x86CallOperand(kind
)
391 def getModifiedListX86_64
397 if node
.is_a
? Instruction
398 unless node
.opcode
== "move"
400 newOperands
= node
.operands
.map
{
402 if operand
.immediate
? and not operand
.validX86Immediate
?
404 raise "Attempt to use scratch register twice at #{operand.codeOriginString}"
406 newList
<< Instruction
.new(operand
.codeOrigin
, "move", [operand
, X64_SCRATCH_REGISTER
])
413 newNode
= Instruction
.new(node
.codeOrigin
, node
.opcode
, newOperands
, node
.annotation
)
416 unless node
.is_a
? Label
or
417 node
.is_a
? LocalLabel
or
419 raise "Unexpected #{node.inspect} at #{node.codeOrigin}"
432 def x86Operands(*kinds
)
433 raise unless kinds
.size
== operands
.size
437 result
<< operands
[idx
].x86Operand(kinds
[idx
])
455 not useX87
? "sd" : raise
480 def handleX86OpWithNumOperands(opcode
, kind
, numOperands
)
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)}"
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)}"
491 $asm.puts
"#{opcode} #{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}"
495 def handleX86Op(opcode
, kind
)
496 handleX86OpWithNumOperands(opcode
, kind
, operands
.size
)
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)}"
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)}"
510 def handleX86DoubleBranch(branchOpcode
, mode
)
512 handleX87Compare(mode
)
516 $asm.puts
"ucomisd #{operands[1].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
518 $asm.puts
"ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
523 $asm.puts
"#{branchOpcode} #{operands[2].asmLabel}"
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)}"
532 $asm.puts
"cmp#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[0].x86Operand(kind)}"
536 def handleX86IntBranch(branchOpcode
, kind
)
537 handleX86IntCompare(branchOpcode
[1..-1], kind
)
538 $asm.puts
"#{branchOpcode} #{operands[2].asmLabel}"
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)}"
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)}"
554 def handleX86IntCompareSet(setOpcode
, kind
)
555 handleX86IntCompare(setOpcode
[3..-1], kind
)
556 handleX86Set(setOpcode
, operands
[2])
559 def handleX86Test(kind
)
563 mask
= Immediate
.new(codeOrigin
, -1)
567 raise "Expected 2 or 3 operands, but got #{operands.size} at #{codeOriginString}"
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)}"
574 $asm.puts
"cmp#{x86Suffix(kind)} $0, #{value.x86Operand(kind)}"
577 $asm.puts
"test#{x86Suffix(kind)} #{mask.x86Operand(kind)}, #{value.x86Operand(kind)}"
581 def handleX86BranchTest(branchOpcode
, kind
)
583 $asm.puts
"#{branchOpcode} #{operands.last.asmLabel}"
586 def handleX86SetTest(setOpcode
, kind
)
588 handleX86Set(setOpcode
, operands
.last
)
591 def handleX86OpBranch(opcode
, branchOpcode
, kind
)
592 handleX86OpWithNumOperands(opcode
, kind
, operands
.size
- 1)
595 jumpTarget
= operands
[3]
597 jumpTarget
= operands
[2]
601 $asm.puts
"#{branchOpcode} #{jumpTarget.asmLabel}"
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)}"
609 handleX86OpWithNumOperands("sub#{x86Suffix(kind)}", kind
, operands
.size
- 1)
613 jumpTarget
= operands
[3]
615 jumpTarget
= operands
[2]
619 $asm.puts
"#{branchOpcode} #{jumpTarget.asmLabel}"
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)}"
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)}"
635 $asm.puts
"lea#{x86Suffix(kind)} #{operands[0].value}(#{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}"
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)}"
643 $asm.puts
"lea#{x86Suffix(kind)} (#{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}"
646 unless Immediate
.new(nil, 0) == operands
[0]
647 $asm.puts
"add#{x86Suffix(kind)} #{x86Operands(kind, kind)}"
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)}"
657 handleX86Op("sub#{x86Suffix(kind)}", kind
)
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)}"
665 # FIXME: could do some peephole in case the left operand is immediate and it's
667 handleX86Op("imul#{x86Suffix(kind)}", kind
)
672 if Immediate
.new(nil, 0) == operands
[0] and operands
[1].is_a
? RegisterID
674 $asm.puts
"xor#{x86Suffix(:quad)} #{operands[1].x86Operand(:quad)}, #{operands[1].x86Operand(:quad)}"
676 $asm.puts
"xor#{x86Suffix(:ptr)} #{operands[1].x86Operand(:ptr)}, #{operands[1].x86Operand(:ptr)}"
678 elsif operands
[0] !
= operands
[1]
680 $asm.puts
"mov#{x86Suffix(:quad)} #{x86Operands(:quad, :quad)}"
682 $asm.puts
"mov#{x86Suffix(:ptr)} #{x86Operands(:ptr, :ptr)}"
687 def handleX87Compare(mode
)
690 if (operands
[0].x87DefaultStackPosition
== 0)
691 $asm.puts
"fucomi #{operands[1].x87Operand(0)}"
693 $asm.puts
"fld #{operands[0].x87Operand(0)}"
694 $asm.puts
"fucomip #{operands[1].x87Operand(1)}"
697 if (operands
[1].x87DefaultStackPosition
== 0)
698 $asm.puts
"fucomi #{operands[0].x87Operand(0)}"
700 $asm.puts
"fld #{operands[1].x87Operand(0)}"
701 $asm.puts
"fucomip #{operands[0].x87Operand(1)}"
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)}"
714 $asm.puts
"fld #{operands[0].x87Operand(0)}"
715 $asm.puts
"#{opcodereverse}p %st, #{operands[1].x87Operand(1)}"
720 raise unless $activeBackend == "X86"
725 raise unless $activeBackend == "X86_64"
730 $asm.codeOrigin codeOriginString
if $enableCodeOriginComments
731 $asm.annotation annotation
if $enableInstrAnnotations
741 handleX86Op("andl", :int)
743 handleX86Op("and#{x86Suffix(:ptr)}", :ptr)
745 handleX86Op("and#{x86Suffix(:quad)}", :quad)
747 handleX86Shift("sall", :int)
749 handleX86Shift("sal#{x86Suffix(:ptr)}", :ptr)
751 handleX86Shift("sal#{x86Suffix(:quad)}", :quad)
759 $asm.puts
"negl #{x86Operands(:int)}"
761 $asm.puts
"neg#{x86Suffix(:ptr)} #{x86Operands(:ptr)}"
763 $asm.puts
"neg#{x86Suffix(:quad)} #{x86Operands(:quad)}"
765 $asm.puts
"notl #{x86Operands(:int)}"
767 handleX86Op("orl", :int)
769 handleX86Op("or#{x86Suffix(:ptr)}", :ptr)
771 handleX86Op("or#{x86Suffix(:quad)}", :quad)
773 handleX86Shift("sarl", :int)
775 handleX86Shift("sar#{x86Suffix(:ptr)}", :ptr)
777 handleX86Shift("sar#{x86Suffix(:quad)}", :quad)
779 handleX86Shift("shrl", :int)
781 handleX86Shift("shr#{x86Suffix(:ptr)}", :ptr)
783 handleX86Shift("shr#{x86Suffix(:quad)}", :quad)
791 handleX86Op("xorl", :int)
793 handleX86Op("xor#{x86Suffix(:ptr)}", :ptr)
795 handleX86Op("xor#{x86Suffix(:quad)}", :quad)
796 when "loadi", "storei"
797 $asm.puts
"movl #{x86Operands(:int, :int)}"
800 $asm.puts
"movslq #{x86Operands(:int, :quad)}"
802 $asm.puts
"movl #{x86Operands(:int, :int)}"
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)}"
809 $asm.puts
"movzbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
811 $asm.puts
"movsbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
813 $asm.puts
"movzwl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}"
815 $asm.puts
"movswl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}"
817 $asm.puts
"movb #{x86Operands(:byte, :byte)}"
820 $asm.puts
"fldl #{operands[0].x86Operand(:double)}"
821 $asm.puts
"fstp #{operands[1].x87Operand(1)}"
823 $asm.puts
"movsd #{x86Operands(:double, :double)}"
827 if (operands
[0].x87DefaultStackPosition
== 0)
828 $asm.puts
"fst #{operands[1].x87Operand(0)}"
830 $asm.puts
"fld #{operands[0].x87Operand(0)}"
831 $asm.puts
"fstp #{operands[1].x87Operand(1)}"
834 $asm.puts
"movsd #{x86Operands(:double, :double)}"
838 if (operands
[0].x87DefaultStackPosition
== 0)
839 $asm.puts
"fstl #{operands[1].x86Operand(:double)}"
841 $asm.puts
"fld #{operands[0].x87Operand(0)}"
842 $asm.puts
"fstpl #{operands[1].x86Operand(:double)}"
845 $asm.puts
"movsd #{x86Operands(:double, :double)}"
849 handleX87BinOp("fadd", "fadd")
851 $asm.puts
"addsd #{x86Operands(:double, :double)}"
855 handleX87BinOp("fmul", "fmul")
857 $asm.puts
"mulsd #{x86Operands(:double, :double)}"
861 handleX87BinOp("fsub", "fsubr")
863 $asm.puts
"subsd #{x86Operands(:double, :double)}"
867 handleX87BinOp("fdiv", "fdivr")
869 $asm.puts
"divsd #{x86Operands(:double, :double)}"
873 $asm.puts
"fld #{operands[0].x87Operand(0)}"
875 $asm.puts
"fstp #{operands[1].x87Operand(1)}"
877 $asm.puts
"sqrtsd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
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)}"
886 $asm.puts
"cvtsi2sd #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:double)}"
890 handleX87Compare(:normal)
892 $asm.puts
"ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
894 if operands
[0] == operands
[1]
895 # This is just a jump ordered, which is a jnp.
896 $asm.puts
"jnp #{operands[2].asmLabel}"
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")
904 handleX86DoubleBranch("jne", :normal)
906 handleX86DoubleBranch("ja", :normal)
908 handleX86DoubleBranch("jae", :normal)
910 handleX86DoubleBranch("ja", :reverse)
912 handleX86DoubleBranch("jae", :reverse)
914 handleX86DoubleBranch("je", :normal)
917 handleX87Compare(:normal)
919 $asm.puts
"ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
921 if operands
[0] == operands
[1]
922 # This is just a jump unordered, which is a jp.
923 $asm.puts
"jp #{operands[2].asmLabel}"
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}"
934 handleX86DoubleBranch("jb", :reverse)
936 handleX86DoubleBranch("jbe", :reverse)
938 handleX86DoubleBranch("jb", :normal)
940 handleX86DoubleBranch("jbe", :normal)
942 # FIXME: unused and unimplemented for x87
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}"
948 # FIXME: unused and unimplemented for x87
950 $asm.puts
"cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
953 sp
= RegisterID
.new(nil, "sp")
954 if (operands
[0].x87DefaultStackPosition
== 0)
955 $asm.puts
"fistl -4(#{sp.x86Operand(:ptr)})"
957 $asm.puts
"fld #{operands[0].x87Operand(0)}"
958 $asm.puts
"fistpl -4(#{sp.x86Operand(:ptr)})"
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}"
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}"
979 $asm.puts
"fstp #{operands[0].x87Operand(1)}"
981 $asm.puts
"xorpd #{operands[0].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
984 $asm.puts
"pop #{operands[0].x86Operand(:ptr)}"
986 $asm.puts
"push #{operands[0].x86Operand(:ptr)}"
990 $asm.puts
"movslq #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:quad)}"
992 $asm.puts
"movl #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
996 handleX86IntBranch("je", :int)
998 handleX86IntBranch("je", :ptr)
1000 handleX86IntBranch("je", :quad)
1002 handleX86IntBranch("jne", :int)
1004 handleX86IntBranch("jne", :ptr)
1006 handleX86IntBranch("jne", :quad)
1008 handleX86IntBranch("ja", :int)
1010 handleX86IntBranch("ja", :ptr)
1012 handleX86IntBranch("ja", :quad)
1014 handleX86IntBranch("jae", :int)
1016 handleX86IntBranch("jae", :ptr)
1018 handleX86IntBranch("jae", :quad)
1020 handleX86IntBranch("jb", :int)
1022 handleX86IntBranch("jb", :ptr)
1024 handleX86IntBranch("jb", :quad)
1026 handleX86IntBranch("jbe", :int)
1028 handleX86IntBranch("jbe", :ptr)
1030 handleX86IntBranch("jbe", :quad)
1032 handleX86IntBranch("jg", :int)
1034 handleX86IntBranch("jg", :ptr)
1036 handleX86IntBranch("jg", :quad)
1038 handleX86IntBranch("jge", :int)
1040 handleX86IntBranch("jge", :ptr)
1042 handleX86IntBranch("jge", :quad)
1044 handleX86IntBranch("jl", :int)
1046 handleX86IntBranch("jl", :ptr)
1048 handleX86IntBranch("jl", :quad)
1050 handleX86IntBranch("jle", :int)
1052 handleX86IntBranch("jle", :ptr)
1054 handleX86IntBranch("jle", :quad)
1056 handleX86IntBranch("je", :byte)
1058 handleX86IntBranch("jne", :byte)
1060 handleX86IntBranch("ja", :byte)
1062 handleX86IntBranch("jae", :byte)
1064 handleX86IntBranch("jb", :byte)
1066 handleX86IntBranch("jbe", :byte)
1068 handleX86IntBranch("jg", :byte)
1070 handleX86IntBranch("jge", :byte)
1072 handleX86IntBranch("jl", :byte)
1074 handleX86IntBranch("jlteq", :byte)
1076 handleX86BranchTest("js", :int)
1078 handleX86BranchTest("js", :ptr)
1080 handleX86BranchTest("js", :quad)
1082 handleX86BranchTest("jz", :int)
1084 handleX86BranchTest("jz", :ptr)
1086 handleX86BranchTest("jz", :quad)
1088 handleX86BranchTest("jnz", :int)
1090 handleX86BranchTest("jnz", :ptr)
1092 handleX86BranchTest("jnz", :quad)
1094 handleX86BranchTest("js", :byte)
1096 handleX86BranchTest("jz", :byte)
1098 handleX86BranchTest("jnz", :byte)
1100 $asm.puts
"jmp #{operands[0].x86CallOperand(:ptr)}"
1102 handleX86OpBranch("addl", "jo", :int)
1104 handleX86OpBranch("add#{x86Suffix(:ptr)}", "jo", :ptr)
1106 handleX86OpBranch("add#{x86Suffix(:quad)}", "jo", :quad)
1108 handleX86OpBranch("addl", "js", :int)
1110 handleX86OpBranch("add#{x86Suffix(:ptr)}", "js", :ptr)
1112 handleX86OpBranch("add#{x86Suffix(:quad)}", "js", :quad)
1114 handleX86OpBranch("addl", "jz", :int)
1116 handleX86OpBranch("add#{x86Suffix(:ptr)}", "jz", :ptr)
1118 handleX86OpBranch("add#{x86Suffix(:quad)}", "jz", :quad)
1120 handleX86OpBranch("addl", "jnz", :int)
1122 handleX86OpBranch("add#{x86Suffix(:ptr)}", "jnz", :ptr)
1124 handleX86OpBranch("add#{x86Suffix(:quad)}", "jnz", :quad)
1126 handleX86SubBranch("jo", :int)
1128 handleX86SubBranch("js", :int)
1130 handleX86SubBranch("jz", :int)
1132 handleX86SubBranch("jnz", :int)
1134 handleX86OpBranch("imull", "jo", :int)
1136 handleX86OpBranch("imull", "js", :int)
1138 handleX86OpBranch("imull", "jz", :int)
1140 handleX86OpBranch("imull", "jnz", :int)
1142 handleX86OpBranch("orl", "jo", :int)
1144 handleX86OpBranch("orl", "js", :int)
1146 handleX86OpBranch("orl", "jz", :int)
1148 handleX86OpBranch("orl", "jnz", :int)
1152 $asm.puts
"call #{operands[0].x86CallOperand(:ptr)}"
1156 handleX86IntCompareSet("sete", :int)
1158 handleX86IntCompareSet("sete", :byte)
1160 handleX86IntCompareSet("sete", :ptr)
1162 handleX86IntCompareSet("sete", :quad)
1164 handleX86IntCompareSet("setne", :int)
1166 handleX86IntCompareSet("setne", :byte)
1168 handleX86IntCompareSet("setne", :ptr)
1170 handleX86IntCompareSet("setne", :quad)
1172 handleX86IntCompareSet("seta", :int)
1174 handleX86IntCompareSet("seta", :byte)
1176 handleX86IntCompareSet("seta", :ptr)
1178 handleX86IntCompareSet("seta", :quad)
1180 handleX86IntCompareSet("setae", :int)
1182 handleX86IntCompareSet("setae", :byte)
1184 handleX86IntCompareSet("setae", :ptr)
1186 handleX86IntCompareSet("setae", :quad)
1188 handleX86IntCompareSet("setb", :int)
1190 handleX86IntCompareSet("setb", :byte)
1192 handleX86IntCompareSet("setb", :ptr)
1194 handleX86IntCompareSet("setb", :quad)
1196 handleX86IntCompareSet("setbe", :int)
1198 handleX86IntCompareSet("setbe", :byte)
1200 handleX86IntCompareSet("setbe", :ptr)
1202 handleX86IntCompareSet("setbe", :quad)
1204 handleX86IntCompareSet("setg", :int)
1206 handleX86IntCompareSet("setg", :byte)
1208 handleX86IntCompareSet("setg", :ptr)
1210 handleX86IntCompareSet("setg", :quad)
1212 handleX86IntCompareSet("setge", :int)
1214 handleX86IntCompareSet("setge", :byte)
1216 handleX86IntCompareSet("setge", :ptr)
1218 handleX86IntCompareSet("setge", :quad)
1220 handleX86IntCompareSet("setl", :int)
1222 handleX86IntCompareSet("setl", :byte)
1224 handleX86IntCompareSet("setl", :ptr)
1226 handleX86IntCompareSet("setl", :quad)
1228 handleX86IntCompareSet("setle", :int)
1230 handleX86IntCompareSet("setle", :byte)
1232 handleX86IntCompareSet("setle", :ptr)
1234 handleX86IntCompareSet("setle", :quad)
1236 handleX86SetTest("sets", :int)
1238 handleX86SetTest("setz", :int)
1240 handleX86SetTest("setnz", :int)
1242 handleX86SetTest("sets", :ptr)
1244 handleX86SetTest("setz", :ptr)
1246 handleX86SetTest("setnz", :ptr)
1248 handleX86SetTest("sets", :quad)
1250 handleX86SetTest("setz", :quad)
1252 handleX86SetTest("setnz", :quad)
1254 handleX86SetTest("sets", :byte)
1256 handleX86SetTest("setz", :byte)
1258 handleX86SetTest("setnz", :byte)
1260 sp
= RegisterID
.new(nil, "sp")
1261 $asm.puts
"mov#{x86Suffix(:ptr)} #{operands[0].value * x86Bytes(:ptr)}(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:ptr)}"
1263 sp
= RegisterID
.new(nil, "sp")
1264 $asm.puts
"mov#{x86Suffix(:quad)} #{operands[0].value * x86Bytes(:quad)}(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:quad)}"
1266 sp
= RegisterID
.new(nil, "sp")
1267 $asm.puts
"mov#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{operands[1].value * x86Bytes(:ptr)}(#{sp.x86Operand(:ptr)})"
1269 sp
= RegisterID
.new(nil, "sp")
1270 $asm.puts
"mov#{x86Suffix(:quad)} #{operands[0].x86Operand(:quad)}, #{operands[1].value * x86Bytes(:quad)}(#{sp.x86Operand(:ptr)})"
1274 $asm.puts
"idivl #{operands[0].x86Operand(:int)}"
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)}"
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)}"
1290 sp
= RegisterID
.new(nil, "sp")
1291 if (operands
[0].x87DefaultStackPosition
== 0)
1292 $asm.puts
"fstl -8(#{sp.x86Operand(:ptr)})"
1294 $asm.puts
"fld #{operands[0].x87Operand(0)}"
1295 $asm.puts
"fstpl -8(#{sp.x86Operand(:ptr)})"
1297 $asm.puts
"movl -8(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:int)}"
1298 $asm.puts
"movl -4(#{sp.x86Operand(:ptr)}), #{operands[2].x86Operand(:int)}"
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)}"
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)}"
1312 $asm.puts
"movq #{operands[0].x86Operand(:quad)}, #{operands[1].x86Operand(:double)}"
1316 sp
= RegisterID
.new(nil, "sp")
1317 if (operands
[0].x87DefaultStackPosition
== 0)
1318 $asm.puts
"fstl -8(#{sp.x86Operand(:ptr)})"
1320 $asm.puts
"fld #{operands[0].x87Operand(0)}"
1321 $asm.puts
"fstpl -8(#{sp.x86Operand(:ptr)})"
1323 $asm.puts
"movq -8(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:quad)}"
1325 $asm.puts
"movq #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:quad)}"
1328 $asm.puts
"jo #{operands[0].asmLabel}"
1330 $asm.puts
"js #{operands[0].asmLabel}"
1332 $asm.puts
"jz #{operands[0].asmLabel}"
1334 $asm.puts
"jnz #{operands[0].asmLabel}"
1336 $asm.puts
"leal #{operands[0].x86AddressOperand(:int)}, #{operands[1].x86Operand(:int)}"
1338 $asm.puts
"lea#{x86Suffix(:ptr)} #{operands[0].x86AddressOperand(:ptr)}, #{operands[1].x86Operand(:ptr)}"
1339 when "resetX87Stack"
1343 $asm.puts
"ffree %st(#{offset})"