diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-03-12 14:11:15 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-03-12 14:11:15 +0100 |
commit | dd91e772430dc294e3bf478c119ef8d43c0a3358 (patch) | |
tree | 6f33ce4d5872a5691e0291eb45bf6ab373a5f567 /Source/JavaScriptCore/offlineasm | |
parent | ad0d549d4cc13433f77c1ac8f0ab379c83d93f28 (diff) | |
download | qtwebkit-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.rb | 50 | ||||
-rw-r--r-- | Source/JavaScriptCore/offlineasm/asm.rb | 13 | ||||
-rw-r--r-- | Source/JavaScriptCore/offlineasm/ast.rb | 187 | ||||
-rw-r--r-- | Source/JavaScriptCore/offlineasm/backends.rb | 18 | ||||
-rw-r--r-- | Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb | 5 | ||||
-rw-r--r-- | Source/JavaScriptCore/offlineasm/instructions.rb | 8 | ||||
-rw-r--r-- | Source/JavaScriptCore/offlineasm/offsets.rb | 12 | ||||
-rw-r--r-- | Source/JavaScriptCore/offlineasm/parser.rb | 102 | ||||
-rw-r--r-- | Source/JavaScriptCore/offlineasm/registers.rb | 8 | ||||
-rw-r--r-- | Source/JavaScriptCore/offlineasm/self_hash.rb | 29 | ||||
-rw-r--r-- | Source/JavaScriptCore/offlineasm/settings.rb | 2 | ||||
-rw-r--r-- | Source/JavaScriptCore/offlineasm/transform.rb | 132 | ||||
-rw-r--r-- | Source/JavaScriptCore/offlineasm/x86.rb | 510 |
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 |