3902
|
1 |
diff --git a/js/src/Makefile.in b/js/src/Makefile.in
|
|
2 |
index fadd850..b719c30 100644
|
|
3 |
--- a/js/src/Makefile.in
|
|
4 |
+++ b/js/src/Makefile.in
|
|
5 |
@@ -350,6 +350,9 @@ endif
|
|
6 |
ifeq (arm, $(TARGET_CPU))
|
|
7 |
#CPPSRCS += only_on_arm.cpp
|
|
8 |
endif
|
|
9 |
+ifeq (sparc, $(findstring sparc,$(TARGET_CPU)))
|
|
10 |
+ASFILES += TrampolineSparc.s
|
|
11 |
+endif
|
|
12 |
#
|
|
13 |
# END enclude sources for the method JIT
|
|
14 |
#############################################
|
|
15 |
@@ -375,7 +378,7 @@ CPPSRCS += checks.cc \
|
|
16 |
# END enclude sources for V8 dtoa
|
|
17 |
#############################################
|
|
18 |
|
|
19 |
-ifeq (,$(filter-out powerpc sparc,$(TARGET_CPU)))
|
|
20 |
+ifeq (,$(filter-out powerpc,$(TARGET_CPU)))
|
|
21 |
|
|
22 |
VPATH += $(srcdir)/assembler \
|
|
23 |
$(srcdir)/assembler/wtf \
|
|
24 |
diff --git a/js/src/assembler/assembler/AbstractMacroAssembler.h b/js/src/assembler/assembler/AbstractMacroAssembler.h
|
|
25 |
index 77958d9..d06a213 100644
|
|
26 |
--- a/js/src/assembler/assembler/AbstractMacroAssembler.h
|
|
27 |
+++ b/js/src/assembler/assembler/AbstractMacroAssembler.h
|
|
28 |
@@ -522,6 +522,11 @@ public:
|
|
29 |
return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
|
|
30 |
}
|
|
31 |
|
|
32 |
+ ptrdiff_t differenceBetween(DataLabel32 from, Jump to)
|
|
33 |
+ {
|
|
34 |
+ return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
|
|
35 |
+ }
|
|
36 |
+
|
|
37 |
ptrdiff_t differenceBetween(DataLabelPtr from, Jump to)
|
|
38 |
{
|
|
39 |
return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
|
|
40 |
diff --git a/js/src/assembler/assembler/MacroAssembler.h b/js/src/assembler/assembler/MacroAssembler.h
|
|
41 |
index 5f24981..73bda22 100644
|
|
42 |
--- a/js/src/assembler/assembler/MacroAssembler.h
|
|
43 |
+++ b/js/src/assembler/assembler/MacroAssembler.h
|
|
44 |
@@ -54,6 +54,10 @@ namespace JSC { typedef MacroAssemblerX86 MacroAssemblerBase; }
|
|
45 |
#include "MacroAssemblerX86_64.h"
|
|
46 |
namespace JSC { typedef MacroAssemblerX86_64 MacroAssemblerBase; }
|
|
47 |
|
|
48 |
+#elif WTF_CPU_SPARC
|
|
49 |
+#include "MacroAssemblerSparc.h"
|
|
50 |
+namespace JSC { typedef MacroAssemblerSparc MacroAssemblerBase; }
|
|
51 |
+
|
|
52 |
#else
|
|
53 |
#error "The MacroAssembler is not supported on this platform."
|
|
54 |
#endif
|
|
55 |
diff --git a/js/src/assembler/assembler/MacroAssemblerSparc.h b/js/src/assembler/assembler/MacroAssemblerSparc.h
|
|
56 |
new file mode 100644
|
|
57 |
index 0000000..a2a039c
|
|
58 |
--- /dev/null
|
|
59 |
+++ b/js/src/assembler/assembler/MacroAssemblerSparc.h
|
|
60 |
@@ -0,0 +1,1485 @@
|
|
61 |
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
62 |
+ * vim: set ts=4 sw=4 et tw=99:
|
|
63 |
+ *
|
|
64 |
+ * ***** BEGIN LICENSE BLOCK *****
|
|
65 |
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
66 |
+ *
|
|
67 |
+ * The contents of this file are subject to the Mozilla Public License Version
|
|
68 |
+ * 1.1 (the "License"); you may not use this file except in compliance with
|
|
69 |
+ * the License. You may obtain a copy of the License at
|
|
70 |
+ * http://www.mozilla.org/MPL/
|
|
71 |
+ *
|
|
72 |
+ * Software distributed under the License is distributed on an "AS IS" basis,
|
|
73 |
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
74 |
+ * for the specific language governing rights and limitations under the
|
|
75 |
+ * License.
|
|
76 |
+ *
|
|
77 |
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
|
|
78 |
+ * May 28, 2008.
|
|
79 |
+ *
|
|
80 |
+ * The Initial Developer of the Original Code is
|
|
81 |
+ * Leon Sha <[email protected]>
|
|
82 |
+ *
|
|
83 |
+ * Portions created by the Initial Developer are Copyright (C) 2010-2011
|
|
84 |
+ * the Initial Developer. All Rights Reserved.
|
|
85 |
+ *
|
|
86 |
+ * Contributor(s):
|
|
87 |
+ *
|
|
88 |
+ * Alternatively, the contents of this file may be used under the terms of
|
|
89 |
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
90 |
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
91 |
+ * in which case the provisions of the GPL or the LGPL are applicable instead
|
|
92 |
+ * of those above. If you wish to allow use of your version of this file only
|
|
93 |
+ * under the terms of either the GPL or the LGPL, and not to allow others to
|
|
94 |
+ * use your version of this file under the terms of the MPL, indicate your
|
|
95 |
+ * decision by deleting the provisions above and replace them with the notice
|
|
96 |
+ * and other provisions required by the GPL or the LGPL. If you do not delete
|
|
97 |
+ * the provisions above, a recipient may use your version of this file under
|
|
98 |
+ * the terms of any one of the MPL, the GPL or the LGPL.
|
|
99 |
+ *
|
|
100 |
+ * ***** END LICENSE BLOCK ***** */
|
|
101 |
+
|
|
102 |
+#ifndef MacroAssemblerSparc_h
|
|
103 |
+#define MacroAssemblerSparc_h
|
|
104 |
+
|
|
105 |
+#include <wtf/Platform.h>
|
|
106 |
+
|
|
107 |
+#if ENABLE_ASSEMBLER && WTF_CPU_SPARC
|
|
108 |
+
|
|
109 |
+#include "SparcAssembler.h"
|
|
110 |
+#include "AbstractMacroAssembler.h"
|
|
111 |
+
|
|
112 |
+namespace JSC {
|
|
113 |
+
|
|
114 |
+ class MacroAssemblerSparc : public AbstractMacroAssembler<SparcAssembler> {
|
|
115 |
+ public:
|
|
116 |
+ enum Condition {
|
|
117 |
+ Equal = SparcAssembler::ConditionE,
|
|
118 |
+ NotEqual = SparcAssembler::ConditionNE,
|
|
119 |
+ Above = SparcAssembler::ConditionGU,
|
|
120 |
+ AboveOrEqual = SparcAssembler::ConditionCC,
|
|
121 |
+ Below = SparcAssembler::ConditionCS,
|
|
122 |
+ BelowOrEqual = SparcAssembler::ConditionLEU,
|
|
123 |
+ GreaterThan = SparcAssembler::ConditionG,
|
|
124 |
+ GreaterThanOrEqual = SparcAssembler::ConditionGE,
|
|
125 |
+ LessThan = SparcAssembler::ConditionL,
|
|
126 |
+ LessThanOrEqual = SparcAssembler::ConditionLE,
|
|
127 |
+ Overflow = SparcAssembler::ConditionVS,
|
|
128 |
+ Signed = SparcAssembler::ConditionNEG,
|
|
129 |
+ Zero = SparcAssembler::ConditionE,
|
|
130 |
+ NonZero = SparcAssembler::ConditionNE
|
|
131 |
+ };
|
|
132 |
+
|
|
133 |
+ enum DoubleCondition {
|
|
134 |
+ // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
|
|
135 |
+ DoubleEqual = SparcAssembler::DoubleConditionE,
|
|
136 |
+ DoubleNotEqual = SparcAssembler::DoubleConditionNE,
|
|
137 |
+ DoubleGreaterThan = SparcAssembler::DoubleConditionG,
|
|
138 |
+ DoubleGreaterThanOrEqual = SparcAssembler::DoubleConditionGE,
|
|
139 |
+ DoubleLessThan = SparcAssembler::DoubleConditionL,
|
|
140 |
+ DoubleLessThanOrEqual = SparcAssembler::DoubleConditionLE,
|
|
141 |
+ // If either operand is NaN, these conditions always evaluate to true.
|
|
142 |
+ DoubleEqualOrUnordered = SparcAssembler::DoubleConditionUE,
|
|
143 |
+ DoubleNotEqualOrUnordered = SparcAssembler::DoubleConditionNE,
|
|
144 |
+ DoubleGreaterThanOrUnordered = SparcAssembler::DoubleConditionUG,
|
|
145 |
+ DoubleGreaterThanOrEqualOrUnordered = SparcAssembler::DoubleConditionUGE,
|
|
146 |
+ DoubleLessThanOrUnordered = SparcAssembler::DoubleConditionUL,
|
|
147 |
+ DoubleLessThanOrEqualOrUnordered = SparcAssembler::DoubleConditionULE
|
|
148 |
+ };
|
|
149 |
+
|
|
150 |
+ static const RegisterID stackPointerRegister = SparcRegisters::sp;
|
|
151 |
+
|
|
152 |
+ static const Scale ScalePtr = TimesFour;
|
|
153 |
+ static const unsigned int TotalRegisters = 32;
|
|
154 |
+
|
|
155 |
+ void add32(RegisterID src, RegisterID dest)
|
|
156 |
+ {
|
|
157 |
+ m_assembler.addcc_r(dest, src, dest);
|
|
158 |
+ }
|
|
159 |
+
|
|
160 |
+ void add32(Imm32 imm, Address address)
|
|
161 |
+ {
|
|
162 |
+ load32(address, SparcRegisters::g2);
|
|
163 |
+ add32(imm, SparcRegisters::g2);
|
|
164 |
+ store32(SparcRegisters::g2, address);
|
|
165 |
+ }
|
|
166 |
+
|
|
167 |
+ void add32(Imm32 imm, RegisterID dest)
|
|
168 |
+ {
|
|
169 |
+ if (m_assembler.isimm13(imm.m_value))
|
|
170 |
+ m_assembler.addcc_imm(dest, imm.m_value, dest);
|
|
171 |
+ else {
|
|
172 |
+ m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
|
|
173 |
+ m_assembler.addcc_r(dest, SparcRegisters::g3, dest);
|
|
174 |
+ }
|
|
175 |
+ }
|
|
176 |
+
|
|
177 |
+ void add32(Address src, RegisterID dest)
|
|
178 |
+ {
|
|
179 |
+ load32(src, SparcRegisters::g2);
|
|
180 |
+ m_assembler.addcc_r(dest, SparcRegisters::g2, dest);
|
|
181 |
+ }
|
|
182 |
+
|
|
183 |
+ void and32(Address src, RegisterID dest)
|
|
184 |
+ {
|
|
185 |
+ load32(src, SparcRegisters::g2);
|
|
186 |
+ m_assembler.andcc_r(dest, SparcRegisters::g2, dest);
|
|
187 |
+ }
|
|
188 |
+
|
|
189 |
+ void add32(Imm32 imm, RegisterID src, RegisterID dest)
|
|
190 |
+ {
|
|
191 |
+ if (m_assembler.isimm13(imm.m_value))
|
|
192 |
+ m_assembler.addcc_imm(src, imm.m_value, dest);
|
|
193 |
+ else {
|
|
194 |
+ m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
|
|
195 |
+ m_assembler.addcc_r(src, SparcRegisters::g3, dest);
|
|
196 |
+ }
|
|
197 |
+ }
|
|
198 |
+
|
|
199 |
+ void and32(RegisterID src, RegisterID dest)
|
|
200 |
+ {
|
|
201 |
+ m_assembler.andcc_r(dest, src, dest);
|
|
202 |
+ }
|
|
203 |
+
|
|
204 |
+ void and32(Imm32 imm, RegisterID dest)
|
|
205 |
+ {
|
|
206 |
+ if (m_assembler.isimm13(imm.m_value))
|
|
207 |
+ m_assembler.andcc_imm(dest, imm.m_value, dest);
|
|
208 |
+ else {
|
|
209 |
+ m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
|
|
210 |
+ m_assembler.andcc_r(dest, SparcRegisters::g3, dest);
|
|
211 |
+ }
|
|
212 |
+ }
|
|
213 |
+
|
|
214 |
+
|
|
215 |
+ void lshift32(RegisterID shift_amount, RegisterID dest)
|
|
216 |
+ {
|
|
217 |
+ m_assembler.sll_r(dest, shift_amount, dest);
|
|
218 |
+ }
|
|
219 |
+
|
|
220 |
+ void lshift32(Imm32 imm, RegisterID dest)
|
|
221 |
+ {
|
|
222 |
+ // No need to check if imm.m_value.
|
|
223 |
+ // The last 5 bit of imm.m_value will be used anyway.
|
|
224 |
+ m_assembler.sll_imm(dest, imm.m_value, dest);
|
|
225 |
+ }
|
|
226 |
+
|
|
227 |
+ void mul32(RegisterID src, RegisterID dest)
|
|
228 |
+ {
|
|
229 |
+ m_assembler.smulcc_r(dest, src, dest);
|
|
230 |
+ }
|
|
231 |
+
|
|
232 |
+ void mul32(Imm32 imm, RegisterID src, RegisterID dest)
|
|
233 |
+ {
|
|
234 |
+ if (m_assembler.isimm13(imm.m_value))
|
|
235 |
+ m_assembler.smulcc_imm(dest, imm.m_value, dest);
|
|
236 |
+ else {
|
|
237 |
+ m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
|
|
238 |
+ m_assembler.smulcc_r(SparcRegisters::g3, dest, dest);
|
|
239 |
+ }
|
|
240 |
+ }
|
|
241 |
+
|
|
242 |
+ void neg32(RegisterID srcDest)
|
|
243 |
+ {
|
|
244 |
+ m_assembler.subcc_r(SparcRegisters::g0, srcDest, srcDest);
|
|
245 |
+ }
|
|
246 |
+
|
|
247 |
+ void not32(RegisterID dest)
|
|
248 |
+ {
|
|
249 |
+ m_assembler.xnorcc_r(dest, SparcRegisters::g0, dest);
|
|
250 |
+ }
|
|
251 |
+
|
|
252 |
+ void or32(RegisterID src, RegisterID dest)
|
|
253 |
+ {
|
|
254 |
+ m_assembler.orcc_r(dest, src, dest);
|
|
255 |
+ }
|
|
256 |
+
|
|
257 |
+ void or32(Imm32 imm, RegisterID dest)
|
|
258 |
+ {
|
|
259 |
+ if (m_assembler.isimm13(imm.m_value))
|
|
260 |
+ m_assembler.orcc_imm(dest, imm.m_value, dest);
|
|
261 |
+ else {
|
|
262 |
+ m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
|
|
263 |
+ m_assembler.or_r(SparcRegisters::g3, dest, dest);
|
|
264 |
+ }
|
|
265 |
+ }
|
|
266 |
+
|
|
267 |
+
|
|
268 |
+ void or32(Address address, RegisterID dest)
|
|
269 |
+ {
|
|
270 |
+ load32(address, SparcRegisters::g2);
|
|
271 |
+ or32(SparcRegisters::g2, dest);
|
|
272 |
+ }
|
|
273 |
+
|
|
274 |
+ void rshift32(RegisterID shift_amount, RegisterID dest)
|
|
275 |
+ {
|
|
276 |
+ m_assembler.sra_r(dest, shift_amount, dest);
|
|
277 |
+ }
|
|
278 |
+
|
|
279 |
+ void rshift32(Imm32 imm, RegisterID dest)
|
|
280 |
+ {
|
|
281 |
+ // No need to check if imm.m_value.
|
|
282 |
+ // The last 5 bit of imm.m_value will be used anyway.
|
|
283 |
+ m_assembler.sra_imm(dest, imm.m_value, dest);
|
|
284 |
+ }
|
|
285 |
+
|
|
286 |
+ void urshift32(RegisterID shift_amount, RegisterID dest)
|
|
287 |
+ {
|
|
288 |
+ m_assembler.srl_r(dest, shift_amount, dest);
|
|
289 |
+ }
|
|
290 |
+
|
|
291 |
+ void urshift32(Imm32 imm, RegisterID dest)
|
|
292 |
+ {
|
|
293 |
+ // No need to check if imm.m_value.
|
|
294 |
+ // The last 5 bit of imm.m_value will be used anyway.
|
|
295 |
+ m_assembler.srl_imm(dest, imm.m_value, dest);
|
|
296 |
+ }
|
|
297 |
+
|
|
298 |
+ void sub32(RegisterID src, RegisterID dest)
|
|
299 |
+ {
|
|
300 |
+ m_assembler.subcc_r(dest, src, dest);
|
|
301 |
+ }
|
|
302 |
+
|
|
303 |
+ void sub32(Imm32 imm, RegisterID dest)
|
|
304 |
+ {
|
|
305 |
+ if (m_assembler.isimm13(imm.m_value))
|
|
306 |
+ m_assembler.subcc_imm(dest, imm.m_value, dest);
|
|
307 |
+ else {
|
|
308 |
+ m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
|
|
309 |
+ m_assembler.subcc_r(dest, SparcRegisters::g3, dest);
|
|
310 |
+ }
|
|
311 |
+ }
|
|
312 |
+
|
|
313 |
+ void sub32(Imm32 imm, Address address)
|
|
314 |
+ {
|
|
315 |
+ load32(address, SparcRegisters::g2);
|
|
316 |
+ sub32(imm, SparcRegisters::g2);
|
|
317 |
+ store32(SparcRegisters::g2, address);
|
|
318 |
+ }
|
|
319 |
+
|
|
320 |
+ void sub32(Address src, RegisterID dest)
|
|
321 |
+ {
|
|
322 |
+ load32(src, SparcRegisters::g2);
|
|
323 |
+ sub32(SparcRegisters::g2, dest);
|
|
324 |
+ }
|
|
325 |
+
|
|
326 |
+ void xor32(RegisterID src, RegisterID dest)
|
|
327 |
+ {
|
|
328 |
+ m_assembler.xorcc_r(src, dest, dest);
|
|
329 |
+ }
|
|
330 |
+
|
|
331 |
+ void xor32(Imm32 imm, RegisterID dest)
|
|
332 |
+ {
|
|
333 |
+ if (m_assembler.isimm13(imm.m_value))
|
|
334 |
+ m_assembler.xorcc_imm(dest, imm.m_value, dest);
|
|
335 |
+ else {
|
|
336 |
+ m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
|
|
337 |
+ m_assembler.xorcc_r(dest, SparcRegisters::g3, dest);
|
|
338 |
+ }
|
|
339 |
+ }
|
|
340 |
+
|
|
341 |
+ void xor32(Address src, RegisterID dest)
|
|
342 |
+ {
|
|
343 |
+ load32(src, SparcRegisters::g2);
|
|
344 |
+ xor32(SparcRegisters::g2, dest);
|
|
345 |
+ }
|
|
346 |
+
|
|
347 |
+ void load8(ImplicitAddress address, RegisterID dest)
|
|
348 |
+ {
|
|
349 |
+ if (m_assembler.isimm13(address.offset))
|
|
350 |
+ m_assembler.ldub_imm(address.base, address.offset, dest);
|
|
351 |
+ else {
|
|
352 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
353 |
+ m_assembler.ldub_r(address.base, SparcRegisters::g3, dest);
|
|
354 |
+ }
|
|
355 |
+ }
|
|
356 |
+
|
|
357 |
+ void load32(ImplicitAddress address, RegisterID dest)
|
|
358 |
+ {
|
|
359 |
+ if (m_assembler.isimm13(address.offset))
|
|
360 |
+ m_assembler.lduw_imm(address.base, address.offset, dest);
|
|
361 |
+ else {
|
|
362 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
363 |
+ m_assembler.lduw_r(address.base, SparcRegisters::g3, dest);
|
|
364 |
+ }
|
|
365 |
+ }
|
|
366 |
+
|
|
367 |
+ void load32(BaseIndex address, RegisterID dest)
|
|
368 |
+ {
|
|
369 |
+ m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
|
|
370 |
+ add32(Imm32(address.offset), SparcRegisters::g2);
|
|
371 |
+ m_assembler.lduw_r(address.base, SparcRegisters::g2, dest);
|
|
372 |
+ }
|
|
373 |
+
|
|
374 |
+ void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
|
|
375 |
+ {
|
|
376 |
+ m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
|
|
377 |
+ add32(Imm32(address.offset+3), SparcRegisters::g2);
|
|
378 |
+ m_assembler.ldub_r(address.base, SparcRegisters::g2, dest);
|
|
379 |
+ m_assembler.subcc_imm(SparcRegisters::g2, 1, SparcRegisters::g2);
|
|
380 |
+ m_assembler.ldub_r(address.base, SparcRegisters::g2, SparcRegisters::g3);
|
|
381 |
+ m_assembler.sll_imm(SparcRegisters::g3, 8, SparcRegisters::g3);
|
|
382 |
+ m_assembler.or_r(SparcRegisters::g3, dest, dest);
|
|
383 |
+ m_assembler.subcc_imm(SparcRegisters::g2, 1, SparcRegisters::g2);
|
|
384 |
+ m_assembler.ldub_r(address.base, SparcRegisters::g2, SparcRegisters::g3);
|
|
385 |
+ m_assembler.sll_imm(SparcRegisters::g3, 16, SparcRegisters::g3);
|
|
386 |
+ m_assembler.or_r(SparcRegisters::g3, dest, dest);
|
|
387 |
+ m_assembler.subcc_imm(SparcRegisters::g2, 1, SparcRegisters::g2);
|
|
388 |
+ m_assembler.ldub_r(address.base, SparcRegisters::g2, SparcRegisters::g3);
|
|
389 |
+ m_assembler.sll_imm(SparcRegisters::g3, 24, SparcRegisters::g3);
|
|
390 |
+ m_assembler.or_r(SparcRegisters::g3, dest, dest);
|
|
391 |
+ }
|
|
392 |
+
|
|
393 |
+ DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
|
|
394 |
+ {
|
|
395 |
+ DataLabel32 dataLabel(this);
|
|
396 |
+ m_assembler.move_nocheck(0, SparcRegisters::g3);
|
|
397 |
+ m_assembler.lduw_r(address.base, SparcRegisters::g3, dest);
|
|
398 |
+ return dataLabel;
|
|
399 |
+ }
|
|
400 |
+
|
|
401 |
+ DataLabel32 load64WithAddressOffsetPatch(Address address, RegisterID hi, RegisterID lo)
|
|
402 |
+ {
|
|
403 |
+ DataLabel32 dataLabel(this);
|
|
404 |
+ m_assembler.move_nocheck(0, SparcRegisters::g3);
|
|
405 |
+ m_assembler.add_imm(SparcRegisters::g3, 4, SparcRegisters::g2);
|
|
406 |
+ m_assembler.lduw_r(address.base, SparcRegisters::g3, hi);
|
|
407 |
+ m_assembler.lduw_r(address.base, SparcRegisters::g2, lo);
|
|
408 |
+ return dataLabel;
|
|
409 |
+ }
|
|
410 |
+
|
|
411 |
+ Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
|
|
412 |
+ {
|
|
413 |
+ Label label(this);
|
|
414 |
+ load32(address, dest);
|
|
415 |
+ return label;
|
|
416 |
+ }
|
|
417 |
+
|
|
418 |
+ void load16(BaseIndex address, RegisterID dest)
|
|
419 |
+ {
|
|
420 |
+ m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
|
|
421 |
+ add32(Imm32(address.offset), SparcRegisters::g2);
|
|
422 |
+ m_assembler.lduh_r(address.base, SparcRegisters::g2, dest);
|
|
423 |
+ }
|
|
424 |
+
|
|
425 |
+ void load16(ImplicitAddress address, RegisterID dest)
|
|
426 |
+ {
|
|
427 |
+ if (m_assembler.isimm13(address.offset))
|
|
428 |
+ m_assembler.lduh_imm(address.base, address.offset, dest);
|
|
429 |
+ else {
|
|
430 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
431 |
+ m_assembler.lduh_r(address.base, SparcRegisters::g3, dest);
|
|
432 |
+ }
|
|
433 |
+ }
|
|
434 |
+
|
|
435 |
+ void store8(RegisterID src, ImplicitAddress address)
|
|
436 |
+ {
|
|
437 |
+ if (m_assembler.isimm13(address.offset))
|
|
438 |
+ m_assembler.stb_imm(src, address.base, address.offset);
|
|
439 |
+ else {
|
|
440 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
441 |
+ m_assembler.stb_r(src, address.base, SparcRegisters::g3);
|
|
442 |
+ }
|
|
443 |
+ }
|
|
444 |
+
|
|
445 |
+ void store8(RegisterID src, BaseIndex address)
|
|
446 |
+ {
|
|
447 |
+ m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
|
|
448 |
+ add32(Imm32(address.offset), SparcRegisters::g2);
|
|
449 |
+ m_assembler.stb_r(src, address.base, SparcRegisters::g2);
|
|
450 |
+ }
|
|
451 |
+
|
|
452 |
+ void store8(Imm32 imm, ImplicitAddress address)
|
|
453 |
+ {
|
|
454 |
+ m_assembler.move_nocheck(imm.m_value, SparcRegisters::g2);
|
|
455 |
+ store8(SparcRegisters::g2, address);
|
|
456 |
+ }
|
|
457 |
+
|
|
458 |
+ void store8(Imm32 imm, BaseIndex address)
|
|
459 |
+ {
|
|
460 |
+ m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
|
|
461 |
+ add32(Imm32(address.offset), SparcRegisters::g2);
|
|
462 |
+ move(imm, SparcRegisters::g3);
|
|
463 |
+ m_assembler.stb_r(SparcRegisters::g3, SparcRegisters::g2, address.base);
|
|
464 |
+ }
|
|
465 |
+
|
|
466 |
+ void store16(RegisterID src, ImplicitAddress address)
|
|
467 |
+ {
|
|
468 |
+ if (m_assembler.isimm13(address.offset))
|
|
469 |
+ m_assembler.sth_imm(src, address.base, address.offset);
|
|
470 |
+ else {
|
|
471 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
472 |
+ m_assembler.sth_r(src, address.base, SparcRegisters::g3);
|
|
473 |
+ }
|
|
474 |
+ }
|
|
475 |
+
|
|
476 |
+ void store16(RegisterID src, BaseIndex address)
|
|
477 |
+ {
|
|
478 |
+ m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
|
|
479 |
+ add32(Imm32(address.offset), SparcRegisters::g2);
|
|
480 |
+ m_assembler.sth_r(src, address.base, SparcRegisters::g2);
|
|
481 |
+ }
|
|
482 |
+
|
|
483 |
+ void store16(Imm32 imm, ImplicitAddress address)
|
|
484 |
+ {
|
|
485 |
+ m_assembler.move_nocheck(imm.m_value, SparcRegisters::g2);
|
|
486 |
+ store16(SparcRegisters::g2, address);
|
|
487 |
+ }
|
|
488 |
+
|
|
489 |
+ void store16(Imm32 imm, BaseIndex address)
|
|
490 |
+ {
|
|
491 |
+ m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
|
|
492 |
+ add32(Imm32(address.offset), SparcRegisters::g2);
|
|
493 |
+ move(imm, SparcRegisters::g3);
|
|
494 |
+ m_assembler.sth_r(SparcRegisters::g3, SparcRegisters::g2, address.base);
|
|
495 |
+ }
|
|
496 |
+
|
|
497 |
+ void load8ZeroExtend(BaseIndex address, RegisterID dest)
|
|
498 |
+ {
|
|
499 |
+ m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
|
|
500 |
+ add32(Imm32(address.offset), SparcRegisters::g2);
|
|
501 |
+ m_assembler.ldub_r(address.base, SparcRegisters::g2, dest);
|
|
502 |
+ }
|
|
503 |
+
|
|
504 |
+ void load8ZeroExtend(Address address, RegisterID dest)
|
|
505 |
+ {
|
|
506 |
+ if (m_assembler.isimm13(address.offset))
|
|
507 |
+ m_assembler.ldub_imm(address.base, address.offset, dest);
|
|
508 |
+ else {
|
|
509 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
510 |
+ m_assembler.ldub_r(address.base, SparcRegisters::g3, dest);
|
|
511 |
+ }
|
|
512 |
+ }
|
|
513 |
+
|
|
514 |
+ void load8SignExtend(BaseIndex address, RegisterID dest)
|
|
515 |
+ {
|
|
516 |
+ m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
|
|
517 |
+ add32(Imm32(address.offset), SparcRegisters::g2);
|
|
518 |
+ m_assembler.ldsb_r(address.base, SparcRegisters::g2, dest);
|
|
519 |
+ }
|
|
520 |
+
|
|
521 |
+ void load8SignExtend(Address address, RegisterID dest)
|
|
522 |
+ {
|
|
523 |
+ if (m_assembler.isimm13(address.offset))
|
|
524 |
+ m_assembler.ldsb_imm(address.base, address.offset, dest);
|
|
525 |
+ else {
|
|
526 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
527 |
+ m_assembler.ldsb_r(address.base, SparcRegisters::g3, dest);
|
|
528 |
+ }
|
|
529 |
+ }
|
|
530 |
+
|
|
531 |
+ void load16SignExtend(BaseIndex address, RegisterID dest)
|
|
532 |
+ {
|
|
533 |
+ m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
|
|
534 |
+ add32(Imm32(address.offset), SparcRegisters::g2);
|
|
535 |
+ m_assembler.ldsh_r(address.base, SparcRegisters::g2, dest);
|
|
536 |
+ }
|
|
537 |
+
|
|
538 |
+ void load16SignExtend(Address address, RegisterID dest)
|
|
539 |
+ {
|
|
540 |
+ if (m_assembler.isimm13(address.offset))
|
|
541 |
+ m_assembler.ldsh_imm(address.base, address.offset, dest);
|
|
542 |
+ else {
|
|
543 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
544 |
+ m_assembler.ldsh_r(address.base, SparcRegisters::g3, dest);
|
|
545 |
+ }
|
|
546 |
+ }
|
|
547 |
+
|
|
548 |
+ DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
|
|
549 |
+ {
|
|
550 |
+ DataLabel32 dataLabel(this);
|
|
551 |
+ // Since this is for patch, we don't check is offset is imm13.
|
|
552 |
+ m_assembler.move_nocheck(0, SparcRegisters::g3);
|
|
553 |
+ m_assembler.stw_r(src, address.base, SparcRegisters::g3);
|
|
554 |
+ return dataLabel;
|
|
555 |
+ }
|
|
556 |
+
|
|
557 |
+
|
|
558 |
+ DataLabel32 store64WithAddressOffsetPatch(RegisterID hi, RegisterID lo, Address address)
|
|
559 |
+ {
|
|
560 |
+ DataLabel32 dataLabel(this);
|
|
561 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
562 |
+ m_assembler.add_r(SparcRegisters::g3, address.base, SparcRegisters::g3);
|
|
563 |
+ m_assembler.stw_imm(lo, SparcRegisters::g3, 4);
|
|
564 |
+ m_assembler.stw_imm(hi, SparcRegisters::g3, 0);
|
|
565 |
+ return dataLabel;
|
|
566 |
+ }
|
|
567 |
+
|
|
568 |
+ DataLabel32 store64WithAddressOffsetPatch(Imm32 hi, RegisterID lo, Address address)
|
|
569 |
+ {
|
|
570 |
+ DataLabel32 dataLabel(this);
|
|
571 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
572 |
+ m_assembler.add_r(SparcRegisters::g3, address.base, SparcRegisters::g3);
|
|
573 |
+ m_assembler.stw_imm(lo, SparcRegisters::g3, 4);
|
|
574 |
+ move(hi, SparcRegisters::g2);
|
|
575 |
+ m_assembler.stw_imm(SparcRegisters::g2, SparcRegisters::g3, 0);
|
|
576 |
+
|
|
577 |
+ return dataLabel;
|
|
578 |
+ }
|
|
579 |
+
|
|
580 |
+ DataLabel32 store64WithAddressOffsetPatch(Imm32 hi, Imm32 lo, Address address)
|
|
581 |
+ {
|
|
582 |
+ DataLabel32 dataLabel(this);
|
|
583 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
584 |
+ m_assembler.add_r(SparcRegisters::g3, address.base, SparcRegisters::g3);
|
|
585 |
+ move(lo, SparcRegisters::g2);
|
|
586 |
+ m_assembler.stw_imm(SparcRegisters::g2, SparcRegisters::g3, 4);
|
|
587 |
+ move(hi, SparcRegisters::g2);
|
|
588 |
+ m_assembler.stw_imm(SparcRegisters::g2, SparcRegisters::g3, 0);
|
|
589 |
+
|
|
590 |
+ return dataLabel;
|
|
591 |
+ }
|
|
592 |
+
|
|
593 |
+
|
|
594 |
+ void store32(RegisterID src, ImplicitAddress address)
|
|
595 |
+ {
|
|
596 |
+ if (m_assembler.isimm13(address.offset))
|
|
597 |
+ m_assembler.stw_imm(src, address.base, address.offset);
|
|
598 |
+ else {
|
|
599 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
600 |
+ m_assembler.stw_r(src, address.base, SparcRegisters::g3);
|
|
601 |
+ }
|
|
602 |
+ }
|
|
603 |
+
|
|
604 |
+ void store32(RegisterID src, BaseIndex address)
|
|
605 |
+ {
|
|
606 |
+ m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
|
|
607 |
+ add32(Imm32(address.offset), SparcRegisters::g2);
|
|
608 |
+ m_assembler.stw_r(src, address.base, SparcRegisters::g2);
|
|
609 |
+ }
|
|
610 |
+
|
|
611 |
+ void store32(Imm32 imm, BaseIndex address)
|
|
612 |
+ {
|
|
613 |
+ m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
|
|
614 |
+ add32(Imm32(address.offset), SparcRegisters::g2);
|
|
615 |
+ move(imm, SparcRegisters::g3);
|
|
616 |
+ m_assembler.stw_r(SparcRegisters::g3, SparcRegisters::g2, address.base);
|
|
617 |
+ }
|
|
618 |
+
|
|
619 |
+ void store32(Imm32 imm, ImplicitAddress address)
|
|
620 |
+ {
|
|
621 |
+ m_assembler.move_nocheck(imm.m_value, SparcRegisters::g2);
|
|
622 |
+ store32(SparcRegisters::g2, address);
|
|
623 |
+ }
|
|
624 |
+
|
|
625 |
+ void store32(RegisterID src, void* address)
|
|
626 |
+ {
|
|
627 |
+ m_assembler.move_nocheck((int)address, SparcRegisters::g3);
|
|
628 |
+ m_assembler.stw_r(src, SparcRegisters::g0, SparcRegisters::g3);
|
|
629 |
+ }
|
|
630 |
+
|
|
631 |
+ void store32(Imm32 imm, void* address)
|
|
632 |
+ {
|
|
633 |
+ move(imm, SparcRegisters::g2);
|
|
634 |
+ store32(SparcRegisters::g2, address);
|
|
635 |
+ }
|
|
636 |
+
|
|
637 |
+ void pop(RegisterID dest)
|
|
638 |
+ {
|
|
639 |
+ m_assembler.lduw_imm(SparcRegisters::sp, 0x68, dest);
|
|
640 |
+ m_assembler.addcc_imm(SparcRegisters::sp, 4, SparcRegisters::sp);
|
|
641 |
+ }
|
|
642 |
+
|
|
643 |
+ void push(RegisterID src)
|
|
644 |
+ {
|
|
645 |
+ m_assembler.subcc_imm(SparcRegisters::sp, 4, SparcRegisters::sp);
|
|
646 |
+ m_assembler.stw_imm(src, SparcRegisters::sp, 0x68);
|
|
647 |
+ }
|
|
648 |
+
|
|
649 |
+ void push(Address address)
|
|
650 |
+ {
|
|
651 |
+ load32(address, SparcRegisters::g2);
|
|
652 |
+ push(SparcRegisters::g2);
|
|
653 |
+ }
|
|
654 |
+
|
|
655 |
+ void push(Imm32 imm)
|
|
656 |
+ {
|
|
657 |
+ move(imm, SparcRegisters::g2);
|
|
658 |
+ push(SparcRegisters::g2);
|
|
659 |
+ }
|
|
660 |
+
|
|
661 |
+ void move(Imm32 imm, RegisterID dest)
|
|
662 |
+ {
|
|
663 |
+ if (m_assembler.isimm13(imm.m_value))
|
|
664 |
+ m_assembler.or_imm(SparcRegisters::g0, imm.m_value, dest);
|
|
665 |
+ else
|
|
666 |
+ m_assembler.move_nocheck(imm.m_value, dest);
|
|
667 |
+ }
|
|
668 |
+
|
|
669 |
+ void move(RegisterID src, RegisterID dest)
|
|
670 |
+ {
|
|
671 |
+ m_assembler.or_r(src, SparcRegisters::g0, dest);
|
|
672 |
+ }
|
|
673 |
+
|
|
674 |
+ void move(ImmPtr imm, RegisterID dest)
|
|
675 |
+ {
|
|
676 |
+ move(Imm32(imm), dest);
|
|
677 |
+ }
|
|
678 |
+
|
|
679 |
+ void swap(RegisterID reg1, RegisterID reg2)
|
|
680 |
+ {
|
|
681 |
+ m_assembler.or_r(reg1, SparcRegisters::g0, SparcRegisters::g3);
|
|
682 |
+ m_assembler.or_r(reg2, SparcRegisters::g0, reg1);
|
|
683 |
+ m_assembler.or_r(SparcRegisters::g3, SparcRegisters::g0, reg2);
|
|
684 |
+ }
|
|
685 |
+
|
|
686 |
+ void signExtend32ToPtr(RegisterID src, RegisterID dest)
|
|
687 |
+ {
|
|
688 |
+ if (src != dest)
|
|
689 |
+ move(src, dest);
|
|
690 |
+ }
|
|
691 |
+
|
|
692 |
+ void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
|
|
693 |
+ {
|
|
694 |
+ if (src != dest)
|
|
695 |
+ move(src, dest);
|
|
696 |
+ }
|
|
697 |
+
|
|
698 |
+ Jump branch8(Condition cond, Address left, Imm32 right)
|
|
699 |
+ {
|
|
700 |
+ load8(left, SparcRegisters::g2);
|
|
701 |
+ return branch32(cond, SparcRegisters::g2, right);
|
|
702 |
+ }
|
|
703 |
+
|
|
704 |
+ Jump branch32_force32(Condition cond, RegisterID left, Imm32 right)
|
|
705 |
+ {
|
|
706 |
+ m_assembler.move_nocheck(right.m_value, SparcRegisters::g3);
|
|
707 |
+ m_assembler.subcc_r(left, SparcRegisters::g3, SparcRegisters::g0);
|
|
708 |
+ return Jump(m_assembler.branch(SparcCondition(cond)));
|
|
709 |
+ }
|
|
710 |
+
|
|
711 |
+ Jump branch32FixedLength(Condition cond, RegisterID left, Imm32 right)
|
|
712 |
+ {
|
|
713 |
+ m_assembler.move_nocheck(right.m_value, SparcRegisters::g2);
|
|
714 |
+ return branch32(cond, left, SparcRegisters::g2);
|
|
715 |
+ }
|
|
716 |
+
|
|
717 |
+ Jump branch32WithPatch(Condition cond, RegisterID left, Imm32 right, DataLabel32 &dataLabel)
|
|
718 |
+ {
|
|
719 |
+ // Always use move_nocheck, since the value is to be patched.
|
|
720 |
+ dataLabel = DataLabel32(this);
|
|
721 |
+ m_assembler.move_nocheck(right.m_value, SparcRegisters::g3);
|
|
722 |
+ m_assembler.subcc_r(left, SparcRegisters::g3, SparcRegisters::g0);
|
|
723 |
+ return Jump(m_assembler.branch(SparcCondition(cond)));
|
|
724 |
+ }
|
|
725 |
+
|
|
726 |
+ Jump branch32(Condition cond, RegisterID left, RegisterID right)
|
|
727 |
+ {
|
|
728 |
+ m_assembler.subcc_r(left, right, SparcRegisters::g0);
|
|
729 |
+ return Jump(m_assembler.branch(SparcCondition(cond)));
|
|
730 |
+ }
|
|
731 |
+
|
|
732 |
+ Jump branch32(Condition cond, RegisterID left, Imm32 right)
|
|
733 |
+ {
|
|
734 |
+ if (m_assembler.isimm13(right.m_value))
|
|
735 |
+ m_assembler.subcc_imm(left, right.m_value, SparcRegisters::g0);
|
|
736 |
+ else {
|
|
737 |
+ m_assembler.move_nocheck(right.m_value, SparcRegisters::g3);
|
|
738 |
+ m_assembler.subcc_r(left, SparcRegisters::g3, SparcRegisters::g0);
|
|
739 |
+ }
|
|
740 |
+ return Jump(m_assembler.branch(SparcCondition(cond)));
|
|
741 |
+ }
|
|
742 |
+
|
|
743 |
+ Jump branch32(Condition cond, RegisterID left, Address right)
|
|
744 |
+ {
|
|
745 |
+ load32(right, SparcRegisters::g2);
|
|
746 |
+ return branch32(cond, left, SparcRegisters::g2);
|
|
747 |
+ }
|
|
748 |
+
|
|
749 |
+ Jump branch32(Condition cond, Address left, RegisterID right)
|
|
750 |
+ {
|
|
751 |
+ load32(left, SparcRegisters::g2);
|
|
752 |
+ return branch32(cond, SparcRegisters::g2, right);
|
|
753 |
+ }
|
|
754 |
+
|
|
755 |
+ Jump branch32(Condition cond, Address left, Imm32 right)
|
|
756 |
+ {
|
|
757 |
+ load32(left, SparcRegisters::g2);
|
|
758 |
+ return branch32(cond, SparcRegisters::g2, right);
|
|
759 |
+ }
|
|
760 |
+
|
|
761 |
+ Jump branch32(Condition cond, BaseIndex left, Imm32 right)
|
|
762 |
+ {
|
|
763 |
+
|
|
764 |
+ load32(left, SparcRegisters::g2);
|
|
765 |
+ return branch32(cond, SparcRegisters::g2, right);
|
|
766 |
+ }
|
|
767 |
+
|
|
768 |
+ Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
|
|
769 |
+ {
|
|
770 |
+ load32WithUnalignedHalfWords(left, SparcRegisters::g4);
|
|
771 |
+ return branch32(cond, SparcRegisters::g4, right);
|
|
772 |
+ }
|
|
773 |
+
|
|
774 |
+ Jump branch16(Condition cond, BaseIndex left, RegisterID right)
|
|
775 |
+ {
|
|
776 |
+ (void)(cond);
|
|
777 |
+ (void)(left);
|
|
778 |
+ (void)(right);
|
|
779 |
+ ASSERT_NOT_REACHED();
|
|
780 |
+ return jump();
|
|
781 |
+ }
|
|
782 |
+
|
|
783 |
+ Jump branch16(Condition cond, BaseIndex left, Imm32 right)
|
|
784 |
+ {
|
|
785 |
+ load16(left, SparcRegisters::g3);
|
|
786 |
+ move(right, SparcRegisters::g2);
|
|
787 |
+ m_assembler.subcc_r(SparcRegisters::g3, SparcRegisters::g2, SparcRegisters::g0);
|
|
788 |
+ return Jump(m_assembler.branch(SparcCondition(cond)));
|
|
789 |
+ }
|
|
790 |
+
|
|
791 |
+ Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1))
|
|
792 |
+ {
|
|
793 |
+ load8(address, SparcRegisters::g2);
|
|
794 |
+ return branchTest32(cond, SparcRegisters::g2, mask);
|
|
795 |
+ }
|
|
796 |
+
|
|
797 |
+ Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
|
|
798 |
+ {
|
|
799 |
+ m_assembler.andcc_r(reg, mask, SparcRegisters::g0);
|
|
800 |
+ return Jump(m_assembler.branch(SparcCondition(cond)));
|
|
801 |
+ }
|
|
802 |
+
|
|
803 |
+ Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
|
|
804 |
+ {
|
|
805 |
+ if (m_assembler.isimm13(mask.m_value))
|
|
806 |
+ m_assembler.andcc_imm(reg, mask.m_value, SparcRegisters::g0);
|
|
807 |
+ else {
|
|
808 |
+ m_assembler.move_nocheck(mask.m_value, SparcRegisters::g3);
|
|
809 |
+ m_assembler.andcc_r(reg, SparcRegisters::g3, SparcRegisters::g0);
|
|
810 |
+ }
|
|
811 |
+ return Jump(m_assembler.branch(SparcCondition(cond)));
|
|
812 |
+ }
|
|
813 |
+
|
|
814 |
+ Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
|
|
815 |
+ {
|
|
816 |
+ load32(address, SparcRegisters::g2);
|
|
817 |
+ return branchTest32(cond, SparcRegisters::g2, mask);
|
|
818 |
+ }
|
|
819 |
+
|
|
820 |
+ Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
|
|
821 |
+ {
|
|
822 |
+ // FIXME. branchTest32 only used by PolyIC.
|
|
823 |
+ // PolyIC is not enabled for sparc now.
|
|
824 |
+ ASSERT(0);
|
|
825 |
+ return jump();
|
|
826 |
+ }
|
|
827 |
+
|
|
828 |
+ Jump jump()
|
|
829 |
+ {
|
|
830 |
+ return Jump(m_assembler.jmp());
|
|
831 |
+ }
|
|
832 |
+
|
|
833 |
+ void jump(RegisterID target)
|
|
834 |
+ {
|
|
835 |
+ m_assembler.jmpl_r(SparcRegisters::g0, target, SparcRegisters::g0);
|
|
836 |
+ m_assembler.nop();
|
|
837 |
+ }
|
|
838 |
+
|
|
839 |
+ void jump(Address address)
|
|
840 |
+ {
|
|
841 |
+ load32(address, SparcRegisters::g2);
|
|
842 |
+ m_assembler.jmpl_r(SparcRegisters::g2, SparcRegisters::g0, SparcRegisters::g0);
|
|
843 |
+ m_assembler.nop();
|
|
844 |
+ }
|
|
845 |
+
|
|
846 |
+ void jump(BaseIndex address)
|
|
847 |
+ {
|
|
848 |
+ load32(address, SparcRegisters::g2);
|
|
849 |
+ m_assembler.jmpl_r(SparcRegisters::g2, SparcRegisters::g0, SparcRegisters::g0);
|
|
850 |
+ m_assembler.nop();
|
|
851 |
+ }
|
|
852 |
+
|
|
853 |
+ Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
|
|
854 |
+ {
|
|
855 |
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
|
|
856 |
+ m_assembler.addcc_r(src, dest, dest);
|
|
857 |
+ return Jump(m_assembler.branch(SparcCondition(cond)));
|
|
858 |
+ }
|
|
859 |
+
|
|
860 |
+ Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
|
|
861 |
+ {
|
|
862 |
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
|
|
863 |
+ if (m_assembler.isimm13(imm.m_value))
|
|
864 |
+ m_assembler.addcc_imm(dest, imm.m_value, dest);
|
|
865 |
+ else {
|
|
866 |
+ m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
|
|
867 |
+ m_assembler.addcc_r(dest, SparcRegisters::g3, dest);
|
|
868 |
+ }
|
|
869 |
+ return Jump(m_assembler.branch(SparcCondition(cond)));
|
|
870 |
+ }
|
|
871 |
+
|
|
872 |
+ Jump branchAdd32(Condition cond, Address src, RegisterID dest)
|
|
873 |
+ {
|
|
874 |
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
|
|
875 |
+ load32(src, SparcRegisters::g2);
|
|
876 |
+ return branchAdd32(cond, SparcRegisters::g2, dest);
|
|
877 |
+ }
|
|
878 |
+
|
|
879 |
+ void mull32(RegisterID src1, RegisterID src2, RegisterID dest)
|
|
880 |
+ {
|
|
881 |
+ m_assembler.smulcc_r(src1, src2, dest);
|
|
882 |
+ }
|
|
883 |
+
|
|
884 |
+ Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
|
|
885 |
+ {
|
|
886 |
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
|
|
887 |
+ m_assembler.smulcc_r(src, dest, dest);
|
|
888 |
+ if (cond == Overflow) {
|
|
889 |
+ m_assembler.rdy(SparcRegisters::g2);
|
|
890 |
+ m_assembler.sra_imm(dest, 31, SparcRegisters::g3);
|
|
891 |
+ m_assembler.subcc_r(SparcRegisters::g2, SparcRegisters::g3, SparcRegisters::g2);
|
|
892 |
+ cond = NotEqual;
|
|
893 |
+ }
|
|
894 |
+ return Jump(m_assembler.branch(SparcCondition(cond)));
|
|
895 |
+ }
|
|
896 |
+
|
|
897 |
+ Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
|
|
898 |
+ {
|
|
899 |
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
|
|
900 |
+ if (m_assembler.isimm13(imm.m_value))
|
|
901 |
+ m_assembler.smulcc_imm(src, imm.m_value, dest);
|
|
902 |
+ else {
|
|
903 |
+ m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
|
|
904 |
+ m_assembler.smulcc_r(src, SparcRegisters::g3, dest);
|
|
905 |
+ }
|
|
906 |
+ if (cond == Overflow) {
|
|
907 |
+ m_assembler.rdy(SparcRegisters::g2);
|
|
908 |
+ m_assembler.sra_imm(dest, 31, SparcRegisters::g3);
|
|
909 |
+ m_assembler.subcc_r(SparcRegisters::g2, SparcRegisters::g3, SparcRegisters::g2);
|
|
910 |
+ cond = NotEqual;
|
|
911 |
+ }
|
|
912 |
+ return Jump(m_assembler.branch(SparcCondition(cond)));
|
|
913 |
+ }
|
|
914 |
+
|
|
915 |
+ Jump branchMul32(Condition cond, Address src, RegisterID dest)
|
|
916 |
+ {
|
|
917 |
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
|
|
918 |
+ load32(src, SparcRegisters::g2);
|
|
919 |
+ return branchMul32(cond, SparcRegisters::g2, dest);
|
|
920 |
+ }
|
|
921 |
+
|
|
922 |
+ Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
|
|
923 |
+ {
|
|
924 |
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
|
|
925 |
+ m_assembler.subcc_r(dest, src, dest);
|
|
926 |
+ return Jump(m_assembler.branch(SparcCondition(cond)));
|
|
927 |
+ }
|
|
928 |
+
|
|
929 |
+ Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
|
|
930 |
+ {
|
|
931 |
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
|
|
932 |
+ sub32(imm, dest);
|
|
933 |
+ return Jump(m_assembler.branch(SparcCondition(cond)));
|
|
934 |
+ }
|
|
935 |
+
|
|
936 |
+ Jump branchSub32(Condition cond, Address src, RegisterID dest)
|
|
937 |
+ {
|
|
938 |
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
|
|
939 |
+ load32(src, SparcRegisters::g2);
|
|
940 |
+ return branchSub32(cond, SparcRegisters::g2, dest);
|
|
941 |
+ }
|
|
942 |
+
|
|
943 |
+ Jump branchSub32(Condition cond, Imm32 imm, Address dest)
|
|
944 |
+ {
|
|
945 |
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
|
|
946 |
+ sub32(imm, dest);
|
|
947 |
+ return Jump(m_assembler.branch(SparcCondition(cond)));
|
|
948 |
+ }
|
|
949 |
+
|
|
950 |
+ Jump branchNeg32(Condition cond, RegisterID srcDest)
|
|
951 |
+ {
|
|
952 |
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
|
|
953 |
+ neg32(srcDest);
|
|
954 |
+ return Jump(m_assembler.branch(SparcCondition(cond)));
|
|
955 |
+ }
|
|
956 |
+
|
|
957 |
+ Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
|
|
958 |
+ {
|
|
959 |
+ ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
|
|
960 |
+ m_assembler.orcc_r(src, dest, dest);
|
|
961 |
+ return Jump(m_assembler.branch(SparcCondition(cond)));
|
|
962 |
+ }
|
|
963 |
+
|
|
964 |
+ void breakpoint()
|
|
965 |
+ {
|
|
966 |
+ m_assembler.ta_imm(8);
|
|
967 |
+ }
|
|
968 |
+
|
|
969 |
+ Call nearCall()
|
|
970 |
+ {
|
|
971 |
+ return Call(m_assembler.call(), Call::LinkableNear);
|
|
972 |
+ }
|
|
973 |
+
|
|
974 |
+ Call call(RegisterID target)
|
|
975 |
+ {
|
|
976 |
+ m_assembler.jmpl_r(target, SparcRegisters::g0, SparcRegisters::o7);
|
|
977 |
+ m_assembler.nop();
|
|
978 |
+ JmpSrc jmpSrc;
|
|
979 |
+ return Call(jmpSrc, Call::None);
|
|
980 |
+ }
|
|
981 |
+
|
|
982 |
+ void call(Address address)
|
|
983 |
+ {
|
|
984 |
+ if (m_assembler.isimm13(address.offset)) {
|
|
985 |
+ m_assembler.jmpl_imm(address.base, address.offset, SparcRegisters::o7);
|
|
986 |
+ m_assembler.nop();
|
|
987 |
+ } else {
|
|
988 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
989 |
+ m_assembler.jmpl_r(address.base, SparcRegisters::g3, SparcRegisters::o7);
|
|
990 |
+ m_assembler.nop();
|
|
991 |
+ }
|
|
992 |
+ }
|
|
993 |
+
|
|
994 |
+ void ret()
|
|
995 |
+ {
|
|
996 |
+ m_assembler.jmpl_imm(SparcRegisters::i7, 8, SparcRegisters::g0);
|
|
997 |
+ m_assembler.nop();
|
|
998 |
+ }
|
|
999 |
+
|
|
1000 |
+ void ret_and_restore()
|
|
1001 |
+ {
|
|
1002 |
+ m_assembler.jmpl_imm(SparcRegisters::i7, 8, SparcRegisters::g0);
|
|
1003 |
+ m_assembler.restore_r(SparcRegisters::g0, SparcRegisters::g0, SparcRegisters::g0);
|
|
1004 |
+ }
|
|
1005 |
+
|
|
1006 |
+ void save(Imm32 size)
|
|
1007 |
+ {
|
|
1008 |
+ if (m_assembler.isimm13(size.m_value)) {
|
|
1009 |
+ m_assembler.save_imm(SparcRegisters::sp, size.m_value, SparcRegisters::sp);
|
|
1010 |
+ } else {
|
|
1011 |
+ m_assembler.move_nocheck(size.m_value, SparcRegisters::g3);
|
|
1012 |
+ m_assembler.save_r(SparcRegisters::sp, SparcRegisters::g3, SparcRegisters::sp);
|
|
1013 |
+ }
|
|
1014 |
+ }
|
|
1015 |
+
|
|
1016 |
+ void set32(Condition cond, Address left, RegisterID right, RegisterID dest)
|
|
1017 |
+ {
|
|
1018 |
+ load32(left, SparcRegisters::g2);
|
|
1019 |
+ set32(cond, SparcRegisters::g2, right, dest);
|
|
1020 |
+ }
|
|
1021 |
+
|
|
1022 |
+ void set32(Condition cond, RegisterID left, Address right, RegisterID dest)
|
|
1023 |
+ {
|
|
1024 |
+ load32(right, SparcRegisters::g2);
|
|
1025 |
+ set32(cond, left, SparcRegisters::g2, dest);
|
|
1026 |
+ }
|
|
1027 |
+
|
|
1028 |
+ void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
|
|
1029 |
+ {
|
|
1030 |
+ m_assembler.subcc_r(left, right, SparcRegisters::g0);
|
|
1031 |
+ m_assembler.or_imm(SparcRegisters::g0, 0, dest);
|
|
1032 |
+ m_assembler.movcc_imm(1, dest, SparcCondition(cond));
|
|
1033 |
+ }
|
|
1034 |
+
|
|
1035 |
+ void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
|
|
1036 |
+ {
|
|
1037 |
+ if (m_assembler.isimm13(right.m_value))
|
|
1038 |
+ m_assembler.subcc_imm(left, right.m_value, SparcRegisters::g0);
|
|
1039 |
+ else {
|
|
1040 |
+ m_assembler.move_nocheck(right.m_value, SparcRegisters::g3);
|
|
1041 |
+ m_assembler.subcc_r(left, SparcRegisters::g3, SparcRegisters::g0);
|
|
1042 |
+ }
|
|
1043 |
+ m_assembler.or_imm(SparcRegisters::g0, 0, dest);
|
|
1044 |
+ m_assembler.movcc_imm(1, dest, SparcCondition(cond));
|
|
1045 |
+ }
|
|
1046 |
+
|
|
1047 |
+ void set32(Condition cond, Address left, Imm32 right, RegisterID dest)
|
|
1048 |
+ {
|
|
1049 |
+ load32(left, SparcRegisters::g2);
|
|
1050 |
+ set32(cond, SparcRegisters::g2, right, dest);
|
|
1051 |
+ }
|
|
1052 |
+
|
|
1053 |
+ void set8(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
|
|
1054 |
+ {
|
|
1055 |
+ // Sparc does not have byte register.
|
|
1056 |
+ set32(cond, left, right, dest);
|
|
1057 |
+ }
|
|
1058 |
+
|
|
1059 |
+ void set8(Condition cond, Address left, RegisterID right, RegisterID dest)
|
|
1060 |
+ {
|
|
1061 |
+ // Sparc doesn't have byte registers
|
|
1062 |
+ load32(left, SparcRegisters::g2);
|
|
1063 |
+ set32(cond, SparcRegisters::g2, right, dest);
|
|
1064 |
+ }
|
|
1065 |
+
|
|
1066 |
+ void set8(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
|
|
1067 |
+ {
|
|
1068 |
+ // Sparc does not have byte register.
|
|
1069 |
+ set32(cond, left, right, dest);
|
|
1070 |
+ }
|
|
1071 |
+
|
|
1072 |
+ void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
|
|
1073 |
+ {
|
|
1074 |
+ load32(address, SparcRegisters::g2);
|
|
1075 |
+ if (m_assembler.isimm13(mask.m_value))
|
|
1076 |
+ m_assembler.andcc_imm(SparcRegisters::g2, mask.m_value, SparcRegisters::g0);
|
|
1077 |
+ else {
|
|
1078 |
+ m_assembler.move_nocheck(mask.m_value, SparcRegisters::g3);
|
|
1079 |
+ m_assembler.andcc_r(SparcRegisters::g3, SparcRegisters::g2, SparcRegisters::g0);
|
|
1080 |
+ }
|
|
1081 |
+ m_assembler.or_imm(SparcRegisters::g0, 0, dest);
|
|
1082 |
+ m_assembler.movcc_imm(1, dest, SparcCondition(cond));
|
|
1083 |
+ }
|
|
1084 |
+
|
|
1085 |
+ void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest)
|
|
1086 |
+ {
|
|
1087 |
+ // Sparc does not have byte register.
|
|
1088 |
+ setTest32(cond, address, mask, dest);
|
|
1089 |
+ }
|
|
1090 |
+
|
|
1091 |
+ void lea(Address address, RegisterID dest)
|
|
1092 |
+ {
|
|
1093 |
+ if (m_assembler.isimm13(address.offset))
|
|
1094 |
+ m_assembler.add_imm(address.base, address.offset, dest);
|
|
1095 |
+ else {
|
|
1096 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
1097 |
+ m_assembler.add_r(address.base, SparcRegisters::g3, dest);
|
|
1098 |
+ }
|
|
1099 |
+ }
|
|
1100 |
+
|
|
1101 |
+ void lea(BaseIndex address, RegisterID dest)
|
|
1102 |
+ {
|
|
1103 |
+ // lea only used by PolyIC.
|
|
1104 |
+ // PolyIC is not enabled for sparc now.
|
|
1105 |
+ ASSERT(0);
|
|
1106 |
+ }
|
|
1107 |
+
|
|
1108 |
+ void add32(Imm32 imm, AbsoluteAddress address)
|
|
1109 |
+ {
|
|
1110 |
+ load32(address.m_ptr, SparcRegisters::g2);
|
|
1111 |
+ add32(imm, SparcRegisters::g2);
|
|
1112 |
+ store32(SparcRegisters::g2, address.m_ptr);
|
|
1113 |
+ }
|
|
1114 |
+
|
|
1115 |
+ void sub32(Imm32 imm, AbsoluteAddress address)
|
|
1116 |
+ {
|
|
1117 |
+ load32(address.m_ptr, SparcRegisters::g2);
|
|
1118 |
+ sub32(imm, SparcRegisters::g2);
|
|
1119 |
+ store32(SparcRegisters::g2, address.m_ptr);
|
|
1120 |
+ }
|
|
1121 |
+
|
|
1122 |
+ void load32(void* address, RegisterID dest)
|
|
1123 |
+ {
|
|
1124 |
+ m_assembler.move_nocheck((int)address, SparcRegisters::g3);
|
|
1125 |
+ m_assembler.lduw_r(SparcRegisters::g3, SparcRegisters::g0, dest);
|
|
1126 |
+ }
|
|
1127 |
+
|
|
1128 |
+ Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
|
|
1129 |
+ {
|
|
1130 |
+ load32(left.m_ptr, SparcRegisters::g2);
|
|
1131 |
+ return branch32(cond, SparcRegisters::g2, right);
|
|
1132 |
+ }
|
|
1133 |
+
|
|
1134 |
+ Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
|
|
1135 |
+ {
|
|
1136 |
+ load32(left.m_ptr, SparcRegisters::g2);
|
|
1137 |
+ return branch32(cond, SparcRegisters::g2, right);
|
|
1138 |
+ }
|
|
1139 |
+
|
|
1140 |
+ Call call()
|
|
1141 |
+ {
|
|
1142 |
+ m_assembler.rdpc(SparcRegisters::g2);
|
|
1143 |
+ m_assembler.add_imm(SparcRegisters::g2, 32, SparcRegisters::g2);
|
|
1144 |
+ m_assembler.stw_imm(SparcRegisters::g2, SparcRegisters::fp, -8);
|
|
1145 |
+ Call cl = Call(m_assembler.call(), Call::Linkable);
|
|
1146 |
+ m_assembler.lduw_imm(SparcRegisters::fp, -8, SparcRegisters::g2);
|
|
1147 |
+ m_assembler.jmpl_imm(SparcRegisters::g2, 0, SparcRegisters::g0);
|
|
1148 |
+ m_assembler.nop();
|
|
1149 |
+ return cl;
|
|
1150 |
+ }
|
|
1151 |
+
|
|
1152 |
+ Call tailRecursiveCall()
|
|
1153 |
+ {
|
|
1154 |
+ return Call::fromTailJump(jump());
|
|
1155 |
+ }
|
|
1156 |
+
|
|
1157 |
+ Call makeTailRecursiveCall(Jump oldJump)
|
|
1158 |
+ {
|
|
1159 |
+ return Call::fromTailJump(oldJump);
|
|
1160 |
+ }
|
|
1161 |
+
|
|
1162 |
+ DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
|
|
1163 |
+ {
|
|
1164 |
+ DataLabelPtr dataLabel(this);
|
|
1165 |
+ Imm32 imm = Imm32(initialValue);
|
|
1166 |
+ m_assembler.move_nocheck(imm.m_value, dest);
|
|
1167 |
+ return dataLabel;
|
|
1168 |
+ }
|
|
1169 |
+
|
|
1170 |
+ DataLabel32 moveWithPatch(Imm32 initialValue, RegisterID dest)
|
|
1171 |
+ {
|
|
1172 |
+ DataLabel32 dataLabel(this);
|
|
1173 |
+ m_assembler.move_nocheck(initialValue.m_value, dest);
|
|
1174 |
+ return dataLabel;
|
|
1175 |
+ }
|
|
1176 |
+
|
|
1177 |
+ Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
|
|
1178 |
+ {
|
|
1179 |
+ dataLabel = moveWithPatch(initialRightValue, SparcRegisters::g2);
|
|
1180 |
+ Jump jump = branch32(cond, left, SparcRegisters::g2);
|
|
1181 |
+ return jump;
|
|
1182 |
+ }
|
|
1183 |
+
|
|
1184 |
+ Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
|
|
1185 |
+ {
|
|
1186 |
+ load32(left, SparcRegisters::g2);
|
|
1187 |
+ dataLabel = moveWithPatch(initialRightValue, SparcRegisters::g3);
|
|
1188 |
+ Jump jump = branch32(cond, SparcRegisters::g3, SparcRegisters::g2);
|
|
1189 |
+ return jump;
|
|
1190 |
+ }
|
|
1191 |
+
|
|
1192 |
+ DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
|
|
1193 |
+ {
|
|
1194 |
+ DataLabelPtr dataLabel = moveWithPatch(initialValue, SparcRegisters::g2);
|
|
1195 |
+ store32(SparcRegisters::g2, address);
|
|
1196 |
+ return dataLabel;
|
|
1197 |
+ }
|
|
1198 |
+
|
|
1199 |
+ DataLabelPtr storePtrWithPatch(ImplicitAddress address)
|
|
1200 |
+ {
|
|
1201 |
+ return storePtrWithPatch(ImmPtr(0), address);
|
|
1202 |
+ }
|
|
1203 |
+
|
|
1204 |
+ // Floating point operators
|
|
1205 |
+ bool supportsFloatingPoint() const
|
|
1206 |
+ {
|
|
1207 |
+ return true;
|
|
1208 |
+ }
|
|
1209 |
+
|
|
1210 |
+ bool supportsFloatingPointTruncate() const
|
|
1211 |
+ {
|
|
1212 |
+ return true;
|
|
1213 |
+ }
|
|
1214 |
+
|
|
1215 |
+ bool supportsFloatingPointSqrt() const
|
|
1216 |
+ {
|
|
1217 |
+ return true;
|
|
1218 |
+ }
|
|
1219 |
+
|
|
1220 |
+ void moveDouble(FPRegisterID src, FPRegisterID dest)
|
|
1221 |
+ {
|
|
1222 |
+ m_assembler.fmovd_r(src, dest);
|
|
1223 |
+ }
|
|
1224 |
+
|
|
1225 |
+ void loadFloat(BaseIndex address, FPRegisterID dest)
|
|
1226 |
+ {
|
|
1227 |
+ m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
|
|
1228 |
+ add32(Imm32(address.offset), SparcRegisters::g2);
|
|
1229 |
+ m_assembler.ldf_r(address.base, SparcRegisters::g2, dest);
|
|
1230 |
+ m_assembler.fstod_r(dest, dest);
|
|
1231 |
+ }
|
|
1232 |
+
|
|
1233 |
+ void loadFloat(ImplicitAddress address, FPRegisterID dest)
|
|
1234 |
+ {
|
|
1235 |
+ if (m_assembler.isimm13(address.offset))
|
|
1236 |
+ m_assembler.ldf_imm(address.base, address.offset, dest);
|
|
1237 |
+ else {
|
|
1238 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
1239 |
+ m_assembler.ldf_r(address.base, SparcRegisters::g3, dest);
|
|
1240 |
+ }
|
|
1241 |
+ m_assembler.fstod_r(dest, dest);
|
|
1242 |
+ }
|
|
1243 |
+
|
|
1244 |
+ void loadFloat(const void* address, FPRegisterID dest)
|
|
1245 |
+ {
|
|
1246 |
+ m_assembler.move_nocheck((int)address, SparcRegisters::g3);
|
|
1247 |
+ m_assembler.ldf_r(SparcRegisters::g3, SparcRegisters::g0, dest);
|
|
1248 |
+ m_assembler.fstod_r(dest, dest);
|
|
1249 |
+ }
|
|
1250 |
+
|
|
1251 |
+ void loadDouble(BaseIndex address, FPRegisterID dest)
|
|
1252 |
+ {
|
|
1253 |
+ m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
|
|
1254 |
+ add32(Imm32(address.offset), SparcRegisters::g2);
|
|
1255 |
+ m_assembler.ldf_r(address.base, SparcRegisters::g2, dest);
|
|
1256 |
+ m_assembler.add_imm(SparcRegisters::g2, 4, SparcRegisters::g2);
|
|
1257 |
+ m_assembler.ldf_r(address.base, SparcRegisters::g2, dest + 1);
|
|
1258 |
+ }
|
|
1259 |
+
|
|
1260 |
+ void loadDouble(ImplicitAddress address, FPRegisterID dest)
|
|
1261 |
+ {
|
|
1262 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
1263 |
+ m_assembler.ldf_r(address.base, SparcRegisters::g3, dest);
|
|
1264 |
+ m_assembler.add_imm(SparcRegisters::g3, 4, SparcRegisters::g3);
|
|
1265 |
+ m_assembler.ldf_r(address.base, SparcRegisters::g3, dest + 1);
|
|
1266 |
+ }
|
|
1267 |
+
|
|
1268 |
+ DataLabelPtr loadDouble(const void* address, FPRegisterID dest)
|
|
1269 |
+ {
|
|
1270 |
+ DataLabelPtr dataLabel(this);
|
|
1271 |
+ m_assembler.move_nocheck((int)address, SparcRegisters::g3);
|
|
1272 |
+ m_assembler.ldf_imm(SparcRegisters::g3, 0, dest);
|
|
1273 |
+ m_assembler.ldf_imm(SparcRegisters::g3, 4, dest + 1);
|
|
1274 |
+ return dataLabel;
|
|
1275 |
+ }
|
|
1276 |
+
|
|
1277 |
+ void storeFloat(FPRegisterID src, BaseIndex address)
|
|
1278 |
+ {
|
|
1279 |
+ m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
|
|
1280 |
+ add32(Imm32(address.offset), SparcRegisters::g2);
|
|
1281 |
+ m_assembler.stf_r(src, address.base, SparcRegisters::g2);
|
|
1282 |
+ }
|
|
1283 |
+
|
|
1284 |
+ void storeFloat(FPRegisterID src, ImplicitAddress address)
|
|
1285 |
+ {
|
|
1286 |
+ if (m_assembler.isimm13(address.offset))
|
|
1287 |
+ m_assembler.stf_imm(src, address.base, address.offset);
|
|
1288 |
+ else {
|
|
1289 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
1290 |
+ m_assembler.stf_r(src, address.base, SparcRegisters::g3);
|
|
1291 |
+ }
|
|
1292 |
+ }
|
|
1293 |
+
|
|
1294 |
+ void storeFloat(ImmDouble imm, Address address)
|
|
1295 |
+ {
|
|
1296 |
+ union {
|
|
1297 |
+ float f;
|
|
1298 |
+ uint32 u32;
|
|
1299 |
+ } u;
|
|
1300 |
+ u.f = imm.u.d;
|
|
1301 |
+ store32(Imm32(u.u32), address);
|
|
1302 |
+ }
|
|
1303 |
+
|
|
1304 |
+ void storeFloat(ImmDouble imm, BaseIndex address)
|
|
1305 |
+ {
|
|
1306 |
+ union {
|
|
1307 |
+ float f;
|
|
1308 |
+ uint32 u32;
|
|
1309 |
+ } u;
|
|
1310 |
+ u.f = imm.u.d;
|
|
1311 |
+ store32(Imm32(u.u32), address);
|
|
1312 |
+ }
|
|
1313 |
+
|
|
1314 |
+ void storeDouble(FPRegisterID src, BaseIndex address)
|
|
1315 |
+ {
|
|
1316 |
+ m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
|
|
1317 |
+ add32(Imm32(address.offset), SparcRegisters::g2);
|
|
1318 |
+ m_assembler.stf_r(src, address.base, SparcRegisters::g2);
|
|
1319 |
+ m_assembler.add_imm(SparcRegisters::g2, 4, SparcRegisters::g2);
|
|
1320 |
+ m_assembler.stf_r(src + 1, address.base, SparcRegisters::g2);
|
|
1321 |
+ }
|
|
1322 |
+
|
|
1323 |
+ void storeDouble(FPRegisterID src, ImplicitAddress address)
|
|
1324 |
+ {
|
|
1325 |
+ if (m_assembler.isimm13(address.offset + 4)) {
|
|
1326 |
+ m_assembler.stf_imm(src, address.base, address.offset);
|
|
1327 |
+ m_assembler.stf_imm(src + 1, address.base, address.offset + 4);
|
|
1328 |
+ } else {
|
|
1329 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
1330 |
+ m_assembler.stf_r(src, address.base, SparcRegisters::g3);
|
|
1331 |
+ m_assembler.add_imm(SparcRegisters::g3, 4, SparcRegisters::g3);
|
|
1332 |
+ m_assembler.stf_r(src + 1, address.base, SparcRegisters::g3);
|
|
1333 |
+ }
|
|
1334 |
+ }
|
|
1335 |
+
|
|
1336 |
+ void storeDouble(ImmDouble imm, Address address)
|
|
1337 |
+ {
|
|
1338 |
+ store32(Imm32(imm.u.s.msb), address);
|
|
1339 |
+ store32(Imm32(imm.u.s.lsb), Address(address.base, address.offset + 4));
|
|
1340 |
+ }
|
|
1341 |
+
|
|
1342 |
+ void storeDouble(ImmDouble imm, BaseIndex address)
|
|
1343 |
+ {
|
|
1344 |
+ store32(Imm32(imm.u.s.msb), address);
|
|
1345 |
+ store32(Imm32(imm.u.s.lsb),
|
|
1346 |
+ BaseIndex(address.base, address.index, address.scale, address.offset + 4));
|
|
1347 |
+ }
|
|
1348 |
+
|
|
1349 |
+ void addDouble(FPRegisterID src, FPRegisterID dest)
|
|
1350 |
+ {
|
|
1351 |
+ m_assembler.faddd_r(src, dest, dest);
|
|
1352 |
+ }
|
|
1353 |
+
|
|
1354 |
+ void addDouble(Address src, FPRegisterID dest)
|
|
1355 |
+ {
|
|
1356 |
+ loadDouble(src, SparcRegisters::f30);
|
|
1357 |
+ m_assembler.faddd_r(SparcRegisters::f30, dest, dest);
|
|
1358 |
+ }
|
|
1359 |
+
|
|
1360 |
+ void divDouble(FPRegisterID src, FPRegisterID dest)
|
|
1361 |
+ {
|
|
1362 |
+ m_assembler.fdivd_r(dest, src, dest);
|
|
1363 |
+ }
|
|
1364 |
+
|
|
1365 |
+ void divDouble(Address src, FPRegisterID dest)
|
|
1366 |
+ {
|
|
1367 |
+ loadDouble(src, SparcRegisters::f30);
|
|
1368 |
+ m_assembler.fdivd_r(dest, SparcRegisters::f30, dest);
|
|
1369 |
+ }
|
|
1370 |
+
|
|
1371 |
+ void subDouble(FPRegisterID src, FPRegisterID dest)
|
|
1372 |
+ {
|
|
1373 |
+ m_assembler.fsubd_r(dest, src, dest);
|
|
1374 |
+ }
|
|
1375 |
+
|
|
1376 |
+ void subDouble(Address src, FPRegisterID dest)
|
|
1377 |
+ {
|
|
1378 |
+ loadDouble(src, SparcRegisters::f30);
|
|
1379 |
+ m_assembler.fsubd_r(dest, SparcRegisters::f30, dest);
|
|
1380 |
+ }
|
|
1381 |
+
|
|
1382 |
+ void mulDouble(FPRegisterID src, FPRegisterID dest)
|
|
1383 |
+ {
|
|
1384 |
+ m_assembler.fmuld_r(src, dest, dest);
|
|
1385 |
+ }
|
|
1386 |
+
|
|
1387 |
+ void mulDouble(Address src, FPRegisterID dest)
|
|
1388 |
+ {
|
|
1389 |
+ loadDouble(src, SparcRegisters::f30);
|
|
1390 |
+ m_assembler.fmuld_r(SparcRegisters::f30, dest, dest);
|
|
1391 |
+ }
|
|
1392 |
+
|
|
1393 |
+ void sqrtDouble(FPRegisterID src, FPRegisterID dest)
|
|
1394 |
+ {
|
|
1395 |
+ m_assembler.fsqrtd_r(src, dest);
|
|
1396 |
+ }
|
|
1397 |
+
|
|
1398 |
+ void negDouble(FPRegisterID src, FPRegisterID dest)
|
|
1399 |
+ {
|
|
1400 |
+ m_assembler.fnegd_r(src, dest);
|
|
1401 |
+ }
|
|
1402 |
+
|
|
1403 |
+ void convertUInt32ToDouble(RegisterID src, FPRegisterID dest)
|
|
1404 |
+ {
|
|
1405 |
+ m_assembler.move_nocheck(0x43300000, SparcRegisters::g1);
|
|
1406 |
+ m_assembler.stw_imm(SparcRegisters::g1, SparcRegisters::sp, 0x60);
|
|
1407 |
+ m_assembler.stw_imm(src, SparcRegisters::sp, 0x64);
|
|
1408 |
+ m_assembler.lddf_imm(SparcRegisters::sp, 0x60, SparcRegisters::f30);
|
|
1409 |
+ m_assembler.stw_imm(SparcRegisters::g0, SparcRegisters::sp, 0x64);
|
|
1410 |
+ m_assembler.lddf_imm(SparcRegisters::sp, 0x60, dest);
|
|
1411 |
+ m_assembler.fsubd_r(SparcRegisters::f30, dest, dest);
|
|
1412 |
+ m_assembler.fabss_r(dest, dest);
|
|
1413 |
+ }
|
|
1414 |
+
|
|
1415 |
+ void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
|
|
1416 |
+ {
|
|
1417 |
+ m_assembler.stw_imm(src, SparcRegisters::sp, 0x60);
|
|
1418 |
+ m_assembler.ldf_imm(SparcRegisters::sp, 0x60, dest);
|
|
1419 |
+ m_assembler.fitod_r(dest, dest);
|
|
1420 |
+ }
|
|
1421 |
+
|
|
1422 |
+ void convertInt32ToDouble(Address address, FPRegisterID dest)
|
|
1423 |
+ {
|
|
1424 |
+ if (m_assembler.isimm13(address.offset))
|
|
1425 |
+ m_assembler.ldf_imm(address.base, address.offset, dest);
|
|
1426 |
+ else {
|
|
1427 |
+ m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
|
|
1428 |
+ m_assembler.ldf_r(address.base, SparcRegisters::g3, dest);
|
|
1429 |
+ }
|
|
1430 |
+ m_assembler.fitod_r(dest, dest);
|
|
1431 |
+ }
|
|
1432 |
+
|
|
1433 |
+ void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
|
|
1434 |
+ {
|
|
1435 |
+ m_assembler.move_nocheck((int)src.m_ptr, SparcRegisters::g3);
|
|
1436 |
+ m_assembler.ldf_r(SparcRegisters::g3, SparcRegisters::g0, dest);
|
|
1437 |
+ m_assembler.fitod_r(dest, dest);
|
|
1438 |
+ }
|
|
1439 |
+
|
|
1440 |
+ void fastLoadDouble(RegisterID lo, RegisterID hi, FPRegisterID fpReg)
|
|
1441 |
+ {
|
|
1442 |
+ m_assembler.stw_imm(lo, SparcRegisters::sp, 0x64);
|
|
1443 |
+ m_assembler.stw_imm(hi, SparcRegisters::sp, 0x60);
|
|
1444 |
+ m_assembler.lddf_imm(SparcRegisters::sp, 0x60, fpReg);
|
|
1445 |
+ }
|
|
1446 |
+
|
|
1447 |
+ void convertDoubleToFloat(FPRegisterID src, FPRegisterID dest)
|
|
1448 |
+ {
|
|
1449 |
+ m_assembler.fdtos_r(src, dest);
|
|
1450 |
+ }
|
|
1451 |
+
|
|
1452 |
+ void breakDoubleTo32(FPRegisterID srcDest, RegisterID typeReg, RegisterID dataReg) {
|
|
1453 |
+ m_assembler.stdf_imm(srcDest, SparcRegisters::sp, 0x60);
|
|
1454 |
+ m_assembler.lduw_imm(SparcRegisters::sp, 0x60, typeReg);
|
|
1455 |
+ m_assembler.lduw_imm(SparcRegisters::sp, 0x64, dataReg);
|
|
1456 |
+ }
|
|
1457 |
+
|
|
1458 |
+ Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
|
|
1459 |
+ {
|
|
1460 |
+ m_assembler.fcmpd_r(left, right);
|
|
1461 |
+ return Jump(m_assembler.fbranch(SparcDoubleCondition(cond)));
|
|
1462 |
+ }
|
|
1463 |
+
|
|
1464 |
+ // Truncates 'src' to an integer, and places the resulting 'dest'.
|
|
1465 |
+ // If the result is not representable as a 32 bit value, branch.
|
|
1466 |
+ // May also branch for some values that are representable in 32 bits
|
|
1467 |
+ // (specifically, in this case, INT_MIN).
|
|
1468 |
+ Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
|
|
1469 |
+ {
|
|
1470 |
+ m_assembler.fdtoi_r(src, SparcRegisters::f30);
|
|
1471 |
+ m_assembler.stf_imm(SparcRegisters::f30, SparcRegisters::sp, 0x60);
|
|
1472 |
+ m_assembler.lduw_imm(SparcRegisters::sp, 0x60, dest);
|
|
1473 |
+
|
|
1474 |
+ m_assembler.or_r(SparcRegisters::g0, SparcRegisters::g0, SparcRegisters::g2);
|
|
1475 |
+ m_assembler.move_nocheck(0x80000000, SparcRegisters::g3);
|
|
1476 |
+ m_assembler.subcc_r(SparcRegisters::g3, dest, SparcRegisters::g0);
|
|
1477 |
+ m_assembler.movcc_imm(1, SparcRegisters::g2, SparcCondition(Equal));
|
|
1478 |
+ m_assembler.move_nocheck(0x7fffffff, SparcRegisters::g3);
|
|
1479 |
+ m_assembler.subcc_r(SparcRegisters::g3, dest, SparcRegisters::g0);
|
|
1480 |
+ m_assembler.movcc_imm(1, SparcRegisters::g2, SparcCondition(Equal));
|
|
1481 |
+
|
|
1482 |
+ return branch32(Equal, SparcRegisters::g2, Imm32(1));
|
|
1483 |
+ }
|
|
1484 |
+
|
|
1485 |
+ // Convert 'src' to an integer, and places the resulting 'dest'.
|
|
1486 |
+ // If the result is not representable as a 32 bit value, branch.
|
|
1487 |
+ // May also branch for some values that are representable in 32 bits
|
|
1488 |
+ // (specifically, in this case, 0).
|
|
1489 |
+ void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
|
|
1490 |
+ {
|
|
1491 |
+ m_assembler.fdtoi_r(src, SparcRegisters::f30);
|
|
1492 |
+ m_assembler.stf_imm(SparcRegisters::f30, SparcRegisters::sp, 0x60);
|
|
1493 |
+ m_assembler.lduw_imm(SparcRegisters::sp, 0x60, dest);
|
|
1494 |
+
|
|
1495 |
+ // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
|
|
1496 |
+ m_assembler.fitod_r(SparcRegisters::f30, SparcRegisters::f30);
|
|
1497 |
+ failureCases.append(branchDouble(DoubleNotEqualOrUnordered, src, SparcRegisters::f30));
|
|
1498 |
+
|
|
1499 |
+ // If the result is zero, it might have been -0.0, and 0.0 equals to -0.0
|
|
1500 |
+ failureCases.append(branchTest32(Zero, dest));
|
|
1501 |
+ }
|
|
1502 |
+
|
|
1503 |
+ void zeroDouble(FPRegisterID srcDest)
|
|
1504 |
+ {
|
|
1505 |
+ m_assembler.fsubd_r(srcDest, srcDest, srcDest);
|
|
1506 |
+ }
|
|
1507 |
+
|
|
1508 |
+ protected:
|
|
1509 |
+ SparcAssembler::Condition SparcCondition(Condition cond)
|
|
1510 |
+ {
|
|
1511 |
+ return static_cast<SparcAssembler::Condition>(cond);
|
|
1512 |
+ }
|
|
1513 |
+
|
|
1514 |
+ SparcAssembler::DoubleCondition SparcDoubleCondition(DoubleCondition cond)
|
|
1515 |
+ {
|
|
1516 |
+ return static_cast<SparcAssembler::DoubleCondition>(cond);
|
|
1517 |
+ }
|
|
1518 |
+
|
|
1519 |
+ private:
|
|
1520 |
+ friend class LinkBuffer;
|
|
1521 |
+ friend class RepatchBuffer;
|
|
1522 |
+
|
|
1523 |
+ static void linkCall(void* code, Call call, FunctionPtr function)
|
|
1524 |
+ {
|
|
1525 |
+ SparcAssembler::linkCall(code, call.m_jmp, function.value());
|
|
1526 |
+ }
|
|
1527 |
+
|
|
1528 |
+ static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
|
|
1529 |
+ {
|
|
1530 |
+ SparcAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
|
|
1531 |
+ }
|
|
1532 |
+
|
|
1533 |
+ static void repatchCall(CodeLocationCall call, FunctionPtr destination)
|
|
1534 |
+ {
|
|
1535 |
+ SparcAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
|
|
1536 |
+ }
|
|
1537 |
+
|
|
1538 |
+ };
|
|
1539 |
+
|
|
1540 |
+}
|
|
1541 |
+
|
|
1542 |
+
|
|
1543 |
+#endif // ENABLE(ASSEMBLER) && CPU(SPARC)
|
|
1544 |
+
|
|
1545 |
+#endif // MacroAssemblerSparc_h
|
|
1546 |
diff --git a/js/src/assembler/assembler/SparcAssembler.h b/js/src/assembler/assembler/SparcAssembler.h
|
|
1547 |
new file mode 100644
|
|
1548 |
index 0000000..72f03fa
|
|
1549 |
--- /dev/null
|
|
1550 |
+++ b/js/src/assembler/assembler/SparcAssembler.h
|
|
1551 |
@@ -0,0 +1,1289 @@
|
|
1552 |
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
1553 |
+ * vim: set ts=4 sw=4 et tw=99:
|
|
1554 |
+ *
|
|
1555 |
+ * ***** BEGIN LICENSE BLOCK *****
|
|
1556 |
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
1557 |
+ *
|
|
1558 |
+ * The contents of this file are subject to the Mozilla Public License Version
|
|
1559 |
+ * 1.1 (the "License"); you may not use this file except in compliance with
|
|
1560 |
+ * the License. You may obtain a copy of the License at
|
|
1561 |
+ * http://www.mozilla.org/MPL/
|
|
1562 |
+ *
|
|
1563 |
+ * Software distributed under the License is distributed on an "AS IS" basis,
|
|
1564 |
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
1565 |
+ * for the specific language governing rights and limitations under the
|
|
1566 |
+ * License.
|
|
1567 |
+ *
|
|
1568 |
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
|
|
1569 |
+ * May 28, 2008.
|
|
1570 |
+ *
|
|
1571 |
+ * The Initial Developer of the Original Code is
|
|
1572 |
+ * Leon Sha <[email protected]>
|
|
1573 |
+ *
|
|
1574 |
+ * Portions created by the Initial Developer are Copyright (C) 2010-2011
|
|
1575 |
+ * the Initial Developer. All Rights Reserved.
|
|
1576 |
+ *
|
|
1577 |
+ * Contributor(s):
|
|
1578 |
+ *
|
|
1579 |
+ * Alternatively, the contents of this file may be used under the terms of
|
|
1580 |
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
1581 |
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
1582 |
+ * in which case the provisions of the GPL or the LGPL are applicable instead
|
|
1583 |
+ * of those above. If you wish to allow use of your version of this file only
|
|
1584 |
+ * under the terms of either the GPL or the LGPL, and not to allow others to
|
|
1585 |
+ * use your version of this file under the terms of the MPL, indicate your
|
|
1586 |
+ * decision by deleting the provisions above and replace them with the notice
|
|
1587 |
+ * and other provisions required by the GPL or the LGPL. If you do not delete
|
|
1588 |
+ * the provisions above, a recipient may use your version of this file under
|
|
1589 |
+ * the terms of any one of the MPL, the GPL or the LGPL.
|
|
1590 |
+ *
|
|
1591 |
+ * ***** END LICENSE BLOCK ***** */
|
|
1592 |
+
|
|
1593 |
+#ifndef SparcAssembler_h
|
|
1594 |
+#define SparcAssembler_h
|
|
1595 |
+
|
|
1596 |
+#include <wtf/Platform.h>
|
|
1597 |
+
|
|
1598 |
+// Some debug code uses s(n)printf for instruction logging.
|
|
1599 |
+#include <stdio.h>
|
|
1600 |
+
|
|
1601 |
+#if ENABLE_ASSEMBLER && WTF_CPU_SPARC
|
|
1602 |
+
|
|
1603 |
+#include "AssemblerBufferWithConstantPool.h"
|
|
1604 |
+#include <wtf/Assertions.h>
|
|
1605 |
+
|
|
1606 |
+#include "methodjit/Logging.h"
|
|
1607 |
+#define IPFX " %s"
|
|
1608 |
+#define ISPFX " "
|
|
1609 |
+#ifdef JS_METHODJIT_SPEW
|
|
1610 |
+# define MAYBE_PAD (isOOLPath ? "> " : "")
|
|
1611 |
+# define PRETTY_PRINT_OFFSET(os) (((os)<0)?"-":""), (((os)<0)?-(os):(os))
|
|
1612 |
+# define FIXME_INSN_PRINTING \
|
|
1613 |
+ do { \
|
|
1614 |
+ js::JaegerSpew(js::JSpew_Insns, \
|
|
1615 |
+ ISPFX "FIXME insn printing %s:%d\n", \
|
|
1616 |
+ __FILE__, __LINE__); \
|
|
1617 |
+ } while (0)
|
|
1618 |
+#else
|
|
1619 |
+# define MAYBE_PAD ""
|
|
1620 |
+# define FIXME_INSN_PRINTING ((void) 0)
|
|
1621 |
+# define PRETTY_PRINT_OFFSET(os) "", 0
|
|
1622 |
+#endif
|
|
1623 |
+
|
|
1624 |
+namespace JSC {
|
|
1625 |
+
|
|
1626 |
+ typedef uint32_t SparcWord;
|
|
1627 |
+
|
|
1628 |
+ namespace SparcRegisters {
|
|
1629 |
+ typedef enum {
|
|
1630 |
+ g0 = 0, // g0 is always 0
|
|
1631 |
+ g1 = 1, // g1 is a scratch register for v8
|
|
1632 |
+ g2 = 2,
|
|
1633 |
+ g3 = 3,
|
|
1634 |
+ g4 = 4,
|
|
1635 |
+ g5 = 5, // Reserved for system
|
|
1636 |
+ g6 = 6, // Reserved for system
|
|
1637 |
+ g7 = 7, // Reserved for system
|
|
1638 |
+
|
|
1639 |
+ o0 = 8,
|
|
1640 |
+ o1 = 9,
|
|
1641 |
+ o2 = 10,
|
|
1642 |
+ o3 = 11,
|
|
1643 |
+ o4 = 12,
|
|
1644 |
+ o5 = 13,
|
|
1645 |
+ o6 = 14, // SP
|
|
1646 |
+ o7 = 15,
|
|
1647 |
+
|
|
1648 |
+ l0 = 16,
|
|
1649 |
+ l1 = 17,
|
|
1650 |
+ l2 = 18,
|
|
1651 |
+ l3 = 19,
|
|
1652 |
+ l4 = 20,
|
|
1653 |
+ l5 = 21,
|
|
1654 |
+ l6 = 22,
|
|
1655 |
+ l7 = 23,
|
|
1656 |
+
|
|
1657 |
+ i0 = 24,
|
|
1658 |
+ i1 = 25,
|
|
1659 |
+ i2 = 26,
|
|
1660 |
+ i3 = 27,
|
|
1661 |
+ i4 = 28,
|
|
1662 |
+ i5 = 29,
|
|
1663 |
+ i6 = 30, // FP
|
|
1664 |
+ i7 = 31,
|
|
1665 |
+
|
|
1666 |
+ sp = o6,
|
|
1667 |
+ fp = i6
|
|
1668 |
+ } RegisterID;
|
|
1669 |
+
|
|
1670 |
+ typedef enum {
|
|
1671 |
+ f0 = 0,
|
|
1672 |
+ f1 = 1,
|
|
1673 |
+ f2 = 2,
|
|
1674 |
+ f3 = 3,
|
|
1675 |
+ f4 = 4,
|
|
1676 |
+ f5 = 5,
|
|
1677 |
+ f6 = 6,
|
|
1678 |
+ f7 = 7,
|
|
1679 |
+ f8 = 8,
|
|
1680 |
+ f9 = 9,
|
|
1681 |
+ f10 = 10,
|
|
1682 |
+ f11 = 11,
|
|
1683 |
+ f12 = 12,
|
|
1684 |
+ f13 = 13,
|
|
1685 |
+ f14 = 14,
|
|
1686 |
+ f15 = 15,
|
|
1687 |
+ f16 = 16,
|
|
1688 |
+ f17 = 17,
|
|
1689 |
+ f18 = 18,
|
|
1690 |
+ f19 = 19,
|
|
1691 |
+ f20 = 20,
|
|
1692 |
+ f21 = 21,
|
|
1693 |
+ f22 = 22,
|
|
1694 |
+ f23 = 23,
|
|
1695 |
+ f24 = 24,
|
|
1696 |
+ f25 = 25,
|
|
1697 |
+ f26 = 26,
|
|
1698 |
+ f27 = 27,
|
|
1699 |
+ f28 = 28,
|
|
1700 |
+ f29 = 29,
|
|
1701 |
+ f30 = 30,
|
|
1702 |
+ f31 = 31
|
|
1703 |
+ } FPRegisterID;
|
|
1704 |
+
|
|
1705 |
+ } // namespace SparcRegisters
|
|
1706 |
+
|
|
1707 |
+ class SparcAssembler {
|
|
1708 |
+ public:
|
|
1709 |
+ typedef SparcRegisters::RegisterID RegisterID;
|
|
1710 |
+ typedef SparcRegisters::FPRegisterID FPRegisterID;
|
|
1711 |
+ AssemblerBuffer m_buffer;
|
|
1712 |
+ bool oom() const { return m_buffer.oom(); }
|
|
1713 |
+
|
|
1714 |
+#ifdef JS_METHODJIT_SPEW
|
|
1715 |
+ bool isOOLPath;
|
|
1716 |
+ SparcAssembler() : isOOLPath(false) { }
|
|
1717 |
+#else
|
|
1718 |
+ SparcAssembler() { }
|
|
1719 |
+#endif
|
|
1720 |
+
|
|
1721 |
+ // Sparc conditional constants
|
|
1722 |
+ typedef enum {
|
|
1723 |
+ ConditionE = 0x1, // Zero
|
|
1724 |
+ ConditionLE = 0x2,
|
|
1725 |
+ ConditionL = 0x3,
|
|
1726 |
+ ConditionLEU = 0x4,
|
|
1727 |
+ ConditionCS = 0x5,
|
|
1728 |
+ ConditionNEG = 0x6,
|
|
1729 |
+ ConditionVS = 0x7,
|
|
1730 |
+ ConditionA = 0x8, // branch_always
|
|
1731 |
+ ConditionNE = 0x9, // Non-zero
|
|
1732 |
+ ConditionG = 0xa,
|
|
1733 |
+ ConditionGE = 0xb,
|
|
1734 |
+ ConditionGU = 0xc,
|
|
1735 |
+ ConditionCC = 0xd,
|
|
1736 |
+ ConditionVC = 0xf
|
|
1737 |
+ } Condition;
|
|
1738 |
+
|
|
1739 |
+
|
|
1740 |
+ typedef enum {
|
|
1741 |
+ DoubleConditionNE = 0x1,
|
|
1742 |
+ DoubleConditionUL = 0x3,
|
|
1743 |
+ DoubleConditionL = 0x4,
|
|
1744 |
+ DoubleConditionUG = 0x5,
|
|
1745 |
+ DoubleConditionG = 0x6,
|
|
1746 |
+ DoubleConditionE = 0x9,
|
|
1747 |
+ DoubleConditionUE = 0xa,
|
|
1748 |
+ DoubleConditionGE = 0xb,
|
|
1749 |
+ DoubleConditionUGE = 0xc,
|
|
1750 |
+ DoubleConditionLE = 0xd,
|
|
1751 |
+ DoubleConditionULE = 0xe
|
|
1752 |
+ } DoubleCondition;
|
|
1753 |
+
|
|
1754 |
+ typedef enum {
|
|
1755 |
+ BranchOnCondition,
|
|
1756 |
+ BranchOnDoubleCondition
|
|
1757 |
+ } BranchType;
|
|
1758 |
+
|
|
1759 |
+ class JmpSrc {
|
|
1760 |
+ friend class SparcAssembler;
|
|
1761 |
+ public:
|
|
1762 |
+ JmpSrc()
|
|
1763 |
+ : m_offset(-1)
|
|
1764 |
+ {
|
|
1765 |
+ }
|
|
1766 |
+
|
|
1767 |
+ private:
|
|
1768 |
+ JmpSrc(int offset)
|
|
1769 |
+ : m_offset(offset)
|
|
1770 |
+ {
|
|
1771 |
+ }
|
|
1772 |
+
|
|
1773 |
+ int m_offset;
|
|
1774 |
+ };
|
|
1775 |
+
|
|
1776 |
+ class JmpDst {
|
|
1777 |
+ friend class SparcAssembler;
|
|
1778 |
+ public:
|
|
1779 |
+ JmpDst()
|
|
1780 |
+ : m_offset(-1)
|
|
1781 |
+ , m_used(false)
|
|
1782 |
+ {
|
|
1783 |
+ }
|
|
1784 |
+
|
|
1785 |
+ bool isUsed() const { return m_used; }
|
|
1786 |
+ void used() { m_used = true; }
|
|
1787 |
+ bool isValid() const { return m_offset != -1; }
|
|
1788 |
+ private:
|
|
1789 |
+ JmpDst(int offset)
|
|
1790 |
+ : m_offset(offset)
|
|
1791 |
+ , m_used(false)
|
|
1792 |
+ {
|
|
1793 |
+ ASSERT(m_offset == offset);
|
|
1794 |
+ }
|
|
1795 |
+
|
|
1796 |
+ int m_used : 1;
|
|
1797 |
+ signed int m_offset : 31;
|
|
1798 |
+ };
|
|
1799 |
+
|
|
1800 |
+ // Instruction formating
|
|
1801 |
+
|
|
1802 |
+ void format_2_1(int rd, int op2, int imm22)
|
|
1803 |
+ {
|
|
1804 |
+ m_buffer.putInt(rd << 25 | op2 << 22 | (imm22 & 0x3FFFFF));
|
|
1805 |
+ }
|
|
1806 |
+
|
|
1807 |
+ void format_2_2(int a, int cond, int op2, int disp22)
|
|
1808 |
+ {
|
|
1809 |
+ format_2_1((a & 0x1) << 4 | (cond & 0xF), op2, disp22);
|
|
1810 |
+ }
|
|
1811 |
+
|
|
1812 |
+ void format_2_3(int a, int cond, int op2, int cc1, int cc0, int p, int disp19)
|
|
1813 |
+ {
|
|
1814 |
+ format_2_2(a, cond, op2, (cc1 & 0x1) << 21 | (cc0 & 0x1) << 20 | (p & 0x1) << 19 | (disp19 & 0x7FFFF));
|
|
1815 |
+ }
|
|
1816 |
+
|
|
1817 |
+ void format_2_4(int a, int rcond, int op2, int d16hi, int p, int rs1, int d16lo)
|
|
1818 |
+ {
|
|
1819 |
+ format_2_2(a, (rcond & 0x7), op2, (d16hi & 0x3) << 20 | (p & 0x1) << 19 | rs1 << 14 | (d16lo & 0x3FFF));
|
|
1820 |
+ }
|
|
1821 |
+
|
|
1822 |
+ void format_3(int op1, int rd, int op3, int bits19)
|
|
1823 |
+ {
|
|
1824 |
+ m_buffer.putInt(op1 << 30 | rd << 25 | op3 << 19 | (bits19 & 0x7FFFF));
|
|
1825 |
+ }
|
|
1826 |
+
|
|
1827 |
+ void format_3_1(int op1, int rd, int op3, int rs1, int bit8, int rs2)
|
|
1828 |
+ {
|
|
1829 |
+ format_3(op1, rd, op3, rs1 << 14 | (bit8 & 0xFF) << 5 | rs2);
|
|
1830 |
+ }
|
|
1831 |
+
|
|
1832 |
+ void format_3_1_imm(int op1, int rd, int op3, int rs1, int simm13)
|
|
1833 |
+ {
|
|
1834 |
+ format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | (simm13 & 0x1FFF));
|
|
1835 |
+ }
|
|
1836 |
+
|
|
1837 |
+ void format_3_2(int op1, int rd, int op3, int rs1, int rcond, int rs2)
|
|
1838 |
+ {
|
|
1839 |
+ format_3(op1, rd, op3, rs1 << 14 | (rcond & 0x3) << 10 | rs2);
|
|
1840 |
+ }
|
|
1841 |
+
|
|
1842 |
+ void format_3_2_imm(int op1, int rd, int op3, int rs1, int rcond, int simm10)
|
|
1843 |
+ {
|
|
1844 |
+ format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | (rcond & 0x3) << 10 | (simm10 & 0x1FFF));
|
|
1845 |
+ }
|
|
1846 |
+
|
|
1847 |
+ void format_3_3(int op1, int rd, int op3, int rs1, int cmask, int mmask)
|
|
1848 |
+ {
|
|
1849 |
+ format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | (cmask & 0x7) << 5 | (mmask & 0xF));
|
|
1850 |
+ }
|
|
1851 |
+ void format_3_4(int op1, int rd, int op3, int bits19)
|
|
1852 |
+ {
|
|
1853 |
+ format_3(op1, rd, op3, bits19);
|
|
1854 |
+ }
|
|
1855 |
+
|
|
1856 |
+ void format_3_5(int op1, int rd, int op3, int rs1, int x, int rs2)
|
|
1857 |
+ {
|
|
1858 |
+ format_3(op1, rd, op3, rs1 << 14 | (x & 0x1) << 12 | rs2);
|
|
1859 |
+ }
|
|
1860 |
+
|
|
1861 |
+ void format_3_6(int op1, int rd, int op3, int rs1, int shcnt32)
|
|
1862 |
+ {
|
|
1863 |
+ format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | (shcnt32 & 0x1F));
|
|
1864 |
+ }
|
|
1865 |
+
|
|
1866 |
+ void format_3_7(int op1, int rd, int op3, int rs1, int shcnt64)
|
|
1867 |
+ {
|
|
1868 |
+ format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | 1 << 12 | (shcnt64 & 0x3F));
|
|
1869 |
+ }
|
|
1870 |
+
|
|
1871 |
+ void format_3_8(int op1, int rd, int op3, int rs1, int bits9, int rs2)
|
|
1872 |
+ {
|
|
1873 |
+ format_3(op1, rd, op3, rs1 << 14 | (bits9 & 0x1FF) << 5 | rs2);
|
|
1874 |
+ }
|
|
1875 |
+
|
|
1876 |
+ void format_3_9(int op1, int cc1, int cc0, int op3, int rs1, int bits9, int rs2)
|
|
1877 |
+ {
|
|
1878 |
+ format_3(op1, (cc1 & 0x1) << 1 | (cc0 & 0x1), op3, rs1 << 14 | (bits9 & 0x1FF) << 5 | rs2);
|
|
1879 |
+ }
|
|
1880 |
+
|
|
1881 |
+ void format_4_1(int rd, int op3, int rs1, int cc1, int cc0, int rs2)
|
|
1882 |
+ {
|
|
1883 |
+ format_3(2, rd, op3, rs1 << 14 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | rs2);
|
|
1884 |
+ }
|
|
1885 |
+
|
|
1886 |
+ void format_4_1_imm(int rd, int op3, int rs1, int cc1, int cc0, int simm11)
|
|
1887 |
+ {
|
|
1888 |
+ format_3(2, rd, op3, rs1 << 14 | (cc1 & 0x1) << 12 | 1 << 13 |(cc0 & 0x1) << 11 | (simm11 & 0x7FF));
|
|
1889 |
+ }
|
|
1890 |
+
|
|
1891 |
+ void format_4_2(int rd, int op3, int cc2, int cond, int cc1, int cc0, int rs2)
|
|
1892 |
+ {
|
|
1893 |
+ format_3(2, rd, op3, (cc2 & 0x1) << 18 | (cond & 0xF) << 14 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | rs2);
|
|
1894 |
+ }
|
|
1895 |
+
|
|
1896 |
+ void format_4_2_imm(int rd, int op3, int cc2, int cond, int cc1, int cc0, int simm11)
|
|
1897 |
+ {
|
|
1898 |
+ format_3(2, rd, op3, (cc2 & 0x1) << 18 | (cond & 0xF) << 14 | 1 << 13 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | (simm11 & 0x7FF));
|
|
1899 |
+ }
|
|
1900 |
+
|
|
1901 |
+ void format_4_3(int rd, int op3, int rs1, int cc1, int cc0, int swap_trap)
|
|
1902 |
+ {
|
|
1903 |
+ format_3(2, rd, op3, rs1 << 14 | 1 << 13 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | (swap_trap & 0x7F));
|
|
1904 |
+ }
|
|
1905 |
+
|
|
1906 |
+ void format_4_4(int rd, int op3, int rs1, int rcond, int opf_low, int rs2)
|
|
1907 |
+ {
|
|
1908 |
+ format_3(2, rd, op3, rs1 << 14 | (rcond & 0x7) << 10 | (opf_low & 0x1F) << 5 | rs2);
|
|
1909 |
+ }
|
|
1910 |
+
|
|
1911 |
+ void format_4_5(int rd, int op3, int cond, int opf_cc, int opf_low, int rs2)
|
|
1912 |
+ {
|
|
1913 |
+ format_3(2, rd, op3, (cond & 0xF) << 14 | (opf_cc & 0x7) << 11 | (opf_low & 0x3F) << 5 | rs2);
|
|
1914 |
+ }
|
|
1915 |
+
|
|
1916 |
+ void addcc_r(int rs1, int rs2, int rd)
|
|
1917 |
+ {
|
|
1918 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
1919 |
+ IPFX "addcc %s, %s, %s\n", MAYBE_PAD,
|
|
1920 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
1921 |
+ format_3_1(2, rd, 0x10, rs1, 0, rs2);
|
|
1922 |
+ }
|
|
1923 |
+
|
|
1924 |
+ void addcc_imm(int rs1, int simm13, int rd)
|
|
1925 |
+ {
|
|
1926 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
1927 |
+ IPFX "addcc %s, %d, %s\n", MAYBE_PAD,
|
|
1928 |
+ nameGpReg(rs1), simm13, nameGpReg(rd));
|
|
1929 |
+ format_3_1_imm(2, rd, 0x10, rs1, simm13);
|
|
1930 |
+ }
|
|
1931 |
+
|
|
1932 |
+ void add_r(int rs1, int rs2, int rd)
|
|
1933 |
+ {
|
|
1934 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
1935 |
+ IPFX "add %s, %s, %s\n", MAYBE_PAD,
|
|
1936 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
1937 |
+ format_3_1(2, rd, 0, rs1, 0, rs2);
|
|
1938 |
+ }
|
|
1939 |
+
|
|
1940 |
+ void add_imm(int rs1, int simm13, int rd)
|
|
1941 |
+ {
|
|
1942 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
1943 |
+ IPFX "add %s, %d, %s\n", MAYBE_PAD,
|
|
1944 |
+ nameGpReg(rs1), simm13, nameGpReg(rd));
|
|
1945 |
+ format_3_1_imm(2, rd, 0, rs1, simm13);
|
|
1946 |
+ }
|
|
1947 |
+
|
|
1948 |
+ void andcc_r(int rs1, int rs2, int rd)
|
|
1949 |
+ {
|
|
1950 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
1951 |
+ IPFX "andcc %s, %s, %s\n", MAYBE_PAD,
|
|
1952 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
1953 |
+ format_3_1(2, rd, 0x11, rs1, 0, rs2);
|
|
1954 |
+ }
|
|
1955 |
+
|
|
1956 |
+ void andcc_imm(int rs1, int simm13, int rd)
|
|
1957 |
+ {
|
|
1958 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
1959 |
+ IPFX "andcc %s, %d, %s\n", MAYBE_PAD,
|
|
1960 |
+ nameGpReg(rs1), simm13, nameGpReg(rd));
|
|
1961 |
+ format_3_1_imm(2, rd, 0x11, rs1, simm13);
|
|
1962 |
+ }
|
|
1963 |
+
|
|
1964 |
+ void or_r(int rs1, int rs2, int rd)
|
|
1965 |
+ {
|
|
1966 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
1967 |
+ IPFX "or %s, %s, %s\n", MAYBE_PAD,
|
|
1968 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
1969 |
+ format_3_1(2, rd, 0x2, rs1, 0, rs2);
|
|
1970 |
+ }
|
|
1971 |
+
|
|
1972 |
+ void or_imm(int rs1, int simm13, int rd)
|
|
1973 |
+ {
|
|
1974 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
1975 |
+ IPFX "or %s, %d, %s\n", MAYBE_PAD,
|
|
1976 |
+ nameGpReg(rs1), simm13, nameGpReg(rd));
|
|
1977 |
+ format_3_1_imm(2, rd, 0x2, rs1, simm13);
|
|
1978 |
+ }
|
|
1979 |
+
|
|
1980 |
+ // sethi %hi(imm22) rd
|
|
1981 |
+ void sethi(int imm22, int rd)
|
|
1982 |
+ {
|
|
1983 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
1984 |
+ IPFX "sethi %%hi(0x%x), %s\n", MAYBE_PAD,
|
|
1985 |
+ imm22, nameGpReg(rd));
|
|
1986 |
+ format_2_1(rd, 0x4, (imm22 >> 10));
|
|
1987 |
+ }
|
|
1988 |
+
|
|
1989 |
+ void sll_r(int rs1, int rs2, int rd)
|
|
1990 |
+ {
|
|
1991 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
1992 |
+ IPFX "sll %s, %s, %s\n", MAYBE_PAD,
|
|
1993 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
1994 |
+ format_3_5(2, rd, 0x25, rs1, 0, rs2);
|
|
1995 |
+ }
|
|
1996 |
+
|
|
1997 |
+ void sll_imm(int rs1, int shcnt32, int rd)
|
|
1998 |
+ {
|
|
1999 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2000 |
+ IPFX "sll %s, %d, %s\n", MAYBE_PAD,
|
|
2001 |
+ nameGpReg(rs1), shcnt32, nameGpReg(rd));
|
|
2002 |
+ format_3_6(2, rd, 0x25, rs1, shcnt32);
|
|
2003 |
+ }
|
|
2004 |
+
|
|
2005 |
+ void sra_r(int rs1, int rs2, int rd)
|
|
2006 |
+ {
|
|
2007 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2008 |
+ IPFX "sra %s, %s, %s\n", MAYBE_PAD,
|
|
2009 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
2010 |
+ format_3_5(2, rd, 0x27, rs1, 0, rs2);
|
|
2011 |
+ }
|
|
2012 |
+
|
|
2013 |
+ void sra_imm(int rs1, int shcnt32, int rd)
|
|
2014 |
+ {
|
|
2015 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2016 |
+ IPFX "sra %s, %d, %s\n", MAYBE_PAD,
|
|
2017 |
+ nameGpReg(rs1), shcnt32, nameGpReg(rd));
|
|
2018 |
+ format_3_6(2, rd, 0x27, rs1, shcnt32);
|
|
2019 |
+ }
|
|
2020 |
+
|
|
2021 |
+ void srl_r(int rs1, int rs2, int rd)
|
|
2022 |
+ {
|
|
2023 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2024 |
+ IPFX "srl %s, %s, %s\n", MAYBE_PAD,
|
|
2025 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
2026 |
+ format_3_5(2, rd, 0x26, rs1, 0, rs2);
|
|
2027 |
+ }
|
|
2028 |
+
|
|
2029 |
+ void srl_imm(int rs1, int shcnt32, int rd)
|
|
2030 |
+ {
|
|
2031 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2032 |
+ IPFX "srl %s, %d, %s\n", MAYBE_PAD,
|
|
2033 |
+ nameGpReg(rs1), shcnt32, nameGpReg(rd));
|
|
2034 |
+ format_3_6(2, rd, 0x26, rs1, shcnt32);
|
|
2035 |
+ }
|
|
2036 |
+
|
|
2037 |
+ void subcc_r(int rs1, int rs2, int rd)
|
|
2038 |
+ {
|
|
2039 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2040 |
+ IPFX "subcc %s, %s, %s\n", MAYBE_PAD,
|
|
2041 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
2042 |
+ format_3_1(2, rd, 0x14, rs1, 0, rs2);
|
|
2043 |
+ }
|
|
2044 |
+
|
|
2045 |
+ void subcc_imm(int rs1, int simm13, int rd)
|
|
2046 |
+ {
|
|
2047 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2048 |
+ IPFX "subcc %s, %d, %s\n", MAYBE_PAD,
|
|
2049 |
+ nameGpReg(rs1), simm13, nameGpReg(rd));
|
|
2050 |
+ format_3_1_imm(2, rd, 0x14, rs1, simm13);
|
|
2051 |
+ }
|
|
2052 |
+
|
|
2053 |
+ void orcc_r(int rs1, int rs2, int rd)
|
|
2054 |
+ {
|
|
2055 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2056 |
+ IPFX "orcc %s, %s, %s\n", MAYBE_PAD,
|
|
2057 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
2058 |
+ format_3_1(2, rd, 0x12, rs1, 0, rs2);
|
|
2059 |
+ }
|
|
2060 |
+
|
|
2061 |
+ void orcc_imm(int rs1, int simm13, int rd)
|
|
2062 |
+ {
|
|
2063 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2064 |
+ IPFX "orcc %s, %d, %s\n", MAYBE_PAD,
|
|
2065 |
+ nameGpReg(rs1), simm13, nameGpReg(rd));
|
|
2066 |
+ format_3_1_imm(2, rd, 0x12, rs1, simm13);
|
|
2067 |
+ }
|
|
2068 |
+
|
|
2069 |
+ void xorcc_r(int rs1, int rs2, int rd)
|
|
2070 |
+ {
|
|
2071 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2072 |
+ IPFX "xorcc %s, %s, %s\n", MAYBE_PAD,
|
|
2073 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
2074 |
+ format_3_1(2, rd, 0x13, rs1, 0, rs2);
|
|
2075 |
+ }
|
|
2076 |
+
|
|
2077 |
+ void xorcc_imm(int rs1, int simm13, int rd)
|
|
2078 |
+ {
|
|
2079 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2080 |
+ IPFX "xorcc %s, %d, %s\n", MAYBE_PAD,
|
|
2081 |
+ nameGpReg(rs1), simm13, nameGpReg(rd));
|
|
2082 |
+ format_3_1_imm(2, rd, 0x13, rs1, simm13);
|
|
2083 |
+ }
|
|
2084 |
+
|
|
2085 |
+ void xnorcc_r(int rs1, int rs2, int rd)
|
|
2086 |
+ {
|
|
2087 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2088 |
+ IPFX "xnorcc %s, %s, %s\n", MAYBE_PAD,
|
|
2089 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
2090 |
+ format_3_1(2, rd, 0x17, rs1, 0, rs2);
|
|
2091 |
+ }
|
|
2092 |
+
|
|
2093 |
+ void xnorcc_imm(int rs1, int simm13, int rd)
|
|
2094 |
+ {
|
|
2095 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2096 |
+ IPFX "xnorcc %s, %d, %s\n", MAYBE_PAD,
|
|
2097 |
+ nameGpReg(rs1), simm13, nameGpReg(rd));
|
|
2098 |
+ format_3_1_imm(2, rd, 0x17, rs1, simm13);
|
|
2099 |
+ }
|
|
2100 |
+
|
|
2101 |
+ void smulcc_r(int rs1, int rs2, int rd)
|
|
2102 |
+ {
|
|
2103 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2104 |
+ IPFX "smulcc %s, %s, %s\n", MAYBE_PAD,
|
|
2105 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
2106 |
+ format_3_1(2, rd, 0x1b, rs1, 0, rs2);
|
|
2107 |
+ }
|
|
2108 |
+
|
|
2109 |
+ void smulcc_imm(int rs1, int simm13, int rd)
|
|
2110 |
+ {
|
|
2111 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2112 |
+ IPFX "smulcc %s, %d, %s\n", MAYBE_PAD,
|
|
2113 |
+ nameGpReg(rs1), simm13, nameGpReg(rd));
|
|
2114 |
+ format_3_1_imm(2, rd, 0x1b, rs1, simm13);
|
|
2115 |
+ }
|
|
2116 |
+
|
|
2117 |
+ void ldsb_r(int rs1, int rs2, int rd)
|
|
2118 |
+ {
|
|
2119 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2120 |
+ IPFX "ldsb [%s + %s], %s\n", MAYBE_PAD,
|
|
2121 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
2122 |
+ format_3_1(3, rd, 0x9, rs1, 0, rs2);
|
|
2123 |
+ }
|
|
2124 |
+
|
|
2125 |
+ void ldsb_imm(int rs1, int simm13, int rd)
|
|
2126 |
+ {
|
|
2127 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2128 |
+ IPFX "ldsb [%s + %d], %s\n", MAYBE_PAD,
|
|
2129 |
+ nameGpReg(rs1), simm13, nameGpReg(rd));
|
|
2130 |
+ format_3_1_imm(3, rd, 0x9, rs1, simm13);
|
|
2131 |
+ }
|
|
2132 |
+
|
|
2133 |
+ void ldub_r(int rs1, int rs2, int rd)
|
|
2134 |
+ {
|
|
2135 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2136 |
+ IPFX "ldub [%s + %s], %s\n", MAYBE_PAD,
|
|
2137 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
2138 |
+ format_3_1(3, rd, 0x1, rs1, 0, rs2);
|
|
2139 |
+ }
|
|
2140 |
+
|
|
2141 |
+ void ldub_imm(int rs1, int simm13, int rd)
|
|
2142 |
+ {
|
|
2143 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2144 |
+ IPFX "ldub [%s + %d], %s\n", MAYBE_PAD,
|
|
2145 |
+ nameGpReg(rs1), simm13, nameGpReg(rd));
|
|
2146 |
+ format_3_1_imm(3, rd, 0x1, rs1, simm13);
|
|
2147 |
+ }
|
|
2148 |
+
|
|
2149 |
+ void lduw_r(int rs1, int rs2, int rd)
|
|
2150 |
+ {
|
|
2151 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2152 |
+ IPFX "lduw [%s + %s], %s\n", MAYBE_PAD,
|
|
2153 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
2154 |
+ format_3_1(3, rd, 0x0, rs1, 0, rs2);
|
|
2155 |
+ }
|
|
2156 |
+
|
|
2157 |
+ void lduwa_r(int rs1, int rs2, int rd)
|
|
2158 |
+ {
|
|
2159 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2160 |
+ IPFX "lduwa [%s + %s], %s\n", MAYBE_PAD,
|
|
2161 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
2162 |
+ format_3_1(3, rd, 0x10, rs1, 0x82, rs2);
|
|
2163 |
+ }
|
|
2164 |
+
|
|
2165 |
+ void lduw_imm(int rs1, int simm13, int rd)
|
|
2166 |
+ {
|
|
2167 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2168 |
+ IPFX "lduw [%s + %d], %s\n", MAYBE_PAD,
|
|
2169 |
+ nameGpReg(rs1), simm13, nameGpReg(rd));
|
|
2170 |
+ format_3_1_imm(3, rd, 0x0, rs1, simm13);
|
|
2171 |
+ }
|
|
2172 |
+
|
|
2173 |
+ void ldsh_r(int rs1, int rs2, int rd)
|
|
2174 |
+ {
|
|
2175 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2176 |
+ IPFX "ldsh [%s + %s], %s\n", MAYBE_PAD,
|
|
2177 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
2178 |
+ format_3_1(3, rd, 0xa, rs1, 0, rs2);
|
|
2179 |
+ }
|
|
2180 |
+
|
|
2181 |
+ void ldsh_imm(int rs1, int simm13, int rd)
|
|
2182 |
+ {
|
|
2183 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2184 |
+ IPFX "ldsh [%s + %d], %s\n", MAYBE_PAD,
|
|
2185 |
+ nameGpReg(rs1), simm13, nameGpReg(rd));
|
|
2186 |
+ format_3_1_imm(3, rd, 0xa, rs1, simm13);
|
|
2187 |
+ }
|
|
2188 |
+
|
|
2189 |
+ void lduh_r(int rs1, int rs2, int rd)
|
|
2190 |
+ {
|
|
2191 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2192 |
+ IPFX "lduh [%s + %s], %s\n", MAYBE_PAD,
|
|
2193 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
2194 |
+ format_3_1(3, rd, 0x2, rs1, 0, rs2);
|
|
2195 |
+ }
|
|
2196 |
+
|
|
2197 |
+ void lduh_imm(int rs1, int simm13, int rd)
|
|
2198 |
+ {
|
|
2199 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2200 |
+ IPFX "lduh [%s + %d], %s\n", MAYBE_PAD,
|
|
2201 |
+ nameGpReg(rs1), simm13, nameGpReg(rd));
|
|
2202 |
+ format_3_1_imm(3, rd, 0x2, rs1, simm13);
|
|
2203 |
+ }
|
|
2204 |
+
|
|
2205 |
+ void stb_r(int rd, int rs2, int rs1)
|
|
2206 |
+ {
|
|
2207 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2208 |
+ IPFX "stb %s, [%s + %s]\n", MAYBE_PAD,
|
|
2209 |
+ nameGpReg(rd), nameGpReg(rs1), nameGpReg(rs2));
|
|
2210 |
+ format_3_1(3, rd, 0x5, rs1, 0, rs2);
|
|
2211 |
+ }
|
|
2212 |
+
|
|
2213 |
+ void stb_imm(int rd, int rs1, int simm13)
|
|
2214 |
+ {
|
|
2215 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2216 |
+ IPFX "stb %s, [%s + %d]\n", MAYBE_PAD,
|
|
2217 |
+ nameGpReg(rd), nameGpReg(rs1), simm13);
|
|
2218 |
+ format_3_1_imm(3, rd, 0x5, rs1, simm13);
|
|
2219 |
+ }
|
|
2220 |
+
|
|
2221 |
+ void sth_r(int rd, int rs2, int rs1)
|
|
2222 |
+ {
|
|
2223 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2224 |
+ IPFX "sth %s, [%s + %s]\n", MAYBE_PAD,
|
|
2225 |
+ nameGpReg(rd), nameGpReg(rs1), nameGpReg(rs2));
|
|
2226 |
+ format_3_1(3, rd, 0x6, rs1, 0, rs2);
|
|
2227 |
+ }
|
|
2228 |
+
|
|
2229 |
+ void sth_imm(int rd, int rs1, int simm13)
|
|
2230 |
+ {
|
|
2231 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2232 |
+ IPFX "sth %s, [%s + %d]\n", MAYBE_PAD,
|
|
2233 |
+ nameGpReg(rd), nameGpReg(rs1), simm13);
|
|
2234 |
+ format_3_1_imm(3, rd, 0x6, rs1, simm13);
|
|
2235 |
+ }
|
|
2236 |
+
|
|
2237 |
+ void stw_r(int rd, int rs2, int rs1)
|
|
2238 |
+ {
|
|
2239 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2240 |
+ IPFX "stw %s, [%s + %s]\n", MAYBE_PAD,
|
|
2241 |
+ nameGpReg(rd), nameGpReg(rs1), nameGpReg(rs2));
|
|
2242 |
+ format_3_1(3, rd, 0x4, rs1, 0, rs2);
|
|
2243 |
+ }
|
|
2244 |
+
|
|
2245 |
+ void stw_imm(int rd, int rs1, int simm13)
|
|
2246 |
+ {
|
|
2247 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2248 |
+ IPFX "stw %s, [%s + %d]\n", MAYBE_PAD,
|
|
2249 |
+ nameGpReg(rd), nameGpReg(rs1), simm13);
|
|
2250 |
+ format_3_1_imm(3, rd, 0x4, rs1, simm13);
|
|
2251 |
+ }
|
|
2252 |
+
|
|
2253 |
+ void ldf_r(int rs1, int rs2, int rd)
|
|
2254 |
+ {
|
|
2255 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2256 |
+ IPFX "ld [%s + %s], %s\n", MAYBE_PAD,
|
|
2257 |
+ nameGpReg(rs1), nameGpReg(rs2), nameFpReg(rd));
|
|
2258 |
+ format_3_1(3, rd, 0x20, rs1, 0, rs2);
|
|
2259 |
+ }
|
|
2260 |
+
|
|
2261 |
+ void ldf_imm(int rs1, int simm13, int rd)
|
|
2262 |
+ {
|
|
2263 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2264 |
+ IPFX "ld [%s + %d], %s\n", MAYBE_PAD,
|
|
2265 |
+ nameGpReg(rs1), simm13, nameFpReg(rd));
|
|
2266 |
+ format_3_1_imm(3, rd, 0x20, rs1, simm13);
|
|
2267 |
+ }
|
|
2268 |
+
|
|
2269 |
+ // lddf and stdf will have mem align problem.
|
|
2270 |
+ void lddf_r(int rs1, int rs2, int rd)
|
|
2271 |
+ {
|
|
2272 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2273 |
+ IPFX "ldd [%s + %s], %s\n", MAYBE_PAD,
|
|
2274 |
+ nameGpReg(rs1), nameGpReg(rs2), nameFpReg(rd));
|
|
2275 |
+ format_3_1(3, rd, 0x23, rs1, 0, rs2);
|
|
2276 |
+ }
|
|
2277 |
+
|
|
2278 |
+ void lddf_imm(int rs1, int simm13, int rd)
|
|
2279 |
+ {
|
|
2280 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2281 |
+ IPFX "ldd [%s + %d], %s\n", MAYBE_PAD,
|
|
2282 |
+ nameGpReg(rs1), simm13, nameFpReg(rd));
|
|
2283 |
+ format_3_1_imm(3, rd, 0x23, rs1, simm13);
|
|
2284 |
+ }
|
|
2285 |
+
|
|
2286 |
+ void stdf_r(int rd, int rs2, int rs1)
|
|
2287 |
+ {
|
|
2288 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2289 |
+ IPFX "std %s, [%s + %s]\n", MAYBE_PAD,
|
|
2290 |
+ nameFpReg(rd), nameGpReg(rs1), nameGpReg(rs2));
|
|
2291 |
+ format_3_1(3, rd, 0x27, rs1, 0, rs2);
|
|
2292 |
+ }
|
|
2293 |
+
|
|
2294 |
+ void stdf_imm(int rd, int rs1, int simm13)
|
|
2295 |
+ {
|
|
2296 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2297 |
+ IPFX "std %s, [%s + %d]\n", MAYBE_PAD,
|
|
2298 |
+ nameFpReg(rd), nameGpReg(rs1), simm13);
|
|
2299 |
+ format_3_1_imm(3, rd, 0x27, rs1, simm13);
|
|
2300 |
+ }
|
|
2301 |
+
|
|
2302 |
+ void stf_r(int rd, int rs2, int rs1)
|
|
2303 |
+ {
|
|
2304 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2305 |
+ IPFX "st %s, [%s + %s]\n", MAYBE_PAD,
|
|
2306 |
+ nameFpReg(rd), nameGpReg(rs1), nameGpReg(rs2));
|
|
2307 |
+ format_3_1(3, rd, 0x24, rs1, 0, rs2);
|
|
2308 |
+ }
|
|
2309 |
+
|
|
2310 |
+ void stf_imm(int rd, int rs1, int simm13)
|
|
2311 |
+ {
|
|
2312 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2313 |
+ IPFX "st %s, [%s + %d]\n", MAYBE_PAD,
|
|
2314 |
+ nameFpReg(rd), nameGpReg(rs1), simm13);
|
|
2315 |
+ format_3_1_imm(3, rd, 0x24, rs1, simm13);
|
|
2316 |
+ }
|
|
2317 |
+
|
|
2318 |
+ void fmovd_r(int rs2, int rd)
|
|
2319 |
+ {
|
|
2320 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2321 |
+ IPFX "fmovd %s, %s\n", MAYBE_PAD,
|
|
2322 |
+ nameFpReg(rs2), nameFpReg(rd));
|
|
2323 |
+ format_3_8(2, rd, 0x34, 0, 0x2, rs2);
|
|
2324 |
+ }
|
|
2325 |
+
|
|
2326 |
+ void fcmpd_r(int rs1, int rs2)
|
|
2327 |
+ {
|
|
2328 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2329 |
+ IPFX "fcmpd %s, %s\n", MAYBE_PAD,
|
|
2330 |
+ nameFpReg(rs1), nameFpReg(rs2));
|
|
2331 |
+ format_3_9(2, 0, 0, 0x35, rs1, 0x52, rs2);
|
|
2332 |
+ }
|
|
2333 |
+
|
|
2334 |
+ void nop()
|
|
2335 |
+ {
|
|
2336 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2337 |
+ IPFX "nop\n", MAYBE_PAD);
|
|
2338 |
+ format_2_1(0, 0x4, 0);
|
|
2339 |
+ }
|
|
2340 |
+
|
|
2341 |
+ void branch_con(Condition cond, int target)
|
|
2342 |
+ {
|
|
2343 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2344 |
+ IPFX "b%s 0x%x\n", MAYBE_PAD,
|
|
2345 |
+ nameICC(cond), target);
|
|
2346 |
+ format_2_2(0, cond, 0x2, target);
|
|
2347 |
+ }
|
|
2348 |
+
|
|
2349 |
+ void fbranch_con(DoubleCondition cond, int target)
|
|
2350 |
+ {
|
|
2351 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2352 |
+ IPFX "fb%s 0x%x\n", MAYBE_PAD,
|
|
2353 |
+ nameFCC(cond), target);
|
|
2354 |
+ format_2_2(0, cond, 0x6, target);
|
|
2355 |
+ }
|
|
2356 |
+
|
|
2357 |
+ void rdy(int rd)
|
|
2358 |
+ {
|
|
2359 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2360 |
+ IPFX "rdy %s\n", MAYBE_PAD,
|
|
2361 |
+ nameFpReg(rd));
|
|
2362 |
+ format_3_1(2, rd, 0x28, 0, 0, 0);
|
|
2363 |
+ }
|
|
2364 |
+
|
|
2365 |
+ void rdpc(int rd)
|
|
2366 |
+ {
|
|
2367 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2368 |
+ IPFX "rdpc %s\n", MAYBE_PAD,
|
|
2369 |
+ nameGpReg(rd));
|
|
2370 |
+ format_3_1(2, rd, 0x28, 5, 0, 0);
|
|
2371 |
+ }
|
|
2372 |
+ void jmpl_r(int rs1, int rs2, int rd)
|
|
2373 |
+ {
|
|
2374 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2375 |
+ IPFX "jmpl %s + %s, %s\n", MAYBE_PAD,
|
|
2376 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
2377 |
+ format_3_1(2, rd, 0x38, rs1, 0, rs2);
|
|
2378 |
+ }
|
|
2379 |
+
|
|
2380 |
+ void jmpl_imm(int rs1, int simm13, int rd)
|
|
2381 |
+ {
|
|
2382 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2383 |
+ IPFX "jmpl %s + %d, %s\n", MAYBE_PAD,
|
|
2384 |
+ nameGpReg(rs1), simm13, nameGpReg(rd));
|
|
2385 |
+ format_3_1_imm(2, rd, 0x38, rs1, simm13);
|
|
2386 |
+ }
|
|
2387 |
+
|
|
2388 |
+ void save_r(int rs1, int rs2, int rd)
|
|
2389 |
+ {
|
|
2390 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2391 |
+ IPFX "save %s, %s, %s\n", MAYBE_PAD,
|
|
2392 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
2393 |
+ format_3_1(2, rd, 0x3c, rs1, 0, rs2);
|
|
2394 |
+ }
|
|
2395 |
+
|
|
2396 |
+ void save_imm(int rs1, int simm13, int rd)
|
|
2397 |
+ {
|
|
2398 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2399 |
+ IPFX "save %s, %d, %s\n", MAYBE_PAD,
|
|
2400 |
+ nameGpReg(rs1), simm13, nameGpReg(rd));
|
|
2401 |
+ format_3_1_imm(2, rd, 0x3c, rs1, simm13);
|
|
2402 |
+ }
|
|
2403 |
+
|
|
2404 |
+ void restore_r(int rs1, int rs2, int rd)
|
|
2405 |
+ {
|
|
2406 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2407 |
+ IPFX "restore %s, %s, %s\n", MAYBE_PAD,
|
|
2408 |
+ nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
|
|
2409 |
+ format_3_1(2, rd, 0x3d, rs1, 0, rs2);
|
|
2410 |
+ }
|
|
2411 |
+
|
|
2412 |
+ void ta_imm(int swap_trap)
|
|
2413 |
+ {
|
|
2414 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2415 |
+ IPFX "ta %d\n", MAYBE_PAD,
|
|
2416 |
+ swap_trap);
|
|
2417 |
+ format_4_3(0x8, 0xa, 0, 0, 0, swap_trap);
|
|
2418 |
+ }
|
|
2419 |
+
|
|
2420 |
+ void movcc_imm(int simm11, int rd, Condition cond)
|
|
2421 |
+ {
|
|
2422 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2423 |
+ IPFX "mov%s %d, %s\n", MAYBE_PAD,
|
|
2424 |
+ nameICC(cond), simm11, nameGpReg(rd));
|
|
2425 |
+ format_4_2_imm(rd, 0x2c, 1, cond, 0, 0, simm11);
|
|
2426 |
+ }
|
|
2427 |
+
|
|
2428 |
+ void fabss_r(int rs2, int rd)
|
|
2429 |
+ {
|
|
2430 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2431 |
+ IPFX "fabss %s, %s\n", MAYBE_PAD,
|
|
2432 |
+ nameFpReg(rs2), nameFpReg(rd));
|
|
2433 |
+ format_3_8(2, rd, 0x34, 0, 0x9, rs2);
|
|
2434 |
+ }
|
|
2435 |
+
|
|
2436 |
+ void faddd_r(int rs1, int rs2, int rd)
|
|
2437 |
+ {
|
|
2438 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2439 |
+ IPFX "faddd %s, %s, %s\n", MAYBE_PAD,
|
|
2440 |
+ nameFpReg(rs1), nameFpReg(rs2), nameFpReg(rd));
|
|
2441 |
+ format_3_8(2, rd, 0x34, rs1, 0x42, rs2);
|
|
2442 |
+ }
|
|
2443 |
+
|
|
2444 |
+ void fsubd_r(int rs1, int rs2, int rd)
|
|
2445 |
+ {
|
|
2446 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2447 |
+ IPFX "fsubd %s, %s, %s\n", MAYBE_PAD,
|
|
2448 |
+ nameFpReg(rs1), nameFpReg(rs2), nameFpReg(rd));
|
|
2449 |
+ format_3_8(2, rd, 0x34, rs1, 0x46, rs2);
|
|
2450 |
+ }
|
|
2451 |
+
|
|
2452 |
+ void fmuld_r(int rs1, int rs2, int rd)
|
|
2453 |
+ {
|
|
2454 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2455 |
+ IPFX "fmuld %s, %s, %s\n", MAYBE_PAD,
|
|
2456 |
+ nameFpReg(rs1), nameFpReg(rs2), nameFpReg(rd));
|
|
2457 |
+ format_3_8(2, rd, 0x34, rs1, 0x4a, rs2);
|
|
2458 |
+ }
|
|
2459 |
+
|
|
2460 |
+ void fdivd_r(int rs1, int rs2, int rd)
|
|
2461 |
+ {
|
|
2462 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2463 |
+ IPFX "fdivd %s, %s, %s\n", MAYBE_PAD,
|
|
2464 |
+ nameFpReg(rs1), nameFpReg(rs2), nameFpReg(rd));
|
|
2465 |
+ format_3_8(2, rd, 0x34, rs1, 0x4e, rs2);
|
|
2466 |
+ }
|
|
2467 |
+
|
|
2468 |
+ void fsqrtd_r(int rs2, int rd)
|
|
2469 |
+ {
|
|
2470 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2471 |
+ IPFX "fsqartd %s, %s\n", MAYBE_PAD,
|
|
2472 |
+ nameFpReg(rs2), nameFpReg(rd));
|
|
2473 |
+ format_3_8(2, rd, 0x34, 0, 0x2a, rs2);
|
|
2474 |
+ }
|
|
2475 |
+
|
|
2476 |
+ void fnegd_r(int rs2, int rd)
|
|
2477 |
+ {
|
|
2478 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2479 |
+ IPFX "fnegd %s, %s\n", MAYBE_PAD,
|
|
2480 |
+ nameFpReg(rs2), nameFpReg(rd));
|
|
2481 |
+ format_3_8(2, rd, 0x34, 0, 0x06, rs2);
|
|
2482 |
+ }
|
|
2483 |
+
|
|
2484 |
+ void fitod_r(int rs2, int rd)
|
|
2485 |
+ {
|
|
2486 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2487 |
+ IPFX "fitod %s, %s\n", MAYBE_PAD,
|
|
2488 |
+ nameFpReg(rs2), nameFpReg(rd));
|
|
2489 |
+ format_3_8(2, rd, 0x34, 0, 0xc8, rs2);
|
|
2490 |
+ }
|
|
2491 |
+
|
|
2492 |
+ void fdtoi_r(int rs2, int rd)
|
|
2493 |
+ {
|
|
2494 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2495 |
+ IPFX "fdtoi %s, %s\n", MAYBE_PAD,
|
|
2496 |
+ nameFpReg(rs2), nameFpReg(rd));
|
|
2497 |
+ format_3_8(2, rd, 0x34, 0, 0xd2, rs2);
|
|
2498 |
+ }
|
|
2499 |
+
|
|
2500 |
+ void fdtos_r(int rs2, int rd)
|
|
2501 |
+ {
|
|
2502 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2503 |
+ IPFX "fdtos %s, %s\n", MAYBE_PAD,
|
|
2504 |
+ nameFpReg(rs2), nameFpReg(rd));
|
|
2505 |
+ format_3_8(2, rd, 0x34, 0, 0xc6, rs2);
|
|
2506 |
+ }
|
|
2507 |
+
|
|
2508 |
+ void fstod_r(int rs2, int rd)
|
|
2509 |
+ {
|
|
2510 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2511 |
+ IPFX "fstod %s, %s\n", MAYBE_PAD,
|
|
2512 |
+ nameFpReg(rs2), nameFpReg(rd));
|
|
2513 |
+ format_3_8(2, rd, 0x34, 0, 0xc9, rs2);
|
|
2514 |
+ }
|
|
2515 |
+
|
|
2516 |
+ static bool isimm13(int imm)
|
|
2517 |
+ {
|
|
2518 |
+ return (imm) <= 0xfff && (imm) >= -0x1000;
|
|
2519 |
+ }
|
|
2520 |
+
|
|
2521 |
+ static bool isimm22(int imm)
|
|
2522 |
+ {
|
|
2523 |
+ return (imm) <= 0x1fffff && (imm) >= -0x200000;
|
|
2524 |
+ }
|
|
2525 |
+
|
|
2526 |
+ void move_nocheck(int imm_v, RegisterID dest)
|
|
2527 |
+ {
|
|
2528 |
+ sethi(imm_v, dest);
|
|
2529 |
+ or_imm(dest, imm_v & 0x3FF, dest);
|
|
2530 |
+ }
|
|
2531 |
+
|
|
2532 |
+ JmpSrc call()
|
|
2533 |
+ {
|
|
2534 |
+ JmpSrc r = JmpSrc(m_buffer.size());
|
|
2535 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2536 |
+ IPFX "call %d\n", MAYBE_PAD,
|
|
2537 |
+ r.m_offset);
|
|
2538 |
+ m_buffer.putInt(0x40000000);
|
|
2539 |
+ nop();
|
|
2540 |
+ return r;
|
|
2541 |
+ }
|
|
2542 |
+
|
|
2543 |
+ JmpSrc jump_common(BranchType branchtype, int cond)
|
|
2544 |
+ {
|
|
2545 |
+ if (branchtype == BranchOnCondition)
|
|
2546 |
+ branch_con(Condition(cond), 0);
|
|
2547 |
+ else
|
|
2548 |
+ fbranch_con(DoubleCondition(cond), 0);
|
|
2549 |
+
|
|
2550 |
+ nop();
|
|
2551 |
+ branch_con(ConditionA, 7);
|
|
2552 |
+ nop();
|
|
2553 |
+ move_nocheck(0, SparcRegisters::g2);
|
|
2554 |
+ rdpc(SparcRegisters::g3);
|
|
2555 |
+ jmpl_r(SparcRegisters::g2, SparcRegisters::g3, SparcRegisters::g0);
|
|
2556 |
+ nop();
|
|
2557 |
+ return JmpSrc(m_buffer.size());
|
|
2558 |
+ }
|
|
2559 |
+
|
|
2560 |
+ JmpSrc branch(Condition cond)
|
|
2561 |
+ {
|
|
2562 |
+ return jump_common(BranchOnCondition, cond);
|
|
2563 |
+ }
|
|
2564 |
+
|
|
2565 |
+ JmpSrc fbranch(DoubleCondition cond)
|
|
2566 |
+ {
|
|
2567 |
+ return jump_common(BranchOnDoubleCondition, cond);
|
|
2568 |
+ }
|
|
2569 |
+
|
|
2570 |
+ JmpSrc jmp()
|
|
2571 |
+ {
|
|
2572 |
+ return jump_common(BranchOnCondition, ConditionA);
|
|
2573 |
+ }
|
|
2574 |
+
|
|
2575 |
+ // Assembler admin methods:
|
|
2576 |
+
|
|
2577 |
+ JmpDst label()
|
|
2578 |
+ {
|
|
2579 |
+ JmpDst r = JmpDst(m_buffer.size());
|
|
2580 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2581 |
+ IPFX "#label ((%d))\n", MAYBE_PAD, r.m_offset);
|
|
2582 |
+ return r;
|
|
2583 |
+ }
|
|
2584 |
+
|
|
2585 |
+ // General helpers
|
|
2586 |
+
|
|
2587 |
+ size_t size() const { return m_buffer.size(); }
|
|
2588 |
+ unsigned char *buffer() const { return m_buffer.buffer(); }
|
|
2589 |
+
|
|
2590 |
+ static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
|
|
2591 |
+ {
|
|
2592 |
+ return dst.m_offset - src.m_offset;
|
|
2593 |
+ }
|
|
2594 |
+
|
|
2595 |
+ static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
|
|
2596 |
+ {
|
|
2597 |
+ return dst.m_offset - src.m_offset;
|
|
2598 |
+ }
|
|
2599 |
+
|
|
2600 |
+ static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
|
|
2601 |
+ {
|
|
2602 |
+ return dst.m_offset - src.m_offset;
|
|
2603 |
+ }
|
|
2604 |
+
|
|
2605 |
+ static unsigned getCallReturnOffset(JmpSrc call)
|
|
2606 |
+ {
|
|
2607 |
+ return call.m_offset + 20;
|
|
2608 |
+ }
|
|
2609 |
+
|
|
2610 |
+ static void* getRelocatedAddress(void* code, JmpSrc jump)
|
|
2611 |
+ {
|
|
2612 |
+ ASSERT(jump.m_offset != -1);
|
|
2613 |
+
|
|
2614 |
+ return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
|
|
2615 |
+ }
|
|
2616 |
+
|
|
2617 |
+ static void* getRelocatedAddress(void* code, JmpDst destination)
|
|
2618 |
+ {
|
|
2619 |
+ ASSERT(destination.m_offset != -1);
|
|
2620 |
+
|
|
2621 |
+ return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
|
|
2622 |
+ }
|
|
2623 |
+
|
|
2624 |
+ void* executableCopy(ExecutablePool* allocator)
|
|
2625 |
+ {
|
|
2626 |
+ return m_buffer.executableCopy(allocator);
|
|
2627 |
+ }
|
|
2628 |
+
|
|
2629 |
+ void* executableCopy(void* buffer)
|
|
2630 |
+ {
|
|
2631 |
+ return memcpy(buffer, m_buffer.buffer(), size());
|
|
2632 |
+ }
|
|
2633 |
+
|
|
2634 |
+ static void patchPointerInternal(void* where, int value)
|
|
2635 |
+ {
|
|
2636 |
+ // Patch move_nocheck.
|
|
2637 |
+ uint32_t *branch = (uint32_t*) where;
|
|
2638 |
+ branch[0] &= 0xFFC00000;
|
|
2639 |
+ branch[0] |= (value >> 10) & 0x3FFFFF;
|
|
2640 |
+ branch[1] &= 0xFFFFFC00;
|
|
2641 |
+ branch[1] |= value & 0x3FF;
|
|
2642 |
+ ExecutableAllocator::cacheFlush(where, 8);
|
|
2643 |
+ }
|
|
2644 |
+
|
|
2645 |
+ static void patchbranch(void* where, int value)
|
|
2646 |
+ {
|
|
2647 |
+ uint32_t *branch = (uint32_t*) where;
|
|
2648 |
+ branch[0] &= 0xFFC00000;
|
|
2649 |
+ branch[0] |= value & 0x3FFFFF;
|
|
2650 |
+ ExecutableAllocator::cacheFlush(where, 4);
|
|
2651 |
+ }
|
|
2652 |
+
|
|
2653 |
+ static bool canRelinkJump(void* from, void* to)
|
|
2654 |
+ {
|
|
2655 |
+ return true;
|
|
2656 |
+ }
|
|
2657 |
+
|
|
2658 |
+ static void relinkJump(void* from, void* to)
|
|
2659 |
+ {
|
|
2660 |
+ from = (void *)((int)from - 36);
|
|
2661 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2662 |
+ ISPFX "##link ((%p)) jumps to ((%p))\n",
|
|
2663 |
+ from, to);
|
|
2664 |
+
|
|
2665 |
+ int value = ((int)to - (int)from) / 4;
|
|
2666 |
+ if (isimm22(value))
|
|
2667 |
+ patchbranch(from, value);
|
|
2668 |
+ else {
|
|
2669 |
+ patchbranch(from, 4);
|
|
2670 |
+ from = (void *)((intptr_t)from + 16);
|
|
2671 |
+ patchPointerInternal(from, (int)(value * 4 - 24));
|
|
2672 |
+ }
|
|
2673 |
+ }
|
|
2674 |
+
|
|
2675 |
+ void linkJump(JmpSrc from, JmpDst to)
|
|
2676 |
+ {
|
|
2677 |
+ ASSERT(from.m_offset != -1);
|
|
2678 |
+ ASSERT(to.m_offset != -1);
|
|
2679 |
+ intptr_t code = (intptr_t)(m_buffer.data());
|
|
2680 |
+ void *where = (void *)((intptr_t)code + from.m_offset);
|
|
2681 |
+ void *target = (void *)((intptr_t)code + to.m_offset);
|
|
2682 |
+ relinkJump(where, target);
|
|
2683 |
+ }
|
|
2684 |
+
|
|
2685 |
+ static void linkJump(void* code, JmpSrc from, void* to)
|
|
2686 |
+ {
|
|
2687 |
+ ASSERT(from.m_offset != -1);
|
|
2688 |
+ void *where = (void *)((intptr_t)code + from.m_offset);
|
|
2689 |
+ relinkJump(where, to);
|
|
2690 |
+ }
|
|
2691 |
+
|
|
2692 |
+ static void relinkCall(void* from, void* to)
|
|
2693 |
+ {
|
|
2694 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2695 |
+ ISPFX "##linkCall ((from=%p)) ((to=%p))\n",
|
|
2696 |
+ from, to);
|
|
2697 |
+
|
|
2698 |
+ int disp = ((int)to - (int)from)/4;
|
|
2699 |
+ *(uint32_t *)((int)from) &= 0x40000000;
|
|
2700 |
+ *(uint32_t *)((int)from) |= disp & 0x3fffffff;
|
|
2701 |
+ ExecutableAllocator::cacheFlush(from, 4);
|
|
2702 |
+ }
|
|
2703 |
+
|
|
2704 |
+ static void linkCall(void* code, JmpSrc where, void* to)
|
|
2705 |
+ {
|
|
2706 |
+ void *from = (void *)((intptr_t)code + where.m_offset);
|
|
2707 |
+ relinkCall(from, to);
|
|
2708 |
+ }
|
|
2709 |
+
|
|
2710 |
+ static void linkPointer(void* code, JmpDst where, void* value)
|
|
2711 |
+ {
|
|
2712 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2713 |
+ ISPFX "##linkPointer ((%p + %#x)) points to ((%p))\n",
|
|
2714 |
+ code, where.m_offset, value);
|
|
2715 |
+
|
|
2716 |
+ void *from = (void *)((intptr_t)code + where.m_offset);
|
|
2717 |
+ patchPointerInternal(from, (int)value);
|
|
2718 |
+ }
|
|
2719 |
+
|
|
2720 |
+ static void repatchInt32(void* where, int value)
|
|
2721 |
+ {
|
|
2722 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2723 |
+ ISPFX "##repatchInt32 ((where=%p)) holds ((value=%d))\n",
|
|
2724 |
+ where, value);
|
|
2725 |
+
|
|
2726 |
+ patchPointerInternal(where, value);
|
|
2727 |
+ }
|
|
2728 |
+
|
|
2729 |
+ static void repatchPointer(void* where, void* value)
|
|
2730 |
+ {
|
|
2731 |
+ js::JaegerSpew(js::JSpew_Insns,
|
|
2732 |
+ ISPFX "##repatchPointer ((where = %p)) points to ((%p))\n",
|
|
2733 |
+ where, value);
|
|
2734 |
+
|
|
2735 |
+ patchPointerInternal(where, (int)value);
|
|
2736 |
+ }
|
|
2737 |
+
|
|
2738 |
+ static void repatchLoadPtrToLEA(void* where)
|
|
2739 |
+ {
|
|
2740 |
+ // sethi is used. The offset is in a register
|
|
2741 |
+ if (*(uint32_t *)((int)where) & 0x01000000)
|
|
2742 |
+ where = (void *)((intptr_t)where + 8);
|
|
2743 |
+
|
|
2744 |
+ *(uint32_t *)((int)where) &= 0x3fffffff;
|
|
2745 |
+ *(uint32_t *)((int)where) |= 0x80000000;
|
|
2746 |
+ ExecutableAllocator::cacheFlush(where, 4);
|
|
2747 |
+ }
|
|
2748 |
+
|
|
2749 |
+ static void repatchLEAToLoadPtr(void* where)
|
|
2750 |
+ {
|
|
2751 |
+ // sethi is used. The offset is in a register
|
|
2752 |
+ if (*(uint32_t *)((int)where) & 0x01000000)
|
|
2753 |
+ where = (void *)((intptr_t)where + 8);
|
|
2754 |
+
|
|
2755 |
+ *(uint32_t *)((int)where) &= 0x3fffffff;
|
|
2756 |
+ *(uint32_t *)((int)where) |= 0xc0000000;
|
|
2757 |
+ ExecutableAllocator::cacheFlush(where, 4);
|
|
2758 |
+ }
|
|
2759 |
+
|
|
2760 |
+ private:
|
|
2761 |
+ static char const * nameGpReg(int reg)
|
|
2762 |
+ {
|
|
2763 |
+ ASSERT(reg <= 31);
|
|
2764 |
+ ASSERT(reg >= 0);
|
|
2765 |
+ static char const * names[] = {
|
|
2766 |
+ "%g0", "%g1", "%g2", "%g3",
|
|
2767 |
+ "%g4", "%g5", "%g6", "%g7",
|
|
2768 |
+ "%o0", "%o1", "%o2", "%o3",
|
|
2769 |
+ "%o4", "%o5", "%sp", "%o7",
|
|
2770 |
+ "%l0", "%l1", "%l2", "%l3",
|
|
2771 |
+ "%l4", "%l5", "%l6", "%l7",
|
|
2772 |
+ "%i0", "%i1", "%i2", "%i3",
|
|
2773 |
+ "%i4", "%i5", "%fp", "%i7"
|
|
2774 |
+ };
|
|
2775 |
+ return names[reg];
|
|
2776 |
+ }
|
|
2777 |
+
|
|
2778 |
+ static char const * nameFpReg(int reg)
|
|
2779 |
+ {
|
|
2780 |
+ ASSERT(reg <= 31);
|
|
2781 |
+ ASSERT(reg >= 0);
|
|
2782 |
+ static char const * names[] = {
|
|
2783 |
+ "%f0", "%f1", "%f2", "%f3",
|
|
2784 |
+ "%f4", "%f5", "%f6", "%f7",
|
|
2785 |
+ "%f8", "%f9", "%f10", "%f11",
|
|
2786 |
+ "%f12", "%f13", "%f14", "%f15",
|
|
2787 |
+ "%f16", "%f17", "%f18", "%f19",
|
|
2788 |
+ "%f20", "%f21", "%f22", "%f23",
|
|
2789 |
+ "%f24", "%f25", "%f26", "%f27",
|
|
2790 |
+ "%f28", "%f29", "%f30", "%f31"
|
|
2791 |
+ };
|
|
2792 |
+ return names[reg];
|
|
2793 |
+ }
|
|
2794 |
+
|
|
2795 |
+ static char const * nameICC(Condition cc)
|
|
2796 |
+ {
|
|
2797 |
+ ASSERT(cc <= ConditionVC);
|
|
2798 |
+ ASSERT(cc >= 0);
|
|
2799 |
+
|
|
2800 |
+ uint32_t ccIndex = cc;
|
|
2801 |
+ static char const * inames[] = {
|
|
2802 |
+ " ", "e ",
|
|
2803 |
+ "le ", "l ",
|
|
2804 |
+ "leu", "cs ",
|
|
2805 |
+ "neg", "vs ",
|
|
2806 |
+ "a ", "ne ",
|
|
2807 |
+ "g ", "ge ",
|
|
2808 |
+ "gu ", "cc ",
|
|
2809 |
+ " ", "vc "
|
|
2810 |
+ };
|
|
2811 |
+ return inames[ccIndex];
|
|
2812 |
+ }
|
|
2813 |
+
|
|
2814 |
+ static char const * nameFCC(DoubleCondition cc)
|
|
2815 |
+ {
|
|
2816 |
+ ASSERT(cc <= DoubleConditionULE);
|
|
2817 |
+ ASSERT(cc >= 0);
|
|
2818 |
+
|
|
2819 |
+ uint32_t ccIndex = cc;
|
|
2820 |
+ static char const * fnames[] = {
|
|
2821 |
+ " ", "ne ",
|
|
2822 |
+ " ", "ul ",
|
|
2823 |
+ "l ", "ug ",
|
|
2824 |
+ "g ", " ",
|
|
2825 |
+ " ", "e ",
|
|
2826 |
+ "ue ", "ge ",
|
|
2827 |
+ "ugu", "le ",
|
|
2828 |
+ "ule", " "
|
|
2829 |
+ };
|
|
2830 |
+ return fnames[ccIndex];
|
|
2831 |
+ }
|
|
2832 |
+
|
|
2833 |
+
|
|
2834 |
+ };
|
|
2835 |
+
|
|
2836 |
+} // namespace JSC
|
|
2837 |
+
|
|
2838 |
+#endif // ENABLE(ASSEMBLER) && CPU(SPARC)
|
|
2839 |
+
|
|
2840 |
+#endif // SparcAssembler_h
|
|
2841 |
diff --git a/js/src/assembler/jit/ExecutableAllocator.h b/js/src/assembler/jit/ExecutableAllocator.h
|
|
2842 |
index 511aebf..50d58ef 100644
|
|
2843 |
--- a/js/src/assembler/jit/ExecutableAllocator.h
|
|
2844 |
+++ b/js/src/assembler/jit/ExecutableAllocator.h
|
|
2845 |
@@ -35,6 +35,10 @@
|
|
2846 |
#include "jsvector.h"
|
|
2847 |
#include "jslock.h"
|
|
2848 |
|
|
2849 |
+#if WTF_CPU_SPARC
|
|
2850 |
+extern "C" void sync_instruction_memory(caddr_t v, u_int len);
|
|
2851 |
+#endif
|
|
2852 |
+
|
|
2853 |
#if WTF_PLATFORM_IPHONE
|
|
2854 |
#include <libkern/OSCacheControl.h>
|
|
2855 |
#include <sys/mman.h>
|
|
2856 |
@@ -391,6 +395,11 @@ public:
|
|
2857 |
{
|
|
2858 |
CacheRangeFlush(code, size, CACHE_SYNC_ALL);
|
|
2859 |
}
|
|
2860 |
+#elif WTF_CPU_SPARC
|
|
2861 |
+ static void cacheFlush(void* code, size_t size)
|
|
2862 |
+ {
|
|
2863 |
+ sync_instruction_memory((caddr_t)code, size);
|
|
2864 |
+ }
|
|
2865 |
#else
|
|
2866 |
#error "The cacheFlush support is missing on this platform."
|
|
2867 |
#endif
|
|
2868 |
diff --git a/js/src/assembler/wtf/Platform.h b/js/src/assembler/wtf/Platform.h
|
|
2869 |
index 3dfad2a..5ad3f75 100644
|
|
2870 |
--- a/js/src/assembler/wtf/Platform.h
|
|
2871 |
+++ b/js/src/assembler/wtf/Platform.h
|
|
2872 |
@@ -159,7 +159,7 @@
|
|
2873 |
|
|
2874 |
/* CPU(SPARC) - any SPARC, true for CPU(SPARC32) and CPU(SPARC64) */
|
|
2875 |
#if WTF_CPU_SPARC32 || WTF_CPU_SPARC64
|
|
2876 |
-#define WTF_CPU_SPARC
|
|
2877 |
+#define WTF_CPU_SPARC 1
|
|
2878 |
#endif
|
|
2879 |
|
|
2880 |
/* CPU(X86) - i386 / x86 32-bit */
|
|
2881 |
@@ -857,6 +857,8 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
|
|
2882 |
/* The JIT is tested & working on x86 Windows */
|
|
2883 |
#elif WTF_CPU_X86 && WTF_PLATFORM_WIN
|
|
2884 |
#define ENABLE_JIT 1
|
|
2885 |
+#elif WTF_CPU_SPARC
|
|
2886 |
+ #define ENABLE_JIT 1
|
|
2887 |
#endif
|
|
2888 |
|
|
2889 |
#if WTF_PLATFORM_QT
|
|
2890 |
@@ -918,8 +920,10 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
|
|
2891 |
#if !defined(ENABLE_YARR_JIT)
|
|
2892 |
|
|
2893 |
/* YARR supports x86 & x86-64, and has been tested on Mac and Windows. */
|
|
2894 |
+
|
|
2895 |
#if (WTF_CPU_X86 \
|
|
2896 |
|| WTF_CPU_X86_64 \
|
|
2897 |
+ || WTF_CPU_SPARC \
|
|
2898 |
|| WTF_CPU_ARM_TRADITIONAL \
|
|
2899 |
|| WTF_CPU_ARM_THUMB2 \
|
|
2900 |
|| WTF_CPU_X86)
|
|
2901 |
diff --git a/js/src/configure.in b/js/src/configure.in
|
|
2902 |
index 5d5365b..faac6b5 100644
|
|
2903 |
--- a/js/src/configure.in
|
|
2904 |
+++ b/js/src/configure.in
|
|
2905 |
@@ -2959,7 +2959,12 @@ arm*-*)
|
|
2906 |
sparc*-*)
|
|
2907 |
ENABLE_TRACEJIT=1
|
|
2908 |
NANOJIT_ARCH=Sparc
|
|
2909 |
+ ENABLE_METHODJIT=1
|
|
2910 |
+ ENABLE_MONOIC=1
|
|
2911 |
+ ENABLE_POLYIC=1
|
|
2912 |
+ ENABLE_POLYIC_TYPED_ARRAY=1
|
|
2913 |
AC_DEFINE(JS_CPU_SPARC)
|
|
2914 |
+ AC_DEFINE(JS_NUNBOX32)
|
|
2915 |
;;
|
|
2916 |
esac
|
|
2917 |
|
|
2918 |
diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
|
|
2919 |
index 3fe567d..a912902 100644
|
|
2920 |
--- a/js/src/jsgc.cpp
|
|
2921 |
+++ b/js/src/jsgc.cpp
|
|
2922 |
@@ -2799,7 +2799,7 @@ js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind)
|
|
2923 |
JS_CHECK_STACK_SIZE(cx->stackLimit + (1 << 14), &stackDummy));
|
|
2924 |
# else
|
|
2925 |
/* -16k because it is possible to perform a GC during an overrecursion report. */
|
|
2926 |
- JS_ASSERT_IF(cx->stackLimit, JS_CHECK_STACK_SIZE(cx->stackLimit - (1 << 14), &stackDummy));
|
|
2927 |
+ JS_ASSERT_IF(cx->stackLimit, JS_CHECK_STACK_SIZE(cx->stackLimit - (1 << 15), &stackDummy));
|
|
2928 |
# endif
|
|
2929 |
#endif
|
|
2930 |
|
|
2931 |
diff --git a/js/src/methodjit/BaseAssembler.h b/js/src/methodjit/BaseAssembler.h
|
|
2932 |
index bc7cd97..400e373 100644
|
|
2933 |
--- a/js/src/methodjit/BaseAssembler.h
|
|
2934 |
+++ b/js/src/methodjit/BaseAssembler.h
|
|
2935 |
@@ -176,6 +176,8 @@ class Assembler : public ValueAssembler
|
|
2936 |
static const RegisterID ClobberInCall = JSC::X86Registers::ecx;
|
|
2937 |
#elif defined(JS_CPU_ARM)
|
|
2938 |
static const RegisterID ClobberInCall = JSC::ARMRegisters::r2;
|
|
2939 |
+#elif defined(JS_CPU_SPARC)
|
|
2940 |
+ static const RegisterID ClobberInCall = JSC::SparcRegisters::l1;
|
|
2941 |
#endif
|
|
2942 |
|
|
2943 |
/* :TODO: OOM */
|
|
2944 |
@@ -225,6 +227,10 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::X86Registe
|
|
2945 |
static const JSC::MacroAssembler::RegisterID JSReturnReg_Type = JSC::ARMRegisters::r2;
|
|
2946 |
static const JSC::MacroAssembler::RegisterID JSReturnReg_Data = JSC::ARMRegisters::r1;
|
|
2947 |
static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegisters::r1;
|
|
2948 |
+#elif defined(JS_CPU_SPARC)
|
|
2949 |
+static const JSC::MacroAssembler::RegisterID JSReturnReg_Type = JSC::SparcRegisters::i0;
|
|
2950 |
+static const JSC::MacroAssembler::RegisterID JSReturnReg_Data = JSC::SparcRegisters::i1;
|
|
2951 |
+static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::SparcRegisters::i2;
|
|
2952 |
#endif
|
|
2953 |
|
|
2954 |
size_t distanceOf(Label l) {
|
|
2955 |
@@ -364,10 +370,18 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegiste
|
|
2956 |
// Windows x64 requires extra space in between calls.
|
|
2957 |
#ifdef _WIN64
|
|
2958 |
static const uint32 ShadowStackSpace = 32;
|
|
2959 |
+#elif defined(JS_CPU_SPARC)
|
|
2960 |
+ static const uint32 ShadowStackSpace = 92;
|
|
2961 |
#else
|
|
2962 |
static const uint32 ShadowStackSpace = 0;
|
|
2963 |
#endif
|
|
2964 |
|
|
2965 |
+#if defined(JS_CPU_SPARC)
|
|
2966 |
+ static const uint32 BaseStackSpace = 104;
|
|
2967 |
+#else
|
|
2968 |
+ static const uint32 BaseStackSpace = 0;
|
|
2969 |
+#endif
|
|
2970 |
+
|
|
2971 |
// Prepare the stack for a call sequence. This must be called AFTER all
|
|
2972 |
// volatile regs have been saved, and BEFORE pushArg() is used. The stack
|
|
2973 |
// is assumed to be aligned to 16-bytes plus any pushes that occured via
|
|
2974 |
@@ -426,7 +440,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegiste
|
|
2975 |
//
|
|
2976 |
// Note that it's not required we're in a call - stackAdjust can be 0.
|
|
2977 |
JS_ASSERT(marker.base <= extraStackSpace);
|
|
2978 |
- return Address(stackPointerRegister, stackAdjust + extraStackSpace - marker.base);
|
|
2979 |
+ return Address(stackPointerRegister, BaseStackSpace + stackAdjust + extraStackSpace - marker.base);
|
|
2980 |
}
|
|
2981 |
|
|
2982 |
// This is an internal function only for use inside a setupABICall(),
|
|
2983 |
@@ -651,9 +665,9 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegiste
|
|
2984 |
Address capacity(objReg, offsetof(JSObject, capacity));
|
|
2985 |
if (key.isConstant()) {
|
|
2986 |
JS_ASSERT(key.index() >= 0);
|
|
2987 |
- return branch32(BelowOrEqual, payloadOf(capacity), Imm32(key.index()));
|
|
2988 |
+ return branch32(BelowOrEqual, capacity, Imm32(key.index()));
|
|
2989 |
}
|
|
2990 |
- return branch32(BelowOrEqual, payloadOf(capacity), key.reg());
|
|
2991 |
+ return branch32(BelowOrEqual, capacity, key.reg());
|
|
2992 |
}
|
|
2993 |
|
|
2994 |
// Load a jsval from an array slot, given a key. |objReg| is clobbered.
|
|
2995 |
diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp
|
|
2996 |
index 5d77692..02c75e5 100644
|
|
2997 |
--- a/js/src/methodjit/Compiler.cpp
|
|
2998 |
+++ b/js/src/methodjit/Compiler.cpp
|
|
2999 |
@@ -1845,7 +1845,7 @@ mjit::Compiler::generateMethod()
|
|
3000 |
// obj->getFlatClosureUpvars()
|
|
3001 |
masm.loadPtr(Address(reg, offsetof(JSObject, slots)), reg);
|
|
3002 |
Address upvarAddress(reg, JSObject::JSSLOT_FLAT_CLOSURE_UPVARS * sizeof(Value));
|
|
3003 |
- masm.loadPrivate(upvarAddress, reg);
|
|
3004 |
+ masm.loadPrivate(masm.payloadOf(upvarAddress), reg);
|
|
3005 |
// push ((Value *) reg)[index]
|
|
3006 |
frame.freeReg(reg);
|
|
3007 |
frame.push(Address(reg, index * sizeof(Value)));
|
|
3008 |
@@ -3605,7 +3605,7 @@ mjit::Compiler::jsop_bindname(JSAtom *atom, bool usePropCache)
|
|
3009 |
masm.loadPtr(Address(JSFrameReg, JSStackFrame::offsetOfScopeChain()), pic.objReg);
|
|
3010 |
|
|
3011 |
pic.shapeGuard = masm.label();
|
|
3012 |
- Jump inlineJump = masm.branchPtr(Assembler::NotEqual, masm.payloadOf(parent), ImmPtr(0));
|
|
3013 |
+ Jump inlineJump = masm.branchPtr(Assembler::NotEqual, parent, ImmPtr(0));
|
|
3014 |
{
|
|
3015 |
RESERVE_OOL_SPACE(stubcc.masm);
|
|
3016 |
pic.slowPathStart = stubcc.linkExit(inlineJump, Uses(0));
|
|
3017 |
@@ -3674,7 +3674,7 @@ mjit::Compiler::jsop_bindname(JSAtom *atom, bool usePropCache)
|
|
3018 |
|
|
3019 |
Address address(reg, offsetof(JSObject, parent));
|
|
3020 |
|
|
3021 |
- Jump j = masm.branchPtr(Assembler::NotEqual, masm.payloadOf(address), ImmPtr(0));
|
|
3022 |
+ Jump j = masm.branchPtr(Assembler::NotEqual, address, ImmPtr(0));
|
|
3023 |
|
|
3024 |
stubcc.linkExit(j, Uses(0));
|
|
3025 |
stubcc.leave();
|
|
3026 |
@@ -4614,7 +4614,7 @@ mjit::Compiler::jsop_instanceof()
|
|
3027 |
Label loop = masm.label();
|
|
3028 |
|
|
3029 |
/* Walk prototype chain, break out on NULL or hit. */
|
|
3030 |
- masm.loadPayload(protoAddr, obj);
|
|
3031 |
+ masm.loadPtr(protoAddr, obj);
|
|
3032 |
Jump isFalse2 = masm.branchTestPtr(Assembler::Zero, obj, obj);
|
|
3033 |
Jump isTrue = masm.branchPtr(Assembler::NotEqual, obj, proto);
|
|
3034 |
isTrue.linkTo(loop, &masm);
|
|
3035 |
diff --git a/js/src/methodjit/FastArithmetic.cpp b/js/src/methodjit/FastArithmetic.cpp
|
|
3036 |
index 653581d..3eb151b 100644
|
|
3037 |
--- a/js/src/methodjit/FastArithmetic.cpp
|
|
3038 |
+++ b/js/src/methodjit/FastArithmetic.cpp
|
|
3039 |
@@ -771,7 +771,7 @@ mjit::Compiler::jsop_neg()
|
|
3040 |
#if defined JS_CPU_X86 || defined JS_CPU_X64
|
|
3041 |
masm.loadDouble(&DoubleNegMask, FPRegisters::Second);
|
|
3042 |
masm.xorDouble(FPRegisters::Second, fpreg);
|
|
3043 |
-#elif defined JS_CPU_ARM
|
|
3044 |
+#elif defined JS_CPU_ARM || defined JS_CPU_SPARC
|
|
3045 |
masm.negDouble(fpreg, fpreg);
|
|
3046 |
#endif
|
|
3047 |
|
|
3048 |
diff --git a/js/src/methodjit/FastOps.cpp b/js/src/methodjit/FastOps.cpp
|
|
3049 |
index 7e1c5b1..3227e30 100644
|
|
3050 |
--- a/js/src/methodjit/FastOps.cpp
|
|
3051 |
+++ b/js/src/methodjit/FastOps.cpp
|
|
3052 |
@@ -1556,13 +1556,13 @@ mjit::Compiler::jsop_stricteq(JSOp op)
|
|
3053 |
|
|
3054 |
Assembler::Condition oppositeCond = (op == JSOP_STRICTEQ) ? Assembler::NotEqual : Assembler::Equal;
|
|
3055 |
|
|
3056 |
-#if defined JS_CPU_X86 || defined JS_CPU_ARM
|
|
3057 |
+#ifndef JS_CPU_X64
|
|
3058 |
static const int CanonicalNaNType = 0x7FF80000;
|
|
3059 |
masm.setPtr(oppositeCond, treg, Imm32(CanonicalNaNType), result);
|
|
3060 |
-#elif defined JS_CPU_X64
|
|
3061 |
+#else
|
|
3062 |
static const void *CanonicalNaNType = (void *)0x7FF8000000000000;
|
|
3063 |
- masm.move(ImmPtr(CanonicalNaNType), JSC::X86Registers::r11);
|
|
3064 |
- masm.setPtr(oppositeCond, treg, JSC::X86Registers::r11, result);
|
|
3065 |
+ masm.move(ImmPtr(CanonicalNaNType), Registers::ScratchReg);
|
|
3066 |
+ masm.setPtr(oppositeCond, treg, Registers::ScratchReg, result);
|
|
3067 |
#endif
|
|
3068 |
|
|
3069 |
frame.popn(2);
|
|
3070 |
@@ -1585,13 +1585,13 @@ mjit::Compiler::jsop_stricteq(JSOp op)
|
|
3071 |
|
|
3072 |
/* This is only true if the other side is |null|. */
|
|
3073 |
RegisterID result = frame.allocReg(Registers::SingleByteRegs);
|
|
3074 |
-#if defined JS_CPU_X86 || defined JS_CPU_ARM
|
|
3075 |
+#ifndef JS_CPU_X64
|
|
3076 |
JSValueTag mask = known->getKnownTag();
|
|
3077 |
if (frame.shouldAvoidTypeRemat(test))
|
|
3078 |
masm.set32(cond, masm.tagOf(frame.addressOf(test)), Imm32(mask), result);
|
|
3079 |
else
|
|
3080 |
masm.set32(cond, frame.tempRegForType(test), Imm32(mask), result);
|
|
3081 |
-#elif defined JS_CPU_X64
|
|
3082 |
+#else
|
|
3083 |
RegisterID maskReg = frame.allocReg();
|
|
3084 |
masm.move(ImmTag(known->getKnownTag()), maskReg);
|
|
3085 |
|
|
3086 |
@@ -1667,7 +1667,7 @@ mjit::Compiler::jsop_stricteq(JSOp op)
|
|
3087 |
return;
|
|
3088 |
}
|
|
3089 |
|
|
3090 |
-#ifndef JS_CPU_ARM
|
|
3091 |
+#if !defined JS_CPU_ARM && !defined JS_CPU_SPARC
|
|
3092 |
/* Try an integer fast-path. */
|
|
3093 |
bool needStub = false;
|
|
3094 |
if (!lhs->isTypeKnown()) {
|
|
3095 |
diff --git a/js/src/methodjit/FrameState-inl.h b/js/src/methodjit/FrameState-inl.h
|
|
3096 |
index 9dfeb82..7764a3f 100644
|
|
3097 |
--- a/js/src/methodjit/FrameState-inl.h
|
|
3098 |
+++ b/js/src/methodjit/FrameState-inl.h
|
|
3099 |
@@ -137,7 +137,7 @@ FrameState::convertInt32ToDouble(Assembler &masm, FrameEntry *fe, FPRegisterID f
|
|
3100 |
if (fe->data.inRegister())
|
|
3101 |
masm.convertInt32ToDouble(fe->data.reg(), fpreg);
|
|
3102 |
else
|
|
3103 |
- masm.convertInt32ToDouble(addressOf(fe), fpreg);
|
|
3104 |
+ masm.convertInt32ToDouble(masm.payloadOf(addressOf(fe)), fpreg);
|
|
3105 |
}
|
|
3106 |
|
|
3107 |
inline bool
|
|
3108 |
diff --git a/js/src/methodjit/ICLabels.h b/js/src/methodjit/ICLabels.h
|
|
3109 |
index cddcf7a..98fdffd 100644
|
|
3110 |
--- a/js/src/methodjit/ICLabels.h
|
|
3111 |
+++ b/js/src/methodjit/ICLabels.h
|
|
3112 |
@@ -64,7 +64,7 @@ namespace ic {
|
|
3113 |
* implementation.
|
|
3114 |
*/
|
|
3115 |
|
|
3116 |
-#if defined JS_CPU_X64 || defined JS_CPU_ARM
|
|
3117 |
+#if defined JS_CPU_X64 || defined JS_CPU_ARM || defined JS_CPU_SPARC
|
|
3118 |
# define JS_HAS_IC_LABELS
|
|
3119 |
#endif
|
|
3120 |
|
|
3121 |
@@ -172,7 +172,7 @@ struct GetPropLabels : MacroAssemblerTypedefs {
|
|
3122 |
int getInlineTypeJumpOffset() {
|
|
3123 |
#if defined JS_CPU_X86 || defined JS_CPU_X64
|
|
3124 |
return INLINE_TYPE_JUMP;
|
|
3125 |
-#elif defined JS_CPU_ARM
|
|
3126 |
+#elif defined JS_CPU_ARM || defined JS_CPU_SPARC
|
|
3127 |
return POST_INST_OFFSET(inlineTypeJumpOffset);
|
|
3128 |
#endif
|
|
3129 |
}
|
|
3130 |
@@ -180,7 +180,7 @@ struct GetPropLabels : MacroAssemblerTypedefs {
|
|
3131 |
void setInlineTypeJumpOffset(int offset) {
|
|
3132 |
#if defined JS_CPU_X86 || defined JS_CPU_X64
|
|
3133 |
JS_ASSERT(INLINE_TYPE_JUMP == offset);
|
|
3134 |
-#elif defined JS_CPU_ARM
|
|
3135 |
+#elif defined JS_CPU_ARM || defined JS_CPU_SPARC
|
|
3136 |
inlineTypeJumpOffset = offset;
|
|
3137 |
JS_ASSERT(offset == inlineTypeJumpOffset);
|
|
3138 |
#endif
|
|
3139 |
@@ -225,6 +225,10 @@ struct GetPropLabels : MacroAssemblerTypedefs {
|
|
3140 |
|
|
3141 |
/* Offset from the fast path to the type guard jump. */
|
|
3142 |
int32 inlineTypeJumpOffset : 8;
|
|
3143 |
+#elif defined JS_CPU_SPARC
|
|
3144 |
+ static const int32 INLINE_SHAPE_JUMP = 48;
|
|
3145 |
+ static const int32 INLINE_TYPE_JUMP = 48;
|
|
3146 |
+ int32 inlineTypeJumpOffset : 8;
|
|
3147 |
#endif
|
|
3148 |
};
|
|
3149 |
|
|
3150 |
diff --git a/js/src/methodjit/ICRepatcher.h b/js/src/methodjit/ICRepatcher.h
|
|
3151 |
index 59d8e78..24b08b9 100644
|
|
3152 |
--- a/js/src/methodjit/ICRepatcher.h
|
|
3153 |
+++ b/js/src/methodjit/ICRepatcher.h
|
|
3154 |
@@ -72,7 +72,7 @@ class Repatcher : public JSC::RepatchBuffer
|
|
3155 |
|
|
3156 |
/* Patch a stub call. */
|
|
3157 |
void relink(CodeLocationCall call, FunctionPtr stub) {
|
|
3158 |
-#if defined JS_CPU_X64 || defined JS_CPU_X86
|
|
3159 |
+#if defined JS_CPU_X64 || defined JS_CPU_X86 || defined JS_CPU_SPARC
|
|
3160 |
JSC::RepatchBuffer::relink(call, stub);
|
|
3161 |
#elif defined JS_CPU_ARM
|
|
3162 |
/*
|
|
3163 |
@@ -95,7 +95,7 @@ class Repatcher : public JSC::RepatchBuffer
|
|
3164 |
|
|
3165 |
/* Patch the offset of a Value load emitted by loadValueWithAddressOffsetPatch. */
|
|
3166 |
void patchAddressOffsetForValueLoad(CodeLocationLabel label, uint32 offset) {
|
|
3167 |
-#if defined JS_CPU_X64 || defined JS_CPU_ARM
|
|
3168 |
+#if defined JS_CPU_X64 || defined JS_CPU_ARM || defined JS_CPU_SPARC
|
|
3169 |
repatch(label.dataLabel32AtOffset(0), offset);
|
|
3170 |
#elif defined JS_CPU_X86
|
|
3171 |
static const unsigned LOAD_TYPE_OFFSET = 6;
|
|
3172 |
@@ -115,7 +115,7 @@ class Repatcher : public JSC::RepatchBuffer
|
|
3173 |
}
|
|
3174 |
|
|
3175 |
void patchAddressOffsetForValueStore(CodeLocationLabel label, uint32 offset, bool typeConst) {
|
|
3176 |
-#if defined JS_CPU_ARM || defined JS_CPU_X64
|
|
3177 |
+#if defined JS_CPU_ARM || defined JS_CPU_X64 || defined JS_CPU_SPARC
|
|
3178 |
(void) typeConst;
|
|
3179 |
repatch(label.dataLabel32AtOffset(0), offset);
|
|
3180 |
#elif defined JS_CPU_X86
|
|
3181 |
diff --git a/js/src/methodjit/MachineRegs.h b/js/src/methodjit/MachineRegs.h
|
|
3182 |
index 149f188..c786cd3 100644
|
|
3183 |
--- a/js/src/methodjit/MachineRegs.h
|
|
3184 |
+++ b/js/src/methodjit/MachineRegs.h
|
|
3185 |
@@ -60,6 +60,7 @@ struct Registers {
|
|
3186 |
static const RegisterID TypeMaskReg = JSC::X86Registers::r13;
|
|
3187 |
static const RegisterID PayloadMaskReg = JSC::X86Registers::r14;
|
|
3188 |
static const RegisterID ValueReg = JSC::X86Registers::r10;
|
|
3189 |
+ static const RegisterID ScratchReg = JSC::X86Registers::r11;
|
|
3190 |
#endif
|
|
3191 |
|
|
3192 |
// Register that homes the current JSStackFrame.
|
|
3193 |
@@ -67,6 +68,8 @@ struct Registers {
|
|
3194 |
static const RegisterID JSFrameReg = JSC::X86Registers::ebx;
|
|
3195 |
#elif defined(JS_CPU_ARM)
|
|
3196 |
static const RegisterID JSFrameReg = JSC::ARMRegisters::r11;
|
|
3197 |
+#elif defined(JS_CPU_SPARC)
|
|
3198 |
+ static const RegisterID JSFrameReg = JSC::SparcRegisters::l0;
|
|
3199 |
#endif
|
|
3200 |
|
|
3201 |
#if defined(JS_CPU_X86) || defined(JS_CPU_X64)
|
|
3202 |
@@ -87,6 +90,14 @@ struct Registers {
|
|
3203 |
static const RegisterID ArgReg0 = JSC::ARMRegisters::r0;
|
|
3204 |
static const RegisterID ArgReg1 = JSC::ARMRegisters::r1;
|
|
3205 |
static const RegisterID ArgReg2 = JSC::ARMRegisters::r2;
|
|
3206 |
+#elif JS_CPU_SPARC
|
|
3207 |
+ static const RegisterID ReturnReg = JSC::SparcRegisters::o0;
|
|
3208 |
+ static const RegisterID ArgReg0 = JSC::SparcRegisters::o0;
|
|
3209 |
+ static const RegisterID ArgReg1 = JSC::SparcRegisters::o1;
|
|
3210 |
+ static const RegisterID ArgReg2 = JSC::SparcRegisters::o2;
|
|
3211 |
+ static const RegisterID ArgReg3 = JSC::SparcRegisters::o3;
|
|
3212 |
+ static const RegisterID ArgReg4 = JSC::SparcRegisters::o4;
|
|
3213 |
+ static const RegisterID ArgReg5 = JSC::SparcRegisters::o5;
|
|
3214 |
#endif
|
|
3215 |
|
|
3216 |
static const RegisterID StackPointer = JSC::MacroAssembler::stackPointerRegister;
|
|
3217 |
@@ -168,6 +179,30 @@ struct Registers {
|
|
3218 |
// r15 is PC (program counter).
|
|
3219 |
|
|
3220 |
static const uint32 SingleByteRegs = TempRegs | SavedRegs;
|
|
3221 |
+#elif defined(JS_CPU_SPARC)
|
|
3222 |
+ static const uint32 TempRegs =
|
|
3223 |
+ (1 << JSC::SparcRegisters::o0)
|
|
3224 |
+ | (1 << JSC::SparcRegisters::o1)
|
|
3225 |
+ | (1 << JSC::SparcRegisters::o2)
|
|
3226 |
+ | (1 << JSC::SparcRegisters::o3)
|
|
3227 |
+ | (1 << JSC::SparcRegisters::o4)
|
|
3228 |
+ | (1 << JSC::SparcRegisters::o5);
|
|
3229 |
+
|
|
3230 |
+ static const uint32 SavedRegs =
|
|
3231 |
+ (1 << JSC::SparcRegisters::l2)
|
|
3232 |
+ | (1 << JSC::SparcRegisters::l3)
|
|
3233 |
+ | (1 << JSC::SparcRegisters::l4)
|
|
3234 |
+ | (1 << JSC::SparcRegisters::l5)
|
|
3235 |
+ | (1 << JSC::SparcRegisters::l6)
|
|
3236 |
+ | (1 << JSC::SparcRegisters::l7)
|
|
3237 |
+ | (1 << JSC::SparcRegisters::i0)
|
|
3238 |
+ | (1 << JSC::SparcRegisters::i1)
|
|
3239 |
+ | (1 << JSC::SparcRegisters::i2)
|
|
3240 |
+ | (1 << JSC::SparcRegisters::i3)
|
|
3241 |
+ | (1 << JSC::SparcRegisters::i4)
|
|
3242 |
+ | (1 << JSC::SparcRegisters::i5);
|
|
3243 |
+
|
|
3244 |
+ static const uint32 SingleByteRegs = TempRegs | SavedRegs;
|
|
3245 |
#else
|
|
3246 |
# error "Unsupported platform"
|
|
3247 |
#endif
|
|
3248 |
@@ -195,6 +230,8 @@ struct Registers {
|
|
3249 |
# endif
|
|
3250 |
#elif defined(JS_CPU_ARM)
|
|
3251 |
return 4;
|
|
3252 |
+#elif defined(JS_CPU_SPARC)
|
|
3253 |
+ return 6;
|
|
3254 |
#endif
|
|
3255 |
}
|
|
3256 |
|
|
3257 |
@@ -236,6 +273,15 @@ struct Registers {
|
|
3258 |
JSC::ARMRegisters::r2,
|
|
3259 |
JSC::ARMRegisters::r3
|
|
3260 |
};
|
|
3261 |
+#elif defined(JS_CPU_SPARC)
|
|
3262 |
+ static const RegisterID regs[] = {
|
|
3263 |
+ JSC::SparcRegisters::o0,
|
|
3264 |
+ JSC::SparcRegisters::o1,
|
|
3265 |
+ JSC::SparcRegisters::o2,
|
|
3266 |
+ JSC::SparcRegisters::o3,
|
|
3267 |
+ JSC::SparcRegisters::o4,
|
|
3268 |
+ JSC::SparcRegisters::o5
|
|
3269 |
+ };
|
|
3270 |
#endif
|
|
3271 |
JS_ASSERT(numArgRegs(conv) == JS_ARRAY_LENGTH(regs));
|
|
3272 |
if (i > JS_ARRAY_LENGTH(regs))
|
|
3273 |
@@ -362,6 +408,27 @@ struct FPRegisters {
|
|
3274 |
static const FPRegisterID Second = JSC::ARMRegisters::d1;
|
|
3275 |
static const FPRegisterID Temp0 = JSC::ARMRegisters::d2;
|
|
3276 |
static const FPRegisterID Temp1 = JSC::ARMRegisters::d3;
|
|
3277 |
+#elif defined(JS_CPU_SPARC)
|
|
3278 |
+ static const uint32 TotalFPRegisters = 16;
|
|
3279 |
+ static const uint32 TempFPRegs =
|
|
3280 |
+ (1 << JSC::SparcRegisters::f0)
|
|
3281 |
+ | (1 << JSC::SparcRegisters::f2)
|
|
3282 |
+ | (1 << JSC::SparcRegisters::f4)
|
|
3283 |
+ | (1 << JSC::SparcRegisters::f6)
|
|
3284 |
+ | (1 << JSC::SparcRegisters::f8)
|
|
3285 |
+ | (1 << JSC::SparcRegisters::f10)
|
|
3286 |
+ | (1 << JSC::SparcRegisters::f12)
|
|
3287 |
+ | (1 << JSC::SparcRegisters::f14)
|
|
3288 |
+ | (1 << JSC::SparcRegisters::f16)
|
|
3289 |
+ | (1 << JSC::SparcRegisters::f18)
|
|
3290 |
+ | (1 << JSC::SparcRegisters::f20)
|
|
3291 |
+ | (1 << JSC::SparcRegisters::f22)
|
|
3292 |
+ | (1 << JSC::SparcRegisters::f24)
|
|
3293 |
+ | (1 << JSC::SparcRegisters::f26)
|
|
3294 |
+ | (1 << JSC::SparcRegisters::f28);
|
|
3295 |
+ /* FIXME: Temporary hack until FPRegister allocation exists. */
|
|
3296 |
+ static const FPRegisterID First = JSC::SparcRegisters::f0;
|
|
3297 |
+ static const FPRegisterID Second = JSC::SparcRegisters::f2;
|
|
3298 |
#else
|
|
3299 |
# error "Unsupported platform"
|
|
3300 |
#endif
|
|
3301 |
diff --git a/js/src/methodjit/MethodJIT.cpp b/js/src/methodjit/MethodJIT.cpp
|
|
3302 |
index 6169972..089a3be 100644
|
|
3303 |
--- a/js/src/methodjit/MethodJIT.cpp
|
|
3304 |
+++ b/js/src/methodjit/MethodJIT.cpp
|
|
3305 |
@@ -555,6 +555,7 @@ SYMBOL_STRING(JaegerStubVeneer) ":" "\n"
|
|
3306 |
" pop {ip,pc}" "\n"
|
|
3307 |
);
|
|
3308 |
|
|
3309 |
+# elif defined(JS_CPU_SPARC)
|
|
3310 |
# else
|
|
3311 |
# error "Unsupported CPU!"
|
|
3312 |
# endif
|
|
3313 |
diff --git a/js/src/methodjit/MethodJIT.h b/js/src/methodjit/MethodJIT.h
|
|
3314 |
index 8c2ab39..9529486 100644
|
|
3315 |
--- a/js/src/methodjit/MethodJIT.h
|
|
3316 |
+++ b/js/src/methodjit/MethodJIT.h
|
|
3317 |
@@ -45,6 +45,7 @@
|
|
3318 |
|
|
3319 |
#if !defined JS_CPU_X64 && \
|
|
3320 |
!defined JS_CPU_X86 && \
|
|
3321 |
+ !defined JS_CPU_SPARC && \
|
|
3322 |
!defined JS_CPU_ARM
|
|
3323 |
# error "Oh no, you should define a platform so this compiles."
|
|
3324 |
#endif
|
|
3325 |
@@ -59,6 +60,39 @@ namespace mjit { struct JITScript; }
|
|
3326 |
|
|
3327 |
struct VMFrame
|
|
3328 |
{
|
|
3329 |
+#if defined(JS_CPU_SPARC)
|
|
3330 |
+ void *savedL0;
|
|
3331 |
+ void *savedL1;
|
|
3332 |
+ void *savedL2;
|
|
3333 |
+ void *savedL3;
|
|
3334 |
+ void *savedL4;
|
|
3335 |
+ void *savedL5;
|
|
3336 |
+ void *savedL6;
|
|
3337 |
+ void *savedL7;
|
|
3338 |
+ void *savedI0;
|
|
3339 |
+ void *savedI1;
|
|
3340 |
+ void *savedI2;
|
|
3341 |
+ void *savedI3;
|
|
3342 |
+ void *savedI4;
|
|
3343 |
+ void *savedI5;
|
|
3344 |
+ void *savedI6;
|
|
3345 |
+ void *savedI7;
|
|
3346 |
+
|
|
3347 |
+ void *str_p;
|
|
3348 |
+
|
|
3349 |
+ void *outgoing_p0;
|
|
3350 |
+ void *outgoing_p1;
|
|
3351 |
+ void *outgoing_p2;
|
|
3352 |
+ void *outgoing_p3;
|
|
3353 |
+ void *outgoing_p4;
|
|
3354 |
+ void *outgoing_p5;
|
|
3355 |
+
|
|
3356 |
+ void *outgoing_p6;
|
|
3357 |
+
|
|
3358 |
+ void *reserve_0;
|
|
3359 |
+ void *reserve_1;
|
|
3360 |
+#endif
|
|
3361 |
+
|
|
3362 |
union Arguments {
|
|
3363 |
struct {
|
|
3364 |
void *ptr;
|
|
3365 |
@@ -131,6 +165,13 @@ struct VMFrame
|
|
3366 |
inline void** returnAddressLocation() {
|
|
3367 |
return reinterpret_cast<void**>(this) - 1;
|
|
3368 |
}
|
|
3369 |
+#elif defined(JS_CPU_SPARC)
|
|
3370 |
+ JSStackFrame *topRetrunAddr;
|
|
3371 |
+ void* veneerReturn;
|
|
3372 |
+ void* _align;
|
|
3373 |
+ inline void** returnAddressLocation() {
|
|
3374 |
+ return reinterpret_cast<void**>(&this->veneerReturn);
|
|
3375 |
+ }
|
|
3376 |
#else
|
|
3377 |
# error "The VMFrame layout isn't defined for your processor architecture!"
|
|
3378 |
#endif
|
|
3379 |
diff --git a/js/src/methodjit/MonoIC.h b/js/src/methodjit/MonoIC.h
|
|
3380 |
index 66254b1..ec33db7 100644
|
|
3381 |
--- a/js/src/methodjit/MonoIC.h
|
|
3382 |
+++ b/js/src/methodjit/MonoIC.h
|
|
3383 |
@@ -125,15 +125,15 @@ struct SetGlobalNameIC : public GlobalNameIC
|
|
3384 |
JSC::JITCode extraStub;
|
|
3385 |
|
|
3386 |
/* SET only, if we had to generate an out-of-line path. */
|
|
3387 |
- int inlineShapeJump : 10; /* Offset into inline path for shape jump. */
|
|
3388 |
- int extraShapeGuard : 6; /* Offset into stub for shape guard. */
|
|
3389 |
+ int32 inlineShapeJump : 10; /* Offset into inline path for shape jump. */
|
|
3390 |
+ int32 extraShapeGuard : 6; /* Offset into stub for shape guard. */
|
|
3391 |
bool objConst : 1; /* True if the object is constant. */
|
|
3392 |
RegisterID objReg : 5; /* Register for object, if objConst is false. */
|
|
3393 |
RegisterID shapeReg : 5; /* Register for shape; volatile. */
|
|
3394 |
bool hasExtraStub : 1; /* Extra stub is preset. */
|
|
3395 |
|
|
3396 |
- int fastRejoinOffset : 16; /* Offset from fastPathStart to rejoin. */
|
|
3397 |
- int extraStoreOffset : 16; /* Offset into store code. */
|
|
3398 |
+ int32 fastRejoinOffset : 16; /* Offset from fastPathStart to rejoin. */
|
|
3399 |
+ int32 extraStoreOffset : 16; /* Offset into store code. */
|
|
3400 |
|
|
3401 |
/* SET only. */
|
|
3402 |
ValueRemat vr; /* RHS value. */
|
|
3403 |
diff --git a/js/src/methodjit/NunboxAssembler.h b/js/src/methodjit/NunboxAssembler.h
|
|
3404 |
index 6ce0ac8..fcce552 100644
|
|
3405 |
--- a/js/src/methodjit/NunboxAssembler.h
|
|
3406 |
+++ b/js/src/methodjit/NunboxAssembler.h
|
|
3407 |
@@ -72,16 +72,24 @@ struct ImmPayload : JSC::MacroAssembler::Imm32
|
|
3408 |
|
|
3409 |
class NunboxAssembler : public JSC::MacroAssembler
|
|
3410 |
{
|
|
3411 |
+ public:
|
|
3412 |
+#ifdef IS_BIG_ENDIAN
|
|
3413 |
+ static const uint32 PAYLOAD_OFFSET = 4;
|
|
3414 |
+ static const uint32 TAG_OFFSET = 0;
|
|
3415 |
+#else
|
|
3416 |
static const uint32 PAYLOAD_OFFSET = 0;
|
|
3417 |
static const uint32 TAG_OFFSET = 4;
|
|
3418 |
+#endif
|
|
3419 |
|
|
3420 |
public:
|
|
3421 |
static const JSC::MacroAssembler::Scale JSVAL_SCALE = JSC::MacroAssembler::TimesEight;
|
|
3422 |
|
|
3423 |
- template <typename T>
|
|
3424 |
- T payloadOf(T address) {
|
|
3425 |
- JS_ASSERT(PAYLOAD_OFFSET == 0);
|
|
3426 |
- return address;
|
|
3427 |
+ Address payloadOf(Address address) {
|
|
3428 |
+ return Address(address.base, address.offset + PAYLOAD_OFFSET);
|
|
3429 |
+ }
|
|
3430 |
+
|
|
3431 |
+ BaseIndex payloadOf(BaseIndex address) {
|
|
3432 |
+ return BaseIndex(address.base, address.index, address.scale, address.offset + PAYLOAD_OFFSET);
|
|
3433 |
}
|
|
3434 |
|
|
3435 |
Address tagOf(Address address) {
|
|
3436 |
@@ -185,7 +193,7 @@ class NunboxAssembler : public JSC::MacroAssembler
|
|
3437 |
JS_ASSERT(differenceBetween(start, endType) == 6);
|
|
3438 |
JS_ASSERT(differenceBetween(endType, endPayload) == 6);
|
|
3439 |
return start;
|
|
3440 |
-#elif defined JS_CPU_ARM
|
|
3441 |
+#elif defined JS_CPU_ARM || defined JS_CPU_SPARC
|
|
3442 |
/*
|
|
3443 |
* On ARM, the first instruction loads the offset from a literal pool, so the label
|
|
3444 |
* returned points at that instruction.
|
|
3445 |
@@ -217,7 +225,7 @@ class NunboxAssembler : public JSC::MacroAssembler
|
|
3446 |
JS_ASSERT(differenceBetween(start, endType) == 6);
|
|
3447 |
JS_ASSERT(differenceBetween(endType, endPayload) == 6);
|
|
3448 |
return start;
|
|
3449 |
-#elif defined JS_CPU_ARM
|
|
3450 |
+#elif defined JS_CPU_ARM || defined JS_CPU_SPARC
|
|
3451 |
return store64WithAddressOffsetPatch(treg, dreg, address);
|
|
3452 |
#endif
|
|
3453 |
}
|
|
3454 |
@@ -233,7 +241,7 @@ class NunboxAssembler : public JSC::MacroAssembler
|
|
3455 |
JS_ASSERT(differenceBetween(start, endType) == 10);
|
|
3456 |
JS_ASSERT(differenceBetween(endType, endPayload) == 6);
|
|
3457 |
return start;
|
|
3458 |
-#elif defined JS_CPU_ARM
|
|
3459 |
+#elif defined JS_CPU_ARM || defined JS_CPU_SPARC
|
|
3460 |
return store64WithAddressOffsetPatch(type, dreg, address);
|
|
3461 |
#endif
|
|
3462 |
}
|
|
3463 |
@@ -253,7 +261,7 @@ class NunboxAssembler : public JSC::MacroAssembler
|
|
3464 |
JS_ASSERT(differenceBetween(start, endType) == 10);
|
|
3465 |
JS_ASSERT(differenceBetween(endType, endPayload) == 10);
|
|
3466 |
return start;
|
|
3467 |
-#elif defined JS_CPU_ARM
|
|
3468 |
+#elif defined JS_CPU_ARM || defined JS_CPU_SPARC
|
|
3469 |
return store64WithAddressOffsetPatch(type, payload, address);
|
|
3470 |
#endif
|
|
3471 |
}
|
|
3472 |
@@ -435,6 +443,8 @@ class NunboxAssembler : public JSC::MacroAssembler
|
|
3473 |
m_assembler.movd_rr(srcDest, dataReg);
|
|
3474 |
m_assembler.psrldq_rr(srcDest, 4);
|
|
3475 |
m_assembler.movd_rr(srcDest, typeReg);
|
|
3476 |
+#elif defined JS_CPU_SPARC
|
|
3477 |
+ breakDoubleTo32(srcDest, typeReg, dataReg);
|
|
3478 |
#else
|
|
3479 |
JS_NOT_REACHED("implement this - push double, pop pop is easiest");
|
|
3480 |
#endif
|
|
3481 |
diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp
|
|
3482 |
index aa82dab..dc7f3da 100644
|
|
3483 |
--- a/js/src/methodjit/PolyIC.cpp
|
|
3484 |
+++ b/js/src/methodjit/PolyIC.cpp
|
|
3485 |
@@ -431,7 +431,7 @@ class SetPropCompiler : public PICStubCompiler
|
|
3486 |
for (Jump *pj = otherGuards.begin(); pj != otherGuards.end(); ++pj)
|
|
3487 |
pj->linkTo(masm.label(), &masm);
|
|
3488 |
slowExit = masm.jump();
|
|
3489 |
- pic.secondShapeGuard = masm.distanceOf(masm.label()) - masm.distanceOf(start);
|
|
3490 |
+ pic.secondShapeGuard = masm.differenceBetween(start, slowExit.get());
|
|
3491 |
} else {
|
|
3492 |
pic.secondShapeGuard = 0;
|
|
3493 |
}
|
|
3494 |
@@ -1075,7 +1075,7 @@ class GetPropCompiler : public PICStubCompiler
|
|
3495 |
if (!shapeMismatches.append(j))
|
|
3496 |
return error();
|
|
3497 |
|
|
3498 |
- pic.secondShapeGuard = masm.distanceOf(masm.label()) - masm.distanceOf(start);
|
|
3499 |
+ pic.secondShapeGuard = masm.differenceBetween(start, j);
|
|
3500 |
} else {
|
|
3501 |
pic.secondShapeGuard = 0;
|
|
3502 |
}
|
|
3503 |
diff --git a/js/src/methodjit/PolyIC.h b/js/src/methodjit/PolyIC.h
|
|
3504 |
index 14e53e3..f6a025f 100644
|
|
3505 |
--- a/js/src/methodjit/PolyIC.h
|
|
3506 |
+++ b/js/src/methodjit/PolyIC.h
|
|
3507 |
@@ -94,7 +94,7 @@ struct BaseIC : public MacroAssemblerTypedefs {
|
|
3508 |
// Offset from start of stub to jump target of second shape guard as Nitro
|
|
3509 |
// asm data location. This is 0 if there is only one shape guard in the
|
|
3510 |
// last stub.
|
|
3511 |
- int secondShapeGuard : 11;
|
|
3512 |
+ int32 secondShapeGuard : 11;
|
|
3513 |
|
|
3514 |
// Opcode this was compiled for.
|
|
3515 |
JSOp op : 9;
|
|
3516 |
@@ -255,9 +255,9 @@ struct GetElementIC : public BasePolyIC {
|
|
3517 |
// These offsets are used for string-key dependent stubs, such as named
|
|
3518 |
// property accesses. They are separated from the int-key dependent stubs,
|
|
3519 |
// in order to guarantee that the id type needs only one guard per type.
|
|
3520 |
- int atomGuard : 8; // optional, non-zero if present
|
|
3521 |
- int firstShapeGuard : 8; // always set
|
|
3522 |
- int secondShapeGuard : 8; // optional, non-zero if present
|
|
3523 |
+ int32 atomGuard : 8; // optional, non-zero if present
|
|
3524 |
+ int32 firstShapeGuard : 11; // always set
|
|
3525 |
+ int32 secondShapeGuard : 11; // optional, non-zero if present
|
|
3526 |
|
|
3527 |
bool hasLastStringStub : 1;
|
|
3528 |
JITCode lastStringStub;
|
|
3529 |
@@ -336,7 +336,7 @@ struct SetElementIC : public BaseIC {
|
|
3530 |
|
|
3531 |
// A bitmask of registers that are volatile and must be preserved across
|
|
3532 |
// stub calls inside the IC.
|
|
3533 |
- uint32 volatileMask : 16;
|
|
3534 |
+ uint32 volatileMask;
|
|
3535 |
|
|
3536 |
// If true, then keyValue contains a constant index value >= 0. Otherwise,
|
|
3537 |
// keyReg contains a dynamic integer index in any range.
|
|
3538 |
diff --git a/js/src/methodjit/TrampolineSparc.s b/js/src/methodjit/TrampolineSparc.s
|
|
3539 |
new file mode 100644
|
|
3540 |
index 0000000..7fb929f
|
|
3541 |
--- /dev/null
|
|
3542 |
+++ b/js/src/methodjit/TrampolineSparc.s
|
|
3543 |
@@ -0,0 +1,117 @@
|
|
3544 |
+! -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
3545 |
+! ***** BEGIN LICENSE BLOCK *****
|
|
3546 |
+! Version: MPL 1.1!GPL 2.0!LGPL 2.1
|
|
3547 |
+!
|
|
3548 |
+! The contents of this file are subject to the Mozilla Public License Version
|
|
3549 |
+! 1.1 (the "License")! you may not use this file except in compliance with
|
|
3550 |
+! the License. You may obtain a copy of the License at
|
|
3551 |
+! http:!!www.mozilla.org!MPL!
|
|
3552 |
+!
|
|
3553 |
+! Software distributed under the License is distributed on an "AS IS" basis,
|
|
3554 |
+! WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
3555 |
+! for the specific language governing rights and limitations under the
|
|
3556 |
+! License.
|
|
3557 |
+!
|
|
3558 |
+! The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
|
|
3559 |
+! May 28, 2008.
|
|
3560 |
+!
|
|
3561 |
+! The Initial Developer of the Original Code is
|
|
3562 |
+! Leon Sha <[email protected]>
|
|
3563 |
+!
|
|
3564 |
+! Portions created by the Initial Developer are Copyright (C) 2010-2011
|
|
3565 |
+! the Initial Developer. All Rights Reserved.
|
|
3566 |
+!
|
|
3567 |
+! Contributor(s):
|
|
3568 |
+!
|
|
3569 |
+! Alternatively, the contents of this file may be used under the terms of
|
|
3570 |
+! either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
3571 |
+! the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
3572 |
+! in which case the provisions of the GPL or the LGPL are applicable instead
|
|
3573 |
+! of those above. If you wish to allow use of your version of this file only
|
|
3574 |
+! under the terms of either the GPL or the LGPL, and not to allow others to
|
|
3575 |
+! use your version of this file under the terms of the MPL, indicate your
|
|
3576 |
+! decision by deleting the provisions above and replace them with the notice
|
|
3577 |
+! and other provisions required by the GPL or the LGPL. If you do not delete
|
|
3578 |
+! the provisions above, a recipient may use your version of this file under
|
|
3579 |
+! the terms of any one of the MPL, the GPL or the LGPL.
|
|
3580 |
+!
|
|
3581 |
+! ***** END LICENSE BLOCK *****
|
|
3582 |
+
|
|
3583 |
+.text
|
|
3584 |
+
|
|
3585 |
+! JSBool JaegerTrampoline(JSContext *cx, JSStackFrame *fp, void *code,
|
|
3586 |
+! , uintptr_t inlineCallCount)
|
|
3587 |
+.global JaegerTrampoline
|
|
3588 |
+.type JaegerTrampoline, #function
|
|
3589 |
+JaegerTrampoline:
|
|
3590 |
+ save %sp,-160,%sp
|
|
3591 |
+ st %i3, [%fp - 20] ! stackLimit
|
|
3592 |
+ st %i0, [%fp - 24] ! cx
|
|
3593 |
+ st %i1, [%fp - 16] ! entryFp
|
|
3594 |
+ st %i1, [%fp - 28] ! regs->fp
|
|
3595 |
+ mov %i1, %l0 ! fp
|
|
3596 |
+ call SetVMFrameRegs
|
|
3597 |
+ mov %sp, %o0
|
|
3598 |
+ call PushActiveVMFrame
|
|
3599 |
+ mov %sp, %o0
|
|
3600 |
+ jmp %i2
|
|
3601 |
+ st %i7, [%fp - 12] ! return address
|
|
3602 |
+.size JaegerTrampoline, . - JaegerTrampoline
|
|
3603 |
+
|
|
3604 |
+! void JaegerTrampolineReturn()
|
|
3605 |
+.global JaegerTrampolineReturn
|
|
3606 |
+.type JaegerTrampolineReturn, #function
|
|
3607 |
+JaegerTrampolineReturn:
|
|
3608 |
+ st %i0, [%l0 + 0x18] /* fp->rval type */
|
|
3609 |
+ st %i1, [%l0 + 0x1c] /* fp->rval data */
|
|
3610 |
+ call PopActiveVMFrame
|
|
3611 |
+ mov %sp, %o0
|
|
3612 |
+ ld [%fp - 12], %i7 ! return address
|
|
3613 |
+ mov 1, %i0
|
|
3614 |
+ ret
|
|
3615 |
+ restore
|
|
3616 |
+.size JaegerTrampolineReturn, . - JaegerTrampolineReturn
|
|
3617 |
+
|
|
3618 |
+! void *JaegerThrowpoline(js::VMFrame *vmFrame)
|
|
3619 |
+.global JaegerThrowpoline
|
|
3620 |
+.type JaegerThrowpoline, #function
|
|
3621 |
+JaegerThrowpoline:
|
|
3622 |
+ call js_InternalThrow
|
|
3623 |
+ mov %sp,%o0
|
|
3624 |
+ tst %o0
|
|
3625 |
+ be throwpoline_exit
|
|
3626 |
+ nop
|
|
3627 |
+ jmp %o0
|
|
3628 |
+ nop
|
|
3629 |
+throwpoline_exit:
|
|
3630 |
+ ta 3
|
|
3631 |
+ mov %sp, %o2
|
|
3632 |
+ mov %fp, %o3
|
|
3633 |
+ ldd [%o2 + (0*8)], %l0
|
|
3634 |
+ ldd [%o2 + (1*8)], %l2
|
|
3635 |
+ ldd [%o2 + (2*8)], %l4
|
|
3636 |
+ ldd [%o2 + (3*8)], %l6
|
|
3637 |
+ ldd [%o2 + (4*8)], %i0
|
|
3638 |
+ ldd [%o2 + (5*8)], %i2
|
|
3639 |
+ ldd [%o2 + (6*8)], %i4
|
|
3640 |
+ ldd [%o2 + (7*8)], %i6
|
|
3641 |
+ ld [%o3 - 12], %i7 ! return address
|
|
3642 |
+ mov %o2, %sp
|
|
3643 |
+ call PopActiveVMFrame
|
|
3644 |
+ mov %sp, %o0
|
|
3645 |
+ clr %i0
|
|
3646 |
+ ret
|
|
3647 |
+ restore
|
|
3648 |
+.size JaegerThrowpoline, . - JaegerThrowpoline
|
|
3649 |
+
|
|
3650 |
+.global InjectJaegerReturn
|
|
3651 |
+.type InjectJaegerReturn, #function
|
|
3652 |
+InjectJaegerReturn:
|
|
3653 |
+ ld [%l0 + 0x18], %i0 /* fp->rval type */
|
|
3654 |
+ ld [%l0 + 0x1c], %i1 /* fp->rval data */
|
|
3655 |
+ ld [%l0 + 0x14], %i7 /* fp->ncode */
|
|
3656 |
+ sub %i7, 8, %i7
|
|
3657 |
+ ld [%fp - 28], %l0
|
|
3658 |
+ ret
|
|
3659 |
+ nop
|
|
3660 |
+.size InjectJaegerReturn, . - InjectJaegerReturn
|
|
3661 |
diff --git a/js/src/methodjit/TypedArrayIC.h b/js/src/methodjit/TypedArrayIC.h
|
|
3662 |
index 88f8175..f97e6b0 100644
|
|
3663 |
--- a/js/src/methodjit/TypedArrayIC.h
|
|
3664 |
+++ b/js/src/methodjit/TypedArrayIC.h
|
|
3665 |
@@ -46,7 +46,7 @@
|
|
3666 |
namespace js {
|
|
3667 |
namespace mjit {
|
|
3668 |
|
|
3669 |
-#if defined(JS_POLYIC) && (defined JS_CPU_X86 || defined JS_CPU_X64)
|
|
3670 |
+#if defined(JS_POLYIC_TYPED_ARRAY)
|
|
3671 |
|
|
3672 |
typedef JSC::MacroAssembler::RegisterID RegisterID;
|
|
3673 |
typedef JSC::MacroAssembler::FPRegisterID FPRegisterID;
|
|
3674 |
diff --git a/js/src/nanojit/NativeSparc.cpp b/js/src/nanojit/NativeSparc.cpp
|
|
3675 |
index 029a22a..a73be3d 100644
|
|
3676 |
--- a/js/src/nanojit/NativeSparc.cpp
|
|
3677 |
+++ b/js/src/nanojit/NativeSparc.cpp
|
|
3678 |
@@ -46,9 +46,33 @@
|
|
3679 |
namespace nanojit
|
|
3680 |
{
|
|
3681 |
#ifdef FEATURE_NANOJIT
|
|
3682 |
+ class SafeUnderrunProtect
|
|
3683 |
+ {
|
|
3684 |
+ public:
|
|
3685 |
+ SafeUnderrunProtect(Assembler* assembler, int n)
|
|
3686 |
+ {
|
|
3687 |
+ _nprotect = n;
|
|
3688 |
+ _assembler = assembler;
|
|
3689 |
+ _assembler->underrunProtect(n);
|
|
3690 |
+ _priorIns = _assembler->_nIns;
|
|
3691 |
+ _priorStart = _assembler->codeStart;
|
|
3692 |
+ };
|
|
3693 |
+
|
|
3694 |
+ ~SafeUnderrunProtect()
|
|
3695 |
+ {
|
|
3696 |
+ NanoAssert(_priorStart == _assembler->codeStart);
|
|
3697 |
+ NanoAssert((intptr_t)_priorIns - (intptr_t)_assembler->_nIns <= _nprotect);
|
|
3698 |
+ };
|
|
3699 |
+
|
|
3700 |
+ private:
|
|
3701 |
+ int _nprotect;
|
|
3702 |
+ Assembler* _assembler;
|
|
3703 |
+ NIns* _priorIns;
|
|
3704 |
+ NIns* _priorStart;
|
|
3705 |
+ };
|
|
3706 |
|
|
3707 |
#ifdef NJ_VERBOSE
|
|
3708 |
- const char *regNames[] = {
|
|
3709 |
+ const char* regNames[] = {
|
|
3710 |
"%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7",
|
|
3711 |
"%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7",
|
|
3712 |
"%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7",
|
|
3713 |
@@ -78,13 +102,13 @@ namespace nanojit
|
|
3714 |
}
|
|
3715 |
|
|
3716 |
inline void Assembler::IntegerOperation
|
|
3717 |
- (Register rs1, Register rs2, Register rd, int32_t op3, const char *opcode) {
|
|
3718 |
+ (Register rs1, Register rs2, Register rd, int32_t op3, const char* opcode) {
|
|
3719 |
Format_3_1(2, rd, op3, rs1, 0, rs2);
|
|
3720 |
asm_output("%s %s, %s, %s", opcode, gpn(rs1), gpn(rs2), gpn(rd));
|
|
3721 |
}
|
|
3722 |
|
|
3723 |
inline void Assembler::IntegerOperationI
|
|
3724 |
- (Register rs1, int32_t simm13, Register rd, int32_t op3, const char *opcode) {
|
|
3725 |
+ (Register rs1, int32_t simm13, Register rd, int32_t op3, const char* opcode) {
|
|
3726 |
Format_3_1I(2, rd, op3, rs1, simm13);
|
|
3727 |
asm_output("%s %s, %d, %s", opcode, gpn(rs1), simm13, gpn(rd));
|
|
3728 |
}
|
|
3729 |
@@ -126,9 +150,9 @@ namespace nanojit
|
|
3730 |
IntegerOperation(rs1, rs2, rd, 0x3, "xor");
|
|
3731 |
}
|
|
3732 |
|
|
3733 |
- inline void Assembler::Bicc(int32_t a, int32_t dsp22, int32_t cond, const char *opcode) {
|
|
3734 |
+ inline void Assembler::Bicc(int32_t a, int32_t dsp22, int32_t cond, const char* opcode) {
|
|
3735 |
Format_2_2(a, cond, 0x2, dsp22);
|
|
3736 |
- asm_output("%s 0x%x", opcode, _nIns + dsp22 - 1);
|
|
3737 |
+ asm_output("%s 0x%x", opcode, _nIns + dsp22);
|
|
3738 |
}
|
|
3739 |
|
|
3740 |
inline void Assembler::BA (int32_t a, int32_t dsp22) { Bicc(a, dsp22, 0x8, "ba"); }
|
|
3741 |
@@ -155,7 +179,7 @@ namespace nanojit
|
|
3742 |
asm_output("faddd %s, %s, %s", gpn(rs1), gpn(rs2), gpn(rd));
|
|
3743 |
}
|
|
3744 |
|
|
3745 |
- inline void Assembler::FBfcc(int32_t a, int32_t dsp22, int32_t cond, const char *opcode) {
|
|
3746 |
+ inline void Assembler::FBfcc(int32_t a, int32_t dsp22, int32_t cond, const char* opcode) {
|
|
3747 |
Format_2_2(a, cond, 0x6, dsp22);
|
|
3748 |
asm_output("%s 0x%x", opcode, _nIns + dsp22 - 1);
|
|
3749 |
}
|
|
3750 |
@@ -178,7 +202,7 @@ namespace nanojit
|
|
3751 |
}
|
|
3752 |
|
|
3753 |
inline void Assembler::FloatOperation
|
|
3754 |
- (Register rs1, Register rs2, Register rd, int32_t opf, const char *opcode) {
|
|
3755 |
+ (Register rs1, Register rs2, Register rd, int32_t opf, const char* opcode) {
|
|
3756 |
Format_3_8(2, rd, 0x34, rs1, opf, rs2);
|
|
3757 |
if (rs1 != G0) {
|
|
3758 |
asm_output("%s %s, %s, %s", opcode, gpn(rs1), gpn(rs2), gpn(rd));
|
|
3759 |
@@ -346,13 +370,13 @@ namespace nanojit
|
|
3760 |
}
|
|
3761 |
|
|
3762 |
inline void Assembler::MOVcc
|
|
3763 |
- (Register rs, int32_t cc2, int32_t cc1, int32_t cc0, Register rd, int32_t cond, const char *opcode) {
|
|
3764 |
+ (Register rs, int32_t cc2, int32_t cc1, int32_t cc0, Register rd, int32_t cond, const char* opcode) {
|
|
3765 |
Format_4_2(rd, 0x2c, cc2, cond, cc1, cc0, rs);
|
|
3766 |
asm_output("%s %s, %s", opcode, gpn(rs), gpn(rd));
|
|
3767 |
}
|
|
3768 |
|
|
3769 |
inline void Assembler::MOVccI
|
|
3770 |
- (int32_t simm11, int32_t cc2, int32_t cc1, int32_t cc0, Register rd, int32_t cond, const char *opcode) {
|
|
3771 |
+ (int32_t simm11, int32_t cc2, int32_t cc1, int32_t cc0, Register rd, int32_t cond, const char* opcode) {
|
|
3772 |
Format_4_2I(rd, 0x2c, cc2, cond, cc1, cc0, simm11);
|
|
3773 |
asm_output("%s 0x%x, %s", opcode, simm11, gpn(rd));
|
|
3774 |
}
|
|
3775 |
@@ -385,7 +409,7 @@ namespace nanojit
|
|
3776 |
inline void Assembler::MOVFGI (int32_t simm11, Register rd) { MOVccI(simm11, 0, 0, 0, rd, 0x6, "movfg"); }
|
|
3777 |
inline void Assembler::MOVFGEI(int32_t simm11, Register rd) { MOVccI(simm11, 0, 0, 0, rd, 0xb, "movfge"); }
|
|
3778 |
|
|
3779 |
- inline void Assembler::FMOVDcc(Register rs, int32_t opt_cc, Register rd, int32_t cond, const char *opcode) {
|
|
3780 |
+ inline void Assembler::FMOVDcc(Register rs, int32_t opt_cc, Register rd, int32_t cond, const char* opcode) {
|
|
3781 |
Format_4_5(rd, 0x35, cond, opt_cc, 0x2, rs);
|
|
3782 |
asm_output("%s %s, %s", opcode, gpn(rs), gpn(rd));
|
|
3783 |
}
|
|
3784 |
@@ -555,24 +579,31 @@ namespace nanojit
|
|
3785 |
}
|
|
3786 |
|
|
3787 |
// general Assemble
|
|
3788 |
- inline void Assembler::JMP_long_nocheck(int32_t t) {
|
|
3789 |
+ inline void Assembler::JMP_long(int32_t t) {
|
|
3790 |
+ SafeUnderrunProtect protect(this, 16);
|
|
3791 |
+ /* if (t) {
|
|
3792 |
+ int32_t tt = ((intptr_t)t - (intptr_t)_nIns + 16) >> 2;
|
|
3793 |
+ if (isIMM22(tt)) {
|
|
3794 |
+ NOP();
|
|
3795 |
+ NOP();
|
|
3796 |
+ NOP();
|
|
3797 |
+ BA(0,tt);
|
|
3798 |
+ return;
|
|
3799 |
+ }
|
|
3800 |
+ }
|
|
3801 |
+*/
|
|
3802 |
NOP();
|
|
3803 |
JMPL(G0, G2, G0);
|
|
3804 |
ORI(G2, t & 0x3FF, G2);
|
|
3805 |
SETHI(t, G2);
|
|
3806 |
}
|
|
3807 |
|
|
3808 |
- inline void Assembler::JMP_long(int32_t t) {
|
|
3809 |
- underrunProtect(16);
|
|
3810 |
- JMP_long_nocheck(t);
|
|
3811 |
- }
|
|
3812 |
-
|
|
3813 |
inline void Assembler::JMP_long_placeholder() {
|
|
3814 |
JMP_long(0);
|
|
3815 |
}
|
|
3816 |
|
|
3817 |
- inline int32_t Assembler::JCC(void *t) {
|
|
3818 |
- underrunProtect(32);
|
|
3819 |
+ inline int32_t Assembler::JCC(void* t) {
|
|
3820 |
+ SafeUnderrunProtect protect(this, 32);
|
|
3821 |
int32_t tt = ((intptr_t)t - (intptr_t)_nIns + 8) >> 2;
|
|
3822 |
if( !(isIMM22(tt)) ) {
|
|
3823 |
NOP();
|
|
3824 |
@@ -586,7 +617,7 @@ namespace nanojit
|
|
3825 |
return tt;
|
|
3826 |
}
|
|
3827 |
|
|
3828 |
- void Assembler::JMP(void *t) {
|
|
3829 |
+ void Assembler::JMP(void* t) {
|
|
3830 |
if (!t) {
|
|
3831 |
JMP_long_placeholder();
|
|
3832 |
} else {
|
|
3833 |
@@ -596,7 +627,6 @@ namespace nanojit
|
|
3834 |
}
|
|
3835 |
|
|
3836 |
void Assembler::MR(Register rd, Register rs) {
|
|
3837 |
- underrunProtect(4);
|
|
3838 |
ORI(rs, 0, rd);
|
|
3839 |
}
|
|
3840 |
|
|
3841 |
@@ -613,7 +643,7 @@ namespace nanojit
|
|
3842 |
/**
|
|
3843 |
* Prologue
|
|
3844 |
*/
|
|
3845 |
- underrunProtect(16);
|
|
3846 |
+ SafeUnderrunProtect protect(this, 28);
|
|
3847 |
uint32_t stackNeeded = STACK_GRANULARITY * _activation.stackSlotsNeeded();
|
|
3848 |
uint32_t frameSize = stackNeeded + kcalleeAreaSize + kLinkageAreaSize;
|
|
3849 |
frameSize = BIT_ROUND_UP(frameSize, 8);
|
|
3850 |
@@ -631,7 +661,7 @@ namespace nanojit
|
|
3851 |
outputf(" 0x%x:",_nIns);
|
|
3852 |
outputf(" patch entry:");
|
|
3853 |
})
|
|
3854 |
- NIns *patchEntry = _nIns;
|
|
3855 |
+ NIns* patchEntry = _nIns;
|
|
3856 |
|
|
3857 |
// The frame size in SAVE is faked. We will still re-caculate SP later.
|
|
3858 |
// We can use 0 here but it is not good for debuggers.
|
|
3859 |
@@ -643,7 +673,8 @@ namespace nanojit
|
|
3860 |
return patchEntry;
|
|
3861 |
}
|
|
3862 |
|
|
3863 |
- void Assembler::asm_align_code() {
|
|
3864 |
+ void Assembler::asm_align_code()
|
|
3865 |
+ {
|
|
3866 |
while(uintptr_t(_nIns) & 15) {
|
|
3867 |
NOP();
|
|
3868 |
}
|
|
3869 |
@@ -652,30 +683,27 @@ namespace nanojit
|
|
3870 |
void Assembler::nFragExit(LIns* guard)
|
|
3871 |
{
|
|
3872 |
SideExit* exit = guard->record()->exit;
|
|
3873 |
- Fragment *frag = exit->target;
|
|
3874 |
- GuardRecord *lr;
|
|
3875 |
- if (frag && frag->fragEntry)
|
|
3876 |
- {
|
|
3877 |
- JMP(frag->fragEntry);
|
|
3878 |
- lr = 0;
|
|
3879 |
- }
|
|
3880 |
- else
|
|
3881 |
- {
|
|
3882 |
- // Target doesn't exit yet. Emit jump to epilog, and set up to patch later.
|
|
3883 |
- if (!_epilogue)
|
|
3884 |
- _epilogue = genEpilogue();
|
|
3885 |
- lr = guard->record();
|
|
3886 |
- JMP_long((intptr_t)_epilogue);
|
|
3887 |
- lr->jmp = _nIns;
|
|
3888 |
- }
|
|
3889 |
+ Fragment* frag = exit->target;
|
|
3890 |
+ GuardRecord* lr;
|
|
3891 |
+ if (frag && frag->fragEntry) {
|
|
3892 |
+ JMP(frag->fragEntry);
|
|
3893 |
+ lr = 0;
|
|
3894 |
+ } else {
|
|
3895 |
+ // Target doesn't exit yet. Emit jump to epilog, and set up to patch later.
|
|
3896 |
+ if (!_epilogue)
|
|
3897 |
+ _epilogue = genEpilogue();
|
|
3898 |
+ lr = guard->record();
|
|
3899 |
+ JMP_long((intptr_t)_epilogue);
|
|
3900 |
+ lr->jmp = _nIns;
|
|
3901 |
+ }
|
|
3902 |
|
|
3903 |
// return value is GuardRecord*
|
|
3904 |
SET32(int(lr), O0);
|
|
3905 |
}
|
|
3906 |
|
|
3907 |
- NIns *Assembler::genEpilogue()
|
|
3908 |
+ NIns* Assembler::genEpilogue()
|
|
3909 |
{
|
|
3910 |
- underrunProtect(12);
|
|
3911 |
+ SafeUnderrunProtect protect(this, 12);
|
|
3912 |
RESTORE(G0, G0, G0); //restore
|
|
3913 |
JMPLI(I7, 8, G0); //ret
|
|
3914 |
ORI(O0, 0, I0);
|
|
3915 |
@@ -685,19 +713,15 @@ namespace nanojit
|
|
3916 |
void Assembler::asm_call(LIns* ins)
|
|
3917 |
{
|
|
3918 |
if (!ins->isop(LIR_callv)) {
|
|
3919 |
- Register retReg = ( ins->isop(LIR_calld) ? F0 : retRegs[0] );
|
|
3920 |
- deprecated_prepResultReg(ins, rmask(retReg));
|
|
3921 |
+ Register retReg = (ins->isop(LIR_calld) ? F0 : retRegs[0]);
|
|
3922 |
+ prepareResultReg(ins, rmask(retReg));
|
|
3923 |
+ evictScratchRegsExcept(rmask(retReg));
|
|
3924 |
+ } else {
|
|
3925 |
+ evictScratchRegsExcept(0);
|
|
3926 |
}
|
|
3927 |
|
|
3928 |
- // Do this after we've handled the call result, so we don't
|
|
3929 |
- // force the call result to be spilled unnecessarily.
|
|
3930 |
- evictScratchRegsExcept(0);
|
|
3931 |
-
|
|
3932 |
const CallInfo* ci = ins->callInfo();
|
|
3933 |
|
|
3934 |
- underrunProtect(8);
|
|
3935 |
- NOP();
|
|
3936 |
-
|
|
3937 |
ArgType argTypes[MAXARGS];
|
|
3938 |
uint32_t argc = ci->getArgTypes(argTypes);
|
|
3939 |
|
|
3940 |
@@ -705,53 +729,59 @@ namespace nanojit
|
|
3941 |
ins->isop(LIR_calld));
|
|
3942 |
verbose_only(if (_logc->lcbits & LC_Native)
|
|
3943 |
outputf(" 0x%x:", _nIns);
|
|
3944 |
- )
|
|
3945 |
+ )
|
|
3946 |
bool indirect = ci->isIndirect();
|
|
3947 |
- if (!indirect) {
|
|
3948 |
- CALL(ci);
|
|
3949 |
- }
|
|
3950 |
- else {
|
|
3951 |
- argc--;
|
|
3952 |
- Register r = findSpecificRegFor(ins->arg(argc), I0);
|
|
3953 |
- JMPL(G0, I0, O7);
|
|
3954 |
+
|
|
3955 |
+ {
|
|
3956 |
+ SafeUnderrunProtect protect(this, 8);
|
|
3957 |
+ NOP();
|
|
3958 |
+ if (!indirect) {
|
|
3959 |
+ CALL(ci);
|
|
3960 |
+ }
|
|
3961 |
+ else {
|
|
3962 |
+ argc--;
|
|
3963 |
+ Register r = findSpecificRegFor(ins->arg(argc), I0);
|
|
3964 |
+ JMPL(G0, I0, O7);
|
|
3965 |
+ }
|
|
3966 |
}
|
|
3967 |
|
|
3968 |
+ freeResourcesOf(ins);
|
|
3969 |
+
|
|
3970 |
Register GPRIndex = O0;
|
|
3971 |
uint32_t offset = kLinkageAreaSize; // start of parameters stack postion.
|
|
3972 |
|
|
3973 |
- for(int i=0; i<argc; i++)
|
|
3974 |
- {
|
|
3975 |
- uint32_t j = argc-i-1;
|
|
3976 |
- ArgType ty = argTypes[j];
|
|
3977 |
- if (ty == ARGTYPE_D) {
|
|
3978 |
- Register r = findRegFor(ins->arg(j), FpRegs);
|
|
3979 |
-
|
|
3980 |
- underrunProtect(48);
|
|
3981 |
- // We might be calling a varargs function.
|
|
3982 |
- // So, make sure the GPR's are also loaded with
|
|
3983 |
- // the value, or the stack contains it.
|
|
3984 |
- if (GPRIndex <= O5) {
|
|
3985 |
- LDSW32(SP, offset, GPRIndex);
|
|
3986 |
- }
|
|
3987 |
- GPRIndex = GPRIndex + 1;
|
|
3988 |
- if (GPRIndex <= O5) {
|
|
3989 |
- LDSW32(SP, offset+4, GPRIndex);
|
|
3990 |
- }
|
|
3991 |
- GPRIndex = GPRIndex + 1;
|
|
3992 |
- STDF32(r, offset, SP);
|
|
3993 |
- offset += 8;
|
|
3994 |
+ for (int i = 0; i < argc; i++) {
|
|
3995 |
+ uint32_t j = argc-i-1;
|
|
3996 |
+ ArgType ty = argTypes[j];
|
|
3997 |
+ if (ty == ARGTYPE_D) {
|
|
3998 |
+ Register r = findRegFor(ins->arg(j), FpRegs);
|
|
3999 |
+
|
|
4000 |
+ SafeUnderrunProtect protect(this, 48);
|
|
4001 |
+ // We might be calling a varargs function.
|
|
4002 |
+ // So, make sure the GPR's are also loaded with
|
|
4003 |
+ // the value, or the stack contains it.
|
|
4004 |
+ if (GPRIndex <= O5) {
|
|
4005 |
+ LDSW32(SP, offset, GPRIndex);
|
|
4006 |
+ }
|
|
4007 |
+ GPRIndex = GPRIndex + 1;
|
|
4008 |
+ if (GPRIndex <= O5) {
|
|
4009 |
+ LDSW32(SP, offset+4, GPRIndex);
|
|
4010 |
+ }
|
|
4011 |
+ GPRIndex = GPRIndex + 1;
|
|
4012 |
+ STDF32(r, offset, SP);
|
|
4013 |
+ offset += 8;
|
|
4014 |
+ } else {
|
|
4015 |
+ if (GPRIndex > O5) {
|
|
4016 |
+ SafeUnderrunProtect protect(this, 12);
|
|
4017 |
+ Register r = findRegFor(ins->arg(j), GpRegs);
|
|
4018 |
+ STW32(r, offset, SP);
|
|
4019 |
} else {
|
|
4020 |
- if (GPRIndex > O5) {
|
|
4021 |
- underrunProtect(12);
|
|
4022 |
- Register r = findRegFor(ins->arg(j), GpRegs);
|
|
4023 |
- STW32(r, offset, SP);
|
|
4024 |
- } else {
|
|
4025 |
- Register r = findSpecificRegFor(ins->arg(j), GPRIndex);
|
|
4026 |
- }
|
|
4027 |
- GPRIndex = GPRIndex + 1;
|
|
4028 |
- offset += 4;
|
|
4029 |
+ Register r = findSpecificRegFor(ins->arg(j), GPRIndex);
|
|
4030 |
}
|
|
4031 |
+ GPRIndex = GPRIndex + 1;
|
|
4032 |
+ offset += 4;
|
|
4033 |
}
|
|
4034 |
+ }
|
|
4035 |
}
|
|
4036 |
|
|
4037 |
Register Assembler::nRegisterAllocFromSet(RegisterMask set)
|
|
4038 |
@@ -772,10 +802,16 @@ namespace nanojit
|
|
4039 |
|
|
4040 |
void Assembler::nPatchBranch(NIns* branch, NIns* location)
|
|
4041 |
{
|
|
4042 |
- *(uint32_t*)&branch[0] &= 0xFFC00000;
|
|
4043 |
- *(uint32_t*)&branch[0] |= ((intptr_t)location >> 10) & 0x3FFFFF;
|
|
4044 |
- *(uint32_t*)&branch[1] &= 0xFFFFFC00;
|
|
4045 |
- *(uint32_t*)&branch[1] |= (intptr_t)location & 0x3FF;
|
|
4046 |
+ intptr_t addr_diff = ((intptr_t)location - (intptr_t)branch) >> 2;
|
|
4047 |
+ if ( !isIMM22(addr_diff)) {
|
|
4048 |
+ *(uint32_t*)&branch[0] = 0x05000000 | ((intptr_t)location >> 10) & 0x3FFFFF; // sethi ..., %g2
|
|
4049 |
+ *(uint32_t*)&branch[1] = 0x8410a000 | (intptr_t)location & 0x3FF; // bset ..., %g2
|
|
4050 |
+ *(uint32_t*)&branch[2] = 0x81c00002; // jmp %g2
|
|
4051 |
+ } else {
|
|
4052 |
+ *(uint32_t*)&branch[0] = 0x10800000 | (addr_diff & 0x3FFFFF); // ba
|
|
4053 |
+ *(uint32_t*)&branch[1] = 0x01000000; // nop
|
|
4054 |
+ *(uint32_t*)&branch[2] = 0x01000000; // nop
|
|
4055 |
+ }
|
|
4056 |
}
|
|
4057 |
|
|
4058 |
RegisterMask Assembler::nHint(LIns* ins)
|
|
4059 |
@@ -792,10 +828,10 @@ namespace nanojit
|
|
4060 |
|
|
4061 |
void Assembler::asm_restore(LIns* i, Register r)
|
|
4062 |
{
|
|
4063 |
- underrunProtect(24);
|
|
4064 |
+ SafeUnderrunProtect protect(this, 24);
|
|
4065 |
if (i->isop(LIR_allocp)) {
|
|
4066 |
ADD(FP, L2, r);
|
|
4067 |
- int32_t d = deprecated_disp(i);
|
|
4068 |
+ int32_t d = arDisp(i);
|
|
4069 |
SET32(d, L2);
|
|
4070 |
}
|
|
4071 |
else if (i->isImmI()) {
|
|
4072 |
@@ -811,7 +847,7 @@ namespace nanojit
|
|
4073 |
}
|
|
4074 |
}
|
|
4075 |
|
|
4076 |
- void Assembler::asm_store32(LOpcode op, LIns *value, int dr, LIns *base)
|
|
4077 |
+ void Assembler::asm_store32(LOpcode op, LIns* value, int dr, LIns* base)
|
|
4078 |
{
|
|
4079 |
switch (op) {
|
|
4080 |
case LIR_sti:
|
|
4081 |
@@ -824,53 +860,38 @@ namespace nanojit
|
|
4082 |
return;
|
|
4083 |
}
|
|
4084 |
|
|
4085 |
- underrunProtect(20);
|
|
4086 |
- if (value->isImmI())
|
|
4087 |
- {
|
|
4088 |
- Register rb = getBaseReg(base, dr, GpRegs);
|
|
4089 |
- int c = value->immI();
|
|
4090 |
- switch (op) {
|
|
4091 |
- case LIR_sti:
|
|
4092 |
- STW32(L2, dr, rb);
|
|
4093 |
- break;
|
|
4094 |
- case LIR_sti2c:
|
|
4095 |
- STB32(L2, dr, rb);
|
|
4096 |
- break;
|
|
4097 |
- case LIR_sti2s:
|
|
4098 |
- STH32(L2, dr, rb);
|
|
4099 |
- break;
|
|
4100 |
- }
|
|
4101 |
- SET32(c, L2);
|
|
4102 |
+ SafeUnderrunProtect protect(this, 20);
|
|
4103 |
+ if (value->isImmI()) {
|
|
4104 |
+ Register rb = getBaseReg(base, dr, GpRegs);
|
|
4105 |
+ int c = value->immI();
|
|
4106 |
+ switch (op) {
|
|
4107 |
+ case LIR_sti: STW32(L2, dr, rb); break;
|
|
4108 |
+ case LIR_sti2c: STB32(L2, dr, rb); break;
|
|
4109 |
+ case LIR_sti2s: STH32(L2, dr, rb); break;
|
|
4110 |
}
|
|
4111 |
- else
|
|
4112 |
- {
|
|
4113 |
- // make sure what is in a register
|
|
4114 |
- Register ra, rb;
|
|
4115 |
- if (base->isImmI()) {
|
|
4116 |
- // absolute address
|
|
4117 |
- dr += base->immI();
|
|
4118 |
- ra = findRegFor(value, GpRegs);
|
|
4119 |
- rb = G0;
|
|
4120 |
- } else {
|
|
4121 |
- getBaseReg2(GpRegs, value, ra, GpRegs, base, rb, dr);
|
|
4122 |
- }
|
|
4123 |
- switch (op) {
|
|
4124 |
- case LIR_sti:
|
|
4125 |
- STW32(ra, dr, rb);
|
|
4126 |
- break;
|
|
4127 |
- case LIR_sti2c:
|
|
4128 |
- STB32(ra, dr, rb);
|
|
4129 |
- break;
|
|
4130 |
- case LIR_sti2s:
|
|
4131 |
- STH32(ra, dr, rb);
|
|
4132 |
- break;
|
|
4133 |
- }
|
|
4134 |
+ SET32(c, L2);
|
|
4135 |
+ } else {
|
|
4136 |
+ // make sure what is in a register
|
|
4137 |
+ Register ra, rb;
|
|
4138 |
+ if (base->isImmI()) {
|
|
4139 |
+ // absolute address
|
|
4140 |
+ dr += base->immI();
|
|
4141 |
+ ra = findRegFor(value, GpRegs);
|
|
4142 |
+ rb = G0;
|
|
4143 |
+ } else {
|
|
4144 |
+ getBaseReg2(GpRegs, value, ra, GpRegs, base, rb, dr);
|
|
4145 |
+ }
|
|
4146 |
+ switch (op) {
|
|
4147 |
+ case LIR_sti: STW32(ra, dr, rb); break;
|
|
4148 |
+ case LIR_sti2c: STB32(ra, dr, rb); break;
|
|
4149 |
+ case LIR_sti2s: STH32(ra, dr, rb); break;
|
|
4150 |
}
|
|
4151 |
+ }
|
|
4152 |
}
|
|
4153 |
|
|
4154 |
void Assembler::asm_spill(Register rr, int d, bool quad)
|
|
4155 |
{
|
|
4156 |
- underrunProtect(24);
|
|
4157 |
+ SafeUnderrunProtect protect(this, 24);
|
|
4158 |
(void)quad;
|
|
4159 |
NanoAssert(d);
|
|
4160 |
if (rmask(rr) & FpRegs) {
|
|
4161 |
@@ -892,7 +913,7 @@ namespace nanojit
|
|
4162 |
return;
|
|
4163 |
}
|
|
4164 |
|
|
4165 |
- underrunProtect(48);
|
|
4166 |
+ SafeUnderrunProtect protect(this, 48);
|
|
4167 |
LIns* base = ins->oprnd1();
|
|
4168 |
int db = ins->disp();
|
|
4169 |
Register rb = getBaseReg(base, db, GpRegs);
|
|
4170 |
@@ -937,7 +958,7 @@ namespace nanojit
|
|
4171 |
return;
|
|
4172 |
}
|
|
4173 |
|
|
4174 |
- underrunProtect(48);
|
|
4175 |
+ SafeUnderrunProtect protect(this, 48);
|
|
4176 |
Register rb = getBaseReg(base, dr, GpRegs);
|
|
4177 |
if (op == LIR_std2f) {
|
|
4178 |
Register rv = ( !value->isInReg()
|
|
4179 |
@@ -949,32 +970,30 @@ namespace nanojit
|
|
4180 |
return;
|
|
4181 |
}
|
|
4182 |
|
|
4183 |
- if (value->isImmD())
|
|
4184 |
- {
|
|
4185 |
- // if a constant 64-bit value just store it now rather than
|
|
4186 |
- // generating a pointless store/load/store sequence
|
|
4187 |
- STW32(L2, dr+4, rb);
|
|
4188 |
- SET32(value->immDlo(), L2);
|
|
4189 |
- STW32(L2, dr, rb);
|
|
4190 |
- SET32(value->immDhi(), L2);
|
|
4191 |
- return;
|
|
4192 |
- }
|
|
4193 |
+ if (value->isImmD()) {
|
|
4194 |
+ // if a constant 64-bit value just store it now rather than
|
|
4195 |
+ // generating a pointless store/load/store sequence
|
|
4196 |
+ STW32(L2, dr+4, rb);
|
|
4197 |
+ SET32(value->immDlo(), L2);
|
|
4198 |
+ STW32(L2, dr, rb);
|
|
4199 |
+ SET32(value->immDhi(), L2);
|
|
4200 |
+ return;
|
|
4201 |
+ }
|
|
4202 |
|
|
4203 |
- if (value->isop(LIR_ldd))
|
|
4204 |
- {
|
|
4205 |
- // value is 64bit struct or int64_t, or maybe a double.
|
|
4206 |
- // it may be live in an FPU reg. Either way, don't
|
|
4207 |
- // put it in an FPU reg just to load & store it.
|
|
4208 |
+ if (value->isop(LIR_ldd)) {
|
|
4209 |
+ // value is 64bit struct or int64_t, or maybe a double.
|
|
4210 |
+ // it may be live in an FPU reg. Either way, don't
|
|
4211 |
+ // put it in an FPU reg just to load & store it.
|
|
4212 |
|
|
4213 |
- // a) if we know it's not a double, this is right.
|
|
4214 |
- // b) if we guarded that its a double, this store could be on
|
|
4215 |
- // the side exit, copying a non-double.
|
|
4216 |
- // c) maybe its a double just being stored. oh well.
|
|
4217 |
+ // a) if we know it's not a double, this is right.
|
|
4218 |
+ // b) if we guarded that its a double, this store could be on
|
|
4219 |
+ // the side exit, copying a non-double.
|
|
4220 |
+ // c) maybe its a double just being stored. oh well.
|
|
4221 |
|
|
4222 |
- int da = findMemFor(value);
|
|
4223 |
- asm_mmq(rb, dr, FP, da);
|
|
4224 |
- return;
|
|
4225 |
- }
|
|
4226 |
+ int da = findMemFor(value);
|
|
4227 |
+ asm_mmq(rb, dr, FP, da);
|
|
4228 |
+ return;
|
|
4229 |
+ }
|
|
4230 |
|
|
4231 |
// if value already in a reg, use that, otherwise
|
|
4232 |
// get it into FPU regs.
|
|
4233 |
@@ -1005,66 +1024,56 @@ namespace nanojit
|
|
4234 |
NIns* at = 0;
|
|
4235 |
LOpcode condop = cond->opcode();
|
|
4236 |
NanoAssert(cond->isCmp());
|
|
4237 |
- if (isCmpDOpcode(condop))
|
|
4238 |
- {
|
|
4239 |
- return asm_branchd(branchOnFalse, cond, targ);
|
|
4240 |
- }
|
|
4241 |
-
|
|
4242 |
- underrunProtect(32);
|
|
4243 |
- intptr_t tt = ((intptr_t)targ - (intptr_t)_nIns + 8) >> 2;
|
|
4244 |
- // !targ means that it needs patch.
|
|
4245 |
- if( !(isIMM22((int32_t)tt)) || !targ ) {
|
|
4246 |
- JMP_long_nocheck((intptr_t)targ);
|
|
4247 |
- at = _nIns;
|
|
4248 |
- NOP();
|
|
4249 |
- BA(0, 5);
|
|
4250 |
- tt = 4;
|
|
4251 |
+ if (isCmpDOpcode(condop)) {
|
|
4252 |
+ return asm_branchd(branchOnFalse, cond, targ);
|
|
4253 |
}
|
|
4254 |
- NOP();
|
|
4255 |
|
|
4256 |
- // produce the branch
|
|
4257 |
- if (branchOnFalse)
|
|
4258 |
- {
|
|
4259 |
- if (condop == LIR_eqi)
|
|
4260 |
- BNE(0, tt);
|
|
4261 |
- else if (condop == LIR_lti)
|
|
4262 |
- BGE(0, tt);
|
|
4263 |
- else if (condop == LIR_lei)
|
|
4264 |
- BG(0, tt);
|
|
4265 |
- else if (condop == LIR_gti)
|
|
4266 |
- BLE(0, tt);
|
|
4267 |
- else if (condop == LIR_gei)
|
|
4268 |
- BL(0, tt);
|
|
4269 |
- else if (condop == LIR_ltui)
|
|
4270 |
- BCC(0, tt);
|
|
4271 |
- else if (condop == LIR_leui)
|
|
4272 |
- BGU(0, tt);
|
|
4273 |
- else if (condop == LIR_gtui)
|
|
4274 |
- BLEU(0, tt);
|
|
4275 |
- else //if (condop == LIR_geui)
|
|
4276 |
- BCS(0, tt);
|
|
4277 |
+ {
|
|
4278 |
+ SafeUnderrunProtect protect(this, 32);
|
|
4279 |
+ intptr_t tt = ((intptr_t)targ - (intptr_t)_nIns + 8) >> 2;
|
|
4280 |
+ // !targ means that it needs patch.
|
|
4281 |
+ if( !(isIMM22((int32_t)tt)) || !targ ) {
|
|
4282 |
+ JMP_long((intptr_t)targ);
|
|
4283 |
+ at = _nIns;
|
|
4284 |
+ NOP();
|
|
4285 |
+ BA(0, 5);
|
|
4286 |
+ tt = 4;
|
|
4287 |
}
|
|
4288 |
- else // op == LIR_xt
|
|
4289 |
- {
|
|
4290 |
- if (condop == LIR_eqi)
|
|
4291 |
- BE(0, tt);
|
|
4292 |
- else if (condop == LIR_lti)
|
|
4293 |
- BL(0, tt);
|
|
4294 |
- else if (condop == LIR_lei)
|
|
4295 |
- BLE(0, tt);
|
|
4296 |
- else if (condop == LIR_gti)
|
|
4297 |
- BG(0, tt);
|
|
4298 |
- else if (condop == LIR_gei)
|
|
4299 |
- BGE(0, tt);
|
|
4300 |
- else if (condop == LIR_ltui)
|
|
4301 |
- BCS(0, tt);
|
|
4302 |
- else if (condop == LIR_leui)
|
|
4303 |
- BLEU(0, tt);
|
|
4304 |
- else if (condop == LIR_gtui)
|
|
4305 |
- BGU(0, tt);
|
|
4306 |
- else //if (condop == LIR_geui)
|
|
4307 |
- BCC(0, tt);
|
|
4308 |
+ NOP();
|
|
4309 |
+
|
|
4310 |
+ // produce the branch
|
|
4311 |
+ if (branchOnFalse) {
|
|
4312 |
+ switch (condop) {
|
|
4313 |
+ case LIR_eqi : BNE (0, tt); break;
|
|
4314 |
+ case LIR_lti : BGE (0, tt); break;
|
|
4315 |
+ case LIR_lei : BG (0, tt); break;
|
|
4316 |
+ case LIR_gti : BLE (0, tt); break;
|
|
4317 |
+ case LIR_gei : BL (0, tt); break;
|
|
4318 |
+ case LIR_ltui: BCC (0, tt); break;
|
|
4319 |
+ case LIR_leui: BGU (0, tt); break;
|
|
4320 |
+ case LIR_gtui: BLEU(0, tt); break;
|
|
4321 |
+ case LIR_geui: BCS (0, tt); break;
|
|
4322 |
+ default:
|
|
4323 |
+ NanoAssertMsg(0, "asm_branch should never receive this cond opcode");
|
|
4324 |
+ return;
|
|
4325 |
+ }
|
|
4326 |
+ } else {// op == LIR_xt
|
|
4327 |
+ switch (condop) {
|
|
4328 |
+ case LIR_eqi : BE (0, tt); break;
|
|
4329 |
+ case LIR_lti : BL (0, tt); break;
|
|
4330 |
+ case LIR_lei : BLE (0, tt); break;
|
|
4331 |
+ case LIR_gti : BG (0, tt); break;
|
|
4332 |
+ case LIR_gei : BGE (0, tt); break;
|
|
4333 |
+ case LIR_ltui: BCS (0, tt); break;
|
|
4334 |
+ case LIR_leui: BLEU(0, tt); break;
|
|
4335 |
+ case LIR_gtui: BGU (0, tt); break;
|
|
4336 |
+ case LIR_geui: BCC (0, tt); break;
|
|
4337 |
+ default:
|
|
4338 |
+ NanoAssertMsg(0, "asm_branch should never receive this cond opcode");
|
|
4339 |
+ return;
|
|
4340 |
+ }
|
|
4341 |
}
|
|
4342 |
+ }
|
|
4343 |
asm_cmp(cond);
|
|
4344 |
return at;
|
|
4345 |
}
|
|
4346 |
@@ -1072,11 +1081,11 @@ namespace nanojit
|
|
4347 |
NIns* Assembler::asm_branch_ov(LOpcode op, NIns* targ)
|
|
4348 |
{
|
|
4349 |
NIns* at = 0;
|
|
4350 |
- underrunProtect(32);
|
|
4351 |
+ SafeUnderrunProtect protect(this, 32);
|
|
4352 |
intptr_t tt = ((intptr_t)targ - (intptr_t)_nIns + 8) >> 2;
|
|
4353 |
// !targ means that it needs patch.
|
|
4354 |
- if( !(isIMM22((int32_t)tt)) || !targ ) {
|
|
4355 |
- JMP_long_nocheck((intptr_t)targ);
|
|
4356 |
+ if (!(isIMM22((int32_t)tt)) || !targ) {
|
|
4357 |
+ JMP_long((intptr_t)targ);
|
|
4358 |
at = _nIns;
|
|
4359 |
NOP();
|
|
4360 |
BA(0, 5);
|
|
4361 |
@@ -1084,242 +1093,264 @@ namespace nanojit
|
|
4362 |
}
|
|
4363 |
NOP();
|
|
4364 |
|
|
4365 |
- if( op == LIR_mulxovi || op == LIR_muljovi )
|
|
4366 |
+ if (op == LIR_mulxovi || op == LIR_muljovi)
|
|
4367 |
BNE(0, tt);
|
|
4368 |
else
|
|
4369 |
BVS(0, tt);
|
|
4370 |
return at;
|
|
4371 |
}
|
|
4372 |
|
|
4373 |
- void Assembler::asm_cmp(LIns *cond)
|
|
4374 |
+ void Assembler::asm_cmp(LIns* cond)
|
|
4375 |
{
|
|
4376 |
- underrunProtect(12);
|
|
4377 |
-
|
|
4378 |
LIns* lhs = cond->oprnd1();
|
|
4379 |
LIns* rhs = cond->oprnd2();
|
|
4380 |
|
|
4381 |
NanoAssert(lhs->isI() && rhs->isI());
|
|
4382 |
|
|
4383 |
// ready to issue the compare
|
|
4384 |
- if (rhs->isImmI())
|
|
4385 |
- {
|
|
4386 |
- int c = rhs->immI();
|
|
4387 |
- Register r = findRegFor(lhs, GpRegs);
|
|
4388 |
- if (c == 0 && cond->isop(LIR_eqi)) {
|
|
4389 |
- ANDCC(r, r, G0);
|
|
4390 |
- }
|
|
4391 |
- else {
|
|
4392 |
- SUBCC(r, L2, G0);
|
|
4393 |
- SET32(c, L2);
|
|
4394 |
- }
|
|
4395 |
- }
|
|
4396 |
- else
|
|
4397 |
- {
|
|
4398 |
- Register ra, rb;
|
|
4399 |
- findRegFor2(GpRegs, lhs, ra, GpRegs, rhs, rb);
|
|
4400 |
- SUBCC(ra, rb, G0);
|
|
4401 |
+ if (rhs->isImmI()) {
|
|
4402 |
+ int c = rhs->immI();
|
|
4403 |
+ Register r = findRegFor(lhs, GpRegs);
|
|
4404 |
+ SafeUnderrunProtect protect(this, 12);
|
|
4405 |
+ if (c == 0 && cond->isop(LIR_eqi)) {
|
|
4406 |
+ ANDCC(r, r, G0);
|
|
4407 |
+ } else {
|
|
4408 |
+ SUBCC(r, L2, G0);
|
|
4409 |
+ SET32(c, L2);
|
|
4410 |
}
|
|
4411 |
+ } else {
|
|
4412 |
+ Register ra, rb;
|
|
4413 |
+ findRegFor2(GpRegs, lhs, ra, GpRegs, rhs, rb);
|
|
4414 |
+ SUBCC(ra, rb, G0);
|
|
4415 |
+ }
|
|
4416 |
}
|
|
4417 |
|
|
4418 |
void Assembler::asm_condd(LIns* ins)
|
|
4419 |
{
|
|
4420 |
// only want certain regs
|
|
4421 |
- Register r = deprecated_prepResultReg(ins, AllowableFlagRegs);
|
|
4422 |
- underrunProtect(8);
|
|
4423 |
+ Register r = prepareResultReg(ins, AllowableFlagRegs);
|
|
4424 |
+ SafeUnderrunProtect protect(this, 12);
|
|
4425 |
LOpcode condop = ins->opcode();
|
|
4426 |
NanoAssert(isCmpDOpcode(condop));
|
|
4427 |
- if (condop == LIR_eqd)
|
|
4428 |
- MOVFEI(1, r);
|
|
4429 |
- else if (condop == LIR_led)
|
|
4430 |
- MOVFLEI(1, r);
|
|
4431 |
- else if (condop == LIR_ltd)
|
|
4432 |
- MOVFLI(1, r);
|
|
4433 |
- else if (condop == LIR_ged)
|
|
4434 |
- MOVFGEI(1, r);
|
|
4435 |
- else // if (condop == LIR_gtd)
|
|
4436 |
- MOVFGI(1, r);
|
|
4437 |
+ switch (condop) {
|
|
4438 |
+ case LIR_eqd: MOVFEI (1, r); break;
|
|
4439 |
+ case LIR_led: MOVFLEI(1, r); break;
|
|
4440 |
+ case LIR_ltd: MOVFLI (1, r); break;
|
|
4441 |
+ case LIR_ged: MOVFGEI(1, r); break;
|
|
4442 |
+ case LIR_gtd: MOVFGI (1, r); break;
|
|
4443 |
+ default:
|
|
4444 |
+ NanoAssertMsg(0, "asm_condd should never receive this cond opcode");
|
|
4445 |
+ return;
|
|
4446 |
+ }
|
|
4447 |
ORI(G0, 0, r);
|
|
4448 |
+ freeResourcesOf(ins);
|
|
4449 |
asm_cmpd(ins);
|
|
4450 |
}
|
|
4451 |
|
|
4452 |
void Assembler::asm_cond(LIns* ins)
|
|
4453 |
{
|
|
4454 |
- underrunProtect(8);
|
|
4455 |
// only want certain regs
|
|
4456 |
- LOpcode op = ins->opcode();
|
|
4457 |
- Register r = deprecated_prepResultReg(ins, AllowableFlagRegs);
|
|
4458 |
-
|
|
4459 |
- if (op == LIR_eqi)
|
|
4460 |
- MOVEI(1, r);
|
|
4461 |
- else if (op == LIR_lti)
|
|
4462 |
- MOVLI(1, r);
|
|
4463 |
- else if (op == LIR_lei)
|
|
4464 |
- MOVLEI(1, r);
|
|
4465 |
- else if (op == LIR_gti)
|
|
4466 |
- MOVGI(1, r);
|
|
4467 |
- else if (op == LIR_gei)
|
|
4468 |
- MOVGEI(1, r);
|
|
4469 |
- else if (op == LIR_ltui)
|
|
4470 |
- MOVCSI(1, r);
|
|
4471 |
- else if (op == LIR_leui)
|
|
4472 |
- MOVLEUI(1, r);
|
|
4473 |
- else if (op == LIR_gtui)
|
|
4474 |
- MOVGUI(1, r);
|
|
4475 |
- else // if (op == LIR_geui)
|
|
4476 |
- MOVCCI(1, r);
|
|
4477 |
+ LOpcode condop = ins->opcode();
|
|
4478 |
+ Register r = prepareResultReg(ins, AllowableFlagRegs);
|
|
4479 |
+ SafeUnderrunProtect protect(this, 20);
|
|
4480 |
+
|
|
4481 |
+ switch (condop) {
|
|
4482 |
+ case LIR_eqi : MOVEI (1, r); break;
|
|
4483 |
+ case LIR_lti : MOVLI (1, r); break;
|
|
4484 |
+ case LIR_lei : MOVLEI (1, r); break;
|
|
4485 |
+ case LIR_gti : MOVGI (1, r); break;
|
|
4486 |
+ case LIR_gei : MOVGEI (1, r); break;
|
|
4487 |
+ case LIR_ltui: MOVCSI (1, r); break;
|
|
4488 |
+ case LIR_leui: MOVLEUI(1, r); break;
|
|
4489 |
+ case LIR_gtui: MOVGUI (1, r); break;
|
|
4490 |
+ case LIR_geui: MOVCCI (1, r); break;
|
|
4491 |
+ default:
|
|
4492 |
+ NanoAssertMsg(0, "asm_cond should never receive this cond opcode");
|
|
4493 |
+ return;
|
|
4494 |
+ }
|
|
4495 |
ORI(G0, 0, r);
|
|
4496 |
+ freeResourcesOf(ins);
|
|
4497 |
asm_cmp(ins);
|
|
4498 |
}
|
|
4499 |
|
|
4500 |
void Assembler::asm_arith(LIns* ins)
|
|
4501 |
{
|
|
4502 |
- underrunProtect(28);
|
|
4503 |
+ SafeUnderrunProtect protect(this, 28);
|
|
4504 |
LOpcode op = ins->opcode();
|
|
4505 |
LIns* lhs = ins->oprnd1();
|
|
4506 |
LIns* rhs = ins->oprnd2();
|
|
4507 |
|
|
4508 |
- Register rb = deprecated_UnknownReg;
|
|
4509 |
+ Register rb;
|
|
4510 |
RegisterMask allow = GpRegs;
|
|
4511 |
bool forceReg = (op == LIR_muli || op == LIR_mulxovi || op == LIR_muljovi || !rhs->isImmI());
|
|
4512 |
|
|
4513 |
- if (lhs != rhs && forceReg)
|
|
4514 |
- {
|
|
4515 |
- if ((rb = asm_binop_rhs_reg(ins)) == deprecated_UnknownReg) {
|
|
4516 |
- rb = findRegFor(rhs, allow);
|
|
4517 |
- }
|
|
4518 |
- allow &= ~rmask(rb);
|
|
4519 |
- }
|
|
4520 |
- else if ((op == LIR_addi || op == LIR_addxovi || op == LIR_addjovi) && lhs->isop(LIR_allocp) && rhs->isImmI()) {
|
|
4521 |
+ if (lhs != rhs && forceReg) {
|
|
4522 |
+ rb = findRegFor(rhs, allow);
|
|
4523 |
+ allow &= ~rmask(rb);
|
|
4524 |
+ } else if ((op == LIR_addi || op == LIR_addxovi || op == LIR_addjovi) && lhs->isop(LIR_allocp) && rhs->isImmI()) {
|
|
4525 |
// add alloc+const, use lea
|
|
4526 |
- Register rr = deprecated_prepResultReg(ins, allow);
|
|
4527 |
+ Register rr = prepareResultReg(ins, allow);
|
|
4528 |
int d = findMemFor(lhs) + rhs->immI();
|
|
4529 |
+ SafeUnderrunProtect protect(this, 12);
|
|
4530 |
ADD(FP, L2, rr);
|
|
4531 |
SET32(d, L2);
|
|
4532 |
+ freeResourcesOf(ins);
|
|
4533 |
return;
|
|
4534 |
}
|
|
4535 |
|
|
4536 |
- Register rr = deprecated_prepResultReg(ins, allow);
|
|
4537 |
- // if this is last use of lhs in reg, we can re-use result reg
|
|
4538 |
- // else, lhs already has a register assigned.
|
|
4539 |
- Register ra = ( !lhs->isInReg()
|
|
4540 |
- ? findSpecificRegFor(lhs, rr)
|
|
4541 |
- : lhs->deprecated_getReg() );
|
|
4542 |
+ Register rr = prepareResultReg(ins, allow);
|
|
4543 |
|
|
4544 |
- if (forceReg)
|
|
4545 |
- {
|
|
4546 |
- if (lhs == rhs)
|
|
4547 |
- rb = ra;
|
|
4548 |
+ // If 'lhs' isn't in a register, it can be clobbered by 'ins'.
|
|
4549 |
+ Register ra = lhs->isInReg() ? lhs->getReg() : rr;
|
|
4550 |
+
|
|
4551 |
+ if (forceReg) {
|
|
4552 |
+ if (lhs == rhs)
|
|
4553 |
+ rb = ra;
|
|
4554 |
|
|
4555 |
- if (op == LIR_addi || op == LIR_addxovi || op == LIR_addjovi)
|
|
4556 |
+ switch (op) {
|
|
4557 |
+ case LIR_addi:
|
|
4558 |
+ case LIR_addxovi:
|
|
4559 |
+ case LIR_addjovi:
|
|
4560 |
ADDCC(rr, rb, rr);
|
|
4561 |
- else if (op == LIR_subi || op == LIR_subxovi || op == LIR_subjovi)
|
|
4562 |
+ break;
|
|
4563 |
+ case LIR_subi:
|
|
4564 |
+ case LIR_subxovi:
|
|
4565 |
+ case LIR_subjovi:
|
|
4566 |
SUBCC(rr, rb, rr);
|
|
4567 |
- else if (op == LIR_muli)
|
|
4568 |
+ break;
|
|
4569 |
+ case LIR_muli:
|
|
4570 |
SMULCC(rr, rb, rr);
|
|
4571 |
- else if (op == LIR_mulxovi || op == LIR_muljovi) {
|
|
4572 |
+ break;
|
|
4573 |
+ case LIR_mulxovi:
|
|
4574 |
+ case LIR_muljovi:
|
|
4575 |
SUBCC(L4, L6, L4);
|
|
4576 |
SRAI(rr, 31, L6);
|
|
4577 |
RDY(L4);
|
|
4578 |
SMULCC(rr, rb, rr);
|
|
4579 |
- }
|
|
4580 |
- else if (op == LIR_andi)
|
|
4581 |
+ break;
|
|
4582 |
+ case LIR_andi:
|
|
4583 |
AND(rr, rb, rr);
|
|
4584 |
- else if (op == LIR_ori)
|
|
4585 |
+ break;
|
|
4586 |
+ case LIR_ori:
|
|
4587 |
OR(rr, rb, rr);
|
|
4588 |
- else if (op == LIR_xori)
|
|
4589 |
+ break;
|
|
4590 |
+ case LIR_xori:
|
|
4591 |
XOR(rr, rb, rr);
|
|
4592 |
- else if (op == LIR_lshi)
|
|
4593 |
+ break;
|
|
4594 |
+ case LIR_lshi:
|
|
4595 |
SLL(rr, rb, rr);
|
|
4596 |
- else if (op == LIR_rshi)
|
|
4597 |
+ break;
|
|
4598 |
+ case LIR_rshi:
|
|
4599 |
SRA(rr, rb, rr);
|
|
4600 |
- else if (op == LIR_rshui)
|
|
4601 |
+ break;
|
|
4602 |
+ case LIR_rshui:
|
|
4603 |
SRL(rr, rb, rr);
|
|
4604 |
- else
|
|
4605 |
+ break;
|
|
4606 |
+ default:
|
|
4607 |
NanoAssertMsg(0, "Unsupported");
|
|
4608 |
+ return;
|
|
4609 |
}
|
|
4610 |
- else
|
|
4611 |
- {
|
|
4612 |
- int c = rhs->immI();
|
|
4613 |
- if (op == LIR_addi || op == LIR_addxovi || op == LIR_addjovi)
|
|
4614 |
+ } else {
|
|
4615 |
+ int c = rhs->immI();
|
|
4616 |
+ switch (op) {
|
|
4617 |
+ case LIR_addi:
|
|
4618 |
+ case LIR_addxovi:
|
|
4619 |
+ case LIR_addjovi:
|
|
4620 |
ADDCC(rr, L2, rr);
|
|
4621 |
- else if (op == LIR_subi || op == LIR_subxovi || op == LIR_subjovi)
|
|
4622 |
+ break;
|
|
4623 |
+ case LIR_subi:
|
|
4624 |
+ case LIR_subxovi:
|
|
4625 |
+ case LIR_subjovi:
|
|
4626 |
SUBCC(rr, L2, rr);
|
|
4627 |
- else if (op == LIR_andi)
|
|
4628 |
+ break;
|
|
4629 |
+ case LIR_andi:
|
|
4630 |
AND(rr, L2, rr);
|
|
4631 |
- else if (op == LIR_ori)
|
|
4632 |
+ break;
|
|
4633 |
+ case LIR_ori:
|
|
4634 |
OR(rr, L2, rr);
|
|
4635 |
- else if (op == LIR_xori)
|
|
4636 |
+ break;
|
|
4637 |
+ case LIR_xori:
|
|
4638 |
XOR(rr, L2, rr);
|
|
4639 |
- else if (op == LIR_lshi)
|
|
4640 |
+ break;
|
|
4641 |
+ case LIR_lshi:
|
|
4642 |
SLL(rr, L2, rr);
|
|
4643 |
- else if (op == LIR_rshi)
|
|
4644 |
+ break;
|
|
4645 |
+ case LIR_rshi:
|
|
4646 |
SRA(rr, L2, rr);
|
|
4647 |
- else if (op == LIR_rshui)
|
|
4648 |
+ break;
|
|
4649 |
+ case LIR_rshui:
|
|
4650 |
SRL(rr, L2, rr);
|
|
4651 |
- else
|
|
4652 |
+ break;
|
|
4653 |
+ default:
|
|
4654 |
NanoAssertMsg(0, "Unsupported");
|
|
4655 |
- SET32(c, L2);
|
|
4656 |
+ return;
|
|
4657 |
}
|
|
4658 |
+ SET32(c, L2);
|
|
4659 |
+ }
|
|
4660 |
|
|
4661 |
- if ( rr != ra )
|
|
4662 |
+ if (rr != ra)
|
|
4663 |
ORI(ra, 0, rr);
|
|
4664 |
+
|
|
4665 |
+ freeResourcesOf(ins);
|
|
4666 |
+ if (!lhs->isInReg()) {
|
|
4667 |
+ NanoAssert(ra == rr);
|
|
4668 |
+ findSpecificRegForUnallocated(lhs, ra);
|
|
4669 |
+ }
|
|
4670 |
}
|
|
4671 |
|
|
4672 |
void Assembler::asm_neg_not(LIns* ins)
|
|
4673 |
{
|
|
4674 |
- underrunProtect(8);
|
|
4675 |
LOpcode op = ins->opcode();
|
|
4676 |
- Register rr = deprecated_prepResultReg(ins, GpRegs);
|
|
4677 |
+ Register rr = prepareResultReg(ins, GpRegs);
|
|
4678 |
|
|
4679 |
+ SafeUnderrunProtect protect(this, 16);
|
|
4680 |
LIns* lhs = ins->oprnd1();
|
|
4681 |
- // if this is last use of lhs in reg, we can re-use result reg
|
|
4682 |
- // else, lhs already has a register assigned.
|
|
4683 |
- Register ra = ( !lhs->isInReg()
|
|
4684 |
- ? findSpecificRegFor(lhs, rr)
|
|
4685 |
- : lhs->deprecated_getReg() );
|
|
4686 |
+ // If 'lhs' isn't in a register, it can be clobbered by 'ins'.
|
|
4687 |
+ Register ra = lhs->isInReg() ? lhs->getReg() : rr;
|
|
4688 |
|
|
4689 |
if (op == LIR_noti)
|
|
4690 |
ORN(G0, rr, rr);
|
|
4691 |
else
|
|
4692 |
SUB(G0, rr, rr);
|
|
4693 |
|
|
4694 |
- if ( rr != ra )
|
|
4695 |
+ if (rr != ra)
|
|
4696 |
ORI(ra, 0, rr);
|
|
4697 |
+
|
|
4698 |
+ freeResourcesOf(ins);
|
|
4699 |
+ if (!lhs->isInReg()) {
|
|
4700 |
+ NanoAssert(ra == rr);
|
|
4701 |
+ findSpecificRegForUnallocated(lhs, ra);
|
|
4702 |
+ }
|
|
4703 |
}
|
|
4704 |
|
|
4705 |
void Assembler::asm_load32(LIns* ins)
|
|
4706 |
{
|
|
4707 |
- underrunProtect(12);
|
|
4708 |
LOpcode op = ins->opcode();
|
|
4709 |
LIns* base = ins->oprnd1();
|
|
4710 |
int d = ins->disp();
|
|
4711 |
- Register rr = deprecated_prepResultReg(ins, GpRegs);
|
|
4712 |
+ Register rr = prepareResultReg(ins, GpRegs);
|
|
4713 |
Register ra = getBaseReg(base, d, GpRegs);
|
|
4714 |
+
|
|
4715 |
+ SafeUnderrunProtect protect(this, 12);
|
|
4716 |
switch(op) {
|
|
4717 |
- case LIR_lduc2ui:
|
|
4718 |
- LDUB32(ra, d, rr);
|
|
4719 |
- break;
|
|
4720 |
- case LIR_ldus2ui:
|
|
4721 |
- LDUH32(ra, d, rr);
|
|
4722 |
- break;
|
|
4723 |
- case LIR_ldi:
|
|
4724 |
- LDSW32(ra, d, rr);
|
|
4725 |
- break;
|
|
4726 |
- case LIR_ldc2i:
|
|
4727 |
- LDSB32(ra, d, rr);
|
|
4728 |
- break;
|
|
4729 |
- case LIR_lds2i:
|
|
4730 |
- LDSH32(ra, d, rr);
|
|
4731 |
- break;
|
|
4732 |
+ case LIR_lduc2ui: LDUB32(ra, d, rr); break;
|
|
4733 |
+ case LIR_ldus2ui: LDUH32(ra, d, rr); break;
|
|
4734 |
+ case LIR_ldi : LDSW32(ra, d, rr); break;
|
|
4735 |
+ case LIR_ldc2i : LDSB32(ra, d, rr); break;
|
|
4736 |
+ case LIR_lds2i : LDSH32(ra, d, rr); break;
|
|
4737 |
default:
|
|
4738 |
NanoAssertMsg(0, "asm_load32 should never receive this LIR opcode");
|
|
4739 |
return;
|
|
4740 |
}
|
|
4741 |
+ freeResourcesOf(ins);
|
|
4742 |
+ if (!base->isop(LIR_allocp) && !base->isInReg()) {
|
|
4743 |
+ NanoAssert(ra == rr);
|
|
4744 |
+ findSpecificRegForUnallocated(base, ra);
|
|
4745 |
+ }
|
|
4746 |
}
|
|
4747 |
|
|
4748 |
void Assembler::asm_cmov(LIns* ins)
|
|
4749 |
{
|
|
4750 |
- underrunProtect(4);
|
|
4751 |
LOpcode op = ins->opcode();
|
|
4752 |
LIns* condval = ins->oprnd1();
|
|
4753 |
LIns* iftrue = ins->oprnd2();
|
|
4754 |
@@ -1330,7 +1361,7 @@ namespace nanojit
|
|
4755 |
(op == LIR_cmovd && iftrue->isD() && iffalse->isD()));
|
|
4756 |
|
|
4757 |
RegisterMask rm = (op == LIR_cmovi) ? GpRegs : FpRegs;
|
|
4758 |
- const Register rr = deprecated_prepResultReg(ins, rm);
|
|
4759 |
+ const Register rr = prepareResultReg(ins, rm);
|
|
4760 |
const Register iffalsereg = findRegFor(iffalse, rm & ~rmask(rr));
|
|
4761 |
bool isIcc = true;
|
|
4762 |
|
|
4763 |
@@ -1346,7 +1377,9 @@ namespace nanojit
|
|
4764 |
case LIR_leui: MOVGU (iffalsereg, rr); break;
|
|
4765 |
case LIR_gtui: MOVLEU(iffalsereg, rr); break;
|
|
4766 |
case LIR_geui: MOVCS (iffalsereg, rr); break;
|
|
4767 |
- debug_only( default: NanoAssert(0); break; )
|
|
4768 |
+ default:
|
|
4769 |
+ NanoAssertMsg(0, "asm_comv should never receive this cond opcode");
|
|
4770 |
+ return;
|
|
4771 |
}
|
|
4772 |
} else {
|
|
4773 |
switch (condval->opcode()) {
|
|
4774 |
@@ -1365,10 +1398,13 @@ namespace nanojit
|
|
4775 |
case LIR_ltd: FMOVDFUGE(iffalsereg, rr); isIcc = false; break;
|
|
4776 |
case LIR_ged: FMOVDFUL (iffalsereg, rr); isIcc = false; break;
|
|
4777 |
case LIR_gtd: FMOVDFULE(iffalsereg, rr); isIcc = false; break;
|
|
4778 |
- debug_only( default: NanoAssert(0); break; )
|
|
4779 |
+ default:
|
|
4780 |
+ NanoAssertMsg(0, "asm_comv should never receive this cond opcode");
|
|
4781 |
+ return;
|
|
4782 |
}
|
|
4783 |
}
|
|
4784 |
|
|
4785 |
+ freeResourcesOf(ins);
|
|
4786 |
/*const Register iftruereg =*/ findSpecificRegFor(iftrue, rr);
|
|
4787 |
if (isIcc)
|
|
4788 |
asm_cmp(condval);
|
|
4789 |
@@ -1379,16 +1415,16 @@ namespace nanojit
|
|
4790 |
|
|
4791 |
void Assembler::asm_param(LIns* ins)
|
|
4792 |
{
|
|
4793 |
- underrunProtect(12);
|
|
4794 |
uint32_t a = ins->paramArg();
|
|
4795 |
NanoAssertMsg(ins->paramKind() == 0, "savedRegs are not used on SPARC");
|
|
4796 |
|
|
4797 |
- if (a < sizeof(argRegs)/sizeof(argRegs[0])) { // i0 - i5
|
|
4798 |
+ if (a < sizeof(argRegs) / sizeof(argRegs[0])) { // i0 - i5
|
|
4799 |
prepareResultReg(ins, rmask(argRegs[a]));
|
|
4800 |
} else {
|
|
4801 |
// Incoming arg is on stack
|
|
4802 |
Register r = prepareResultReg(ins, GpRegs);
|
|
4803 |
int32_t d = a * sizeof (intptr_t) + kLinkageAreaSize;
|
|
4804 |
+ SafeUnderrunProtect protect(this, 12);
|
|
4805 |
LDSW32(FP, d, r);
|
|
4806 |
}
|
|
4807 |
freeResourcesOf(ins);
|
|
4808 |
@@ -1396,100 +1432,102 @@ namespace nanojit
|
|
4809 |
|
|
4810 |
void Assembler::asm_immi(LIns* ins)
|
|
4811 |
{
|
|
4812 |
- underrunProtect(8);
|
|
4813 |
- Register rr = deprecated_prepResultReg(ins, GpRegs);
|
|
4814 |
+ Register rr = prepareResultReg(ins, GpRegs);
|
|
4815 |
+ SafeUnderrunProtect protect(this, 12);
|
|
4816 |
int32_t val = ins->immI();
|
|
4817 |
if (val == 0)
|
|
4818 |
XOR(rr, rr, rr);
|
|
4819 |
else
|
|
4820 |
SET32(val, rr);
|
|
4821 |
+ freeResourcesOf(ins);
|
|
4822 |
}
|
|
4823 |
|
|
4824 |
void Assembler::asm_immd(LIns* ins)
|
|
4825 |
{
|
|
4826 |
- underrunProtect(64);
|
|
4827 |
- Register rr = ins->deprecated_getReg();
|
|
4828 |
- if (rr != deprecated_UnknownReg)
|
|
4829 |
- {
|
|
4830 |
- // @todo -- add special-cases for 0 and 1
|
|
4831 |
- _allocator.retire(rr);
|
|
4832 |
- ins->clearReg();
|
|
4833 |
- NanoAssert((rmask(rr) & FpRegs) != 0);
|
|
4834 |
- findMemFor(ins);
|
|
4835 |
- int d = deprecated_disp(ins);
|
|
4836 |
- LDDF32(FP, d, rr);
|
|
4837 |
- }
|
|
4838 |
+ SafeUnderrunProtect protect(this, 64);
|
|
4839 |
+ if (ins->isInReg()) {
|
|
4840 |
+ Register rr = ins->getReg();
|
|
4841 |
+ // @todo -- add special-cases for 0 and 1
|
|
4842 |
+ _allocator.retire(rr);
|
|
4843 |
+ ins->clearReg();
|
|
4844 |
+ NanoAssert((rmask(rr) & FpRegs) != 0);
|
|
4845 |
+ findMemFor(ins);
|
|
4846 |
+ int d = arDisp(ins);
|
|
4847 |
+ LDDF32(FP, d, rr);
|
|
4848 |
+ }
|
|
4849 |
|
|
4850 |
// @todo, if we used xor, ldsd, fldz, etc above, we don't need mem here
|
|
4851 |
- int d = deprecated_disp(ins);
|
|
4852 |
- deprecated_freeRsrcOf(ins);
|
|
4853 |
- if (d)
|
|
4854 |
- {
|
|
4855 |
- STW32(L2, d+4, FP);
|
|
4856 |
- SET32(ins->immDlo(), L2);
|
|
4857 |
- STW32(L2, d, FP);
|
|
4858 |
- SET32(ins->immDhi(), L2);
|
|
4859 |
- }
|
|
4860 |
+ int d = arDisp(ins);
|
|
4861 |
+ if (d) {
|
|
4862 |
+ STW32(L2, d+4, FP);
|
|
4863 |
+ SET32(ins->immDlo(), L2);
|
|
4864 |
+ STW32(L2, d, FP);
|
|
4865 |
+ SET32(ins->immDhi(), L2);
|
|
4866 |
+ }
|
|
4867 |
+ freeResourcesOf(ins);
|
|
4868 |
}
|
|
4869 |
|
|
4870 |
void Assembler::asm_fneg(LIns* ins)
|
|
4871 |
{
|
|
4872 |
- underrunProtect(4);
|
|
4873 |
- Register rr = deprecated_prepResultReg(ins, FpRegs);
|
|
4874 |
+ Register rr = prepareResultReg(ins, FpRegs);
|
|
4875 |
LIns* lhs = ins->oprnd1();
|
|
4876 |
|
|
4877 |
- // lhs into reg, prefer same reg as result
|
|
4878 |
- // if this is last use of lhs in reg, we can re-use result reg
|
|
4879 |
- // else, lhs already has a different reg assigned
|
|
4880 |
- Register ra = ( !lhs->isInReg()
|
|
4881 |
- ? findSpecificRegFor(lhs, rr)
|
|
4882 |
- : findRegFor(lhs, FpRegs) );
|
|
4883 |
+ // If 'lhs' isn't in a register, it can be clobbered by 'ins'.
|
|
4884 |
+ Register ra = lhs->isInReg() ? lhs->getReg() : rr;
|
|
4885 |
|
|
4886 |
FNEGD(ra, rr);
|
|
4887 |
+
|
|
4888 |
+ freeResourcesOf(ins);
|
|
4889 |
+ if (!lhs->isInReg()) {
|
|
4890 |
+ NanoAssert(ra == rr);
|
|
4891 |
+ findSpecificRegForUnallocated(lhs, ra);
|
|
4892 |
+ }
|
|
4893 |
}
|
|
4894 |
|
|
4895 |
void Assembler::asm_fop(LIns* ins)
|
|
4896 |
{
|
|
4897 |
- underrunProtect(4);
|
|
4898 |
LOpcode op = ins->opcode();
|
|
4899 |
- LIns *lhs = ins->oprnd1();
|
|
4900 |
- LIns *rhs = ins->oprnd2();
|
|
4901 |
+ LIns* lhs = ins->oprnd1();
|
|
4902 |
+ LIns* rhs = ins->oprnd2();
|
|
4903 |
|
|
4904 |
RegisterMask allow = FpRegs;
|
|
4905 |
Register ra, rb;
|
|
4906 |
findRegFor2(allow, lhs, ra, allow, rhs, rb);
|
|
4907 |
- Register rr = deprecated_prepResultReg(ins, allow);
|
|
4908 |
+ Register rr = prepareResultReg(ins, allow);
|
|
4909 |
|
|
4910 |
- if (op == LIR_addd)
|
|
4911 |
- FADDD(ra, rb, rr);
|
|
4912 |
- else if (op == LIR_subd)
|
|
4913 |
- FSUBD(ra, rb, rr);
|
|
4914 |
- else if (op == LIR_muld)
|
|
4915 |
- FMULD(ra, rb, rr);
|
|
4916 |
- else //if (op == LIR_divd)
|
|
4917 |
- FDIVD(ra, rb, rr);
|
|
4918 |
+ switch (op) {
|
|
4919 |
+ case LIR_addd: FADDD(ra, rb, rr); break;
|
|
4920 |
+ case LIR_subd: FSUBD(ra, rb, rr); break;
|
|
4921 |
+ case LIR_muld: FMULD(ra, rb, rr); break;
|
|
4922 |
+ case LIR_divd: FDIVD(ra, rb, rr); break;
|
|
4923 |
+ default:
|
|
4924 |
+ NanoAssertMsg(0, "asm_fop should never receive this opcode");
|
|
4925 |
+ return;
|
|
4926 |
+ }
|
|
4927 |
|
|
4928 |
+ freeResourcesOf(ins);
|
|
4929 |
}
|
|
4930 |
|
|
4931 |
void Assembler::asm_i2d(LIns* ins)
|
|
4932 |
{
|
|
4933 |
- underrunProtect(32);
|
|
4934 |
// where our result goes
|
|
4935 |
- Register rr = deprecated_prepResultReg(ins, FpRegs);
|
|
4936 |
+ Register rr = prepareResultReg(ins, FpRegs);
|
|
4937 |
+ SafeUnderrunProtect protect(this, 32);
|
|
4938 |
int d = findMemFor(ins->oprnd1());
|
|
4939 |
FITOD(rr, rr);
|
|
4940 |
LDDF32(FP, d, rr);
|
|
4941 |
+ freeResourcesOf(ins);
|
|
4942 |
}
|
|
4943 |
|
|
4944 |
void Assembler::asm_ui2d(LIns* ins)
|
|
4945 |
{
|
|
4946 |
- underrunProtect(72);
|
|
4947 |
// where our result goes
|
|
4948 |
- Register rr = deprecated_prepResultReg(ins, FpRegs);
|
|
4949 |
+ Register rr = prepareResultReg(ins, FpRegs);
|
|
4950 |
Register rt = registerAllocTmp(FpRegs & ~(rmask(rr)));
|
|
4951 |
Register gr = findRegFor(ins->oprnd1(), GpRegs);
|
|
4952 |
int disp = -8;
|
|
4953 |
|
|
4954 |
+ SafeUnderrunProtect protect(this, 72);
|
|
4955 |
FABSS(rr, rr);
|
|
4956 |
FSUBD(rt, rr, rr);
|
|
4957 |
LDDF32(SP, disp, rr);
|
|
4958 |
@@ -1498,37 +1536,37 @@ namespace nanojit
|
|
4959 |
STWI(gr, disp+4, SP);
|
|
4960 |
STWI(G1, disp, SP);
|
|
4961 |
SETHI(0x43300000, G1);
|
|
4962 |
+ freeResourcesOf(ins);
|
|
4963 |
}
|
|
4964 |
|
|
4965 |
void Assembler::asm_d2i(LIns* ins) {
|
|
4966 |
- underrunProtect(28);
|
|
4967 |
- LIns *lhs = ins->oprnd1();
|
|
4968 |
+ LIns* lhs = ins->oprnd1();
|
|
4969 |
Register rr = prepareResultReg(ins, GpRegs);
|
|
4970 |
Register ra = findRegFor(lhs, FpRegs);
|
|
4971 |
int d = findMemFor(ins);
|
|
4972 |
+ SafeUnderrunProtect protect(this, 28);
|
|
4973 |
LDSW32(FP, d, rr);
|
|
4974 |
- STF32(ra, d, FP);
|
|
4975 |
- FDTOI(ra, ra);
|
|
4976 |
+ STF32(F28, d, FP);
|
|
4977 |
+ FDTOI(ra, F28);
|
|
4978 |
freeResourcesOf(ins);
|
|
4979 |
}
|
|
4980 |
|
|
4981 |
void Assembler::asm_nongp_copy(Register r, Register s)
|
|
4982 |
{
|
|
4983 |
- underrunProtect(4);
|
|
4984 |
NanoAssert((rmask(r) & FpRegs) && (rmask(s) & FpRegs));
|
|
4985 |
FMOVD(s, r);
|
|
4986 |
}
|
|
4987 |
|
|
4988 |
- NIns * Assembler::asm_branchd(bool branchOnFalse, LIns *cond, NIns *targ)
|
|
4989 |
+ NIns* Assembler::asm_branchd(bool branchOnFalse, LIns* cond, NIns* targ)
|
|
4990 |
{
|
|
4991 |
- NIns *at = 0;
|
|
4992 |
+ NIns* at = 0;
|
|
4993 |
LOpcode condop = cond->opcode();
|
|
4994 |
NanoAssert(isCmpDOpcode(condop));
|
|
4995 |
- underrunProtect(32);
|
|
4996 |
+ SafeUnderrunProtect protect(this, 32);
|
|
4997 |
intptr_t tt = ((intptr_t)targ - (intptr_t)_nIns + 8) >> 2;
|
|
4998 |
// !targ means that it needs patch.
|
|
4999 |
if( !(isIMM22((int32_t)tt)) || !targ ) {
|
|
5000 |
- JMP_long_nocheck((intptr_t)targ);
|
|
5001 |
+ JMP_long((intptr_t)targ);
|
|
5002 |
at = _nIns;
|
|
5003 |
NOP();
|
|
5004 |
BA(0, 5);
|
|
5005 |
@@ -1537,39 +1575,35 @@ namespace nanojit
|
|
5006 |
NOP();
|
|
5007 |
|
|
5008 |
// produce the branch
|
|
5009 |
- if (branchOnFalse)
|
|
5010 |
- {
|
|
5011 |
- if (condop == LIR_eqd)
|
|
5012 |
- FBNE(0, tt);
|
|
5013 |
- else if (condop == LIR_led)
|
|
5014 |
- FBUG(0, tt);
|
|
5015 |
- else if (condop == LIR_ltd)
|
|
5016 |
- FBUGE(0, tt);
|
|
5017 |
- else if (condop == LIR_ged)
|
|
5018 |
- FBUL(0, tt);
|
|
5019 |
- else //if (condop == LIR_gtd)
|
|
5020 |
- FBULE(0, tt);
|
|
5021 |
+ if (branchOnFalse) {
|
|
5022 |
+ switch (condop) {
|
|
5023 |
+ case LIR_eqd: FBNE (0, tt); break;
|
|
5024 |
+ case LIR_led: FBUG (0, tt); break;
|
|
5025 |
+ case LIR_ltd: FBUGE(0, tt); break;
|
|
5026 |
+ case LIR_ged: FBUL (0, tt); break;
|
|
5027 |
+ case LIR_gtd: FBULE(0, tt); break;
|
|
5028 |
+ default:
|
|
5029 |
+ NanoAssertMsg(0, "asm_branchd should never receive this cond opcode");
|
|
5030 |
+ return;
|
|
5031 |
}
|
|
5032 |
- else // op == LIR_xt
|
|
5033 |
- {
|
|
5034 |
- if (condop == LIR_eqd)
|
|
5035 |
- FBE(0, tt);
|
|
5036 |
- else if (condop == LIR_led)
|
|
5037 |
- FBLE(0, tt);
|
|
5038 |
- else if (condop == LIR_ltd)
|
|
5039 |
- FBL(0, tt);
|
|
5040 |
- else if (condop == LIR_ged)
|
|
5041 |
- FBGE(0, tt);
|
|
5042 |
- else //if (condop == LIR_gtd)
|
|
5043 |
- FBG(0, tt);
|
|
5044 |
+ } else { // op == LIR_xt
|
|
5045 |
+ switch (condop) {
|
|
5046 |
+ case LIR_eqd: FBE (0, tt); break;
|
|
5047 |
+ case LIR_led: FBLE(0, tt); break;
|
|
5048 |
+ case LIR_ltd: FBL (0, tt); break;
|
|
5049 |
+ case LIR_ged: FBGE(0, tt); break;
|
|
5050 |
+ case LIR_gtd: FBG (0, tt); break;
|
|
5051 |
+ default:
|
|
5052 |
+ NanoAssertMsg(0, "asm_branchd should never receive this cond opcode");
|
|
5053 |
+ return;
|
|
5054 |
}
|
|
5055 |
+ }
|
|
5056 |
asm_cmpd(cond);
|
|
5057 |
return at;
|
|
5058 |
}
|
|
5059 |
|
|
5060 |
- void Assembler::asm_cmpd(LIns *cond)
|
|
5061 |
+ void Assembler::asm_cmpd(LIns* cond)
|
|
5062 |
{
|
|
5063 |
- underrunProtect(4);
|
|
5064 |
LIns* lhs = cond->oprnd1();
|
|
5065 |
LIns* rhs = cond->oprnd2();
|
|
5066 |
|
|
5067 |
@@ -1583,11 +1617,6 @@ namespace nanojit
|
|
5068 |
{
|
|
5069 |
}
|
|
5070 |
|
|
5071 |
- Register Assembler::asm_binop_rhs_reg(LIns* ins)
|
|
5072 |
- {
|
|
5073 |
- return deprecated_UnknownReg;
|
|
5074 |
- }
|
|
5075 |
-
|
|
5076 |
void Assembler::nativePageSetup()
|
|
5077 |
{
|
|
5078 |
NanoAssert(!_inExit);
|
|
5079 |
@@ -1607,11 +1636,12 @@ namespace nanojit
|
|
5080 |
void
|
|
5081 |
Assembler::underrunProtect(int n)
|
|
5082 |
{
|
|
5083 |
- NIns *eip = _nIns;
|
|
5084 |
+ NIns* eip = _nIns;
|
|
5085 |
+ NanoAssertMsg(n <= LARGEST_UNDERRUN_PROT, "constant LARGEST_UNDERRUN_PROT is too small %d");
|
|
5086 |
// This may be in a normal code chunk or an exit code chunk.
|
|
5087 |
- if (eip - n < codeStart) {
|
|
5088 |
+ if ((intptr_t)eip - n < (intptr_t)codeStart) {
|
|
5089 |
codeAlloc(codeStart, codeEnd, _nIns verbose_only(, codeBytes));
|
|
5090 |
- JMP_long_nocheck((intptr_t)eip);
|
|
5091 |
+ JMP_long((intptr_t)eip);
|
|
5092 |
}
|
|
5093 |
}
|
|
5094 |
|
|
5095 |
@@ -1620,7 +1650,7 @@ namespace nanojit
|
|
5096 |
genEpilogue();
|
|
5097 |
releaseRegisters();
|
|
5098 |
assignSavedRegs();
|
|
5099 |
- LIns *val = ins->oprnd1();
|
|
5100 |
+ LIns* val = ins->oprnd1();
|
|
5101 |
if (ins->isop(LIR_reti)) {
|
|
5102 |
findSpecificRegFor(val, retRegs[0]);
|
|
5103 |
} else {
|
|
5104 |
diff --git a/js/src/nanojit/NativeSparc.h b/js/src/nanojit/NativeSparc.h
|
|
5105 |
index 2a69caa..462ffc8 100644
|
|
5106 |
--- a/js/src/nanojit/NativeSparc.h
|
|
5107 |
+++ b/js/src/nanojit/NativeSparc.h
|
|
5108 |
@@ -71,7 +71,7 @@ namespace nanojit
|
|
5109 |
{
|
|
5110 |
const int NJ_MAX_REGISTERS = 30; // L0 - L7, I0 - I5, F2 - F14
|
|
5111 |
|
|
5112 |
- const int LARGEST_UNDERRUN_PROT = 32; // largest value passed to underrunProtect
|
|
5113 |
+ const int LARGEST_UNDERRUN_PROT = 72; // largest value passed to underrunProtect
|
|
5114 |
|
|
5115 |
#define NJ_MAX_STACK_ENTRY 8192
|
|
5116 |
#define NJ_MAX_PARAMETERS 1
|
|
5117 |
@@ -203,6 +203,7 @@ namespace nanojit
|
|
5118 |
#define DECLARE_PLATFORM_REGALLOC()
|
|
5119 |
|
|
5120 |
#define DECLARE_PLATFORM_ASSEMBLER() \
|
|
5121 |
+ friend class SafeUnderrunProtect; \
|
|
5122 |
const static Register argRegs[6], retRegs[1]; \
|
|
5123 |
bool has_cmov; \
|
|
5124 |
void nativePageReset(); \
|
|
5125 |
@@ -210,10 +211,11 @@ namespace nanojit
|
|
5126 |
void underrunProtect(int bytes); \
|
|
5127 |
bool hardenNopInsertion(const Config& /*c*/) { return false; } \
|
|
5128 |
void asm_align_code(); \
|
|
5129 |
- void asm_cmp(LIns *cond); \
|
|
5130 |
- void asm_cmpd(LIns *cond); \
|
|
5131 |
+ void asm_cmp(LIns* cond); \
|
|
5132 |
+ void asm_cmpd(LIns* cond); \
|
|
5133 |
NIns* asm_branchd(bool, LIns*, NIns*); \
|
|
5134 |
void IMM32(int32_t i) { \
|
|
5135 |
+ underrunProtect(4); \
|
|
5136 |
--_nIns; \
|
|
5137 |
*((int32_t*)_nIns) = i; \
|
|
5138 |
} \
|
|
5139 |
@@ -295,16 +297,16 @@ namespace nanojit
|
|
5140 |
void Format_4_5(Register rd, int32_t op3, int32_t cond, int32_t opf_cc, int32_t opf_low, Register rs2) { \
|
|
5141 |
Format_3A(2, rd, op3, (cond & 0xF) << 14 | (opf_cc & 0x7) << 11 | (opf_low & 0x3F) << 5 | _reg_(rs2)); \
|
|
5142 |
} \
|
|
5143 |
- void IntegerOperation(Register rs1, Register rs2, Register rd, int32_t op3, const char *opcode); \
|
|
5144 |
- void IntegerOperationI(Register rs1, int32_t simm13, Register rd, int32_t op3, const char *opcode); \
|
|
5145 |
- void FloatOperation(Register rs1, Register rs2, Register rd, int32_t op3, const char *opcode); \
|
|
5146 |
- void Bicc(int32_t a, int32_t dsp22, int32_t cond, const char *opcode); \
|
|
5147 |
- void FBfcc(int32_t a, int32_t dsp22, int32_t cond, const char *opcode); \
|
|
5148 |
+ void IntegerOperation(Register rs1, Register rs2, Register rd, int32_t op3, const char* opcode); \
|
|
5149 |
+ void IntegerOperationI(Register rs1, int32_t simm13, Register rd, int32_t op3, const char* opcode); \
|
|
5150 |
+ void FloatOperation(Register rs1, Register rs2, Register rd, int32_t op3, const char* opcode); \
|
|
5151 |
+ void Bicc(int32_t a, int32_t dsp22, int32_t cond, const char* opcode); \
|
|
5152 |
+ void FBfcc(int32_t a, int32_t dsp22, int32_t cond, const char* opcode); \
|
|
5153 |
void LoadOperation(Register rs1, Register rs2, Register rd, int32_t op3, const char* opcode); \
|
|
5154 |
void LoadOperationI(Register rs1, int32_t simm13, Register rd, int32_t op3, const char* opcode); \
|
|
5155 |
- void MOVcc(Register rs, int32_t cc2, int32_t cc1, int32_t cc0, Register rd, int32_t cond, const char *opcode); \
|
|
5156 |
- void MOVccI(int32_t simm11, int32_t cc2, int32_t cc1, int32_t cc0, Register rd, int32_t cond, const char *opcode); \
|
|
5157 |
- void FMOVDcc(Register rs, int32_t opt_cc, Register rd, int32_t cond, const char *opcode); \
|
|
5158 |
+ void MOVcc(Register rs, int32_t cc2, int32_t cc1, int32_t cc0, Register rd, int32_t cond, const char* opcode); \
|
|
5159 |
+ void MOVccI(int32_t simm11, int32_t cc2, int32_t cc1, int32_t cc0, Register rd, int32_t cond, const char* opcode); \
|
|
5160 |
+ void FMOVDcc(Register rs, int32_t opt_cc, Register rd, int32_t cond, const char* opcode); \
|
|
5161 |
void ShiftOperation(Register rs1, Register rs2, Register rd, int32_t op3, const char* opcode); \
|
|
5162 |
void ShiftOperationI(Register rs1, int32_t shcnt32, Register rd, int32_t op3, const char* opcode); \
|
|
5163 |
void Store(Register rd, Register rs1, Register rs2, int32_t op3, const char* opcode); \
|
|
5164 |
@@ -443,14 +445,13 @@ namespace nanojit
|
|
5165 |
void STB(Register rd, Register rs1, Register rs2); \
|
|
5166 |
void STBI(Register rd, int32_t simm13, Register rs1); \
|
|
5167 |
void STB32(Register rd, int32_t immI, Register rs1); \
|
|
5168 |
- bool isIMM13(int32_t imm) { return (imm) <= 0xfff && (imm) >= -0x1000; } \
|
|
5169 |
- bool isIMM19(int32_t imm) { return (imm) <= 0x3ffff && (imm) >= -0x40000; } \
|
|
5170 |
- bool isIMM22(int32_t imm) { return (imm) <= 0x1fffff && (imm) >= -0x200000; } \
|
|
5171 |
- void JMP_long_nocheck(int32_t t); \
|
|
5172 |
+ static bool isIMM13(int32_t imm) { return (imm) <= 0xfff && (imm) >= -0x1000; } \
|
|
5173 |
+ static bool isIMM19(int32_t imm) { return (imm) <= 0x3ffff && (imm) >= -0x40000; } \
|
|
5174 |
+ static bool isIMM22(int32_t imm) { return (imm) <= 0x1fffff && (imm) >= -0x200000; } \
|
|
5175 |
void JMP_long(int32_t t); \
|
|
5176 |
void JMP_long_placeholder(); \
|
|
5177 |
- int32_t JCC(void *t); \
|
|
5178 |
- void JMP(void *t); \
|
|
5179 |
+ int32_t JCC(void* t); \
|
|
5180 |
+ void JMP(void* t); \
|
|
5181 |
void MR(Register rd, Register rs);
|
|
5182 |
}
|
|
5183 |
#endif // __nanojit_NativeSparc__
|
|
5184 |
index c8fd987..3caf5cf 100644
|
|
5185 |
--- a/js/src/yarr/yarr/RegexCompiler.cpp
|
|
5186 |
+++ b/js/src/yarr/yarr/RegexCompiler.cpp
|
|
5187 |
@@ -34,6 +34,12 @@ namespace JSC { namespace Yarr {
|
|
5188 |
|
|
5189 |
#include "RegExpJitTables.h"
|
|
5190 |
|
|
5191 |
+#if WTF_CPU_SPARC
|
|
5192 |
+#define BASE_FRAME_SIZE 24
|
|
5193 |
+#else
|
|
5194 |
+#define BASE_FRAME_SIZE 0
|
|
5195 |
+#endif
|
|
5196 |
+
|
|
5197 |
class CharacterClassConstructor {
|
|
5198 |
public:
|
|
5199 |
CharacterClassConstructor(bool isCaseInsensitive = false)
|
|
5200 |
@@ -592,7 +598,7 @@ public:
|
|
5201 |
|
|
5202 |
void setupOffsets()
|
|
5203 |
{
|
|
5204 |
- setupDisjunctionOffsets(m_pattern.m_body, 0, 0);
|
|
5205 |
+ setupDisjunctionOffsets(m_pattern.m_body, BASE_FRAME_SIZE, 0);
|
|
5206 |
}
|
|
5207 |
|
|
5208 |
// This optimization identifies sets of parentheses that we will never need to backtrack.
|
|
5209 |
diff --git a/js/src/yarr/yarr/RegexJIT.cpp b/js/src/yarr/yarr/RegexJIT.cpp
|
|
5210 |
index 9b58ee7..e11907a 100644
|
|
5211 |
--- a/js/src/yarr/yarr/RegexJIT.cpp
|
|
5212 |
+++ b/js/src/yarr/yarr/RegexJIT.cpp
|
|
5213 |
@@ -62,6 +62,16 @@ class RegexGenerator : private MacroAssembler {
|
|
5214 |
static const RegisterID regT1 = MIPSRegisters::t5;
|
|
5215 |
|
|
5216 |
static const RegisterID returnRegister = MIPSRegisters::v0;
|
|
5217 |
+#elif WTF_CPU_SPARC
|
|
5218 |
+ static const RegisterID input = SparcRegisters::i0;
|
|
5219 |
+ static const RegisterID index = SparcRegisters::i1;
|
|
5220 |
+ static const RegisterID length = SparcRegisters::i2;
|
|
5221 |
+ static const RegisterID output = SparcRegisters::i3;
|
|
5222 |
+
|
|
5223 |
+ static const RegisterID regT0 = SparcRegisters::i4;
|
|
5224 |
+ static const RegisterID regT1 = SparcRegisters::i5;
|
|
5225 |
+
|
|
5226 |
+ static const RegisterID returnRegister = SparcRegisters::i0;
|
|
5227 |
#elif WTF_CPU_X86
|
|
5228 |
static const RegisterID input = X86Registers::eax;
|
|
5229 |
static const RegisterID index = X86Registers::edx;
|
|
5230 |
@@ -564,8 +574,13 @@ class RegexGenerator : private MacroAssembler {
|
|
5231 |
void generatePatternCharacterPair(TermGenerationState& state)
|
|
5232 |
{
|
|
5233 |
const RegisterID character = regT0;
|
|
5234 |
+#if WTF_CPU_BIG_ENDIAN
|
|
5235 |
+ UChar ch2 = state.term().patternCharacter;
|
|
5236 |
+ UChar ch1 = state.lookaheadTerm().patternCharacter;
|
|
5237 |
+#else
|
|
5238 |
UChar ch1 = state.term().patternCharacter;
|
|
5239 |
UChar ch2 = state.lookaheadTerm().patternCharacter;
|
|
5240 |
+#endif
|
|
5241 |
|
|
5242 |
int mask = 0;
|
|
5243 |
int chPair = ch1 | (ch2 << 16);
|
|
5244 |
@@ -1449,6 +1464,10 @@ class RegexGenerator : private MacroAssembler {
|
|
5245 |
push(ARMRegisters::r8); // scratch register
|
|
5246 |
#endif
|
|
5247 |
move(ARMRegisters::r3, output);
|
|
5248 |
+#elif WTF_CPU_SPARC
|
|
5249 |
+ save(Imm32(-m_pattern.m_body->m_callFrameSize * sizeof(void*)));
|
|
5250 |
+ // set m_callFrameSize to 0 avoid and stack movement later.
|
|
5251 |
+ m_pattern.m_body->m_callFrameSize = 0;
|
|
5252 |
#elif WTF_CPU_MIPS
|
|
5253 |
// Do nothing.
|
|
5254 |
#endif
|
|
5255 |
@@ -1471,6 +1490,9 @@ class RegexGenerator : private MacroAssembler {
|
|
5256 |
pop(ARMRegisters::r6);
|
|
5257 |
pop(ARMRegisters::r5);
|
|
5258 |
pop(ARMRegisters::r4);
|
|
5259 |
+#elif WTF_CPU_SPARC
|
|
5260 |
+ ret_and_restore();
|
|
5261 |
+ return;
|
|
5262 |
#elif WTF_CPU_MIPS
|
|
5263 |
// Do nothing
|
|
5264 |
#endif
|