summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/offlineasm/x86.rb
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/offlineasm/x86.rb')
-rw-r--r--Source/JavaScriptCore/offlineasm/x86.rb681
1 files changed, 681 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/offlineasm/x86.rb b/Source/JavaScriptCore/offlineasm/x86.rb
new file mode 100644
index 000000000..b89f2d90c
--- /dev/null
+++ b/Source/JavaScriptCore/offlineasm/x86.rb
@@ -0,0 +1,681 @@
+# Copyright (C) 2011 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+# THE POSSIBILITY OF SUCH DAMAGE.
+
+class RegisterID
+ def supports8BitOnX86
+ case name
+ when "t0", "a0", "r0", "t1", "a1", "r1", "t2", "t3"
+ true
+ when "t4", "cfr"
+ false
+ else
+ raise
+ end
+ end
+
+ def x86Operand(kind)
+ case name
+ when "t0", "a0", "r0"
+ case kind
+ when :byte
+ "%al"
+ when :half
+ "%ax"
+ when :int
+ "%eax"
+ else
+ raise
+ end
+ when "t1", "a1", "r1"
+ case kind
+ when :byte
+ "%dl"
+ when :half
+ "%dx"
+ when :int
+ "%edx"
+ else
+ raise
+ end
+ when "t2"
+ case kind
+ when :byte
+ "%cl"
+ when :half
+ "%cx"
+ when :int
+ "%ecx"
+ else
+ raise
+ end
+ when "t3"
+ case kind
+ when :byte
+ "%bl"
+ when :half
+ "%bx"
+ when :int
+ "%ebx"
+ else
+ raise
+ end
+ when "t4"
+ case kind
+ when :byte
+ "%sil"
+ when :half
+ "%si"
+ when :int
+ "%esi"
+ else
+ raise
+ end
+ when "cfr"
+ case kind
+ when :byte
+ "%dil"
+ when :half
+ "%di"
+ when :int
+ "%edi"
+ else
+ raise
+ end
+ when "sp"
+ case kind
+ when :byte
+ "%spl"
+ when :half
+ "%sp"
+ when :int
+ "%esp"
+ else
+ raise
+ end
+ else
+ raise "Bad register #{name} for X86 at #{codeOriginString}"
+ end
+ end
+ def x86CallOperand(kind)
+ "*#{x86Operand(kind)}"
+ end
+end
+
+class FPRegisterID
+ def x86Operand(kind)
+ raise unless kind == :double
+ case name
+ when "ft0", "fa0", "fr"
+ "%xmm0"
+ when "ft1", "fa1"
+ "%xmm1"
+ when "ft2", "fa2"
+ "%xmm2"
+ when "ft3", "fa3"
+ "%xmm3"
+ when "ft4"
+ "%xmm4"
+ when "ft5"
+ "%xmm5"
+ else
+ raise "Bad register #{name} for X86 at #{codeOriginString}"
+ end
+ end
+ def x86CallOperand(kind)
+ "*#{x86Operand(kind)}"
+ end
+end
+
+class Immediate
+ def x86Operand(kind)
+ "$#{value}"
+ end
+ def x86CallOperand(kind)
+ "#{value}"
+ end
+end
+
+class Address
+ def supports8BitOnX86
+ true
+ end
+
+ def x86Operand(kind)
+ "#{offset.value}(#{base.x86Operand(:int)})"
+ end
+ def x86CallOperand(kind)
+ "*#{x86Operand(kind)}"
+ end
+end
+
+class BaseIndex
+ def supports8BitOnX86
+ true
+ end
+
+ def x86Operand(kind)
+ "#{offset.value}(#{base.x86Operand(:int)}, #{index.x86Operand(:int)}, #{scale})"
+ end
+
+ def x86CallOperand(kind)
+ "*#{x86operand(kind)}"
+ end
+end
+
+class AbsoluteAddress
+ def supports8BitOnX86
+ true
+ end
+
+ def x86Operand(kind)
+ "#{address.value}"
+ end
+
+ def x86CallOperand(kind)
+ "*#{address.value}"
+ end
+end
+
+class LabelReference
+ def x86CallOperand(kind)
+ asmLabel
+ end
+end
+
+class LocalLabelReference
+ def x86CallOperand(kind)
+ asmLabel
+ end
+end
+
+class Instruction
+ def x86Operands(*kinds)
+ raise unless kinds.size == operands.size
+ result = []
+ kinds.size.times {
+ | idx |
+ result << operands[idx].x86Operand(kinds[idx])
+ }
+ result.join(", ")
+ end
+
+ def x86Suffix(kind)
+ case kind
+ when :byte
+ "b"
+ when :half
+ "w"
+ when :int
+ "l"
+ when :double
+ "sd"
+ else
+ raise
+ end
+ end
+
+ def handleX86OpWithNumOperands(opcode, kind, numOperands)
+ if numOperands == 3
+ if operands[0] == operands[2]
+ $asm.puts "#{opcode} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
+ elsif operands[1] == operands[2]
+ $asm.puts "#{opcode} #{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)}"
+ end
+ else
+ $asm.puts "#{opcode} #{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}"
+ end
+ end
+
+ def handleX86Op(opcode, kind)
+ handleX86OpWithNumOperands(opcode, kind, operands.size)
+ end
+
+ 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)}"
+ else
+ $asm.puts "xchgl #{operands[0].x86Operand(:int)}, %ecx"
+ $asm.puts "#{opcode} %cl, #{operands[1].x86Operand(kind)}"
+ $asm.puts "xchgl #{operands[0].x86Operand(:int)}, %ecx"
+ 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)}"
+ else
+ raise mode.inspect
+ 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)}"
+ 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)}"
+ else
+ $asm.puts "cmp#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[0].x86Operand(kind)}"
+ end
+ end
+
+ def handleX86IntBranch(branchOpcode, kind)
+ handleX86IntCompare(branchOpcode[1..-1], kind)
+ $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
+ end
+
+ def handleX86Set(setOpcode, operand)
+ if operand.supports8BitOnX86
+ $asm.puts "#{setOpcode} #{operand.x86Operand(:byte)}"
+ $asm.puts "movzbl #{operand.x86Operand(:byte)}, #{operand.x86Operand(:int)}"
+ else
+ $asm.puts "xchgl #{operand.x86Operand(:int)}, %eax"
+ $asm.puts "#{setOpcode} %al"
+ $asm.puts "movzbl %al, %eax"
+ $asm.puts "xchgl #{operand.x86Operand(:int)}, %eax"
+ end
+ end
+
+ def handleX86IntCompareSet(setOpcode, kind)
+ handleX86IntCompare(setOpcode[3..-1], kind)
+ handleX86Set(setOpcode, operands[2])
+ end
+
+ def handleX86Test(kind)
+ value = operands[0]
+ case operands.size
+ when 2
+ mask = Immediate.new(codeOrigin, -1)
+ when 3
+ mask = operands[1]
+ else
+ raise "Expected 2 or 3 operands, but got #{operands.size} at #{codeOriginString}"
+ end
+
+ if mask.is_a? Immediate and mask.value == -1
+ 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)}"
+ end
+ else
+ $asm.puts "test#{x86Suffix(kind)} #{mask.x86Operand(kind)}, #{value.x86Operand(kind)}"
+ end
+ end
+
+ def handleX86BranchTest(branchOpcode, kind)
+ handleX86Test(kind)
+ $asm.puts "#{branchOpcode} #{operands.last.asmLabel}"
+ end
+
+ def handleX86SetTest(setOpcode, kind)
+ handleX86Test(kind)
+ handleX86Set(setOpcode, operands.last)
+ end
+
+ def handleX86OpBranch(opcode, branchOpcode, kind)
+ handleX86OpWithNumOperands(opcode, kind, operands.size - 1)
+ case operands.size
+ when 4
+ jumpTarget = operands[3]
+ when 3
+ jumpTarget = operands[2]
+ else
+ raise self.inspect
+ end
+ $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}"
+ end
+
+ def handleX86SubBranch(branchOpcode, kind)
+ if operands.size == 4 and operands[1] == operands[2]
+ $asm.puts "negl #{operands[2].x86Operand(:int)}"
+ $asm.puts "addl #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:int)}"
+ else
+ handleX86OpWithNumOperands("sub#{x86Suffix(kind)}", kind, operands.size - 1)
+ end
+ case operands.size
+ when 4
+ jumpTarget = operands[3]
+ when 3
+ jumpTarget = operands[2]
+ else
+ raise self.inspect
+ end
+ $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}"
+ end
+
+ def lowerX86
+ $asm.comment codeOriginString
+ case opcode
+ when "addi", "addp"
+ if 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 "movl #{operands[1].x86Operand(:int)}, #{operands[2].x86Operand(:int)}"
+ end
+ else
+ $asm.puts "leal #{operands[0].value}(#{operands[1].x86Operand(:int)}), #{operands[2].x86Operand(:int)}"
+ 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 "leal (#{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}), #{operands[2].x86Operand(:int)}"
+ else
+ unless Immediate.new(nil, 0) == operands[0]
+ $asm.puts "addl #{x86Operands(:int, :int)}"
+ end
+ end
+ when "andi", "andp"
+ handleX86Op("andl", :int)
+ when "lshifti"
+ handleX86Shift("sall", :int)
+ when "muli"
+ if operands.size == 3 and operands[0].is_a? Immediate
+ $asm.puts "imull #{x86Operands(:int, :int, :int)}"
+ else
+ # FIXME: could do some peephole in case the left operand is immediate and it's
+ # a power of two.
+ handleX86Op("imull", :int)
+ end
+ when "negi"
+ $asm.puts "negl #{x86Operands(:int)}"
+ when "noti"
+ $asm.puts "notl #{x86Operands(:int)}"
+ when "ori", "orp"
+ handleX86Op("orl", :int)
+ when "rshifti"
+ handleX86Shift("sarl", :int)
+ when "urshifti"
+ handleX86Shift("shrl", :int)
+ when "subi", "subp"
+ if operands.size == 3 and operands[1] == operands[2]
+ $asm.puts "negl #{operands[2].x86Operand(:int)}"
+ $asm.puts "addl #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:int)}"
+ else
+ handleX86Op("subl", :int)
+ end
+ when "xori", "xorp"
+ handleX86Op("xorl", :int)
+ when "loadi", "storei", "loadp", "storep"
+ $asm.puts "movl #{x86Operands(:int, :int)}"
+ when "loadb"
+ $asm.puts "movzbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
+ 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)}"
+ 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)}"
+ when "addd"
+ $asm.puts "addsd #{x86Operands(:double, :double)}"
+ when "divd"
+ $asm.puts "divsd #{x86Operands(:double, :double)}"
+ when "subd"
+ $asm.puts "subsd #{x86Operands(:double, :double)}"
+ when "muld"
+ $asm.puts "mulsd #{x86Operands(:double, :double)}"
+ when "sqrtd"
+ $asm.puts "sqrtsd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
+ when "ci2d"
+ $asm.puts "cvtsi2sd #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:double)}"
+ 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")
+ when "bdneq"
+ handleX86DoubleBranch("jne", :normal)
+ when "bdgt"
+ handleX86DoubleBranch("ja", :normal)
+ when "bdgteq"
+ handleX86DoubleBranch("jae", :normal)
+ when "bdlt"
+ handleX86DoubleBranch("ja", :reverse)
+ when "bdlteq"
+ handleX86DoubleBranch("jae", :reverse)
+ 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")
+ when "bdgtun"
+ handleX86DoubleBranch("jb", :reverse)
+ when "bdgtequn"
+ handleX86DoubleBranch("jbe", :reverse)
+ when "bdltun"
+ handleX86DoubleBranch("jb", :normal)
+ when "bdltequn"
+ handleX86DoubleBranch("jbe", :normal)
+ when "btd2i"
+ $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"
+ $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}"
+ when "movdz"
+ $asm.puts "xorpd #{operands[0].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
+ when "pop"
+ $asm.puts "pop #{operands[0].x86Operand(:int)}"
+ when "push"
+ $asm.puts "push #{operands[0].x86Operand(:int)}"
+ when "move", "sxi2p", "zxi2p"
+ if Immediate.new(nil, 0) == operands[0] and operands[1].is_a? RegisterID
+ $asm.puts "xorl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
+ elsif operands[0] != operands[1]
+ $asm.puts "movl #{x86Operands(:int, :int)}"
+ end
+ when "nop"
+ $asm.puts "nop"
+ when "bieq", "bpeq"
+ handleX86IntBranch("je", :int)
+ when "bineq", "bpneq"
+ handleX86IntBranch("jne", :int)
+ when "bia", "bpa"
+ handleX86IntBranch("ja", :int)
+ when "biaeq", "bpaeq"
+ handleX86IntBranch("jae", :int)
+ when "bib", "bpb"
+ handleX86IntBranch("jb", :int)
+ when "bibeq", "bpbeq"
+ handleX86IntBranch("jbe", :int)
+ when "bigt", "bpgt"
+ handleX86IntBranch("jg", :int)
+ when "bigteq", "bpgteq"
+ handleX86IntBranch("jge", :int)
+ when "bilt", "bplt"
+ handleX86IntBranch("jl", :int)
+ when "bilteq", "bplteq"
+ handleX86IntBranch("jle", :int)
+ when "bbeq"
+ handleX86IntBranch("je", :byte)
+ when "bbneq"
+ handleX86IntBranch("jne", :byte)
+ when "bba"
+ handleX86IntBranch("ja", :byte)
+ when "bbaeq"
+ handleX86IntBranch("jae", :byte)
+ when "bbb"
+ handleX86IntBranch("jb", :byte)
+ when "bbbeq"
+ handleX86IntBranch("jbe", :byte)
+ when "bbgt"
+ handleX86IntBranch("jg", :byte)
+ when "bbgteq"
+ handleX86IntBranch("jge", :byte)
+ when "bblt"
+ handleX86IntBranch("jl", :byte)
+ when "bblteq"
+ handleX86IntBranch("jlteq", :byte)
+ when "btio", "btpo"
+ handleX86BranchTest("jo", :int)
+ when "btis", "btps"
+ handleX86BranchTest("js", :int)
+ when "btiz", "btpz"
+ handleX86BranchTest("jz", :int)
+ when "btinz", "btpnz"
+ handleX86BranchTest("jnz", :int)
+ when "btbo"
+ handleX86BranchTest("jo", :byte)
+ when "btbs"
+ handleX86BranchTest("js", :byte)
+ when "btbz"
+ handleX86BranchTest("jz", :byte)
+ when "btbnz"
+ handleX86BranchTest("jnz", :byte)
+ when "jmp"
+ $asm.puts "jmp #{operands[0].x86CallOperand(:int)}"
+ when "baddio", "baddpo"
+ handleX86OpBranch("addl", "jo", :int)
+ when "baddis", "baddps"
+ handleX86OpBranch("addl", "js", :int)
+ when "baddiz", "baddpz"
+ handleX86OpBranch("addl", "jz", :int)
+ when "baddinz", "baddpnz"
+ handleX86OpBranch("addl", "jnz", :int)
+ when "bsubio"
+ handleX86SubBranch("jo", :int)
+ when "bsubis"
+ handleX86SubBranch("js", :int)
+ when "bsubiz"
+ handleX86SubBranch("jz", :int)
+ when "bsubinz"
+ handleX86SubBranch("jnz", :int)
+ when "bmulio"
+ handleX86OpBranch("imull", "jo", :int)
+ when "bmulis"
+ handleX86OpBranch("imull", "js", :int)
+ when "bmuliz"
+ handleX86OpBranch("imull", "jz", :int)
+ when "bmulinz"
+ handleX86OpBranch("imull", "jnz", :int)
+ when "borio"
+ handleX86OpBranch("orl", "jo", :int)
+ when "boris"
+ handleX86OpBranch("orl", "js", :int)
+ when "boriz"
+ handleX86OpBranch("orl", "jz", :int)
+ when "borinz"
+ handleX86OpBranch("orl", "jnz", :int)
+ when "break"
+ $asm.puts "int $3"
+ when "call"
+ $asm.puts "call #{operands[0].x86CallOperand(:int)}"
+ when "ret"
+ $asm.puts "ret"
+ when "cieq", "cpeq"
+ handleX86IntCompareSet("sete", :int)
+ when "cineq", "cpneq"
+ handleX86IntCompareSet("setne", :int)
+ when "cia", "cpa"
+ handleX86IntCompareSet("seta", :int)
+ when "ciaeq", "cpaeq"
+ handleX86IntCompareSet("setae", :int)
+ when "cib", "cpb"
+ handleX86IntCompareSet("setb", :int)
+ when "cibeq", "cpbeq"
+ handleX86IntCompareSet("setbe", :int)
+ when "cigt", "cpgt"
+ handleX86IntCompareSet("setg", :int)
+ when "cigteq", "cpgteq"
+ handleX86IntCompareSet("setge", :int)
+ when "cilt", "cplt"
+ handleX86IntCompareSet("setl", :int)
+ when "cilteq", "cplteq"
+ handleX86IntCompareSet("setle", :int)
+ when "tio"
+ handleX86SetTest("seto", :int)
+ when "tis"
+ handleX86SetTest("sets", :int)
+ when "tiz"
+ handleX86SetTest("setz", :int)
+ when "tinz"
+ handleX86SetTest("setnz", :int)
+ when "tbo"
+ handleX86SetTest("seto", :byte)
+ when "tbs"
+ handleX86SetTest("sets", :byte)
+ when "tbz"
+ handleX86SetTest("setz", :byte)
+ when "tbnz"
+ handleX86SetTest("setnz", :byte)
+ when "peek"
+ $asm.puts "movl #{operands[0].value * 4}(%esp), #{operands[1].x86Operand(:int)}"
+ when "poke"
+ $asm.puts "movl #{operands[0].x86Operand(:int)}, #{operands[1].value * 4}(%esp)"
+ when "cdqi"
+ $asm.puts "cdq"
+ when "idivi"
+ $asm.puts "idivl #{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)}"
+ 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 "bo"
+ $asm.puts "jo #{operands[0].asmLabel}"
+ when "bs"
+ $asm.puts "js #{operands[0].asmLabel}"
+ when "bz"
+ $asm.puts "jz #{operands[0].asmLabel}"
+ when "bnz"
+ $asm.puts "jnz #{operands[0].asmLabel}"
+ when "leai", "leap"
+ $asm.puts "leal #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
+ else
+ raise "Bad opcode: #{opcode}"
+ end
+ end
+end
+