]> Git Repo - qemu.git/blob - tcg/sparc/tcg-target.c
Fix qemu_ld/st branches, constification, use orcc for tst synthetic op
[qemu.git] / tcg / sparc / tcg-target.c
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
25 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
26     "%g0",
27     "%g1",
28     "%g2",
29     "%g3",
30     "%g4",
31     "%g5",
32     "%g6",
33     "%g7",
34     "%o0",
35     "%o1",
36     "%o2",
37     "%o3",
38     "%o4",
39     "%o5",
40     "%o6",
41     "%o7",
42     "%l0",
43     "%l1",
44     "%l2",
45     "%l3",
46     "%l4",
47     "%l5",
48     "%l6",
49     "%l7",
50     "%i0",
51     "%i1",
52     "%i2",
53     "%i3",
54     "%i4",
55     "%i5",
56     "%i6",
57     "%i7",
58 };
59
60 static const int tcg_target_reg_alloc_order[] = {
61     TCG_REG_L0,
62     TCG_REG_L1,
63     TCG_REG_L2,
64     TCG_REG_L3,
65     TCG_REG_L4,
66     TCG_REG_L5,
67     TCG_REG_L6,
68     TCG_REG_L7,
69     TCG_REG_I0,
70     TCG_REG_I1,
71     TCG_REG_I2,
72     TCG_REG_I3,
73     TCG_REG_I4,
74 };
75
76 static const int tcg_target_call_iarg_regs[6] = {
77     TCG_REG_O0,
78     TCG_REG_O1,
79     TCG_REG_O2,
80     TCG_REG_O3,
81     TCG_REG_O4,
82     TCG_REG_O5,
83 };
84
85 static const int tcg_target_call_oarg_regs[2] = {
86     TCG_REG_O0,
87     TCG_REG_O1,
88 };
89
90 static inline int check_fit(tcg_target_long val, unsigned int bits)
91 {
92     return ((val << ((sizeof(tcg_target_long) * 8 - bits))
93              >> (sizeof(tcg_target_long) * 8 - bits)) == val);
94 }
95
96 static void patch_reloc(uint8_t *code_ptr, int type,
97                         tcg_target_long value, tcg_target_long addend)
98 {
99     value += addend;
100     switch (type) {
101     case R_SPARC_32:
102         if (value != (uint32_t)value)
103             tcg_abort();
104         *(uint32_t *)code_ptr = value;
105         break;
106     case R_SPARC_WDISP22:
107         value -= (long)code_ptr;
108         value >>= 2;
109         if (!check_fit(value, 22))
110             tcg_abort();
111         *(uint32_t *)code_ptr = ((*(uint32_t *)code_ptr) & ~0x3fffff) | value;
112         break;
113     default:
114         tcg_abort();
115     }
116 }
117
118 /* maximum number of register used for input function arguments */
119 static inline int tcg_target_get_call_iarg_regs_count(int flags)
120 {
121     return 6;
122 }
123
124 /* parse target specific constraints */
125 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
126 {
127     const char *ct_str;
128
129     ct_str = *pct_str;
130     switch (ct_str[0]) {
131     case 'r':
132     case 'L': /* qemu_ld/st constraint */
133         ct->ct |= TCG_CT_REG;
134         tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
135         tcg_regset_reset_reg(ct->u.regs, TCG_REG_I0);
136         tcg_regset_reset_reg(ct->u.regs, TCG_REG_I1);
137         break;
138     case 'I':
139         ct->ct |= TCG_CT_CONST_S11;
140         break;
141     case 'J':
142         ct->ct |= TCG_CT_CONST_S13;
143         break;
144     default:
145         return -1;
146     }
147     ct_str++;
148     *pct_str = ct_str;
149     return 0;
150 }
151
152 /* test if a constant matches the constraint */
153 static inline int tcg_target_const_match(tcg_target_long val,
154                                          const TCGArgConstraint *arg_ct)
155 {
156     int ct;
157
158     ct = arg_ct->ct;
159     if (ct & TCG_CT_CONST)
160         return 1;
161     else if ((ct & TCG_CT_CONST_S11) && check_fit(val, 11))
162         return 1;
163     else if ((ct & TCG_CT_CONST_S13) && check_fit(val, 13))
164         return 1;
165     else
166         return 0;
167 }
168
169 #define INSN_OP(x)  ((x) << 30)
170 #define INSN_OP2(x) ((x) << 22)
171 #define INSN_OP3(x) ((x) << 19)
172 #define INSN_OPF(x) ((x) << 5)
173 #define INSN_RD(x)  ((x) << 25)
174 #define INSN_RS1(x) ((x) << 14)
175 #define INSN_RS2(x) (x)
176
177 #define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff))
178 #define INSN_OFF22(x) (((x) >> 2) & 0x3fffff)
179
180 #define INSN_COND(x, a) (((x) << 25) | ((a) << 29))
181 #define COND_N     0x0
182 #define COND_E     0x1
183 #define COND_LE    0x2
184 #define COND_L     0x3
185 #define COND_LEU   0x4
186 #define COND_CS    0x5
187 #define COND_NEG   0x6
188 #define COND_VS    0x7
189 #define COND_A     0x8
190 #define COND_NE    0x9
191 #define COND_G     0xa
192 #define COND_GE    0xb
193 #define COND_GU    0xc
194 #define COND_CC    0xd
195 #define COND_POS   0xe
196 #define COND_VC    0xf
197 #define BA         (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2))
198
199 #define ARITH_ADD  (INSN_OP(2) | INSN_OP3(0x00))
200 #define ARITH_AND  (INSN_OP(2) | INSN_OP3(0x01))
201 #define ARITH_OR   (INSN_OP(2) | INSN_OP3(0x02))
202 #define ARITH_ORCC (INSN_OP(2) | INSN_OP3(0x12))
203 #define ARITH_XOR  (INSN_OP(2) | INSN_OP3(0x03))
204 #define ARITH_SUB  (INSN_OP(2) | INSN_OP3(0x04))
205 #define ARITH_SUBCC (INSN_OP(2) | INSN_OP3(0x14))
206 #define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x10))
207 #define ARITH_SUBX (INSN_OP(2) | INSN_OP3(0x0c))
208 #define ARITH_UMUL (INSN_OP(2) | INSN_OP3(0x0a))
209 #define ARITH_UDIV (INSN_OP(2) | INSN_OP3(0x0e))
210 #define ARITH_SDIV (INSN_OP(2) | INSN_OP3(0x0f))
211 #define ARITH_MULX (INSN_OP(2) | INSN_OP3(0x09))
212 #define ARITH_UDIVX (INSN_OP(2) | INSN_OP3(0x0d))
213 #define ARITH_SDIVX (INSN_OP(2) | INSN_OP3(0x2d))
214
215 #define SHIFT_SLL  (INSN_OP(2) | INSN_OP3(0x25))
216 #define SHIFT_SRL  (INSN_OP(2) | INSN_OP3(0x26))
217 #define SHIFT_SRA  (INSN_OP(2) | INSN_OP3(0x27))
218
219 #define SHIFT_SLLX (INSN_OP(2) | INSN_OP3(0x25) | (1 << 12))
220 #define SHIFT_SRLX (INSN_OP(2) | INSN_OP3(0x26) | (1 << 12))
221 #define SHIFT_SRAX (INSN_OP(2) | INSN_OP3(0x27) | (1 << 12))
222
223 #define WRY        (INSN_OP(2) | INSN_OP3(0x30))
224 #define JMPL       (INSN_OP(2) | INSN_OP3(0x38))
225 #define SAVE       (INSN_OP(2) | INSN_OP3(0x3c))
226 #define RESTORE    (INSN_OP(2) | INSN_OP3(0x3d))
227 #define SETHI      (INSN_OP(0) | INSN_OP2(0x4))
228 #define CALL       INSN_OP(1)
229 #define LDUB       (INSN_OP(3) | INSN_OP3(0x01))
230 #define LDSB       (INSN_OP(3) | INSN_OP3(0x09))
231 #define LDUH       (INSN_OP(3) | INSN_OP3(0x02))
232 #define LDSH       (INSN_OP(3) | INSN_OP3(0x0a))
233 #define LDUW       (INSN_OP(3) | INSN_OP3(0x00))
234 #define LDSW       (INSN_OP(3) | INSN_OP3(0x08))
235 #define LDX        (INSN_OP(3) | INSN_OP3(0x0b))
236 #define STB        (INSN_OP(3) | INSN_OP3(0x05))
237 #define STH        (INSN_OP(3) | INSN_OP3(0x06))
238 #define STW        (INSN_OP(3) | INSN_OP3(0x04))
239 #define STX        (INSN_OP(3) | INSN_OP3(0x0e))
240
241 static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
242 {
243     tcg_out32(s, ARITH_OR | INSN_RD(ret) | INSN_RS1(arg) |
244               INSN_RS2(TCG_REG_G0));
245 }
246
247 static inline void tcg_out_movi(TCGContext *s, TCGType type,
248                                 int ret, tcg_target_long arg)
249 {
250 #if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
251     if (!check_fit(arg, 32))
252         fprintf(stderr, "unimplemented %s with constant %ld\n", __func__, arg);
253 #endif
254     if (check_fit(arg, 13))
255         tcg_out32(s, ARITH_OR | INSN_RD(ret) | INSN_RS1(TCG_REG_G0) |
256                   INSN_IMM13(arg));
257     else {
258         tcg_out32(s, SETHI | INSN_RD(ret) | ((arg & 0xfffffc00) >> 10));
259         if (arg & 0x3ff)
260             tcg_out32(s, ARITH_OR | INSN_RD(ret) | INSN_RS1(ret) |
261                       INSN_IMM13(arg & 0x3ff));
262     }
263 }
264
265 static inline void tcg_out_ld_raw(TCGContext *s, int ret,
266                                   tcg_target_long arg)
267 {
268     tcg_out32(s, SETHI | INSN_RD(ret) | (((uint32_t)arg & 0xfffffc00) >> 10));
269     tcg_out32(s, LDUW | INSN_RD(ret) | INSN_RS1(ret) |
270               INSN_IMM13(arg & 0x3ff));
271 }
272
273 static inline void tcg_out_ld_ptr(TCGContext *s, int ret,
274                                   tcg_target_long arg)
275 {
276 #if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
277     if (!check_fit(arg, 32))
278         fprintf(stderr, "unimplemented %s with offset %ld\n", __func__, arg);
279     if (!check_fit(arg, 13))
280         tcg_out32(s, SETHI | INSN_RD(ret) | (((uint32_t)arg & 0xfffffc00) >> 10));
281     tcg_out32(s, LDX | INSN_RD(ret) | INSN_RS1(ret) |
282               INSN_IMM13(arg & 0x3ff));
283 #else
284     tcg_out_ld_raw(s, ret, arg);
285 #endif
286 }
287
288 static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset, int op)
289 {
290     if (check_fit(offset, 13))
291         tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) |
292                   INSN_IMM13(offset));
293     else {
294         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, offset);
295         tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(TCG_REG_I5) |
296                   INSN_RS2(addr));
297     }
298 }
299
300 static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
301                               int arg1, tcg_target_long arg2)
302 {
303     if (type == TCG_TYPE_I32)
304         tcg_out_ldst(s, ret, arg1, arg2, LDUW);
305     else
306         tcg_out_ldst(s, ret, arg1, arg2, LDX);
307 }
308
309 static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
310                               int arg1, tcg_target_long arg2)
311 {
312     if (type == TCG_TYPE_I32)
313         tcg_out_ldst(s, arg, arg1, arg2, STW);
314     else
315         tcg_out_ldst(s, arg, arg1, arg2, STX);
316 }
317
318 static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2,
319                                  int op)
320 {
321     tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) |
322               INSN_RS2(rs2));
323 }
324
325 static inline void tcg_out_arithi(TCGContext *s, int rd, int rs1, int offset,
326                                   int op)
327 {
328     tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) |
329               INSN_IMM13(offset));
330 }
331
332 static inline void tcg_out_sety(TCGContext *s, tcg_target_long val)
333 {
334     if (val == 0 || val == -1)
335         tcg_out32(s, WRY | INSN_IMM13(val));
336     else
337         fprintf(stderr, "unimplemented sety %ld\n", (long)val);
338 }
339
340 static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
341 {
342     if (val != 0) {
343         if (check_fit(val, 13))
344             tcg_out_arithi(s, reg, reg, val, ARITH_ADD);
345         else {
346             tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, val);
347             tcg_out_arith(s, reg, reg, TCG_REG_I5, ARITH_ADD);
348         }
349     }
350 }
351
352 static inline void tcg_out_nop(TCGContext *s)
353 {
354     tcg_out32(s, SETHI | INSN_RD(TCG_REG_G0) | 0);
355 }
356
357 static void tcg_out_branch(TCGContext *s, int opc, int label_index)
358 {
359     int32_t val;
360     TCGLabel *l = &s->labels[label_index];
361
362     if (l->has_value) {
363         val = l->u.value - (tcg_target_long)s->code_ptr;
364         tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2)
365                       | INSN_OFF22(l->u.value - (unsigned long)s->code_ptr)));
366     } else {
367         tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP22, label_index, 0);
368         tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) | 0));
369     }
370 }
371
372 static const uint8_t tcg_cond_to_bcond[10] = {
373     [TCG_COND_EQ] = COND_E,
374     [TCG_COND_NE] = COND_NE,
375     [TCG_COND_LT] = COND_L,
376     [TCG_COND_GE] = COND_GE,
377     [TCG_COND_LE] = COND_LE,
378     [TCG_COND_GT] = COND_G,
379     [TCG_COND_LTU] = COND_CS,
380     [TCG_COND_GEU] = COND_CC,
381     [TCG_COND_LEU] = COND_LEU,
382     [TCG_COND_GTU] = COND_GU,
383 };
384
385 static void tcg_out_brcond(TCGContext *s, int cond,
386                            TCGArg arg1, TCGArg arg2, int const_arg2,
387                            int label_index)
388 {
389     if (const_arg2 && arg2 == 0)
390         /* orcc r, r, %g0 */
391         tcg_out_arith(s, TCG_REG_G0, TCG_REG_G0, arg1, ARITH_ORCC);
392     else
393         /* subcc r1, r2, %g0 */
394         tcg_out_arith(s, TCG_REG_G0, arg1, arg2, ARITH_SUBCC);
395     tcg_out_branch(s, tcg_cond_to_bcond[cond], label_index);
396     tcg_out_nop(s);
397 }
398
399 /* Generate global QEMU prologue and epilogue code */
400 void tcg_target_qemu_prologue(TCGContext *s)
401 {
402     tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) |
403               INSN_IMM13(-TCG_TARGET_STACK_MINFRAME));
404     tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I0) |
405               INSN_RS2(TCG_REG_G0));
406     tcg_out_nop(s);
407 }
408
409 #if defined(CONFIG_SOFTMMU)
410 extern void __ldb_mmu(void);
411 extern void __ldw_mmu(void);
412 extern void __ldl_mmu(void);
413 extern void __ldq_mmu(void);
414
415 extern void __stb_mmu(void);
416 extern void __stw_mmu(void);
417 extern void __stl_mmu(void);
418 extern void __stq_mmu(void);
419
420
421 static const void * const qemu_ld_helpers[4] = {
422     __ldb_mmu,
423     __ldw_mmu,
424     __ldl_mmu,
425     __ldq_mmu,
426 };
427
428 static const void * const qemu_st_helpers[4] = {
429     __stb_mmu,
430     __stw_mmu,
431     __stl_mmu,
432     __stq_mmu,
433 };
434 #endif
435
436 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
437                             int opc)
438 {
439     int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, ld_op;
440 #if defined(CONFIG_SOFTMMU)
441     uint8_t *label1_ptr, *label2_ptr;
442 #endif
443
444     data_reg = *args++;
445     addr_reg = *args++;
446     mem_index = *args;
447     s_bits = opc & 3;
448
449     r0 = TCG_REG_I0;
450     r1 = TCG_REG_I1;
451
452 #if TARGET_LONG_BITS == 32
453     ld_op = LDUW;
454 #else
455     ld_op = LDX;
456 #endif
457
458 #if defined(CONFIG_SOFTMMU)
459     /* srl addr_reg, x, r1 */
460     tcg_out_arithi(s, r1, addr_reg, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS,
461                    SHIFT_SRL);
462     /* and addr_reg, x, r0 */
463     tcg_out_arithi(s, r0, addr_reg, TARGET_PAGE_MASK | ((1 << s_bits) - 1),
464                    ARITH_AND);
465
466     /* and r1, x, r1 */
467     tcg_out_arithi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS,
468                    ARITH_AND);
469
470     /* add r1, x, r1 */
471     tcg_out_arithi(s, r1, r1, offsetof(CPUState, tlb_table[mem_index][0].addr_read),
472                    ARITH_ADD);
473
474     /* ld [env + r1], r1 */
475     tcg_out_ldst(s, r1, TCG_AREG0, r1, ld_op);
476
477     /* subcc r0, r1, %g0 */
478     tcg_out_arith(s, TCG_REG_G0, r0, r1, ARITH_SUBCC);
479
480     /* will become:
481        be label1 */
482     label1_ptr = s->code_ptr;
483     tcg_out32(s, 0);
484
485     /* mov (delay slot)*/
486     tcg_out_mov(s, r0, addr_reg);
487
488     /* XXX: move that code at the end of the TB */
489     tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_ld_helpers[s_bits]
490                            - (tcg_target_ulong)s->code_ptr) >> 2)
491                          & 0x3fffffff));
492     /* mov (delay slot)*/
493     tcg_out_movi(s, TCG_TYPE_I32, r1, mem_index);
494
495     switch(opc) {
496     case 0 | 4:
497         /* sll i0, 24/56, i0 */
498         tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0,
499                        sizeof(tcg_target_long) * 8 - 8, SHIFT_SLL);
500         /* sra i0, 24/56, data_reg */
501         tcg_out_arithi(s, data_reg, TCG_REG_I0,
502                        sizeof(tcg_target_long) * 8 - 8, SHIFT_SRA);
503         break;
504     case 1 | 4:
505         /* sll i0, 16/48, i0 */
506         tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0,
507                        sizeof(tcg_target_long) * 8 - 16, SHIFT_SLL);
508         /* sra i0, 16/48, data_reg */
509         tcg_out_arithi(s, data_reg, TCG_REG_I0,
510                        sizeof(tcg_target_long) * 8 - 16, SHIFT_SRA);
511         break;
512     case 2 | 4:
513         /* sll i0, 32, i0 */
514         tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0, 32, SHIFT_SLL);
515         /* sra i0, 32, data_reg */
516         tcg_out_arithi(s, data_reg, TCG_REG_I0, 32, SHIFT_SRA);
517         break;
518     case 0:
519     case 1:
520     case 2:
521     case 3:
522     default:
523         /* mov */
524         tcg_out_mov(s, data_reg, TCG_REG_I0);
525         break;
526     }
527
528     /* will become:
529        ba label2 */
530     label2_ptr = s->code_ptr;
531     tcg_out32(s, 0);
532
533     /* label1: */
534     *label1_ptr = (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2) |
535                    INSN_OFF22((unsigned long)label1_ptr -
536                               (unsigned long)s->code_ptr));
537
538     /* ld [r1 + x], r1 */
539     tcg_out_ldst(s, r1, r1, offsetof(CPUTLBEntry, addend) -
540                  offsetof(CPUTLBEntry, addr_read), ld_op);
541     /* add x(r1), r0 */
542     tcg_out_arith(s, r0, r1, r0, ARITH_ADD);
543 #else
544     r0 = addr_reg;
545 #endif
546
547 #ifdef TARGET_WORDS_BIGENDIAN
548     bswap = 0;
549 #else
550     bswap = 1;
551 #endif
552     switch(opc) {
553     case 0:
554         /* ldub [r0], data_reg */
555         tcg_out_ldst(s, data_reg, r0, 0, LDUB);
556         break;
557     case 0 | 4:
558         /* ldsb [r0], data_reg */
559         tcg_out_ldst(s, data_reg, r0, 0, LDSB);
560         break;
561     case 1:
562         /* lduh [r0], data_reg */
563         tcg_out_ldst(s, data_reg, r0, 0, LDUH);
564         if (bswap) {
565             fprintf(stderr, "unimplemented %s with bswap\n", __func__);
566         }
567         break;
568     case 1 | 4:
569         /* ldsh [r0], data_reg */
570         tcg_out_ldst(s, data_reg, r0, 0, LDSH);
571         if (bswap) {
572             fprintf(stderr, "unimplemented %s with bswap\n", __func__);
573         }
574         break;
575     case 2:
576         /* lduw [r0], data_reg */
577         tcg_out_ldst(s, data_reg, r0, 0, LDUW);
578         if (bswap) {
579             fprintf(stderr, "unimplemented %s with bswap\n", __func__);
580         }
581         break;
582     case 2 | 4:
583         /* ldsw [r0], data_reg */
584         tcg_out_ldst(s, data_reg, r0, 0, LDSW);
585         if (bswap) {
586             fprintf(stderr, "unimplemented %s with bswap\n", __func__);
587         }
588         break;
589     case 3:
590         /* ldx [r0], data_reg */
591         tcg_out_ldst(s, data_reg, r0, 0, LDX);
592         if (bswap) {
593             fprintf(stderr, "unimplemented %s with bswap\n", __func__);
594         }
595         break;
596     default:
597         tcg_abort();
598     }
599
600 #if defined(CONFIG_SOFTMMU)
601     /* label2: */
602     *label2_ptr = (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2) |
603                    INSN_OFF22((unsigned long)label2_ptr -
604                               (unsigned long)s->code_ptr));
605 #endif
606 }
607
608 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
609                             int opc)
610 {
611     int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, ld_op;
612 #if defined(CONFIG_SOFTMMU)
613     uint8_t *label1_ptr, *label2_ptr;
614 #endif
615
616     data_reg = *args++;
617     addr_reg = *args++;
618     mem_index = *args;
619
620     s_bits = opc;
621
622     r0 = TCG_REG_I5;
623     r1 = TCG_REG_I4;
624
625 #if TARGET_LONG_BITS == 32
626     ld_op = LDUW;
627 #else
628     ld_op = LDX;
629 #endif
630
631 #if defined(CONFIG_SOFTMMU)
632     /* srl addr_reg, x, r1 */
633     tcg_out_arithi(s, r1, addr_reg, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS,
634                    SHIFT_SRL);
635     /* and addr_reg, x, r0 */
636     tcg_out_arithi(s, r0, addr_reg, TARGET_PAGE_MASK | ((1 << s_bits) - 1),
637                    ARITH_AND);
638
639     /* and r1, x, r1 */
640     tcg_out_arithi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS,
641                    ARITH_AND);
642
643     /* add r1, x, r1 */
644     tcg_out_arithi(s, r1, r1,
645                    offsetof(CPUState, tlb_table[mem_index][0].addr_write),
646                    ARITH_ADD);
647
648     /* ld [env + r1], r1 */
649     tcg_out_ldst(s, r1, TCG_AREG0, r1, ld_op);
650
651     /* subcc r0, r1, %g0 */
652     tcg_out_arith(s, TCG_REG_G0, r0, r1, ARITH_SUBCC);
653
654     /* will become:
655        be label1 */
656     label1_ptr = s->code_ptr;
657     tcg_out32(s, 0);
658     /* mov (delay slot)*/
659     tcg_out_mov(s, r0, addr_reg);
660
661     switch(opc) {
662     case 0 | 4:
663         /* sll i0, 24/56, i0 */
664         tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0,
665                        sizeof(tcg_target_long) * 8 - 8, SHIFT_SLL);
666         /* sra i0, 24/56, data_reg */
667         tcg_out_arithi(s, data_reg, TCG_REG_I0,
668                        sizeof(tcg_target_long) * 8 - 8, SHIFT_SRA);
669         break;
670     case 1 | 4:
671         /* sll i0, 16/48, i0 */
672         tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0,
673                        sizeof(tcg_target_long) * 8 - 16, SHIFT_SLL);
674         /* sra i0, 16/48, data_reg */
675         tcg_out_arithi(s, data_reg, TCG_REG_I0,
676                        sizeof(tcg_target_long) * 8 - 16, SHIFT_SRA);
677         break;
678     case 2 | 4:
679         /* sll i0, 32, i0 */
680         tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0, 32, SHIFT_SLL);
681         /* sra i0, 32, data_reg */
682         tcg_out_arithi(s, data_reg, TCG_REG_I0, 32, SHIFT_SRA);
683         break;
684     case 0:
685     case 1:
686     case 2:
687     case 3:
688     default:
689         /* mov */
690         tcg_out_mov(s, data_reg, TCG_REG_I0);
691         break;
692     }
693
694     tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_st_helpers[s_bits]
695                            - (tcg_target_ulong)s->code_ptr) >> 2)
696                          & 0x3fffffff));
697     /* mov (delay slot)*/
698     tcg_out_movi(s, TCG_TYPE_I32, r1, mem_index);
699
700     /* will become:
701        ba label2 */
702     label2_ptr = s->code_ptr;
703     tcg_out32(s, 0);
704
705     /* label1: */
706     *label1_ptr = (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2) |
707                    INSN_OFF22((unsigned long)label1_ptr -
708                               (unsigned long)s->code_ptr));
709
710     /* ld [r1 + x], r1 */
711     tcg_out_ldst(s, r1, r1, offsetof(CPUTLBEntry, addend) -
712                  offsetof(CPUTLBEntry, addr_write), ld_op);
713     /* add x(r1), r0 */
714     tcg_out_arith(s, r0, r1, r0, ARITH_ADD);
715 #else
716     r0 = addr_reg;
717 #endif
718
719 #ifdef TARGET_WORDS_BIGENDIAN
720     bswap = 0;
721 #else
722     bswap = 1;
723 #endif
724     switch(opc) {
725     case 0:
726         /* stb data_reg, [r0] */
727         tcg_out_ldst(s, data_reg, r0, 0, STB);
728         break;
729     case 1:
730         if (bswap) {
731             fprintf(stderr, "unimplemented %s with bswap\n", __func__);
732         }
733         /* sth data_reg, [r0] */
734         tcg_out_ldst(s, data_reg, r0, 0, STH);
735         break;
736     case 2:
737         if (bswap) {
738             fprintf(stderr, "unimplemented %s with bswap\n", __func__);
739         }
740         /* stw data_reg, [r0] */
741         tcg_out_ldst(s, data_reg, r0, 0, STW);
742         break;
743     case 3:
744         if (bswap) {
745             fprintf(stderr, "unimplemented %s with bswap\n", __func__);
746         }
747         /* stx data_reg, [r0] */
748         tcg_out_ldst(s, data_reg, r0, 0, STX);
749         break;
750     default:
751         tcg_abort();
752     }
753
754 #if defined(CONFIG_SOFTMMU)
755     /* label2: */
756     *label2_ptr = (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2) |
757                    INSN_OFF22((unsigned long)label2_ptr -
758                               (unsigned long)s->code_ptr));
759 #endif
760 }
761
762 static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
763                               const int *const_args)
764 {
765     int c;
766
767     switch (opc) {
768     case INDEX_op_exit_tb:
769         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I0, args[0]);
770         tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I7) |
771                   INSN_IMM13(8));
772         tcg_out32(s, RESTORE | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_G0) |
773                       INSN_RS2(TCG_REG_G0));
774         break;
775     case INDEX_op_goto_tb:
776         if (s->tb_jmp_offset) {
777             /* direct jump method */
778             tcg_out32(s, SETHI | INSN_RD(TCG_REG_I5) |
779                       ((args[0] & 0xffffe000) >> 10));
780             tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I5) |
781                       INSN_IMM13((args[0] & 0x1fff)));
782             s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
783         } else {
784             /* indirect jump method */
785             tcg_out_ld_ptr(s, TCG_REG_I5, (tcg_target_long)(s->tb_next + args[0]));
786             tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I5) |
787                       INSN_RS2(TCG_REG_G0));
788         }
789         tcg_out_nop(s);
790         s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
791         break;
792     case INDEX_op_call:
793         if (const_args[0]) {
794             tcg_out32(s, CALL | ((((tcg_target_ulong)args[0]
795                                   - (tcg_target_ulong)s->code_ptr) >> 2)
796                                  & 0x3fffffff));
797             tcg_out_nop(s);
798         } else {
799             tcg_out_ld_ptr(s, TCG_REG_I5, (tcg_target_long)(s->tb_next + args[0]));
800             tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_I5) |
801                       INSN_RS2(TCG_REG_G0));
802             tcg_out_nop(s);
803         }
804         break;
805     case INDEX_op_jmp:
806     case INDEX_op_br:
807         tcg_out_branch(s, COND_A, args[0]);
808         tcg_out_nop(s);
809         break;
810     case INDEX_op_movi_i32:
811         tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]);
812         break;
813
814 #if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
815 #define OP_32_64(x)                             \
816         glue(glue(case INDEX_op_, x), _i32:)    \
817         glue(glue(case INDEX_op_, x), _i64:)
818 #else
819 #define OP_32_64(x)                             \
820         glue(glue(case INDEX_op_, x), _i32:)
821 #endif
822         OP_32_64(ld8u);
823         tcg_out_ldst(s, args[0], args[1], args[2], LDUB);
824         break;
825         OP_32_64(ld8s);
826         tcg_out_ldst(s, args[0], args[1], args[2], LDSB);
827         break;
828         OP_32_64(ld16u);
829         tcg_out_ldst(s, args[0], args[1], args[2], LDUH);
830         break;
831         OP_32_64(ld16s);
832         tcg_out_ldst(s, args[0], args[1], args[2], LDSH);
833         break;
834     case INDEX_op_ld_i32:
835 #if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
836     case INDEX_op_ld32u_i64:
837 #endif
838         tcg_out_ldst(s, args[0], args[1], args[2], LDUW);
839         break;
840         OP_32_64(st8);
841         tcg_out_ldst(s, args[0], args[1], args[2], STB);
842         break;
843         OP_32_64(st16);
844         tcg_out_ldst(s, args[0], args[1], args[2], STH);
845         break;
846     case INDEX_op_st_i32:
847 #if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
848     case INDEX_op_st32_i64:
849 #endif
850         tcg_out_ldst(s, args[0], args[1], args[2], STW);
851         break;
852         OP_32_64(add);
853         c = ARITH_ADD;
854         goto gen_arith32;
855         OP_32_64(sub);
856         c = ARITH_SUB;
857         goto gen_arith32;
858         OP_32_64(and);
859         c = ARITH_AND;
860         goto gen_arith32;
861         OP_32_64(or);
862         c = ARITH_OR;
863         goto gen_arith32;
864         OP_32_64(xor);
865         c = ARITH_XOR;
866         goto gen_arith32;
867     case INDEX_op_shl_i32:
868         c = SHIFT_SLL;
869         goto gen_arith32;
870     case INDEX_op_shr_i32:
871         c = SHIFT_SRL;
872         goto gen_arith32;
873     case INDEX_op_sar_i32:
874         c = SHIFT_SRA;
875         goto gen_arith32;
876     case INDEX_op_mul_i32:
877         c = ARITH_UMUL;
878         goto gen_arith32;
879     case INDEX_op_div2_i32:
880 #if defined(__sparc_v9__) || defined(__sparc_v8plus__)
881         c = ARITH_SDIVX;
882         goto gen_arith32;
883 #else
884         tcg_out_sety(s, 0);
885         c = ARITH_SDIV;
886         goto gen_arith32;
887 #endif
888     case INDEX_op_divu2_i32:
889 #if defined(__sparc_v9__) || defined(__sparc_v8plus__)
890         c = ARITH_UDIVX;
891         goto gen_arith32;
892 #else
893         tcg_out_sety(s, 0);
894         c = ARITH_UDIV;
895         goto gen_arith32;
896 #endif
897
898     case INDEX_op_brcond_i32:
899         tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
900                        args[3]);
901         break;
902
903     case INDEX_op_qemu_ld8u:
904         tcg_out_qemu_ld(s, args, 0);
905         break;
906     case INDEX_op_qemu_ld8s:
907         tcg_out_qemu_ld(s, args, 0 | 4);
908         break;
909     case INDEX_op_qemu_ld16u:
910         tcg_out_qemu_ld(s, args, 1);
911         break;
912     case INDEX_op_qemu_ld16s:
913         tcg_out_qemu_ld(s, args, 1 | 4);
914         break;
915     case INDEX_op_qemu_ld32u:
916         tcg_out_qemu_ld(s, args, 2);
917         break;
918     case INDEX_op_qemu_ld32s:
919         tcg_out_qemu_ld(s, args, 2 | 4);
920         break;
921     case INDEX_op_qemu_st8:
922         tcg_out_qemu_st(s, args, 0);
923         break;
924     case INDEX_op_qemu_st16:
925         tcg_out_qemu_st(s, args, 1);
926         break;
927     case INDEX_op_qemu_st32:
928         tcg_out_qemu_st(s, args, 2);
929         break;
930
931 #if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
932     case INDEX_op_movi_i64:
933         tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
934         break;
935     case INDEX_op_ld32s_i64:
936         tcg_out_ldst(s, args[0], args[1], args[2], LDSW);
937         break;
938     case INDEX_op_ld_i64:
939         tcg_out_ldst(s, args[0], args[1], args[2], LDX);
940         break;
941     case INDEX_op_st_i64:
942         tcg_out_ldst(s, args[0], args[1], args[2], STX);
943         break;
944     case INDEX_op_shl_i64:
945         c = SHIFT_SLLX;
946         goto gen_arith32;
947     case INDEX_op_shr_i64:
948         c = SHIFT_SRLX;
949         goto gen_arith32;
950     case INDEX_op_sar_i64:
951         c = SHIFT_SRAX;
952         goto gen_arith32;
953     case INDEX_op_mul_i64:
954         c = ARITH_MULX;
955         goto gen_arith32;
956     case INDEX_op_div2_i64:
957         c = ARITH_SDIVX;
958         goto gen_arith32;
959     case INDEX_op_divu2_i64:
960         c = ARITH_UDIVX;
961         goto gen_arith32;
962
963     case INDEX_op_brcond_i64:
964         tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
965                        args[3]);
966         break;
967     case INDEX_op_qemu_ld64:
968         tcg_out_qemu_ld(s, args, 3);
969         break;
970     case INDEX_op_qemu_st64:
971         tcg_out_qemu_st(s, args, 3);
972         break;
973
974 #endif
975     gen_arith32:
976         if (const_args[2]) {
977             tcg_out_arithi(s, args[0], args[1], args[2], c);
978         } else {
979             tcg_out_arith(s, args[0], args[1], args[2], c);
980         }
981         break;
982
983     default:
984         fprintf(stderr, "unknown opcode 0x%x\n", opc);
985         tcg_abort();
986     }
987 }
988
989 static const TCGTargetOpDef sparc_op_defs[] = {
990     { INDEX_op_exit_tb, { } },
991     { INDEX_op_goto_tb, { } },
992     { INDEX_op_call, { "ri" } },
993     { INDEX_op_jmp, { "ri" } },
994     { INDEX_op_br, { } },
995
996     { INDEX_op_mov_i32, { "r", "r" } },
997     { INDEX_op_movi_i32, { "r" } },
998     { INDEX_op_ld8u_i32, { "r", "r" } },
999     { INDEX_op_ld8s_i32, { "r", "r" } },
1000     { INDEX_op_ld16u_i32, { "r", "r" } },
1001     { INDEX_op_ld16s_i32, { "r", "r" } },
1002     { INDEX_op_ld_i32, { "r", "r" } },
1003     { INDEX_op_st8_i32, { "r", "r" } },
1004     { INDEX_op_st16_i32, { "r", "r" } },
1005     { INDEX_op_st_i32, { "r", "r" } },
1006
1007     { INDEX_op_add_i32, { "r", "r", "rJ" } },
1008     { INDEX_op_mul_i32, { "r", "r", "rJ" } },
1009     { INDEX_op_div2_i32, { "r", "r", "0", "1", "r" } },
1010     { INDEX_op_divu2_i32, { "r", "r", "0", "1", "r" } },
1011     { INDEX_op_sub_i32, { "r", "r", "rJ" } },
1012     { INDEX_op_and_i32, { "r", "r", "rJ" } },
1013     { INDEX_op_or_i32, { "r", "r", "rJ" } },
1014     { INDEX_op_xor_i32, { "r", "r", "rJ" } },
1015
1016     { INDEX_op_shl_i32, { "r", "r", "rJ" } },
1017     { INDEX_op_shr_i32, { "r", "r", "rJ" } },
1018     { INDEX_op_sar_i32, { "r", "r", "rJ" } },
1019
1020     { INDEX_op_brcond_i32, { "r", "ri" } },
1021
1022     { INDEX_op_qemu_ld8u, { "r", "L" } },
1023     { INDEX_op_qemu_ld8s, { "r", "L" } },
1024     { INDEX_op_qemu_ld16u, { "r", "L" } },
1025     { INDEX_op_qemu_ld16s, { "r", "L" } },
1026     { INDEX_op_qemu_ld32u, { "r", "L" } },
1027     { INDEX_op_qemu_ld32s, { "r", "L" } },
1028
1029     { INDEX_op_qemu_st8, { "L", "L" } },
1030     { INDEX_op_qemu_st16, { "L", "L" } },
1031     { INDEX_op_qemu_st32, { "L", "L" } },
1032
1033 #if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
1034     { INDEX_op_mov_i64, { "r", "r" } },
1035     { INDEX_op_movi_i64, { "r" } },
1036     { INDEX_op_ld8u_i64, { "r", "r" } },
1037     { INDEX_op_ld8s_i64, { "r", "r" } },
1038     { INDEX_op_ld16u_i64, { "r", "r" } },
1039     { INDEX_op_ld16s_i64, { "r", "r" } },
1040     { INDEX_op_ld32u_i64, { "r", "r" } },
1041     { INDEX_op_ld32s_i64, { "r", "r" } },
1042     { INDEX_op_ld_i64, { "r", "r" } },
1043     { INDEX_op_st8_i64, { "r", "r" } },
1044     { INDEX_op_st16_i64, { "r", "r" } },
1045     { INDEX_op_st32_i64, { "r", "r" } },
1046     { INDEX_op_st_i64, { "r", "r" } },
1047
1048     { INDEX_op_add_i64, { "r", "r", "rJ" } },
1049     { INDEX_op_mul_i64, { "r", "r", "rJ" } },
1050     { INDEX_op_div2_i64, { "r", "r", "0", "1", "r" } },
1051     { INDEX_op_divu2_i64, { "r", "r", "0", "1", "r" } },
1052     { INDEX_op_sub_i64, { "r", "r", "rJ" } },
1053     { INDEX_op_and_i64, { "r", "r", "rJ" } },
1054     { INDEX_op_or_i64, { "r", "r", "rJ" } },
1055     { INDEX_op_xor_i64, { "r", "r", "rJ" } },
1056
1057     { INDEX_op_shl_i64, { "r", "r", "rJ" } },
1058     { INDEX_op_shr_i64, { "r", "r", "rJ" } },
1059     { INDEX_op_sar_i64, { "r", "r", "rJ" } },
1060
1061     { INDEX_op_brcond_i64, { "r", "ri" } },
1062 #endif
1063     { -1 },
1064 };
1065
1066 void tcg_target_init(TCGContext *s)
1067 {
1068     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1069 #if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
1070     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
1071 #endif
1072     tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1073                      (1 << TCG_REG_G1) |
1074                      (1 << TCG_REG_G2) |
1075                      (1 << TCG_REG_G3) |
1076                      (1 << TCG_REG_G4) |
1077                      (1 << TCG_REG_G5) |
1078                      (1 << TCG_REG_G6) |
1079                      (1 << TCG_REG_G7) |
1080                      (1 << TCG_REG_O0) |
1081                      (1 << TCG_REG_O1) |
1082                      (1 << TCG_REG_O2) |
1083                      (1 << TCG_REG_O3) |
1084                      (1 << TCG_REG_O4) |
1085                      (1 << TCG_REG_O5) |
1086                      (1 << TCG_REG_O7));
1087
1088     tcg_regset_clear(s->reserved_regs);
1089     tcg_regset_set_reg(s->reserved_regs, TCG_REG_G0);
1090     tcg_regset_set_reg(s->reserved_regs, TCG_REG_I5); // for internal use
1091     tcg_regset_set_reg(s->reserved_regs, TCG_REG_I6);
1092     tcg_regset_set_reg(s->reserved_regs, TCG_REG_I7);
1093     tcg_regset_set_reg(s->reserved_regs, TCG_REG_O6);
1094     tcg_regset_set_reg(s->reserved_regs, TCG_REG_O7);
1095     tcg_add_target_add_op_defs(sparc_op_defs);
1096 }
This page took 0.101055 seconds and 4 git commands to generate.