• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     "%r0",
27     "%r1",
28     "%rp",
29     "%r3",
30     "%r4",
31     "%r5",
32     "%r6",
33     "%r7",
34     "%r8",
35     "%r9",
36     "%r10",
37     "%r11",
38     "%r12",
39     "%r13",
40     "%r14",
41     "%r15",
42     "%r16",
43     "%r17",
44     "%r18",
45     "%r19",
46     "%r20",
47     "%r21",
48     "%r22",
49     "%r23",
50     "%r24",
51     "%r25",
52     "%r26",
53     "%dp",
54     "%ret0",
55     "%ret1",
56     "%sp",
57     "%r31",
58 };
59 
60 static const int tcg_target_reg_alloc_order[] = {
61     TCG_REG_R4,
62     TCG_REG_R5,
63     TCG_REG_R6,
64     TCG_REG_R7,
65     TCG_REG_R8,
66     TCG_REG_R9,
67     TCG_REG_R10,
68     TCG_REG_R11,
69     TCG_REG_R12,
70     TCG_REG_R13,
71 
72     TCG_REG_R17,
73     TCG_REG_R14,
74     TCG_REG_R15,
75     TCG_REG_R16,
76 };
77 
78 static const int tcg_target_call_iarg_regs[4] = {
79     TCG_REG_R26,
80     TCG_REG_R25,
81     TCG_REG_R24,
82     TCG_REG_R23,
83 };
84 
85 static const int tcg_target_call_oarg_regs[2] = {
86     TCG_REG_RET0,
87     TCG_REG_RET1,
88 };
89 
patch_reloc(uint8_t * code_ptr,int type,tcg_target_long value,tcg_target_long addend)90 static void patch_reloc(uint8_t *code_ptr, int type,
91                         tcg_target_long value, tcg_target_long addend)
92 {
93     switch (type) {
94     case R_PARISC_PCREL17F:
95         hppa_patch17f((uint32_t *)code_ptr, value, addend);
96         break;
97     default:
98         tcg_abort();
99     }
100 }
101 
102 /* maximum number of register used for input function arguments */
tcg_target_get_call_iarg_regs_count(int flags)103 static inline int tcg_target_get_call_iarg_regs_count(int flags)
104 {
105     return 4;
106 }
107 
108 /* parse target specific constraints */
target_parse_constraint(TCGArgConstraint * ct,const char ** pct_str)109 int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
110 {
111     const char *ct_str;
112 
113     ct_str = *pct_str;
114     switch (ct_str[0]) {
115     case 'r':
116         ct->ct |= TCG_CT_REG;
117         tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
118         break;
119     case 'L': /* qemu_ld/st constraint */
120         ct->ct |= TCG_CT_REG;
121         tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
122         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R26);
123         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R25);
124         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R24);
125         tcg_regset_reset_reg(ct->u.regs, TCG_REG_R23);
126         break;
127     default:
128         return -1;
129     }
130     ct_str++;
131     *pct_str = ct_str;
132     return 0;
133 }
134 
135 /* test if a constant matches the constraint */
tcg_target_const_match(tcg_target_long val,const TCGArgConstraint * arg_ct)136 static inline int tcg_target_const_match(tcg_target_long val,
137                                          const TCGArgConstraint *arg_ct)
138 {
139     int ct;
140 
141     ct = arg_ct->ct;
142 
143     /* TODO */
144 
145     return 0;
146 }
147 
148 #define INSN_OP(x)       ((x) << 26)
149 #define INSN_EXT3BR(x)   ((x) << 13)
150 #define INSN_EXT3SH(x)   ((x) << 10)
151 #define INSN_EXT4(x)     ((x) << 6)
152 #define INSN_EXT5(x)     (x)
153 #define INSN_EXT6(x)     ((x) << 6)
154 #define INSN_EXT7(x)     ((x) << 6)
155 #define INSN_EXT8A(x)    ((x) << 6)
156 #define INSN_EXT8B(x)    ((x) << 5)
157 #define INSN_T(x)        (x)
158 #define INSN_R1(x)       ((x) << 16)
159 #define INSN_R2(x)       ((x) << 21)
160 #define INSN_DEP_LEN(x)  (32 - (x))
161 #define INSN_SHDEP_CP(x) ((31 - (x)) << 5)
162 #define INSN_SHDEP_P(x)  ((x) << 5)
163 #define INSN_COND(x)     ((x) << 13)
164 
165 #define COND_NEVER 0
166 #define COND_EQUAL 1
167 #define COND_LT    2
168 #define COND_LTEQ  3
169 #define COND_LTU   4
170 #define COND_LTUEQ 5
171 #define COND_SV    6
172 #define COND_OD    7
173 
174 
175 /* Logical ADD */
176 #define ARITH_ADD  (INSN_OP(0x02) | INSN_EXT6(0x28))
177 #define ARITH_AND  (INSN_OP(0x02) | INSN_EXT6(0x08))
178 #define ARITH_OR   (INSN_OP(0x02) | INSN_EXT6(0x09))
179 #define ARITH_XOR  (INSN_OP(0x02) | INSN_EXT6(0x0a))
180 #define ARITH_SUB  (INSN_OP(0x02) | INSN_EXT6(0x10))
181 
182 #define SHD        (INSN_OP(0x34) | INSN_EXT3SH(2))
183 #define VSHD       (INSN_OP(0x34) | INSN_EXT3SH(0))
184 #define DEP        (INSN_OP(0x35) | INSN_EXT3SH(3))
185 #define ZDEP       (INSN_OP(0x35) | INSN_EXT3SH(2))
186 #define ZVDEP      (INSN_OP(0x35) | INSN_EXT3SH(0))
187 #define EXTRU      (INSN_OP(0x34) | INSN_EXT3SH(6))
188 #define EXTRS      (INSN_OP(0x34) | INSN_EXT3SH(7))
189 #define VEXTRS     (INSN_OP(0x34) | INSN_EXT3SH(5))
190 
191 #define SUBI       (INSN_OP(0x25))
192 #define MTCTL      (INSN_OP(0x00) | INSN_EXT8B(0xc2))
193 
194 #define BL         (INSN_OP(0x3a) | INSN_EXT3BR(0))
195 #define BLE_SR4    (INSN_OP(0x39) | (1 << 13))
196 #define BV         (INSN_OP(0x3a) | INSN_EXT3BR(6))
197 #define BV_N       (INSN_OP(0x3a) | INSN_EXT3BR(6) | 2)
198 #define LDIL       (INSN_OP(0x08))
199 #define LDO        (INSN_OP(0x0d))
200 
201 #define LDB        (INSN_OP(0x10))
202 #define LDH        (INSN_OP(0x11))
203 #define LDW        (INSN_OP(0x12))
204 #define LDWM       (INSN_OP(0x13))
205 
206 #define STB        (INSN_OP(0x18))
207 #define STH        (INSN_OP(0x19))
208 #define STW        (INSN_OP(0x1a))
209 #define STWM       (INSN_OP(0x1b))
210 
211 #define COMBT      (INSN_OP(0x20))
212 #define COMBF      (INSN_OP(0x22))
213 
lowsignext(uint32_t val,int start,int length)214 static int lowsignext(uint32_t val, int start, int length)
215 {
216     return (((val << 1) & ~(~0 << length)) |
217             ((val >> (length - 1)) & 1)) << start;
218 }
219 
tcg_out_mov(TCGContext * s,int ret,int arg)220 static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
221 {
222     /* PA1.1 defines COPY as OR r,0,t */
223     tcg_out32(s, ARITH_OR | INSN_T(ret) | INSN_R1(arg) | INSN_R2(TCG_REG_R0));
224 
225     /* PA2.0 defines COPY as LDO 0(r),t
226      * but hppa-dis.c is unaware of this definition */
227     /* tcg_out32(s, LDO | INSN_R1(ret) | INSN_R2(arg) | reassemble_14(0)); */
228 }
229 
tcg_out_movi(TCGContext * s,TCGType type,int ret,tcg_target_long arg)230 static inline void tcg_out_movi(TCGContext *s, TCGType type,
231                                 int ret, tcg_target_long arg)
232 {
233     if (arg == (arg & 0x1fff)) {
234         tcg_out32(s, LDO | INSN_R1(ret) | INSN_R2(TCG_REG_R0) |
235                      reassemble_14(arg));
236     } else {
237         tcg_out32(s, LDIL | INSN_R2(ret) |
238                      reassemble_21(lrsel((uint32_t)arg, 0)));
239         if (arg & 0x7ff)
240             tcg_out32(s, LDO | INSN_R1(ret) | INSN_R2(ret) |
241                          reassemble_14(rrsel((uint32_t)arg, 0)));
242     }
243 }
244 
tcg_out_ld_raw(TCGContext * s,int ret,tcg_target_long arg)245 static inline void tcg_out_ld_raw(TCGContext *s, int ret,
246                                   tcg_target_long arg)
247 {
248     tcg_out32(s, LDIL | INSN_R2(ret) |
249                  reassemble_21(lrsel((uint32_t)arg, 0)));
250     tcg_out32(s, LDW | INSN_R1(ret) | INSN_R2(ret) |
251                  reassemble_14(rrsel((uint32_t)arg, 0)));
252 }
253 
tcg_out_ld_ptr(TCGContext * s,int ret,tcg_target_long arg)254 static inline void tcg_out_ld_ptr(TCGContext *s, int ret,
255                                   tcg_target_long arg)
256 {
257     tcg_out_ld_raw(s, ret, arg);
258 }
259 
tcg_out_ldst(TCGContext * s,int ret,int addr,int offset,int op)260 static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset,
261                                 int op)
262 {
263     if (offset == (offset & 0xfff))
264         tcg_out32(s, op | INSN_R1(ret) | INSN_R2(addr) |
265                  reassemble_14(offset));
266     else {
267         fprintf(stderr, "unimplemented %s with offset %d\n", __func__, offset);
268         tcg_abort();
269     }
270 }
271 
tcg_out_ld(TCGContext * s,TCGType type,int ret,int arg1,tcg_target_long arg2)272 static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
273                               int arg1, tcg_target_long arg2)
274 {
275     fprintf(stderr, "unimplemented %s\n", __func__);
276     tcg_abort();
277 }
278 
tcg_out_st(TCGContext * s,TCGType type,int ret,int arg1,tcg_target_long arg2)279 static inline void tcg_out_st(TCGContext *s, TCGType type, int ret,
280                               int arg1, tcg_target_long arg2)
281 {
282     fprintf(stderr, "unimplemented %s\n", __func__);
283     tcg_abort();
284 }
285 
tcg_out_arith(TCGContext * s,int t,int r1,int r2,int op)286 static inline void tcg_out_arith(TCGContext *s, int t, int r1, int r2, int op)
287 {
288     tcg_out32(s, op | INSN_T(t) | INSN_R1(r1) | INSN_R2(r2));
289 }
290 
tcg_out_arithi(TCGContext * s,int t,int r1,tcg_target_long val,int op)291 static inline void tcg_out_arithi(TCGContext *s, int t, int r1,
292                                   tcg_target_long val, int op)
293 {
294     tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R20, val);
295     tcg_out_arith(s, t, r1, TCG_REG_R20, op);
296 }
297 
tcg_out_addi(TCGContext * s,int reg,tcg_target_long val)298 static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
299 {
300     tcg_out_arithi(s, reg, reg, val, ARITH_ADD);
301 }
302 
tcg_out_nop(TCGContext * s)303 static inline void tcg_out_nop(TCGContext *s)
304 {
305     tcg_out32(s, ARITH_OR | INSN_T(TCG_REG_R0) | INSN_R1(TCG_REG_R0) |
306                  INSN_R2(TCG_REG_R0));
307 }
308 
tcg_out_ext8s(TCGContext * s,int ret,int arg)309 static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg) {
310     tcg_out32(s, EXTRS | INSN_R1(ret) | INSN_R2(arg) |
311                  INSN_SHDEP_P(31) | INSN_DEP_LEN(8));
312 }
313 
tcg_out_ext16s(TCGContext * s,int ret,int arg)314 static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg) {
315     tcg_out32(s, EXTRS | INSN_R1(ret) | INSN_R2(arg) |
316                  INSN_SHDEP_P(31) | INSN_DEP_LEN(16));
317 }
318 
tcg_out_bswap16(TCGContext * s,int ret,int arg)319 static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg) {
320     if(ret != arg)
321         tcg_out_mov(s, ret, arg);
322     tcg_out32(s, DEP | INSN_R2(ret) | INSN_R1(ret) |
323                  INSN_SHDEP_CP(15) | INSN_DEP_LEN(8));
324     tcg_out32(s, SHD | INSN_T(ret) | INSN_R1(TCG_REG_R0) |
325                  INSN_R2(ret) | INSN_SHDEP_CP(8));
326 }
327 
tcg_out_bswap32(TCGContext * s,int ret,int arg,int temp)328 static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg, int temp) {
329     tcg_out32(s, SHD | INSN_T(temp) | INSN_R1(arg) |
330                  INSN_R2(arg) | INSN_SHDEP_CP(16));
331     tcg_out32(s, DEP | INSN_R2(temp) | INSN_R1(temp) |
332                  INSN_SHDEP_CP(15) | INSN_DEP_LEN(8));
333     tcg_out32(s, SHD | INSN_T(ret) | INSN_R1(arg) |
334                  INSN_R2(temp) | INSN_SHDEP_CP(8));
335 }
336 
tcg_out_call(TCGContext * s,void * func)337 static inline void tcg_out_call(TCGContext *s, void *func)
338 {
339     uint32_t val = (uint32_t)__canonicalize_funcptr_for_compare(func);
340     tcg_out32(s, LDIL | INSN_R2(TCG_REG_R20) |
341                  reassemble_21(lrsel(val, 0)));
342     tcg_out32(s, BLE_SR4 | INSN_R2(TCG_REG_R20) |
343                  reassemble_17(rrsel(val, 0) >> 2));
344     tcg_out_mov(s, TCG_REG_RP, TCG_REG_R31);
345 }
346 
347 #if defined(CONFIG_SOFTMMU)
348 
349 #include "../../softmmu_defs.h"
350 
351 static void *qemu_ld_helpers[4] = {
352     __ldb_mmu,
353     __ldw_mmu,
354     __ldl_mmu,
355     __ldq_mmu,
356 };
357 
358 static void *qemu_st_helpers[4] = {
359     __stb_mmu,
360     __stw_mmu,
361     __stl_mmu,
362     __stq_mmu,
363 };
364 #endif
365 
tcg_out_qemu_ld(TCGContext * s,const TCGArg * args,int opc)366 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
367 {
368     int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
369 #if defined(CONFIG_SOFTMMU)
370     uint32_t *label1_ptr, *label2_ptr;
371 #endif
372 #if TARGET_LONG_BITS == 64
373 #if defined(CONFIG_SOFTMMU)
374     uint32_t *label3_ptr;
375 #endif
376     int addr_reg2;
377 #endif
378 
379     data_reg = *args++;
380     if (opc == 3)
381         data_reg2 = *args++;
382     else
383         data_reg2 = 0; /* surpress warning */
384     addr_reg = *args++;
385 #if TARGET_LONG_BITS == 64
386     addr_reg2 = *args++;
387 #endif
388     mem_index = *args;
389     s_bits = opc & 3;
390 
391     r0 = TCG_REG_R26;
392     r1 = TCG_REG_R25;
393 
394 #if defined(CONFIG_SOFTMMU)
395     tcg_out_mov(s, r1, addr_reg);
396 
397     tcg_out_mov(s, r0, addr_reg);
398 
399     tcg_out32(s, SHD | INSN_T(r1) | INSN_R1(TCG_REG_R0) | INSN_R2(r1) |
400                  INSN_SHDEP_CP(TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS));
401 
402     tcg_out_arithi(s, r0, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1),
403                    ARITH_AND);
404 
405     tcg_out_arithi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS,
406                    ARITH_AND);
407 
408     tcg_out_arith(s, r1, r1, TCG_AREG0, ARITH_ADD);
409     tcg_out_arithi(s, r1, r1,
410                    offsetof(CPUState, tlb_table[mem_index][0].addr_read),
411                    ARITH_ADD);
412 
413     tcg_out_ldst(s, TCG_REG_R20, r1, 0, LDW);
414 
415 #if TARGET_LONG_BITS == 32
416     /* if equal, jump to label1 */
417     label1_ptr = (uint32_t *)s->code_ptr;
418     tcg_out32(s, COMBT | INSN_R1(TCG_REG_R20) | INSN_R2(r0) |
419                  INSN_COND(COND_EQUAL));
420     tcg_out_mov(s, r0, addr_reg); /* delay slot */
421 #else
422     /* if not equal, jump to label3 */
423     label3_ptr = (uint32_t *)s->code_ptr;
424     tcg_out32(s, COMBF | INSN_R1(TCG_REG_R20) | INSN_R2(r0) |
425                  INSN_COND(COND_EQUAL));
426     tcg_out_mov(s, r0, addr_reg); /* delay slot */
427 
428     tcg_out_ldst(s, TCG_REG_R20, r1, 4, LDW);
429 
430     /* if equal, jump to label1 */
431     label1_ptr = (uint32_t *)s->code_ptr;
432     tcg_out32(s, COMBT | INSN_R1(TCG_REG_R20) | INSN_R2(addr_reg2) |
433                  INSN_COND(COND_EQUAL));
434     tcg_out_nop(s); /* delay slot */
435 
436     /* label3: */
437     *label3_ptr |= reassemble_12((uint32_t *)s->code_ptr - label3_ptr - 2);
438 #endif
439 
440 #if TARGET_LONG_BITS == 32
441     tcg_out_mov(s, TCG_REG_R26, addr_reg);
442     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R25, mem_index);
443 #else
444     tcg_out_mov(s, TCG_REG_R26, addr_reg);
445     tcg_out_mov(s, TCG_REG_R25, addr_reg2);
446     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R24, mem_index);
447 #endif
448 
449     tcg_out_call(s, qemu_ld_helpers[s_bits]);
450 
451     switch(opc) {
452         case 0 | 4:
453             tcg_out_ext8s(s, data_reg, TCG_REG_RET0);
454             break;
455         case 1 | 4:
456             tcg_out_ext16s(s, data_reg, TCG_REG_RET0);
457             break;
458         case 0:
459         case 1:
460         case 2:
461         default:
462             tcg_out_mov(s, data_reg, TCG_REG_RET0);
463             break;
464         case 3:
465             tcg_abort();
466             tcg_out_mov(s, data_reg, TCG_REG_RET0);
467             tcg_out_mov(s, data_reg2, TCG_REG_RET1);
468             break;
469     }
470 
471     /* jump to label2 */
472     label2_ptr = (uint32_t *)s->code_ptr;
473     tcg_out32(s, BL | INSN_R2(TCG_REG_R0) | 2);
474 
475     /* label1: */
476     *label1_ptr |= reassemble_12((uint32_t *)s->code_ptr - label1_ptr - 2);
477 
478     tcg_out_arithi(s, TCG_REG_R20, r1,
479                    offsetof(CPUTLBEntry, addend) - offsetof(CPUTLBEntry, addr_read),
480                    ARITH_ADD);
481     tcg_out_ldst(s, TCG_REG_R20, TCG_REG_R20, 0, LDW);
482     tcg_out_arith(s, r0, r0, TCG_REG_R20, ARITH_ADD);
483 #else
484     r0 = addr_reg;
485 #endif
486 
487 #ifdef TARGET_WORDS_BIGENDIAN
488     bswap = 0;
489 #else
490     bswap = 1;
491 #endif
492     switch (opc) {
493         case 0:
494             tcg_out_ldst(s, data_reg, r0, 0, LDB);
495             break;
496         case 0 | 4:
497             tcg_out_ldst(s, data_reg, r0, 0, LDB);
498             tcg_out_ext8s(s, data_reg, data_reg);
499             break;
500         case 1:
501             tcg_out_ldst(s, data_reg, r0, 0, LDH);
502             if (bswap)
503                 tcg_out_bswap16(s, data_reg, data_reg);
504             break;
505         case 1 | 4:
506             tcg_out_ldst(s, data_reg, r0, 0, LDH);
507             if (bswap)
508                 tcg_out_bswap16(s, data_reg, data_reg);
509             tcg_out_ext16s(s, data_reg, data_reg);
510             break;
511         case 2:
512             tcg_out_ldst(s, data_reg, r0, 0, LDW);
513             if (bswap)
514                 tcg_out_bswap32(s, data_reg, data_reg, TCG_REG_R20);
515             break;
516         case 3:
517             tcg_abort();
518             if (!bswap) {
519                 tcg_out_ldst(s, data_reg, r0, 0, LDW);
520                 tcg_out_ldst(s, data_reg2, r0, 4, LDW);
521             } else {
522                 tcg_out_ldst(s, data_reg, r0, 4, LDW);
523                 tcg_out_bswap32(s, data_reg, data_reg, TCG_REG_R20);
524                 tcg_out_ldst(s, data_reg2, r0, 0, LDW);
525                 tcg_out_bswap32(s, data_reg2, data_reg2, TCG_REG_R20);
526             }
527             break;
528         default:
529             tcg_abort();
530     }
531 
532 #if defined(CONFIG_SOFTMMU)
533     /* label2: */
534     *label2_ptr |= reassemble_17((uint32_t *)s->code_ptr - label2_ptr - 2);
535 #endif
536 }
537 
tcg_out_qemu_st(TCGContext * s,const TCGArg * args,int opc)538 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
539 {
540     int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
541 #if defined(CONFIG_SOFTMMU)
542     uint32_t *label1_ptr, *label2_ptr;
543 #endif
544 #if TARGET_LONG_BITS == 64
545 #if defined(CONFIG_SOFTMMU)
546     uint32_t *label3_ptr;
547 #endif
548     int addr_reg2;
549 #endif
550 
551     data_reg = *args++;
552     if (opc == 3)
553         data_reg2 = *args++;
554     else
555         data_reg2 = 0; /* surpress warning */
556     addr_reg = *args++;
557 #if TARGET_LONG_BITS == 64
558     addr_reg2 = *args++;
559 #endif
560     mem_index = *args;
561 
562     s_bits = opc;
563 
564     r0 = TCG_REG_R26;
565     r1 = TCG_REG_R25;
566 
567 #if defined(CONFIG_SOFTMMU)
568     tcg_out_mov(s, r1, addr_reg);
569 
570     tcg_out_mov(s, r0, addr_reg);
571 
572     tcg_out32(s, SHD | INSN_T(r1) | INSN_R1(TCG_REG_R0) | INSN_R2(r1) |
573                  INSN_SHDEP_CP(TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS));
574 
575     tcg_out_arithi(s, r0, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1),
576                    ARITH_AND);
577 
578     tcg_out_arithi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS,
579                    ARITH_AND);
580 
581     tcg_out_arith(s, r1, r1, TCG_AREG0, ARITH_ADD);
582     tcg_out_arithi(s, r1, r1,
583                    offsetof(CPUState, tlb_table[mem_index][0].addr_write),
584                    ARITH_ADD);
585 
586     tcg_out_ldst(s, TCG_REG_R20, r1, 0, LDW);
587 
588 #if TARGET_LONG_BITS == 32
589     /* if equal, jump to label1 */
590     label1_ptr = (uint32_t *)s->code_ptr;
591     tcg_out32(s, COMBT | INSN_R1(TCG_REG_R20) | INSN_R2(r0) |
592                  INSN_COND(COND_EQUAL));
593     tcg_out_mov(s, r0, addr_reg); /* delay slot */
594 #else
595     /* if not equal, jump to label3 */
596     label3_ptr = (uint32_t *)s->code_ptr;
597     tcg_out32(s, COMBF | INSN_R1(TCG_REG_R20) | INSN_R2(r0) |
598                  INSN_COND(COND_EQUAL));
599     tcg_out_mov(s, r0, addr_reg); /* delay slot */
600 
601     tcg_out_ldst(s, TCG_REG_R20, r1, 4, LDW);
602 
603     /* if equal, jump to label1 */
604     label1_ptr = (uint32_t *)s->code_ptr;
605     tcg_out32(s, COMBT | INSN_R1(TCG_REG_R20) | INSN_R2(addr_reg2) |
606                  INSN_COND(COND_EQUAL));
607     tcg_out_nop(s); /* delay slot */
608 
609     /* label3: */
610     *label3_ptr |= reassemble_12((uint32_t *)s->code_ptr - label3_ptr - 2);
611 #endif
612 
613     tcg_out_mov(s, TCG_REG_R26, addr_reg);
614 #if TARGET_LONG_BITS == 64
615     tcg_out_mov(s, TCG_REG_R25, addr_reg2);
616     if (opc == 3) {
617         tcg_abort();
618         tcg_out_mov(s, TCG_REG_R24, data_reg);
619         tcg_out_mov(s, TCG_REG_R23, data_reg2);
620         /* TODO: push mem_index */
621         tcg_abort();
622     } else {
623         switch(opc) {
624         case 0:
625             tcg_out32(s, EXTRU | INSN_R1(TCG_REG_R24) | INSN_R2(data_reg) |
626                          INSN_SHDEP_P(31) | INSN_DEP_LEN(8));
627             break;
628         case 1:
629             tcg_out32(s, EXTRU | INSN_R1(TCG_REG_R24) | INSN_R2(data_reg) |
630                          INSN_SHDEP_P(31) | INSN_DEP_LEN(16));
631             break;
632         case 2:
633             tcg_out_mov(s, TCG_REG_R24, data_reg);
634             break;
635         }
636         tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R23, mem_index);
637     }
638 #else
639     if (opc == 3) {
640         tcg_abort();
641         tcg_out_mov(s, TCG_REG_R25, data_reg);
642         tcg_out_mov(s, TCG_REG_R24, data_reg2);
643         tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R23, mem_index);
644     } else {
645         switch(opc) {
646         case 0:
647             tcg_out32(s, EXTRU | INSN_R1(TCG_REG_R25) | INSN_R2(data_reg) |
648                          INSN_SHDEP_P(31) | INSN_DEP_LEN(8));
649             break;
650         case 1:
651             tcg_out32(s, EXTRU | INSN_R1(TCG_REG_R25) | INSN_R2(data_reg) |
652                          INSN_SHDEP_P(31) | INSN_DEP_LEN(16));
653             break;
654         case 2:
655             tcg_out_mov(s, TCG_REG_R25, data_reg);
656             break;
657         }
658         tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R24, mem_index);
659     }
660 #endif
661     tcg_out_call(s, qemu_st_helpers[s_bits]);
662 
663     /* jump to label2 */
664     label2_ptr = (uint32_t *)s->code_ptr;
665     tcg_out32(s, BL | INSN_R2(TCG_REG_R0) | 2);
666 
667     /* label1: */
668     *label1_ptr |= reassemble_12((uint32_t *)s->code_ptr - label1_ptr - 2);
669 
670     tcg_out_arithi(s, TCG_REG_R20, r1,
671                    offsetof(CPUTLBEntry, addend) - offsetof(CPUTLBEntry, addr_write),
672                    ARITH_ADD);
673     tcg_out_ldst(s, TCG_REG_R20, TCG_REG_R20, 0, LDW);
674     tcg_out_arith(s, r0, r0, TCG_REG_R20, ARITH_ADD);
675 #else
676     r0 = addr_reg;
677 #endif
678 
679 #ifdef TARGET_WORDS_BIGENDIAN
680     bswap = 0;
681 #else
682     bswap = 1;
683 #endif
684     switch (opc) {
685     case 0:
686         tcg_out_ldst(s, data_reg, r0, 0, STB);
687         break;
688     case 1:
689         if (bswap) {
690             tcg_out_bswap16(s, TCG_REG_R20, data_reg);
691             data_reg = TCG_REG_R20;
692         }
693         tcg_out_ldst(s, data_reg, r0, 0, STH);
694         break;
695     case 2:
696         if (bswap) {
697             tcg_out_bswap32(s, TCG_REG_R20, data_reg, TCG_REG_R20);
698             data_reg = TCG_REG_R20;
699         }
700         tcg_out_ldst(s, data_reg, r0, 0, STW);
701         break;
702     case 3:
703         tcg_abort();
704         if (!bswap) {
705             tcg_out_ldst(s, data_reg, r0, 0, STW);
706             tcg_out_ldst(s, data_reg2, r0, 4, STW);
707         } else {
708             tcg_out_bswap32(s, TCG_REG_R20, data_reg, TCG_REG_R20);
709             tcg_out_ldst(s, TCG_REG_R20, r0, 4, STW);
710             tcg_out_bswap32(s, TCG_REG_R20, data_reg2, TCG_REG_R20);
711             tcg_out_ldst(s, TCG_REG_R20, r0, 0, STW);
712         }
713         break;
714     default:
715         tcg_abort();
716     }
717 
718 #if defined(CONFIG_SOFTMMU)
719     /* label2: */
720     *label2_ptr |= reassemble_17((uint32_t *)s->code_ptr - label2_ptr - 2);
721 #endif
722 }
723 
tcg_out_op(TCGContext * s,int opc,const TCGArg * args,const int * const_args)724 static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
725                               const int *const_args)
726 {
727     int c;
728 
729     switch (opc) {
730     case INDEX_op_exit_tb:
731         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RET0, args[0]);
732         tcg_out32(s, BV_N | INSN_R2(TCG_REG_R18));
733         break;
734     case INDEX_op_goto_tb:
735         if (s->tb_jmp_offset) {
736             /* direct jump method */
737             fprintf(stderr, "goto_tb direct\n");
738             tcg_abort();
739             tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R20, args[0]);
740             tcg_out32(s, BV_N | INSN_R2(TCG_REG_R20));
741             s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
742         } else {
743             /* indirect jump method */
744             tcg_out_ld_ptr(s, TCG_REG_R20,
745                            (tcg_target_long)(s->tb_next + args[0]));
746             tcg_out32(s, BV_N | INSN_R2(TCG_REG_R20));
747         }
748         s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
749         break;
750     case INDEX_op_call:
751         tcg_out32(s, BLE_SR4 | INSN_R2(args[0]));
752         tcg_out_mov(s, TCG_REG_RP, TCG_REG_R31);
753         break;
754     case INDEX_op_jmp:
755         fprintf(stderr, "unimplemented jmp\n");
756         tcg_abort();
757         break;
758     case INDEX_op_br:
759         fprintf(stderr, "unimplemented br\n");
760         tcg_abort();
761         break;
762     case INDEX_op_movi_i32:
763         tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]);
764         break;
765 
766     case INDEX_op_ld8u_i32:
767         tcg_out_ldst(s, args[0], args[1], args[2], LDB);
768         break;
769     case INDEX_op_ld8s_i32:
770         tcg_out_ldst(s, args[0], args[1], args[2], LDB);
771         tcg_out_ext8s(s, args[0], args[0]);
772         break;
773     case INDEX_op_ld16u_i32:
774         tcg_out_ldst(s, args[0], args[1], args[2], LDH);
775         break;
776     case INDEX_op_ld16s_i32:
777         tcg_out_ldst(s, args[0], args[1], args[2], LDH);
778         tcg_out_ext16s(s, args[0], args[0]);
779         break;
780     case INDEX_op_ld_i32:
781         tcg_out_ldst(s, args[0], args[1], args[2], LDW);
782         break;
783 
784     case INDEX_op_st8_i32:
785         tcg_out_ldst(s, args[0], args[1], args[2], STB);
786         break;
787     case INDEX_op_st16_i32:
788         tcg_out_ldst(s, args[0], args[1], args[2], STH);
789         break;
790     case INDEX_op_st_i32:
791         tcg_out_ldst(s, args[0], args[1], args[2], STW);
792         break;
793 
794     case INDEX_op_sub_i32:
795         c = ARITH_SUB;
796         goto gen_arith;
797     case INDEX_op_and_i32:
798         c = ARITH_AND;
799         goto gen_arith;
800     case INDEX_op_or_i32:
801         c = ARITH_OR;
802         goto gen_arith;
803     case INDEX_op_xor_i32:
804         c = ARITH_XOR;
805         goto gen_arith;
806     case INDEX_op_add_i32:
807         c = ARITH_ADD;
808         goto gen_arith;
809 
810     case INDEX_op_shl_i32:
811         tcg_out32(s, SUBI | INSN_R1(TCG_REG_R20) | INSN_R2(args[2]) |
812                      lowsignext(0x1f, 0, 11));
813         tcg_out32(s, MTCTL | INSN_R2(11) | INSN_R1(TCG_REG_R20));
814         tcg_out32(s, ZVDEP | INSN_R2(args[0]) | INSN_R1(args[1]) |
815                      INSN_DEP_LEN(32));
816         break;
817     case INDEX_op_shr_i32:
818         tcg_out32(s, MTCTL | INSN_R2(11) | INSN_R1(args[2]));
819         tcg_out32(s, VSHD | INSN_T(args[0]) | INSN_R1(TCG_REG_R0) |
820                      INSN_R2(args[1]));
821         break;
822     case INDEX_op_sar_i32:
823         tcg_out32(s, SUBI | INSN_R1(TCG_REG_R20) | INSN_R2(args[2]) |
824                      lowsignext(0x1f, 0, 11));
825         tcg_out32(s, MTCTL | INSN_R2(11) | INSN_R1(TCG_REG_R20));
826         tcg_out32(s, VEXTRS | INSN_R1(args[0]) | INSN_R2(args[1]) |
827                      INSN_DEP_LEN(32));
828         break;
829 
830     case INDEX_op_mul_i32:
831         fprintf(stderr, "unimplemented mul\n");
832         tcg_abort();
833         break;
834     case INDEX_op_mulu2_i32:
835         fprintf(stderr, "unimplemented mulu2\n");
836         tcg_abort();
837         break;
838     case INDEX_op_div2_i32:
839         fprintf(stderr, "unimplemented div2\n");
840         tcg_abort();
841         break;
842     case INDEX_op_divu2_i32:
843         fprintf(stderr, "unimplemented divu2\n");
844         tcg_abort();
845         break;
846 
847     case INDEX_op_brcond_i32:
848         fprintf(stderr, "unimplemented brcond\n");
849         tcg_abort();
850         break;
851 
852     case INDEX_op_qemu_ld8u:
853         tcg_out_qemu_ld(s, args, 0);
854         break;
855     case INDEX_op_qemu_ld8s:
856         tcg_out_qemu_ld(s, args, 0 | 4);
857         break;
858     case INDEX_op_qemu_ld16u:
859         tcg_out_qemu_ld(s, args, 1);
860         break;
861     case INDEX_op_qemu_ld16s:
862         tcg_out_qemu_ld(s, args, 1 | 4);
863         break;
864     case INDEX_op_qemu_ld32u:
865         tcg_out_qemu_ld(s, args, 2);
866         break;
867 
868     case INDEX_op_qemu_st8:
869         tcg_out_qemu_st(s, args, 0);
870         break;
871     case INDEX_op_qemu_st16:
872         tcg_out_qemu_st(s, args, 1);
873         break;
874     case INDEX_op_qemu_st32:
875         tcg_out_qemu_st(s, args, 2);
876         break;
877 
878     default:
879         fprintf(stderr, "unknown opcode 0x%x\n", opc);
880         tcg_abort();
881     }
882     return;
883 
884 gen_arith:
885     tcg_out_arith(s, args[0], args[1], args[2], c);
886 }
887 
888 static const TCGTargetOpDef hppa_op_defs[] = {
889     { INDEX_op_exit_tb, { } },
890     { INDEX_op_goto_tb, { } },
891 
892     { INDEX_op_call, { "r" } },
893     { INDEX_op_jmp, { "r" } },
894     { INDEX_op_br, { } },
895 
896     { INDEX_op_mov_i32, { "r", "r" } },
897     { INDEX_op_movi_i32, { "r" } },
898     { INDEX_op_ld8u_i32, { "r", "r" } },
899     { INDEX_op_ld8s_i32, { "r", "r" } },
900     { INDEX_op_ld16u_i32, { "r", "r" } },
901     { INDEX_op_ld16s_i32, { "r", "r" } },
902     { INDEX_op_ld_i32, { "r", "r" } },
903     { INDEX_op_st8_i32, { "r", "r" } },
904     { INDEX_op_st16_i32, { "r", "r" } },
905     { INDEX_op_st_i32, { "r", "r" } },
906 
907     { INDEX_op_add_i32, { "r", "r", "r" } },
908     { INDEX_op_sub_i32, { "r", "r", "r" } },
909     { INDEX_op_and_i32, { "r", "r", "r" } },
910     { INDEX_op_or_i32, { "r", "r", "r" } },
911     { INDEX_op_xor_i32, { "r", "r", "r" } },
912 
913     { INDEX_op_shl_i32, { "r", "r", "r" } },
914     { INDEX_op_shr_i32, { "r", "r", "r" } },
915     { INDEX_op_sar_i32, { "r", "r", "r" } },
916 
917     { INDEX_op_brcond_i32, { "r", "r" } },
918 
919 #if TARGET_LONG_BITS == 32
920     { INDEX_op_qemu_ld8u, { "r", "L" } },
921     { INDEX_op_qemu_ld8s, { "r", "L" } },
922     { INDEX_op_qemu_ld16u, { "r", "L" } },
923     { INDEX_op_qemu_ld16s, { "r", "L" } },
924     { INDEX_op_qemu_ld32u, { "r", "L" } },
925     { INDEX_op_qemu_ld64, { "r", "r", "L" } },
926 
927     { INDEX_op_qemu_st8, { "L", "L" } },
928     { INDEX_op_qemu_st16, { "L", "L" } },
929     { INDEX_op_qemu_st32, { "L", "L" } },
930     { INDEX_op_qemu_st64, { "L", "L", "L" } },
931 #else
932     { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
933     { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
934     { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
935     { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
936     { INDEX_op_qemu_ld32u, { "r", "L", "L" } },
937     { INDEX_op_qemu_ld32s, { "r", "L", "L" } },
938     { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
939 
940     { INDEX_op_qemu_st8, { "L", "L", "L" } },
941     { INDEX_op_qemu_st16, { "L", "L", "L" } },
942     { INDEX_op_qemu_st32, { "L", "L", "L" } },
943     { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
944 #endif
945     { -1 },
946 };
947 
tcg_target_init(TCGContext * s)948 void tcg_target_init(TCGContext *s)
949 {
950     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
951     tcg_regset_set32(tcg_target_call_clobber_regs, 0,
952                      (1 << TCG_REG_R20) |
953                      (1 << TCG_REG_R21) |
954                      (1 << TCG_REG_R22) |
955                      (1 << TCG_REG_R23) |
956                      (1 << TCG_REG_R24) |
957                      (1 << TCG_REG_R25) |
958                      (1 << TCG_REG_R26));
959 
960     tcg_regset_clear(s->reserved_regs);
961     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);  /* hardwired to zero */
962     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1);  /* addil target */
963     tcg_regset_set_reg(s->reserved_regs, TCG_REG_RP);  /* link register */
964     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R3);  /* frame pointer */
965     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R18); /* return pointer */
966     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R19); /* clobbered w/o pic */
967     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R20); /* reserved */
968     tcg_regset_set_reg(s->reserved_regs, TCG_REG_DP);  /* data pointer */
969     tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);  /* stack pointer */
970     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R31); /* ble link reg */
971 
972     tcg_add_target_add_op_defs(hppa_op_defs);
973 }
974