]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/sparc/tcg-target.c
tcg-sparc: Dont handle constant arguments to ext32 ops
[mirror_qemu.git] / tcg / sparc / tcg-target.c
CommitLineData
8289b279
BS
1/*
2 * Tiny Code Generator for QEMU
3 *
4 * Copyright (c) 2008 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
3cf246f0
RH
25#include "tcg-be-null.h"
26
d4a9eb1f 27#ifndef NDEBUG
8289b279
BS
28static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
29 "%g0",
30 "%g1",
31 "%g2",
32 "%g3",
33 "%g4",
34 "%g5",
35 "%g6",
36 "%g7",
37 "%o0",
38 "%o1",
39 "%o2",
40 "%o3",
41 "%o4",
42 "%o5",
43 "%o6",
44 "%o7",
45 "%l0",
46 "%l1",
47 "%l2",
48 "%l3",
49 "%l4",
50 "%l5",
51 "%l6",
52 "%l7",
53 "%i0",
54 "%i1",
55 "%i2",
56 "%i3",
57 "%i4",
58 "%i5",
59 "%i6",
60 "%i7",
61};
d4a9eb1f 62#endif
8289b279 63
375816f8
RH
64/* Define some temporary registers. T2 is used for constant generation. */
65#define TCG_REG_T1 TCG_REG_G1
66#define TCG_REG_T2 TCG_REG_O7
67
c6f7e4fb 68#ifdef CONFIG_USE_GUEST_BASE
375816f8 69# define TCG_GUEST_BASE_REG TCG_REG_I5
c6f7e4fb
RH
70#else
71# define TCG_GUEST_BASE_REG TCG_REG_G0
72#endif
e141ab52 73
0954d0d9 74static const int tcg_target_reg_alloc_order[] = {
8289b279
BS
75 TCG_REG_L0,
76 TCG_REG_L1,
77 TCG_REG_L2,
78 TCG_REG_L3,
79 TCG_REG_L4,
80 TCG_REG_L5,
81 TCG_REG_L6,
82 TCG_REG_L7,
26adfb75 83
8289b279
BS
84 TCG_REG_I0,
85 TCG_REG_I1,
86 TCG_REG_I2,
87 TCG_REG_I3,
88 TCG_REG_I4,
375816f8 89 TCG_REG_I5,
26adfb75
RH
90
91 TCG_REG_G2,
92 TCG_REG_G3,
93 TCG_REG_G4,
94 TCG_REG_G5,
95
96 TCG_REG_O0,
97 TCG_REG_O1,
98 TCG_REG_O2,
99 TCG_REG_O3,
100 TCG_REG_O4,
101 TCG_REG_O5,
8289b279
BS
102};
103
104static const int tcg_target_call_iarg_regs[6] = {
105 TCG_REG_O0,
106 TCG_REG_O1,
107 TCG_REG_O2,
108 TCG_REG_O3,
109 TCG_REG_O4,
110 TCG_REG_O5,
111};
112
26a74ae3 113static const int tcg_target_call_oarg_regs[] = {
8289b279 114 TCG_REG_O0,
e141ab52
BS
115 TCG_REG_O1,
116 TCG_REG_O2,
117 TCG_REG_O3,
8289b279
BS
118};
119
8289b279
BS
120#define INSN_OP(x) ((x) << 30)
121#define INSN_OP2(x) ((x) << 22)
122#define INSN_OP3(x) ((x) << 19)
123#define INSN_OPF(x) ((x) << 5)
124#define INSN_RD(x) ((x) << 25)
125#define INSN_RS1(x) ((x) << 14)
126#define INSN_RS2(x) (x)
8384dd67 127#define INSN_ASI(x) ((x) << 5)
8289b279 128
203342d8 129#define INSN_IMM10(x) ((1 << 13) | ((x) & 0x3ff))
dbfe80e1 130#define INSN_IMM11(x) ((1 << 13) | ((x) & 0x7ff))
8289b279 131#define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff))
ab1339b9 132#define INSN_OFF16(x) ((((x) >> 2) & 0x3fff) | ((((x) >> 16) & 3) << 20))
1da92db2 133#define INSN_OFF19(x) (((x) >> 2) & 0x07ffff)
a115f3ea 134#define INSN_COND(x) ((x) << 25)
8289b279 135
cf7c2ca5
BS
136#define COND_N 0x0
137#define COND_E 0x1
138#define COND_LE 0x2
139#define COND_L 0x3
140#define COND_LEU 0x4
141#define COND_CS 0x5
142#define COND_NEG 0x6
143#define COND_VS 0x7
b3db8758 144#define COND_A 0x8
cf7c2ca5
BS
145#define COND_NE 0x9
146#define COND_G 0xa
147#define COND_GE 0xb
148#define COND_GU 0xc
149#define COND_CC 0xd
150#define COND_POS 0xe
151#define COND_VC 0xf
a115f3ea 152#define BA (INSN_OP(0) | INSN_COND(COND_A) | INSN_OP2(0x2))
8289b279 153
ab1339b9
RH
154#define RCOND_Z 1
155#define RCOND_LEZ 2
156#define RCOND_LZ 3
157#define RCOND_NZ 5
158#define RCOND_GZ 6
159#define RCOND_GEZ 7
160
dbfe80e1
RH
161#define MOVCC_ICC (1 << 18)
162#define MOVCC_XCC (1 << 18 | 1 << 12)
163
a115f3ea
RH
164#define BPCC_ICC 0
165#define BPCC_XCC (2 << 20)
166#define BPCC_PT (1 << 19)
167#define BPCC_PN 0
168#define BPCC_A (1 << 29)
169
ab1339b9
RH
170#define BPR_PT BPCC_PT
171
8289b279 172#define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00))
7a3766f3 173#define ARITH_ADDCC (INSN_OP(2) | INSN_OP3(0x10))
8289b279 174#define ARITH_AND (INSN_OP(2) | INSN_OP3(0x01))
dc69960d 175#define ARITH_ANDN (INSN_OP(2) | INSN_OP3(0x05))
8289b279 176#define ARITH_OR (INSN_OP(2) | INSN_OP3(0x02))
9a7f3228 177#define ARITH_ORCC (INSN_OP(2) | INSN_OP3(0x12))
be6551b1 178#define ARITH_ORN (INSN_OP(2) | INSN_OP3(0x06))
8289b279 179#define ARITH_XOR (INSN_OP(2) | INSN_OP3(0x03))
f5ef6aac
BS
180#define ARITH_SUB (INSN_OP(2) | INSN_OP3(0x04))
181#define ARITH_SUBCC (INSN_OP(2) | INSN_OP3(0x14))
a221ae3f 182#define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x08))
8289b279
BS
183#define ARITH_SUBX (INSN_OP(2) | INSN_OP3(0x0c))
184#define ARITH_UMUL (INSN_OP(2) | INSN_OP3(0x0a))
185#define ARITH_UDIV (INSN_OP(2) | INSN_OP3(0x0e))
186#define ARITH_SDIV (INSN_OP(2) | INSN_OP3(0x0f))
187#define ARITH_MULX (INSN_OP(2) | INSN_OP3(0x09))
188#define ARITH_UDIVX (INSN_OP(2) | INSN_OP3(0x0d))
189#define ARITH_SDIVX (INSN_OP(2) | INSN_OP3(0x2d))
dbfe80e1 190#define ARITH_MOVCC (INSN_OP(2) | INSN_OP3(0x2c))
203342d8 191#define ARITH_MOVR (INSN_OP(2) | INSN_OP3(0x2f))
8289b279
BS
192
193#define SHIFT_SLL (INSN_OP(2) | INSN_OP3(0x25))
194#define SHIFT_SRL (INSN_OP(2) | INSN_OP3(0x26))
195#define SHIFT_SRA (INSN_OP(2) | INSN_OP3(0x27))
196
197#define SHIFT_SLLX (INSN_OP(2) | INSN_OP3(0x25) | (1 << 12))
198#define SHIFT_SRLX (INSN_OP(2) | INSN_OP3(0x26) | (1 << 12))
199#define SHIFT_SRAX (INSN_OP(2) | INSN_OP3(0x27) | (1 << 12))
200
7a3766f3 201#define RDY (INSN_OP(2) | INSN_OP3(0x28) | INSN_RS1(0))
583d1215 202#define WRY (INSN_OP(2) | INSN_OP3(0x30) | INSN_RD(0))
8289b279
BS
203#define JMPL (INSN_OP(2) | INSN_OP3(0x38))
204#define SAVE (INSN_OP(2) | INSN_OP3(0x3c))
205#define RESTORE (INSN_OP(2) | INSN_OP3(0x3d))
206#define SETHI (INSN_OP(0) | INSN_OP2(0x4))
207#define CALL INSN_OP(1)
208#define LDUB (INSN_OP(3) | INSN_OP3(0x01))
209#define LDSB (INSN_OP(3) | INSN_OP3(0x09))
210#define LDUH (INSN_OP(3) | INSN_OP3(0x02))
211#define LDSH (INSN_OP(3) | INSN_OP3(0x0a))
212#define LDUW (INSN_OP(3) | INSN_OP3(0x00))
213#define LDSW (INSN_OP(3) | INSN_OP3(0x08))
214#define LDX (INSN_OP(3) | INSN_OP3(0x0b))
215#define STB (INSN_OP(3) | INSN_OP3(0x05))
216#define STH (INSN_OP(3) | INSN_OP3(0x06))
217#define STW (INSN_OP(3) | INSN_OP3(0x04))
218#define STX (INSN_OP(3) | INSN_OP3(0x0e))
8384dd67
BS
219#define LDUBA (INSN_OP(3) | INSN_OP3(0x11))
220#define LDSBA (INSN_OP(3) | INSN_OP3(0x19))
221#define LDUHA (INSN_OP(3) | INSN_OP3(0x12))
222#define LDSHA (INSN_OP(3) | INSN_OP3(0x1a))
223#define LDUWA (INSN_OP(3) | INSN_OP3(0x10))
224#define LDSWA (INSN_OP(3) | INSN_OP3(0x18))
225#define LDXA (INSN_OP(3) | INSN_OP3(0x1b))
226#define STBA (INSN_OP(3) | INSN_OP3(0x15))
227#define STHA (INSN_OP(3) | INSN_OP3(0x16))
228#define STWA (INSN_OP(3) | INSN_OP3(0x14))
229#define STXA (INSN_OP(3) | INSN_OP3(0x1e))
230
231#ifndef ASI_PRIMARY_LITTLE
232#define ASI_PRIMARY_LITTLE 0x88
233#endif
8289b279 234
a0ce341a
RH
235#define LDUH_LE (LDUHA | INSN_ASI(ASI_PRIMARY_LITTLE))
236#define LDSH_LE (LDSHA | INSN_ASI(ASI_PRIMARY_LITTLE))
237#define LDUW_LE (LDUWA | INSN_ASI(ASI_PRIMARY_LITTLE))
238#define LDSW_LE (LDSWA | INSN_ASI(ASI_PRIMARY_LITTLE))
239#define LDX_LE (LDXA | INSN_ASI(ASI_PRIMARY_LITTLE))
240
241#define STH_LE (STHA | INSN_ASI(ASI_PRIMARY_LITTLE))
242#define STW_LE (STWA | INSN_ASI(ASI_PRIMARY_LITTLE))
243#define STX_LE (STXA | INSN_ASI(ASI_PRIMARY_LITTLE))
244
a115f3ea
RH
245static inline int check_fit_tl(tcg_target_long val, unsigned int bits)
246{
247 return (val << ((sizeof(tcg_target_long) * 8 - bits))
248 >> (sizeof(tcg_target_long) * 8 - bits)) == val;
249}
250
251static inline int check_fit_i32(uint32_t val, unsigned int bits)
252{
253 return ((val << (32 - bits)) >> (32 - bits)) == val;
254}
255
256static void patch_reloc(uint8_t *code_ptr, int type,
2ba7fae2 257 intptr_t value, intptr_t addend)
a115f3ea
RH
258{
259 uint32_t insn;
260 value += addend;
261 switch (type) {
262 case R_SPARC_32:
263 if (value != (uint32_t)value) {
264 tcg_abort();
265 }
266 *(uint32_t *)code_ptr = value;
267 break;
ab1339b9 268 case R_SPARC_WDISP16:
2ba7fae2 269 value -= (intptr_t)code_ptr;
ab1339b9
RH
270 if (!check_fit_tl(value >> 2, 16)) {
271 tcg_abort();
272 }
273 insn = *(uint32_t *)code_ptr;
274 insn &= ~INSN_OFF16(-1);
275 insn |= INSN_OFF16(value);
276 *(uint32_t *)code_ptr = insn;
277 break;
a115f3ea 278 case R_SPARC_WDISP19:
2ba7fae2 279 value -= (intptr_t)code_ptr;
a115f3ea
RH
280 if (!check_fit_tl(value >> 2, 19)) {
281 tcg_abort();
282 }
283 insn = *(uint32_t *)code_ptr;
284 insn &= ~INSN_OFF19(-1);
285 insn |= INSN_OFF19(value);
286 *(uint32_t *)code_ptr = insn;
287 break;
288 default:
289 tcg_abort();
290 }
291}
292
293/* parse target specific constraints */
294static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
295{
296 const char *ct_str;
297
298 ct_str = *pct_str;
299 switch (ct_str[0]) {
300 case 'r':
301 ct->ct |= TCG_CT_REG;
302 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
303 break;
304 case 'L': /* qemu_ld/st constraint */
305 ct->ct |= TCG_CT_REG;
306 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
307 // Helper args
308 tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0);
309 tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1);
310 tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2);
311 break;
312 case 'I':
313 ct->ct |= TCG_CT_CONST_S11;
314 break;
315 case 'J':
316 ct->ct |= TCG_CT_CONST_S13;
317 break;
318 case 'Z':
319 ct->ct |= TCG_CT_CONST_ZERO;
320 break;
321 default:
322 return -1;
323 }
324 ct_str++;
325 *pct_str = ct_str;
326 return 0;
327}
328
329/* test if a constant matches the constraint */
330static inline int tcg_target_const_match(tcg_target_long val,
331 const TCGArgConstraint *arg_ct)
332{
333 int ct = arg_ct->ct;
334
335 if (ct & TCG_CT_CONST) {
336 return 1;
337 } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
338 return 1;
339 } else if ((ct & TCG_CT_CONST_S11) && check_fit_tl(val, 11)) {
340 return 1;
341 } else if ((ct & TCG_CT_CONST_S13) && check_fit_tl(val, 13)) {
342 return 1;
343 } else {
344 return 0;
345 }
346}
347
26cc915c
BS
348static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2,
349 int op)
350{
351 tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) |
352 INSN_RS2(rs2));
353}
354
6f41b777
BS
355static inline void tcg_out_arithi(TCGContext *s, int rd, int rs1,
356 uint32_t offset, int op)
26cc915c
BS
357{
358 tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) |
359 INSN_IMM13(offset));
360}
361
ba225198
RH
362static void tcg_out_arithc(TCGContext *s, int rd, int rs1,
363 int val2, int val2const, int op)
364{
365 tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1)
366 | (val2const ? INSN_IMM13(val2) : INSN_RS2(val2)));
367}
368
2a534aff
RH
369static inline void tcg_out_mov(TCGContext *s, TCGType type,
370 TCGReg ret, TCGReg arg)
8289b279 371{
dda73c78
RH
372 if (ret != arg) {
373 tcg_out_arith(s, ret, arg, TCG_REG_G0, ARITH_OR);
374 }
26cc915c
BS
375}
376
377static inline void tcg_out_sethi(TCGContext *s, int ret, uint32_t arg)
378{
379 tcg_out32(s, SETHI | INSN_RD(ret) | ((arg & 0xfffffc00) >> 10));
8289b279
BS
380}
381
b101234a
BS
382static inline void tcg_out_movi_imm13(TCGContext *s, int ret, uint32_t arg)
383{
384 tcg_out_arithi(s, ret, TCG_REG_G0, arg, ARITH_OR);
385}
386
387static inline void tcg_out_movi_imm32(TCGContext *s, int ret, uint32_t arg)
8289b279 388{
4a09aa89 389 if (check_fit_tl(arg, 13))
b101234a 390 tcg_out_movi_imm13(s, ret, arg);
8289b279 391 else {
26cc915c 392 tcg_out_sethi(s, ret, arg);
8289b279 393 if (arg & 0x3ff)
b101234a 394 tcg_out_arithi(s, ret, ret, arg & 0x3ff, ARITH_OR);
8289b279
BS
395 }
396}
397
b101234a 398static inline void tcg_out_movi(TCGContext *s, TCGType type,
2a534aff 399 TCGReg ret, tcg_target_long arg)
b101234a 400{
43172207
RH
401 /* All 32-bit constants, as well as 64-bit constants with
402 no high bits set go through movi_imm32. */
403 if (TCG_TARGET_REG_BITS == 32
404 || type == TCG_TYPE_I32
405 || (arg & ~(tcg_target_long)0xffffffff) == 0) {
406 tcg_out_movi_imm32(s, ret, arg);
407 } else if (check_fit_tl(arg, 13)) {
408 /* A 13-bit constant sign-extended to 64-bits. */
409 tcg_out_movi_imm13(s, ret, arg);
410 } else if (check_fit_tl(arg, 32)) {
411 /* A 32-bit constant sign-extended to 64-bits. */
412 tcg_out_sethi(s, ret, ~arg);
413 tcg_out_arithi(s, ret, ret, (arg & 0x3ff) | -0x400, ARITH_XOR);
414 } else {
375816f8
RH
415 tcg_out_movi_imm32(s, ret, arg >> (TCG_TARGET_REG_BITS / 2));
416 tcg_out_arithi(s, ret, ret, 32, SHIFT_SLLX);
417 tcg_out_movi_imm32(s, TCG_REG_T2, arg);
418 tcg_out_arith(s, ret, ret, TCG_REG_T2, ARITH_OR);
6f41b777 419 }
b101234a
BS
420}
421
a0ce341a
RH
422static inline void tcg_out_ldst_rr(TCGContext *s, int data, int a1,
423 int a2, int op)
8289b279 424{
a0ce341a 425 tcg_out32(s, op | INSN_RD(data) | INSN_RS1(a1) | INSN_RS2(a2));
8289b279
BS
426}
427
a0ce341a
RH
428static inline void tcg_out_ldst(TCGContext *s, int ret, int addr,
429 int offset, int op)
8289b279 430{
a0ce341a 431 if (check_fit_tl(offset, 13)) {
8289b279
BS
432 tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) |
433 INSN_IMM13(offset));
a0ce341a 434 } else {
375816f8
RH
435 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, offset);
436 tcg_out_ldst_rr(s, ret, addr, TCG_REG_T1, op);
cf7c2ca5 437 }
8289b279
BS
438}
439
2a534aff 440static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
a05b5b9b 441 TCGReg arg1, intptr_t arg2)
8289b279 442{
a0ce341a 443 tcg_out_ldst(s, ret, arg1, arg2, (type == TCG_TYPE_I32 ? LDUW : LDX));
8289b279
BS
444}
445
2a534aff 446static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
a05b5b9b 447 TCGReg arg1, intptr_t arg2)
8289b279 448{
a0ce341a
RH
449 tcg_out_ldst(s, arg, arg1, arg2, (type == TCG_TYPE_I32 ? STW : STX));
450}
451
c8fc56ce 452static inline void tcg_out_ld_ptr(TCGContext *s, TCGReg ret, uintptr_t arg)
a0ce341a 453{
c8fc56ce 454 TCGReg base = TCG_REG_G0;
a0ce341a
RH
455 if (!check_fit_tl(arg, 10)) {
456 tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ff);
c8fc56ce 457 base = ret;
a0ce341a 458 }
c8fc56ce 459 tcg_out_ld(s, TCG_TYPE_PTR, ret, base, arg & 0x3ff);
8289b279
BS
460}
461
583d1215 462static inline void tcg_out_sety(TCGContext *s, int rs)
8289b279 463{
583d1215 464 tcg_out32(s, WRY | INSN_RS1(TCG_REG_G0) | INSN_RS2(rs));
8289b279
BS
465}
466
7a3766f3
RH
467static inline void tcg_out_rdy(TCGContext *s, int rd)
468{
469 tcg_out32(s, RDY | INSN_RD(rd));
470}
471
8289b279
BS
472static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
473{
474 if (val != 0) {
57e49b40 475 if (check_fit_tl(val, 13))
8289b279 476 tcg_out_arithi(s, reg, reg, val, ARITH_ADD);
f5ef6aac 477 else {
375816f8
RH
478 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, val);
479 tcg_out_arith(s, reg, reg, TCG_REG_T1, ARITH_ADD);
f5ef6aac 480 }
8289b279
BS
481 }
482}
483
583d1215
RH
484static void tcg_out_div32(TCGContext *s, int rd, int rs1,
485 int val2, int val2const, int uns)
486{
487 /* Load Y with the sign/zero extension of RS1 to 64-bits. */
488 if (uns) {
489 tcg_out_sety(s, TCG_REG_G0);
490 } else {
375816f8
RH
491 tcg_out_arithi(s, TCG_REG_T1, rs1, 31, SHIFT_SRA);
492 tcg_out_sety(s, TCG_REG_T1);
583d1215
RH
493 }
494
495 tcg_out_arithc(s, rd, rs1, val2, val2const,
496 uns ? ARITH_UDIV : ARITH_SDIV);
497}
498
8289b279
BS
499static inline void tcg_out_nop(TCGContext *s)
500{
26cc915c 501 tcg_out_sethi(s, TCG_REG_G0, 0);
8289b279
BS
502}
503
0aed257f 504static const uint8_t tcg_cond_to_bcond[] = {
cf7c2ca5
BS
505 [TCG_COND_EQ] = COND_E,
506 [TCG_COND_NE] = COND_NE,
507 [TCG_COND_LT] = COND_L,
508 [TCG_COND_GE] = COND_GE,
509 [TCG_COND_LE] = COND_LE,
510 [TCG_COND_GT] = COND_G,
511 [TCG_COND_LTU] = COND_CS,
512 [TCG_COND_GEU] = COND_CC,
513 [TCG_COND_LEU] = COND_LEU,
514 [TCG_COND_GTU] = COND_GU,
515};
516
ab1339b9
RH
517static const uint8_t tcg_cond_to_rcond[] = {
518 [TCG_COND_EQ] = RCOND_Z,
519 [TCG_COND_NE] = RCOND_NZ,
520 [TCG_COND_LT] = RCOND_LZ,
521 [TCG_COND_GT] = RCOND_GZ,
522 [TCG_COND_LE] = RCOND_LEZ,
523 [TCG_COND_GE] = RCOND_GEZ
524};
525
a115f3ea
RH
526static void tcg_out_bpcc0(TCGContext *s, int scond, int flags, int off19)
527{
528 tcg_out32(s, INSN_OP(0) | INSN_OP2(1) | INSN_COND(scond) | flags | off19);
529}
530
531static void tcg_out_bpcc(TCGContext *s, int scond, int flags, int label)
532{
533 TCGLabel *l = &s->labels[label];
534 int off19;
535
536 if (l->has_value) {
537 off19 = INSN_OFF19(l->u.value - (unsigned long)s->code_ptr);
538 } else {
539 /* Make sure to preserve destinations during retranslation. */
540 off19 = *(uint32_t *)s->code_ptr & INSN_OFF19(-1);
541 tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP19, label, 0);
542 }
543 tcg_out_bpcc0(s, scond, flags, off19);
544}
545
56f4927e
RH
546static void tcg_out_cmp(TCGContext *s, TCGArg c1, TCGArg c2, int c2const)
547{
ba225198 548 tcg_out_arithc(s, TCG_REG_G0, c1, c2, c2const, ARITH_SUBCC);
56f4927e
RH
549}
550
a115f3ea
RH
551static void tcg_out_brcond_i32(TCGContext *s, TCGCond cond, TCGArg arg1,
552 TCGArg arg2, int const_arg2, int label)
cf7c2ca5 553{
56f4927e 554 tcg_out_cmp(s, arg1, arg2, const_arg2);
a115f3ea 555 tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_ICC | BPCC_PT, label);
cf7c2ca5
BS
556 tcg_out_nop(s);
557}
558
ded37f0d
RH
559static void tcg_out_movcc(TCGContext *s, TCGCond cond, int cc, TCGArg ret,
560 TCGArg v1, int v1const)
561{
562 tcg_out32(s, ARITH_MOVCC | cc | INSN_RD(ret)
563 | INSN_RS1(tcg_cond_to_bcond[cond])
564 | (v1const ? INSN_IMM11(v1) : INSN_RS2(v1)));
565}
566
567static void tcg_out_movcond_i32(TCGContext *s, TCGCond cond, TCGArg ret,
568 TCGArg c1, TCGArg c2, int c2const,
569 TCGArg v1, int v1const)
570{
571 tcg_out_cmp(s, c1, c2, c2const);
572 tcg_out_movcc(s, cond, MOVCC_ICC, ret, v1, v1const);
573}
574
a212ea75 575#if TCG_TARGET_REG_BITS == 64
a115f3ea
RH
576static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGArg arg1,
577 TCGArg arg2, int const_arg2, int label)
1da92db2 578{
ab1339b9
RH
579 /* For 64-bit signed comparisons vs zero, we can avoid the compare. */
580 if (arg2 == 0 && !is_unsigned_cond(cond)) {
581 TCGLabel *l = &s->labels[label];
582 int off16;
583
584 if (l->has_value) {
585 off16 = INSN_OFF16(l->u.value - (unsigned long)s->code_ptr);
586 } else {
587 /* Make sure to preserve destinations during retranslation. */
588 off16 = *(uint32_t *)s->code_ptr & INSN_OFF16(-1);
589 tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP16, label, 0);
590 }
591 tcg_out32(s, INSN_OP(0) | INSN_OP2(3) | BPR_PT | INSN_RS1(arg1)
592 | INSN_COND(tcg_cond_to_rcond[cond]) | off16);
593 } else {
594 tcg_out_cmp(s, arg1, arg2, const_arg2);
595 tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_XCC | BPCC_PT, label);
596 }
1da92db2
BS
597 tcg_out_nop(s);
598}
ded37f0d 599
203342d8
RH
600static void tcg_out_movr(TCGContext *s, TCGCond cond, TCGArg ret, TCGArg c1,
601 TCGArg v1, int v1const)
602{
603 tcg_out32(s, ARITH_MOVR | INSN_RD(ret) | INSN_RS1(c1)
604 | (tcg_cond_to_rcond[cond] << 10)
605 | (v1const ? INSN_IMM10(v1) : INSN_RS2(v1)));
606}
607
ded37f0d
RH
608static void tcg_out_movcond_i64(TCGContext *s, TCGCond cond, TCGArg ret,
609 TCGArg c1, TCGArg c2, int c2const,
610 TCGArg v1, int v1const)
611{
203342d8
RH
612 /* For 64-bit signed comparisons vs zero, we can avoid the compare.
613 Note that the immediate range is one bit smaller, so we must check
614 for that as well. */
615 if (c2 == 0 && !is_unsigned_cond(cond)
616 && (!v1const || check_fit_tl(v1, 10))) {
617 tcg_out_movr(s, cond, ret, c1, v1, v1const);
618 } else {
619 tcg_out_cmp(s, c1, c2, c2const);
620 tcg_out_movcc(s, cond, MOVCC_XCC, ret, v1, v1const);
621 }
ded37f0d 622}
56f4927e 623#else
8a56e840 624static void tcg_out_brcond2_i32(TCGContext *s, TCGCond cond,
56f4927e
RH
625 TCGArg al, TCGArg ah,
626 TCGArg bl, int blconst,
627 TCGArg bh, int bhconst, int label_dest)
628{
a115f3ea 629 int scond, label_next = gen_new_label();
56f4927e
RH
630
631 tcg_out_cmp(s, ah, bh, bhconst);
632
633 /* Note that we fill one of the delay slots with the second compare. */
634 switch (cond) {
635 case TCG_COND_EQ:
a115f3ea 636 tcg_out_bpcc(s, COND_NE, BPCC_ICC | BPCC_PT, label_next);
56f4927e 637 tcg_out_cmp(s, al, bl, blconst);
a115f3ea 638 tcg_out_bpcc(s, COND_E, BPCC_ICC | BPCC_PT, label_dest);
56f4927e
RH
639 break;
640
641 case TCG_COND_NE:
a115f3ea 642 tcg_out_bpcc(s, COND_NE, BPCC_ICC | BPCC_PT, label_dest);
56f4927e 643 tcg_out_cmp(s, al, bl, blconst);
a115f3ea 644 tcg_out_bpcc(s, COND_NE, BPCC_ICC | BPCC_PT, label_dest);
56f4927e
RH
645 break;
646
647 default:
a115f3ea
RH
648 scond = tcg_cond_to_bcond[tcg_high_cond(cond)];
649 tcg_out_bpcc(s, scond, BPCC_ICC | BPCC_PT, label_dest);
56f4927e 650 tcg_out_nop(s);
a115f3ea 651 tcg_out_bpcc(s, COND_NE, BPCC_ICC | BPCC_PT, label_next);
56f4927e 652 tcg_out_cmp(s, al, bl, blconst);
a115f3ea
RH
653 scond = tcg_cond_to_bcond[tcg_unsigned_cond(cond)];
654 tcg_out_bpcc(s, scond, BPCC_ICC | BPCC_PT, label_dest);
56f4927e
RH
655 break;
656 }
657 tcg_out_nop(s);
658
9d6fca70 659 tcg_out_label(s, label_next, s->code_ptr);
56f4927e 660}
1da92db2
BS
661#endif
662
8a56e840 663static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGArg ret,
dbfe80e1
RH
664 TCGArg c1, TCGArg c2, int c2const)
665{
dbfe80e1
RH
666 /* For 32-bit comparisons, we can play games with ADDX/SUBX. */
667 switch (cond) {
7d458a75
RH
668 case TCG_COND_LTU:
669 case TCG_COND_GEU:
670 /* The result of the comparison is in the carry bit. */
671 break;
672
dbfe80e1
RH
673 case TCG_COND_EQ:
674 case TCG_COND_NE:
7d458a75 675 /* For equality, we can transform to inequality vs zero. */
dbfe80e1
RH
676 if (c2 != 0) {
677 tcg_out_arithc(s, ret, c1, c2, c2const, ARITH_XOR);
678 }
679 c1 = TCG_REG_G0, c2 = ret, c2const = 0;
7d458a75 680 cond = (cond == TCG_COND_EQ ? TCG_COND_GEU : TCG_COND_LTU);
dbfe80e1
RH
681 break;
682
683 case TCG_COND_GTU:
dbfe80e1 684 case TCG_COND_LEU:
7d458a75
RH
685 /* If we don't need to load a constant into a register, we can
686 swap the operands on GTU/LEU. There's no benefit to loading
687 the constant into a temporary register. */
688 if (!c2const || c2 == 0) {
689 TCGArg t = c1;
690 c1 = c2;
691 c2 = t;
692 c2const = 0;
693 cond = tcg_swap_cond(cond);
694 break;
695 }
696 /* FALLTHRU */
dbfe80e1
RH
697
698 default:
699 tcg_out_cmp(s, c1, c2, c2const);
dbfe80e1 700 tcg_out_movi_imm13(s, ret, 0);
ded37f0d 701 tcg_out_movcc(s, cond, MOVCC_ICC, ret, 1, 1);
dbfe80e1
RH
702 return;
703 }
704
705 tcg_out_cmp(s, c1, c2, c2const);
706 if (cond == TCG_COND_LTU) {
707 tcg_out_arithi(s, ret, TCG_REG_G0, 0, ARITH_ADDX);
708 } else {
709 tcg_out_arithi(s, ret, TCG_REG_G0, -1, ARITH_SUBX);
710 }
711}
712
713#if TCG_TARGET_REG_BITS == 64
8a56e840 714static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGArg ret,
dbfe80e1
RH
715 TCGArg c1, TCGArg c2, int c2const)
716{
203342d8
RH
717 /* For 64-bit signed comparisons vs zero, we can avoid the compare
718 if the input does not overlap the output. */
719 if (c2 == 0 && !is_unsigned_cond(cond) && c1 != ret) {
720 tcg_out_movi_imm13(s, ret, 0);
721 tcg_out_movr(s, cond, ret, c1, 1, 1);
722 } else {
723 tcg_out_cmp(s, c1, c2, c2const);
724 tcg_out_movi_imm13(s, ret, 0);
725 tcg_out_movcc(s, cond, MOVCC_XCC, ret, 1, 1);
726 }
dbfe80e1
RH
727}
728#else
8a56e840 729static void tcg_out_setcond2_i32(TCGContext *s, TCGCond cond, TCGArg ret,
dbfe80e1
RH
730 TCGArg al, TCGArg ah,
731 TCGArg bl, int blconst,
732 TCGArg bh, int bhconst)
733{
dda73c78
RH
734 int tmp = TCG_REG_T1;
735
736 /* Note that the low parts are fully consumed before tmp is set. */
737 if (ret != ah && (bhconst || ret != bh)) {
738 tmp = ret;
739 }
dbfe80e1
RH
740
741 switch (cond) {
742 case TCG_COND_EQ:
dbfe80e1 743 case TCG_COND_NE:
fd84ea23
RH
744 if (bl == 0 && bh == 0) {
745 if (cond == TCG_COND_EQ) {
746 tcg_out_arith(s, TCG_REG_G0, al, ah, ARITH_ORCC);
747 tcg_out_movi(s, TCG_TYPE_I32, ret, 1);
748 } else {
749 tcg_out_arith(s, ret, al, ah, ARITH_ORCC);
750 }
751 } else {
752 tcg_out_setcond_i32(s, cond, tmp, al, bl, blconst);
753 tcg_out_cmp(s, ah, bh, bhconst);
754 tcg_out_mov(s, TCG_TYPE_I32, ret, tmp);
755 }
dda73c78 756 tcg_out_movcc(s, TCG_COND_NE, MOVCC_ICC, ret, cond == TCG_COND_NE, 1);
dbfe80e1
RH
757 break;
758
759 default:
dda73c78
RH
760 /* <= : ah < bh | (ah == bh && al <= bl) */
761 tcg_out_setcond_i32(s, tcg_unsigned_cond(cond), tmp, al, bl, blconst);
dbfe80e1 762 tcg_out_cmp(s, ah, bh, bhconst);
dda73c78
RH
763 tcg_out_mov(s, TCG_TYPE_I32, ret, tmp);
764 tcg_out_movcc(s, TCG_COND_NE, MOVCC_ICC, ret, 0, 1);
765 tcg_out_movcc(s, tcg_high_cond(cond), MOVCC_ICC, ret, 1, 1);
dbfe80e1
RH
766 break;
767 }
768}
07ca08ba 769#endif
4ec28e25
RH
770
771static void tcg_out_addsub2(TCGContext *s, TCGArg rl, TCGArg rh,
772 TCGArg al, TCGArg ah, TCGArg bl, int blconst,
773 TCGArg bh, int bhconst, int opl, int oph)
774{
775 TCGArg tmp = TCG_REG_T1;
776
777 /* Note that the low parts are fully consumed before tmp is set. */
778 if (rl != ah && (bhconst || rl != bh)) {
779 tmp = rl;
780 }
781
782 tcg_out_arithc(s, tmp, al, bl, blconst, opl);
783 tcg_out_arithc(s, rh, ah, bh, bhconst, oph);
784 tcg_out_mov(s, TCG_TYPE_I32, rl, tmp);
785}
dbfe80e1 786
aad2f06a
RH
787static inline void tcg_out_calli(TCGContext *s, uintptr_t dest)
788{
789 intptr_t disp = dest - (uintptr_t)s->code_ptr;
790
791 if (disp == (int32_t)disp) {
792 tcg_out32(s, CALL | (uint32_t)disp >> 2);
793 } else {
794 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, dest & ~0xfff);
795 tcg_out_arithi(s, TCG_REG_O7, TCG_REG_T1, dest & 0xfff, JMPL);
796 }
797}
798
7d551702 799/* Generate global QEMU prologue and epilogue code */
e4d58b41 800static void tcg_target_qemu_prologue(TCGContext *s)
b3db8758 801{
4c3204cb
RH
802 int tmp_buf_size, frame_size;
803
804 /* The TCG temp buffer is at the top of the frame, immediately
805 below the frame pointer. */
806 tmp_buf_size = CPU_TEMP_BUF_NLONGS * (int)sizeof(long);
807 tcg_set_frame(s, TCG_REG_I6, TCG_TARGET_STACK_BIAS - tmp_buf_size,
808 tmp_buf_size);
809
810 /* TCG_TARGET_CALL_STACK_OFFSET includes the stack bias, but is
811 otherwise the minimal frame usable by callees. */
812 frame_size = TCG_TARGET_CALL_STACK_OFFSET - TCG_TARGET_STACK_BIAS;
813 frame_size += TCG_STATIC_CALL_ARGS_SIZE + tmp_buf_size;
814 frame_size += TCG_TARGET_STACK_ALIGN - 1;
815 frame_size &= -TCG_TARGET_STACK_ALIGN;
b3db8758 816 tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) |
4c3204cb 817 INSN_IMM13(-frame_size));
c6f7e4fb
RH
818
819#ifdef CONFIG_USE_GUEST_BASE
820 if (GUEST_BASE != 0) {
821 tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE);
822 tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
823 }
824#endif
825
aad2f06a 826 tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I1, 0, JMPL);
0c554161
RH
827 /* delay slot */
828 tcg_out_nop(s);
4c3204cb
RH
829
830 /* No epilogue required. We issue ret + restore directly in the TB. */
b3db8758
BS
831}
832
f5ef6aac 833#if defined(CONFIG_SOFTMMU)
f5ef6aac 834
e141ab52
BS
835/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
836 int mmu_idx) */
837static const void * const qemu_ld_helpers[4] = {
838 helper_ldb_mmu,
839 helper_ldw_mmu,
840 helper_ldl_mmu,
841 helper_ldq_mmu,
842};
843
844/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
845 uintxx_t val, int mmu_idx) */
846static const void * const qemu_st_helpers[4] = {
847 helper_stb_mmu,
848 helper_stw_mmu,
849 helper_stl_mmu,
850 helper_stq_mmu,
851};
f5ef6aac 852
a0ce341a 853/* Perform the TLB load and compare.
bffe1431 854
a0ce341a
RH
855 Inputs:
856 ADDRLO_IDX contains the index into ARGS of the low part of the
857 address; the high part of the address is at ADDR_LOW_IDX+1.
858
859 MEM_INDEX and S_BITS are the memory context and log2 size of the load.
860
861 WHICH is the offset into the CPUTLBEntry structure of the slot to read.
862 This should be offsetof addr_read or addr_write.
863
864 The result of the TLB comparison is in %[ix]cc. The sanitized address
865 is in the returned register, maybe %o0. The TLB addend is in %o1. */
866
867static int tcg_out_tlb_load(TCGContext *s, int addrlo_idx, int mem_index,
868 int s_bits, const TCGArg *args, int which)
869{
870 const int addrlo = args[addrlo_idx];
871 const int r0 = TCG_REG_O0;
872 const int r1 = TCG_REG_O1;
873 const int r2 = TCG_REG_O2;
874 int addr = addrlo;
875 int tlb_ofs;
876
877 if (TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 64) {
878 /* Assemble the 64-bit address in R0. */
879 tcg_out_arithi(s, r0, addrlo, 0, SHIFT_SRL);
880 tcg_out_arithi(s, r1, args[addrlo_idx + 1], 32, SHIFT_SLLX);
881 tcg_out_arith(s, r0, r0, r1, ARITH_OR);
d801a8f2 882 addr = r0;
a0ce341a
RH
883 }
884
d801a8f2
RH
885 /* Shift the page number down. */
886 tcg_out_arithi(s, r1, addrlo, TARGET_PAGE_BITS, SHIFT_SRL);
a0ce341a
RH
887
888 /* Mask out the page offset, except for the required alignment. */
d801a8f2
RH
889 tcg_out_movi(s, TCG_TYPE_TL, TCG_REG_T1,
890 TARGET_PAGE_MASK | ((1 << s_bits) - 1));
891
892 /* Mask the tlb index. */
893 tcg_out_arithi(s, r1, r1, CPU_TLB_SIZE - 1, ARITH_AND);
894
895 /* Mask page, part 2. */
896 tcg_out_arith(s, r0, addr, TCG_REG_T1, ARITH_AND);
a0ce341a 897
d801a8f2
RH
898 /* Shift the tlb index into place. */
899 tcg_out_arithi(s, r1, r1, CPU_TLB_ENTRY_BITS, SHIFT_SLL);
a0ce341a
RH
900
901 /* Relative to the current ENV. */
902 tcg_out_arith(s, r1, TCG_AREG0, r1, ARITH_ADD);
903
904 /* Find a base address that can load both tlb comparator and addend. */
905 tlb_ofs = offsetof(CPUArchState, tlb_table[mem_index][0]);
906 if (!check_fit_tl(tlb_ofs + sizeof(CPUTLBEntry), 13)) {
d801a8f2
RH
907 tcg_out_addi(s, r1, tlb_ofs & ~0x3ff);
908 tlb_ofs &= 0x3ff;
a0ce341a
RH
909 }
910
911 /* Load the tlb comparator and the addend. */
912 tcg_out_ld(s, TCG_TYPE_TL, r2, r1, tlb_ofs + which);
913 tcg_out_ld(s, TCG_TYPE_PTR, r1, r1, tlb_ofs+offsetof(CPUTLBEntry, addend));
914
915 /* subcc arg0, arg2, %g0 */
916 tcg_out_cmp(s, r0, r2, 0);
917
918 /* If the guest address must be zero-extended, do so now. */
919 if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) {
920 tcg_out_arithi(s, r0, addrlo, 0, SHIFT_SRL);
921 return r0;
922 }
923 return addrlo;
924}
925#endif /* CONFIG_SOFTMMU */
926
927static const int qemu_ld_opc[8] = {
928#ifdef TARGET_WORDS_BIGENDIAN
929 LDUB, LDUH, LDUW, LDX, LDSB, LDSH, LDSW, LDX
65850a02 930#else
a0ce341a 931 LDUB, LDUH_LE, LDUW_LE, LDX_LE, LDSB, LDSH_LE, LDSW_LE, LDX_LE
65850a02 932#endif
a0ce341a 933};
9d0efc88 934
a0ce341a
RH
935static const int qemu_st_opc[4] = {
936#ifdef TARGET_WORDS_BIGENDIAN
937 STB, STH, STW, STX
bffe1431 938#else
a0ce341a 939 STB, STH_LE, STW_LE, STX_LE
bffe1431 940#endif
a0ce341a 941};
bffe1431 942
a0ce341a 943static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop)
f5ef6aac 944{
a0ce341a 945 int addrlo_idx = 1, datalo, datahi, addr_reg;
f5ef6aac 946#if defined(CONFIG_SOFTMMU)
a0ce341a
RH
947 int memi_idx, memi, s_bits, n;
948 uint32_t *label_ptr[2];
f5ef6aac
BS
949#endif
950
a0ce341a
RH
951 datahi = datalo = args[0];
952 if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
953 datahi = args[1];
954 addrlo_idx = 2;
955 }
f5ef6aac 956
f5ef6aac 957#if defined(CONFIG_SOFTMMU)
a0ce341a
RH
958 memi_idx = addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS);
959 memi = args[memi_idx];
960 s_bits = sizeop & 3;
961
962 addr_reg = tcg_out_tlb_load(s, addrlo_idx, memi, s_bits, args,
963 offsetof(CPUTLBEntry, addr_read));
964
965 if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
966 int reg64;
967
968 /* bne,pn %[xi]cc, label0 */
969 label_ptr[0] = (uint32_t *)s->code_ptr;
a115f3ea
RH
970 tcg_out_bpcc0(s, COND_NE, BPCC_PN
971 | (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
e7bc9004 972 tcg_out_nop(s);
a0ce341a
RH
973
974 /* TLB Hit. */
975 /* Load all 64-bits into an O/G register. */
976 reg64 = (datalo < 16 ? datalo : TCG_REG_O0);
977 tcg_out_ldst_rr(s, reg64, addr_reg, TCG_REG_O1, qemu_ld_opc[sizeop]);
978
979 /* Move the two 32-bit pieces into the destination registers. */
980 tcg_out_arithi(s, datahi, reg64, 32, SHIFT_SRLX);
981 if (reg64 != datalo) {
982 tcg_out_mov(s, TCG_TYPE_I32, datalo, reg64);
983 }
f5ef6aac 984
a0ce341a
RH
985 /* b,a,pt label1 */
986 label_ptr[1] = (uint32_t *)s->code_ptr;
a115f3ea 987 tcg_out_bpcc0(s, COND_A, BPCC_A | BPCC_PT, 0);
a0ce341a
RH
988 } else {
989 /* The fast path is exactly one insn. Thus we can perform the
990 entire TLB Hit in the (annulled) delay slot of the branch
991 over the TLB Miss case. */
992
993 /* beq,a,pt %[xi]cc, label0 */
994 label_ptr[0] = NULL;
995 label_ptr[1] = (uint32_t *)s->code_ptr;
a115f3ea
RH
996 tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT
997 | (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
a0ce341a
RH
998 /* delay slot */
999 tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_O1, qemu_ld_opc[sizeop]);
1000 }
53c37487 1001
a0ce341a 1002 /* TLB Miss. */
f5ef6aac 1003
a0ce341a
RH
1004 if (label_ptr[0]) {
1005 *label_ptr[0] |= INSN_OFF19((unsigned long)s->code_ptr -
1006 (unsigned long)label_ptr[0]);
1007 }
1008 n = 0;
1009 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[n++], TCG_AREG0);
1010 if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
1011 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
1012 args[addrlo_idx + 1]);
1013 }
1014 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
1015 args[addrlo_idx]);
f5ef6aac 1016
53c37487 1017 /* qemu_ld_helper[s_bits](arg0, arg1) */
aad2f06a 1018 tcg_out_calli(s, (uintptr_t)qemu_ld_helpers[s_bits]);
a0ce341a
RH
1019 /* delay slot */
1020 tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[n], memi);
1021
a0ce341a
RH
1022 n = tcg_target_call_oarg_regs[0];
1023 /* datalo = sign_extend(arg0) */
1024 switch (sizeop) {
f5ef6aac 1025 case 0 | 4:
a0ce341a
RH
1026 /* Recall that SRA sign extends from bit 31 through bit 63. */
1027 tcg_out_arithi(s, datalo, n, 24, SHIFT_SLL);
1028 tcg_out_arithi(s, datalo, datalo, 24, SHIFT_SRA);
f5ef6aac
BS
1029 break;
1030 case 1 | 4:
a0ce341a
RH
1031 tcg_out_arithi(s, datalo, n, 16, SHIFT_SLL);
1032 tcg_out_arithi(s, datalo, datalo, 16, SHIFT_SRA);
f5ef6aac
BS
1033 break;
1034 case 2 | 4:
a0ce341a 1035 tcg_out_arithi(s, datalo, n, 0, SHIFT_SRA);
f5ef6aac 1036 break;
a0ce341a
RH
1037 case 3:
1038 if (TCG_TARGET_REG_BITS == 32) {
1039 tcg_out_mov(s, TCG_TYPE_REG, datahi, n);
1040 tcg_out_mov(s, TCG_TYPE_REG, datalo, n + 1);
1041 break;
1042 }
1043 /* FALLTHRU */
f5ef6aac
BS
1044 case 0:
1045 case 1:
1046 case 2:
f5ef6aac
BS
1047 default:
1048 /* mov */
a0ce341a 1049 tcg_out_mov(s, TCG_TYPE_REG, datalo, n);
f5ef6aac
BS
1050 break;
1051 }
1052
a0ce341a
RH
1053 *label_ptr[1] |= INSN_OFF19((unsigned long)s->code_ptr -
1054 (unsigned long)label_ptr[1]);
90cbed46 1055#else
a0ce341a
RH
1056 addr_reg = args[addrlo_idx];
1057 if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) {
375816f8
RH
1058 tcg_out_arithi(s, TCG_REG_T1, addr_reg, 0, SHIFT_SRL);
1059 addr_reg = TCG_REG_T1;
a0ce341a
RH
1060 }
1061 if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
1062 int reg64 = (datalo < 16 ? datalo : TCG_REG_O0);
90cbed46 1063
c6f7e4fb
RH
1064 tcg_out_ldst_rr(s, reg64, addr_reg,
1065 (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
1066 qemu_ld_opc[sizeop]);
f5ef6aac 1067
a0ce341a
RH
1068 tcg_out_arithi(s, datahi, reg64, 32, SHIFT_SRLX);
1069 if (reg64 != datalo) {
1070 tcg_out_mov(s, TCG_TYPE_I32, datalo, reg64);
1071 }
1072 } else {
c6f7e4fb
RH
1073 tcg_out_ldst_rr(s, datalo, addr_reg,
1074 (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
1075 qemu_ld_opc[sizeop]);
f5ef6aac 1076 }
a0ce341a 1077#endif /* CONFIG_SOFTMMU */
f5ef6aac
BS
1078}
1079
a0ce341a 1080static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop)
f5ef6aac 1081{
a0ce341a 1082 int addrlo_idx = 1, datalo, datahi, addr_reg;
f5ef6aac 1083#if defined(CONFIG_SOFTMMU)
a7a49843 1084 int memi_idx, memi, n, datafull;
a0ce341a 1085 uint32_t *label_ptr;
f5ef6aac
BS
1086#endif
1087
a0ce341a
RH
1088 datahi = datalo = args[0];
1089 if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
1090 datahi = args[1];
1091 addrlo_idx = 2;
1092 }
f5ef6aac 1093
f5ef6aac 1094#if defined(CONFIG_SOFTMMU)
a0ce341a
RH
1095 memi_idx = addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS);
1096 memi = args[memi_idx];
1097
1098 addr_reg = tcg_out_tlb_load(s, addrlo_idx, memi, sizeop, args,
1099 offsetof(CPUTLBEntry, addr_write));
1100
a7a49843 1101 datafull = datalo;
a0ce341a 1102 if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
375816f8
RH
1103 /* Reconstruct the full 64-bit value. */
1104 tcg_out_arithi(s, TCG_REG_T1, datalo, 0, SHIFT_SRL);
a0ce341a 1105 tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX);
375816f8 1106 tcg_out_arith(s, TCG_REG_O2, TCG_REG_T1, TCG_REG_O2, ARITH_OR);
a7a49843 1107 datafull = TCG_REG_O2;
a0ce341a 1108 }
f5ef6aac 1109
a0ce341a
RH
1110 /* The fast path is exactly one insn. Thus we can perform the entire
1111 TLB Hit in the (annulled) delay slot of the branch over TLB Miss. */
1112 /* beq,a,pt %[xi]cc, label0 */
1113 label_ptr = (uint32_t *)s->code_ptr;
a115f3ea
RH
1114 tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT
1115 | (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
a0ce341a 1116 /* delay slot */
a7a49843 1117 tcg_out_ldst_rr(s, datafull, addr_reg, TCG_REG_O1, qemu_st_opc[sizeop]);
a0ce341a
RH
1118
1119 /* TLB Miss. */
1120
1121 n = 0;
1122 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[n++], TCG_AREG0);
1123 if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
1124 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
1125 args[addrlo_idx + 1]);
1126 }
1127 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
1128 args[addrlo_idx]);
1129 if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
1130 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], datahi);
1131 }
1132 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], datalo);
53c37487 1133
53c37487 1134 /* qemu_st_helper[s_bits](arg0, arg1, arg2) */
aad2f06a 1135 tcg_out_calli(s, (uintptr_t)qemu_st_helpers[sizeop]);
a0ce341a
RH
1136 /* delay slot */
1137 tcg_out_movi(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n], memi);
f5ef6aac 1138
a0ce341a
RH
1139 *label_ptr |= INSN_OFF19((unsigned long)s->code_ptr -
1140 (unsigned long)label_ptr);
8384dd67 1141#else
a0ce341a
RH
1142 addr_reg = args[addrlo_idx];
1143 if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) {
375816f8
RH
1144 tcg_out_arithi(s, TCG_REG_T1, addr_reg, 0, SHIFT_SRL);
1145 addr_reg = TCG_REG_T1;
f5ef6aac 1146 }
a0ce341a 1147 if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
375816f8 1148 tcg_out_arithi(s, TCG_REG_T1, datalo, 0, SHIFT_SRL);
a0ce341a 1149 tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX);
375816f8
RH
1150 tcg_out_arith(s, TCG_REG_O2, TCG_REG_T1, TCG_REG_O2, ARITH_OR);
1151 datalo = TCG_REG_O2;
a0ce341a 1152 }
c6f7e4fb
RH
1153 tcg_out_ldst_rr(s, datalo, addr_reg,
1154 (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
1155 qemu_st_opc[sizeop]);
a0ce341a 1156#endif /* CONFIG_SOFTMMU */
f5ef6aac
BS
1157}
1158
a9751609 1159static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
8289b279
BS
1160 const int *const_args)
1161{
1162 int c;
1163
1164 switch (opc) {
1165 case INDEX_op_exit_tb:
b3db8758 1166 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I0, args[0]);
aad2f06a 1167 tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, JMPL);
b3db8758
BS
1168 tcg_out32(s, RESTORE | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_G0) |
1169 INSN_RS2(TCG_REG_G0));
8289b279
BS
1170 break;
1171 case INDEX_op_goto_tb:
1172 if (s->tb_jmp_offset) {
1173 /* direct jump method */
5bbd2cae 1174 uint32_t old_insn = *(uint32_t *)s->code_ptr;
8289b279 1175 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
5bbd2cae
RH
1176 /* Make sure to preserve links during retranslation. */
1177 tcg_out32(s, CALL | (old_insn & ~INSN_OP(-1)));
8289b279
BS
1178 } else {
1179 /* indirect jump method */
c8fc56ce 1180 tcg_out_ld_ptr(s, TCG_REG_T1, (uintptr_t)(s->tb_next + args[0]));
aad2f06a 1181 tcg_out_arithi(s, TCG_REG_G0, TCG_REG_T1, 0, JMPL);
8289b279 1182 }
53cd9273 1183 tcg_out_nop(s);
8289b279
BS
1184 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1185 break;
1186 case INDEX_op_call:
375816f8 1187 if (const_args[0]) {
aad2f06a 1188 tcg_out_calli(s, args[0]);
375816f8 1189 } else {
aad2f06a 1190 tcg_out_arithi(s, TCG_REG_O7, args[0], 0, JMPL);
8289b279 1191 }
4c3204cb
RH
1192 /* delay slot */
1193 tcg_out_nop(s);
8289b279 1194 break;
8289b279 1195 case INDEX_op_br:
a115f3ea 1196 tcg_out_bpcc(s, COND_A, BPCC_PT, args[0]);
f5ef6aac 1197 tcg_out_nop(s);
8289b279
BS
1198 break;
1199 case INDEX_op_movi_i32:
1200 tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]);
1201 break;
1202
a212ea75 1203#if TCG_TARGET_REG_BITS == 64
8289b279 1204#define OP_32_64(x) \
ba225198
RH
1205 glue(glue(case INDEX_op_, x), _i32): \
1206 glue(glue(case INDEX_op_, x), _i64)
8289b279
BS
1207#else
1208#define OP_32_64(x) \
ba225198 1209 glue(glue(case INDEX_op_, x), _i32)
8289b279 1210#endif
ba225198 1211 OP_32_64(ld8u):
8289b279
BS
1212 tcg_out_ldst(s, args[0], args[1], args[2], LDUB);
1213 break;
ba225198 1214 OP_32_64(ld8s):
8289b279
BS
1215 tcg_out_ldst(s, args[0], args[1], args[2], LDSB);
1216 break;
ba225198 1217 OP_32_64(ld16u):
8289b279
BS
1218 tcg_out_ldst(s, args[0], args[1], args[2], LDUH);
1219 break;
ba225198 1220 OP_32_64(ld16s):
8289b279
BS
1221 tcg_out_ldst(s, args[0], args[1], args[2], LDSH);
1222 break;
1223 case INDEX_op_ld_i32:
a212ea75 1224#if TCG_TARGET_REG_BITS == 64
53cd9273 1225 case INDEX_op_ld32u_i64:
8289b279
BS
1226#endif
1227 tcg_out_ldst(s, args[0], args[1], args[2], LDUW);
1228 break;
ba225198 1229 OP_32_64(st8):
8289b279
BS
1230 tcg_out_ldst(s, args[0], args[1], args[2], STB);
1231 break;
ba225198 1232 OP_32_64(st16):
8289b279
BS
1233 tcg_out_ldst(s, args[0], args[1], args[2], STH);
1234 break;
1235 case INDEX_op_st_i32:
a212ea75 1236#if TCG_TARGET_REG_BITS == 64
53cd9273 1237 case INDEX_op_st32_i64:
8289b279
BS
1238#endif
1239 tcg_out_ldst(s, args[0], args[1], args[2], STW);
1240 break;
ba225198 1241 OP_32_64(add):
53cd9273 1242 c = ARITH_ADD;
ba225198
RH
1243 goto gen_arith;
1244 OP_32_64(sub):
8289b279 1245 c = ARITH_SUB;
ba225198
RH
1246 goto gen_arith;
1247 OP_32_64(and):
8289b279 1248 c = ARITH_AND;
ba225198 1249 goto gen_arith;
dc69960d
RH
1250 OP_32_64(andc):
1251 c = ARITH_ANDN;
1252 goto gen_arith;
ba225198 1253 OP_32_64(or):
8289b279 1254 c = ARITH_OR;
ba225198 1255 goto gen_arith;
18c8f7a3
RH
1256 OP_32_64(orc):
1257 c = ARITH_ORN;
1258 goto gen_arith;
ba225198 1259 OP_32_64(xor):
8289b279 1260 c = ARITH_XOR;
ba225198 1261 goto gen_arith;
8289b279
BS
1262 case INDEX_op_shl_i32:
1263 c = SHIFT_SLL;
1fd95946
RH
1264 do_shift32:
1265 /* Limit immediate shift count lest we create an illegal insn. */
1266 tcg_out_arithc(s, args[0], args[1], args[2] & 31, const_args[2], c);
1267 break;
8289b279
BS
1268 case INDEX_op_shr_i32:
1269 c = SHIFT_SRL;
1fd95946 1270 goto do_shift32;
8289b279
BS
1271 case INDEX_op_sar_i32:
1272 c = SHIFT_SRA;
1fd95946 1273 goto do_shift32;
8289b279
BS
1274 case INDEX_op_mul_i32:
1275 c = ARITH_UMUL;
ba225198 1276 goto gen_arith;
583d1215 1277
4b5a85c1
RH
1278 OP_32_64(neg):
1279 c = ARITH_SUB;
1280 goto gen_arith1;
be6551b1
RH
1281 OP_32_64(not):
1282 c = ARITH_ORN;
1283 goto gen_arith1;
4b5a85c1 1284
583d1215
RH
1285 case INDEX_op_div_i32:
1286 tcg_out_div32(s, args[0], args[1], args[2], const_args[2], 0);
1287 break;
1288 case INDEX_op_divu_i32:
1289 tcg_out_div32(s, args[0], args[1], args[2], const_args[2], 1);
1290 break;
1291
8289b279 1292 case INDEX_op_brcond_i32:
1da92db2
BS
1293 tcg_out_brcond_i32(s, args[2], args[0], args[1], const_args[1],
1294 args[3]);
8289b279 1295 break;
dbfe80e1
RH
1296 case INDEX_op_setcond_i32:
1297 tcg_out_setcond_i32(s, args[3], args[0], args[1],
1298 args[2], const_args[2]);
1299 break;
ded37f0d
RH
1300 case INDEX_op_movcond_i32:
1301 tcg_out_movcond_i32(s, args[5], args[0], args[1],
1302 args[2], const_args[2], args[3], const_args[3]);
1303 break;
dbfe80e1 1304
56f4927e
RH
1305#if TCG_TARGET_REG_BITS == 32
1306 case INDEX_op_brcond2_i32:
1307 tcg_out_brcond2_i32(s, args[4], args[0], args[1],
1308 args[2], const_args[2],
1309 args[3], const_args[3], args[5]);
1310 break;
dbfe80e1
RH
1311 case INDEX_op_setcond2_i32:
1312 tcg_out_setcond2_i32(s, args[5], args[0], args[1], args[2],
1313 args[3], const_args[3],
1314 args[4], const_args[4]);
1315 break;
803d805b
RH
1316#endif
1317
7a3766f3 1318 case INDEX_op_add2_i32:
4ec28e25
RH
1319 tcg_out_addsub2(s, args[0], args[1], args[2], args[3],
1320 args[4], const_args[4], args[5], const_args[5],
1321 ARITH_ADDCC, ARITH_ADDX);
7a3766f3
RH
1322 break;
1323 case INDEX_op_sub2_i32:
4ec28e25
RH
1324 tcg_out_addsub2(s, args[0], args[1], args[2], args[3],
1325 args[4], const_args[4], args[5], const_args[5],
1326 ARITH_SUBCC, ARITH_SUBX);
7a3766f3
RH
1327 break;
1328 case INDEX_op_mulu2_i32:
1329 tcg_out_arithc(s, args[0], args[2], args[3], const_args[3],
1330 ARITH_UMUL);
1331 tcg_out_rdy(s, args[1]);
1332 break;
8289b279
BS
1333
1334 case INDEX_op_qemu_ld8u:
f5ef6aac 1335 tcg_out_qemu_ld(s, args, 0);
8289b279
BS
1336 break;
1337 case INDEX_op_qemu_ld8s:
f5ef6aac 1338 tcg_out_qemu_ld(s, args, 0 | 4);
8289b279
BS
1339 break;
1340 case INDEX_op_qemu_ld16u:
f5ef6aac 1341 tcg_out_qemu_ld(s, args, 1);
8289b279
BS
1342 break;
1343 case INDEX_op_qemu_ld16s:
f5ef6aac 1344 tcg_out_qemu_ld(s, args, 1 | 4);
8289b279 1345 break;
86feb1c8
RH
1346 case INDEX_op_qemu_ld32:
1347#if TCG_TARGET_REG_BITS == 64
8289b279 1348 case INDEX_op_qemu_ld32u:
86feb1c8 1349#endif
f5ef6aac 1350 tcg_out_qemu_ld(s, args, 2);
8289b279 1351 break;
30c0c76c 1352#if TCG_TARGET_REG_BITS == 64
8289b279 1353 case INDEX_op_qemu_ld32s:
f5ef6aac 1354 tcg_out_qemu_ld(s, args, 2 | 4);
8289b279 1355 break;
30c0c76c 1356#endif
a0ce341a
RH
1357 case INDEX_op_qemu_ld64:
1358 tcg_out_qemu_ld(s, args, 3);
1359 break;
8289b279 1360 case INDEX_op_qemu_st8:
f5ef6aac 1361 tcg_out_qemu_st(s, args, 0);
8289b279
BS
1362 break;
1363 case INDEX_op_qemu_st16:
f5ef6aac 1364 tcg_out_qemu_st(s, args, 1);
8289b279
BS
1365 break;
1366 case INDEX_op_qemu_st32:
f5ef6aac 1367 tcg_out_qemu_st(s, args, 2);
8289b279 1368 break;
a0ce341a
RH
1369 case INDEX_op_qemu_st64:
1370 tcg_out_qemu_st(s, args, 3);
1371 break;
8289b279 1372
a212ea75 1373#if TCG_TARGET_REG_BITS == 64
8289b279
BS
1374 case INDEX_op_movi_i64:
1375 tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
1376 break;
53cd9273
BS
1377 case INDEX_op_ld32s_i64:
1378 tcg_out_ldst(s, args[0], args[1], args[2], LDSW);
1379 break;
8289b279
BS
1380 case INDEX_op_ld_i64:
1381 tcg_out_ldst(s, args[0], args[1], args[2], LDX);
1382 break;
1383 case INDEX_op_st_i64:
1384 tcg_out_ldst(s, args[0], args[1], args[2], STX);
1385 break;
1386 case INDEX_op_shl_i64:
1387 c = SHIFT_SLLX;
1fd95946
RH
1388 do_shift64:
1389 /* Limit immediate shift count lest we create an illegal insn. */
1390 tcg_out_arithc(s, args[0], args[1], args[2] & 63, const_args[2], c);
1391 break;
8289b279
BS
1392 case INDEX_op_shr_i64:
1393 c = SHIFT_SRLX;
1fd95946 1394 goto do_shift64;
8289b279
BS
1395 case INDEX_op_sar_i64:
1396 c = SHIFT_SRAX;
1fd95946 1397 goto do_shift64;
8289b279
BS
1398 case INDEX_op_mul_i64:
1399 c = ARITH_MULX;
ba225198 1400 goto gen_arith;
583d1215 1401 case INDEX_op_div_i64:
53cd9273 1402 c = ARITH_SDIVX;
ba225198 1403 goto gen_arith;
583d1215 1404 case INDEX_op_divu_i64:
8289b279 1405 c = ARITH_UDIVX;
ba225198 1406 goto gen_arith;
cc6dfecf 1407 case INDEX_op_ext32s_i64:
1d0a6068 1408 tcg_out_arithi(s, args[0], args[1], 0, SHIFT_SRA);
cc6dfecf
RH
1409 break;
1410 case INDEX_op_ext32u_i64:
1d0a6068 1411 tcg_out_arithi(s, args[0], args[1], 0, SHIFT_SRL);
cc6dfecf 1412 break;
8289b279
BS
1413
1414 case INDEX_op_brcond_i64:
1da92db2
BS
1415 tcg_out_brcond_i64(s, args[2], args[0], args[1], const_args[1],
1416 args[3]);
8289b279 1417 break;
dbfe80e1
RH
1418 case INDEX_op_setcond_i64:
1419 tcg_out_setcond_i64(s, args[3], args[0], args[1],
1420 args[2], const_args[2]);
1421 break;
ded37f0d
RH
1422 case INDEX_op_movcond_i64:
1423 tcg_out_movcond_i64(s, args[5], args[0], args[1],
1424 args[2], const_args[2], args[3], const_args[3]);
1425 break;
8289b279 1426#endif
ba225198
RH
1427 gen_arith:
1428 tcg_out_arithc(s, args[0], args[1], args[2], const_args[2], c);
53cd9273
BS
1429 break;
1430
4b5a85c1
RH
1431 gen_arith1:
1432 tcg_out_arithc(s, args[0], TCG_REG_G0, args[1], const_args[1], c);
1433 break;
1434
8289b279
BS
1435 default:
1436 fprintf(stderr, "unknown opcode 0x%x\n", opc);
1437 tcg_abort();
1438 }
1439}
1440
1441static const TCGTargetOpDef sparc_op_defs[] = {
1442 { INDEX_op_exit_tb, { } },
b3db8758 1443 { INDEX_op_goto_tb, { } },
8289b279 1444 { INDEX_op_call, { "ri" } },
8289b279
BS
1445 { INDEX_op_br, { } },
1446
1447 { INDEX_op_mov_i32, { "r", "r" } },
1448 { INDEX_op_movi_i32, { "r" } },
1449 { INDEX_op_ld8u_i32, { "r", "r" } },
1450 { INDEX_op_ld8s_i32, { "r", "r" } },
1451 { INDEX_op_ld16u_i32, { "r", "r" } },
1452 { INDEX_op_ld16s_i32, { "r", "r" } },
1453 { INDEX_op_ld_i32, { "r", "r" } },
89269f6c
RH
1454 { INDEX_op_st8_i32, { "rZ", "r" } },
1455 { INDEX_op_st16_i32, { "rZ", "r" } },
1456 { INDEX_op_st_i32, { "rZ", "r" } },
1457
1458 { INDEX_op_add_i32, { "r", "rZ", "rJ" } },
1459 { INDEX_op_mul_i32, { "r", "rZ", "rJ" } },
1460 { INDEX_op_div_i32, { "r", "rZ", "rJ" } },
1461 { INDEX_op_divu_i32, { "r", "rZ", "rJ" } },
89269f6c
RH
1462 { INDEX_op_sub_i32, { "r", "rZ", "rJ" } },
1463 { INDEX_op_and_i32, { "r", "rZ", "rJ" } },
1464 { INDEX_op_andc_i32, { "r", "rZ", "rJ" } },
1465 { INDEX_op_or_i32, { "r", "rZ", "rJ" } },
1466 { INDEX_op_orc_i32, { "r", "rZ", "rJ" } },
1467 { INDEX_op_xor_i32, { "r", "rZ", "rJ" } },
1468
1469 { INDEX_op_shl_i32, { "r", "rZ", "rJ" } },
1470 { INDEX_op_shr_i32, { "r", "rZ", "rJ" } },
1471 { INDEX_op_sar_i32, { "r", "rZ", "rJ" } },
8289b279 1472
4b5a85c1 1473 { INDEX_op_neg_i32, { "r", "rJ" } },
be6551b1 1474 { INDEX_op_not_i32, { "r", "rJ" } },
4b5a85c1 1475
89269f6c
RH
1476 { INDEX_op_brcond_i32, { "rZ", "rJ" } },
1477 { INDEX_op_setcond_i32, { "r", "rZ", "rJ" } },
1478 { INDEX_op_movcond_i32, { "r", "rZ", "rJ", "rI", "0" } },
dbfe80e1 1479
56f4927e 1480#if TCG_TARGET_REG_BITS == 32
89269f6c
RH
1481 { INDEX_op_brcond2_i32, { "rZ", "rZ", "rJ", "rJ" } },
1482 { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rJ", "rJ" } },
803d805b
RH
1483#endif
1484
89269f6c
RH
1485 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
1486 { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
1487 { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rJ" } },
8289b279 1488
a212ea75 1489#if TCG_TARGET_REG_BITS == 64
8289b279
BS
1490 { INDEX_op_mov_i64, { "r", "r" } },
1491 { INDEX_op_movi_i64, { "r" } },
1492 { INDEX_op_ld8u_i64, { "r", "r" } },
1493 { INDEX_op_ld8s_i64, { "r", "r" } },
1494 { INDEX_op_ld16u_i64, { "r", "r" } },
1495 { INDEX_op_ld16s_i64, { "r", "r" } },
1496 { INDEX_op_ld32u_i64, { "r", "r" } },
1497 { INDEX_op_ld32s_i64, { "r", "r" } },
1498 { INDEX_op_ld_i64, { "r", "r" } },
89269f6c
RH
1499 { INDEX_op_st8_i64, { "rZ", "r" } },
1500 { INDEX_op_st16_i64, { "rZ", "r" } },
1501 { INDEX_op_st32_i64, { "rZ", "r" } },
1502 { INDEX_op_st_i64, { "rZ", "r" } },
1503
1504 { INDEX_op_add_i64, { "r", "rZ", "rJ" } },
1505 { INDEX_op_mul_i64, { "r", "rZ", "rJ" } },
1506 { INDEX_op_div_i64, { "r", "rZ", "rJ" } },
1507 { INDEX_op_divu_i64, { "r", "rZ", "rJ" } },
89269f6c
RH
1508 { INDEX_op_sub_i64, { "r", "rZ", "rJ" } },
1509 { INDEX_op_and_i64, { "r", "rZ", "rJ" } },
1510 { INDEX_op_andc_i64, { "r", "rZ", "rJ" } },
1511 { INDEX_op_or_i64, { "r", "rZ", "rJ" } },
1512 { INDEX_op_orc_i64, { "r", "rZ", "rJ" } },
1513 { INDEX_op_xor_i64, { "r", "rZ", "rJ" } },
1514
1515 { INDEX_op_shl_i64, { "r", "rZ", "rJ" } },
1516 { INDEX_op_shr_i64, { "r", "rZ", "rJ" } },
1517 { INDEX_op_sar_i64, { "r", "rZ", "rJ" } },
4b5a85c1
RH
1518
1519 { INDEX_op_neg_i64, { "r", "rJ" } },
be6551b1 1520 { INDEX_op_not_i64, { "r", "rJ" } },
4b5a85c1 1521
1d0a6068
RH
1522 { INDEX_op_ext32s_i64, { "r", "r" } },
1523 { INDEX_op_ext32u_i64, { "r", "r" } },
8289b279 1524
89269f6c
RH
1525 { INDEX_op_brcond_i64, { "rZ", "rJ" } },
1526 { INDEX_op_setcond_i64, { "r", "rZ", "rJ" } },
1527 { INDEX_op_movcond_i64, { "r", "rZ", "rJ", "rI", "0" } },
8289b279 1528#endif
a0ce341a
RH
1529
1530#if TCG_TARGET_REG_BITS == 64
1531 { INDEX_op_qemu_ld8u, { "r", "L" } },
1532 { INDEX_op_qemu_ld8s, { "r", "L" } },
1533 { INDEX_op_qemu_ld16u, { "r", "L" } },
1534 { INDEX_op_qemu_ld16s, { "r", "L" } },
1535 { INDEX_op_qemu_ld32, { "r", "L" } },
1536 { INDEX_op_qemu_ld32u, { "r", "L" } },
1537 { INDEX_op_qemu_ld32s, { "r", "L" } },
1538 { INDEX_op_qemu_ld64, { "r", "L" } },
1539
1540 { INDEX_op_qemu_st8, { "L", "L" } },
1541 { INDEX_op_qemu_st16, { "L", "L" } },
1542 { INDEX_op_qemu_st32, { "L", "L" } },
1543 { INDEX_op_qemu_st64, { "L", "L" } },
1544#elif TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
1545 { INDEX_op_qemu_ld8u, { "r", "L" } },
1546 { INDEX_op_qemu_ld8s, { "r", "L" } },
1547 { INDEX_op_qemu_ld16u, { "r", "L" } },
1548 { INDEX_op_qemu_ld16s, { "r", "L" } },
1549 { INDEX_op_qemu_ld32, { "r", "L" } },
1550 { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1551
1552 { INDEX_op_qemu_st8, { "L", "L" } },
1553 { INDEX_op_qemu_st16, { "L", "L" } },
1554 { INDEX_op_qemu_st32, { "L", "L" } },
3ee60ad4 1555 { INDEX_op_qemu_st64, { "L", "L", "L" } },
a0ce341a
RH
1556#else
1557 { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1558 { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1559 { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1560 { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1561 { INDEX_op_qemu_ld32, { "r", "L", "L" } },
1562 { INDEX_op_qemu_ld64, { "L", "L", "L", "L" } },
1563
1564 { INDEX_op_qemu_st8, { "L", "L", "L" } },
1565 { INDEX_op_qemu_st16, { "L", "L", "L" } },
1566 { INDEX_op_qemu_st32, { "L", "L", "L" } },
1567 { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
8289b279 1568#endif
a0ce341a 1569
8289b279
BS
1570 { -1 },
1571};
1572
e4d58b41 1573static void tcg_target_init(TCGContext *s)
8289b279
BS
1574{
1575 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
a212ea75 1576#if TCG_TARGET_REG_BITS == 64
8289b279
BS
1577 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
1578#endif
1579 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
b3db8758
BS
1580 (1 << TCG_REG_G1) |
1581 (1 << TCG_REG_G2) |
1582 (1 << TCG_REG_G3) |
1583 (1 << TCG_REG_G4) |
1584 (1 << TCG_REG_G5) |
1585 (1 << TCG_REG_G6) |
1586 (1 << TCG_REG_G7) |
8289b279
BS
1587 (1 << TCG_REG_O0) |
1588 (1 << TCG_REG_O1) |
1589 (1 << TCG_REG_O2) |
1590 (1 << TCG_REG_O3) |
1591 (1 << TCG_REG_O4) |
1592 (1 << TCG_REG_O5) |
8289b279
BS
1593 (1 << TCG_REG_O7));
1594
1595 tcg_regset_clear(s->reserved_regs);
375816f8
RH
1596 tcg_regset_set_reg(s->reserved_regs, TCG_REG_G0); /* zero */
1597 tcg_regset_set_reg(s->reserved_regs, TCG_REG_G6); /* reserved for os */
1598 tcg_regset_set_reg(s->reserved_regs, TCG_REG_G7); /* thread pointer */
1599 tcg_regset_set_reg(s->reserved_regs, TCG_REG_I6); /* frame pointer */
1600 tcg_regset_set_reg(s->reserved_regs, TCG_REG_I7); /* return address */
1601 tcg_regset_set_reg(s->reserved_regs, TCG_REG_O6); /* stack pointer */
1602 tcg_regset_set_reg(s->reserved_regs, TCG_REG_T1); /* for internal use */
1603 tcg_regset_set_reg(s->reserved_regs, TCG_REG_T2); /* for internal use */
1604
8289b279
BS
1605 tcg_add_target_add_op_defs(sparc_op_defs);
1606}
cb1977d3
RH
1607
1608#if TCG_TARGET_REG_BITS == 64
1609# define ELF_HOST_MACHINE EM_SPARCV9
9b9c37c3 1610#else
cb1977d3
RH
1611# define ELF_HOST_MACHINE EM_SPARC32PLUS
1612# define ELF_HOST_FLAGS EF_SPARC_32PLUS
cb1977d3
RH
1613#endif
1614
cb1977d3
RH
1615typedef struct {
1616 DebugFrameCIE cie;
497a22eb
RH
1617 DebugFrameFDEHeader fde;
1618 uint8_t fde_def_cfa[TCG_TARGET_REG_BITS == 64 ? 4 : 2];
1619 uint8_t fde_win_save;
1620 uint8_t fde_ret_save[3];
cb1977d3
RH
1621} DebugFrame;
1622
1623static DebugFrame debug_frame = {
1624 .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
1625 .cie.id = -1,
1626 .cie.version = 1,
1627 .cie.code_align = 1,
1628 .cie.data_align = -sizeof(void *) & 0x7f,
1629 .cie.return_column = 15, /* o7 */
1630
497a22eb
RH
1631 /* Total FDE size does not include the "len" member. */
1632 .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
1633
1634 .fde_def_cfa = {
cb1977d3
RH
1635#if TCG_TARGET_REG_BITS == 64
1636 12, 30, /* DW_CFA_def_cfa i6, 2047 */
1637 (2047 & 0x7f) | 0x80, (2047 >> 7)
1638#else
1639 13, 30 /* DW_CFA_def_cfa_register i6 */
1640#endif
1641 },
497a22eb
RH
1642 .fde_win_save = 0x2d, /* DW_CFA_GNU_window_save */
1643 .fde_ret_save = { 9, 15, 31 }, /* DW_CFA_register o7, i7 */
cb1977d3
RH
1644};
1645
1646void tcg_register_jit(void *buf, size_t buf_size)
1647{
c8fc56ce 1648 debug_frame.fde.func_start = (uintptr_t)buf;
cb1977d3
RH
1649 debug_frame.fde.func_len = buf_size;
1650
1651 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
1652}
5bbd2cae
RH
1653
1654void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
1655{
1656 uint32_t *ptr = (uint32_t *)jmp_addr;
c8fc56ce 1657 uintptr_t disp = addr - jmp_addr;
5bbd2cae
RH
1658
1659 /* We can reach the entire address space for 32-bit. For 64-bit
1660 the code_gen_buffer can't be larger than 2GB. */
c8fc56ce 1661 assert(disp == (int32_t)disp);
5bbd2cae 1662
c8fc56ce 1663 *ptr = CALL | (uint32_t)disp >> 2;
5bbd2cae
RH
1664 flush_icache_range(jmp_addr, jmp_addr + 4);
1665}