12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352 |
- # Copyright (C) 2012 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
- # 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.
- require "config"
- def isX64
- case $activeBackend
- when "X86"
- false
- when "X86_64"
- true
- else
- raise "bad value for $activeBackend: #{$activeBackend}"
- end
- end
- def useX87
- case $activeBackend
- when "X86"
- true
- when "X86_64"
- false
- else
- raise "bad value for $activeBackend: #{$activeBackend}"
- end
- end
- class SpecialRegister < NoChildren
- def x86Operand(kind)
- raise unless @name =~ /^r/
- raise unless isX64
- case kind
- when :half
- "%" + @name + "w"
- when :int
- "%" + @name + "d"
- when :ptr
- "%" + @name
- when :quad
- "%" + @name
- else
- raise
- end
- end
- def x86CallOperand(kind)
- # Call operands are not allowed to be partial registers.
- "*#{x86Operand(:quad)}"
- end
- end
- X64_SCRATCH_REGISTER = SpecialRegister.new("r11")
- class RegisterID
- def supports8BitOnX86
- case name
- when "t0", "a0", "r0", "t1", "a1", "r1", "t2", "t3"
- true
- when "cfr", "ttnr", "tmr"
- false
- when "t4", "t5"
- isX64
- else
- raise
- end
- end
-
- def x86Operand(kind)
- case name
- when "t0", "a0", "r0"
- case kind
- when :byte
- "%al"
- when :half
- "%ax"
- when :int
- "%eax"
- when :ptr
- isX64 ? "%rax" : "%eax"
- when :quad
- isX64 ? "%rax" : raise
- else
- raise
- end
- when "t1", "a1", "r1"
- case kind
- when :byte
- "%dl"
- when :half
- "%dx"
- when :int
- "%edx"
- when :ptr
- isX64 ? "%rdx" : "%edx"
- when :quad
- isX64 ? "%rdx" : raise
- else
- raise
- end
- when "t2"
- case kind
- when :byte
- "%cl"
- when :half
- "%cx"
- when :int
- "%ecx"
- when :ptr
- isX64 ? "%rcx" : "%ecx"
- when :quad
- isX64 ? "%rcx" : raise
- else
- raise
- end
- when "t3"
- case kind
- when :byte
- "%bl"
- when :half
- "%bx"
- when :int
- "%ebx"
- when :ptr
- isX64 ? "%rbx" : "%ebx"
- when :quad
- isX64 ? "%rbx" : raise
- else
- raise
- end
- when "t4"
- case kind
- when :byte
- "%sil"
- when :half
- "%si"
- when :int
- "%esi"
- when :ptr
- isX64 ? "%rsi" : "%esi"
- when :quad
- isX64 ? "%rsi" : raise
- else
- raise
- end
- when "cfr"
- if isX64
- case kind
- when :half
- "%r13w"
- when :int
- "%r13d"
- when :ptr
- "%r13"
- when :quad
- "%r13"
- else
- raise
- end
- else
- case kind
- when :byte
- "%dil"
- when :half
- "%di"
- when :int
- "%edi"
- when :ptr
- "%edi"
- else
- raise
- end
- end
- when "sp"
- case kind
- when :byte
- "%spl"
- when :half
- "%sp"
- when :int
- "%esp"
- when :ptr
- isX64 ? "%rsp" : "%esp"
- when :quad
- isX64 ? "%rsp" : raise
- else
- raise
- end
- when "t5"
- raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
- case kind
- when :byte
- "%dil"
- when :half
- "%di"
- when :int
- "%edi"
- when :ptr
- "%rdi"
- when :quad
- "%rdi"
- end
- when "t6"
- raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
- case kind
- when :half
- "%r10w"
- when :int
- "%r10d"
- when :ptr
- "%r10"
- when :quad
- "%r10"
- end
- when "csr1"
- raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
- case kind
- when :half
- "%r14w"
- when :int
- "%r14d"
- when :ptr
- "%r14"
- when :quad
- "%r14"
- end
- when "csr2"
- raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
- case kind
- when :half
- "%r15w"
- when :int
- "%r15d"
- when :ptr
- "%r15"
- when :quad
- "%r15"
- end
- else
- raise "Bad register #{name} for X86 at #{codeOriginString}"
- end
- end
- def x86CallOperand(kind)
- isX64 ? "*#{x86Operand(:quad)}" : "*#{x86Operand(:ptr)}"
- end
- end
- class FPRegisterID
- def x86Operand(kind)
- raise unless kind == :double
- raise if useX87
- 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 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
- "%st(#{x87DefaultStackPosition + offset})"
- end
- def x86CallOperand(kind)
- "*#{x86Operand(kind)}"
- end
- end
- class Immediate
- def validX86Immediate?
- if isX64
- value >= -0x80000000 and value <= 0x7fffffff
- else
- true
- end
- end
- def x86Operand(kind)
- "$#{value}"
- end
- def x86CallOperand(kind)
- "#{value}"
- end
- end
- class Address
- def supports8BitOnX86
- true
- end
-
- def x86AddressOperand(addressKind)
- "#{offset.value}(#{base.x86Operand(addressKind)})"
- end
- def x86Operand(kind)
- x86AddressOperand(:ptr)
- end
- def x86CallOperand(kind)
- "*#{x86Operand(kind)}"
- end
- end
- class BaseIndex
- def supports8BitOnX86
- true
- end
-
- def x86AddressOperand(addressKind)
- "#{offset.value}(#{base.x86Operand(addressKind)}, #{index.x86Operand(addressKind)}, #{scale})"
- end
-
- def x86Operand(kind)
- x86AddressOperand(:ptr)
- end
- def x86CallOperand(kind)
- "*#{x86Operand(kind)}"
- end
- end
- class AbsoluteAddress
- def supports8BitOnX86
- true
- end
-
- def x86AddressOperand(addressKind)
- "#{address.value}"
- 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 Sequence
- def getModifiedListX86_64
- newList = []
-
- @list.each {
- | node |
- newNode = node
- if node.is_a? Instruction
- unless node.opcode == "move"
- usedScratch = false
- newOperands = node.operands.map {
- | operand |
- if operand.immediate? and not operand.validX86Immediate?
- if usedScratch
- raise "Attempt to use scratch register twice at #{operand.codeOriginString}"
- end
- newList << Instruction.new(operand.codeOrigin, "move", [operand, X64_SCRATCH_REGISTER])
- usedScratch = true
- X64_SCRATCH_REGISTER
- else
- operand
- end
- }
- newNode = Instruction.new(node.codeOrigin, node.opcode, newOperands, node.annotation)
- end
- else
- unless node.is_a? Label or
- node.is_a? LocalLabel or
- node.is_a? Skip
- raise "Unexpected #{node.inspect} at #{node.codeOrigin}"
- end
- end
- if newNode
- newList << newNode
- end
- }
-
- return newList
- 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 :ptr
- isX64 ? "q" : "l"
- when :quad
- isX64 ? "q" : raise
- when :double
- not useX87 ? "sd" : raise
- else
- raise
- end
- end
-
- def x86Bytes(kind)
- case kind
- when :byte
- 1
- when :half
- 2
- when :int
- 4
- when :ptr
- isX64 ? 8 : 4
- when :quad
- isX64 ? 8 : raise
- when :double
- 8
- 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
- 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 "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}"
- end
- end
-
- def handleX86DoubleBranch(branchOpcode, mode)
- if useX87
- handleX87Compare(mode)
- else
- 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
- 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
- ax = RegisterID.new(nil, "t0")
- $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}"
- $asm.puts "#{setOpcode} %al"
- $asm.puts "movzbl %al, %eax"
- $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}"
- 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 "neg#{x86Suffix(kind)} #{operands[2].x86Operand(kind)}"
- $asm.puts "add#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
- 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 handleX86Add(kind)
- if operands.size == 3 and operands[1] == operands[2]
- unless Immediate.new(nil, 0) == operands[0]
- $asm.puts "add#{x86Suffix(kind)} #{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)}"
- end
- else
- $asm.puts "lea#{x86Suffix(kind)} #{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
- if operands[0] == operands[2]
- $asm.puts "add#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
- else
- $asm.puts "lea#{x86Suffix(kind)} (#{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}"
- end
- else
- unless Immediate.new(nil, 0) == operands[0]
- $asm.puts "add#{x86Suffix(kind)} #{x86Operands(kind, kind)}"
- end
- end
- end
-
- 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)}"
- else
- handleX86Op("sub#{x86Suffix(kind)}", kind)
- end
- end
-
- def handleX86Mul(kind)
- if operands.size == 3 and operands[0].is_a? Immediate
- $asm.puts "imul#{x86Suffix(kind)} #{x86Operands(kind, kind, kind)}"
- else
- # FIXME: could do some peephole in case the left operand is immediate and it's
- # a power of two.
- handleX86Op("imul#{x86Suffix(kind)}", kind)
- end
- end
-
- def handleMove
- if Immediate.new(nil, 0) == operands[0] and operands[1].is_a? RegisterID
- 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]
- 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 #{operands[1].x87Operand(0)}"
- else
- $asm.puts "fld #{operands[0].x87Operand(0)}"
- $asm.puts "fucomip #{operands[1].x87Operand(1)}"
- end
- when :reverse
- if (operands[1].x87DefaultStackPosition == 0)
- $asm.puts "fucomi #{operands[0].x87Operand(0)}"
- else
- $asm.puts "fld #{operands[1].x87Operand(0)}"
- $asm.puts "fucomip #{operands[0].x87Operand(1)}"
- end
- else
- raise mode.inspect
- end
- end
- def handleX87BinOp(opcode, opcodereverse)
- if (operands[1].x87DefaultStackPosition == 0)
- $asm.puts "#{opcode} #{operands[0].x87Operand(0)}, %st"
- elsif (operands[0].x87DefaultStackPosition == 0)
- $asm.puts "#{opcodereverse} %st, #{operands[1].x87Operand(0)}"
- else
- $asm.puts "fld #{operands[0].x87Operand(0)}"
- $asm.puts "#{opcodereverse}p %st, #{operands[1].x87Operand(1)}"
- end
- end
- def lowerX86
- raise unless $activeBackend == "X86"
- lowerX86Common
- end
-
- def lowerX86_64
- raise unless $activeBackend == "X86_64"
- lowerX86Common
- end
-
- def lowerX86Common
- $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)
- when "andp"
- handleX86Op("and#{x86Suffix(:ptr)}", :ptr)
- when "andq"
- handleX86Op("and#{x86Suffix(:quad)}", :quad)
- when "lshifti"
- handleX86Shift("sall", :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)}"
- 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)}"
- when "ori"
- handleX86Op("orl", :int)
- when "orp"
- handleX86Op("or#{x86Suffix(:ptr)}", :ptr)
- when "orq"
- handleX86Op("or#{x86Suffix(:quad)}", :quad)
- when "rshifti"
- handleX86Shift("sarl", :int)
- when "rshiftp"
- handleX86Shift("sar#{x86Suffix(:ptr)}", :ptr)
- when "rshiftq"
- handleX86Shift("sar#{x86Suffix(:quad)}", :quad)
- when "urshifti"
- handleX86Shift("shrl", :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)
- when "xorp"
- handleX86Op("xor#{x86Suffix(:ptr)}", :ptr)
- when "xorq"
- handleX86Op("xor#{x86Suffix(:quad)}", :quad)
- when "loadi", "storei"
- $asm.puts "movl #{x86Operands(:int, :int)}"
- when "loadis"
- if isX64
- $asm.puts "movslq #{x86Operands(:int, :quad)}"
- else
- $asm.puts "movl #{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)}"
- 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"
- if useX87
- $asm.puts "fldl #{operands[0].x86Operand(:double)}"
- $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 "fstl #{operands[1].x86Operand(:double)}"
- else
- $asm.puts "fld #{operands[0].x87Operand(0)}"
- $asm.puts "fstpl #{operands[1].x86Operand(:double)}"
- end
- else
- $asm.puts "movsd #{x86Operands(:double, :double)}"
- end
- when "addd"
- if useX87
- handleX87BinOp("fadd", "fadd")
- else
- $asm.puts "addsd #{x86Operands(:double, :double)}"
- end
- when "muld"
- 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"
- 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"
- if useX87
- sp = RegisterID.new(nil, "sp")
- $asm.puts "movl #{operands[0].x86Operand(:int)}, -4(#{sp.x86Operand(:ptr)})"
- $asm.puts "fildl -4(#{sp.x86Operand(:ptr)})"
- $asm.puts "fstp #{operands[1].x87Operand(1)}"
- else
- $asm.puts "cvtsi2sd #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:double)}"
- end
- when "bdeq"
- if useX87
- handleX87Compare(:normal)
- else
- $asm.puts "ucomisd #{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"
- 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"
- if useX87
- handleX87Compare(:normal)
- else
- $asm.puts "ucomisd #{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"
- handleX86DoubleBranch("jbe", :reverse)
- when "bdltun"
- handleX86DoubleBranch("jb", :normal)
- 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"
- 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 "fistpl -4(#{sp.x86Operand(:ptr)})"
- end
- $asm.puts "movl -4(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:int)}"
- $asm.puts "testl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
- $asm.puts "je #{operands[2].asmLabel}"
- $asm.puts "fildl -4(#{sp.x86Operand(:ptr)})"
- $asm.puts "fucomip #{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 "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}"
- end
- when "movdz"
- 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)}"
- when "push"
- $asm.puts "push #{operands[0].x86Operand(:ptr)}"
- when "move"
- handleMove
- when "sxi2q"
- $asm.puts "movslq #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:quad)}"
- when "zxi2q"
- $asm.puts "movl #{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"
- 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 "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 "btqnz"
- handleX86BranchTest("jnz", :quad)
- when "btbs"
- handleX86BranchTest("js", :byte)
- when "btbz"
- handleX86BranchTest("jz", :byte)
- when "btbnz"
- handleX86BranchTest("jnz", :byte)
- when "jmp"
- $asm.puts "jmp #{operands[0].x86CallOperand(:ptr)}"
- when "baddio"
- handleX86OpBranch("addl", "jo", :int)
- when "baddpo"
- handleX86OpBranch("add#{x86Suffix(:ptr)}", "jo", :ptr)
- when "baddqo"
- handleX86OpBranch("add#{x86Suffix(:quad)}", "jo", :quad)
- when "baddis"
- handleX86OpBranch("addl", "js", :int)
- when "baddps"
- handleX86OpBranch("add#{x86Suffix(:ptr)}", "js", :ptr)
- when "baddqs"
- handleX86OpBranch("add#{x86Suffix(:quad)}", "js", :quad)
- when "baddiz"
- handleX86OpBranch("addl", "jz", :int)
- when "baddpz"
- handleX86OpBranch("add#{x86Suffix(:ptr)}", "jz", :ptr)
- when "baddqz"
- handleX86OpBranch("add#{x86Suffix(:quad)}", "jz", :quad)
- when "baddinz"
- handleX86OpBranch("addl", "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"
- 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(:ptr)}"
- when "ret"
- $asm.puts "ret"
- when "cieq"
- handleX86IntCompareSet("sete", :int)
- when "cbeq"
- 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 "cqlteq"
- handleX86IntCompareSet("setle", :quad)
- when "tis"
- handleX86SetTest("sets", :int)
- when "tiz"
- handleX86SetTest("setz", :int)
- when "tinz"
- handleX86SetTest("setnz", :int)
- when "tps"
- handleX86SetTest("sets", :ptr)
- when "tpz"
- handleX86SetTest("setz", :ptr)
- when "tpnz"
- handleX86SetTest("setnz", :ptr)
- when "tqs"
- handleX86SetTest("sets", :quad)
- when "tqz"
- handleX86SetTest("setz", :quad)
- when "tqnz"
- handleX86SetTest("setnz", :quad)
- when "tbs"
- handleX86SetTest("sets", :byte)
- when "tbz"
- handleX86SetTest("setz", :byte)
- 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)}"
- when "peekq"
- sp = RegisterID.new(nil, "sp")
- $asm.puts "mov#{x86Suffix(:quad)} #{operands[0].value * x86Bytes(:quad)}(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:quad)}"
- when "poke"
- sp = RegisterID.new(nil, "sp")
- $asm.puts "mov#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{operands[1].value * x86Bytes(:ptr)}(#{sp.x86Operand(:ptr)})"
- when "pokeq"
- sp = RegisterID.new(nil, "sp")
- $asm.puts "mov#{x86Suffix(:quad)} #{operands[0].x86Operand(:quad)}, #{operands[1].value * x86Bytes(:quad)}(#{sp.x86Operand(:ptr)})"
- when "cdqi"
- $asm.puts "cdq"
- when "idivi"
- $asm.puts "idivl #{operands[0].x86Operand(:int)}"
- when "fii2d"
- if useX87
- sp = RegisterID.new(nil, "sp")
- $asm.puts "movl #{operands[0].x86Operand(:int)}, -8(#{sp.x86Operand(:ptr)})"
- $asm.puts "movl #{operands[1].x86Operand(:int)}, -4(#{sp.x86Operand(:ptr)})"
- $asm.puts "fldl -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"
- if useX87
- sp = RegisterID.new(nil, "sp")
- if (operands[0].x87DefaultStackPosition == 0)
- $asm.puts "fstl -8(#{sp.x86Operand(:ptr)})"
- else
- $asm.puts "fld #{operands[0].x87Operand(0)}"
- $asm.puts "fstpl -8(#{sp.x86Operand(:ptr)})"
- end
- $asm.puts "movl -8(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:int)}"
- $asm.puts "movl -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
- $asm.puts "movq #{operands[0].x86Operand(:quad)}, #{operands[1].x86Operand(:double)}"
- end
- when "fd2q"
- if useX87
- sp = RegisterID.new(nil, "sp")
- if (operands[0].x87DefaultStackPosition == 0)
- $asm.puts "fstl -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
- $asm.puts "movq #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:quad)}"
- end
- 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"
- $asm.puts "leal #{operands[0].x86AddressOperand(:int)}, #{operands[1].x86Operand(:int)}"
- when "leap"
- $asm.puts "lea#{x86Suffix(:ptr)} #{operands[0].x86AddressOperand(:ptr)}, #{operands[1].x86Operand(:ptr)}"
- when "resetX87Stack"
- if useX87
- 2.times {
- | offset |
- $asm.puts "ffree %st(#{offset})"
- }
- end
- else
- lowerDefault
- end
- end
- end
|