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.rb276
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"