# Copyright (C) 2011, 2012, 2014 Apple Inc. All rights reserved.
+# Copyright (C) 2014 University of Szeged. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# Actual lowering code follows.
#
+def arm64LowerMalformedLoadStoreAddresses(list)
+ newList = []
+
+ def isAddressMalformed(operand)
+ operand.is_a? Address and not (-255..4095).include? operand.offset.value
+ end
+
+ list.each {
+ | node |
+ if node.is_a? Instruction
+ if node.opcode =~ /^store/ and isAddressMalformed(node.operands[1])
+ address = node.operands[1]
+ tmp = Tmp.new(codeOrigin, :gpr)
+ newList << Instruction.new(node.codeOrigin, "move", [address.offset, tmp])
+ newList << Instruction.new(node.codeOrigin, node.opcode, [node.operands[0], BaseIndex.new(node.codeOrigin, address.base, tmp, 1, Immediate.new(codeOrigin, 0))], node.annotation)
+ elsif node.opcode =~ /^load/ and isAddressMalformed(node.operands[0])
+ address = node.operands[0]
+ tmp = Tmp.new(codeOrigin, :gpr)
+ newList << Instruction.new(node.codeOrigin, "move", [address.offset, tmp])
+ newList << Instruction.new(node.codeOrigin, node.opcode, [BaseIndex.new(node.codeOrigin, address.base, tmp, 1, Immediate.new(codeOrigin, 0)), node.operands[1]], node.annotation)
+ else
+ newList << node
+ end
+ else
+ newList << node
+ end
+ }
+ newList
+end
+
+# Workaround for Cortex-A53 erratum (835769)
+def arm64CortexA53Fix835769(list)
+ newList = []
+ lastOpcodeUnsafe = false
+
+ list.each {
+ | node |
+ if node.is_a? Instruction
+ case node.opcode
+ when /^store/, /^load/
+ # List all macro instructions that can be lowered to a load, store or prefetch ARM64 assembly instruction
+ lastOpcodeUnsafe = true
+ when "muli", "mulp", "mulq", "smulli"
+ # List all macro instructions that can be lowered to a 64-bit multiply-accumulate ARM64 assembly instruction
+ # (defined as one of MADD, MSUB, SMADDL, SMSUBL, UMADDL or UMSUBL).
+ if lastOpcodeUnsafe
+ newList << Instruction.new(node.codeOrigin, "nopCortexA53Fix835769", [])
+ end
+ lastOpcodeUnsafe = false
+ else
+ lastOpcodeUnsafe = false
+ end
+ end
+ newList << node
+ }
+ newList
+end
+
class Sequence
def getModifiedListARM64
result = @list
result = riscLowerSimpleBranchOps(result)
result = riscLowerHardBranchOps64(result)
result = riscLowerShiftOps(result)
+ result = arm64LowerMalformedLoadStoreAddresses(result)
result = riscLowerMalformedAddresses(result) {
| node, address |
case node.opcode
result = riscLowerTest(result)
result = assignRegistersToTemporaries(result, :gpr, ARM64_EXTRA_GPRS)
result = assignRegistersToTemporaries(result, :fpr, ARM64_EXTRA_FPRS)
+ result = arm64CortexA53Fix835769(result)
return result
end
end
[48, 32, 16, 0].each {
| shift |
currentValue = (value >> shift) & 0xffff
- next if currentValue == (isNegative ? 0xffff : 0) and shift != 0
+ next if currentValue == (isNegative ? 0xffff : 0) and (shift != 0 or !first)
if first
if isNegative
$asm.puts "movn #{target.arm64Operand(:ptr)}, \##{(~currentValue) & 0xffff}, lsl \##{shift}"
| ops |
$asm.puts "stp #{ops[0].arm64Operand(:ptr)}, #{ops[1].arm64Operand(:ptr)}, [sp, #-16]!"
}
- when "popLRAndFP"
- $asm.puts "ldp x29, x30, [sp], #16"
- when "pushLRAndFP"
- $asm.puts "stp x29, x30, [sp, #-16]!"
- when "popCalleeSaves"
- $asm.puts "ldp x28, x27, [sp], #16"
- $asm.puts "ldp x26, x25, [sp], #16"
- $asm.puts "ldp x24, x23, [sp], #16"
- $asm.puts "ldp x22, x21, [sp], #16"
- $asm.puts "ldp x20, x19, [sp], #16"
- when "pushCalleeSaves"
- $asm.puts "stp x20, x19, [sp, #-16]!"
- $asm.puts "stp x22, x21, [sp, #-16]!"
- $asm.puts "stp x24, x23, [sp, #-16]!"
- $asm.puts "stp x26, x25, [sp, #-16]!"
- $asm.puts "stp x28, x27, [sp, #-16]!"
when "move"
if operands[0].immediate?
emitARM64MoveImmediate(operands[0].value, operands[1])
when "memfence"
$asm.puts "dmb sy"
when "pcrtoaddr"
- $asm.puts "adr #{operands[1].arm64Operand(:ptr)}, #{operands[0].value}"
+ $asm.puts "adr #{operands[1].arm64Operand(:ptr)}, #{operands[0].value}"
+ when "nopCortexA53Fix835769"
+ $asm.putStr("#if CPU(ARM64_CORTEXA53)")
+ $asm.puts "nop"
+ $asm.putStr("#endif")
else
lowerDefault
end