]>
Commit | Line | Data |
---|---|---|
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 | ||
24 | require 'ast' | |
25 | require 'opt' | |
26 | require '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 | ||
44 | def 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 | |
63 | end | |
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 | ||
79 | def 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 | |
96 | end | |
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 | ||
118 | def 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 | |
203 | end | |
204 |