diff options
Diffstat (limited to 'Source/JavaScriptCore/offlineasm/x86.rb')
-rw-r--r-- | Source/JavaScriptCore/offlineasm/x86.rb | 276 |
1 files changed, 238 insertions, 38 deletions
diff --git a/Source/JavaScriptCore/offlineasm/x86.rb b/Source/JavaScriptCore/offlineasm/x86.rb index f78b43912..5e040ba76 100644 --- a/Source/JavaScriptCore/offlineasm/x86.rb +++ b/Source/JavaScriptCore/offlineasm/x86.rb @@ -1,4 +1,5 @@ # 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 @@ -34,6 +35,17 @@ def isX64 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/ @@ -255,6 +267,7 @@ end class FPRegisterID def x86Operand(kind) raise unless kind == :double + raise if useX87 case name when "ft0", "fa0", "fr" "%xmm0" @@ -272,6 +285,23 @@ class FPRegisterID 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 @@ -422,7 +452,7 @@ class Instruction when :quad isX64 ? "q" : raise when :double - "sd" + not useX87 ? "sd" : raise else raise end @@ -478,13 +508,17 @@ class Instruction 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 #{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 @@ -584,7 +618,7 @@ class Instruction 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] @@ -650,6 +684,38 @@ class Instruction 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 @@ -749,22 +815,82 @@ class Instruction $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 "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" - $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 "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" - $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}" + 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}" @@ -787,7 +913,11 @@ class Instruction when "bdequn" handleX86DoubleBranch("je", :normal) when "bdnequn" - $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}" + 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}" @@ -809,21 +939,47 @@ 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 "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" - $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)}" when "push" @@ -993,6 +1149,12 @@ class Instruction when "break" $asm.puts "int $3" when "call" + if useX87 + 2.times { + | offset | + $asm.puts "ffree %st(#{offset})" + } + end $asm.puts "call #{operands[0].x86CallOperand(:ptr)}" when "ret" $asm.puts "ret" @@ -1117,19 +1279,57 @@ class Instruction 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)}" + 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" - $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)}" + 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" - $asm.puts "movd #{operands[0].x86Operand(:quad)}, #{operands[1].x86Operand(:double)}" + 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" - $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:quad)}" + 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" |