ne2000_isa: make optional
[qemu/lumag.git] / tcg / mips / tcg-target.c
blobe04b0dc32f373d021cc6fe58132de66c0dbcb235
1 /*
2 * Tiny Code Generator for QEMU
4 * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
5 * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
6 * Based on i386/tcg-target.c - Copyright (c) 2008 Fabrice Bellard
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
27 #if defined(TCG_TARGET_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
28 # define TCG_NEED_BSWAP 0
29 #else
30 # define TCG_NEED_BSWAP 1
31 #endif
33 #ifndef NDEBUG
34 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
35 "zero",
36 "at",
37 "v0",
38 "v1",
39 "a0",
40 "a1",
41 "a2",
42 "a3",
43 "t0",
44 "t1",
45 "t2",
46 "t3",
47 "t4",
48 "t5",
49 "t6",
50 "t7",
51 "s0",
52 "s1",
53 "s2",
54 "s3",
55 "s4",
56 "s5",
57 "s6",
58 "s7",
59 "t8",
60 "t9",
61 "k0",
62 "k1",
63 "gp",
64 "sp",
65 "fp",
66 "ra",
68 #endif
70 /* check if we really need so many registers :P */
71 static const int tcg_target_reg_alloc_order[] = {
72 TCG_REG_S0,
73 TCG_REG_S1,
74 TCG_REG_S2,
75 TCG_REG_S3,
76 TCG_REG_S4,
77 TCG_REG_S5,
78 TCG_REG_S6,
79 TCG_REG_S7,
80 TCG_REG_T1,
81 TCG_REG_T2,
82 TCG_REG_T3,
83 TCG_REG_T4,
84 TCG_REG_T5,
85 TCG_REG_T6,
86 TCG_REG_T7,
87 TCG_REG_T8,
88 TCG_REG_T9,
89 TCG_REG_A0,
90 TCG_REG_A1,
91 TCG_REG_A2,
92 TCG_REG_A3,
93 TCG_REG_V0,
94 TCG_REG_V1
97 static const int tcg_target_call_iarg_regs[4] = {
98 TCG_REG_A0,
99 TCG_REG_A1,
100 TCG_REG_A2,
101 TCG_REG_A3
104 static const int tcg_target_call_oarg_regs[2] = {
105 TCG_REG_V0,
106 TCG_REG_V1
109 static uint8_t *tb_ret_addr;
111 static inline uint32_t reloc_lo16_val (void *pc, tcg_target_long target)
113 return target & 0xffff;
116 static inline void reloc_lo16 (void *pc, tcg_target_long target)
118 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
119 | reloc_lo16_val(pc, target);
122 static inline uint32_t reloc_hi16_val (void *pc, tcg_target_long target)
124 return (target >> 16) & 0xffff;
127 static inline void reloc_hi16 (void *pc, tcg_target_long target)
129 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
130 | reloc_hi16_val(pc, target);
133 static inline uint32_t reloc_pc16_val (void *pc, tcg_target_long target)
135 int32_t disp;
137 disp = target - (tcg_target_long) pc - 4;
138 if (disp != (disp << 14) >> 14) {
139 tcg_abort ();
142 return (disp >> 2) & 0xffff;
145 static inline void reloc_pc16 (void *pc, tcg_target_long target)
147 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
148 | reloc_pc16_val(pc, target);
151 static inline uint32_t reloc_26_val (void *pc, tcg_target_long target)
153 if ((((tcg_target_long)pc + 4) & 0xf0000000) != (target & 0xf0000000)) {
154 tcg_abort ();
157 return (target >> 2) & 0x3ffffff;
160 static inline void reloc_pc26 (void *pc, tcg_target_long target)
162 *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3ffffff)
163 | reloc_26_val(pc, target);
166 static void patch_reloc(uint8_t *code_ptr, int type,
167 tcg_target_long value, tcg_target_long addend)
169 value += addend;
170 switch(type) {
171 case R_MIPS_LO16:
172 reloc_lo16(code_ptr, value);
173 break;
174 case R_MIPS_HI16:
175 reloc_hi16(code_ptr, value);
176 break;
177 case R_MIPS_PC16:
178 reloc_pc16(code_ptr, value);
179 break;
180 case R_MIPS_26:
181 reloc_pc26(code_ptr, value);
182 break;
183 default:
184 tcg_abort();
188 /* maximum number of register used for input function arguments */
189 static inline int tcg_target_get_call_iarg_regs_count(int flags)
191 return 4;
194 /* parse target specific constraints */
195 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
197 const char *ct_str;
199 ct_str = *pct_str;
200 switch(ct_str[0]) {
201 case 'r':
202 ct->ct |= TCG_CT_REG;
203 tcg_regset_set(ct->u.regs, 0xffffffff);
204 break;
205 case 'C':
206 ct->ct |= TCG_CT_REG;
207 tcg_regset_clear(ct->u.regs);
208 tcg_regset_set_reg(ct->u.regs, TCG_REG_T9);
209 break;
210 case 'L': /* qemu_ld output arg constraint */
211 ct->ct |= TCG_CT_REG;
212 tcg_regset_set(ct->u.regs, 0xffffffff);
213 tcg_regset_reset_reg(ct->u.regs, TCG_REG_V0);
214 break;
215 case 'l': /* qemu_ld input arg constraint */
216 ct->ct |= TCG_CT_REG;
217 tcg_regset_set(ct->u.regs, 0xffffffff);
218 #if defined(CONFIG_SOFTMMU)
219 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
220 #endif
221 break;
222 case 'S': /* qemu_st constraint */
223 ct->ct |= TCG_CT_REG;
224 tcg_regset_set(ct->u.regs, 0xffffffff);
225 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
226 #if defined(CONFIG_SOFTMMU)
227 # if TARGET_LONG_BITS == 64
228 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
229 # endif
230 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
231 #endif
232 break;
233 case 'I':
234 ct->ct |= TCG_CT_CONST_U16;
235 break;
236 case 'J':
237 ct->ct |= TCG_CT_CONST_S16;
238 break;
239 case 'Z':
240 /* We are cheating a bit here, using the fact that the register
241 ZERO is also the register number 0. Hence there is no need
242 to check for const_args in each instruction. */
243 ct->ct |= TCG_CT_CONST_ZERO;
244 break;
245 default:
246 return -1;
248 ct_str++;
249 *pct_str = ct_str;
250 return 0;
253 /* test if a constant matches the constraint */
254 static inline int tcg_target_const_match(tcg_target_long val,
255 const TCGArgConstraint *arg_ct)
257 int ct;
258 ct = arg_ct->ct;
259 if (ct & TCG_CT_CONST)
260 return 1;
261 else if ((ct & TCG_CT_CONST_ZERO) && val == 0)
262 return 1;
263 else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val)
264 return 1;
265 else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val)
266 return 1;
267 else
268 return 0;
271 /* instruction opcodes */
272 enum {
273 OPC_BEQ = 0x04 << 26,
274 OPC_BNE = 0x05 << 26,
275 OPC_ADDIU = 0x09 << 26,
276 OPC_SLTI = 0x0A << 26,
277 OPC_SLTIU = 0x0B << 26,
278 OPC_ANDI = 0x0C << 26,
279 OPC_ORI = 0x0D << 26,
280 OPC_XORI = 0x0E << 26,
281 OPC_LUI = 0x0F << 26,
282 OPC_LB = 0x20 << 26,
283 OPC_LH = 0x21 << 26,
284 OPC_LW = 0x23 << 26,
285 OPC_LBU = 0x24 << 26,
286 OPC_LHU = 0x25 << 26,
287 OPC_LWU = 0x27 << 26,
288 OPC_SB = 0x28 << 26,
289 OPC_SH = 0x29 << 26,
290 OPC_SW = 0x2B << 26,
292 OPC_SPECIAL = 0x00 << 26,
293 OPC_SLL = OPC_SPECIAL | 0x00,
294 OPC_SRL = OPC_SPECIAL | 0x02,
295 OPC_SRA = OPC_SPECIAL | 0x03,
296 OPC_SLLV = OPC_SPECIAL | 0x04,
297 OPC_SRLV = OPC_SPECIAL | 0x06,
298 OPC_SRAV = OPC_SPECIAL | 0x07,
299 OPC_JR = OPC_SPECIAL | 0x08,
300 OPC_JALR = OPC_SPECIAL | 0x09,
301 OPC_MFHI = OPC_SPECIAL | 0x10,
302 OPC_MFLO = OPC_SPECIAL | 0x12,
303 OPC_MULT = OPC_SPECIAL | 0x18,
304 OPC_MULTU = OPC_SPECIAL | 0x19,
305 OPC_DIV = OPC_SPECIAL | 0x1A,
306 OPC_DIVU = OPC_SPECIAL | 0x1B,
307 OPC_ADDU = OPC_SPECIAL | 0x21,
308 OPC_SUBU = OPC_SPECIAL | 0x23,
309 OPC_AND = OPC_SPECIAL | 0x24,
310 OPC_OR = OPC_SPECIAL | 0x25,
311 OPC_XOR = OPC_SPECIAL | 0x26,
312 OPC_NOR = OPC_SPECIAL | 0x27,
313 OPC_SLT = OPC_SPECIAL | 0x2A,
314 OPC_SLTU = OPC_SPECIAL | 0x2B,
316 OPC_SPECIAL3 = 0x1f << 26,
317 OPC_SEB = OPC_SPECIAL3 | 0x420,
318 OPC_SEH = OPC_SPECIAL3 | 0x620,
322 * Type reg
324 static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int rt)
326 int32_t inst;
328 inst = opc;
329 inst |= (rs & 0x1F) << 21;
330 inst |= (rt & 0x1F) << 16;
331 inst |= (rd & 0x1F) << 11;
332 tcg_out32(s, inst);
336 * Type immediate
338 static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int imm)
340 int32_t inst;
342 inst = opc;
343 inst |= (rs & 0x1F) << 21;
344 inst |= (rt & 0x1F) << 16;
345 inst |= (imm & 0xffff);
346 tcg_out32(s, inst);
350 * Type branch
352 static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
354 /* We pay attention here to not modify the branch target by reading
355 the existing value and using it again. This ensure that caches and
356 memory are kept coherent during retranslation. */
357 uint16_t offset = (uint16_t)(*(uint32_t *) s->code_ptr);
359 tcg_out_opc_imm(s, opc, rt, rs, offset);
363 * Type sa
365 static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa)
367 int32_t inst;
369 inst = opc;
370 inst |= (rt & 0x1F) << 16;
371 inst |= (rd & 0x1F) << 11;
372 inst |= (sa & 0x1F) << 6;
373 tcg_out32(s, inst);
377 static inline void tcg_out_nop(TCGContext *s)
379 tcg_out32(s, 0);
382 static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
384 tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
387 static inline void tcg_out_movi(TCGContext *s, TCGType type,
388 int reg, int32_t arg)
390 if (arg == (int16_t)arg) {
391 tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
392 } else if (arg == (uint16_t)arg) {
393 tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
394 } else {
395 tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
396 tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
400 static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
402 /* ret and arg can't be register at */
403 if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
404 tcg_abort();
407 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
408 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
410 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
411 tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
412 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
415 static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
417 /* ret and arg can't be register at */
418 if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
419 tcg_abort();
422 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
423 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
425 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
426 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
427 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
430 static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
432 /* ret and arg must be different and can't be register at */
433 if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
434 tcg_abort();
437 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
439 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
440 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
442 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
443 tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
444 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
446 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
447 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
448 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
451 static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg)
453 #ifdef _MIPS_ARCH_MIPS32R2
454 tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
455 #else
456 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
457 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24);
458 #endif
461 static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg)
463 #ifdef _MIPS_ARCH_MIPS32R2
464 tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
465 #else
466 tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
467 tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
468 #endif
471 static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
472 int arg1, tcg_target_long arg2)
474 if (arg2 == (int16_t) arg2) {
475 tcg_out_opc_imm(s, opc, arg, arg1, arg2);
476 } else {
477 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
478 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
479 tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
483 static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
484 int arg1, tcg_target_long arg2)
486 tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
489 static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
490 int arg1, tcg_target_long arg2)
492 tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
495 static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
497 if (val == (int16_t)val) {
498 tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
499 } else {
500 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
501 tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
505 static void tcg_out_brcond(TCGContext *s, TCGCond cond, int arg1,
506 int arg2, int label_index)
508 TCGLabel *l = &s->labels[label_index];
510 switch (cond) {
511 case TCG_COND_EQ:
512 tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
513 break;
514 case TCG_COND_NE:
515 tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
516 break;
517 case TCG_COND_LT:
518 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
519 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
520 break;
521 case TCG_COND_LTU:
522 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
523 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
524 break;
525 case TCG_COND_GE:
526 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
527 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
528 break;
529 case TCG_COND_GEU:
530 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
531 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
532 break;
533 case TCG_COND_LE:
534 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
535 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
536 break;
537 case TCG_COND_LEU:
538 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
539 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
540 break;
541 case TCG_COND_GT:
542 tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
543 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
544 break;
545 case TCG_COND_GTU:
546 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
547 tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
548 break;
549 default:
550 tcg_abort();
551 break;
553 if (l->has_value) {
554 reloc_pc16(s->code_ptr - 4, l->u.value);
555 } else {
556 tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
558 tcg_out_nop(s);
561 /* XXX: we implement it at the target level to avoid having to
562 handle cross basic blocks temporaries */
563 static void tcg_out_brcond2(TCGContext *s, TCGCond cond, int arg1,
564 int arg2, int arg3, int arg4, int label_index)
566 void *label_ptr;
568 switch(cond) {
569 case TCG_COND_NE:
570 tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
571 tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
572 return;
573 case TCG_COND_EQ:
574 break;
575 case TCG_COND_LT:
576 case TCG_COND_LE:
577 tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
578 break;
579 case TCG_COND_GT:
580 case TCG_COND_GE:
581 tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
582 break;
583 case TCG_COND_LTU:
584 case TCG_COND_LEU:
585 tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
586 break;
587 case TCG_COND_GTU:
588 case TCG_COND_GEU:
589 tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
590 break;
591 default:
592 tcg_abort();
595 label_ptr = s->code_ptr;
596 tcg_out_opc_br(s, OPC_BNE, arg2, arg4);
597 tcg_out_nop(s);
599 switch(cond) {
600 case TCG_COND_EQ:
601 tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
602 break;
603 case TCG_COND_LT:
604 case TCG_COND_LTU:
605 tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
606 break;
607 case TCG_COND_LE:
608 case TCG_COND_LEU:
609 tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
610 break;
611 case TCG_COND_GT:
612 case TCG_COND_GTU:
613 tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
614 break;
615 case TCG_COND_GE:
616 case TCG_COND_GEU:
617 tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
618 break;
619 default:
620 tcg_abort();
623 reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
626 static void tcg_out_setcond(TCGContext *s, TCGCond cond, int ret,
627 int arg1, int arg2)
629 switch (cond) {
630 case TCG_COND_EQ:
631 if (arg1 == 0) {
632 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg2, 1);
633 } else if (arg2 == 0) {
634 tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
635 } else {
636 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
637 tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
639 break;
640 case TCG_COND_NE:
641 if (arg1 == 0) {
642 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg2);
643 } else if (arg2 == 0) {
644 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
645 } else {
646 tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
647 tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
649 break;
650 case TCG_COND_LT:
651 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
652 break;
653 case TCG_COND_LTU:
654 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
655 break;
656 case TCG_COND_GE:
657 tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
658 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
659 break;
660 case TCG_COND_GEU:
661 tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
662 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
663 break;
664 case TCG_COND_LE:
665 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
666 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
667 break;
668 case TCG_COND_LEU:
669 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
670 tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
671 break;
672 case TCG_COND_GT:
673 tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
674 break;
675 case TCG_COND_GTU:
676 tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
677 break;
678 default:
679 tcg_abort();
680 break;
684 /* XXX: we implement it at the target level to avoid having to
685 handle cross basic blocks temporaries */
686 static void tcg_out_setcond2(TCGContext *s, TCGCond cond, int ret,
687 int arg1, int arg2, int arg3, int arg4)
689 switch (cond) {
690 case TCG_COND_EQ:
691 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_AT, arg2, arg4);
692 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg1, arg3);
693 tcg_out_opc_reg(s, OPC_AND, ret, TCG_REG_AT, TCG_REG_T0);
694 return;
695 case TCG_COND_NE:
696 tcg_out_setcond(s, TCG_COND_NE, TCG_REG_AT, arg2, arg4);
697 tcg_out_setcond(s, TCG_COND_NE, TCG_REG_T0, arg1, arg3);
698 tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_AT, TCG_REG_T0);
699 return;
700 case TCG_COND_LT:
701 case TCG_COND_LE:
702 tcg_out_setcond(s, TCG_COND_LT, TCG_REG_AT, arg2, arg4);
703 break;
704 case TCG_COND_GT:
705 case TCG_COND_GE:
706 tcg_out_setcond(s, TCG_COND_GT, TCG_REG_AT, arg2, arg4);
707 break;
708 case TCG_COND_LTU:
709 case TCG_COND_LEU:
710 tcg_out_setcond(s, TCG_COND_LTU, TCG_REG_AT, arg2, arg4);
711 break;
712 case TCG_COND_GTU:
713 case TCG_COND_GEU:
714 tcg_out_setcond(s, TCG_COND_GTU, TCG_REG_AT, arg2, arg4);
715 break;
716 default:
717 tcg_abort();
718 break;
721 tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg2, arg4);
723 switch(cond) {
724 case TCG_COND_LT:
725 case TCG_COND_LTU:
726 tcg_out_setcond(s, TCG_COND_LTU, ret, arg1, arg3);
727 break;
728 case TCG_COND_LE:
729 case TCG_COND_LEU:
730 tcg_out_setcond(s, TCG_COND_LEU, ret, arg1, arg3);
731 break;
732 case TCG_COND_GT:
733 case TCG_COND_GTU:
734 tcg_out_setcond(s, TCG_COND_GTU, ret, arg1, arg3);
735 break;
736 case TCG_COND_GE:
737 case TCG_COND_GEU:
738 tcg_out_setcond(s, TCG_COND_GEU, ret, arg1, arg3);
739 break;
740 default:
741 tcg_abort();
744 tcg_out_opc_reg(s, OPC_AND, ret, ret, TCG_REG_T0);
745 tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
748 #if defined(CONFIG_SOFTMMU)
750 #include "../../softmmu_defs.h"
752 static void *qemu_ld_helpers[4] = {
753 __ldb_mmu,
754 __ldw_mmu,
755 __ldl_mmu,
756 __ldq_mmu,
759 static void *qemu_st_helpers[4] = {
760 __stb_mmu,
761 __stw_mmu,
762 __stl_mmu,
763 __stq_mmu,
765 #endif
767 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
768 int opc)
770 int addr_regl, addr_reg1, addr_meml;
771 int data_regl, data_regh, data_reg1, data_reg2;
772 int mem_index, s_bits;
773 #if defined(CONFIG_SOFTMMU)
774 void *label1_ptr, *label2_ptr;
775 int sp_args;
776 #endif
777 #if TARGET_LONG_BITS == 64
778 # if defined(CONFIG_SOFTMMU)
779 uint8_t *label3_ptr;
780 # endif
781 int addr_regh, addr_reg2, addr_memh;
782 #endif
783 data_regl = *args++;
784 if (opc == 3)
785 data_regh = *args++;
786 else
787 data_regh = 0;
788 addr_regl = *args++;
789 #if TARGET_LONG_BITS == 64
790 addr_regh = *args++;
791 #endif
792 mem_index = *args;
793 s_bits = opc & 3;
795 if (opc == 3) {
796 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
797 data_reg1 = data_regh;
798 data_reg2 = data_regl;
799 #else
800 data_reg1 = data_regl;
801 data_reg2 = data_regh;
802 #endif
803 } else {
804 data_reg1 = data_regl;
805 data_reg2 = 0;
807 #if TARGET_LONG_BITS == 64
808 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
809 addr_reg1 = addr_regh;
810 addr_reg2 = addr_regl;
811 addr_memh = 0;
812 addr_meml = 4;
813 # else
814 addr_reg1 = addr_regl;
815 addr_reg2 = addr_regh;
816 addr_memh = 4;
817 addr_meml = 0;
818 # endif
819 #else
820 addr_reg1 = addr_regl;
821 addr_meml = 0;
822 #endif
824 #if defined(CONFIG_SOFTMMU)
825 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
826 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
827 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
828 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
829 offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_meml);
830 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
831 tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
833 # if TARGET_LONG_BITS == 64
834 label3_ptr = s->code_ptr;
835 tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
836 tcg_out_nop(s);
838 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
839 offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh);
841 label1_ptr = s->code_ptr;
842 tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
843 tcg_out_nop(s);
845 reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
846 # else
847 label1_ptr = s->code_ptr;
848 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
849 tcg_out_nop(s);
850 # endif
852 /* slow path */
853 sp_args = TCG_REG_A0;
854 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
855 # if TARGET_LONG_BITS == 64
856 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
857 # endif
858 tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
859 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
860 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
861 tcg_out_nop(s);
863 switch(opc) {
864 case 0:
865 tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
866 break;
867 case 0 | 4:
868 tcg_out_ext8s(s, data_reg1, TCG_REG_V0);
869 break;
870 case 1:
871 tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
872 break;
873 case 1 | 4:
874 tcg_out_ext16s(s, data_reg1, TCG_REG_V0);
875 break;
876 case 2:
877 tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
878 break;
879 case 3:
880 tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_V1);
881 tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
882 break;
883 default:
884 tcg_abort();
887 label2_ptr = s->code_ptr;
888 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
889 tcg_out_nop(s);
891 /* label1: fast path */
892 reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
894 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
895 offsetof(CPUState, tlb_table[mem_index][0].addend));
896 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
897 #else
898 if (GUEST_BASE == (int16_t)GUEST_BASE) {
899 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_V0, addr_regl, GUEST_BASE);
900 } else {
901 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, GUEST_BASE);
902 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
904 #endif
906 switch(opc) {
907 case 0:
908 tcg_out_opc_imm(s, OPC_LBU, data_reg1, TCG_REG_V0, 0);
909 break;
910 case 0 | 4:
911 tcg_out_opc_imm(s, OPC_LB, data_reg1, TCG_REG_V0, 0);
912 break;
913 case 1:
914 if (TCG_NEED_BSWAP) {
915 tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
916 tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
917 } else {
918 tcg_out_opc_imm(s, OPC_LHU, data_reg1, TCG_REG_V0, 0);
920 break;
921 case 1 | 4:
922 if (TCG_NEED_BSWAP) {
923 tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
924 tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
925 } else {
926 tcg_out_opc_imm(s, OPC_LH, data_reg1, TCG_REG_V0, 0);
928 break;
929 case 2:
930 if (TCG_NEED_BSWAP) {
931 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
932 tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
933 } else {
934 tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
936 break;
937 case 3:
938 if (TCG_NEED_BSWAP) {
939 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 4);
940 tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
941 tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
942 tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
943 } else {
944 tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
945 tcg_out_opc_imm(s, OPC_LW, data_reg2, TCG_REG_V0, 4);
947 break;
948 default:
949 tcg_abort();
952 #if defined(CONFIG_SOFTMMU)
953 reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
954 #endif
957 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
958 int opc)
960 int addr_regl, addr_reg1, addr_meml;
961 int data_regl, data_regh, data_reg1, data_reg2;
962 int mem_index, s_bits;
963 #if defined(CONFIG_SOFTMMU)
964 uint8_t *label1_ptr, *label2_ptr;
965 int sp_args;
966 #endif
967 #if TARGET_LONG_BITS == 64
968 # if defined(CONFIG_SOFTMMU)
969 uint8_t *label3_ptr;
970 # endif
971 int addr_regh, addr_reg2, addr_memh;
972 #endif
974 data_regl = *args++;
975 if (opc == 3) {
976 data_regh = *args++;
977 #if defined(TCG_TARGET_WORDS_BIGENDIAN)
978 data_reg1 = data_regh;
979 data_reg2 = data_regl;
980 #else
981 data_reg1 = data_regl;
982 data_reg2 = data_regh;
983 #endif
984 } else {
985 data_reg1 = data_regl;
986 data_reg2 = 0;
987 data_regh = 0;
989 addr_regl = *args++;
990 #if TARGET_LONG_BITS == 64
991 addr_regh = *args++;
992 # if defined(TCG_TARGET_WORDS_BIGENDIAN)
993 addr_reg1 = addr_regh;
994 addr_reg2 = addr_regl;
995 addr_memh = 0;
996 addr_meml = 4;
997 # else
998 addr_reg1 = addr_regl;
999 addr_reg2 = addr_regh;
1000 addr_memh = 4;
1001 addr_meml = 0;
1002 # endif
1003 #else
1004 addr_reg1 = addr_regl;
1005 addr_meml = 0;
1006 #endif
1007 mem_index = *args;
1008 s_bits = opc;
1010 #if defined(CONFIG_SOFTMMU)
1011 tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1012 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
1013 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
1014 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1015 offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_meml);
1016 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
1017 tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
1019 # if TARGET_LONG_BITS == 64
1020 label3_ptr = s->code_ptr;
1021 tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
1022 tcg_out_nop(s);
1024 tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1025 offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh);
1027 label1_ptr = s->code_ptr;
1028 tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1029 tcg_out_nop(s);
1031 reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
1032 # else
1033 label1_ptr = s->code_ptr;
1034 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1035 tcg_out_nop(s);
1036 # endif
1038 /* slow path */
1039 sp_args = TCG_REG_A0;
1040 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
1041 # if TARGET_LONG_BITS == 64
1042 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
1043 # endif
1044 switch(opc) {
1045 case 0:
1046 tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xff);
1047 break;
1048 case 1:
1049 tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
1050 break;
1051 case 2:
1052 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
1053 break;
1054 case 3:
1055 sp_args = (sp_args + 1) & ~1;
1056 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
1057 tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg2);
1058 break;
1059 default:
1060 tcg_abort();
1062 if (sp_args > TCG_REG_A3) {
1063 /* Push mem_index on the stack */
1064 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, mem_index);
1065 tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 16);
1066 } else {
1067 tcg_out_movi(s, TCG_TYPE_I32, sp_args, mem_index);
1070 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
1071 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1072 tcg_out_nop(s);
1074 label2_ptr = s->code_ptr;
1075 tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1076 tcg_out_nop(s);
1078 /* label1: fast path */
1079 reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
1081 tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1082 offsetof(CPUState, tlb_table[mem_index][0].addend));
1083 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1084 #else
1085 if (GUEST_BASE == (int16_t)GUEST_BASE) {
1086 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, addr_regl, GUEST_BASE);
1087 } else {
1088 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, GUEST_BASE);
1089 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1092 #endif
1094 switch(opc) {
1095 case 0:
1096 tcg_out_opc_imm(s, OPC_SB, data_reg1, TCG_REG_A0, 0);
1097 break;
1098 case 1:
1099 if (TCG_NEED_BSWAP) {
1100 tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
1101 tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, TCG_REG_A0, 0);
1102 } else {
1103 tcg_out_opc_imm(s, OPC_SH, data_reg1, TCG_REG_A0, 0);
1105 break;
1106 case 2:
1107 if (TCG_NEED_BSWAP) {
1108 tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1109 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1110 } else {
1111 tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1113 break;
1114 case 3:
1115 if (TCG_NEED_BSWAP) {
1116 tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
1117 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1118 tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1119 tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 4);
1120 } else {
1121 tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1122 tcg_out_opc_imm(s, OPC_SW, data_reg2, TCG_REG_A0, 4);
1124 break;
1125 default:
1126 tcg_abort();
1129 #if defined(CONFIG_SOFTMMU)
1130 reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1131 #endif
1134 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1135 const TCGArg *args, const int *const_args)
1137 switch(opc) {
1138 case INDEX_op_exit_tb:
1139 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
1140 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
1141 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1142 tcg_out_nop(s);
1143 break;
1144 case INDEX_op_goto_tb:
1145 if (s->tb_jmp_offset) {
1146 /* direct jump method */
1147 tcg_abort();
1148 } else {
1149 /* indirect jump method */
1150 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
1151 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
1152 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1154 tcg_out_nop(s);
1155 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1156 break;
1157 case INDEX_op_call:
1158 tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
1159 tcg_out_nop(s);
1160 break;
1161 case INDEX_op_jmp:
1162 tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
1163 tcg_out_nop(s);
1164 break;
1165 case INDEX_op_br:
1166 tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1167 break;
1169 case INDEX_op_mov_i32:
1170 tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
1171 break;
1172 case INDEX_op_movi_i32:
1173 tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1174 break;
1176 case INDEX_op_ld8u_i32:
1177 tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1178 break;
1179 case INDEX_op_ld8s_i32:
1180 tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1181 break;
1182 case INDEX_op_ld16u_i32:
1183 tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1184 break;
1185 case INDEX_op_ld16s_i32:
1186 tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1187 break;
1188 case INDEX_op_ld_i32:
1189 tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1190 break;
1191 case INDEX_op_st8_i32:
1192 tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1193 break;
1194 case INDEX_op_st16_i32:
1195 tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1196 break;
1197 case INDEX_op_st_i32:
1198 tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1199 break;
1201 case INDEX_op_add_i32:
1202 if (const_args[2]) {
1203 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1204 } else {
1205 tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1207 break;
1208 case INDEX_op_add2_i32:
1209 if (const_args[4]) {
1210 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1211 } else {
1212 tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1214 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1215 if (const_args[5]) {
1216 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1217 } else {
1218 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1220 tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1221 tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1222 break;
1223 case INDEX_op_sub_i32:
1224 if (const_args[2]) {
1225 tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1226 } else {
1227 tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1229 break;
1230 case INDEX_op_sub2_i32:
1231 if (const_args[4]) {
1232 tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1233 } else {
1234 tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1236 tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1237 if (const_args[5]) {
1238 tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1239 } else {
1240 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1242 tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1243 tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1244 break;
1245 case INDEX_op_mul_i32:
1246 tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1247 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1248 break;
1249 case INDEX_op_mulu2_i32:
1250 tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1251 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1252 tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1253 break;
1254 case INDEX_op_div_i32:
1255 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1256 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1257 break;
1258 case INDEX_op_divu_i32:
1259 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1260 tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1261 break;
1262 case INDEX_op_rem_i32:
1263 tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1264 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1265 break;
1266 case INDEX_op_remu_i32:
1267 tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1268 tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1269 break;
1271 case INDEX_op_and_i32:
1272 if (const_args[2]) {
1273 tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1274 } else {
1275 tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1277 break;
1278 case INDEX_op_or_i32:
1279 if (const_args[2]) {
1280 tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1281 } else {
1282 tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1284 break;
1285 case INDEX_op_nor_i32:
1286 tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[2]);
1287 break;
1288 case INDEX_op_not_i32:
1289 tcg_out_opc_reg(s, OPC_NOR, args[0], TCG_REG_ZERO, args[1]);
1290 break;
1291 case INDEX_op_xor_i32:
1292 if (const_args[2]) {
1293 tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1294 } else {
1295 tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1297 break;
1299 case INDEX_op_sar_i32:
1300 if (const_args[2]) {
1301 tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1302 } else {
1303 tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1305 break;
1306 case INDEX_op_shl_i32:
1307 if (const_args[2]) {
1308 tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1309 } else {
1310 tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1312 break;
1313 case INDEX_op_shr_i32:
1314 if (const_args[2]) {
1315 tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1316 } else {
1317 tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1319 break;
1321 case INDEX_op_ext8s_i32:
1322 tcg_out_ext8s(s, args[0], args[1]);
1323 break;
1324 case INDEX_op_ext16s_i32:
1325 tcg_out_ext16s(s, args[0], args[1]);
1326 break;
1328 case INDEX_op_brcond_i32:
1329 tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1330 break;
1331 case INDEX_op_brcond2_i32:
1332 tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1333 break;
1335 case INDEX_op_setcond_i32:
1336 tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
1337 break;
1338 case INDEX_op_setcond2_i32:
1339 tcg_out_setcond2(s, args[5], args[0], args[1], args[2], args[3], args[4]);
1340 break;
1342 case INDEX_op_qemu_ld8u:
1343 tcg_out_qemu_ld(s, args, 0);
1344 break;
1345 case INDEX_op_qemu_ld8s:
1346 tcg_out_qemu_ld(s, args, 0 | 4);
1347 break;
1348 case INDEX_op_qemu_ld16u:
1349 tcg_out_qemu_ld(s, args, 1);
1350 break;
1351 case INDEX_op_qemu_ld16s:
1352 tcg_out_qemu_ld(s, args, 1 | 4);
1353 break;
1354 case INDEX_op_qemu_ld32:
1355 tcg_out_qemu_ld(s, args, 2);
1356 break;
1357 case INDEX_op_qemu_ld64:
1358 tcg_out_qemu_ld(s, args, 3);
1359 break;
1360 case INDEX_op_qemu_st8:
1361 tcg_out_qemu_st(s, args, 0);
1362 break;
1363 case INDEX_op_qemu_st16:
1364 tcg_out_qemu_st(s, args, 1);
1365 break;
1366 case INDEX_op_qemu_st32:
1367 tcg_out_qemu_st(s, args, 2);
1368 break;
1369 case INDEX_op_qemu_st64:
1370 tcg_out_qemu_st(s, args, 3);
1371 break;
1373 default:
1374 tcg_abort();
1378 static const TCGTargetOpDef mips_op_defs[] = {
1379 { INDEX_op_exit_tb, { } },
1380 { INDEX_op_goto_tb, { } },
1381 { INDEX_op_call, { "C" } },
1382 { INDEX_op_jmp, { "r" } },
1383 { INDEX_op_br, { } },
1385 { INDEX_op_mov_i32, { "r", "r" } },
1386 { INDEX_op_movi_i32, { "r" } },
1387 { INDEX_op_ld8u_i32, { "r", "r" } },
1388 { INDEX_op_ld8s_i32, { "r", "r" } },
1389 { INDEX_op_ld16u_i32, { "r", "r" } },
1390 { INDEX_op_ld16s_i32, { "r", "r" } },
1391 { INDEX_op_ld_i32, { "r", "r" } },
1392 { INDEX_op_st8_i32, { "rZ", "r" } },
1393 { INDEX_op_st16_i32, { "rZ", "r" } },
1394 { INDEX_op_st_i32, { "rZ", "r" } },
1396 { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
1397 { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1398 { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1399 { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1400 { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1401 { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1402 { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1403 { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
1405 { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
1406 { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
1407 { INDEX_op_not_i32, { "r", "rZ" } },
1408 { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1409 { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1411 { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
1412 { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
1413 { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
1415 { INDEX_op_ext8s_i32, { "r", "rZ" } },
1416 { INDEX_op_ext16s_i32, { "r", "rZ" } },
1418 { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1419 { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
1420 { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
1422 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1423 { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1424 { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1426 #if TARGET_LONG_BITS == 32
1427 { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1428 { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1429 { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1430 { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1431 { INDEX_op_qemu_ld32, { "L", "lZ" } },
1432 { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1434 { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1435 { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1436 { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1437 { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1438 #else
1439 { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1440 { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1441 { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1442 { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1443 { INDEX_op_qemu_ld32, { "L", "lZ", "lZ" } },
1444 { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1446 { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1447 { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1448 { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1449 { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1450 #endif
1451 { -1 },
1454 static int tcg_target_callee_save_regs[] = {
1455 #if 0 /* used for the global env (TCG_AREG0), so no need to save */
1456 TCG_REG_S0,
1457 #endif
1458 TCG_REG_S1,
1459 TCG_REG_S2,
1460 TCG_REG_S3,
1461 TCG_REG_S4,
1462 TCG_REG_S5,
1463 TCG_REG_S6,
1464 TCG_REG_S7,
1465 TCG_REG_GP,
1466 TCG_REG_FP,
1467 TCG_REG_RA, /* should be last for ABI compliance */
1470 /* Generate global QEMU prologue and epilogue code */
1471 static void tcg_target_qemu_prologue(TCGContext *s)
1473 int i, frame_size;
1475 /* reserve some stack space */
1476 frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1477 + TCG_STATIC_CALL_ARGS_SIZE;
1478 frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1479 ~(TCG_TARGET_STACK_ALIGN - 1);
1481 /* TB prologue */
1482 tcg_out_addi(s, TCG_REG_SP, -frame_size);
1483 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1484 tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1485 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1488 /* Call generated code */
1489 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_A0, 0);
1490 tcg_out_nop(s);
1491 tb_ret_addr = s->code_ptr;
1493 /* TB epilogue */
1494 for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1495 tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1496 TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1499 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1500 tcg_out_addi(s, TCG_REG_SP, frame_size);
1503 static void tcg_target_init(TCGContext *s)
1505 tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1506 tcg_regset_set(tcg_target_call_clobber_regs,
1507 (1 << TCG_REG_V0) |
1508 (1 << TCG_REG_V1) |
1509 (1 << TCG_REG_A0) |
1510 (1 << TCG_REG_A1) |
1511 (1 << TCG_REG_A2) |
1512 (1 << TCG_REG_A3) |
1513 (1 << TCG_REG_T1) |
1514 (1 << TCG_REG_T2) |
1515 (1 << TCG_REG_T3) |
1516 (1 << TCG_REG_T4) |
1517 (1 << TCG_REG_T5) |
1518 (1 << TCG_REG_T6) |
1519 (1 << TCG_REG_T7) |
1520 (1 << TCG_REG_T8) |
1521 (1 << TCG_REG_T9));
1523 tcg_regset_clear(s->reserved_regs);
1524 tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1525 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
1526 tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
1527 tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT); /* internal use */
1528 tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0); /* internal use */
1529 tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
1530 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
1532 tcg_add_target_add_op_defs(mips_op_defs);