]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - offlineasm/risc.rb
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / offlineasm / risc.rb
index 9547861f92094e8a3e33b6aae717e3d0d05ff6fc..3fbc07d0b416370f59d819aee493ec34dc39ab7f 100644 (file)
@@ -558,3 +558,173 @@ def riscLowerRegisterReuse(list)
     newList
 end
 
+#
+# Lowering of the not instruction. The following:
+#
+# noti t0
+#
+# becomes:
+#
+# xori -1, t0
+#
+
+def riscLowerNot(list)
+    newList = []
+    list.each {
+        | node |
+        if node.is_a? Instruction
+            case node.opcode
+            when "noti", "notp"
+                raise "Wrong nubmer of operands at #{node.codeOriginString}" unless node.operands.size == 1
+                suffix = node.opcode[-1..-1]
+                newList << Instruction.new(node.codeOrigin, "xor" + suffix,
+                                           [Immediate.new(node.codeOrigin, -1), node.operands[0]])
+            else
+                newList << node
+            end
+        else
+            newList << node
+        end
+    }
+    return newList
+end
+
+#
+# Lowing of complex branch ops on 64-bit. For example:
+#
+# bmulio foo, bar, baz
+#
+# becomes:
+#
+# smulli foo, bar, bar
+# rshiftp bar, 32, tmp1
+# rshifti bar, 31, tmp2
+# zxi2p bar, bar 
+# bineq tmp1, tmp2, baz
+#
+
+def riscLowerHardBranchOps64(list)
+    newList = []
+    list.each {
+        | node |
+        if node.is_a? Instruction and node.opcode == "bmulio"
+            tmp1 = Tmp.new(node.codeOrigin, :gpr)
+            tmp2 = Tmp.new(node.codeOrigin, :gpr)
+            newList << Instruction.new(node.codeOrigin, "smulli", [node.operands[0], node.operands[1], node.operands[1]])
+            newList << Instruction.new(node.codeOrigin, "rshiftp", [node.operands[1], Immediate.new(node.codeOrigin, 32), tmp1])
+            newList << Instruction.new(node.codeOrigin, "rshifti", [node.operands[1], Immediate.new(node.codeOrigin, 31), tmp2])
+            newList << Instruction.new(node.codeOrigin, "zxi2p", [node.operands[1], node.operands[1]])
+            newList << Instruction.new(node.codeOrigin, "bineq", [tmp1, tmp2, node.operands[2]])
+        else
+            newList << node
+        end
+    }
+    newList
+end
+
+#
+# Lowering of test instructions. For example:
+#
+# btiz t0, t1, .foo
+#
+# becomes:
+#
+# andi t0, t1, tmp
+# bieq tmp, 0, .foo
+#
+# and another example:
+#
+# tiz t0, t1, t2
+#
+# becomes:
+#
+# andi t0, t1, tmp
+# cieq tmp, 0, t2
+#
+
+def riscLowerTest(list)
+    def emit(newList, andOpcode, branchOpcode, node)
+        if node.operands.size == 2
+            newList << Instruction.new(node.codeOrigin, branchOpcode, [node.operands[0], Immediate.new(node.codeOrigin, 0), node.operands[1]])
+            return
+        end
+
+        raise "Incorrect number of operands at #{codeOriginString}" unless node.operands.size == 3
+
+        if node.operands[0].immediate? and node.operands[0].value == -1
+            newList << Instruction.new(node.codeOrigin, branchOpcode, [node.operands[1], Immediate.new(node.codeOrigin, 0), node.operands[2]])
+            return
+        end
+
+        if node.operands[1].immediate? and node.operands[1].value == -1
+            newList << Instruction.new(node.codeOrigin, branchOpcode, [node.operands[0], Immediate.new(node.codeOrigin, 0), node.operands[2]])
+            return
+        end
+        
+        tmp = Tmp.new(node.codeOrigin, :gpr)
+        newList << Instruction.new(node.codeOrigin, andOpcode, [node.operands[0], node.operands[1], tmp])
+        newList << Instruction.new(node.codeOrigin, branchOpcode, [tmp, Immediate.new(node.codeOrigin, 0), node.operands[2]])
+    end
+
+    newList = []
+    list.each {
+        | node |
+        if node.is_a? Instruction
+            case node.opcode
+            when "btis"
+                emit(newList, "andi", "bilt", node)
+            when "btiz"
+                emit(newList, "andi", "bieq", node)
+            when "btinz"
+                emit(newList, "andi", "bineq", node)
+            when "btps"
+                emit(newList, "andp", "bplt", node)
+            when "btpz"
+                emit(newList, "andp", "bpeq", node)
+            when "btpnz"
+                emit(newList, "andp", "bpneq", node)
+            when "btqs"
+                emit(newList, "andq", "bqlt", node)
+            when "btqz"
+                emit(newList, "andq", "bqeq", node)
+            when "btqnz"
+                emit(newList, "andq", "bqneq", node)
+            when "btbs"
+                emit(newList, "andi", "bblt", node)
+            when "btbz"
+                emit(newList, "andi", "bbeq", node)
+            when "btbnz"
+                emit(newList, "andi", "bbneq", node)
+            when "tis"
+                emit(newList, "andi", "cilt", node)
+            when "tiz"
+                emit(newList, "andi", "cieq", node)
+            when "tinz"
+                emit(newList, "andi", "cineq", node)
+            when "tps"
+                emit(newList, "andp", "cplt", node)
+            when "tpz"
+                emit(newList, "andp", "cpeq", node)
+            when "tpnz"
+                emit(newList, "andp", "cpneq", node)
+            when "tqs"
+                emit(newList, "andq", "cqlt", node)
+            when "tqz"
+                emit(newList, "andq", "cqeq", node)
+            when "tqnz"
+                emit(newList, "andq", "cqneq", node)
+            when "tbs"
+                emit(newList, "andi", "cblt", node)
+            when "tbz"
+                emit(newList, "andi", "cbeq", node)
+            when "tbnz"
+                emit(newList, "andi", "cbneq", node)
+            else
+                newList << node
+            end
+        else
+            newList << node
+        end
+    }
+    return newList
+end