|
|
1.1 root 1: /*
2: * Tiny Code Generator for QEMU
3: *
4: * Copyright (c) 2008-2009 Arnaud Patard <[email protected]>
5: * Copyright (c) 2009 Aurelien Jarno <[email protected]>
6: * Based on i386/tcg-target.c - Copyright (c) 2008 Fabrice Bellard
7: *
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:
14: *
15: * The above copyright notice and this permission notice shall be included in
16: * all copies or substantial portions of the Software.
17: *
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.
25: */
26:
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
32:
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",
67: };
68: #endif
69:
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
95: };
96:
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
102: };
103:
104: static const int tcg_target_call_oarg_regs[2] = {
105: TCG_REG_V0,
106: TCG_REG_V1
107: };
108:
109: static uint8_t *tb_ret_addr;
110:
111: static inline uint32_t reloc_lo16_val (void *pc, tcg_target_long target)
112: {
113: return target & 0xffff;
114: }
115:
116: static inline void reloc_lo16 (void *pc, tcg_target_long target)
117: {
118: *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
119: | reloc_lo16_val(pc, target);
120: }
121:
122: static inline uint32_t reloc_hi16_val (void *pc, tcg_target_long target)
123: {
124: return (target >> 16) & 0xffff;
125: }
126:
127: static inline void reloc_hi16 (void *pc, tcg_target_long target)
128: {
129: *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
130: | reloc_hi16_val(pc, target);
131: }
132:
133: static inline uint32_t reloc_pc16_val (void *pc, tcg_target_long target)
134: {
135: int32_t disp;
136:
137: disp = target - (tcg_target_long) pc - 4;
138: if (disp != (disp << 14) >> 14) {
139: tcg_abort ();
140: }
141:
142: return (disp >> 2) & 0xffff;
143: }
144:
145: static inline void reloc_pc16 (void *pc, tcg_target_long target)
146: {
147: *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
148: | reloc_pc16_val(pc, target);
149: }
150:
151: static inline uint32_t reloc_26_val (void *pc, tcg_target_long target)
152: {
153: if ((((tcg_target_long)pc + 4) & 0xf0000000) != (target & 0xf0000000)) {
154: tcg_abort ();
155: }
156:
157: return (target >> 2) & 0x3ffffff;
158: }
159:
160: static inline void reloc_pc26 (void *pc, tcg_target_long target)
161: {
162: *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3ffffff)
163: | reloc_26_val(pc, target);
164: }
165:
166: static void patch_reloc(uint8_t *code_ptr, int type,
167: tcg_target_long value, tcg_target_long addend)
168: {
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();
185: }
186: }
187:
188: /* maximum number of register used for input function arguments */
189: static inline int tcg_target_get_call_iarg_regs_count(int flags)
190: {
191: return 4;
192: }
193:
194: /* parse target specific constraints */
195: static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
196: {
197: const char *ct_str;
198:
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);
1.1.1.4 root 226: #if defined(CONFIG_SOFTMMU)
1.1 root 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;
247: }
248: ct_str++;
249: *pct_str = ct_str;
250: return 0;
251: }
252:
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)
256: {
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;
269: }
270:
271: /* instruction opcodes */
272: enum {
273: OPC_BEQ = 0x04 << 26,
274: OPC_BNE = 0x05 << 26,
275: OPC_ADDIU = 0x09 << 26,
1.1.1.4 root 276: OPC_SLTI = 0x0A << 26,
277: OPC_SLTIU = 0x0B << 26,
1.1 root 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,
1.1.1.4 root 291:
292: OPC_SPECIAL = 0x00 << 26,
1.1 root 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,
1.1.1.4 root 315:
316: OPC_SPECIAL3 = 0x1f << 26,
317: OPC_SEB = OPC_SPECIAL3 | 0x420,
318: OPC_SEH = OPC_SPECIAL3 | 0x620,
1.1 root 319: };
320:
321: /*
322: * Type reg
323: */
324: static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int rt)
325: {
326: int32_t inst;
327:
328: inst = opc;
329: inst |= (rs & 0x1F) << 21;
330: inst |= (rt & 0x1F) << 16;
331: inst |= (rd & 0x1F) << 11;
332: tcg_out32(s, inst);
333: }
334:
335: /*
336: * Type immediate
337: */
338: static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int imm)
339: {
340: int32_t inst;
341:
342: inst = opc;
343: inst |= (rs & 0x1F) << 21;
344: inst |= (rt & 0x1F) << 16;
345: inst |= (imm & 0xffff);
346: tcg_out32(s, inst);
347: }
348:
349: /*
1.1.1.3 root 350: * Type branch
351: */
352: static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
353: {
1.1.1.5 root 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);
1.1.1.3 root 358:
359: tcg_out_opc_imm(s, opc, rt, rs, offset);
360: }
361:
362: /*
1.1 root 363: * Type sa
364: */
365: static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa)
366: {
367: int32_t inst;
368:
369: inst = opc;
370: inst |= (rt & 0x1F) << 16;
371: inst |= (rd & 0x1F) << 11;
372: inst |= (sa & 0x1F) << 6;
373: tcg_out32(s, inst);
374:
375: }
376:
377: static inline void tcg_out_nop(TCGContext *s)
378: {
379: tcg_out32(s, 0);
380: }
381:
1.1.1.7 ! root 382: static inline void tcg_out_mov(TCGContext *s, TCGType type,
! 383: TCGReg ret, TCGReg arg)
1.1 root 384: {
385: tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
386: }
387:
388: static inline void tcg_out_movi(TCGContext *s, TCGType type,
1.1.1.7 ! root 389: TCGReg reg, tcg_target_long arg)
1.1 root 390: {
391: if (arg == (int16_t)arg) {
392: tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
393: } else if (arg == (uint16_t)arg) {
394: tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
395: } else {
396: tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
397: tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
398: }
399: }
400:
401: static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
402: {
403: /* ret and arg can't be register at */
404: if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
405: tcg_abort();
406: }
407:
408: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
409: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
410:
411: tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
412: tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
413: tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
414: }
415:
416: static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
417: {
418: /* ret and arg can't be register at */
419: if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
420: tcg_abort();
421: }
422:
423: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
424: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
425:
426: tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
427: tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
428: tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
429: }
430:
431: static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
432: {
433: /* ret and arg must be different and can't be register at */
434: if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
435: tcg_abort();
436: }
437:
438: tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
439:
440: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
441: tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
442:
443: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
444: tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
445: tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
446:
447: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
448: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
449: tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
450: }
451:
1.1.1.4 root 452: static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg)
453: {
454: #ifdef _MIPS_ARCH_MIPS32R2
455: tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
456: #else
457: tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
458: tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24);
459: #endif
460: }
461:
462: static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg)
463: {
464: #ifdef _MIPS_ARCH_MIPS32R2
465: tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
466: #else
467: tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
468: tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
469: #endif
470: }
471:
1.1 root 472: static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
473: int arg1, tcg_target_long arg2)
474: {
475: if (arg2 == (int16_t) arg2) {
476: tcg_out_opc_imm(s, opc, arg, arg1, arg2);
477: } else {
478: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
479: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
480: tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
481: }
482: }
483:
1.1.1.7 ! root 484: static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
! 485: TCGReg arg1, tcg_target_long arg2)
1.1 root 486: {
487: tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
488: }
489:
1.1.1.7 ! root 490: static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
! 491: TCGReg arg1, tcg_target_long arg2)
1.1 root 492: {
493: tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
494: }
495:
496: static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
497: {
498: if (val == (int16_t)val) {
499: tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
500: } else {
501: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
502: tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
503: }
504: }
505:
1.1.1.4 root 506: static void tcg_out_brcond(TCGContext *s, TCGCond cond, int arg1,
1.1 root 507: int arg2, int label_index)
508: {
509: TCGLabel *l = &s->labels[label_index];
510:
511: switch (cond) {
512: case TCG_COND_EQ:
1.1.1.3 root 513: tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
1.1 root 514: break;
515: case TCG_COND_NE:
1.1.1.3 root 516: tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
1.1 root 517: break;
518: case TCG_COND_LT:
519: tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
1.1.1.3 root 520: tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
1.1 root 521: break;
522: case TCG_COND_LTU:
523: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
1.1.1.3 root 524: tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
1.1 root 525: break;
526: case TCG_COND_GE:
527: tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
1.1.1.3 root 528: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
1.1 root 529: break;
530: case TCG_COND_GEU:
531: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
1.1.1.3 root 532: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
1.1 root 533: break;
534: case TCG_COND_LE:
535: tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
1.1.1.3 root 536: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
1.1 root 537: break;
538: case TCG_COND_LEU:
539: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
1.1.1.3 root 540: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
1.1 root 541: break;
542: case TCG_COND_GT:
543: tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
1.1.1.3 root 544: tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
1.1 root 545: break;
546: case TCG_COND_GTU:
547: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
1.1.1.3 root 548: tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
1.1 root 549: break;
550: default:
551: tcg_abort();
552: break;
553: }
554: if (l->has_value) {
555: reloc_pc16(s->code_ptr - 4, l->u.value);
556: } else {
557: tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
558: }
559: tcg_out_nop(s);
560: }
561:
562: /* XXX: we implement it at the target level to avoid having to
563: handle cross basic blocks temporaries */
1.1.1.4 root 564: static void tcg_out_brcond2(TCGContext *s, TCGCond cond, int arg1,
1.1 root 565: int arg2, int arg3, int arg4, int label_index)
566: {
567: void *label_ptr;
568:
569: switch(cond) {
570: case TCG_COND_NE:
571: tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
572: tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
573: return;
574: case TCG_COND_EQ:
575: break;
576: case TCG_COND_LT:
577: case TCG_COND_LE:
578: tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
579: break;
580: case TCG_COND_GT:
581: case TCG_COND_GE:
582: tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
583: break;
584: case TCG_COND_LTU:
585: case TCG_COND_LEU:
586: tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
587: break;
588: case TCG_COND_GTU:
589: case TCG_COND_GEU:
590: tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
591: break;
592: default:
593: tcg_abort();
594: }
595:
596: label_ptr = s->code_ptr;
1.1.1.3 root 597: tcg_out_opc_br(s, OPC_BNE, arg2, arg4);
1.1 root 598: tcg_out_nop(s);
599:
600: switch(cond) {
601: case TCG_COND_EQ:
602: tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
603: break;
604: case TCG_COND_LT:
605: case TCG_COND_LTU:
606: tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
607: break;
608: case TCG_COND_LE:
609: case TCG_COND_LEU:
610: tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
611: break;
612: case TCG_COND_GT:
613: case TCG_COND_GTU:
614: tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
615: break;
616: case TCG_COND_GE:
617: case TCG_COND_GEU:
618: tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
619: break;
620: default:
621: tcg_abort();
622: }
623:
624: reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
625: }
626:
1.1.1.4 root 627: static void tcg_out_setcond(TCGContext *s, TCGCond cond, int ret,
628: int arg1, int arg2)
629: {
630: switch (cond) {
631: case TCG_COND_EQ:
632: if (arg1 == 0) {
633: tcg_out_opc_imm(s, OPC_SLTIU, ret, arg2, 1);
634: } else if (arg2 == 0) {
635: tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
636: } else {
637: tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
638: tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
639: }
640: break;
641: case TCG_COND_NE:
642: if (arg1 == 0) {
643: tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg2);
644: } else if (arg2 == 0) {
645: tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
646: } else {
647: tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
648: tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
649: }
650: break;
651: case TCG_COND_LT:
652: tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
653: break;
654: case TCG_COND_LTU:
655: tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
656: break;
657: case TCG_COND_GE:
658: tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
659: tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
660: break;
661: case TCG_COND_GEU:
662: tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
663: tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
664: break;
665: case TCG_COND_LE:
666: tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
667: tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
668: break;
669: case TCG_COND_LEU:
670: tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
671: tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
672: break;
673: case TCG_COND_GT:
674: tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
675: break;
676: case TCG_COND_GTU:
677: tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
678: break;
679: default:
680: tcg_abort();
681: break;
682: }
683: }
684:
685: /* XXX: we implement it at the target level to avoid having to
686: handle cross basic blocks temporaries */
687: static void tcg_out_setcond2(TCGContext *s, TCGCond cond, int ret,
688: int arg1, int arg2, int arg3, int arg4)
689: {
690: switch (cond) {
691: case TCG_COND_EQ:
692: tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_AT, arg2, arg4);
693: tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg1, arg3);
694: tcg_out_opc_reg(s, OPC_AND, ret, TCG_REG_AT, TCG_REG_T0);
695: return;
696: case TCG_COND_NE:
697: tcg_out_setcond(s, TCG_COND_NE, TCG_REG_AT, arg2, arg4);
698: tcg_out_setcond(s, TCG_COND_NE, TCG_REG_T0, arg1, arg3);
699: tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_AT, TCG_REG_T0);
700: return;
701: case TCG_COND_LT:
702: case TCG_COND_LE:
703: tcg_out_setcond(s, TCG_COND_LT, TCG_REG_AT, arg2, arg4);
704: break;
705: case TCG_COND_GT:
706: case TCG_COND_GE:
707: tcg_out_setcond(s, TCG_COND_GT, TCG_REG_AT, arg2, arg4);
708: break;
709: case TCG_COND_LTU:
710: case TCG_COND_LEU:
711: tcg_out_setcond(s, TCG_COND_LTU, TCG_REG_AT, arg2, arg4);
712: break;
713: case TCG_COND_GTU:
714: case TCG_COND_GEU:
715: tcg_out_setcond(s, TCG_COND_GTU, TCG_REG_AT, arg2, arg4);
716: break;
717: default:
718: tcg_abort();
719: break;
720: }
721:
722: tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg2, arg4);
723:
724: switch(cond) {
725: case TCG_COND_LT:
726: case TCG_COND_LTU:
727: tcg_out_setcond(s, TCG_COND_LTU, ret, arg1, arg3);
728: break;
729: case TCG_COND_LE:
730: case TCG_COND_LEU:
731: tcg_out_setcond(s, TCG_COND_LEU, ret, arg1, arg3);
732: break;
733: case TCG_COND_GT:
734: case TCG_COND_GTU:
735: tcg_out_setcond(s, TCG_COND_GTU, ret, arg1, arg3);
736: break;
737: case TCG_COND_GE:
738: case TCG_COND_GEU:
739: tcg_out_setcond(s, TCG_COND_GEU, ret, arg1, arg3);
740: break;
741: default:
742: tcg_abort();
743: }
744:
745: tcg_out_opc_reg(s, OPC_AND, ret, ret, TCG_REG_T0);
746: tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
747: }
748:
1.1 root 749: #if defined(CONFIG_SOFTMMU)
750:
751: #include "../../softmmu_defs.h"
752:
753: static void *qemu_ld_helpers[4] = {
754: __ldb_mmu,
755: __ldw_mmu,
756: __ldl_mmu,
757: __ldq_mmu,
758: };
759:
760: static void *qemu_st_helpers[4] = {
761: __stb_mmu,
762: __stw_mmu,
763: __stl_mmu,
764: __stq_mmu,
765: };
766: #endif
767:
768: static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
769: int opc)
770: {
771: int addr_regl, addr_reg1, addr_meml;
772: int data_regl, data_regh, data_reg1, data_reg2;
773: int mem_index, s_bits;
774: #if defined(CONFIG_SOFTMMU)
775: void *label1_ptr, *label2_ptr;
776: int sp_args;
777: #endif
778: #if TARGET_LONG_BITS == 64
779: # if defined(CONFIG_SOFTMMU)
780: uint8_t *label3_ptr;
781: # endif
782: int addr_regh, addr_reg2, addr_memh;
783: #endif
784: data_regl = *args++;
785: if (opc == 3)
786: data_regh = *args++;
787: else
788: data_regh = 0;
789: addr_regl = *args++;
790: #if TARGET_LONG_BITS == 64
791: addr_regh = *args++;
792: #endif
793: mem_index = *args;
794: s_bits = opc & 3;
795:
796: if (opc == 3) {
797: #if defined(TCG_TARGET_WORDS_BIGENDIAN)
798: data_reg1 = data_regh;
799: data_reg2 = data_regl;
800: #else
801: data_reg1 = data_regl;
802: data_reg2 = data_regh;
803: #endif
804: } else {
805: data_reg1 = data_regl;
806: data_reg2 = 0;
807: }
808: #if TARGET_LONG_BITS == 64
809: # if defined(TCG_TARGET_WORDS_BIGENDIAN)
810: addr_reg1 = addr_regh;
811: addr_reg2 = addr_regl;
812: addr_memh = 0;
813: addr_meml = 4;
814: # else
815: addr_reg1 = addr_regl;
816: addr_reg2 = addr_regh;
817: addr_memh = 4;
818: addr_meml = 0;
819: # endif
820: #else
821: addr_reg1 = addr_regl;
822: addr_meml = 0;
823: #endif
824:
825: #if defined(CONFIG_SOFTMMU)
826: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
827: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
828: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
829: tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
830: offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_meml);
831: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
832: tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
833:
834: # if TARGET_LONG_BITS == 64
835: label3_ptr = s->code_ptr;
1.1.1.3 root 836: tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
1.1 root 837: tcg_out_nop(s);
838:
839: tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
840: offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh);
841:
842: label1_ptr = s->code_ptr;
1.1.1.3 root 843: tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1.1 root 844: tcg_out_nop(s);
845:
846: reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
847: # else
848: label1_ptr = s->code_ptr;
1.1.1.3 root 849: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1.1 root 850: tcg_out_nop(s);
851: # endif
852:
853: /* slow path */
854: sp_args = TCG_REG_A0;
1.1.1.4 root 855: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
1.1 root 856: # if TARGET_LONG_BITS == 64
1.1.1.4 root 857: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
1.1 root 858: # endif
859: tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
860: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
861: tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
862: tcg_out_nop(s);
863:
864: switch(opc) {
865: case 0:
866: tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
867: break;
868: case 0 | 4:
1.1.1.4 root 869: tcg_out_ext8s(s, data_reg1, TCG_REG_V0);
1.1 root 870: break;
871: case 1:
872: tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
873: break;
874: case 1 | 4:
1.1.1.4 root 875: tcg_out_ext16s(s, data_reg1, TCG_REG_V0);
1.1 root 876: break;
877: case 2:
1.1.1.4 root 878: tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
1.1 root 879: break;
880: case 3:
1.1.1.4 root 881: tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_V1);
882: tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
1.1 root 883: break;
884: default:
885: tcg_abort();
886: }
887:
888: label2_ptr = s->code_ptr;
1.1.1.3 root 889: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1.1 root 890: tcg_out_nop(s);
891:
892: /* label1: fast path */
893: reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
894:
1.1.1.2 root 895: tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1.1.1.4 root 896: offsetof(CPUState, tlb_table[mem_index][0].addend));
1.1.1.2 root 897: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
1.1.1.4 root 898: #else
899: if (GUEST_BASE == (int16_t)GUEST_BASE) {
900: tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_V0, addr_regl, GUEST_BASE);
901: } else {
902: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, GUEST_BASE);
903: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
904: }
1.1 root 905: #endif
906:
907: switch(opc) {
908: case 0:
1.1.1.4 root 909: tcg_out_opc_imm(s, OPC_LBU, data_reg1, TCG_REG_V0, 0);
1.1 root 910: break;
911: case 0 | 4:
1.1.1.4 root 912: tcg_out_opc_imm(s, OPC_LB, data_reg1, TCG_REG_V0, 0);
1.1 root 913: break;
914: case 1:
915: if (TCG_NEED_BSWAP) {
1.1.1.4 root 916: tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
1.1 root 917: tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
918: } else {
1.1.1.4 root 919: tcg_out_opc_imm(s, OPC_LHU, data_reg1, TCG_REG_V0, 0);
1.1 root 920: }
921: break;
922: case 1 | 4:
923: if (TCG_NEED_BSWAP) {
1.1.1.4 root 924: tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
1.1 root 925: tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
926: } else {
1.1.1.4 root 927: tcg_out_opc_imm(s, OPC_LH, data_reg1, TCG_REG_V0, 0);
1.1 root 928: }
929: break;
930: case 2:
931: if (TCG_NEED_BSWAP) {
1.1.1.4 root 932: tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
1.1 root 933: tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
934: } else {
1.1.1.4 root 935: tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
1.1 root 936: }
937: break;
938: case 3:
939: if (TCG_NEED_BSWAP) {
1.1.1.4 root 940: tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 4);
1.1 root 941: tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
1.1.1.4 root 942: tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
1.1 root 943: tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
944: } else {
1.1.1.4 root 945: tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
946: tcg_out_opc_imm(s, OPC_LW, data_reg2, TCG_REG_V0, 4);
1.1 root 947: }
948: break;
949: default:
950: tcg_abort();
951: }
952:
953: #if defined(CONFIG_SOFTMMU)
954: reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
955: #endif
956: }
957:
958: static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
959: int opc)
960: {
961: int addr_regl, addr_reg1, addr_meml;
962: int data_regl, data_regh, data_reg1, data_reg2;
963: int mem_index, s_bits;
964: #if defined(CONFIG_SOFTMMU)
965: uint8_t *label1_ptr, *label2_ptr;
966: int sp_args;
967: #endif
968: #if TARGET_LONG_BITS == 64
969: # if defined(CONFIG_SOFTMMU)
970: uint8_t *label3_ptr;
971: # endif
972: int addr_regh, addr_reg2, addr_memh;
973: #endif
974:
975: data_regl = *args++;
976: if (opc == 3) {
977: data_regh = *args++;
978: #if defined(TCG_TARGET_WORDS_BIGENDIAN)
979: data_reg1 = data_regh;
980: data_reg2 = data_regl;
981: #else
982: data_reg1 = data_regl;
983: data_reg2 = data_regh;
984: #endif
985: } else {
986: data_reg1 = data_regl;
987: data_reg2 = 0;
988: data_regh = 0;
989: }
990: addr_regl = *args++;
991: #if TARGET_LONG_BITS == 64
992: addr_regh = *args++;
993: # if defined(TCG_TARGET_WORDS_BIGENDIAN)
994: addr_reg1 = addr_regh;
995: addr_reg2 = addr_regl;
996: addr_memh = 0;
997: addr_meml = 4;
998: # else
999: addr_reg1 = addr_regl;
1000: addr_reg2 = addr_regh;
1001: addr_memh = 4;
1002: addr_meml = 0;
1003: # endif
1004: #else
1005: addr_reg1 = addr_regl;
1006: addr_meml = 0;
1007: #endif
1008: mem_index = *args;
1009: s_bits = opc;
1010:
1011: #if defined(CONFIG_SOFTMMU)
1012: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1013: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
1014: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
1015: tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1016: offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_meml);
1017: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
1018: tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
1019:
1020: # if TARGET_LONG_BITS == 64
1021: label3_ptr = s->code_ptr;
1.1.1.3 root 1022: tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
1.1 root 1023: tcg_out_nop(s);
1024:
1025: tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1026: offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh);
1027:
1028: label1_ptr = s->code_ptr;
1.1.1.3 root 1029: tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1.1 root 1030: tcg_out_nop(s);
1031:
1032: reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
1033: # else
1034: label1_ptr = s->code_ptr;
1.1.1.3 root 1035: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1.1 root 1036: tcg_out_nop(s);
1037: # endif
1038:
1039: /* slow path */
1040: sp_args = TCG_REG_A0;
1.1.1.4 root 1041: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
1.1 root 1042: # if TARGET_LONG_BITS == 64
1.1.1.4 root 1043: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
1.1 root 1044: # endif
1045: switch(opc) {
1046: case 0:
1047: tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xff);
1048: break;
1049: case 1:
1050: tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
1051: break;
1052: case 2:
1.1.1.4 root 1053: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
1.1 root 1054: break;
1055: case 3:
1056: sp_args = (sp_args + 1) & ~1;
1.1.1.4 root 1057: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
1058: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg2);
1.1 root 1059: break;
1060: default:
1061: tcg_abort();
1062: }
1063: if (sp_args > TCG_REG_A3) {
1064: /* Push mem_index on the stack */
1065: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, mem_index);
1066: tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 16);
1067: } else {
1068: tcg_out_movi(s, TCG_TYPE_I32, sp_args, mem_index);
1069: }
1070:
1071: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
1072: tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1073: tcg_out_nop(s);
1074:
1075: label2_ptr = s->code_ptr;
1.1.1.3 root 1076: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1.1 root 1077: tcg_out_nop(s);
1078:
1079: /* label1: fast path */
1080: reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
1081:
1082: tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1.1.1.4 root 1083: offsetof(CPUState, tlb_table[mem_index][0].addend));
1.1 root 1084: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1.1.1.4 root 1085: #else
1086: if (GUEST_BASE == (int16_t)GUEST_BASE) {
1087: tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, addr_regl, GUEST_BASE);
1088: } else {
1089: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, GUEST_BASE);
1090: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1091: }
1.1 root 1092:
1093: #endif
1094:
1095: switch(opc) {
1096: case 0:
1.1.1.4 root 1097: tcg_out_opc_imm(s, OPC_SB, data_reg1, TCG_REG_A0, 0);
1.1 root 1098: break;
1099: case 1:
1100: if (TCG_NEED_BSWAP) {
1101: tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
1.1.1.4 root 1102: tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, TCG_REG_A0, 0);
1.1 root 1103: } else {
1.1.1.4 root 1104: tcg_out_opc_imm(s, OPC_SH, data_reg1, TCG_REG_A0, 0);
1.1 root 1105: }
1106: break;
1107: case 2:
1108: if (TCG_NEED_BSWAP) {
1109: tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1.1.1.4 root 1110: tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1.1 root 1111: } else {
1.1.1.4 root 1112: tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1.1 root 1113: }
1114: break;
1115: case 3:
1116: if (TCG_NEED_BSWAP) {
1117: tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
1.1.1.4 root 1118: tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1.1 root 1119: tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1.1.1.4 root 1120: tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 4);
1.1 root 1121: } else {
1.1.1.4 root 1122: tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1123: tcg_out_opc_imm(s, OPC_SW, data_reg2, TCG_REG_A0, 4);
1.1 root 1124: }
1125: break;
1126: default:
1127: tcg_abort();
1128: }
1129:
1130: #if defined(CONFIG_SOFTMMU)
1131: reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1132: #endif
1133: }
1134:
1.1.1.4 root 1135: static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1.1 root 1136: const TCGArg *args, const int *const_args)
1137: {
1138: switch(opc) {
1139: case INDEX_op_exit_tb:
1140: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
1141: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
1142: tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1143: tcg_out_nop(s);
1144: break;
1145: case INDEX_op_goto_tb:
1146: if (s->tb_jmp_offset) {
1147: /* direct jump method */
1148: tcg_abort();
1149: } else {
1150: /* indirect jump method */
1151: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
1152: tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
1153: tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1154: }
1155: tcg_out_nop(s);
1156: s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1157: break;
1158: case INDEX_op_call:
1159: tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
1160: tcg_out_nop(s);
1161: break;
1162: case INDEX_op_jmp:
1163: tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
1164: tcg_out_nop(s);
1165: break;
1166: case INDEX_op_br:
1167: tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1168: break;
1169:
1170: case INDEX_op_mov_i32:
1.1.1.4 root 1171: tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
1.1 root 1172: break;
1173: case INDEX_op_movi_i32:
1174: tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1175: break;
1176:
1177: case INDEX_op_ld8u_i32:
1.1.1.4 root 1178: tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1.1 root 1179: break;
1180: case INDEX_op_ld8s_i32:
1181: tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1182: break;
1183: case INDEX_op_ld16u_i32:
1184: tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1185: break;
1186: case INDEX_op_ld16s_i32:
1187: tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1188: break;
1189: case INDEX_op_ld_i32:
1190: tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1191: break;
1192: case INDEX_op_st8_i32:
1193: tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1194: break;
1195: case INDEX_op_st16_i32:
1196: tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1197: break;
1198: case INDEX_op_st_i32:
1199: tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1200: break;
1201:
1202: case INDEX_op_add_i32:
1203: if (const_args[2]) {
1204: tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1205: } else {
1206: tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1207: }
1208: break;
1209: case INDEX_op_add2_i32:
1210: if (const_args[4]) {
1211: tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1212: } else {
1213: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1214: }
1215: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1216: if (const_args[5]) {
1217: tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1218: } else {
1219: tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1220: }
1221: tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1.1.1.4 root 1222: tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1.1 root 1223: break;
1224: case INDEX_op_sub_i32:
1225: if (const_args[2]) {
1226: tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1227: } else {
1228: tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1229: }
1230: break;
1231: case INDEX_op_sub2_i32:
1232: if (const_args[4]) {
1233: tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1234: } else {
1235: tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1236: }
1237: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1238: if (const_args[5]) {
1239: tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1240: } else {
1241: tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1242: }
1243: tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1.1.1.4 root 1244: tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1.1 root 1245: break;
1246: case INDEX_op_mul_i32:
1247: tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1248: tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1249: break;
1250: case INDEX_op_mulu2_i32:
1251: tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1252: tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1253: tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1254: break;
1255: case INDEX_op_div_i32:
1256: tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1257: tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1258: break;
1259: case INDEX_op_divu_i32:
1260: tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1261: tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1262: break;
1263: case INDEX_op_rem_i32:
1264: tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1265: tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1266: break;
1267: case INDEX_op_remu_i32:
1268: tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1269: tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1270: break;
1271:
1272: case INDEX_op_and_i32:
1273: if (const_args[2]) {
1274: tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1275: } else {
1276: tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1277: }
1278: break;
1279: case INDEX_op_or_i32:
1280: if (const_args[2]) {
1281: tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1282: } else {
1283: tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1284: }
1285: break;
1.1.1.4 root 1286: case INDEX_op_nor_i32:
1287: tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[2]);
1288: break;
1.1 root 1289: case INDEX_op_not_i32:
1.1.1.4 root 1290: tcg_out_opc_reg(s, OPC_NOR, args[0], TCG_REG_ZERO, args[1]);
1.1 root 1291: break;
1292: case INDEX_op_xor_i32:
1293: if (const_args[2]) {
1294: tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1295: } else {
1296: tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1297: }
1298: break;
1299:
1300: case INDEX_op_sar_i32:
1301: if (const_args[2]) {
1302: tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1303: } else {
1304: tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1305: }
1306: break;
1307: case INDEX_op_shl_i32:
1308: if (const_args[2]) {
1309: tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1310: } else {
1311: tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1312: }
1313: break;
1314: case INDEX_op_shr_i32:
1315: if (const_args[2]) {
1316: tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1317: } else {
1318: tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1319: }
1320: break;
1321:
1.1.1.4 root 1322: case INDEX_op_ext8s_i32:
1323: tcg_out_ext8s(s, args[0], args[1]);
1324: break;
1325: case INDEX_op_ext16s_i32:
1326: tcg_out_ext16s(s, args[0], args[1]);
1327: break;
1328:
1.1 root 1329: case INDEX_op_brcond_i32:
1330: tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1331: break;
1332: case INDEX_op_brcond2_i32:
1333: tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1334: break;
1335:
1.1.1.4 root 1336: case INDEX_op_setcond_i32:
1337: tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
1338: break;
1339: case INDEX_op_setcond2_i32:
1340: tcg_out_setcond2(s, args[5], args[0], args[1], args[2], args[3], args[4]);
1341: break;
1342:
1.1 root 1343: case INDEX_op_qemu_ld8u:
1344: tcg_out_qemu_ld(s, args, 0);
1345: break;
1346: case INDEX_op_qemu_ld8s:
1347: tcg_out_qemu_ld(s, args, 0 | 4);
1348: break;
1349: case INDEX_op_qemu_ld16u:
1350: tcg_out_qemu_ld(s, args, 1);
1351: break;
1352: case INDEX_op_qemu_ld16s:
1353: tcg_out_qemu_ld(s, args, 1 | 4);
1354: break;
1.1.1.4 root 1355: case INDEX_op_qemu_ld32:
1.1 root 1356: tcg_out_qemu_ld(s, args, 2);
1357: break;
1358: case INDEX_op_qemu_ld64:
1359: tcg_out_qemu_ld(s, args, 3);
1360: break;
1361: case INDEX_op_qemu_st8:
1362: tcg_out_qemu_st(s, args, 0);
1363: break;
1364: case INDEX_op_qemu_st16:
1365: tcg_out_qemu_st(s, args, 1);
1366: break;
1367: case INDEX_op_qemu_st32:
1368: tcg_out_qemu_st(s, args, 2);
1369: break;
1370: case INDEX_op_qemu_st64:
1371: tcg_out_qemu_st(s, args, 3);
1372: break;
1373:
1374: default:
1375: tcg_abort();
1376: }
1377: }
1378:
1379: static const TCGTargetOpDef mips_op_defs[] = {
1380: { INDEX_op_exit_tb, { } },
1381: { INDEX_op_goto_tb, { } },
1382: { INDEX_op_call, { "C" } },
1383: { INDEX_op_jmp, { "r" } },
1384: { INDEX_op_br, { } },
1385:
1386: { INDEX_op_mov_i32, { "r", "r" } },
1387: { INDEX_op_movi_i32, { "r" } },
1388: { INDEX_op_ld8u_i32, { "r", "r" } },
1389: { INDEX_op_ld8s_i32, { "r", "r" } },
1390: { INDEX_op_ld16u_i32, { "r", "r" } },
1391: { INDEX_op_ld16s_i32, { "r", "r" } },
1392: { INDEX_op_ld_i32, { "r", "r" } },
1393: { INDEX_op_st8_i32, { "rZ", "r" } },
1394: { INDEX_op_st16_i32, { "rZ", "r" } },
1395: { INDEX_op_st_i32, { "rZ", "r" } },
1396:
1397: { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
1398: { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1399: { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1400: { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1401: { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1402: { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1403: { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1404: { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
1405:
1406: { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
1.1.1.4 root 1407: { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
1.1 root 1408: { INDEX_op_not_i32, { "r", "rZ" } },
1409: { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1410: { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1411:
1412: { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
1413: { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
1414: { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
1415:
1.1.1.4 root 1416: { INDEX_op_ext8s_i32, { "r", "rZ" } },
1417: { INDEX_op_ext16s_i32, { "r", "rZ" } },
1418:
1.1 root 1419: { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1.1.1.4 root 1420: { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
1421: { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
1.1 root 1422:
1423: { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1424: { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1425: { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1426:
1427: #if TARGET_LONG_BITS == 32
1428: { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1429: { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1430: { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1431: { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1.1.1.4 root 1432: { INDEX_op_qemu_ld32, { "L", "lZ" } },
1.1 root 1433: { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1434:
1435: { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1436: { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1437: { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1438: { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1439: #else
1440: { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1441: { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1442: { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1443: { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1.1.1.4 root 1444: { INDEX_op_qemu_ld32, { "L", "lZ", "lZ" } },
1.1 root 1445: { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1446:
1447: { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1448: { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1449: { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1450: { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1451: #endif
1452: { -1 },
1453: };
1454:
1455: static int tcg_target_callee_save_regs[] = {
1.1.1.6 root 1456: TCG_REG_S0, /* used for the global env (TCG_AREG0) */
1.1 root 1457: TCG_REG_S1,
1458: TCG_REG_S2,
1459: TCG_REG_S3,
1460: TCG_REG_S4,
1461: TCG_REG_S5,
1462: TCG_REG_S6,
1463: TCG_REG_S7,
1464: TCG_REG_GP,
1.1.1.3 root 1465: TCG_REG_FP,
1.1 root 1466: TCG_REG_RA, /* should be last for ABI compliance */
1467: };
1468:
1469: /* Generate global QEMU prologue and epilogue code */
1.1.1.4 root 1470: static void tcg_target_qemu_prologue(TCGContext *s)
1.1 root 1471: {
1472: int i, frame_size;
1473:
1474: /* reserve some stack space */
1475: frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1476: + TCG_STATIC_CALL_ARGS_SIZE;
1477: frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1478: ~(TCG_TARGET_STACK_ALIGN - 1);
1479:
1480: /* TB prologue */
1481: tcg_out_addi(s, TCG_REG_SP, -frame_size);
1482: for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1483: tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1484: TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1485: }
1486:
1487: /* Call generated code */
1.1.1.6 root 1488: tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
1489: tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1.1 root 1490: tb_ret_addr = s->code_ptr;
1491:
1492: /* TB epilogue */
1493: for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1494: tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1495: TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1496: }
1497:
1498: tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1499: tcg_out_addi(s, TCG_REG_SP, frame_size);
1500: }
1501:
1.1.1.4 root 1502: static void tcg_target_init(TCGContext *s)
1.1 root 1503: {
1504: tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1505: tcg_regset_set(tcg_target_call_clobber_regs,
1506: (1 << TCG_REG_V0) |
1507: (1 << TCG_REG_V1) |
1508: (1 << TCG_REG_A0) |
1509: (1 << TCG_REG_A1) |
1510: (1 << TCG_REG_A2) |
1511: (1 << TCG_REG_A3) |
1512: (1 << TCG_REG_T1) |
1513: (1 << TCG_REG_T2) |
1514: (1 << TCG_REG_T3) |
1515: (1 << TCG_REG_T4) |
1516: (1 << TCG_REG_T5) |
1517: (1 << TCG_REG_T6) |
1518: (1 << TCG_REG_T7) |
1519: (1 << TCG_REG_T8) |
1520: (1 << TCG_REG_T9));
1521:
1522: tcg_regset_clear(s->reserved_regs);
1523: tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1524: tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
1525: tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
1526: tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT); /* internal use */
1527: tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0); /* internal use */
1528: tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
1529: tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
1530:
1531: tcg_add_target_add_op_defs(mips_op_defs);
1.1.1.6 root 1532: tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
1533: CPU_TEMP_BUF_NLONGS * sizeof(long));
1.1 root 1534: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.