summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/offlineasm
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-03-12 14:11:15 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-03-12 14:11:15 +0100
commitdd91e772430dc294e3bf478c119ef8d43c0a3358 (patch)
tree6f33ce4d5872a5691e0291eb45bf6ab373a5f567 /Source/JavaScriptCore/offlineasm
parentad0d549d4cc13433f77c1ac8f0ab379c83d93f28 (diff)
downloadqtwebkit-dd91e772430dc294e3bf478c119ef8d43c0a3358.tar.gz
Imported WebKit commit 3db4eb1820ac8fb03065d7ea73a4d9db1e8fea1a (http://svn.webkit.org/repository/webkit/trunk@110422)
This includes build fixes for the latest qtbase/qtdeclarative as well as the final QML2 API.
Diffstat (limited to 'Source/JavaScriptCore/offlineasm')
-rw-r--r--Source/JavaScriptCore/offlineasm/armv7.rb50
-rw-r--r--Source/JavaScriptCore/offlineasm/asm.rb13
-rw-r--r--Source/JavaScriptCore/offlineasm/ast.rb187
-rw-r--r--Source/JavaScriptCore/offlineasm/backends.rb18
-rw-r--r--Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb5
-rw-r--r--Source/JavaScriptCore/offlineasm/instructions.rb8
-rw-r--r--Source/JavaScriptCore/offlineasm/offsets.rb12
-rw-r--r--Source/JavaScriptCore/offlineasm/parser.rb102
-rw-r--r--Source/JavaScriptCore/offlineasm/registers.rb8
-rw-r--r--Source/JavaScriptCore/offlineasm/self_hash.rb29
-rw-r--r--Source/JavaScriptCore/offlineasm/settings.rb2
-rw-r--r--Source/JavaScriptCore/offlineasm/transform.rb132
-rw-r--r--Source/JavaScriptCore/offlineasm/x86.rb510
13 files changed, 900 insertions, 176 deletions
diff --git a/Source/JavaScriptCore/offlineasm/armv7.rb b/Source/JavaScriptCore/offlineasm/armv7.rb
index eb8df6869..ed7db5618 100644
--- a/Source/JavaScriptCore/offlineasm/armv7.rb
+++ b/Source/JavaScriptCore/offlineasm/armv7.rb
@@ -33,29 +33,9 @@ class Node
end
class SpecialRegister < NoChildren
- def initialize(name)
- @name = name
- end
-
def armV7Operand
@name
end
-
- def address?
- false
- end
-
- def label?
- false
- end
-
- def immediate?
- false
- end
-
- def register?
- true
- end
end
ARMv7_EXTRA_GPRS = [SpecialRegister.new("r9"), SpecialRegister.new("r8"), SpecialRegister.new("r3")]
@@ -228,7 +208,7 @@ def armV7LowerShiftOps(list)
| node |
if node.is_a? Instruction
case node.opcode
- when "lshifti", "rshifti", "urshifti"
+ when "lshifti", "rshifti", "urshifti", "lshiftp", "rshiftp", "urshiftp"
if node.operands.size == 2
newList << Instruction.new(node.codeOrigin, node.opcode, [armV7SanitizeShift(node.operands[0], newList), node.operands[1]])
else
@@ -469,7 +449,7 @@ def armV7LowerMalformedImmediates(list)
else
newList << node.armV7LowerMalformedImmediatesRecurse(newList)
end
- when "muli"
+ when "muli", "mulp"
if node.operands[0].is_a? Immediate
tmp = Tmp.new(codeOrigin, :gpr)
newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp])
@@ -535,9 +515,9 @@ def armV7LowerMisplacedAddresses(list)
if node.is_a? Instruction
postInstructions = []
case node.opcode
- when "addi", "addp", "addis", "andi", "andp", "lshifti", "muli", "negi", "noti", "ori", "oris",
- "orp", "rshifti", "urshifti", "subi", "subp", "subis", "xori", "xorp", /^bi/, /^bp/, /^bti/,
- /^btp/, /^ci/, /^cp/, /^ti/
+ when "addi", "addp", "addis", "andi", "andp", "lshifti", "lshiftp", "muli", "mulp", "negi",
+ "negp", "noti", "ori", "oris", "orp", "rshifti", "urshifti", "rshiftp", "urshiftp", "subi",
+ "subp", "subis", "xori", "xorp", /^bi/, /^bp/, /^bti/, /^btp/, /^ci/, /^cp/, /^ti/
newList << Instruction.new(node.codeOrigin,
node.opcode,
armV7AsRegisters(newList, postInstructions, node.operands, "i"))
@@ -649,7 +629,7 @@ end
#
class Sequence
- def lowerARMv7
+ def getModifiedListARMv7
myList = @list
# Verify that we will only see instructions and labels.
@@ -673,10 +653,8 @@ class Sequence
myList = armV7LowerRegisterReuse(myList)
myList = assignRegistersToTemporaries(myList, :gpr, ARMv7_EXTRA_GPRS)
myList = assignRegistersToTemporaries(myList, :fpr, ARMv7_EXTRA_FPRS)
- myList.each {
- | node |
- node.lower("ARMv7")
- }
+
+ return myList
end
end
@@ -792,13 +770,13 @@ class Instruction
emitArmV7Compact("orrs", "orrs", operands)
when "xori", "xorp"
emitArmV7Compact("eors", "eor", operands)
- when "lshifti"
+ when "lshifti", "lshiftp"
emitArmV7Compact("lsls", "lsls", operands)
- when "rshifti"
+ when "rshifti", "rshiftp"
emitArmV7Compact("asrs", "asrs", operands)
- when "urshifti"
+ when "urshifti", "urshiftp"
emitArmV7Compact("lsrs", "lsrs", operands)
- when "muli"
+ when "muli", "mulp"
if operands.size == 2 or operands[0] == operands[2] or operands[1] == operands[2]
emitArmV7("muls", operands)
else
@@ -807,11 +785,11 @@ class Instruction
end
when "subi", "subp", "subis"
emitArmV7Compact("subs", "subs", operands)
- when "negi"
+ when "negi", "negp"
$asm.puts "rsbs #{operands[0].armV7Operand}, #{operands[0].armV7Operand}, \#0"
when "noti"
$asm.puts "mvns #{operands[0].armV7Operand}, #{operands[0].armV7Operand}"
- when "loadi", "loadp"
+ when "loadi", "loadis", "loadp"
$asm.puts "ldr #{armV7FlippedOperands(operands)}"
when "storei", "storep"
$asm.puts "str #{armV7Operands(operands)}"
diff --git a/Source/JavaScriptCore/offlineasm/asm.rb b/Source/JavaScriptCore/offlineasm/asm.rb
index a93a8c5dd..12bade022 100644
--- a/Source/JavaScriptCore/offlineasm/asm.rb
+++ b/Source/JavaScriptCore/offlineasm/asm.rb
@@ -128,11 +128,15 @@ outputFlnm = ARGV.shift
$stderr.puts "offlineasm: Parsing #{asmFile} and #{offsetsFile} and creating assembly file #{outputFlnm}."
-configurationList = offsetsAndConfigurationIndex(offsetsFile)
-inputData = IO::read(asmFile)
+begin
+ configurationList = offsetsAndConfigurationIndex(offsetsFile)
+rescue MissingMagicValuesException
+ $stderr.puts "offlineasm: No magic values found. Skipping assembly file generation assuming the classic interpreter is enabled."
+ exit 0
+end
inputHash =
- "// offlineasm input hash: " + Digest::SHA1.hexdigest(inputData) +
+ "// offlineasm input hash: " + parseHash(asmFile) +
" " + Digest::SHA1.hexdigest(configurationList.map{|v| (v[0] + [v[1]]).join(' ')}.join(' ')) +
" " + selfHash
@@ -154,7 +158,7 @@ File.open(outputFlnm, "w") {
$asm = Assembler.new($output)
- ast = parse(lex(inputData))
+ ast = parse(asmFile)
configurationList.each {
| configuration |
@@ -163,6 +167,7 @@ File.open(outputFlnm, "w") {
forSettings(computeSettingsCombinations(ast)[configIndex], ast) {
| concreteSettings, lowLevelAST, backend |
lowLevelAST = lowLevelAST.resolve(*buildOffsetsMap(lowLevelAST, offsetsList))
+ lowLevelAST.validate
emitCodeInConfiguration(concreteSettings, lowLevelAST, backend) {
$asm.inAsm {
lowLevelAST.lower(backend)
diff --git a/Source/JavaScriptCore/offlineasm/ast.rb b/Source/JavaScriptCore/offlineasm/ast.rb
index f67b0fc60..e555b5d98 100644
--- a/Source/JavaScriptCore/offlineasm/ast.rb
+++ b/Source/JavaScriptCore/offlineasm/ast.rb
@@ -57,7 +57,7 @@ class Node
end
def codeOriginString
- "line number #{@codeOrigin}"
+ @codeOrigin.to_s
end
def descendants
@@ -383,6 +383,157 @@ class NegImmediate < Node
end
end
+class OrImmediates < Node
+ attr_reader :left, :right
+
+ def initialize(codeOrigin, left, right)
+ super(codeOrigin)
+ @left = left
+ @right = right
+ end
+
+ def children
+ [@left, @right]
+ end
+
+ def mapChildren
+ OrImmediates.new(codeOrigin, (yield @left), (yield @right))
+ end
+
+ def dump
+ "(#{left.dump} | #{right.dump})"
+ end
+
+ def address?
+ false
+ end
+
+ def label?
+ false
+ end
+
+ def immediate?
+ true
+ end
+
+ def register?
+ false
+ end
+end
+
+class AndImmediates < Node
+ attr_reader :left, :right
+
+ def initialize(codeOrigin, left, right)
+ super(codeOrigin)
+ @left = left
+ @right = right
+ end
+
+ def children
+ [@left, @right]
+ end
+
+ def mapChildren
+ AndImmediates.new(codeOrigin, (yield @left), (yield @right))
+ end
+
+ def dump
+ "(#{left.dump} & #{right.dump})"
+ end
+
+ def address?
+ false
+ end
+
+ def label?
+ false
+ end
+
+ def immediate?
+ true
+ end
+
+ def register?
+ false
+ end
+end
+
+class XorImmediates < Node
+ attr_reader :left, :right
+
+ def initialize(codeOrigin, left, right)
+ super(codeOrigin)
+ @left = left
+ @right = right
+ end
+
+ def children
+ [@left, @right]
+ end
+
+ def mapChildren
+ XorImmediates.new(codeOrigin, (yield @left), (yield @right))
+ end
+
+ def dump
+ "(#{left.dump} ^ #{right.dump})"
+ end
+
+ def address?
+ false
+ end
+
+ def label?
+ false
+ end
+
+ def immediate?
+ true
+ end
+
+ def register?
+ false
+ end
+end
+
+class BitnotImmediate < Node
+ attr_reader :child
+
+ def initialize(codeOrigin, child)
+ super(codeOrigin)
+ @child = child
+ end
+
+ def children
+ [@child]
+ end
+
+ def mapChildren
+ BitnotImmediate.new(codeOrigin, (yield @child))
+ end
+
+ def dump
+ "(~#{@child.dump})"
+ end
+
+ def address?
+ false
+ end
+
+ def label?
+ false
+ end
+
+ def immediate?
+ true
+ end
+
+ def register?
+ false
+ end
+end
+
class RegisterID < NoChildren
attr_reader :name
@@ -459,6 +610,28 @@ class FPRegisterID < NoChildren
end
end
+class SpecialRegister < NoChildren
+ def initialize(name)
+ @name = name
+ end
+
+ def address?
+ false
+ end
+
+ def label?
+ false
+ end
+
+ def immediate?
+ false
+ end
+
+ def register?
+ true
+ end
+end
+
class Variable < NoChildren
attr_reader :name
@@ -479,6 +652,10 @@ class Variable < NoChildren
def dump
name
end
+
+ def inspect
+ "<variable #{name} at #{codeOriginString}>"
+ end
end
class Address < Node
@@ -757,6 +934,10 @@ class LabelReference < Node
def label?
true
end
+
+ def immediate?
+ false
+ end
end
class LocalLabelReference < NoChildren
@@ -790,6 +971,10 @@ class LocalLabelReference < NoChildren
def label?
true
end
+
+ def immediate?
+ false
+ end
end
class Sequence < Node
diff --git a/Source/JavaScriptCore/offlineasm/backends.rb b/Source/JavaScriptCore/offlineasm/backends.rb
index 2c65b517d..db7a1e218 100644
--- a/Source/JavaScriptCore/offlineasm/backends.rb
+++ b/Source/JavaScriptCore/offlineasm/backends.rb
@@ -28,6 +28,7 @@ require "x86"
BACKENDS =
[
"X86",
+ "X86_64",
"ARMv7"
]
@@ -39,6 +40,7 @@ BACKENDS =
WORKING_BACKENDS =
[
"X86",
+ "X86_64",
"ARMv7"
]
@@ -46,7 +48,12 @@ BACKEND_PATTERN = Regexp.new('\\A(' + BACKENDS.join(')|(') + ')\\Z')
class Node
def lower(name)
- send("lower" + name)
+ begin
+ $activeBackend = name
+ send("lower" + name)
+ rescue => e
+ raise "Got error #{e} at #{codeOriginString}"
+ end
end
end
@@ -83,7 +90,14 @@ end
class Sequence
def lower(name)
- if respond_to? "lower#{name}"
+ $activeBackend = name
+ if respond_to? "getModifiedList#{name}"
+ newList = send("getModifiedList#{name}")
+ newList.each {
+ | node |
+ node.lower(name)
+ }
+ elsif respond_to? "lower#{name}"
send("lower#{name}")
else
@list.each {
diff --git a/Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb b/Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb
index 8bdf4505d..b2a8c2c83 100644
--- a/Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb
+++ b/Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb
@@ -45,8 +45,7 @@ def emitMagicNumber
}
end
-inputData = IO::read(inputFlnm)
-inputHash = "// offlineasm input hash: #{Digest::SHA1.hexdigest(inputData)} #{selfHash}"
+inputHash = "// offlineasm input hash: #{parseHash(inputFlnm)} #{selfHash}"
if FileTest.exist? outputFlnm
File.open(outputFlnm, "r") {
@@ -59,7 +58,7 @@ if FileTest.exist? outputFlnm
}
end
-originalAST = parse(lex(inputData))
+originalAST = parse(inputFlnm)
#
# Optimize the AST to make configuration extraction faster. This reduces the AST to a form
diff --git a/Source/JavaScriptCore/offlineasm/instructions.rb b/Source/JavaScriptCore/offlineasm/instructions.rb
index 497b47371..cc7e0c6a5 100644
--- a/Source/JavaScriptCore/offlineasm/instructions.rb
+++ b/Source/JavaScriptCore/offlineasm/instructions.rb
@@ -30,15 +30,20 @@ MACRO_INSTRUCTIONS =
"addi",
"andi",
"lshifti",
+ "lshiftp",
"muli",
"negi",
+ "negp",
"noti",
"ori",
"rshifti",
"urshifti",
+ "rshiftp",
+ "urshiftp",
"subi",
"xori",
"loadi",
+ "loadis",
"loadb",
"loadbs",
"loadh",
@@ -56,6 +61,8 @@ MACRO_INSTRUCTIONS =
"ci2d",
"fii2d", # usage: fii2d <gpr with least significant bits>, <gpr with most significant bits>, <fpr>
"fd2ii", # usage: fd2ii <fpr>, <gpr with least significant bits>, <gpr with most significant bits>
+ "fp2d",
+ "fd2p",
"bdeq",
"bdneq",
"bdgt",
@@ -157,6 +164,7 @@ MACRO_INSTRUCTIONS =
"bplt",
"bplteq",
"addp",
+ "mulp",
"andp",
"orp",
"subp",
diff --git a/Source/JavaScriptCore/offlineasm/offsets.rb b/Source/JavaScriptCore/offlineasm/offsets.rb
index 21e1706d2..63af014bb 100644
--- a/Source/JavaScriptCore/offlineasm/offsets.rb
+++ b/Source/JavaScriptCore/offlineasm/offsets.rb
@@ -27,6 +27,16 @@ OFFSET_HEADER_MAGIC_NUMBERS = [ 0x9e43fd66, 0x4379bfba ]
OFFSET_MAGIC_NUMBERS = [ 0xec577ac7, 0x0ff5e755 ]
#
+# MissingMagicValuesException
+#
+# Thrown when magic values are missing from the binary.
+# This is usually an indication that the classic interpreter is enabled.
+#
+
+class MissingMagicValuesException < Exception
+end
+
+#
# offsetsList(ast)
# sizesList(ast)
#
@@ -142,7 +152,7 @@ def offsetsAndConfigurationIndex(file)
end
}
- raise unless result.length >= 1
+ raise MissingMagicValuesException unless result.length >= 1
raise if result.map{|v| v[1]}.uniq.size < result.map{|v| v[1]}.size
result
diff --git a/Source/JavaScriptCore/offlineasm/parser.rb b/Source/JavaScriptCore/offlineasm/parser.rb
index f0e4b0045..11863c724 100644
--- a/Source/JavaScriptCore/offlineasm/parser.rb
+++ b/Source/JavaScriptCore/offlineasm/parser.rb
@@ -23,7 +23,22 @@
require "ast"
require "instructions"
+require "pathname"
require "registers"
+require "self_hash"
+
+class CodeOrigin
+ attr_reader :fileName, :lineNumber
+
+ def initialize(fileName, lineNumber)
+ @fileName = fileName
+ @lineNumber = lineNumber
+ end
+
+ def to_s
+ "#{fileName}:#{lineNumber}"
+ end
+end
class Token
attr_reader :codeOrigin, :string
@@ -46,7 +61,7 @@ class Token
end
def to_s
- "#{@string.inspect} at line #{codeOrigin}"
+ "#{@string.inspect} at #{codeOrigin}"
end
def parseError(*comment)
@@ -62,7 +77,8 @@ end
# The lexer. Takes a string and returns an array of tokens.
#
-def lex(str)
+def lex(str, fileName)
+ fileName = Pathname.new(fileName)
result = []
lineNumber = 1
while not str.empty?
@@ -70,28 +86,28 @@ def lex(str)
when /\A\#([^\n]*)/
# comment, ignore
when /\A\n/
- result << Token.new(lineNumber, $&)
+ result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
lineNumber += 1
when /\A[a-zA-Z]([a-zA-Z0-9_]*)/
- result << Token.new(lineNumber, $&)
+ result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
when /\A\.([a-zA-Z0-9_]*)/
- result << Token.new(lineNumber, $&)
+ result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
when /\A_([a-zA-Z0-9_]*)/
- result << Token.new(lineNumber, $&)
+ result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
when /\A([ \t]+)/
# whitespace, ignore
when /\A0x([0-9a-fA-F]+)/
- result << Token.new(lineNumber, $&.hex.to_s)
+ result << Token.new(CodeOrigin.new(fileName, lineNumber), $&.hex.to_s)
when /\A0([0-7]+)/
- result << Token.new(lineNumber, $&.oct.to_s)
+ result << Token.new(CodeOrigin.new(fileName, lineNumber), $&.oct.to_s)
when /\A([0-9]+)/
- result << Token.new(lineNumber, $&)
+ result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
when /\A::/
- result << Token.new(lineNumber, $&)
- when /\A[:,\(\)\[\]=\+\-*]/
- result << Token.new(lineNumber, $&)
+ result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
+ when /\A[:,\(\)\[\]=\+\-~\|&^*]/
+ result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
else
- raise "Lexer error at line number #{lineNumber}, unexpected sequence #{str[0..20].inspect}"
+ raise "Lexer error at #{CodeOrigin.new(fileName, lineNumber).to_s}, unexpected sequence #{str[0..20].inspect}"
end
str = $~.post_match
end
@@ -111,7 +127,7 @@ def isInstruction(token)
end
def isKeyword(token)
- token =~ /\A((true)|(false)|(if)|(then)|(else)|(elsif)|(end)|(and)|(or)|(not)|(macro)|(const)|(sizeof)|(error))\Z/ or
+ token =~ /\A((true)|(false)|(if)|(then)|(else)|(elsif)|(end)|(and)|(or)|(not)|(macro)|(const)|(sizeof)|(error)|(include))\Z/ or
token =~ REGISTER_PATTERN or
token =~ INSTRUCTION_PATTERN
end
@@ -142,8 +158,8 @@ end
#
class Parser
- def initialize(tokens)
- @tokens = tokens
+ def initialize(data, fileName)
+ @tokens = lex(data, fileName)
@idx = 0
end
@@ -306,6 +322,9 @@ class Parser
if @tokens[@idx] == "-"
@idx += 1
NegImmediate.new(@tokens[@idx - 1].codeOrigin, parseExpressionAtom)
+ elsif @tokens[@idx] == "~"
+ @idx += 1
+ BitnotImmediate.new(@tokens[@idx - 1].codeOrigin, parseExpressionAtom)
elsif @tokens[@idx] == "("
@idx += 1
result = parseExpression
@@ -349,10 +368,10 @@ class Parser
end
def couldBeExpression
- @tokens[@idx] == "-" or @tokens[@idx] == "sizeof" or isInteger(@tokens[@idx]) or isVariable(@tokens[@idx]) or @tokens[@idx] == "("
+ @tokens[@idx] == "-" or @tokens[@idx] == "~" or @tokens[@idx] == "sizeof" or isInteger(@tokens[@idx]) or isVariable(@tokens[@idx]) or @tokens[@idx] == "("
end
- def parseExpression
+ def parseExpressionAdd
skipNewLine
result = parseExpressionMul
while @tokens[@idx] == "+" or @tokens[@idx] == "-"
@@ -369,6 +388,33 @@ class Parser
result
end
+ def parseExpressionAnd
+ skipNewLine
+ result = parseExpressionAdd
+ while @tokens[@idx] == "&"
+ @idx += 1
+ result = AndImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionAdd)
+ end
+ result
+ end
+
+ def parseExpression
+ skipNewLine
+ result = parseExpressionAnd
+ while @tokens[@idx] == "|" or @tokens[@idx] == "^"
+ if @tokens[@idx] == "|"
+ @idx += 1
+ result = OrImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionAnd)
+ elsif @tokens[@idx] == "^"
+ @idx += 1
+ result = XorImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionAnd)
+ else
+ raise
+ end
+ end
+ result
+ end
+
def parseOperand(comment)
skipNewLine
if couldBeExpression
@@ -571,6 +617,14 @@ class Parser
list << LocalLabel.forName(codeOrigin, name)
end
@idx += 1
+ elsif @tokens[@idx] == "include"
+ @idx += 1
+ parseError unless isIdentifier(@tokens[@idx])
+ moduleName = @tokens[@idx].string
+ fileName = @tokens[@idx].codeOrigin.fileName.dirname + (moduleName + ".asm")
+ @idx += 1
+ $stderr.puts "offlineasm: Including file #{fileName}"
+ list << parse(fileName)
else
parseError "Expecting terminal #{final} #{comment}"
end
@@ -579,8 +633,16 @@ class Parser
end
end
-def parse(tokens)
- parser = Parser.new(tokens)
+def parseData(data, fileName)
+ parser = Parser.new(data, fileName)
parser.parseSequence(nil, "")
end
+def parse(fileName)
+ parseData(IO::read(fileName), fileName)
+end
+
+def parseHash(fileName)
+ dirHash(Pathname.new(fileName).dirname, /\.asm$/)
+end
+
diff --git a/Source/JavaScriptCore/offlineasm/registers.rb b/Source/JavaScriptCore/offlineasm/registers.rb
index 75fae4192..2c5a4ebf6 100644
--- a/Source/JavaScriptCore/offlineasm/registers.rb
+++ b/Source/JavaScriptCore/offlineasm/registers.rb
@@ -34,7 +34,13 @@ GPRS =
"r0",
"r1",
"sp",
- "lr"
+ "lr",
+
+ # 64-bit only registers:
+ "t5",
+ "t6", # r10
+ "csr1", # r14, tag type number register
+ "csr2" # r15, tag mask register
]
FPRS =
diff --git a/Source/JavaScriptCore/offlineasm/self_hash.rb b/Source/JavaScriptCore/offlineasm/self_hash.rb
index a7b51e112..2c300fccc 100644
--- a/Source/JavaScriptCore/offlineasm/self_hash.rb
+++ b/Source/JavaScriptCore/offlineasm/self_hash.rb
@@ -25,22 +25,33 @@ require "digest/sha1"
require "pathname"
#
-# selfHash -> SHA1 hexdigest
+# dirHash(directory, regexp) -> SHA1 hexdigest
#
-# Returns a hash of the offlineasm source code. This allows dependency
-# tracking for not just changes in input, but also changes in the assembler
-# itself.
+# Returns a hash of all files in the given directory that fit the given
+# pattern.
#
-def selfHash
+def dirHash(directory, regexp)
+ directory = Pathname.new(directory)
contents = ""
- myPath = Pathname.new(__FILE__).dirname
- Dir.foreach(myPath) {
+ Dir.foreach(directory) {
| entry |
- if entry =~ /\.rb$/
- contents += IO::read(myPath + entry)
+ if entry =~ regexp
+ contents += IO::read(directory + entry)
end
}
return Digest::SHA1.hexdigest(contents)
end
+#
+# selfHash -> SHA1 hexdigest
+#
+# Returns a hash of the offlineasm source code. This allows dependency
+# tracking for not just changes in input, but also changes in the assembler
+# itself.
+#
+
+def selfHash
+ dirHash(Pathname.new(__FILE__).dirname, /\.rb$/)
+end
+
diff --git a/Source/JavaScriptCore/offlineasm/settings.rb b/Source/JavaScriptCore/offlineasm/settings.rb
index 34598181c..b7daa7492 100644
--- a/Source/JavaScriptCore/offlineasm/settings.rb
+++ b/Source/JavaScriptCore/offlineasm/settings.rb
@@ -53,7 +53,7 @@ def computeSettingsCombinations(ast)
settingsCombinator(settingsCombinations, newMap, remaining[1..-1])
end
- settingsCombinator(settingsCombinations, {}, (ast.filter(Setting).uniq.collect{|v| v.name} + ["X86", "ARMv7"]).uniq)
+ settingsCombinator(settingsCombinations, {}, (ast.filter(Setting).uniq.collect{|v| v.name} + BACKENDS).uniq)
settingsCombinations
end
diff --git a/Source/JavaScriptCore/offlineasm/transform.rb b/Source/JavaScriptCore/offlineasm/transform.rb
index 5f5024d9e..86c72be67 100644
--- a/Source/JavaScriptCore/offlineasm/transform.rb
+++ b/Source/JavaScriptCore/offlineasm/transform.rb
@@ -328,6 +328,44 @@ class NegImmediate
end
end
+class OrImmediates
+ def fold
+ @left = @left.fold
+ @right = @right.fold
+ return self unless @left.is_a? Immediate
+ return self unless @right.is_a? Immediate
+ Immediate.new(codeOrigin, @left.value | @right.value)
+ end
+end
+
+class AndImmediates
+ def fold
+ @left = @left.fold
+ @right = @right.fold
+ return self unless @left.is_a? Immediate
+ return self unless @right.is_a? Immediate
+ Immediate.new(codeOrigin, @left.value & @right.value)
+ end
+end
+
+class XorImmediates
+ def fold
+ @left = @left.fold
+ @right = @right.fold
+ return self unless @left.is_a? Immediate
+ return self unless @right.is_a? Immediate
+ Immediate.new(codeOrigin, @left.value ^ @right.value)
+ end
+end
+
+class BitnotImmediate
+ def fold
+ @child = @child.fold
+ return self unless @child.is_a? Immediate
+ Immediate.new(codeOrigin, ~@child.value)
+ end
+end
+
#
# node.resolveAfterSettings(offsets, sizes)
#
@@ -340,3 +378,97 @@ class Node
end
end
+#
+# node.validate
+#
+# Checks that the node is ready for backend compilation.
+#
+
+class Node
+ def validate
+ raise "Unresolved #{dump} at #{codeOriginString}"
+ end
+
+ def validateChildren
+ children.each {
+ | node |
+ node.validate
+ }
+ end
+end
+
+class Sequence
+ def validate
+ validateChildren
+ end
+end
+
+class Immediate
+ def validate
+ end
+end
+
+class RegisterID
+ def validate
+ end
+end
+
+class FPRegisterID
+ def validate
+ end
+end
+
+class Address
+ def validate
+ validateChildren
+ end
+end
+
+class BaseIndex
+ def validate
+ validateChildren
+ end
+end
+
+class AbsoluteAddress
+ def validate
+ validateChildren
+ end
+end
+
+class Instruction
+ def validate
+ validateChildren
+ end
+end
+
+class Error
+ def validate
+ end
+end
+
+class Label
+ def validate
+ end
+end
+
+class LocalLabel
+ def validate
+ end
+end
+
+class LabelReference
+ def validate
+ end
+end
+
+class LocalLabelReference
+ def validate
+ end
+end
+
+class Skip
+ def validate
+ end
+end
+
diff --git a/Source/JavaScriptCore/offlineasm/x86.rb b/Source/JavaScriptCore/offlineasm/x86.rb
index b89f2d90c..4416ec909 100644
--- a/Source/JavaScriptCore/offlineasm/x86.rb
+++ b/Source/JavaScriptCore/offlineasm/x86.rb
@@ -1,4 +1,4 @@
-# Copyright (C) 2011 Apple Inc. All rights reserved.
+# Copyright (C) 2012 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -21,13 +21,48 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
+def isX64
+ case $activeBackend
+ when "X86"
+ false
+ when "X86_64"
+ true
+ 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
+ else
+ raise
+ end
+ end
+ def x86CallOperand(kind)
+ "*#{x86Operand(kind)}"
+ 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 "t4", "cfr"
+ when "cfr", "ttnr", "tmr"
false
+ when "t4", "t5"
+ isX64
else
raise
end
@@ -43,6 +78,8 @@ class RegisterID
"%ax"
when :int
"%eax"
+ when :ptr
+ isX64 ? "%rax" : "%eax"
else
raise
end
@@ -54,6 +91,8 @@ class RegisterID
"%dx"
when :int
"%edx"
+ when :ptr
+ isX64 ? "%rdx" : "%edx"
else
raise
end
@@ -65,6 +104,8 @@ class RegisterID
"%cx"
when :int
"%ecx"
+ when :ptr
+ isX64 ? "%rcx" : "%ecx"
else
raise
end
@@ -76,6 +117,8 @@ class RegisterID
"%bx"
when :int
"%ebx"
+ when :ptr
+ isX64 ? "%rbx" : "%ebx"
else
raise
end
@@ -87,19 +130,36 @@ class RegisterID
"%si"
when :int
"%esi"
+ when :ptr
+ isX64 ? "%rsi" : "%esi"
else
raise
end
when "cfr"
- case kind
- when :byte
- "%dil"
- when :half
- "%di"
- when :int
- "%edi"
+ if isX64
+ case kind
+ when :half
+ "%r13w"
+ when :int
+ "%r13d"
+ when :ptr
+ "%r13"
+ else
+ raise
+ end
else
- raise
+ case kind
+ when :byte
+ "%dil"
+ when :half
+ "%di"
+ when :int
+ "%edi"
+ when :ptr
+ "%edi"
+ else
+ raise
+ end
end
when "sp"
case kind
@@ -109,9 +169,53 @@ class RegisterID
"%sp"
when :int
"%esp"
+ when :ptr
+ isX64 ? "%rsp" : "%esp"
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"
+ 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"
+ 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"
+ 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"
+ end
else
raise "Bad register #{name} for X86 at #{codeOriginString}"
end
@@ -147,6 +251,13 @@ class FPRegisterID
end
class Immediate
+ def validX86Immediate?
+ if isX64
+ value >= -0x80000000 and value <= 0x7fffffff
+ else
+ true
+ end
+ end
def x86Operand(kind)
"$#{value}"
end
@@ -160,8 +271,11 @@ class Address
true
end
+ def x86AddressOperand(addressKind)
+ "#{offset.value}(#{base.x86Operand(addressKind)})"
+ end
def x86Operand(kind)
- "#{offset.value}(#{base.x86Operand(:int)})"
+ x86AddressOperand(:ptr)
end
def x86CallOperand(kind)
"*#{x86Operand(kind)}"
@@ -173,12 +287,16 @@ class BaseIndex
true
end
+ def x86AddressOperand(addressKind)
+ "#{offset.value}(#{base.x86Operand(addressKind)}, #{index.x86Operand(addressKind)}, #{scale})"
+ end
+
def x86Operand(kind)
- "#{offset.value}(#{base.x86Operand(:int)}, #{index.x86Operand(:int)}, #{scale})"
+ x86AddressOperand(:ptr)
end
def x86CallOperand(kind)
- "*#{x86operand(kind)}"
+ "*#{x86Operand(kind)}"
end
end
@@ -187,6 +305,10 @@ class AbsoluteAddress
true
end
+ def x86AddressOperand(addressKind)
+ "#{address.value}"
+ end
+
def x86Operand(kind)
"#{address.value}"
end
@@ -208,6 +330,47 @@ class LocalLabelReference
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)
+ 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
@@ -227,6 +390,8 @@ class Instruction
"w"
when :int
"l"
+ when :ptr
+ isX64 ? "q" : "l"
when :double
"sd"
else
@@ -234,6 +399,23 @@ class Instruction
end
end
+ def x86Bytes(kind)
+ case kind
+ when :byte
+ 1
+ when :half
+ 2
+ when :int
+ 4
+ when :ptr
+ isX64 ? 8 : 4
+ when :double
+ 8
+ else
+ raise
+ end
+ end
+
def handleX86OpWithNumOperands(opcode, kind, numOperands)
if numOperands == 3
if operands[0] == operands[2]
@@ -257,9 +439,10 @@ class Instruction
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
- $asm.puts "xchgl #{operands[0].x86Operand(:int)}, %ecx"
+ 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 "xchgl #{operands[0].x86Operand(:int)}, %ecx"
+ $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}"
end
end
@@ -295,10 +478,11 @@ class Instruction
$asm.puts "#{setOpcode} #{operand.x86Operand(:byte)}"
$asm.puts "movzbl #{operand.x86Operand(:byte)}, #{operand.x86Operand(:int)}"
else
- $asm.puts "xchgl #{operand.x86Operand(:int)}, %eax"
+ 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 "xchgl #{operand.x86Operand(:int)}, %eax"
+ $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}"
end
end
@@ -354,8 +538,8 @@ class Instruction
def handleX86SubBranch(branchOpcode, kind)
if operands.size == 4 and operands[1] == operands[2]
- $asm.puts "negl #{operands[2].x86Operand(:int)}"
- $asm.puts "addl #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:int)}"
+ $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
@@ -370,62 +554,120 @@ class Instruction
$asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}"
end
- def lowerX86
- $asm.comment codeOriginString
- case opcode
- when "addi", "addp"
- if 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 "movl #{operands[1].x86Operand(:int)}, #{operands[2].x86Operand(:int)}"
- end
- else
- $asm.puts "leal #{operands[0].value}(#{operands[1].x86Operand(:int)}), #{operands[2].x86Operand(:int)}"
+ def handleX86Add(kind)
+ if 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
- elsif operands.size == 3 and operands[0].is_a? RegisterID
- raise unless operands[1].is_a? RegisterID
- raise unless operands[2].is_a? RegisterID
- $asm.puts "leal (#{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}), #{operands[2].x86Operand(:int)}"
else
- unless Immediate.new(nil, 0) == operands[0]
- $asm.puts "addl #{x86Operands(:int, :int)}"
- end
+ $asm.puts "lea#{x86Suffix(kind)} #{operands[0].value}(#{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}"
end
- when "andi", "andp"
+ elsif operands.size == 3 and operands[0].is_a? RegisterID
+ raise unless operands[1].is_a? RegisterID
+ raise unless operands[2].is_a? RegisterID
+ $asm.puts "lea#{x86Suffix(kind)} (#{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}"
+ 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
+ $asm.puts "xor#{x86Suffix(:ptr)} #{operands[1].x86Operand(:ptr)}, #{operands[1].x86Operand(:ptr)}"
+ elsif operands[0] != operands[1]
+ $asm.puts "mov#{x86Suffix(:ptr)} #{x86Operands(:ptr, :ptr)}"
+ end
+ end
+
+ def lowerX86
+ raise unless $activeBackend == "X86"
+ lowerX86Common
+ end
+
+ def lowerX86_64
+ raise unless $activeBackend == "X86_64"
+ lowerX86Common
+ end
+
+ def lowerX86Common
+ $asm.comment codeOriginString
+ case opcode
+ when "addi"
+ handleX86Add(:int)
+ when "addp"
+ handleX86Add(:ptr)
+ when "andi"
handleX86Op("andl", :int)
+ when "andp"
+ handleX86Op("and#{x86Suffix(:ptr)}", :ptr)
when "lshifti"
handleX86Shift("sall", :int)
+ when "lshiftp"
+ handleX86Shift("sal#{x86Suffix(:ptr)}", :ptr)
when "muli"
- if operands.size == 3 and operands[0].is_a? Immediate
- $asm.puts "imull #{x86Operands(:int, :int, :int)}"
- else
- # FIXME: could do some peephole in case the left operand is immediate and it's
- # a power of two.
- handleX86Op("imull", :int)
- end
+ handleX86Mul(:int)
+ when "mulp"
+ handleX86Mul(:ptr)
when "negi"
$asm.puts "negl #{x86Operands(:int)}"
+ when "negp"
+ $asm.puts "neg#{x86Suffix(:ptr)} #{x86Operands(:ptr)}"
when "noti"
$asm.puts "notl #{x86Operands(:int)}"
- when "ori", "orp"
+ when "ori"
handleX86Op("orl", :int)
+ when "orp"
+ handleX86Op("or#{x86Suffix(:ptr)}", :ptr)
when "rshifti"
handleX86Shift("sarl", :int)
+ when "rshiftp"
+ handleX86Shift("sar#{x86Suffix(:ptr)}", :ptr)
when "urshifti"
handleX86Shift("shrl", :int)
- when "subi", "subp"
- if operands.size == 3 and operands[1] == operands[2]
- $asm.puts "negl #{operands[2].x86Operand(:int)}"
- $asm.puts "addl #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:int)}"
- else
- handleX86Op("subl", :int)
- end
- when "xori", "xorp"
+ when "urshiftp"
+ handleX86Shift("shr#{x86Suffix(:ptr)}", :ptr)
+ when "subi"
+ handleX86Sub(:int)
+ when "subp"
+ handleX86Sub(:ptr)
+ when "xori"
handleX86Op("xorl", :int)
- when "loadi", "storei", "loadp", "storep"
+ when "xorp"
+ handleX86Op("xor#{x86Suffix(:ptr)}", :ptr)
+ when "loadi", "storei"
$asm.puts "movl #{x86Operands(:int, :int)}"
+ when "loadis"
+ if isX64
+ $asm.puts "movslq #{x86Operands(:int, :ptr)}"
+ else
+ $asm.puts "movl #{x86Operands(:int, :int)}"
+ end
+ when "loadp", "storep"
+ $asm.puts "mov#{x86Suffix(:ptr)} #{x86Operands(:ptr, :ptr)}"
when "loadb"
$asm.puts "movzbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
when "loadbs"
@@ -502,37 +744,65 @@ class Instruction
when "movdz"
$asm.puts "xorpd #{operands[0].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
when "pop"
- $asm.puts "pop #{operands[0].x86Operand(:int)}"
+ $asm.puts "pop #{operands[0].x86Operand(:ptr)}"
when "push"
- $asm.puts "push #{operands[0].x86Operand(:int)}"
- when "move", "sxi2p", "zxi2p"
- if Immediate.new(nil, 0) == operands[0] and operands[1].is_a? RegisterID
- $asm.puts "xorl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
- elsif operands[0] != operands[1]
- $asm.puts "movl #{x86Operands(:int, :int)}"
+ $asm.puts "push #{operands[0].x86Operand(:ptr)}"
+ when "move"
+ handleMove
+ when "sxi2p"
+ if isX64
+ $asm.puts "movslq #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:ptr)}"
+ else
+ handleMove
+ end
+ when "zxi2p"
+ if isX64
+ $asm.puts "movl #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
+ else
+ handleMove
end
when "nop"
$asm.puts "nop"
- when "bieq", "bpeq"
+ when "bieq"
handleX86IntBranch("je", :int)
- when "bineq", "bpneq"
+ when "bpeq"
+ handleX86IntBranch("je", :ptr)
+ when "bineq"
handleX86IntBranch("jne", :int)
- when "bia", "bpa"
+ when "bpneq"
+ handleX86IntBranch("jne", :ptr)
+ when "bia"
handleX86IntBranch("ja", :int)
- when "biaeq", "bpaeq"
+ when "bpa"
+ handleX86IntBranch("ja", :ptr)
+ when "biaeq"
handleX86IntBranch("jae", :int)
- when "bib", "bpb"
+ when "bpaeq"
+ handleX86IntBranch("jae", :ptr)
+ when "bib"
handleX86IntBranch("jb", :int)
- when "bibeq", "bpbeq"
+ when "bpb"
+ handleX86IntBranch("jb", :ptr)
+ when "bibeq"
handleX86IntBranch("jbe", :int)
- when "bigt", "bpgt"
+ when "bpbeq"
+ handleX86IntBranch("jbe", :ptr)
+ when "bigt"
handleX86IntBranch("jg", :int)
- when "bigteq", "bpgteq"
+ when "bpgt"
+ handleX86IntBranch("jg", :ptr)
+ when "bigteq"
handleX86IntBranch("jge", :int)
- when "bilt", "bplt"
+ when "bpgteq"
+ handleX86IntBranch("jge", :ptr)
+ when "bilt"
handleX86IntBranch("jl", :int)
- when "bilteq", "bplteq"
+ when "bplt"
+ handleX86IntBranch("jl", :ptr)
+ when "bilteq"
handleX86IntBranch("jle", :int)
+ when "bplteq"
+ handleX86IntBranch("jle", :ptr)
when "bbeq"
handleX86IntBranch("je", :byte)
when "bbneq"
@@ -553,14 +823,22 @@ class Instruction
handleX86IntBranch("jl", :byte)
when "bblteq"
handleX86IntBranch("jlteq", :byte)
- when "btio", "btpo"
+ when "btio"
handleX86BranchTest("jo", :int)
- when "btis", "btps"
+ when "btpo"
+ handleX86BranchTest("jo", :ptr)
+ when "btis"
handleX86BranchTest("js", :int)
- when "btiz", "btpz"
+ when "btps"
+ handleX86BranchTest("js", :ptr)
+ when "btiz"
handleX86BranchTest("jz", :int)
- when "btinz", "btpnz"
+ when "btpz"
+ handleX86BranchTest("jz", :ptr)
+ when "btinz"
handleX86BranchTest("jnz", :int)
+ when "btpnz"
+ handleX86BranchTest("jnz", :ptr)
when "btbo"
handleX86BranchTest("jo", :byte)
when "btbs"
@@ -570,15 +848,23 @@ class Instruction
when "btbnz"
handleX86BranchTest("jnz", :byte)
when "jmp"
- $asm.puts "jmp #{operands[0].x86CallOperand(:int)}"
- when "baddio", "baddpo"
+ $asm.puts "jmp #{operands[0].x86CallOperand(:ptr)}"
+ when "baddio"
handleX86OpBranch("addl", "jo", :int)
- when "baddis", "baddps"
+ when "baddpo"
+ handleX86OpBranch("add#{x86Suffix(:ptr)}", "jo", :ptr)
+ when "baddis"
handleX86OpBranch("addl", "js", :int)
- when "baddiz", "baddpz"
+ when "baddps"
+ handleX86OpBranch("add#{x86Suffix(:ptr)}", "js", :ptr)
+ when "baddiz"
handleX86OpBranch("addl", "jz", :int)
- when "baddinz", "baddpnz"
+ when "baddpz"
+ handleX86OpBranch("add#{x86Suffix(:ptr)}", "jz", :ptr)
+ when "baddinz"
handleX86OpBranch("addl", "jnz", :int)
+ when "baddpnz"
+ handleX86OpBranch("add#{x86Suffix(:ptr)}", "jnz", :ptr)
when "bsubio"
handleX86SubBranch("jo", :int)
when "bsubis"
@@ -606,29 +892,49 @@ class Instruction
when "break"
$asm.puts "int $3"
when "call"
- $asm.puts "call #{operands[0].x86CallOperand(:int)}"
+ $asm.puts "call #{operands[0].x86CallOperand(:ptr)}"
when "ret"
$asm.puts "ret"
- when "cieq", "cpeq"
+ when "cieq"
handleX86IntCompareSet("sete", :int)
- when "cineq", "cpneq"
+ when "cpeq"
+ handleX86IntCompareSet("sete", :ptr)
+ when "cineq"
handleX86IntCompareSet("setne", :int)
- when "cia", "cpa"
+ when "cpneq"
+ handleX86IntCompareSet("setne", :ptr)
+ when "cia"
handleX86IntCompareSet("seta", :int)
- when "ciaeq", "cpaeq"
+ when "cpa"
+ handleX86IntCompareSet("seta", :ptr)
+ when "ciaeq"
handleX86IntCompareSet("setae", :int)
- when "cib", "cpb"
+ when "cpaeq"
+ handleX86IntCompareSet("setae", :ptr)
+ when "cib"
handleX86IntCompareSet("setb", :int)
- when "cibeq", "cpbeq"
+ when "cpb"
+ handleX86IntCompareSet("setb", :ptr)
+ when "cibeq"
handleX86IntCompareSet("setbe", :int)
- when "cigt", "cpgt"
+ when "cpbeq"
+ handleX86IntCompareSet("setbe", :ptr)
+ when "cigt"
handleX86IntCompareSet("setg", :int)
- when "cigteq", "cpgteq"
+ when "cpgt"
+ handleX86IntCompareSet("setg", :ptr)
+ when "cigteq"
handleX86IntCompareSet("setge", :int)
- when "cilt", "cplt"
+ when "cpgteq"
+ handleX86IntCompareSet("setge", :ptr)
+ when "cilt"
handleX86IntCompareSet("setl", :int)
- when "cilteq", "cplteq"
+ when "cplt"
+ handleX86IntCompareSet("setl", :ptr)
+ when "cilteq"
handleX86IntCompareSet("setle", :int)
+ when "cplteq"
+ handleX86IntCompareSet("setle", :ptr)
when "tio"
handleX86SetTest("seto", :int)
when "tis"
@@ -646,9 +952,11 @@ class Instruction
when "tbnz"
handleX86SetTest("setnz", :byte)
when "peek"
- $asm.puts "movl #{operands[0].value * 4}(%esp), #{operands[1].x86Operand(:int)}"
+ sp = RegisterID.new(nil, "sp")
+ $asm.puts "mov#{x86Suffix(:ptr)} #{operands[0].value * x86Bytes(:ptr)}(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:ptr)}"
when "poke"
- $asm.puts "movl #{operands[0].x86Operand(:int)}, #{operands[1].value * 4}(%esp)"
+ sp = RegisterID.new(nil, "sp")
+ $asm.puts "mov#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{operands[1].value * x86Bytes(:ptr)}(#{sp.x86Operand(:ptr)})"
when "cdqi"
$asm.puts "cdq"
when "idivi"
@@ -663,6 +971,10 @@ class Instruction
$asm.puts "movsd #{operands[0].x86Operand(:double)}, %xmm7"
$asm.puts "psrlq $32, %xmm7"
$asm.puts "movsd %xmm7, #{operands[2].x86Operand(:int)}"
+ when "fp2d"
+ $asm.puts "movd #{operands[0].x86Operand(:ptr)}, #{operands[1].x86Operand(:double)}"
+ when "fd2p"
+ $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:ptr)}"
when "bo"
$asm.puts "jo #{operands[0].asmLabel}"
when "bs"
@@ -671,8 +983,10 @@ class Instruction
$asm.puts "jz #{operands[0].asmLabel}"
when "bnz"
$asm.puts "jnz #{operands[0].asmLabel}"
- when "leai", "leap"
- $asm.puts "leal #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
+ 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)}"
else
raise "Bad opcode: #{opcode}"
end