2 * Tiny Code Generator for QEMU
4 * Copyright (c) 2008 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
26 static const char * const tcg_target_reg_names
[TCG_TARGET_NB_REGS
] = {
62 static const int tcg_target_reg_alloc_order
[] = {
80 static const int tcg_target_call_iarg_regs
[4] = {
87 static const int tcg_target_call_oarg_regs
[2] = {
92 static void patch_reloc(uint8_t *code_ptr
, int type
,
93 tcg_target_long value
, tcg_target_long addend
)
96 case R_PARISC_PCREL17F
:
97 hppa_patch17f((uint32_t *)code_ptr
, value
, addend
);
104 /* maximum number of register used for input function arguments */
105 static inline int tcg_target_get_call_iarg_regs_count(int flags
)
110 /* parse target specific constraints */
111 static int target_parse_constraint(TCGArgConstraint
*ct
, const char **pct_str
)
118 ct
->ct
|= TCG_CT_REG
;
119 tcg_regset_set32(ct
->u
.regs
, 0, 0xffffffff);
121 case 'L': /* qemu_ld/st constraint */
122 ct
->ct
|= TCG_CT_REG
;
123 tcg_regset_set32(ct
->u
.regs
, 0, 0xffffffff);
124 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R26
);
125 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R25
);
126 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R24
);
127 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R23
);
137 /* test if a constant matches the constraint */
138 static inline int tcg_target_const_match(tcg_target_long val
,
139 const TCGArgConstraint
*arg_ct
)
150 #define INSN_OP(x) ((x) << 26)
151 #define INSN_EXT3BR(x) ((x) << 13)
152 #define INSN_EXT3SH(x) ((x) << 10)
153 #define INSN_EXT4(x) ((x) << 6)
154 #define INSN_EXT5(x) (x)
155 #define INSN_EXT6(x) ((x) << 6)
156 #define INSN_EXT7(x) ((x) << 6)
157 #define INSN_EXT8A(x) ((x) << 6)
158 #define INSN_EXT8B(x) ((x) << 5)
159 #define INSN_T(x) (x)
160 #define INSN_R1(x) ((x) << 16)
161 #define INSN_R2(x) ((x) << 21)
162 #define INSN_DEP_LEN(x) (32 - (x))
163 #define INSN_SHDEP_CP(x) ((31 - (x)) << 5)
164 #define INSN_SHDEP_P(x) ((x) << 5)
165 #define INSN_COND(x) ((x) << 13)
178 #define ARITH_ADD (INSN_OP(0x02) | INSN_EXT6(0x28))
179 #define ARITH_AND (INSN_OP(0x02) | INSN_EXT6(0x08))
180 #define ARITH_OR (INSN_OP(0x02) | INSN_EXT6(0x09))
181 #define ARITH_XOR (INSN_OP(0x02) | INSN_EXT6(0x0a))
182 #define ARITH_SUB (INSN_OP(0x02) | INSN_EXT6(0x10))
184 #define SHD (INSN_OP(0x34) | INSN_EXT3SH(2))
185 #define VSHD (INSN_OP(0x34) | INSN_EXT3SH(0))
186 #define DEP (INSN_OP(0x35) | INSN_EXT3SH(3))
187 #define ZDEP (INSN_OP(0x35) | INSN_EXT3SH(2))
188 #define ZVDEP (INSN_OP(0x35) | INSN_EXT3SH(0))
189 #define EXTRU (INSN_OP(0x34) | INSN_EXT3SH(6))
190 #define EXTRS (INSN_OP(0x34) | INSN_EXT3SH(7))
191 #define VEXTRS (INSN_OP(0x34) | INSN_EXT3SH(5))
193 #define SUBI (INSN_OP(0x25))
194 #define MTCTL (INSN_OP(0x00) | INSN_EXT8B(0xc2))
196 #define BL (INSN_OP(0x3a) | INSN_EXT3BR(0))
197 #define BLE_SR4 (INSN_OP(0x39) | (1 << 13))
198 #define BV (INSN_OP(0x3a) | INSN_EXT3BR(6))
199 #define BV_N (INSN_OP(0x3a) | INSN_EXT3BR(6) | 2)
200 #define LDIL (INSN_OP(0x08))
201 #define LDO (INSN_OP(0x0d))
203 #define LDB (INSN_OP(0x10))
204 #define LDH (INSN_OP(0x11))
205 #define LDW (INSN_OP(0x12))
206 #define LDWM (INSN_OP(0x13))
208 #define STB (INSN_OP(0x18))
209 #define STH (INSN_OP(0x19))
210 #define STW (INSN_OP(0x1a))
211 #define STWM (INSN_OP(0x1b))
213 #define COMBT (INSN_OP(0x20))
214 #define COMBF (INSN_OP(0x22))
216 static int lowsignext(uint32_t val
, int start
, int length
)
218 return (((val
<< 1) & ~(~0 << length
)) |
219 ((val
>> (length
- 1)) & 1)) << start
;
222 static inline void tcg_out_mov(TCGContext
*s
, int ret
, int arg
)
224 /* PA1.1 defines COPY as OR r,0,t */
225 tcg_out32(s
, ARITH_OR
| INSN_T(ret
) | INSN_R1(arg
) | INSN_R2(TCG_REG_R0
));
227 /* PA2.0 defines COPY as LDO 0(r),t
228 * but hppa-dis.c is unaware of this definition */
229 /* tcg_out32(s, LDO | INSN_R1(ret) | INSN_R2(arg) | reassemble_14(0)); */
232 static inline void tcg_out_movi(TCGContext
*s
, TCGType type
,
233 int ret
, tcg_target_long arg
)
235 if (arg
== (arg
& 0x1fff)) {
236 tcg_out32(s
, LDO
| INSN_R1(ret
) | INSN_R2(TCG_REG_R0
) |
239 tcg_out32(s
, LDIL
| INSN_R2(ret
) |
240 reassemble_21(lrsel((uint32_t)arg
, 0)));
242 tcg_out32(s
, LDO
| INSN_R1(ret
) | INSN_R2(ret
) |
243 reassemble_14(rrsel((uint32_t)arg
, 0)));
247 static inline void tcg_out_ld_raw(TCGContext
*s
, int ret
,
250 tcg_out32(s
, LDIL
| INSN_R2(ret
) |
251 reassemble_21(lrsel((uint32_t)arg
, 0)));
252 tcg_out32(s
, LDW
| INSN_R1(ret
) | INSN_R2(ret
) |
253 reassemble_14(rrsel((uint32_t)arg
, 0)));
256 static inline void tcg_out_ld_ptr(TCGContext
*s
, int ret
,
259 tcg_out_ld_raw(s
, ret
, arg
);
262 static inline void tcg_out_ldst(TCGContext
*s
, int ret
, int addr
, int offset
,
265 if (offset
== (offset
& 0xfff))
266 tcg_out32(s
, op
| INSN_R1(ret
) | INSN_R2(addr
) |
267 reassemble_14(offset
));
269 fprintf(stderr
, "unimplemented %s with offset %d\n", __func__
, offset
);
274 static inline void tcg_out_ld(TCGContext
*s
, TCGType type
, int ret
,
275 int arg1
, tcg_target_long arg2
)
277 fprintf(stderr
, "unimplemented %s\n", __func__
);
281 static inline void tcg_out_st(TCGContext
*s
, TCGType type
, int ret
,
282 int arg1
, tcg_target_long arg2
)
284 fprintf(stderr
, "unimplemented %s\n", __func__
);
288 static inline void tcg_out_arith(TCGContext
*s
, int t
, int r1
, int r2
, int op
)
290 tcg_out32(s
, op
| INSN_T(t
) | INSN_R1(r1
) | INSN_R2(r2
));
293 static inline void tcg_out_arithi(TCGContext
*s
, int t
, int r1
,
294 tcg_target_long val
, int op
)
296 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_R20
, val
);
297 tcg_out_arith(s
, t
, r1
, TCG_REG_R20
, op
);
300 static inline void tcg_out_addi(TCGContext
*s
, int reg
, tcg_target_long val
)
302 tcg_out_arithi(s
, reg
, reg
, val
, ARITH_ADD
);
305 static inline void tcg_out_nop(TCGContext
*s
)
307 tcg_out32(s
, ARITH_OR
| INSN_T(TCG_REG_R0
) | INSN_R1(TCG_REG_R0
) |
308 INSN_R2(TCG_REG_R0
));
311 static inline void tcg_out_ext8s(TCGContext
*s
, int ret
, int arg
) {
312 tcg_out32(s
, EXTRS
| INSN_R1(ret
) | INSN_R2(arg
) |
313 INSN_SHDEP_P(31) | INSN_DEP_LEN(8));
316 static inline void tcg_out_ext16s(TCGContext
*s
, int ret
, int arg
) {
317 tcg_out32(s
, EXTRS
| INSN_R1(ret
) | INSN_R2(arg
) |
318 INSN_SHDEP_P(31) | INSN_DEP_LEN(16));
321 static inline void tcg_out_bswap16(TCGContext
*s
, int ret
, int arg
) {
323 tcg_out_mov(s
, ret
, arg
);
324 tcg_out32(s
, DEP
| INSN_R2(ret
) | INSN_R1(ret
) |
325 INSN_SHDEP_CP(15) | INSN_DEP_LEN(8));
326 tcg_out32(s
, SHD
| INSN_T(ret
) | INSN_R1(TCG_REG_R0
) |
327 INSN_R2(ret
) | INSN_SHDEP_CP(8));
330 static inline void tcg_out_bswap32(TCGContext
*s
, int ret
, int arg
, int temp
) {
331 tcg_out32(s
, SHD
| INSN_T(temp
) | INSN_R1(arg
) |
332 INSN_R2(arg
) | INSN_SHDEP_CP(16));
333 tcg_out32(s
, DEP
| INSN_R2(temp
) | INSN_R1(temp
) |
334 INSN_SHDEP_CP(15) | INSN_DEP_LEN(8));
335 tcg_out32(s
, SHD
| INSN_T(ret
) | INSN_R1(arg
) |
336 INSN_R2(temp
) | INSN_SHDEP_CP(8));
339 static inline void tcg_out_call(TCGContext
*s
, void *func
)
341 uint32_t val
= (uint32_t)__canonicalize_funcptr_for_compare(func
);
342 tcg_out32(s
, LDIL
| INSN_R2(TCG_REG_R20
) |
343 reassemble_21(lrsel(val
, 0)));
344 tcg_out32(s
, BLE_SR4
| INSN_R2(TCG_REG_R20
) |
345 reassemble_17(rrsel(val
, 0) >> 2));
346 tcg_out_mov(s
, TCG_REG_RP
, TCG_REG_R31
);
349 #if defined(CONFIG_SOFTMMU)
351 #include "../../softmmu_defs.h"
353 static void *qemu_ld_helpers
[4] = {
360 static void *qemu_st_helpers
[4] = {
368 static void tcg_out_qemu_ld(TCGContext
*s
, const TCGArg
*args
, int opc
)
370 int addr_reg
, data_reg
, data_reg2
, r0
, r1
, mem_index
, s_bits
, bswap
;
371 #if defined(CONFIG_SOFTMMU)
372 uint32_t *label1_ptr
, *label2_ptr
;
374 #if TARGET_LONG_BITS == 64
375 #if defined(CONFIG_SOFTMMU)
376 uint32_t *label3_ptr
;
385 data_reg2
= 0; /* suppress warning */
387 #if TARGET_LONG_BITS == 64
396 #if defined(CONFIG_SOFTMMU)
397 tcg_out_mov(s
, r1
, addr_reg
);
399 tcg_out_mov(s
, r0
, addr_reg
);
401 tcg_out32(s
, SHD
| INSN_T(r1
) | INSN_R1(TCG_REG_R0
) | INSN_R2(r1
) |
402 INSN_SHDEP_CP(TARGET_PAGE_BITS
- CPU_TLB_ENTRY_BITS
));
404 tcg_out_arithi(s
, r0
, r0
, TARGET_PAGE_MASK
| ((1 << s_bits
) - 1),
407 tcg_out_arithi(s
, r1
, r1
, (CPU_TLB_SIZE
- 1) << CPU_TLB_ENTRY_BITS
,
410 tcg_out_arith(s
, r1
, r1
, TCG_AREG0
, ARITH_ADD
);
411 tcg_out_arithi(s
, r1
, r1
,
412 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_read
),
415 tcg_out_ldst(s
, TCG_REG_R20
, r1
, 0, LDW
);
417 #if TARGET_LONG_BITS == 32
418 /* if equal, jump to label1 */
419 label1_ptr
= (uint32_t *)s
->code_ptr
;
420 tcg_out32(s
, COMBT
| INSN_R1(TCG_REG_R20
) | INSN_R2(r0
) |
421 INSN_COND(COND_EQUAL
));
422 tcg_out_mov(s
, r0
, addr_reg
); /* delay slot */
424 /* if not equal, jump to label3 */
425 label3_ptr
= (uint32_t *)s
->code_ptr
;
426 tcg_out32(s
, COMBF
| INSN_R1(TCG_REG_R20
) | INSN_R2(r0
) |
427 INSN_COND(COND_EQUAL
));
428 tcg_out_mov(s
, r0
, addr_reg
); /* delay slot */
430 tcg_out_ldst(s
, TCG_REG_R20
, r1
, 4, LDW
);
432 /* if equal, jump to label1 */
433 label1_ptr
= (uint32_t *)s
->code_ptr
;
434 tcg_out32(s
, COMBT
| INSN_R1(TCG_REG_R20
) | INSN_R2(addr_reg2
) |
435 INSN_COND(COND_EQUAL
));
436 tcg_out_nop(s
); /* delay slot */
439 *label3_ptr
|= reassemble_12((uint32_t *)s
->code_ptr
- label3_ptr
- 2);
442 #if TARGET_LONG_BITS == 32
443 tcg_out_mov(s
, TCG_REG_R26
, addr_reg
);
444 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_R25
, mem_index
);
446 tcg_out_mov(s
, TCG_REG_R26
, addr_reg
);
447 tcg_out_mov(s
, TCG_REG_R25
, addr_reg2
);
448 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_R24
, mem_index
);
451 tcg_out_call(s
, qemu_ld_helpers
[s_bits
]);
455 tcg_out_ext8s(s
, data_reg
, TCG_REG_RET0
);
458 tcg_out_ext16s(s
, data_reg
, TCG_REG_RET0
);
464 tcg_out_mov(s
, data_reg
, TCG_REG_RET0
);
468 tcg_out_mov(s
, data_reg
, TCG_REG_RET0
);
469 tcg_out_mov(s
, data_reg2
, TCG_REG_RET1
);
474 label2_ptr
= (uint32_t *)s
->code_ptr
;
475 tcg_out32(s
, BL
| INSN_R2(TCG_REG_R0
) | 2);
478 *label1_ptr
|= reassemble_12((uint32_t *)s
->code_ptr
- label1_ptr
- 2);
480 tcg_out_arithi(s
, TCG_REG_R20
, r1
,
481 offsetof(CPUTLBEntry
, addend
) - offsetof(CPUTLBEntry
, addr_read
),
483 tcg_out_ldst(s
, TCG_REG_R20
, TCG_REG_R20
, 0, LDW
);
484 tcg_out_arith(s
, r0
, r0
, TCG_REG_R20
, ARITH_ADD
);
489 #ifdef TARGET_WORDS_BIGENDIAN
496 tcg_out_ldst(s
, data_reg
, r0
, 0, LDB
);
499 tcg_out_ldst(s
, data_reg
, r0
, 0, LDB
);
500 tcg_out_ext8s(s
, data_reg
, data_reg
);
503 tcg_out_ldst(s
, data_reg
, r0
, 0, LDH
);
505 tcg_out_bswap16(s
, data_reg
, data_reg
);
508 tcg_out_ldst(s
, data_reg
, r0
, 0, LDH
);
510 tcg_out_bswap16(s
, data_reg
, data_reg
);
511 tcg_out_ext16s(s
, data_reg
, data_reg
);
514 tcg_out_ldst(s
, data_reg
, r0
, 0, LDW
);
516 tcg_out_bswap32(s
, data_reg
, data_reg
, TCG_REG_R20
);
521 tcg_out_ldst(s
, data_reg
, r0
, 0, LDW
);
522 tcg_out_ldst(s
, data_reg2
, r0
, 4, LDW
);
524 tcg_out_ldst(s
, data_reg
, r0
, 4, LDW
);
525 tcg_out_bswap32(s
, data_reg
, data_reg
, TCG_REG_R20
);
526 tcg_out_ldst(s
, data_reg2
, r0
, 0, LDW
);
527 tcg_out_bswap32(s
, data_reg2
, data_reg2
, TCG_REG_R20
);
534 #if defined(CONFIG_SOFTMMU)
536 *label2_ptr
|= reassemble_17((uint32_t *)s
->code_ptr
- label2_ptr
- 2);
540 static void tcg_out_qemu_st(TCGContext
*s
, const TCGArg
*args
, int opc
)
542 int addr_reg
, data_reg
, data_reg2
, r0
, r1
, mem_index
, s_bits
, bswap
;
543 #if defined(CONFIG_SOFTMMU)
544 uint32_t *label1_ptr
, *label2_ptr
;
546 #if TARGET_LONG_BITS == 64
547 #if defined(CONFIG_SOFTMMU)
548 uint32_t *label3_ptr
;
557 data_reg2
= 0; /* suppress warning */
559 #if TARGET_LONG_BITS == 64
569 #if defined(CONFIG_SOFTMMU)
570 tcg_out_mov(s
, r1
, addr_reg
);
572 tcg_out_mov(s
, r0
, addr_reg
);
574 tcg_out32(s
, SHD
| INSN_T(r1
) | INSN_R1(TCG_REG_R0
) | INSN_R2(r1
) |
575 INSN_SHDEP_CP(TARGET_PAGE_BITS
- CPU_TLB_ENTRY_BITS
));
577 tcg_out_arithi(s
, r0
, r0
, TARGET_PAGE_MASK
| ((1 << s_bits
) - 1),
580 tcg_out_arithi(s
, r1
, r1
, (CPU_TLB_SIZE
- 1) << CPU_TLB_ENTRY_BITS
,
583 tcg_out_arith(s
, r1
, r1
, TCG_AREG0
, ARITH_ADD
);
584 tcg_out_arithi(s
, r1
, r1
,
585 offsetof(CPUState
, tlb_table
[mem_index
][0].addr_write
),
588 tcg_out_ldst(s
, TCG_REG_R20
, r1
, 0, LDW
);
590 #if TARGET_LONG_BITS == 32
591 /* if equal, jump to label1 */
592 label1_ptr
= (uint32_t *)s
->code_ptr
;
593 tcg_out32(s
, COMBT
| INSN_R1(TCG_REG_R20
) | INSN_R2(r0
) |
594 INSN_COND(COND_EQUAL
));
595 tcg_out_mov(s
, r0
, addr_reg
); /* delay slot */
597 /* if not equal, jump to label3 */
598 label3_ptr
= (uint32_t *)s
->code_ptr
;
599 tcg_out32(s
, COMBF
| INSN_R1(TCG_REG_R20
) | INSN_R2(r0
) |
600 INSN_COND(COND_EQUAL
));
601 tcg_out_mov(s
, r0
, addr_reg
); /* delay slot */
603 tcg_out_ldst(s
, TCG_REG_R20
, r1
, 4, LDW
);
605 /* if equal, jump to label1 */
606 label1_ptr
= (uint32_t *)s
->code_ptr
;
607 tcg_out32(s
, COMBT
| INSN_R1(TCG_REG_R20
) | INSN_R2(addr_reg2
) |
608 INSN_COND(COND_EQUAL
));
609 tcg_out_nop(s
); /* delay slot */
612 *label3_ptr
|= reassemble_12((uint32_t *)s
->code_ptr
- label3_ptr
- 2);
615 tcg_out_mov(s
, TCG_REG_R26
, addr_reg
);
616 #if TARGET_LONG_BITS == 64
617 tcg_out_mov(s
, TCG_REG_R25
, addr_reg2
);
620 tcg_out_mov(s
, TCG_REG_R24
, data_reg
);
621 tcg_out_mov(s
, TCG_REG_R23
, data_reg2
);
622 /* TODO: push mem_index */
627 tcg_out32(s
, EXTRU
| INSN_R1(TCG_REG_R24
) | INSN_R2(data_reg
) |
628 INSN_SHDEP_P(31) | INSN_DEP_LEN(8));
631 tcg_out32(s
, EXTRU
| INSN_R1(TCG_REG_R24
) | INSN_R2(data_reg
) |
632 INSN_SHDEP_P(31) | INSN_DEP_LEN(16));
635 tcg_out_mov(s
, TCG_REG_R24
, data_reg
);
638 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_R23
, mem_index
);
643 tcg_out_mov(s
, TCG_REG_R25
, data_reg
);
644 tcg_out_mov(s
, TCG_REG_R24
, data_reg2
);
645 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_R23
, mem_index
);
649 tcg_out32(s
, EXTRU
| INSN_R1(TCG_REG_R25
) | INSN_R2(data_reg
) |
650 INSN_SHDEP_P(31) | INSN_DEP_LEN(8));
653 tcg_out32(s
, EXTRU
| INSN_R1(TCG_REG_R25
) | INSN_R2(data_reg
) |
654 INSN_SHDEP_P(31) | INSN_DEP_LEN(16));
657 tcg_out_mov(s
, TCG_REG_R25
, data_reg
);
660 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_R24
, mem_index
);
663 tcg_out_call(s
, qemu_st_helpers
[s_bits
]);
666 label2_ptr
= (uint32_t *)s
->code_ptr
;
667 tcg_out32(s
, BL
| INSN_R2(TCG_REG_R0
) | 2);
670 *label1_ptr
|= reassemble_12((uint32_t *)s
->code_ptr
- label1_ptr
- 2);
672 tcg_out_arithi(s
, TCG_REG_R20
, r1
,
673 offsetof(CPUTLBEntry
, addend
) - offsetof(CPUTLBEntry
, addr_write
),
675 tcg_out_ldst(s
, TCG_REG_R20
, TCG_REG_R20
, 0, LDW
);
676 tcg_out_arith(s
, r0
, r0
, TCG_REG_R20
, ARITH_ADD
);
681 #ifdef TARGET_WORDS_BIGENDIAN
688 tcg_out_ldst(s
, data_reg
, r0
, 0, STB
);
692 tcg_out_bswap16(s
, TCG_REG_R20
, data_reg
);
693 data_reg
= TCG_REG_R20
;
695 tcg_out_ldst(s
, data_reg
, r0
, 0, STH
);
699 tcg_out_bswap32(s
, TCG_REG_R20
, data_reg
, TCG_REG_R20
);
700 data_reg
= TCG_REG_R20
;
702 tcg_out_ldst(s
, data_reg
, r0
, 0, STW
);
707 tcg_out_ldst(s
, data_reg
, r0
, 0, STW
);
708 tcg_out_ldst(s
, data_reg2
, r0
, 4, STW
);
710 tcg_out_bswap32(s
, TCG_REG_R20
, data_reg
, TCG_REG_R20
);
711 tcg_out_ldst(s
, TCG_REG_R20
, r0
, 4, STW
);
712 tcg_out_bswap32(s
, TCG_REG_R20
, data_reg2
, TCG_REG_R20
);
713 tcg_out_ldst(s
, TCG_REG_R20
, r0
, 0, STW
);
720 #if defined(CONFIG_SOFTMMU)
722 *label2_ptr
|= reassemble_17((uint32_t *)s
->code_ptr
- label2_ptr
- 2);
726 static inline void tcg_out_op(TCGContext
*s
, int opc
, const TCGArg
*args
,
727 const int *const_args
)
732 case INDEX_op_exit_tb
:
733 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_RET0
, args
[0]);
734 tcg_out32(s
, BV_N
| INSN_R2(TCG_REG_R18
));
736 case INDEX_op_goto_tb
:
737 if (s
->tb_jmp_offset
) {
738 /* direct jump method */
739 fprintf(stderr
, "goto_tb direct\n");
741 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_R20
, args
[0]);
742 tcg_out32(s
, BV_N
| INSN_R2(TCG_REG_R20
));
743 s
->tb_jmp_offset
[args
[0]] = s
->code_ptr
- s
->code_buf
;
745 /* indirect jump method */
746 tcg_out_ld_ptr(s
, TCG_REG_R20
,
747 (tcg_target_long
)(s
->tb_next
+ args
[0]));
748 tcg_out32(s
, BV_N
| INSN_R2(TCG_REG_R20
));
750 s
->tb_next_offset
[args
[0]] = s
->code_ptr
- s
->code_buf
;
753 tcg_out32(s
, BLE_SR4
| INSN_R2(args
[0]));
754 tcg_out_mov(s
, TCG_REG_RP
, TCG_REG_R31
);
757 fprintf(stderr
, "unimplemented jmp\n");
761 fprintf(stderr
, "unimplemented br\n");
764 case INDEX_op_movi_i32
:
765 tcg_out_movi(s
, TCG_TYPE_I32
, args
[0], (uint32_t)args
[1]);
768 case INDEX_op_ld8u_i32
:
769 tcg_out_ldst(s
, args
[0], args
[1], args
[2], LDB
);
771 case INDEX_op_ld8s_i32
:
772 tcg_out_ldst(s
, args
[0], args
[1], args
[2], LDB
);
773 tcg_out_ext8s(s
, args
[0], args
[0]);
775 case INDEX_op_ld16u_i32
:
776 tcg_out_ldst(s
, args
[0], args
[1], args
[2], LDH
);
778 case INDEX_op_ld16s_i32
:
779 tcg_out_ldst(s
, args
[0], args
[1], args
[2], LDH
);
780 tcg_out_ext16s(s
, args
[0], args
[0]);
782 case INDEX_op_ld_i32
:
783 tcg_out_ldst(s
, args
[0], args
[1], args
[2], LDW
);
786 case INDEX_op_st8_i32
:
787 tcg_out_ldst(s
, args
[0], args
[1], args
[2], STB
);
789 case INDEX_op_st16_i32
:
790 tcg_out_ldst(s
, args
[0], args
[1], args
[2], STH
);
792 case INDEX_op_st_i32
:
793 tcg_out_ldst(s
, args
[0], args
[1], args
[2], STW
);
796 case INDEX_op_sub_i32
:
799 case INDEX_op_and_i32
:
802 case INDEX_op_or_i32
:
805 case INDEX_op_xor_i32
:
808 case INDEX_op_add_i32
:
812 case INDEX_op_shl_i32
:
813 tcg_out32(s
, SUBI
| INSN_R1(TCG_REG_R20
) | INSN_R2(args
[2]) |
814 lowsignext(0x1f, 0, 11));
815 tcg_out32(s
, MTCTL
| INSN_R2(11) | INSN_R1(TCG_REG_R20
));
816 tcg_out32(s
, ZVDEP
| INSN_R2(args
[0]) | INSN_R1(args
[1]) |
819 case INDEX_op_shr_i32
:
820 tcg_out32(s
, MTCTL
| INSN_R2(11) | INSN_R1(args
[2]));
821 tcg_out32(s
, VSHD
| INSN_T(args
[0]) | INSN_R1(TCG_REG_R0
) |
824 case INDEX_op_sar_i32
:
825 tcg_out32(s
, SUBI
| INSN_R1(TCG_REG_R20
) | INSN_R2(args
[2]) |
826 lowsignext(0x1f, 0, 11));
827 tcg_out32(s
, MTCTL
| INSN_R2(11) | INSN_R1(TCG_REG_R20
));
828 tcg_out32(s
, VEXTRS
| INSN_R1(args
[0]) | INSN_R2(args
[1]) |
832 case INDEX_op_mul_i32
:
833 fprintf(stderr
, "unimplemented mul\n");
836 case INDEX_op_mulu2_i32
:
837 fprintf(stderr
, "unimplemented mulu2\n");
840 case INDEX_op_div2_i32
:
841 fprintf(stderr
, "unimplemented div2\n");
844 case INDEX_op_divu2_i32
:
845 fprintf(stderr
, "unimplemented divu2\n");
849 case INDEX_op_brcond_i32
:
850 fprintf(stderr
, "unimplemented brcond\n");
854 case INDEX_op_qemu_ld8u
:
855 tcg_out_qemu_ld(s
, args
, 0);
857 case INDEX_op_qemu_ld8s
:
858 tcg_out_qemu_ld(s
, args
, 0 | 4);
860 case INDEX_op_qemu_ld16u
:
861 tcg_out_qemu_ld(s
, args
, 1);
863 case INDEX_op_qemu_ld16s
:
864 tcg_out_qemu_ld(s
, args
, 1 | 4);
866 case INDEX_op_qemu_ld32u
:
867 tcg_out_qemu_ld(s
, args
, 2);
870 case INDEX_op_qemu_st8
:
871 tcg_out_qemu_st(s
, args
, 0);
873 case INDEX_op_qemu_st16
:
874 tcg_out_qemu_st(s
, args
, 1);
876 case INDEX_op_qemu_st32
:
877 tcg_out_qemu_st(s
, args
, 2);
881 fprintf(stderr
, "unknown opcode 0x%x\n", opc
);
887 tcg_out_arith(s
, args
[0], args
[1], args
[2], c
);
890 static const TCGTargetOpDef hppa_op_defs
[] = {
891 { INDEX_op_exit_tb
, { } },
892 { INDEX_op_goto_tb
, { } },
894 { INDEX_op_call
, { "r" } },
895 { INDEX_op_jmp
, { "r" } },
896 { INDEX_op_br
, { } },
898 { INDEX_op_mov_i32
, { "r", "r" } },
899 { INDEX_op_movi_i32
, { "r" } },
900 { INDEX_op_ld8u_i32
, { "r", "r" } },
901 { INDEX_op_ld8s_i32
, { "r", "r" } },
902 { INDEX_op_ld16u_i32
, { "r", "r" } },
903 { INDEX_op_ld16s_i32
, { "r", "r" } },
904 { INDEX_op_ld_i32
, { "r", "r" } },
905 { INDEX_op_st8_i32
, { "r", "r" } },
906 { INDEX_op_st16_i32
, { "r", "r" } },
907 { INDEX_op_st_i32
, { "r", "r" } },
909 { INDEX_op_add_i32
, { "r", "r", "r" } },
910 { INDEX_op_sub_i32
, { "r", "r", "r" } },
911 { INDEX_op_and_i32
, { "r", "r", "r" } },
912 { INDEX_op_or_i32
, { "r", "r", "r" } },
913 { INDEX_op_xor_i32
, { "r", "r", "r" } },
915 { INDEX_op_shl_i32
, { "r", "r", "r" } },
916 { INDEX_op_shr_i32
, { "r", "r", "r" } },
917 { INDEX_op_sar_i32
, { "r", "r", "r" } },
919 { INDEX_op_brcond_i32
, { "r", "r" } },
921 #if TARGET_LONG_BITS == 32
922 { INDEX_op_qemu_ld8u
, { "r", "L" } },
923 { INDEX_op_qemu_ld8s
, { "r", "L" } },
924 { INDEX_op_qemu_ld16u
, { "r", "L" } },
925 { INDEX_op_qemu_ld16s
, { "r", "L" } },
926 { INDEX_op_qemu_ld32u
, { "r", "L" } },
927 { INDEX_op_qemu_ld64
, { "r", "r", "L" } },
929 { INDEX_op_qemu_st8
, { "L", "L" } },
930 { INDEX_op_qemu_st16
, { "L", "L" } },
931 { INDEX_op_qemu_st32
, { "L", "L" } },
932 { INDEX_op_qemu_st64
, { "L", "L", "L" } },
934 { INDEX_op_qemu_ld8u
, { "r", "L", "L" } },
935 { INDEX_op_qemu_ld8s
, { "r", "L", "L" } },
936 { INDEX_op_qemu_ld16u
, { "r", "L", "L" } },
937 { INDEX_op_qemu_ld16s
, { "r", "L", "L" } },
938 { INDEX_op_qemu_ld32u
, { "r", "L", "L" } },
939 { INDEX_op_qemu_ld32s
, { "r", "L", "L" } },
940 { INDEX_op_qemu_ld64
, { "r", "r", "L", "L" } },
942 { INDEX_op_qemu_st8
, { "L", "L", "L" } },
943 { INDEX_op_qemu_st16
, { "L", "L", "L" } },
944 { INDEX_op_qemu_st32
, { "L", "L", "L" } },
945 { INDEX_op_qemu_st64
, { "L", "L", "L", "L" } },
950 void tcg_target_init(TCGContext
*s
)
952 tcg_regset_set32(tcg_target_available_regs
[TCG_TYPE_I32
], 0, 0xffffffff);
953 tcg_regset_set32(tcg_target_call_clobber_regs
, 0,
962 tcg_regset_clear(s
->reserved_regs
);
963 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_R0
); /* hardwired to zero */
964 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_R1
); /* addil target */
965 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_RP
); /* link register */
966 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_R3
); /* frame pointer */
967 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_R18
); /* return pointer */
968 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_R19
); /* clobbered w/o pic */
969 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_R20
); /* reserved */
970 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_DP
); /* data pointer */
971 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_SP
); /* stack pointer */
972 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_R31
); /* ble link reg */
974 tcg_add_target_add_op_defs(hppa_op_defs
);