Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef assembler_assembler_SparcAssembler_h
8 #define assembler_assembler_SparcAssembler_h
10 #include "assembler/wtf/Platform.h"
12 // Some debug code uses s(n)printf for instruction logging.
13 #include <stdio.h>
15 #if ENABLE_ASSEMBLER && WTF_CPU_SPARC
17 #include "assembler/assembler/AssemblerBufferWithConstantPool.h"
18 #include "assembler/wtf/Assertions.h"
20 #define IPFX " %s"
21 #define ISPFX " "
22 #ifdef JS_METHODJIT_SPEW
23 # define MAYBE_PAD (isOOLPath ? "> " : "")
24 #else
25 # define MAYBE_PAD ""
26 #endif
28 namespace JSC {
30 typedef uint32_t SparcWord;
32 namespace SparcRegisters {
33 typedef enum {
34 g0 = 0, // g0 is always 0
35 g1 = 1, // g1 is a scratch register for v8
36 g2 = 2,
37 g3 = 3,
38 g4 = 4,
39 g5 = 5, // Reserved for system
40 g6 = 6, // Reserved for system
41 g7 = 7, // Reserved for system
43 o0 = 8,
44 o1 = 9,
45 o2 = 10,
46 o3 = 11,
47 o4 = 12,
48 o5 = 13,
49 o6 = 14, // SP
50 o7 = 15,
52 l0 = 16,
53 l1 = 17,
54 l2 = 18,
55 l3 = 19,
56 l4 = 20,
57 l5 = 21,
58 l6 = 22,
59 l7 = 23,
61 i0 = 24,
62 i1 = 25,
63 i2 = 26,
64 i3 = 27,
65 i4 = 28,
66 i5 = 29,
67 i6 = 30, // FP
68 i7 = 31,
70 sp = o6,
71 fp = i6
72 } RegisterID;
74 typedef enum {
75 f0 = 0,
76 f1 = 1,
77 f2 = 2,
78 f3 = 3,
79 f4 = 4,
80 f5 = 5,
81 f6 = 6,
82 f7 = 7,
83 f8 = 8,
84 f9 = 9,
85 f10 = 10,
86 f11 = 11,
87 f12 = 12,
88 f13 = 13,
89 f14 = 14,
90 f15 = 15,
91 f16 = 16,
92 f17 = 17,
93 f18 = 18,
94 f19 = 19,
95 f20 = 20,
96 f21 = 21,
97 f22 = 22,
98 f23 = 23,
99 f24 = 24,
100 f25 = 25,
101 f26 = 26,
102 f27 = 27,
103 f28 = 28,
104 f29 = 29,
105 f30 = 30,
106 f31 = 31
107 } FPRegisterID;
109 } // namespace SparcRegisters
111 class SparcAssembler : public GenericAssembler {
112 public:
113 typedef SparcRegisters::RegisterID RegisterID;
114 typedef SparcRegisters::FPRegisterID FPRegisterID;
115 AssemblerBuffer m_buffer;
116 bool oom() const { return m_buffer.oom(); }
118 // Sparc conditional constants
119 typedef enum {
120 ConditionE = 0x1, // Zero
121 ConditionLE = 0x2,
122 ConditionL = 0x3,
123 ConditionLEU = 0x4,
124 ConditionCS = 0x5,
125 ConditionNEG = 0x6,
126 ConditionVS = 0x7,
127 ConditionA = 0x8, // branch_always
128 ConditionNE = 0x9, // Non-zero
129 ConditionG = 0xa,
130 ConditionGE = 0xb,
131 ConditionGU = 0xc,
132 ConditionCC = 0xd,
133 ConditionVC = 0xf
134 } Condition;
137 typedef enum {
138 DoubleConditionNE = 0x1,
139 DoubleConditionUL = 0x3,
140 DoubleConditionL = 0x4,
141 DoubleConditionUG = 0x5,
142 DoubleConditionG = 0x6,
143 DoubleConditionE = 0x9,
144 DoubleConditionUE = 0xa,
145 DoubleConditionGE = 0xb,
146 DoubleConditionUGE = 0xc,
147 DoubleConditionLE = 0xd,
148 DoubleConditionULE = 0xe
149 } DoubleCondition;
151 typedef enum {
152 BranchOnCondition,
153 BranchOnDoubleCondition
154 } BranchType;
156 class JmpSrc {
157 friend class SparcAssembler;
158 public:
159 JmpSrc()
160 : m_offset(-1)
161 {
162 }
164 private:
165 JmpSrc(int offset)
166 : m_offset(offset)
167 {
168 }
170 int m_offset;
171 };
173 class JmpDst {
174 friend class SparcAssembler;
175 public:
176 JmpDst()
177 : m_offset(-1)
178 , m_used(false)
179 {
180 }
182 bool isUsed() const { return m_used; }
183 void used() { m_used = true; }
184 bool isValid() const { return m_offset != -1; }
185 private:
186 JmpDst(int offset)
187 : m_offset(offset)
188 , m_used(false)
189 {
190 ASSERT(m_offset == offset);
191 }
193 int m_used : 1;
194 signed int m_offset : 31;
195 };
197 // Instruction formating
199 void format_2_1(int rd, int op2, int imm22)
200 {
201 m_buffer.putInt(rd << 25 | op2 << 22 | (imm22 & 0x3FFFFF));
202 }
204 void format_2_2(int a, int cond, int op2, int disp22)
205 {
206 format_2_1((a & 0x1) << 4 | (cond & 0xF), op2, disp22);
207 }
209 void format_2_3(int a, int cond, int op2, int cc1, int cc0, int p, int disp19)
210 {
211 format_2_2(a, cond, op2, (cc1 & 0x1) << 21 | (cc0 & 0x1) << 20 | (p & 0x1) << 19 | (disp19 & 0x7FFFF));
212 }
214 void format_2_4(int a, int rcond, int op2, int d16hi, int p, int rs1, int d16lo)
215 {
216 format_2_2(a, (rcond & 0x7), op2, (d16hi & 0x3) << 20 | (p & 0x1) << 19 | rs1 << 14 | (d16lo & 0x3FFF));
217 }
219 void format_3(int op1, int rd, int op3, int bits19)
220 {
221 m_buffer.putInt(op1 << 30 | rd << 25 | op3 << 19 | (bits19 & 0x7FFFF));
222 }
224 void format_3_1(int op1, int rd, int op3, int rs1, int bit8, int rs2)
225 {
226 format_3(op1, rd, op3, rs1 << 14 | (bit8 & 0xFF) << 5 | rs2);
227 }
229 void format_3_1_imm(int op1, int rd, int op3, int rs1, int simm13)
230 {
231 format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | (simm13 & 0x1FFF));
232 }
234 void format_3_2(int op1, int rd, int op3, int rs1, int rcond, int rs2)
235 {
236 format_3(op1, rd, op3, rs1 << 14 | (rcond & 0x3) << 10 | rs2);
237 }
239 void format_3_2_imm(int op1, int rd, int op3, int rs1, int rcond, int simm10)
240 {
241 format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | (rcond & 0x3) << 10 | (simm10 & 0x1FFF));
242 }
244 void format_3_3(int op1, int rd, int op3, int rs1, int cmask, int mmask)
245 {
246 format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | (cmask & 0x7) << 5 | (mmask & 0xF));
247 }
248 void format_3_4(int op1, int rd, int op3, int bits19)
249 {
250 format_3(op1, rd, op3, bits19);
251 }
253 void format_3_5(int op1, int rd, int op3, int rs1, int x, int rs2)
254 {
255 format_3(op1, rd, op3, rs1 << 14 | (x & 0x1) << 12 | rs2);
256 }
258 void format_3_6(int op1, int rd, int op3, int rs1, int shcnt32)
259 {
260 format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | (shcnt32 & 0x1F));
261 }
263 void format_3_7(int op1, int rd, int op3, int rs1, int shcnt64)
264 {
265 format_3(op1, rd, op3, rs1 << 14 | 1 << 13 | 1 << 12 | (shcnt64 & 0x3F));
266 }
268 void format_3_8(int op1, int rd, int op3, int rs1, int bits9, int rs2)
269 {
270 format_3(op1, rd, op3, rs1 << 14 | (bits9 & 0x1FF) << 5 | rs2);
271 }
273 void format_3_9(int op1, int cc1, int cc0, int op3, int rs1, int bits9, int rs2)
274 {
275 format_3(op1, (cc1 & 0x1) << 1 | (cc0 & 0x1), op3, rs1 << 14 | (bits9 & 0x1FF) << 5 | rs2);
276 }
278 void format_4_1(int rd, int op3, int rs1, int cc1, int cc0, int rs2)
279 {
280 format_3(2, rd, op3, rs1 << 14 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | rs2);
281 }
283 void format_4_1_imm(int rd, int op3, int rs1, int cc1, int cc0, int simm11)
284 {
285 format_3(2, rd, op3, rs1 << 14 | (cc1 & 0x1) << 12 | 1 << 13 |(cc0 & 0x1) << 11 | (simm11 & 0x7FF));
286 }
288 void format_4_2(int rd, int op3, int cc2, int cond, int cc1, int cc0, int rs2)
289 {
290 format_3(2, rd, op3, (cc2 & 0x1) << 18 | (cond & 0xF) << 14 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | rs2);
291 }
293 void format_4_2_imm(int rd, int op3, int cc2, int cond, int cc1, int cc0, int simm11)
294 {
295 format_3(2, rd, op3, (cc2 & 0x1) << 18 | (cond & 0xF) << 14 | 1 << 13 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | (simm11 & 0x7FF));
296 }
298 void format_4_3(int rd, int op3, int rs1, int cc1, int cc0, int swap_trap)
299 {
300 format_3(2, rd, op3, rs1 << 14 | 1 << 13 | (cc1 & 0x1) << 12 | (cc0 & 0x1) << 11 | (swap_trap & 0x7F));
301 }
303 void format_4_4(int rd, int op3, int rs1, int rcond, int opf_low, int rs2)
304 {
305 format_3(2, rd, op3, rs1 << 14 | (rcond & 0x7) << 10 | (opf_low & 0x1F) << 5 | rs2);
306 }
308 void format_4_5(int rd, int op3, int cond, int opf_cc, int opf_low, int rs2)
309 {
310 format_3(2, rd, op3, (cond & 0xF) << 14 | (opf_cc & 0x7) << 11 | (opf_low & 0x3F) << 5 | rs2);
311 }
313 void addcc_r(int rs1, int rs2, int rd)
314 {
315 js::JaegerSpew(js::JSpew_Insns,
316 IPFX "addcc %s, %s, %s\n", MAYBE_PAD,
317 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
318 format_3_1(2, rd, 0x10, rs1, 0, rs2);
319 }
321 void addcc_imm(int rs1, int simm13, int rd)
322 {
323 js::JaegerSpew(js::JSpew_Insns,
324 IPFX "addcc %s, %d, %s\n", MAYBE_PAD,
325 nameGpReg(rs1), simm13, nameGpReg(rd));
326 format_3_1_imm(2, rd, 0x10, rs1, simm13);
327 }
329 void add_r(int rs1, int rs2, int rd)
330 {
331 js::JaegerSpew(js::JSpew_Insns,
332 IPFX "add %s, %s, %s\n", MAYBE_PAD,
333 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
334 format_3_1(2, rd, 0, rs1, 0, rs2);
335 }
337 void add_imm(int rs1, int simm13, int rd)
338 {
339 js::JaegerSpew(js::JSpew_Insns,
340 IPFX "add %s, %d, %s\n", MAYBE_PAD,
341 nameGpReg(rs1), simm13, nameGpReg(rd));
342 format_3_1_imm(2, rd, 0, rs1, simm13);
343 }
345 void andcc_r(int rs1, int rs2, int rd)
346 {
347 js::JaegerSpew(js::JSpew_Insns,
348 IPFX "andcc %s, %s, %s\n", MAYBE_PAD,
349 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
350 format_3_1(2, rd, 0x11, rs1, 0, rs2);
351 }
353 void andcc_imm(int rs1, int simm13, int rd)
354 {
355 js::JaegerSpew(js::JSpew_Insns,
356 IPFX "andcc %s, %d, %s\n", MAYBE_PAD,
357 nameGpReg(rs1), simm13, nameGpReg(rd));
358 format_3_1_imm(2, rd, 0x11, rs1, simm13);
359 }
361 void or_r(int rs1, int rs2, int rd)
362 {
363 js::JaegerSpew(js::JSpew_Insns,
364 IPFX "or %s, %s, %s\n", MAYBE_PAD,
365 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
366 format_3_1(2, rd, 0x2, rs1, 0, rs2);
367 }
369 void or_imm(int rs1, int simm13, int rd)
370 {
371 js::JaegerSpew(js::JSpew_Insns,
372 IPFX "or %s, %d, %s\n", MAYBE_PAD,
373 nameGpReg(rs1), simm13, nameGpReg(rd));
374 format_3_1_imm(2, rd, 0x2, rs1, simm13);
375 }
377 // sethi %hi(imm22) rd
378 void sethi(int imm22, int rd)
379 {
380 js::JaegerSpew(js::JSpew_Insns,
381 IPFX "sethi %%hi(0x%x), %s\n", MAYBE_PAD,
382 imm22, nameGpReg(rd));
383 format_2_1(rd, 0x4, (imm22 >> 10));
384 }
386 void sll_r(int rs1, int rs2, int rd)
387 {
388 js::JaegerSpew(js::JSpew_Insns,
389 IPFX "sll %s, %s, %s\n", MAYBE_PAD,
390 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
391 format_3_5(2, rd, 0x25, rs1, 0, rs2);
392 }
394 void sll_imm(int rs1, int shcnt32, int rd)
395 {
396 js::JaegerSpew(js::JSpew_Insns,
397 IPFX "sll %s, %d, %s\n", MAYBE_PAD,
398 nameGpReg(rs1), shcnt32, nameGpReg(rd));
399 format_3_6(2, rd, 0x25, rs1, shcnt32);
400 }
402 void sra_r(int rs1, int rs2, int rd)
403 {
404 js::JaegerSpew(js::JSpew_Insns,
405 IPFX "sra %s, %s, %s\n", MAYBE_PAD,
406 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
407 format_3_5(2, rd, 0x27, rs1, 0, rs2);
408 }
410 void sra_imm(int rs1, int shcnt32, int rd)
411 {
412 js::JaegerSpew(js::JSpew_Insns,
413 IPFX "sra %s, %d, %s\n", MAYBE_PAD,
414 nameGpReg(rs1), shcnt32, nameGpReg(rd));
415 format_3_6(2, rd, 0x27, rs1, shcnt32);
416 }
418 void srl_r(int rs1, int rs2, int rd)
419 {
420 js::JaegerSpew(js::JSpew_Insns,
421 IPFX "srl %s, %s, %s\n", MAYBE_PAD,
422 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
423 format_3_5(2, rd, 0x26, rs1, 0, rs2);
424 }
426 void srl_imm(int rs1, int shcnt32, int rd)
427 {
428 js::JaegerSpew(js::JSpew_Insns,
429 IPFX "srl %s, %d, %s\n", MAYBE_PAD,
430 nameGpReg(rs1), shcnt32, nameGpReg(rd));
431 format_3_6(2, rd, 0x26, rs1, shcnt32);
432 }
434 void subcc_r(int rs1, int rs2, int rd)
435 {
436 js::JaegerSpew(js::JSpew_Insns,
437 IPFX "subcc %s, %s, %s\n", MAYBE_PAD,
438 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
439 format_3_1(2, rd, 0x14, rs1, 0, rs2);
440 }
442 void subcc_imm(int rs1, int simm13, int rd)
443 {
444 js::JaegerSpew(js::JSpew_Insns,
445 IPFX "subcc %s, %d, %s\n", MAYBE_PAD,
446 nameGpReg(rs1), simm13, nameGpReg(rd));
447 format_3_1_imm(2, rd, 0x14, rs1, simm13);
448 }
450 void orcc_r(int rs1, int rs2, int rd)
451 {
452 js::JaegerSpew(js::JSpew_Insns,
453 IPFX "orcc %s, %s, %s\n", MAYBE_PAD,
454 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
455 format_3_1(2, rd, 0x12, rs1, 0, rs2);
456 }
458 void orcc_imm(int rs1, int simm13, int rd)
459 {
460 js::JaegerSpew(js::JSpew_Insns,
461 IPFX "orcc %s, %d, %s\n", MAYBE_PAD,
462 nameGpReg(rs1), simm13, nameGpReg(rd));
463 format_3_1_imm(2, rd, 0x12, rs1, simm13);
464 }
466 void xorcc_r(int rs1, int rs2, int rd)
467 {
468 js::JaegerSpew(js::JSpew_Insns,
469 IPFX "xorcc %s, %s, %s\n", MAYBE_PAD,
470 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
471 format_3_1(2, rd, 0x13, rs1, 0, rs2);
472 }
474 void xorcc_imm(int rs1, int simm13, int rd)
475 {
476 js::JaegerSpew(js::JSpew_Insns,
477 IPFX "xorcc %s, %d, %s\n", MAYBE_PAD,
478 nameGpReg(rs1), simm13, nameGpReg(rd));
479 format_3_1_imm(2, rd, 0x13, rs1, simm13);
480 }
482 void xnorcc_r(int rs1, int rs2, int rd)
483 {
484 js::JaegerSpew(js::JSpew_Insns,
485 IPFX "xnorcc %s, %s, %s\n", MAYBE_PAD,
486 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
487 format_3_1(2, rd, 0x17, rs1, 0, rs2);
488 }
490 void xnorcc_imm(int rs1, int simm13, int rd)
491 {
492 js::JaegerSpew(js::JSpew_Insns,
493 IPFX "xnorcc %s, %d, %s\n", MAYBE_PAD,
494 nameGpReg(rs1), simm13, nameGpReg(rd));
495 format_3_1_imm(2, rd, 0x17, rs1, simm13);
496 }
498 void smulcc_r(int rs1, int rs2, int rd)
499 {
500 js::JaegerSpew(js::JSpew_Insns,
501 IPFX "smulcc %s, %s, %s\n", MAYBE_PAD,
502 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
503 format_3_1(2, rd, 0x1b, rs1, 0, rs2);
504 }
506 void smulcc_imm(int rs1, int simm13, int rd)
507 {
508 js::JaegerSpew(js::JSpew_Insns,
509 IPFX "smulcc %s, %d, %s\n", MAYBE_PAD,
510 nameGpReg(rs1), simm13, nameGpReg(rd));
511 format_3_1_imm(2, rd, 0x1b, rs1, simm13);
512 }
514 void ldsb_r(int rs1, int rs2, int rd)
515 {
516 js::JaegerSpew(js::JSpew_Insns,
517 IPFX "ldsb [%s + %s], %s\n", MAYBE_PAD,
518 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
519 format_3_1(3, rd, 0x9, rs1, 0, rs2);
520 }
522 void ldsb_imm(int rs1, int simm13, int rd)
523 {
524 js::JaegerSpew(js::JSpew_Insns,
525 IPFX "ldsb [%s + %d], %s\n", MAYBE_PAD,
526 nameGpReg(rs1), simm13, nameGpReg(rd));
527 format_3_1_imm(3, rd, 0x9, rs1, simm13);
528 }
530 void ldub_r(int rs1, int rs2, int rd)
531 {
532 js::JaegerSpew(js::JSpew_Insns,
533 IPFX "ldub [%s + %s], %s\n", MAYBE_PAD,
534 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
535 format_3_1(3, rd, 0x1, rs1, 0, rs2);
536 }
538 void ldub_imm(int rs1, int simm13, int rd)
539 {
540 js::JaegerSpew(js::JSpew_Insns,
541 IPFX "ldub [%s + %d], %s\n", MAYBE_PAD,
542 nameGpReg(rs1), simm13, nameGpReg(rd));
543 format_3_1_imm(3, rd, 0x1, rs1, simm13);
544 }
546 void lduw_r(int rs1, int rs2, int rd)
547 {
548 js::JaegerSpew(js::JSpew_Insns,
549 IPFX "lduw [%s + %s], %s\n", MAYBE_PAD,
550 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
551 format_3_1(3, rd, 0x0, rs1, 0, rs2);
552 }
554 void lduwa_r(int rs1, int rs2, int rd)
555 {
556 js::JaegerSpew(js::JSpew_Insns,
557 IPFX "lduwa [%s + %s], %s\n", MAYBE_PAD,
558 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
559 format_3_1(3, rd, 0x10, rs1, 0x82, rs2);
560 }
562 void lduw_imm(int rs1, int simm13, int rd)
563 {
564 js::JaegerSpew(js::JSpew_Insns,
565 IPFX "lduw [%s + %d], %s\n", MAYBE_PAD,
566 nameGpReg(rs1), simm13, nameGpReg(rd));
567 format_3_1_imm(3, rd, 0x0, rs1, simm13);
568 }
570 void ldsh_r(int rs1, int rs2, int rd)
571 {
572 js::JaegerSpew(js::JSpew_Insns,
573 IPFX "ldsh [%s + %s], %s\n", MAYBE_PAD,
574 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
575 format_3_1(3, rd, 0xa, rs1, 0, rs2);
576 }
578 void ldsh_imm(int rs1, int simm13, int rd)
579 {
580 js::JaegerSpew(js::JSpew_Insns,
581 IPFX "ldsh [%s + %d], %s\n", MAYBE_PAD,
582 nameGpReg(rs1), simm13, nameGpReg(rd));
583 format_3_1_imm(3, rd, 0xa, rs1, simm13);
584 }
586 void lduh_r(int rs1, int rs2, int rd)
587 {
588 js::JaegerSpew(js::JSpew_Insns,
589 IPFX "lduh [%s + %s], %s\n", MAYBE_PAD,
590 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
591 format_3_1(3, rd, 0x2, rs1, 0, rs2);
592 }
594 void lduh_imm(int rs1, int simm13, int rd)
595 {
596 js::JaegerSpew(js::JSpew_Insns,
597 IPFX "lduh [%s + %d], %s\n", MAYBE_PAD,
598 nameGpReg(rs1), simm13, nameGpReg(rd));
599 format_3_1_imm(3, rd, 0x2, rs1, simm13);
600 }
602 void stb_r(int rd, int rs2, int rs1)
603 {
604 js::JaegerSpew(js::JSpew_Insns,
605 IPFX "stb %s, [%s + %s]\n", MAYBE_PAD,
606 nameGpReg(rd), nameGpReg(rs1), nameGpReg(rs2));
607 format_3_1(3, rd, 0x5, rs1, 0, rs2);
608 }
610 void stb_imm(int rd, int rs1, int simm13)
611 {
612 js::JaegerSpew(js::JSpew_Insns,
613 IPFX "stb %s, [%s + %d]\n", MAYBE_PAD,
614 nameGpReg(rd), nameGpReg(rs1), simm13);
615 format_3_1_imm(3, rd, 0x5, rs1, simm13);
616 }
618 void sth_r(int rd, int rs2, int rs1)
619 {
620 js::JaegerSpew(js::JSpew_Insns,
621 IPFX "sth %s, [%s + %s]\n", MAYBE_PAD,
622 nameGpReg(rd), nameGpReg(rs1), nameGpReg(rs2));
623 format_3_1(3, rd, 0x6, rs1, 0, rs2);
624 }
626 void sth_imm(int rd, int rs1, int simm13)
627 {
628 js::JaegerSpew(js::JSpew_Insns,
629 IPFX "sth %s, [%s + %d]\n", MAYBE_PAD,
630 nameGpReg(rd), nameGpReg(rs1), simm13);
631 format_3_1_imm(3, rd, 0x6, rs1, simm13);
632 }
634 void stw_r(int rd, int rs2, int rs1)
635 {
636 js::JaegerSpew(js::JSpew_Insns,
637 IPFX "stw %s, [%s + %s]\n", MAYBE_PAD,
638 nameGpReg(rd), nameGpReg(rs1), nameGpReg(rs2));
639 format_3_1(3, rd, 0x4, rs1, 0, rs2);
640 }
642 void stw_imm(int rd, int rs1, int simm13)
643 {
644 js::JaegerSpew(js::JSpew_Insns,
645 IPFX "stw %s, [%s + %d]\n", MAYBE_PAD,
646 nameGpReg(rd), nameGpReg(rs1), simm13);
647 format_3_1_imm(3, rd, 0x4, rs1, simm13);
648 }
650 void ldf_r(int rs1, int rs2, int rd)
651 {
652 js::JaegerSpew(js::JSpew_Insns,
653 IPFX "ld [%s + %s], %s\n", MAYBE_PAD,
654 nameGpReg(rs1), nameGpReg(rs2), nameFpReg(rd));
655 format_3_1(3, rd, 0x20, rs1, 0, rs2);
656 }
658 void ldf_imm(int rs1, int simm13, int rd)
659 {
660 js::JaegerSpew(js::JSpew_Insns,
661 IPFX "ld [%s + %d], %s\n", MAYBE_PAD,
662 nameGpReg(rs1), simm13, nameFpReg(rd));
663 format_3_1_imm(3, rd, 0x20, rs1, simm13);
664 }
666 void stf_r(int rd, int rs2, int rs1)
667 {
668 js::JaegerSpew(js::JSpew_Insns,
669 IPFX "st %s, [%s + %s]\n", MAYBE_PAD,
670 nameFpReg(rd), nameGpReg(rs1), nameGpReg(rs2));
671 format_3_1(3, rd, 0x24, rs1, 0, rs2);
672 }
674 void stf_imm(int rd, int rs1, int simm13)
675 {
676 js::JaegerSpew(js::JSpew_Insns,
677 IPFX "st %s, [%s + %d]\n", MAYBE_PAD,
678 nameFpReg(rd), nameGpReg(rs1), simm13);
679 format_3_1_imm(3, rd, 0x24, rs1, simm13);
680 }
682 void fmovd_r(int rs2, int rd)
683 {
684 js::JaegerSpew(js::JSpew_Insns,
685 IPFX "fmovd %s, %s\n", MAYBE_PAD,
686 nameFpReg(rs2), nameFpReg(rd));
687 format_3_8(2, rd, 0x34, 0, 0x2, rs2);
688 }
690 void fcmpd_r(int rs1, int rs2)
691 {
692 js::JaegerSpew(js::JSpew_Insns,
693 IPFX "fcmpd %s, %s\n", MAYBE_PAD,
694 nameFpReg(rs1), nameFpReg(rs2));
695 format_3_9(2, 0, 0, 0x35, rs1, 0x52, rs2);
696 }
698 void nop()
699 {
700 js::JaegerSpew(js::JSpew_Insns,
701 IPFX "nop\n", MAYBE_PAD);
702 format_2_1(0, 0x4, 0);
703 }
705 void branch_con(Condition cond, int target)
706 {
707 js::JaegerSpew(js::JSpew_Insns,
708 IPFX "b%s 0x%x\n", MAYBE_PAD,
709 nameICC(cond), target);
710 format_2_2(0, cond, 0x2, target);
711 }
713 void fbranch_con(DoubleCondition cond, int target)
714 {
715 js::JaegerSpew(js::JSpew_Insns,
716 IPFX "fb%s 0x%x\n", MAYBE_PAD,
717 nameFCC(cond), target);
718 format_2_2(0, cond, 0x6, target);
719 }
721 void rdy(int rd)
722 {
723 js::JaegerSpew(js::JSpew_Insns,
724 IPFX "rdy %s\n", MAYBE_PAD,
725 nameFpReg(rd));
726 format_3_1(2, rd, 0x28, 0, 0, 0);
727 }
729 void rdpc(int rd)
730 {
731 js::JaegerSpew(js::JSpew_Insns,
732 IPFX "rdpc %s\n", MAYBE_PAD,
733 nameGpReg(rd));
734 format_3_1(2, rd, 0x28, 5, 0, 0);
735 }
736 void jmpl_r(int rs1, int rs2, int rd)
737 {
738 js::JaegerSpew(js::JSpew_Insns,
739 IPFX "jmpl %s + %s, %s\n", MAYBE_PAD,
740 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
741 format_3_1(2, rd, 0x38, rs1, 0, rs2);
742 }
744 void jmpl_imm(int rs1, int simm13, int rd)
745 {
746 js::JaegerSpew(js::JSpew_Insns,
747 IPFX "jmpl %s + %d, %s\n", MAYBE_PAD,
748 nameGpReg(rs1), simm13, nameGpReg(rd));
749 format_3_1_imm(2, rd, 0x38, rs1, simm13);
750 }
752 void save_r(int rs1, int rs2, int rd)
753 {
754 js::JaegerSpew(js::JSpew_Insns,
755 IPFX "save %s, %s, %s\n", MAYBE_PAD,
756 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
757 format_3_1(2, rd, 0x3c, rs1, 0, rs2);
758 }
760 void save_imm(int rs1, int simm13, int rd)
761 {
762 js::JaegerSpew(js::JSpew_Insns,
763 IPFX "save %s, %d, %s\n", MAYBE_PAD,
764 nameGpReg(rs1), simm13, nameGpReg(rd));
765 format_3_1_imm(2, rd, 0x3c, rs1, simm13);
766 }
768 void restore_r(int rs1, int rs2, int rd)
769 {
770 js::JaegerSpew(js::JSpew_Insns,
771 IPFX "restore %s, %s, %s\n", MAYBE_PAD,
772 nameGpReg(rs1), nameGpReg(rs2), nameGpReg(rd));
773 format_3_1(2, rd, 0x3d, rs1, 0, rs2);
774 }
776 void ta_imm(int swap_trap)
777 {
778 js::JaegerSpew(js::JSpew_Insns,
779 IPFX "ta %d\n", MAYBE_PAD,
780 swap_trap);
781 format_4_3(0x8, 0xa, 0, 0, 0, swap_trap);
782 }
784 void movcc_imm(int simm11, int rd, Condition cond)
785 {
786 js::JaegerSpew(js::JSpew_Insns,
787 IPFX "mov%s %d, %s\n", MAYBE_PAD,
788 nameICC(cond), simm11, nameGpReg(rd));
789 format_4_2_imm(rd, 0x2c, 1, cond, 0, 0, simm11);
790 }
792 void fabss_r(int rs2, int rd)
793 {
794 js::JaegerSpew(js::JSpew_Insns,
795 IPFX "fabss %s, %s\n", MAYBE_PAD,
796 nameFpReg(rs2), nameFpReg(rd));
797 format_3_8(2, rd, 0x34, 0, 0x9, rs2);
798 }
800 void faddd_r(int rs1, int rs2, int rd)
801 {
802 js::JaegerSpew(js::JSpew_Insns,
803 IPFX "faddd %s, %s, %s\n", MAYBE_PAD,
804 nameFpReg(rs1), nameFpReg(rs2), nameFpReg(rd));
805 format_3_8(2, rd, 0x34, rs1, 0x42, rs2);
806 }
808 void fsubd_r(int rs1, int rs2, int rd)
809 {
810 js::JaegerSpew(js::JSpew_Insns,
811 IPFX "fsubd %s, %s, %s\n", MAYBE_PAD,
812 nameFpReg(rs1), nameFpReg(rs2), nameFpReg(rd));
813 format_3_8(2, rd, 0x34, rs1, 0x46, rs2);
814 }
816 void fmuld_r(int rs1, int rs2, int rd)
817 {
818 js::JaegerSpew(js::JSpew_Insns,
819 IPFX "fmuld %s, %s, %s\n", MAYBE_PAD,
820 nameFpReg(rs1), nameFpReg(rs2), nameFpReg(rd));
821 format_3_8(2, rd, 0x34, rs1, 0x4a, rs2);
822 }
824 void fdivd_r(int rs1, int rs2, int rd)
825 {
826 js::JaegerSpew(js::JSpew_Insns,
827 IPFX "fdivd %s, %s, %s\n", MAYBE_PAD,
828 nameFpReg(rs1), nameFpReg(rs2), nameFpReg(rd));
829 format_3_8(2, rd, 0x34, rs1, 0x4e, rs2);
830 }
832 void fsqrtd_r(int rs2, int rd)
833 {
834 js::JaegerSpew(js::JSpew_Insns,
835 IPFX "fsqartd %s, %s\n", MAYBE_PAD,
836 nameFpReg(rs2), nameFpReg(rd));
837 format_3_8(2, rd, 0x34, 0, 0x2a, rs2);
838 }
840 void fabsd_r(int rs2, int rd)
841 {
842 js::JaegerSpew(js::JSpew_Insns,
843 IPFX "fabsd %s, %s\n", MAYBE_PAD,
844 nameFpReg(rs2), nameFpReg(rd));
845 format_3_8(2, rd, 0x34, 0, 0x0a, rs2);
846 }
848 void fnegd_r(int rs2, int rd)
849 {
850 js::JaegerSpew(js::JSpew_Insns,
851 IPFX "fnegd %s, %s\n", MAYBE_PAD,
852 nameFpReg(rs2), nameFpReg(rd));
853 format_3_8(2, rd, 0x34, 0, 0x06, rs2);
854 }
856 void fitod_r(int rs2, int rd)
857 {
858 js::JaegerSpew(js::JSpew_Insns,
859 IPFX "fitod %s, %s\n", MAYBE_PAD,
860 nameFpReg(rs2), nameFpReg(rd));
861 format_3_8(2, rd, 0x34, 0, 0xc8, rs2);
862 }
864 void fdtoi_r(int rs2, int rd)
865 {
866 js::JaegerSpew(js::JSpew_Insns,
867 IPFX "fdtoi %s, %s\n", MAYBE_PAD,
868 nameFpReg(rs2), nameFpReg(rd));
869 format_3_8(2, rd, 0x34, 0, 0xd2, rs2);
870 }
872 void fdtos_r(int rs2, int rd)
873 {
874 js::JaegerSpew(js::JSpew_Insns,
875 IPFX "fdtos %s, %s\n", MAYBE_PAD,
876 nameFpReg(rs2), nameFpReg(rd));
877 format_3_8(2, rd, 0x34, 0, 0xc6, rs2);
878 }
880 void fstod_r(int rs2, int rd)
881 {
882 js::JaegerSpew(js::JSpew_Insns,
883 IPFX "fstod %s, %s\n", MAYBE_PAD,
884 nameFpReg(rs2), nameFpReg(rd));
885 format_3_8(2, rd, 0x34, 0, 0xc9, rs2);
886 }
888 static bool isimm13(int imm)
889 {
890 return (imm) <= 0xfff && (imm) >= -0x1000;
891 }
893 static bool isimm22(int imm)
894 {
895 return (imm) <= 0x1fffff && (imm) >= -0x200000;
896 }
898 void move_nocheck(int imm_v, RegisterID dest)
899 {
900 sethi(imm_v, dest);
901 or_imm(dest, imm_v & 0x3FF, dest);
902 }
904 JmpSrc call()
905 {
906 JmpSrc r = JmpSrc(m_buffer.size());
907 js::JaegerSpew(js::JSpew_Insns,
908 IPFX "call %d\n", MAYBE_PAD,
909 r.m_offset);
910 m_buffer.putInt(0x40000000);
911 nop();
912 return r;
913 }
915 JmpSrc jump_common(BranchType branchtype, int cond)
916 {
917 if (branchtype == BranchOnCondition)
918 branch_con(Condition(cond), 0);
919 else
920 fbranch_con(DoubleCondition(cond), 0);
922 nop();
923 branch_con(ConditionA, 7);
924 nop();
925 move_nocheck(0, SparcRegisters::g2);
926 rdpc(SparcRegisters::g3);
927 jmpl_r(SparcRegisters::g2, SparcRegisters::g3, SparcRegisters::g0);
928 nop();
929 return JmpSrc(m_buffer.size());
930 }
932 JmpSrc branch(Condition cond)
933 {
934 return jump_common(BranchOnCondition, cond);
935 }
937 JmpSrc fbranch(DoubleCondition cond)
938 {
939 return jump_common(BranchOnDoubleCondition, cond);
940 }
942 JmpSrc jmp()
943 {
944 return jump_common(BranchOnCondition, ConditionA);
945 }
947 // Assembler admin methods:
949 JmpDst label()
950 {
951 JmpDst r = JmpDst(m_buffer.size());
952 js::JaegerSpew(js::JSpew_Insns,
953 IPFX "#label ((%d))\n", MAYBE_PAD, r.m_offset);
954 return r;
955 }
957 // General helpers
959 size_t size() const { return m_buffer.size(); }
960 unsigned char *buffer() const { return m_buffer.buffer(); }
962 static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
963 {
964 return dst.m_offset - src.m_offset;
965 }
967 static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
968 {
969 return dst.m_offset - src.m_offset;
970 }
972 static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
973 {
974 return dst.m_offset - src.m_offset;
975 }
977 static unsigned getCallReturnOffset(JmpSrc call)
978 {
979 return call.m_offset + 20;
980 }
982 static void* getRelocatedAddress(void* code, JmpSrc jump)
983 {
984 ASSERT(jump.m_offset != -1);
986 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
987 }
989 static void* getRelocatedAddress(void* code, JmpDst destination)
990 {
991 ASSERT(destination.m_offset != -1);
993 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
994 }
996 void* executableAllocAndCopy(ExecutableAllocator* allocator, ExecutablePool **poolp, CodeKind kind)
997 {
998 return m_buffer.executableAllocAndCopy(allocator, poolp, kind);
999 }
1001 void* executableCopy(void* buffer)
1002 {
1003 return memcpy(buffer, m_buffer.buffer(), size());
1004 }
1006 static void patchPointerInternal(void* where, int value)
1007 {
1008 // Patch move_nocheck.
1009 uint32_t *branch = (uint32_t*) where;
1010 branch[0] &= 0xFFC00000;
1011 branch[0] |= (value >> 10) & 0x3FFFFF;
1012 branch[1] &= 0xFFFFFC00;
1013 branch[1] |= value & 0x3FF;
1014 ExecutableAllocator::cacheFlush(where, 8);
1015 }
1017 static void patchbranch(void* where, int value)
1018 {
1019 uint32_t *branch = (uint32_t*) where;
1020 branch[0] &= 0xFFC00000;
1021 branch[0] |= value & 0x3FFFFF;
1022 ExecutableAllocator::cacheFlush(where, 4);
1023 }
1025 static bool canRelinkJump(void* from, void* to)
1026 {
1027 return true;
1028 }
1030 static void relinkJump(void* from, void* to)
1031 {
1032 from = (void *)((int)from - 36);
1033 js::JaegerSpew(js::JSpew_Insns,
1034 ISPFX "##link ((%p)) jumps to ((%p))\n",
1035 from, to);
1037 int value = ((int)to - (int)from) / 4;
1038 if (isimm22(value))
1039 patchbranch(from, value);
1040 else {
1041 patchbranch(from, 4);
1042 from = (void *)((intptr_t)from + 16);
1043 patchPointerInternal(from, (int)(value * 4 - 24));
1044 }
1045 }
1047 void linkJump(JmpSrc from, JmpDst to)
1048 {
1049 ASSERT(from.m_offset != -1);
1050 ASSERT(to.m_offset != -1);
1051 intptr_t code = (intptr_t)(m_buffer.data());
1052 void *where = (void *)((intptr_t)code + from.m_offset);
1053 void *target = (void *)((intptr_t)code + to.m_offset);
1054 relinkJump(where, target);
1055 }
1057 static void linkJump(void* code, JmpSrc from, void* to)
1058 {
1059 ASSERT(from.m_offset != -1);
1060 void *where = (void *)((intptr_t)code + from.m_offset);
1061 relinkJump(where, to);
1062 }
1064 static void relinkCall(void* from, void* to)
1065 {
1066 js::JaegerSpew(js::JSpew_Insns,
1067 ISPFX "##relinkCall ((from=%p)) ((to=%p))\n",
1068 from, to);
1070 void * where= (void *)((intptr_t)from - 20);
1071 patchPointerInternal(where, (int)to);
1072 ExecutableAllocator::cacheFlush(where, 8);
1073 }
1075 static void linkCall(void* code, JmpSrc where, void* to)
1076 {
1077 void *from = (void *)((intptr_t)code + where.m_offset);
1078 js::JaegerSpew(js::JSpew_Insns,
1079 ISPFX "##linkCall ((from=%p)) ((to=%p))\n",
1080 from, to);
1081 int disp = ((int)to - (int)from)/4;
1082 *(uint32_t *)((int)from) &= 0x40000000;
1083 *(uint32_t *)((int)from) |= disp & 0x3fffffff;
1084 ExecutableAllocator::cacheFlush(from, 4);
1085 }
1087 static void linkPointer(void* code, JmpDst where, void* value)
1088 {
1089 js::JaegerSpew(js::JSpew_Insns,
1090 ISPFX "##linkPointer ((%p + %#x)) points to ((%p))\n",
1091 code, where.m_offset, value);
1093 void *from = (void *)((intptr_t)code + where.m_offset);
1094 patchPointerInternal(from, (int)value);
1095 }
1097 static void repatchInt32(void* where, int value)
1098 {
1099 js::JaegerSpew(js::JSpew_Insns,
1100 ISPFX "##repatchInt32 ((where=%p)) holds ((value=%d))\n",
1101 where, value);
1103 patchPointerInternal(where, value);
1104 }
1106 static void repatchPointer(void* where, void* value)
1107 {
1108 js::JaegerSpew(js::JSpew_Insns,
1109 ISPFX "##repatchPointer ((where = %p)) points to ((%p))\n",
1110 where, value);
1112 patchPointerInternal(where, (int)value);
1113 }
1115 static void repatchLoadPtrToLEA(void* where)
1116 {
1117 // sethi is used. The offset is in a register
1118 if (*(uint32_t *)((int)where) & 0x01000000)
1119 where = (void *)((intptr_t)where + 8);
1121 *(uint32_t *)((int)where) &= 0x3fffffff;
1122 *(uint32_t *)((int)where) |= 0x80000000;
1123 ExecutableAllocator::cacheFlush(where, 4);
1124 }
1126 static void repatchLEAToLoadPtr(void* where)
1127 {
1128 // sethi is used. The offset is in a register
1129 if (*(uint32_t *)((int)where) & 0x01000000)
1130 where = (void *)((intptr_t)where + 8);
1132 *(uint32_t *)((int)where) &= 0x3fffffff;
1133 *(uint32_t *)((int)where) |= 0xc0000000;
1134 ExecutableAllocator::cacheFlush(where, 4);
1135 }
1137 private:
1138 static char const * nameGpReg(int reg)
1139 {
1140 ASSERT(reg <= 31);
1141 ASSERT(reg >= 0);
1142 static char const * const names[] = {
1143 "%g0", "%g1", "%g2", "%g3",
1144 "%g4", "%g5", "%g6", "%g7",
1145 "%o0", "%o1", "%o2", "%o3",
1146 "%o4", "%o5", "%sp", "%o7",
1147 "%l0", "%l1", "%l2", "%l3",
1148 "%l4", "%l5", "%l6", "%l7",
1149 "%i0", "%i1", "%i2", "%i3",
1150 "%i4", "%i5", "%fp", "%i7"
1151 };
1152 return names[reg];
1153 }
1155 static char const * nameFpReg(int reg)
1156 {
1157 ASSERT(reg <= 31);
1158 ASSERT(reg >= 0);
1159 static char const * const names[] = {
1160 "%f0", "%f1", "%f2", "%f3",
1161 "%f4", "%f5", "%f6", "%f7",
1162 "%f8", "%f9", "%f10", "%f11",
1163 "%f12", "%f13", "%f14", "%f15",
1164 "%f16", "%f17", "%f18", "%f19",
1165 "%f20", "%f21", "%f22", "%f23",
1166 "%f24", "%f25", "%f26", "%f27",
1167 "%f28", "%f29", "%f30", "%f31"
1168 };
1169 return names[reg];
1170 }
1172 static char const * nameICC(Condition cc)
1173 {
1174 ASSERT(cc <= ConditionVC);
1175 ASSERT(cc >= 0);
1177 uint32_t ccIndex = cc;
1178 static char const * const inames[] = {
1179 " ", "e ",
1180 "le ", "l ",
1181 "leu", "cs ",
1182 "neg", "vs ",
1183 "a ", "ne ",
1184 "g ", "ge ",
1185 "gu ", "cc ",
1186 " ", "vc "
1187 };
1188 return inames[ccIndex];
1189 }
1191 static char const * nameFCC(DoubleCondition cc)
1192 {
1193 ASSERT(cc <= DoubleConditionULE);
1194 ASSERT(cc >= 0);
1196 uint32_t ccIndex = cc;
1197 static char const * const fnames[] = {
1198 " ", "ne ",
1199 " ", "ul ",
1200 "l ", "ug ",
1201 "g ", " ",
1202 " ", "e ",
1203 "ue ", "ge ",
1204 "ugu", "le ",
1205 "ule", " "
1206 };
1207 return fnames[ccIndex];
1208 }
1211 };
1213 } // namespace JSC
1215 #endif // ENABLE(ASSEMBLER) && CPU(SPARC)
1217 #endif /* assembler_assembler_SparcAssembler_h */