]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - offlineasm/x86.rb
JavaScriptCore-7600.1.4.15.12.tar.gz
[apple/javascriptcore.git] / offlineasm / x86.rb
index e6a5c92cab86c02bbb1f3582319782b705bead52..3be1d267c6c1b594d629e82885bcb35f63bd5a33 100644 (file)
@@ -1,4 +1,5 @@
-# Copyright (C) 2012 Apple Inc. All rights reserved.
+# Copyright (C) 2012, 2014 Apple Inc. All rights reserved.
+# Copyright (C) 2013 Digia Plc. and/or its subsidiary(-ies)
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 # THE POSSIBILITY OF SUCH DAMAGE.
 
+require "config"
+
 def isX64
     case $activeBackend
     when "X86"
         false
+    when "X86_WIN"
+        false
     when "X86_64"
         true
+    when "X86_64_WIN"
+        true
+    else
+        raise "bad value for $activeBackend: #{$activeBackend}"
+    end
+end
+
+def useX87
+    case $activeBackend
+    when "X86"
+        true
+    when "X86_WIN"
+        true
+    when "X86_64"
+        false
+    when "X86_64_WIN"
+        false
     else
         raise "bad value for $activeBackend: #{$activeBackend}"
     end
 end
 
+def isWindows
+    RUBY_PLATFORM =~ /cygwin/i
+end
+
+def isGCC
+    !isWindows
+end
+
+def isMSVC
+    isWindows
+end
+
+def isIntelSyntax
+    isWindows
+end
+
+def register(name)
+    isIntelSyntax ? name : "%" + name
+end
+
+def offsetRegister(off, register)
+    isIntelSyntax ? "[#{off} + #{register}]" : "#{off}(#{register})"
+end
+
+def callPrefix
+    isIntelSyntax ? "" : "*"
+end
+
+def orderOperands(opA, opB)
+    isIntelSyntax ? "#{opB}, #{opA}" : "#{opA}, #{opB}"
+end
+
+def const(c)
+    isIntelSyntax ? "#{c}" : "$#{c}"
+end
+
+def getSizeString(kind)
+    if !isIntelSyntax
+        return ""
+    end
+
+    size = ""
+    case kind
+    when :byte
+        size = "byte"
+    when :half
+        size = "word"
+    when :int
+        size = "dword"
+    when :ptr
+        size =  isX64 ? "qword" : "dword"
+    when :double
+        size = "qword"
+    when :quad
+        size = "qword"
+    else
+        raise "Invalid kind #{kind}"
+    end
+
+    return size + " " + "ptr" + " ";
+end
+
 class SpecialRegister < NoChildren
     def x86Operand(kind)
         raise unless @name =~ /^r/
         raise unless isX64
         case kind
         when :half
-            "%" + @name + "w"
+            register(@name + "w")
         when :int
-            "%" + @name + "d"
+            register(@name + "d")
         when :ptr
-            "%" + @name
+            register(@name)
+        when :quad
+            register(@name)
         else
             raise
         end
     end
     def x86CallOperand(kind)
-        "*#{x86Operand(kind)}"
+        # Call operands are not allowed to be partial registers.
+        "#{callPrefix}#{x86Operand(:quad)}"
     end
 end
 
@@ -57,11 +144,11 @@ X64_SCRATCH_REGISTER = SpecialRegister.new("r11")
 class RegisterID
     def supports8BitOnX86
         case name
-        when "t0", "a0", "r0", "t1", "a1", "r1", "t2", "t3"
+        when "t0", "a0", "r0", "t1", "a1", "r1", "t2", "t3", "t4", "t5"
             true
         when "cfr", "ttnr", "tmr"
             false
-        when "t4", "t5"
+        when "t6"
             isX64
         else
             raise
@@ -73,65 +160,75 @@ class RegisterID
         when "t0", "a0", "r0"
             case kind
             when :byte
-                "%al"
+                register("al")
             when :half
-                "%ax"
+                register("ax")
             when :int
-                "%eax"
+                register("eax")
             when :ptr
-                isX64 ? "%rax" : "%eax"
+                isX64 ? register("rax") : register("eax")
+            when :quad
+                isX64 ? register("rax") : raise
             else
-                raise
+                raise "Invalid kind #{kind} for name #{name}"
             end
         when "t1", "a1", "r1"
             case kind
             when :byte
-                "%dl"
+                register("dl")
             when :half
-                "%dx"
+                register("dx")
             when :int
-                "%edx"
+                register("edx")
             when :ptr
-                isX64 ? "%rdx" : "%edx"
+                isX64 ? register("rdx") : register("edx")
+            when :quad
+                isX64 ? register("rdx") : raise
             else
                 raise
             end
         when "t2"
             case kind
             when :byte
-                "%cl"
+                register("cl")
             when :half
-                "%cx"
+                register("cx")
             when :int
-                "%ecx"
+                register("ecx")
             when :ptr
-                isX64 ? "%rcx" : "%ecx"
+                isX64 ? register("rcx") : register("ecx")
+            when :quad
+                isX64 ? register("rcx") : raise
             else
                 raise
             end
         when "t3"
             case kind
             when :byte
-                "%bl"
+                register("bl")
             when :half
-                "%bx"
+                register("bx")
             when :int
-                "%ebx"
+                register("ebx")
             when :ptr
-                isX64 ? "%rbx" : "%ebx"
+                isX64 ? register("rbx") : register("ebx")
+            when :quad
+                isX64 ? register("rbx") : raise
             else
                 raise
             end
         when "t4"
             case kind
             when :byte
-                "%sil"
+                register("dil")
             when :half
-                "%si"
+                register("di")
             when :int
-                "%esi"
+                register("edi")
             when :ptr
-                isX64 ? "%rsi" : "%esi"
+                isX64 ? register("rdi") : register("edi")
+            when :quad
+                isX64 ? register("rdi") : raise
             else
                 raise
             end
@@ -139,24 +236,24 @@ class RegisterID
             if isX64
                 case kind
                 when :half
-                    "%r13w"
+                    register("bp")
                 when :int
-                    "%r13d"
+                    register("ebp")
                 when :ptr
-                    "%r13"
+                    register("rbp")
+                when :quad
+                    register("rbp")
                 else
                     raise
                 end
             else
                 case kind
-                when :byte
-                    "%dil"
                 when :half
-                    "%di"
+                    register("bp")
                 when :int
-                    "%edi"
+                    register("ebp")
                 when :ptr
-                    "%edi"
+                    register("ebp")
                 else
                     raise
                 end
@@ -164,89 +261,128 @@ class RegisterID
         when "sp"
             case kind
             when :byte
-                "%spl"
+                register("spl")
             when :half
-                "%sp"
+                register("sp")
             when :int
-                "%esp"
+                register("esp")
             when :ptr
-                isX64 ? "%rsp" : "%esp"
+                isX64 ? register("rsp") : register("esp")
+            when :quad
+                isX64 ? register("rsp") : raise
             else
                 raise
             end
         when "t5"
-            raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
             case kind
             when :byte
-                "%dil"
+                register("sil")
             when :half
-                "%di"
+                register("si")
             when :int
-                "%edi"
+                register("esi")
             when :ptr
-                "%rdi"
+                isX64 ? register("rsi") : register("esi")
+            when :quad
+                isX64 ? register("rsi") : raise
             end
         when "t6"
             raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
             case kind
             when :half
-                "%r10w"
+                register("r8w")
+            when :int
+                register("r8d")
+            when :ptr
+                register("r8")
+            when :quad
+                register("r8")
+            end
+        when "t7"
+            raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
+            case kind
+            when :half
+                register("r9w")
             when :int
-                "%r10d"
+                register("r9d")
             when :ptr
-                "%r10"
+                register("r9")
+            when :quad
+                register("r9")
             end
         when "csr1"
             raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
             case kind
             when :half
-                "%r14w"
+                register("r14w")
             when :int
-                "%r14d"
+                register("r14d")
             when :ptr
-                "%r14"
+                register("r14")
+            when :quad
+                register("r14")
             end
         when "csr2"
             raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
             case kind
             when :half
-                "%r15w"
+                register("r15w")
             when :int
-                "%r15d"
+                register("r15d")
             when :ptr
-                "%r15"
+                register("r15")
+            when :quad
+                register("r15")
             end
         else
             raise "Bad register #{name} for X86 at #{codeOriginString}"
         end
     end
     def x86CallOperand(kind)
-        "*#{x86Operand(kind)}"
+        isX64 ? "#{callPrefix}#{x86Operand(:quad)}" : "#{callPrefix}#{x86Operand(:ptr)}"
     end
 end
 
 class FPRegisterID
     def x86Operand(kind)
         raise unless kind == :double
+        raise if useX87
         case name
         when "ft0", "fa0", "fr"
-            "%xmm0"
+            register("xmm0")
         when "ft1", "fa1"
-            "%xmm1"
+            register("xmm1")
         when "ft2", "fa2"
-            "%xmm2"
+            register("xmm2")
         when "ft3", "fa3"
-            "%xmm3"
+            register("xmm3")
         when "ft4"
-            "%xmm4"
+            register("xmm4")
         when "ft5"
-            "%xmm5"
+            register("xmm5")
         else
             raise "Bad register #{name} for X86 at #{codeOriginString}"
         end
     end
+    def x87DefaultStackPosition
+        case name
+        when "ft0", "fr"
+            0
+        when "ft1"
+            1
+        when "ft2", "ft3", "ft4", "ft5"
+            raise "Unimplemented register #{name} for X86 at #{codeOriginString}"
+        else
+            raise "Bad register #{name} for X86 at #{codeOriginString}"
+        end
+    end
+    def x87Operand(offset)
+        raise unless useX87
+        raise unless offset == 0 or offset == 1
+        "#{register("st")}(#{x87DefaultStackPosition + offset})"
+    end
     def x86CallOperand(kind)
-        "*#{x86Operand(kind)}"
+        "#{callPrefix}#{x86Operand(kind)}"
     end
 end
 
@@ -259,7 +395,7 @@ class Immediate
         end
     end
     def x86Operand(kind)
-        "$#{value}"
+        "#{const(value)}"
     end
     def x86CallOperand(kind)
         "#{value}"
@@ -272,13 +408,13 @@ class Address
     end
     
     def x86AddressOperand(addressKind)
-        "#{offset.value}(#{base.x86Operand(addressKind)})"
+        "#{offsetRegister(offset.value, base.x86Operand(addressKind))}"
     end
     def x86Operand(kind)
-        x86AddressOperand(:ptr)
+        "#{getSizeString(kind)}#{x86AddressOperand(:ptr)}"
     end
     def x86CallOperand(kind)
-        "*#{x86Operand(kind)}"
+        "#{callPrefix}#{x86Operand(kind)}"
     end
 end
 
@@ -288,15 +424,23 @@ class BaseIndex
     end
     
     def x86AddressOperand(addressKind)
-        "#{offset.value}(#{base.x86Operand(addressKind)}, #{index.x86Operand(addressKind)}, #{scale})"
+        if !isIntelSyntax
+            "#{offset.value}(#{base.x86Operand(addressKind)}, #{index.x86Operand(addressKind)}, #{scale})"
+        else
+            "#{getSizeString(addressKind)}[#{offset.value} + #{base.x86Operand(addressKind)} + #{index.x86Operand(addressKind)} * #{scale}]"
+        end
     end
     
     def x86Operand(kind)
-        x86AddressOperand(:ptr)
+        if !isIntelSyntax
+            x86AddressOperand(:ptr)
+        else
+            "#{getSizeString(kind)}[#{offset.value} + #{base.x86Operand(:ptr)} + #{index.x86Operand(:ptr)} * #{scale}]"
+        end
     end
 
     def x86CallOperand(kind)
-        "*#{x86Operand(kind)}"
+        "#{callPrefix}#{x86Operand(kind)}"
     end
 end
 
@@ -314,7 +458,7 @@ class AbsoluteAddress
     end
 
     def x86CallOperand(kind)
-        "*#{address.value}"
+        "#{callPrefix}#{address.value}"
     end
 end
 
@@ -325,6 +469,9 @@ class LabelReference
 end
 
 class LocalLabelReference
+    def x86Operand(kind)
+        asmLabel
+    end
     def x86CallOperand(kind)
         asmLabel
     end
@@ -353,7 +500,7 @@ class Sequence
                             operand
                         end
                     }
-                    newNode = Instruction.new(node.codeOrigin, node.opcode, newOperands)
+                    newNode = Instruction.new(node.codeOrigin, node.opcode, newOperands, node.annotation)
                 end
             else
                 unless node.is_a? Label or
@@ -369,20 +516,30 @@ class Sequence
         
         return newList
     end
+    def getModifiedListX86_64_WIN
+        getModifiedListX86_64
+    end
 end
 
 class Instruction
+    @@floatingPointCompareImplicitOperand = isIntelSyntax ? "st(0), " : ""
+    
     def x86Operands(*kinds)
         raise unless kinds.size == operands.size
         result = []
         kinds.size.times {
             | idx |
-            result << operands[idx].x86Operand(kinds[idx])
+            i = isIntelSyntax ? (kinds.size - idx - 1) : idx
+            result << operands[i].x86Operand(kinds[i])
         }
         result.join(", ")
     end
 
     def x86Suffix(kind)
+        if isIntelSyntax
+            return ""
+        end
+
         case kind
         when :byte
             "b"
@@ -392,8 +549,10 @@ class Instruction
             "l"
         when :ptr
             isX64 ? "q" : "l"
+        when :quad
+            isX64 ? "q" : raise
         when :double
-            "sd"
+            not useX87 ? "sd" : raise
         else
             raise
         end
@@ -409,6 +568,8 @@ class Instruction
             4
         when :ptr
             isX64 ? 8 : 4
+        when :quad
+            isX64 ? 8 : raise
         when :double
             8
         else
@@ -419,15 +580,15 @@ class Instruction
     def handleX86OpWithNumOperands(opcode, kind, numOperands)
         if numOperands == 3
             if operands[0] == operands[2]
-                $asm.puts "#{opcode} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
+                $asm.puts "#{opcode} #{orderOperands(operands[1].x86Operand(kind), operands[2].x86Operand(kind))}"
             elsif operands[1] == operands[2]
-                $asm.puts "#{opcode} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
+                $asm.puts "#{opcode} #{orderOperands(operands[0].x86Operand(kind), operands[2].x86Operand(kind))}"
             else
-                $asm.puts "mov#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
-                $asm.puts "#{opcode} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
+                $asm.puts "mov#{x86Suffix(kind)} #{orderOperands(operands[0].x86Operand(kind), operands[2].x86Operand(kind))}"
+                $asm.puts "#{opcode} #{orderOperands(operands[1].x86Operand(kind), operands[2].x86Operand(kind))}"
             end
         else
-            $asm.puts "#{opcode} #{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}"
+            $asm.puts "#{opcode} #{orderOperands(operands[0].x86Operand(kind), operands[1].x86Operand(kind))}"
         end
     end
     
@@ -437,34 +598,38 @@ class Instruction
     
     def handleX86Shift(opcode, kind)
         if operands[0].is_a? Immediate or operands[0] == RegisterID.forName(nil, "t2")
-            $asm.puts "#{opcode} #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(kind)}"
+            $asm.puts "#{opcode} #{orderOperands(operands[0].x86Operand(:byte), operands[1].x86Operand(kind))}"
         else
             cx = RegisterID.forName(nil, "t2")
             $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}"
-            $asm.puts "#{opcode} %cl, #{operands[1].x86Operand(kind)}"
+            $asm.puts "#{opcode} #{orderOperands(register("cl"), operands[1].x86Operand(kind))}"
             $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}"
         end
     end
     
     def handleX86DoubleBranch(branchOpcode, mode)
-        case mode
-        when :normal
-            $asm.puts "ucomisd #{operands[1].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
-        when :reverse
-            $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
+        if useX87
+            handleX87Compare(mode)
         else
-            raise mode.inspect
+            case mode
+            when :normal
+                $asm.puts "ucomisd #{orderOperands(operands[1].x86Operand(:double), operands[0].x86Operand(:double))}"
+            when :reverse
+                $asm.puts "ucomisd #{orderOperands(operands[0].x86Operand(:double), operands[1].x86Operand(:double))}"
+            else
+                raise mode.inspect
+            end
         end
         $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
     end
     
     def handleX86IntCompare(opcodeSuffix, kind)
         if operands[0].is_a? Immediate and operands[0].value == 0 and operands[1].is_a? RegisterID and (opcodeSuffix == "e" or opcodeSuffix == "ne")
-            $asm.puts "test#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}"
+            $asm.puts "test#{x86Suffix(kind)} #{orderOperands(operands[1].x86Operand(kind), operands[1].x86Operand(kind))}"
         elsif operands[1].is_a? Immediate and operands[1].value == 0 and operands[0].is_a? RegisterID and (opcodeSuffix == "e" or opcodeSuffix == "ne")
-            $asm.puts "test#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}"
+            $asm.puts "test#{x86Suffix(kind)}  #{orderOperands(operands[0].x86Operand(kind), operands[0].x86Operand(kind))}"
         else
-            $asm.puts "cmp#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[0].x86Operand(kind)}"
+            $asm.puts "cmp#{x86Suffix(kind)} #{orderOperands(operands[1].x86Operand(kind), operands[0].x86Operand(kind))}"
         end
     end
     
@@ -476,7 +641,11 @@ class Instruction
     def handleX86Set(setOpcode, operand)
         if operand.supports8BitOnX86
             $asm.puts "#{setOpcode} #{operand.x86Operand(:byte)}"
-            $asm.puts "movzbl #{operand.x86Operand(:byte)}, #{operand.x86Operand(:int)}"
+            if !isIntelSyntax
+                $asm.puts "movzbl #{orderOperands(operand.x86Operand(:byte), operand.x86Operand(:int))}"
+            else
+                $asm.puts "movzx #{orderOperands(operand.x86Operand(:byte), operand.x86Operand(:int))}"
+            end
         else
             ax = RegisterID.new(nil, "t0")
             $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}"
@@ -506,10 +675,10 @@ class Instruction
             if value.is_a? RegisterID
                 $asm.puts "test#{x86Suffix(kind)} #{value.x86Operand(kind)}, #{value.x86Operand(kind)}"
             else
-                $asm.puts "cmp#{x86Suffix(kind)} $0, #{value.x86Operand(kind)}"
+                $asm.puts "cmp#{x86Suffix(kind)} #{orderOperands(const(0), value.x86Operand(kind))}"
             end
         else
-            $asm.puts "test#{x86Suffix(kind)} #{mask.x86Operand(kind)}, #{value.x86Operand(kind)}"
+            $asm.puts "test#{x86Suffix(kind)} #{orderOperands(mask.x86Operand(kind), value.x86Operand(kind))}"
         end
     end
     
@@ -539,7 +708,7 @@ class Instruction
     def handleX86SubBranch(branchOpcode, kind)
         if operands.size == 4 and operands[1] == operands[2]
             $asm.puts "neg#{x86Suffix(kind)} #{operands[2].x86Operand(kind)}"
-            $asm.puts "add#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
+            $asm.puts "add#{x86Suffix(kind)} #{orderOperands(operands[0].x86Operand(kind), operands[2].x86Operand(kind))}"
         else
             handleX86OpWithNumOperands("sub#{x86Suffix(kind)}", kind, operands.size - 1)
         end
@@ -553,22 +722,34 @@ class Instruction
         end
         $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}"
     end
-    
+
     def handleX86Add(kind)
-        if operands.size == 3 and operands[0].is_a? Immediate
+        if operands.size == 3 and operands[1] == operands[2]
+            unless Immediate.new(nil, 0) == operands[0]
+                $asm.puts "add#{x86Suffix(kind)} #{orderOperands(operands[0].x86Operand(kind), operands[2].x86Operand(kind))}"
+            end
+        elsif operands.size == 3 and operands[0].is_a? Immediate
             raise unless operands[1].is_a? RegisterID
             raise unless operands[2].is_a? RegisterID
             if operands[0].value == 0
                 unless operands[1] == operands[2]
-                    $asm.puts "mov#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
+                    $asm.puts "mov#{x86Suffix(kind)} #{orderOperands(operands[1].x86Operand(kind), operands[2].x86Operand(kind))}"
                 end
             else
-                $asm.puts "lea#{x86Suffix(kind)} #{operands[0].value}(#{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}"
+                $asm.puts "lea#{x86Suffix(kind)} #{orderOperands(offsetRegister(operands[0].value, operands[1].x86Operand(kind)), operands[2].x86Operand(kind))}"
             end
         elsif operands.size == 3 and operands[0].is_a? RegisterID
             raise unless operands[1].is_a? RegisterID
             raise unless operands[2].is_a? RegisterID
-            $asm.puts "lea#{x86Suffix(kind)} (#{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}"
+            if operands[0] == operands[2]
+                $asm.puts "add#{x86Suffix(kind)} #{orderOperands(operands[1].x86Operand(kind), operands[2].x86Operand(kind))}"
+            else
+                if !isIntelSyntax
+                    $asm.puts "lea#{x86Suffix(kind)} (#{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}"
+                else
+                    $asm.puts "lea#{x86Suffix(kind)} #{operands[2].x86Operand(kind)}, [#{operands[0].x86Operand(kind)} + #{operands[1].x86Operand(kind)}]"
+                end
+            end
         else
             unless Immediate.new(nil, 0) == operands[0]
                 $asm.puts "add#{x86Suffix(kind)} #{x86Operands(kind, kind)}"
@@ -579,7 +760,7 @@ class Instruction
     def handleX86Sub(kind)
         if operands.size == 3 and operands[1] == operands[2]
             $asm.puts "neg#{x86Suffix(kind)} #{operands[2].x86Operand(kind)}"
-            $asm.puts "add#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
+            $asm.puts "add#{x86Suffix(kind)} #{orderOperands(operands[0].x86Operand(kind), operands[2].x86Operand(kind))}"
         else
             handleX86Op("sub#{x86Suffix(kind)}", kind)
         end
@@ -595,109 +776,286 @@ class Instruction
         end
     end
     
+    def handleX86Peek()
+        sp = RegisterID.new(nil, "sp")
+        opA = offsetRegister(operands[0].value * x86Bytes(:ptr), sp.x86Operand(:ptr))
+        opB = operands[1].x86Operand(:ptr)
+        $asm.puts "mov#{x86Suffix(:ptr)} #{orderOperands(opA, opB)}"
+    end
+
+    def handleX86Poke()
+        sp = RegisterID.new(nil, "sp")
+        opA = operands[0].x86Operand(:ptr)
+        opB = offsetRegister(operands[1].value * x86Bytes(:ptr), sp.x86Operand(:ptr))
+        $asm.puts "mov#{x86Suffix(:ptr)} #{orderOperands(opA, opB)}"
+    end
+
     def handleMove
         if Immediate.new(nil, 0) == operands[0] and operands[1].is_a? RegisterID
-            $asm.puts "xor#{x86Suffix(:ptr)} #{operands[1].x86Operand(:ptr)}, #{operands[1].x86Operand(:ptr)}"
+            if isX64
+                $asm.puts "xor#{x86Suffix(:quad)} #{operands[1].x86Operand(:quad)}, #{operands[1].x86Operand(:quad)}"
+            else
+                $asm.puts "xor#{x86Suffix(:ptr)} #{operands[1].x86Operand(:ptr)}, #{operands[1].x86Operand(:ptr)}"
+            end
         elsif operands[0] != operands[1]
-            $asm.puts "mov#{x86Suffix(:ptr)} #{x86Operands(:ptr, :ptr)}"
+            if isX64
+                $asm.puts "mov#{x86Suffix(:quad)} #{x86Operands(:quad, :quad)}"
+            else
+                $asm.puts "mov#{x86Suffix(:ptr)} #{x86Operands(:ptr, :ptr)}"
+            end
         end
     end
-    
+
+    def handleX87Compare(mode)
+        case mode
+        when :normal
+            if (operands[0].x87DefaultStackPosition == 0)
+                $asm.puts "fucomi #{@@floatingPointCompareImplicitOperand}#{operands[1].x87Operand(0)}"
+            else
+                $asm.puts "fld #{operands[0].x87Operand(0)}"
+                $asm.puts "fucomip #{@@floatingPointCompareImplicitOperand}#{operands[1].x87Operand(1)}"
+            end
+        when :reverse
+            if (operands[1].x87DefaultStackPosition == 0)
+                $asm.puts "fucomi #{@@floatingPointCompareImplicitOperand}#{operands[0].x87Operand(0)}"
+            else
+                $asm.puts "fld #{operands[1].x87Operand(0)}"
+                $asm.puts "fucomip #{@@floatingPointCompareImplicitOperand}#{operands[0].x87Operand(1)}"
+            end
+        else
+            raise mode.inspect
+        end
+    end
+
+    def handleX87BinOp(opcode, opcodereverse)
+        if (operands[1].x87DefaultStackPosition == 0)
+            $asm.puts "#{opcode} #{orderOperands(operands[0].x87Operand(0), register("st"))}"
+        elsif (operands[0].x87DefaultStackPosition == 0)
+            if !isIntelSyntax
+                $asm.puts "#{opcodereverse} #{register("st")}, #{operands[1].x87Operand(0)}"
+            else
+                $asm.puts "#{opcode} #{operands[1].x87Operand(0)}, #{register("st")}"
+            end
+        else
+            $asm.puts "fld #{operands[0].x87Operand(0)}"
+            $asm.puts "#{opcodereverse}p #{orderOperands(register("st"), operands[1].x87Operand(1))}"
+        end
+    end
+
     def lowerX86
         raise unless $activeBackend == "X86"
         lowerX86Common
     end
+
+    def lowerX86_WIN
+        raise unless $activeBackend == "X86_WIN" 
+        lowerX86Common
+    end
     
     def lowerX86_64
         raise unless $activeBackend == "X86_64"
         lowerX86Common
     end
-    
+
+    def lowerX86_64_WIN
+        raise unless $activeBackend == "X86_64_WIN"
+        lowerX86Common
+    end
+
     def lowerX86Common
-        $asm.comment codeOriginString
+        $asm.codeOrigin codeOriginString if $enableCodeOriginComments
+        $asm.annotation annotation if $enableInstrAnnotations
+
         case opcode
         when "addi"
             handleX86Add(:int)
         when "addp"
             handleX86Add(:ptr)
+        when "addq"
+            handleX86Add(:quad)
         when "andi"
-            handleX86Op("andl", :int)
+            handleX86Op("and#{x86Suffix(:int)}", :int)
         when "andp"
             handleX86Op("and#{x86Suffix(:ptr)}", :ptr)
+        when "andq"
+            handleX86Op("and#{x86Suffix(:quad)}", :quad)
         when "lshifti"
-            handleX86Shift("sall", :int)
+            handleX86Shift("sal#{x86Suffix(:int)}", :int)
         when "lshiftp"
             handleX86Shift("sal#{x86Suffix(:ptr)}", :ptr)
+        when "lshiftq"
+            handleX86Shift("sal#{x86Suffix(:quad)}", :quad)
         when "muli"
             handleX86Mul(:int)
         when "mulp"
             handleX86Mul(:ptr)
+        when "mulq"
+            handleX86Mul(:quad)
         when "negi"
-            $asm.puts "negl #{x86Operands(:int)}"
+            $asm.puts "neg#{x86Suffix(:int)} #{x86Operands(:int)}"
         when "negp"
             $asm.puts "neg#{x86Suffix(:ptr)} #{x86Operands(:ptr)}"
+        when "negq"
+            $asm.puts "neg#{x86Suffix(:quad)} #{x86Operands(:quad)}"
         when "noti"
-            $asm.puts "notl #{x86Operands(:int)}"
+            $asm.puts "not#{x86Suffix(:int)} #{x86Operands(:int)}"
         when "ori"
-            handleX86Op("orl", :int)
+            handleX86Op("or#{x86Suffix(:int)}", :int)
         when "orp"
             handleX86Op("or#{x86Suffix(:ptr)}", :ptr)
+        when "orq"
+            handleX86Op("or#{x86Suffix(:quad)}", :quad)
         when "rshifti"
-            handleX86Shift("sarl", :int)
+            handleX86Shift("sar#{x86Suffix(:int)}", :int)
         when "rshiftp"
             handleX86Shift("sar#{x86Suffix(:ptr)}", :ptr)
+        when "rshiftq"
+            handleX86Shift("sar#{x86Suffix(:quad)}", :quad)
         when "urshifti"
-            handleX86Shift("shrl", :int)
+            handleX86Shift("shr#{x86Suffix(:int)}", :int)
         when "urshiftp"
             handleX86Shift("shr#{x86Suffix(:ptr)}", :ptr)
+        when "urshiftq"
+            handleX86Shift("shr#{x86Suffix(:quad)}", :quad)
         when "subi"
             handleX86Sub(:int)
         when "subp"
             handleX86Sub(:ptr)
+        when "subq"
+            handleX86Sub(:quad)
         when "xori"
-            handleX86Op("xorl", :int)
+            handleX86Op("xor#{x86Suffix(:int)}", :int)
         when "xorp"
             handleX86Op("xor#{x86Suffix(:ptr)}", :ptr)
+        when "xorq"
+            handleX86Op("xor#{x86Suffix(:quad)}", :quad)
         when "loadi", "storei"
-            $asm.puts "movl #{x86Operands(:int, :int)}"
+            $asm.puts "mov#{x86Suffix(:int)} #{x86Operands(:int, :int)}"
         when "loadis"
             if isX64
-                $asm.puts "movslq #{x86Operands(:int, :ptr)}"
+                if !isIntelSyntax
+                    $asm.puts "movslq #{x86Operands(:int, :quad)}"
+                else
+                    $asm.puts "movsxd #{x86Operands(:int, :quad)}"
+                end
             else
-                $asm.puts "movl #{x86Operands(:int, :int)}"
+                $asm.puts "mov#{x86Suffix(:int)} #{x86Operands(:int, :int)}"
             end
         when "loadp", "storep"
             $asm.puts "mov#{x86Suffix(:ptr)} #{x86Operands(:ptr, :ptr)}"
+        when "loadq", "storeq"
+            $asm.puts "mov#{x86Suffix(:quad)} #{x86Operands(:quad, :quad)}"
         when "loadb"
-            $asm.puts "movzbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
+            if !isIntelSyntax
+                $asm.puts "movzbl #{orderOperands(operands[0].x86Operand(:byte), operands[1].x86Operand(:int))}"
+            else
+                $asm.puts "movzx #{orderOperands(operands[0].x86Operand(:byte), operands[1].x86Operand(:int))}"
+            end
         when "loadbs"
             $asm.puts "movsbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
         when "loadh"
-            $asm.puts "movzwl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}"
+            if !isIntelSyntax
+                $asm.puts "movzwl #{orderOperands(operands[0].x86Operand(:half), operands[1].x86Operand(:int))}"
+            else
+                $asm.puts "movzx #{orderOperands(operands[0].x86Operand(:half), operands[1].x86Operand(:int))}"
+            end
         when "loadhs"
             $asm.puts "movswl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}"
         when "storeb"
-            $asm.puts "movb #{x86Operands(:byte, :byte)}"
-        when "loadd", "moved", "stored"
-            $asm.puts "movsd #{x86Operands(:double, :double)}"
+            $asm.puts "mov#{x86Suffix(:byte)} #{x86Operands(:byte, :byte)}"
+        when "loadd"
+            if useX87
+                if !isIntelSyntax
+                    $asm.puts "fldl #{operands[0].x86Operand(:double)}"
+                else
+                    $asm.puts "fld #{operands[0].x86Operand(:double)}"
+                end
+                $asm.puts "fstp #{operands[1].x87Operand(1)}"
+            else
+                $asm.puts "movsd #{x86Operands(:double, :double)}"
+            end
+        when "moved"
+            if useX87
+                if (operands[0].x87DefaultStackPosition == 0)
+                    $asm.puts "fst #{operands[1].x87Operand(0)}"
+                else
+                    $asm.puts "fld #{operands[0].x87Operand(0)}"
+                    $asm.puts "fstp #{operands[1].x87Operand(1)}"
+                end
+            else
+                $asm.puts "movsd #{x86Operands(:double, :double)}"
+            end
+        when "stored"
+            if useX87
+                if (operands[0].x87DefaultStackPosition == 0)
+                    $asm.puts "fst#{x86Suffix(:int)} #{operands[1].x86Operand(:double)}"
+                else
+                    $asm.puts "fld #{operands[0].x87Operand(0)}"
+                    if !isIntelSyntax
+                        $asm.puts "fstpl #{operands[1].x86Operand(:double)}"
+                    else
+                        $asm.puts "fstp #{operands[1].x86Operand(:double)}"
+                    end
+                end
+            else
+                $asm.puts "movsd #{x86Operands(:double, :double)}"
+            end
         when "addd"
-            $asm.puts "addsd #{x86Operands(:double, :double)}"
-        when "divd"
-            $asm.puts "divsd #{x86Operands(:double, :double)}"
-        when "subd"
-            $asm.puts "subsd #{x86Operands(:double, :double)}"
+            if useX87
+                handleX87BinOp("fadd", "fadd")
+            else
+                $asm.puts "addsd #{x86Operands(:double, :double)}"
+            end
         when "muld"
-            $asm.puts "mulsd #{x86Operands(:double, :double)}"
+            if useX87
+                handleX87BinOp("fmul", "fmul")
+            else
+                $asm.puts "mulsd #{x86Operands(:double, :double)}"
+            end
+        when "subd"
+            if useX87
+                handleX87BinOp("fsub", "fsubr")
+            else
+                $asm.puts "subsd #{x86Operands(:double, :double)}"
+            end
+        when "divd"
+            if useX87
+                handleX87BinOp("fdiv", "fdivr")
+            else
+                $asm.puts "divsd #{x86Operands(:double, :double)}"
+            end
         when "sqrtd"
-            $asm.puts "sqrtsd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
+            if useX87
+                $asm.puts "fld #{operands[0].x87Operand(0)}"
+                $asm.puts "fsqrtl"
+                $asm.puts "fstp #{operands[1].x87Operand(1)}"
+            else
+                $asm.puts "sqrtsd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
+            end
         when "ci2d"
-            $asm.puts "cvtsi2sd #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:double)}"
+            if useX87
+                sp = RegisterID.new(nil, "sp")
+                $asm.puts "mov#{x86Suffix(:int)} #{orderOperands(operands[0].x86Operand(:int), offsetRegister(-4, sp.x86Operand(:ptr)))}"
+                $asm.puts "fild#{x86Suffix(:ptr)} #{getSizeString(:ptr)}#{offsetRegister(-4, sp.x86Operand(:ptr))}"
+                $asm.puts "fstp #{operands[1].x87Operand(1)}"
+            else
+                $asm.puts "cvtsi2sd #{orderOperands(operands[0].x86Operand(:int), operands[1].x86Operand(:double))}"
+            end
         when "bdeq"
-            isUnordered = LocalLabel.unique("bdeq")
-            $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
-            $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
-            $asm.puts "je #{LabelReference.new(codeOrigin, operands[2]).asmLabel}"
-            isUnordered.lower("X86")
+            if useX87
+                handleX87Compare(:normal)
+            else
+                $asm.puts "ucomisd #{orderOperands(operands[0].x86Operand(:double), operands[1].x86Operand(:double))}"
+            end
+            if operands[0] == operands[1]
+                # This is just a jump ordered, which is a jnp.
+                $asm.puts "jnp #{operands[2].asmLabel}"
+            else
+                isUnordered = LocalLabel.unique("bdeq")
+                $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
+                $asm.puts "je #{LabelReference.new(codeOrigin, operands[2]).asmLabel}"
+                isUnordered.lower("X86")
+            end
         when "bdneq"
             handleX86DoubleBranch("jne", :normal)
         when "bdgt"
@@ -711,14 +1069,23 @@ class Instruction
         when "bdequn"
             handleX86DoubleBranch("je", :normal)
         when "bdnequn"
-            isUnordered = LocalLabel.unique("bdnequn")
-            isEqual = LocalLabel.unique("bdnequn")
-            $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
-            $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
-            $asm.puts "je #{LabelReference.new(codeOrigin, isEqual).asmLabel}"
-            isUnordered.lower("X86")
-            $asm.puts "jmp #{operands[2].asmLabel}"
-            isEqual.lower("X86")
+            if useX87
+                handleX87Compare(:normal)
+            else
+                $asm.puts "ucomisd #{orderOperands(operands[0].x86Operand(:double), operands[1].x86Operand(:double))}"
+            end
+            if operands[0] == operands[1]
+                # This is just a jump unordered, which is a jp.
+                $asm.puts "jp #{operands[2].asmLabel}"
+            else
+                isUnordered = LocalLabel.unique("bdnequn")
+                isEqual = LocalLabel.unique("bdnequn")
+                $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
+                $asm.puts "je #{LabelReference.new(codeOrigin, isEqual).asmLabel}"
+                isUnordered.lower("X86")
+                $asm.puts "jmp #{operands[2].asmLabel}"
+                isEqual.lower("X86")
+            end
         when "bdgtun"
             handleX86DoubleBranch("jb", :reverse)
         when "bdgtequn"
@@ -728,81 +1095,161 @@ class Instruction
         when "bdltequn"
             handleX86DoubleBranch("jbe", :normal)
         when "btd2i"
+            # FIXME: unused and unimplemented for x87
+            raise if useX87
             $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
             $asm.puts "cmpl $0x80000000 #{operands[1].x86Operand(:int)}"
             $asm.puts "je #{operands[2].asmLabel}"
         when "td2i"
+            # FIXME: unused and unimplemented for x87
+            raise if useX87
             $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
         when "bcd2i"
-            $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
-            $asm.puts "testl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
-            $asm.puts "je #{operands[2].asmLabel}"
-            $asm.puts "cvtsi2sd #{operands[1].x86Operand(:int)}, %xmm7"
-            $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, %xmm7"
-            $asm.puts "jp #{operands[2].asmLabel}"
-            $asm.puts "jne #{operands[2].asmLabel}"
+            if useX87
+                sp = RegisterID.new(nil, "sp")
+                if (operands[0].x87DefaultStackPosition == 0)
+                    $asm.puts "fistl -4(#{sp.x86Operand(:ptr)})"
+                else
+                    $asm.puts "fld #{operands[0].x87Operand(0)}"
+                    $asm.puts "fistp#{x86Suffix(:ptr)} #{getSizeString(:ptr)}#{offsetRegister(-4, sp.x86Operand(:ptr))}"
+                end
+                $asm.puts "mov#{x86Suffix(:int)} #{orderOperands(offsetRegister(-4, sp.x86Operand(:ptr)), operands[1].x86Operand(:int))}"
+                $asm.puts "test#{x86Suffix(:int)} #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
+                $asm.puts "je #{operands[2].asmLabel}"
+                $asm.puts "fild#{x86Suffix(:int)} #{getSizeString(:int)}#{offsetRegister(-4, sp.x86Operand(:ptr))}"
+                $asm.puts "fucomip #{@@floatingPointCompareImplicitOperand}#{operands[0].x87Operand(1)}"
+                $asm.puts "jp #{operands[2].asmLabel}"
+                $asm.puts "jne #{operands[2].asmLabel}"
+            else
+                $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
+                $asm.puts "test#{x86Suffix(:int)} #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
+                $asm.puts "je #{operands[2].asmLabel}"
+                $asm.puts "cvtsi2sd #{operands[1].x86Operand(:int)}, %xmm7"
+                $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, %xmm7"
+                $asm.puts "jp #{operands[2].asmLabel}"
+                $asm.puts "jne #{operands[2].asmLabel}"
+            end
         when "movdz"
-            $asm.puts "xorpd #{operands[0].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
+            if useX87
+                $asm.puts "fldzl"
+                $asm.puts "fstp #{operands[0].x87Operand(1)}"
+            else
+                $asm.puts "xorpd #{operands[0].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
+            end
         when "pop"
-            $asm.puts "pop #{operands[0].x86Operand(:ptr)}"
+            operands.each {
+                | op |
+                $asm.puts "pop #{op.x86Operand(:ptr)}"
+            }
         when "push"
-            $asm.puts "push #{operands[0].x86Operand(:ptr)}"
-        when "move"
-            handleMove
-        when "sxi2p"
+            operands.each {
+                | op |
+                $asm.puts "push #{op.x86Operand(:ptr)}"
+            }
+        when "popCalleeSaves"
             if isX64
-                $asm.puts "movslq #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:ptr)}"
+                if isMSVC
+                    $asm.puts "pop " + register("rsi")
+                    $asm.puts "pop " + register("rdi")
+                end
+                $asm.puts "pop " + register("rbx")
+                $asm.puts "pop " + register("r15")
+                $asm.puts "pop " + register("r14")
+                $asm.puts "pop " + register("r13")
+                $asm.puts "pop " + register("r12")
             else
-                handleMove
+                $asm.puts "pop " + register("ebx")
+                $asm.puts "pop " + register("edi")
+                $asm.puts "pop " + register("esi")
             end
-        when "zxi2p"
+        when "pushCalleeSaves"
             if isX64
-                $asm.puts "movl #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
+                $asm.puts "push " + register("r12")
+                $asm.puts "push " + register("r13")
+                $asm.puts "push " + register("r14")
+                $asm.puts "push " + register("r15")
+                $asm.puts "push " + register("rbx")
+                if isMSVC
+                    $asm.puts "push " + register("rdi")
+                    $asm.puts "push " + register("rsi")
+                end
+            else
+                $asm.puts "push " + register("esi")
+                $asm.puts "push " + register("edi")
+                $asm.puts "push " + register("ebx")
+            end
+        when "move"
+            handleMove
+        when "sxi2q"
+            if !isIntelSyntax
+                $asm.puts "movslq #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:quad)}"
             else
-                handleMove
+                $asm.puts "movsxd #{orderOperands(operands[0].x86Operand(:int), operands[1].x86Operand(:quad))}"
             end
+        when "zxi2q"
+            $asm.puts "mov#{x86Suffix(:int)} #{orderOperands(operands[0].x86Operand(:int), operands[1].x86Operand(:int))}"
         when "nop"
             $asm.puts "nop"
         when "bieq"
             handleX86IntBranch("je", :int)
         when "bpeq"
             handleX86IntBranch("je", :ptr)
+        when "bqeq"
+            handleX86IntBranch("je", :quad)
         when "bineq"
             handleX86IntBranch("jne", :int)
         when "bpneq"
             handleX86IntBranch("jne", :ptr)
+        when "bqneq"
+            handleX86IntBranch("jne", :quad)
         when "bia"
             handleX86IntBranch("ja", :int)
         when "bpa"
             handleX86IntBranch("ja", :ptr)
+        when "bqa"
+            handleX86IntBranch("ja", :quad)
         when "biaeq"
             handleX86IntBranch("jae", :int)
         when "bpaeq"
             handleX86IntBranch("jae", :ptr)
+        when "bqaeq"
+            handleX86IntBranch("jae", :quad)
         when "bib"
             handleX86IntBranch("jb", :int)
         when "bpb"
             handleX86IntBranch("jb", :ptr)
+        when "bqb"
+            handleX86IntBranch("jb", :quad)
         when "bibeq"
             handleX86IntBranch("jbe", :int)
         when "bpbeq"
             handleX86IntBranch("jbe", :ptr)
+        when "bqbeq"
+            handleX86IntBranch("jbe", :quad)
         when "bigt"
             handleX86IntBranch("jg", :int)
         when "bpgt"
             handleX86IntBranch("jg", :ptr)
+        when "bqgt"
+            handleX86IntBranch("jg", :quad)
         when "bigteq"
             handleX86IntBranch("jge", :int)
         when "bpgteq"
             handleX86IntBranch("jge", :ptr)
+        when "bqgteq"
+            handleX86IntBranch("jge", :quad)
         when "bilt"
             handleX86IntBranch("jl", :int)
         when "bplt"
             handleX86IntBranch("jl", :ptr)
+        when "bqlt"
+            handleX86IntBranch("jl", :quad)
         when "bilteq"
             handleX86IntBranch("jle", :int)
         when "bplteq"
             handleX86IntBranch("jle", :ptr)
+        when "bqlteq"
+            handleX86IntBranch("jle", :quad)
         when "bbeq"
             handleX86IntBranch("je", :byte)
         when "bbneq"
@@ -823,24 +1270,24 @@ class Instruction
             handleX86IntBranch("jl", :byte)
         when "bblteq"
             handleX86IntBranch("jlteq", :byte)
-        when "btio"
-            handleX86BranchTest("jo", :int)
-        when "btpo"
-            handleX86BranchTest("jo", :ptr)
         when "btis"
             handleX86BranchTest("js", :int)
         when "btps"
             handleX86BranchTest("js", :ptr)
+        when "btqs"
+            handleX86BranchTest("js", :quad)
         when "btiz"
             handleX86BranchTest("jz", :int)
         when "btpz"
             handleX86BranchTest("jz", :ptr)
+        when "btqz"
+            handleX86BranchTest("jz", :quad)
         when "btinz"
             handleX86BranchTest("jnz", :int)
         when "btpnz"
             handleX86BranchTest("jnz", :ptr)
-        when "btbo"
-            handleX86BranchTest("jo", :byte)
+        when "btqnz"
+            handleX86BranchTest("jnz", :quad)
         when "btbs"
             handleX86BranchTest("js", :byte)
         when "btbz"
@@ -850,21 +1297,29 @@ class Instruction
         when "jmp"
             $asm.puts "jmp #{operands[0].x86CallOperand(:ptr)}"
         when "baddio"
-            handleX86OpBranch("addl", "jo", :int)
+            handleX86OpBranch("add#{x86Suffix(:int)}", "jo", :int)
         when "baddpo"
             handleX86OpBranch("add#{x86Suffix(:ptr)}", "jo", :ptr)
+        when "baddqo"
+            handleX86OpBranch("add#{x86Suffix(:quad)}", "jo", :quad)
         when "baddis"
-            handleX86OpBranch("addl", "js", :int)
+            handleX86OpBranch("add#{x86Suffix(:int)}", "js", :int)
         when "baddps"
             handleX86OpBranch("add#{x86Suffix(:ptr)}", "js", :ptr)
+        when "baddqs"
+            handleX86OpBranch("add#{x86Suffix(:quad)}", "js", :quad)
         when "baddiz"
-            handleX86OpBranch("addl", "jz", :int)
+            handleX86OpBranch("add#{x86Suffix(:int)}", "jz", :int)
         when "baddpz"
             handleX86OpBranch("add#{x86Suffix(:ptr)}", "jz", :ptr)
+        when "baddqz"
+            handleX86OpBranch("add#{x86Suffix(:quad)}", "jz", :quad)
         when "baddinz"
-            handleX86OpBranch("addl", "jnz", :int)
+            handleX86OpBranch("add#{x86Suffix(:int)}", "jnz", :int)
         when "baddpnz"
             handleX86OpBranch("add#{x86Suffix(:ptr)}", "jnz", :ptr)
+        when "baddqnz"
+            handleX86OpBranch("add#{x86Suffix(:quad)}", "jnz", :quad)
         when "bsubio"
             handleX86SubBranch("jo", :int)
         when "bsubis"
@@ -874,13 +1329,13 @@ class Instruction
         when "bsubinz"
             handleX86SubBranch("jnz", :int)
         when "bmulio"
-            handleX86OpBranch("imull", "jo", :int)
+            handleX86OpBranch("imul#{x86Suffix(:int)}", "jo", :int)
         when "bmulis"
-            handleX86OpBranch("imull", "js", :int)
+            handleX86OpBranch("imul#{x86Suffix(:int)}", "js", :int)
         when "bmuliz"
-            handleX86OpBranch("imull", "jz", :int)
+            handleX86OpBranch("imul#{x86Suffix(:int)}", "jz", :int)
         when "bmulinz"
-            handleX86OpBranch("imull", "jnz", :int)
+            handleX86OpBranch("imul#{x86Suffix(:int)}", "jnz", :int)
         when "borio"
             handleX86OpBranch("orl", "jo", :int)
         when "boris"
@@ -890,9 +1345,19 @@ class Instruction
         when "borinz"
             handleX86OpBranch("orl", "jnz", :int)
         when "break"
-            $asm.puts "int $3"
+            $asm.puts "int #{const(3)}"
         when "call"
-            $asm.puts "call #{operands[0].x86CallOperand(:ptr)}"
+            if useX87
+                2.times {
+                    | offset |
+                    $asm.puts "ffree #{register("st")}(#{offset})"
+                }
+            end
+            op = operands[0].x86CallOperand(:ptr)
+            if operands[0].is_a? LabelReference
+                operands[0].used
+            end
+            $asm.puts "call #{op}"
         when "ret"
             $asm.puts "ret"
         when "cieq"
@@ -901,78 +1366,98 @@ class Instruction
             handleX86IntCompareSet("sete", :byte)
         when "cpeq"
             handleX86IntCompareSet("sete", :ptr)
+        when "cqeq"
+            handleX86IntCompareSet("sete", :quad)
         when "cineq"
             handleX86IntCompareSet("setne", :int)
         when "cbneq"
             handleX86IntCompareSet("setne", :byte)
         when "cpneq"
             handleX86IntCompareSet("setne", :ptr)
+        when "cqneq"
+            handleX86IntCompareSet("setne", :quad)
         when "cia"
             handleX86IntCompareSet("seta", :int)
         when "cba"
             handleX86IntCompareSet("seta", :byte)
         when "cpa"
             handleX86IntCompareSet("seta", :ptr)
+        when "cqa"
+            handleX86IntCompareSet("seta", :quad)
         when "ciaeq"
             handleX86IntCompareSet("setae", :int)
         when "cbaeq"
             handleX86IntCompareSet("setae", :byte)
         when "cpaeq"
             handleX86IntCompareSet("setae", :ptr)
+        when "cqaeq"
+            handleX86IntCompareSet("setae", :quad)
         when "cib"
             handleX86IntCompareSet("setb", :int)
         when "cbb"
             handleX86IntCompareSet("setb", :byte)
         when "cpb"
             handleX86IntCompareSet("setb", :ptr)
+        when "cqb"
+            handleX86IntCompareSet("setb", :quad)
         when "cibeq"
             handleX86IntCompareSet("setbe", :int)
         when "cbbeq"
             handleX86IntCompareSet("setbe", :byte)
         when "cpbeq"
             handleX86IntCompareSet("setbe", :ptr)
+        when "cqbeq"
+            handleX86IntCompareSet("setbe", :quad)
         when "cigt"
             handleX86IntCompareSet("setg", :int)
         when "cbgt"
             handleX86IntCompareSet("setg", :byte)
         when "cpgt"
             handleX86IntCompareSet("setg", :ptr)
+        when "cqgt"
+            handleX86IntCompareSet("setg", :quad)
         when "cigteq"
             handleX86IntCompareSet("setge", :int)
         when "cbgteq"
             handleX86IntCompareSet("setge", :byte)
         when "cpgteq"
             handleX86IntCompareSet("setge", :ptr)
+        when "cqgteq"
+            handleX86IntCompareSet("setge", :quad)
         when "cilt"
             handleX86IntCompareSet("setl", :int)
         when "cblt"
             handleX86IntCompareSet("setl", :byte)
         when "cplt"
             handleX86IntCompareSet("setl", :ptr)
+        when "cqlt"
+            handleX86IntCompareSet("setl", :quad)
         when "cilteq"
             handleX86IntCompareSet("setle", :int)
         when "cblteq"
             handleX86IntCompareSet("setle", :byte)
         when "cplteq"
             handleX86IntCompareSet("setle", :ptr)
-        when "tio"
-            handleX86SetTest("seto", :int)
+        when "cqlteq"
+            handleX86IntCompareSet("setle", :quad)
         when "tis"
             handleX86SetTest("sets", :int)
         when "tiz"
             handleX86SetTest("setz", :int)
         when "tinz"
             handleX86SetTest("setnz", :int)
-        when "tpo"
-            handleX86SetTest("seto", :ptr)
         when "tps"
             handleX86SetTest("sets", :ptr)
         when "tpz"
             handleX86SetTest("setz", :ptr)
         when "tpnz"
             handleX86SetTest("setnz", :ptr)
-        when "tbo"
-            handleX86SetTest("seto", :byte)
+        when "tqs"
+            handleX86SetTest("sets", :quad)
+        when "tqz"
+            handleX86SetTest("setz", :quad)
+        when "tqnz"
+            handleX86SetTest("setnz", :quad)
         when "tbs"
             handleX86SetTest("sets", :byte)
         when "tbz"
@@ -980,29 +1465,77 @@ class Instruction
         when "tbnz"
             handleX86SetTest("setnz", :byte)
         when "peek"
-            sp = RegisterID.new(nil, "sp")
-            $asm.puts "mov#{x86Suffix(:ptr)} #{operands[0].value * x86Bytes(:ptr)}(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:ptr)}"
+            handleX86Peek()
         when "poke"
-            sp = RegisterID.new(nil, "sp")
-            $asm.puts "mov#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{operands[1].value * x86Bytes(:ptr)}(#{sp.x86Operand(:ptr)})"
+            handleX86Poke()
         when "cdqi"
             $asm.puts "cdq"
         when "idivi"
-            $asm.puts "idivl #{operands[0].x86Operand(:int)}"
+            $asm.puts "idiv#{x86Suffix(:int)} #{operands[0].x86Operand(:int)}"
         when "fii2d"
-            $asm.puts "movd #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:double)}"
-            $asm.puts "movd #{operands[1].x86Operand(:int)}, %xmm7"
-            $asm.puts "psllq $32, %xmm7"
-            $asm.puts "por %xmm7, #{operands[2].x86Operand(:double)}"
+            if useX87
+                sp = RegisterID.new(nil, "sp")
+                $asm.puts "mov#{x86Suffix(:int)} #{orderOperands(operands[0].x86Operand(:int), offsetRegister(-8, sp.x86Operand(:ptr)))}"
+                $asm.puts "mov#{x86Suffix(:int)} #{orderOperands(operands[1].x86Operand(:int), offsetRegister(-4, sp.x86Operand(:ptr)))}"
+                $asm.puts "fld#{x86Suffix(:ptr)} #{getSizeString(:double)}#{offsetRegister(-8, sp.x86Operand(:ptr))}"
+                $asm.puts "fstp #{operands[2].x87Operand(1)}"
+            else
+                $asm.puts "movd #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:double)}"
+                $asm.puts "movd #{operands[1].x86Operand(:int)}, %xmm7"
+                $asm.puts "psllq $32, %xmm7"
+                $asm.puts "por %xmm7, #{operands[2].x86Operand(:double)}"
+            end
         when "fd2ii"
-            $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
-            $asm.puts "movsd #{operands[0].x86Operand(:double)}, %xmm7"
-            $asm.puts "psrlq $32, %xmm7"
-            $asm.puts "movsd %xmm7, #{operands[2].x86Operand(:int)}"
-        when "fp2d"
-            $asm.puts "movd #{operands[0].x86Operand(:ptr)}, #{operands[1].x86Operand(:double)}"
-        when "fd2p"
-            $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:ptr)}"
+            if useX87
+                sp = RegisterID.new(nil, "sp")
+                if (operands[0].x87DefaultStackPosition == 0)
+                    $asm.puts "fst#{x86Suffix(:ptr)} #{getSizeString(:double)}#{offsetRegister(-8, sp.x86Operand(:ptr))}"
+                else
+                    $asm.puts "fld #{operands[0].x87Operand(0)}"
+                    $asm.puts "fstpl -8(#{sp.x86Operand(:ptr)})"
+                end
+                $asm.puts "mov#{x86Suffix(:int)} #{orderOperands(offsetRegister(-8, sp.x86Operand(:ptr)), operands[1].x86Operand(:int))}"
+                $asm.puts "mov#{x86Suffix(:int)} #{orderOperands(offsetRegister(-4, sp.x86Operand(:ptr)), operands[2].x86Operand(:int))}"
+            else
+                $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
+                $asm.puts "movsd #{operands[0].x86Operand(:double)}, %xmm7"
+                $asm.puts "psrlq $32, %xmm7"
+                $asm.puts "movd %xmm7, #{operands[2].x86Operand(:int)}"
+            end
+        when "fq2d"
+            if useX87
+                sp = RegisterID.new(nil, "sp")
+                $asm.puts "movq #{operands[0].x86Operand(:quad)}, -8(#{sp.x86Operand(:ptr)})"
+                $asm.puts "fldl -8(#{sp.x86Operand(:ptr)})"
+                $asm.puts "fstp #{operands[1].x87Operand(1)}"
+            else
+                if !isIntelSyntax
+                    $asm.puts "movq #{operands[0].x86Operand(:quad)}, #{operands[1].x86Operand(:double)}"
+                else
+                    # MASM does not accept register operands with movq.
+                    # Debugging shows that movd actually moves a qword when using MASM.
+                    $asm.puts "movd #{operands[1].x86Operand(:double)}, #{operands[0].x86Operand(:quad)}"
+                end
+            end
+        when "fd2q"
+            if useX87
+                sp = RegisterID.new(nil, "sp")
+                if (operands[0].x87DefaultStackPosition == 0)
+                    $asm.puts "fst#{x86Suffix(:int)} #{getSizeString(:int)}#{offsetRegister(-8, sp.x86Operand(:ptr))}"
+                else
+                    $asm.puts "fld #{operands[0].x87Operand(0)}"
+                    $asm.puts "fstpl -8(#{sp.x86Operand(:ptr)})"
+                end
+                $asm.puts "movq -8(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:quad)}"
+            else
+                if !isIntelSyntax
+                    $asm.puts "movq #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:quad)}"
+                else
+                    # MASM does not accept register operands with movq.
+                    # Debugging shows that movd actually moves a qword when using MASM.
+                    $asm.puts "movd #{operands[1].x86Operand(:quad)}, #{operands[0].x86Operand(:double)}"
+                end
+            end
         when "bo"
             $asm.puts "jo #{operands[0].asmLabel}"
         when "bs"
@@ -1012,11 +1545,13 @@ class Instruction
         when "bnz"
             $asm.puts "jnz #{operands[0].asmLabel}"
         when "leai"
-            $asm.puts "leal #{operands[0].x86AddressOperand(:int)}, #{operands[1].x86Operand(:int)}"
+            $asm.puts "lea#{x86Suffix(:int)} #{orderOperands(operands[0].x86AddressOperand(:int), operands[1].x86Operand(:int))}"
         when "leap"
-            $asm.puts "lea#{x86Suffix(:ptr)} #{operands[0].x86AddressOperand(:ptr)}, #{operands[1].x86Operand(:ptr)}"
+            $asm.puts "lea#{x86Suffix(:ptr)} #{orderOperands(operands[0].x86AddressOperand(:ptr), operands[1].x86Operand(:ptr))}"
+        when "memfence"
+            $asm.puts "mfence"
         else
-            raise "Bad opcode: #{opcode}"
+            lowerDefault
         end
     end
 end