summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/offlineasm/mips.rb
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/offlineasm/mips.rb')
-rw-r--r--Source/JavaScriptCore/offlineasm/mips.rb187
1 files changed, 141 insertions, 46 deletions
diff --git a/Source/JavaScriptCore/offlineasm/mips.rb b/Source/JavaScriptCore/offlineasm/mips.rb
index 08fd02662..53bb9c143 100644
--- a/Source/JavaScriptCore/offlineasm/mips.rb
+++ b/Source/JavaScriptCore/offlineasm/mips.rb
@@ -24,6 +24,43 @@
require 'risc'
+# GPR conventions, to match the baseline JIT
+#
+# $a0 => a0
+# $a1 => a1
+# $a2 => a2
+# $a3 => a3
+# $v0 => t0, r0
+# $v1 => t1, r1
+# $t0 => (scratch)
+# $t1 => (scratch)
+# $t2 => t2
+# $t3 => t3
+# $t4 => t4
+# $t5 => t5
+# $t6 => t6
+# $t7 => (scratch)
+# $t8 => (scratch)
+# $t9 => (stores the callee of a call opcode)
+# $gp => (globals)
+# $s4 => (callee-save used to preserve $gp across calls)
+# $ra => lr
+# $sp => sp
+# $fp => cfr
+#
+# FPR conventions, to match the baseline JIT
+# We don't have fa2 or fa3!
+# $f0 => ft0, fr
+# $f2 => ft1
+# $f4 => ft2
+# $f6 => ft3
+# $f8 => ft4
+# $f10 => ft5
+# $f12 => fa0
+# $f14 => fa1
+# $f16 => (scratch)
+# $f18 => (scratch)
+
class Assembler
def putStr(str)
@outp.puts str
@@ -57,8 +94,7 @@ class SpecialRegister < NoChildren
end
end
-MIPS_TEMP_GPRS = [SpecialRegister.new("$t5"), SpecialRegister.new("$t6"), SpecialRegister.new("$t7"),
- SpecialRegister.new("$t8")]
+MIPS_TEMP_GPRS = [SpecialRegister.new("$t0"), SpecialRegister.new("$t1"), SpecialRegister.new("$t7"), SpecialRegister.new("$t8")]
MIPS_ZERO_REG = SpecialRegister.new("$zero")
MIPS_GP_REG = SpecialRegister.new("$gp")
MIPS_GPSAVE_REG = SpecialRegister.new("$s4")
@@ -81,26 +117,24 @@ class RegisterID
"$a0"
when "a1"
"$a1"
- when "r0", "t0"
+ when "a2"
+ "$a2"
+ when "a3"
+ "$a3"
+ when "t0", "r0"
"$v0"
- when "r1", "t1"
+ when "t1", "r1"
"$v1"
when "t2"
"$t2"
when "t3"
- "$s3"
- when "t4" # PC reg in llint
- "$s2"
+ "$t3"
+ when "t4"
+ "$t4"
when "t5"
"$t5"
- when "t6"
- "$t6"
- when "t7"
- "$t7"
- when "t8"
- "$t8"
when "cfr"
- "$s0"
+ "$fp"
when "lr"
"$ra"
when "sp"
@@ -138,7 +172,7 @@ end
class Immediate
def mipsOperand
- raise "Invalid immediate #{value} at #{codeOriginString}" if value < -0x7fff or value > 0x7fff
+ raise "Invalid immediate #{value} at #{codeOriginString}" if value < -0x7fff or value > 0xffff
"#{value}"
end
end
@@ -371,46 +405,93 @@ end
#
class Node
- def mipsLowerMalformedAddressesRecurse(list, topLevelNode, &block)
+ def mipsLowerMalformedAddressesRecurse(list)
mapChildren {
| subNode |
- subNode.mipsLowerMalformedAddressesRecurse(list, topLevelNode, &block)
+ subNode.mipsLowerMalformedAddressesRecurse(list)
}
end
-end
-class Address
- def mipsLowerMalformedAddressesRecurse(list, node, &block)
- riscLowerMalformedAddressesRecurse(list, node, &block)
+ def mipsLowerShiftedAddressesRecurse(list, isFirst, tmp)
+ mapChildren {
+ | subNode |
+ subNode.mipsLowerShiftedAddressesRecurse(list, isFirst, tmp)
+ }
end
end
class BaseIndex
- def mipsLowerMalformedAddressesRecurse(list, node, &block)
+ def mipsLowerMalformedAddressesRecurse(list)
+ tmp = Tmp.new(codeOrigin, :gpr)
if scaleShift == 0
- tmp0 = Tmp.new(codeOrigin, :gpr)
- list << Instruction.new(codeOrigin, "addp", [base, index, tmp0])
- Address.new(codeOrigin, tmp0, Immediate.new(codeOrigin, offset.value));
- else
- tmp0 = Tmp.new(codeOrigin, :gpr)
- list << Instruction.new(codeOrigin, "lshifti", [index, Immediate.new(codeOrigin, scaleShift), tmp0]);
- list << Instruction.new(codeOrigin, "addp", [base, tmp0])
- Address.new(codeOrigin, tmp0, Immediate.new(codeOrigin, offset.value));
+ list << Instruction.new(codeOrigin, "addp", [base, index, tmp])
+ Address.new(codeOrigin, tmp, Immediate.new(codeOrigin, offset.value));
end
end
-end
-class AbsoluteAddress
- def mipsLowerMalformedAddressesRecurse(list, node, &block)
- riscLowerMalformedAddressesRecurse(list, node, &block)
+ def mipsLowerShiftedAddressesRecurse(list, isFirst, tmp)
+ if isFirst
+ list << Instruction.new(codeOrigin, "lshifti", [index, Immediate.new(codeOrigin, scaleShift), tmp]);
+ list << Instruction.new(codeOrigin, "addp", [base, tmp])
+ end
+ Address.new(codeOrigin, tmp, Immediate.new(codeOrigin, offset.value));
end
end
-def mipsLowerMalformedAddresses(list, &block)
- newList = []
- list.each {
- | node |
- newList << node.mipsLowerMalformedAddressesRecurse(newList, node, &block)
+#
+# Lowering of BaseIndex addresses with optimization for MIPS.
+#
+# offline asm instruction pair:
+# loadi 4[cfr, t0, 8], t2
+# loadi 0[cfr, t0, 8], t0
+#
+# lowered instructions:
+# lshifti t0, 3, tmp
+# addp cfr, tmp
+# loadi 4[tmp], t2
+# loadi 0[tmp], t0
+#
+
+def mipsHasShiftedBaseIndexAddress(instruction)
+ instruction.operands.each_with_index {
+ | operand, index |
+ if operand.is_a? BaseIndex and operand.scaleShift != 0
+ return index
+ end
+ }
+ -1
+end
+
+def mipsScaleOfBaseIndexMatches(baseIndex0, baseIndex1)
+ baseIndex0.base == baseIndex1.base and
+ baseIndex0.index == baseIndex1.index and
+ baseIndex0.scale == baseIndex1.scale
+end
+
+def mipsLowerBaseIndexAddresses(list)
+ newList = [ list[0] ]
+ tmp = nil
+ list.each_cons(2) {
+ | nodes |
+ if nodes[1].is_a? Instruction
+ ind = mipsHasShiftedBaseIndexAddress(nodes[1])
+ if ind != -1
+ if nodes[0].is_a? Instruction and
+ nodes[0].opcode == nodes[1].opcode and
+ ind == mipsHasShiftedBaseIndexAddress(nodes[0]) and
+ mipsScaleOfBaseIndexMatches(nodes[0].operands[ind], nodes[1].operands[ind])
+
+ newList << nodes[1].mipsLowerShiftedAddressesRecurse(newList, false, tmp)
+ else
+ tmp = Tmp.new(codeOrigin, :gpr)
+ newList << nodes[1].mipsLowerShiftedAddressesRecurse(newList, true, tmp)
+ end
+ else
+ newList << nodes[1].mipsLowerMalformedAddressesRecurse(newList)
+ end
+ else
+ newList << nodes[1]
+ end
}
newList
end
@@ -442,6 +523,10 @@ def mipsLowerMisplacedImmediates(list)
else
newList << node
end
+ when /^(addi|subi)/
+ newList << node.riscLowerMalformedImmediatesRecurse(newList, -0x7fff..0x7fff)
+ when "andi", "andp", "ori", "orp", "xori", "xorp"
+ newList << node.riscLowerMalformedImmediatesRecurse(newList, 0..0xffff)
else
newList << node
end
@@ -624,7 +709,8 @@ class Sequence
result = riscLowerSimpleBranchOps(result)
result = riscLowerHardBranchOps(result)
result = riscLowerShiftOps(result)
- result = mipsLowerMalformedAddresses(result) {
+ result = mipsLowerBaseIndexAddresses(result)
+ result = riscLowerMalformedAddresses(result) {
| node, address |
if address.is_a? Address
(-0xffff..0xffff).include? address.offset.value
@@ -864,11 +950,17 @@ class Instruction
# FIXME: either support this or remove it.
raise "MIPS does not support this opcode yet, #{codeOrigin}"
when "pop"
- $asm.puts "lw #{operands[0].mipsOperand}, 0($sp)"
- $asm.puts "addiu $sp, $sp, 4"
+ operands.each {
+ | op |
+ $asm.puts "lw #{op.mipsOperand}, 0($sp)"
+ $asm.puts "addiu $sp, $sp, 4"
+ }
when "push"
- $asm.puts "addiu $sp, $sp, -4"
- $asm.puts "sw #{operands[0].mipsOperand}, 0($sp)"
+ operands.each {
+ | op |
+ $asm.puts "addiu $sp, $sp, -4"
+ $asm.puts "sw #{op.mipsOperand}, 0($sp)"
+ }
when "move", "sxi2p", "zxi2p"
if operands[0].is_a? Immediate
mipsMoveImmediate(operands[0].value, operands[1])
@@ -946,15 +1038,18 @@ class Instruction
$asm.puts "movz #{operands[0].mipsOperand}, #{operands[1].mipsOperand}, #{operands[2].mipsOperand}"
when "movn"
$asm.puts "movn #{operands[0].mipsOperand}, #{operands[1].mipsOperand}, #{operands[2].mipsOperand}"
+ when "setcallreg"
+ $asm.puts "move #{MIPS_CALL_REG.mipsOperand}, #{operands[0].mipsOperand}"
when "slt", "sltb"
$asm.puts "slt #{operands[0].mipsOperand}, #{operands[1].mipsOperand}, #{operands[2].mipsOperand}"
when "sltu", "sltub"
$asm.puts "sltu #{operands[0].mipsOperand}, #{operands[1].mipsOperand}, #{operands[2].mipsOperand}"
when "pichdr"
$asm.putStr("OFFLINE_ASM_CPLOAD(#{MIPS_CALL_REG.mipsOperand})")
- $asm.puts "move #{MIPS_GPSAVE_REG.mipsOperand}, #{MIPS_GP_REG.mipsOperand}"
+ when "memfence"
+ $asm.puts "sync"
else
- raise "Unhandled opcode #{opcode} at #{codeOriginString}"
+ lowerDefault
end
end
end