]> git.saurik.com Git - apple/javascriptcore.git/blame - offlineasm/risc_arm64.rb
JavaScriptCore-1218.33.tar.gz
[apple/javascriptcore.git] / offlineasm / risc_arm64.rb
CommitLineData
93a37866
A
1# Copyright (C) 2012 Apple Inc. All rights reserved.
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions
5# are met:
6# 1. Redistributions of source code must retain the above copyright
7# notice, this list of conditions and the following disclaimer.
8# 2. Redistributions in binary form must reproduce the above copyright
9# notice, this list of conditions and the following disclaimer in the
10# documentation and/or other materials provided with the distribution.
11#
12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
13# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
14# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
15# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
16# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
18# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
19# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
22# THE POSSIBILITY OF SUCH DAMAGE.
23
24require 'ast'
25require 'opt'
26require 'risc'
27
28# This file contains utilities that should be in risc.rb if it wasn't for the
29# fact that risc.rb is shared with the ARMv7 backend, and may be part of a
30# code dump before ARM64 goes public.
31#
32# FIXME: when ARM64 goes public, we should merge this file into risc.rb
33
34#
35# Lowering of the not instruction. The following:
36#
37# noti t0
38#
39# becomes:
40#
41# xori -1, t0
42#
43
44def riscLowerNot(list)
45 newList = []
46 list.each {
47 | node |
48 if node.is_a? Instruction
49 case node.opcode
50 when "noti", "notp"
51 raise "Wrong nubmer of operands at #{node.codeOriginString}" unless node.operands.size == 1
52 suffix = node.opcode[-1..-1]
53 newList << Instruction.new(node.codeOrigin, "xor" + suffix,
54 [Immediate.new(node.codeOrigin, -1), node.operands[0]])
55 else
56 newList << node
57 end
58 else
59 newList << node
60 end
61 }
62 return newList
63end
64
65#
66# Lowing of complex branch ops on 64-bit. For example:
67#
68# bmulio foo, bar, baz
69#
70# becomes:
71#
72# smulli foo, bar, bar
73# rshiftp bar, 32, tmp1
74# rshifti bar, 31, tmp2
75# zxi2p bar, bar
76# bineq tmp1, tmp2, baz
77#
78
79def riscLowerHardBranchOps64(list)
80 newList = []
81 list.each {
82 | node |
83 if node.is_a? Instruction and node.opcode == "bmulio"
84 tmp1 = Tmp.new(node.codeOrigin, :gpr)
85 tmp2 = Tmp.new(node.codeOrigin, :gpr)
86 newList << Instruction.new(node.codeOrigin, "smulli", [node.operands[0], node.operands[1], node.operands[1]])
87 newList << Instruction.new(node.codeOrigin, "rshiftp", [node.operands[1], Immediate.new(node.codeOrigin, 32), tmp1])
88 newList << Instruction.new(node.codeOrigin, "rshifti", [node.operands[1], Immediate.new(node.codeOrigin, 31), tmp2])
89 newList << Instruction.new(node.codeOrigin, "zxi2p", [node.operands[1], node.operands[1]])
90 newList << Instruction.new(node.codeOrigin, "bineq", [tmp1, tmp2, node.operands[2]])
91 else
92 newList << node
93 end
94 }
95 newList
96end
97
98#
99# Lowering of test instructions. For example:
100#
101# btiz t0, t1, .foo
102#
103# becomes:
104#
105# andi t0, t1, tmp
106# bieq tmp, 0, .foo
107#
108# and another example:
109#
110# tiz t0, t1, t2
111#
112# becomes:
113#
114# andi t0, t1, tmp
115# cieq tmp, 0, t2
116#
117
118def riscLowerTest(list)
119 def emit(newList, andOpcode, branchOpcode, node)
120 if node.operands.size == 2
121 newList << Instruction.new(node.codeOrigin, branchOpcode, [node.operands[0], Immediate.new(node.codeOrigin, 0), node.operands[1]])
122 return
123 end
124
125 raise "Incorrect number of operands at #{codeOriginString}" unless node.operands.size == 3
126
127 if node.operands[0].immediate? and node.operands[0].value == -1
128 newList << Instruction.new(node.codeOrigin, branchOpcode, [node.operands[1], Immediate.new(node.codeOrigin, 0), node.operands[2]])
129 return
130 end
131
132 if node.operands[1].immediate? and node.operands[1].value == -1
133 newList << Instruction.new(node.codeOrigin, branchOpcode, [node.operands[0], Immediate.new(node.codeOrigin, 0), node.operands[2]])
134 return
135 end
136
137 tmp = Tmp.new(node.codeOrigin, :gpr)
138 newList << Instruction.new(node.codeOrigin, andOpcode, [node.operands[0], node.operands[1], tmp])
139 newList << Instruction.new(node.codeOrigin, branchOpcode, [tmp, Immediate.new(node.codeOrigin, 0), node.operands[2]])
140 end
141
142 newList = []
143 list.each {
144 | node |
145 if node.is_a? Instruction
146 case node.opcode
147 when "btis"
148 emit(newList, "andi", "bilt", node)
149 when "btiz"
150 emit(newList, "andi", "bieq", node)
151 when "btinz"
152 emit(newList, "andi", "bineq", node)
153 when "btps"
154 emit(newList, "andp", "bplt", node)
155 when "btpz"
156 emit(newList, "andp", "bpeq", node)
157 when "btpnz"
158 emit(newList, "andp", "bpneq", node)
159 when "btqs"
160 emit(newList, "andq", "bqlt", node)
161 when "btqz"
162 emit(newList, "andq", "bqeq", node)
163 when "btqnz"
164 emit(newList, "andq", "bqneq", node)
165 when "btbs"
166 emit(newList, "andi", "bblt", node)
167 when "btbz"
168 emit(newList, "andi", "bbeq", node)
169 when "btbnz"
170 emit(newList, "andi", "bbneq", node)
171 when "tis"
172 emit(newList, "andi", "cilt", node)
173 when "tiz"
174 emit(newList, "andi", "cieq", node)
175 when "tinz"
176 emit(newList, "andi", "cineq", node)
177 when "tps"
178 emit(newList, "andp", "cplt", node)
179 when "tpz"
180 emit(newList, "andp", "cpeq", node)
181 when "tpnz"
182 emit(newList, "andp", "cpneq", node)
183 when "tqs"
184 emit(newList, "andq", "cqlt", node)
185 when "tqz"
186 emit(newList, "andq", "cqeq", node)
187 when "tqnz"
188 emit(newList, "andq", "cqneq", node)
189 when "tbs"
190 emit(newList, "andi", "cblt", node)
191 when "tbz"
192 emit(newList, "andi", "cbeq", node)
193 when "tbnz"
194 emit(newList, "andi", "cbneq", node)
195 else
196 newList << node
197 end
198 else
199 newList << node
200 end
201 }
202 return newList
203end
204