|
|
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:
1.1.1.8 ! root 753: #ifdef CONFIG_TCG_PASS_AREG0
! 754: /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
! 755: int mmu_idx) */
! 756: static const void * const qemu_ld_helpers[4] = {
! 757: helper_ldb_mmu,
! 758: helper_ldw_mmu,
! 759: helper_ldl_mmu,
! 760: helper_ldq_mmu,
! 761: };
! 762:
! 763: /* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
! 764: uintxx_t val, int mmu_idx) */
! 765: static const void * const qemu_st_helpers[4] = {
! 766: helper_stb_mmu,
! 767: helper_stw_mmu,
! 768: helper_stl_mmu,
! 769: helper_stq_mmu,
! 770: };
! 771: #else
! 772: /* legacy helper signature: __ld_mmu(target_ulong addr, int
! 773: mmu_idx) */
1.1 root 774: static void *qemu_ld_helpers[4] = {
775: __ldb_mmu,
776: __ldw_mmu,
777: __ldl_mmu,
778: __ldq_mmu,
779: };
780:
1.1.1.8 ! root 781: /* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
! 782: int mmu_idx) */
1.1 root 783: static void *qemu_st_helpers[4] = {
784: __stb_mmu,
785: __stw_mmu,
786: __stl_mmu,
787: __stq_mmu,
788: };
789: #endif
1.1.1.8 ! root 790: #endif
1.1 root 791:
792: static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
793: int opc)
794: {
795: int addr_regl, addr_reg1, addr_meml;
796: int data_regl, data_regh, data_reg1, data_reg2;
797: int mem_index, s_bits;
798: #if defined(CONFIG_SOFTMMU)
799: void *label1_ptr, *label2_ptr;
800: int sp_args;
801: #endif
802: #if TARGET_LONG_BITS == 64
803: # if defined(CONFIG_SOFTMMU)
804: uint8_t *label3_ptr;
805: # endif
806: int addr_regh, addr_reg2, addr_memh;
807: #endif
808: data_regl = *args++;
809: if (opc == 3)
810: data_regh = *args++;
811: else
812: data_regh = 0;
813: addr_regl = *args++;
814: #if TARGET_LONG_BITS == 64
815: addr_regh = *args++;
816: #endif
817: mem_index = *args;
818: s_bits = opc & 3;
819:
820: if (opc == 3) {
821: #if defined(TCG_TARGET_WORDS_BIGENDIAN)
822: data_reg1 = data_regh;
823: data_reg2 = data_regl;
824: #else
825: data_reg1 = data_regl;
826: data_reg2 = data_regh;
827: #endif
828: } else {
829: data_reg1 = data_regl;
830: data_reg2 = 0;
831: }
832: #if TARGET_LONG_BITS == 64
833: # if defined(TCG_TARGET_WORDS_BIGENDIAN)
834: addr_reg1 = addr_regh;
835: addr_reg2 = addr_regl;
836: addr_memh = 0;
837: addr_meml = 4;
838: # else
839: addr_reg1 = addr_regl;
840: addr_reg2 = addr_regh;
841: addr_memh = 4;
842: addr_meml = 0;
843: # endif
844: #else
845: addr_reg1 = addr_regl;
846: addr_meml = 0;
847: #endif
848:
849: #if defined(CONFIG_SOFTMMU)
850: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
851: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
852: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
853: tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1.1.1.8 ! root 854: offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + addr_meml);
1.1 root 855: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
856: tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
857:
858: # if TARGET_LONG_BITS == 64
859: label3_ptr = s->code_ptr;
1.1.1.3 root 860: tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
1.1 root 861: tcg_out_nop(s);
862:
863: tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1.1.1.8 ! root 864: offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + addr_memh);
1.1 root 865:
866: label1_ptr = s->code_ptr;
1.1.1.3 root 867: tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1.1 root 868: tcg_out_nop(s);
869:
870: reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
871: # else
872: label1_ptr = s->code_ptr;
1.1.1.3 root 873: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1.1 root 874: tcg_out_nop(s);
875: # endif
876:
877: /* slow path */
878: sp_args = TCG_REG_A0;
1.1.1.4 root 879: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
1.1 root 880: # if TARGET_LONG_BITS == 64
1.1.1.4 root 881: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
1.1 root 882: # endif
883: tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
884: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
1.1.1.8 ! root 885: #ifdef CONFIG_TCG_PASS_AREG0
! 886: /* XXX/FIXME: suboptimal and incorrect for 64 on 32 bit */
! 887: tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
! 888: tcg_target_call_iarg_regs[1]);
! 889: tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
! 890: tcg_target_call_iarg_regs[0]);
! 891: tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
! 892: TCG_AREG0);
! 893: #endif
1.1 root 894: tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
895: tcg_out_nop(s);
896:
897: switch(opc) {
898: case 0:
899: tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
900: break;
901: case 0 | 4:
1.1.1.4 root 902: tcg_out_ext8s(s, data_reg1, TCG_REG_V0);
1.1 root 903: break;
904: case 1:
905: tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
906: break;
907: case 1 | 4:
1.1.1.4 root 908: tcg_out_ext16s(s, data_reg1, TCG_REG_V0);
1.1 root 909: break;
910: case 2:
1.1.1.4 root 911: tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
1.1 root 912: break;
913: case 3:
1.1.1.4 root 914: tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_V1);
915: tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
1.1 root 916: break;
917: default:
918: tcg_abort();
919: }
920:
921: label2_ptr = s->code_ptr;
1.1.1.3 root 922: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1.1 root 923: tcg_out_nop(s);
924:
925: /* label1: fast path */
926: reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
927:
1.1.1.2 root 928: tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1.1.1.8 ! root 929: offsetof(CPUArchState, tlb_table[mem_index][0].addend));
1.1.1.2 root 930: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
1.1.1.4 root 931: #else
932: if (GUEST_BASE == (int16_t)GUEST_BASE) {
933: tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_V0, addr_regl, GUEST_BASE);
934: } else {
935: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, GUEST_BASE);
936: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
937: }
1.1 root 938: #endif
939:
940: switch(opc) {
941: case 0:
1.1.1.4 root 942: tcg_out_opc_imm(s, OPC_LBU, data_reg1, TCG_REG_V0, 0);
1.1 root 943: break;
944: case 0 | 4:
1.1.1.4 root 945: tcg_out_opc_imm(s, OPC_LB, data_reg1, TCG_REG_V0, 0);
1.1 root 946: break;
947: case 1:
948: if (TCG_NEED_BSWAP) {
1.1.1.4 root 949: tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
1.1 root 950: tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
951: } else {
1.1.1.4 root 952: tcg_out_opc_imm(s, OPC_LHU, data_reg1, TCG_REG_V0, 0);
1.1 root 953: }
954: break;
955: case 1 | 4:
956: if (TCG_NEED_BSWAP) {
1.1.1.4 root 957: tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
1.1 root 958: tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
959: } else {
1.1.1.4 root 960: tcg_out_opc_imm(s, OPC_LH, data_reg1, TCG_REG_V0, 0);
1.1 root 961: }
962: break;
963: case 2:
964: if (TCG_NEED_BSWAP) {
1.1.1.4 root 965: tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
1.1 root 966: tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
967: } else {
1.1.1.4 root 968: tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
1.1 root 969: }
970: break;
971: case 3:
972: if (TCG_NEED_BSWAP) {
1.1.1.4 root 973: tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 4);
1.1 root 974: tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
1.1.1.4 root 975: tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
1.1 root 976: tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
977: } else {
1.1.1.4 root 978: tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
979: tcg_out_opc_imm(s, OPC_LW, data_reg2, TCG_REG_V0, 4);
1.1 root 980: }
981: break;
982: default:
983: tcg_abort();
984: }
985:
986: #if defined(CONFIG_SOFTMMU)
987: reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
988: #endif
989: }
990:
991: static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
992: int opc)
993: {
994: int addr_regl, addr_reg1, addr_meml;
995: int data_regl, data_regh, data_reg1, data_reg2;
996: int mem_index, s_bits;
997: #if defined(CONFIG_SOFTMMU)
998: uint8_t *label1_ptr, *label2_ptr;
999: int sp_args;
1000: #endif
1001: #if TARGET_LONG_BITS == 64
1002: # if defined(CONFIG_SOFTMMU)
1003: uint8_t *label3_ptr;
1004: # endif
1005: int addr_regh, addr_reg2, addr_memh;
1006: #endif
1007:
1008: data_regl = *args++;
1009: if (opc == 3) {
1010: data_regh = *args++;
1011: #if defined(TCG_TARGET_WORDS_BIGENDIAN)
1012: data_reg1 = data_regh;
1013: data_reg2 = data_regl;
1014: #else
1015: data_reg1 = data_regl;
1016: data_reg2 = data_regh;
1017: #endif
1018: } else {
1019: data_reg1 = data_regl;
1020: data_reg2 = 0;
1021: data_regh = 0;
1022: }
1023: addr_regl = *args++;
1024: #if TARGET_LONG_BITS == 64
1025: addr_regh = *args++;
1026: # if defined(TCG_TARGET_WORDS_BIGENDIAN)
1027: addr_reg1 = addr_regh;
1028: addr_reg2 = addr_regl;
1029: addr_memh = 0;
1030: addr_meml = 4;
1031: # else
1032: addr_reg1 = addr_regl;
1033: addr_reg2 = addr_regh;
1034: addr_memh = 4;
1035: addr_meml = 0;
1036: # endif
1037: #else
1038: addr_reg1 = addr_regl;
1039: addr_meml = 0;
1040: #endif
1041: mem_index = *args;
1042: s_bits = opc;
1043:
1044: #if defined(CONFIG_SOFTMMU)
1045: tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1046: tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
1047: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
1048: tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1.1.1.8 ! root 1049: offsetof(CPUArchState, tlb_table[mem_index][0].addr_write) + addr_meml);
1.1 root 1050: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
1051: tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
1052:
1053: # if TARGET_LONG_BITS == 64
1054: label3_ptr = s->code_ptr;
1.1.1.3 root 1055: tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
1.1 root 1056: tcg_out_nop(s);
1057:
1058: tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1.1.1.8 ! root 1059: offsetof(CPUArchState, tlb_table[mem_index][0].addr_write) + addr_memh);
1.1 root 1060:
1061: label1_ptr = s->code_ptr;
1.1.1.3 root 1062: tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1.1 root 1063: tcg_out_nop(s);
1064:
1065: reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
1066: # else
1067: label1_ptr = s->code_ptr;
1.1.1.3 root 1068: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1.1 root 1069: tcg_out_nop(s);
1070: # endif
1071:
1072: /* slow path */
1073: sp_args = TCG_REG_A0;
1.1.1.4 root 1074: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
1.1 root 1075: # if TARGET_LONG_BITS == 64
1.1.1.4 root 1076: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
1.1 root 1077: # endif
1078: switch(opc) {
1079: case 0:
1080: tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xff);
1081: break;
1082: case 1:
1083: tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
1084: break;
1085: case 2:
1.1.1.4 root 1086: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
1.1 root 1087: break;
1088: case 3:
1089: sp_args = (sp_args + 1) & ~1;
1.1.1.4 root 1090: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
1091: tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg2);
1.1 root 1092: break;
1093: default:
1094: tcg_abort();
1095: }
1096: if (sp_args > TCG_REG_A3) {
1097: /* Push mem_index on the stack */
1098: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, mem_index);
1099: tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 16);
1100: } else {
1101: tcg_out_movi(s, TCG_TYPE_I32, sp_args, mem_index);
1102: }
1103:
1104: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
1.1.1.8 ! root 1105: #ifdef CONFIG_TCG_PASS_AREG0
! 1106: /* XXX/FIXME: suboptimal and incorrect for 64 on 32 bit */
! 1107: tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
! 1108: tcg_target_call_iarg_regs[2]);
! 1109: tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[2],
! 1110: tcg_target_call_iarg_regs[1]);
! 1111: tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
! 1112: tcg_target_call_iarg_regs[0]);
! 1113: tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0],
! 1114: TCG_AREG0);
! 1115: #endif
1.1 root 1116: tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1117: tcg_out_nop(s);
1118:
1119: label2_ptr = s->code_ptr;
1.1.1.3 root 1120: tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1.1 root 1121: tcg_out_nop(s);
1122:
1123: /* label1: fast path */
1124: reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
1125:
1126: tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1.1.1.8 ! root 1127: offsetof(CPUArchState, tlb_table[mem_index][0].addend));
1.1 root 1128: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1.1.1.4 root 1129: #else
1130: if (GUEST_BASE == (int16_t)GUEST_BASE) {
1131: tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, addr_regl, GUEST_BASE);
1132: } else {
1133: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, GUEST_BASE);
1134: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1135: }
1.1 root 1136:
1137: #endif
1138:
1139: switch(opc) {
1140: case 0:
1.1.1.4 root 1141: tcg_out_opc_imm(s, OPC_SB, data_reg1, TCG_REG_A0, 0);
1.1 root 1142: break;
1143: case 1:
1144: if (TCG_NEED_BSWAP) {
1145: tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
1.1.1.4 root 1146: tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, TCG_REG_A0, 0);
1.1 root 1147: } else {
1.1.1.4 root 1148: tcg_out_opc_imm(s, OPC_SH, data_reg1, TCG_REG_A0, 0);
1.1 root 1149: }
1150: break;
1151: case 2:
1152: if (TCG_NEED_BSWAP) {
1153: tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1.1.1.4 root 1154: tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1.1 root 1155: } else {
1.1.1.4 root 1156: tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1.1 root 1157: }
1158: break;
1159: case 3:
1160: if (TCG_NEED_BSWAP) {
1161: tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
1.1.1.4 root 1162: tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1.1 root 1163: tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1.1.1.4 root 1164: tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 4);
1.1 root 1165: } else {
1.1.1.4 root 1166: tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1167: tcg_out_opc_imm(s, OPC_SW, data_reg2, TCG_REG_A0, 4);
1.1 root 1168: }
1169: break;
1170: default:
1171: tcg_abort();
1172: }
1173:
1174: #if defined(CONFIG_SOFTMMU)
1175: reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1176: #endif
1177: }
1178:
1.1.1.4 root 1179: static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1.1 root 1180: const TCGArg *args, const int *const_args)
1181: {
1182: switch(opc) {
1183: case INDEX_op_exit_tb:
1184: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
1185: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
1186: tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1187: tcg_out_nop(s);
1188: break;
1189: case INDEX_op_goto_tb:
1190: if (s->tb_jmp_offset) {
1191: /* direct jump method */
1192: tcg_abort();
1193: } else {
1194: /* indirect jump method */
1195: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
1196: tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
1197: tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1198: }
1199: tcg_out_nop(s);
1200: s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1201: break;
1202: case INDEX_op_call:
1203: tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
1204: tcg_out_nop(s);
1205: break;
1206: case INDEX_op_jmp:
1207: tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
1208: tcg_out_nop(s);
1209: break;
1210: case INDEX_op_br:
1211: tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1212: break;
1213:
1214: case INDEX_op_mov_i32:
1.1.1.4 root 1215: tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
1.1 root 1216: break;
1217: case INDEX_op_movi_i32:
1218: tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1219: break;
1220:
1221: case INDEX_op_ld8u_i32:
1.1.1.4 root 1222: tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1.1 root 1223: break;
1224: case INDEX_op_ld8s_i32:
1225: tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1226: break;
1227: case INDEX_op_ld16u_i32:
1228: tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1229: break;
1230: case INDEX_op_ld16s_i32:
1231: tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1232: break;
1233: case INDEX_op_ld_i32:
1234: tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1235: break;
1236: case INDEX_op_st8_i32:
1237: tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1238: break;
1239: case INDEX_op_st16_i32:
1240: tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1241: break;
1242: case INDEX_op_st_i32:
1243: tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1244: break;
1245:
1246: case INDEX_op_add_i32:
1247: if (const_args[2]) {
1248: tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1249: } else {
1250: tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1251: }
1252: break;
1253: case INDEX_op_add2_i32:
1254: if (const_args[4]) {
1255: tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1256: } else {
1257: tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1258: }
1259: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1260: if (const_args[5]) {
1261: tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1262: } else {
1263: tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1264: }
1265: tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1.1.1.4 root 1266: tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1.1 root 1267: break;
1268: case INDEX_op_sub_i32:
1269: if (const_args[2]) {
1270: tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1271: } else {
1272: tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1273: }
1274: break;
1275: case INDEX_op_sub2_i32:
1276: if (const_args[4]) {
1277: tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1278: } else {
1279: tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1280: }
1281: tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1282: if (const_args[5]) {
1283: tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1284: } else {
1285: tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1286: }
1287: tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1.1.1.4 root 1288: tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1.1 root 1289: break;
1290: case INDEX_op_mul_i32:
1291: tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1292: tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1293: break;
1294: case INDEX_op_mulu2_i32:
1295: tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1296: tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1297: tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1298: break;
1299: case INDEX_op_div_i32:
1300: tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1301: tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1302: break;
1303: case INDEX_op_divu_i32:
1304: tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1305: tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1306: break;
1307: case INDEX_op_rem_i32:
1308: tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1309: tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1310: break;
1311: case INDEX_op_remu_i32:
1312: tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1313: tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1314: break;
1315:
1316: case INDEX_op_and_i32:
1317: if (const_args[2]) {
1318: tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1319: } else {
1320: tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1321: }
1322: break;
1323: case INDEX_op_or_i32:
1324: if (const_args[2]) {
1325: tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1326: } else {
1327: tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1328: }
1329: break;
1.1.1.4 root 1330: case INDEX_op_nor_i32:
1331: tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[2]);
1332: break;
1.1 root 1333: case INDEX_op_not_i32:
1.1.1.4 root 1334: tcg_out_opc_reg(s, OPC_NOR, args[0], TCG_REG_ZERO, args[1]);
1.1 root 1335: break;
1336: case INDEX_op_xor_i32:
1337: if (const_args[2]) {
1338: tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1339: } else {
1340: tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1341: }
1342: break;
1343:
1344: case INDEX_op_sar_i32:
1345: if (const_args[2]) {
1346: tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1347: } else {
1348: tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1349: }
1350: break;
1351: case INDEX_op_shl_i32:
1352: if (const_args[2]) {
1353: tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1354: } else {
1355: tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1356: }
1357: break;
1358: case INDEX_op_shr_i32:
1359: if (const_args[2]) {
1360: tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1361: } else {
1362: tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1363: }
1364: break;
1365:
1.1.1.4 root 1366: case INDEX_op_ext8s_i32:
1367: tcg_out_ext8s(s, args[0], args[1]);
1368: break;
1369: case INDEX_op_ext16s_i32:
1370: tcg_out_ext16s(s, args[0], args[1]);
1371: break;
1372:
1.1 root 1373: case INDEX_op_brcond_i32:
1374: tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1375: break;
1376: case INDEX_op_brcond2_i32:
1377: tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1378: break;
1379:
1.1.1.4 root 1380: case INDEX_op_setcond_i32:
1381: tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
1382: break;
1383: case INDEX_op_setcond2_i32:
1384: tcg_out_setcond2(s, args[5], args[0], args[1], args[2], args[3], args[4]);
1385: break;
1386:
1.1 root 1387: case INDEX_op_qemu_ld8u:
1388: tcg_out_qemu_ld(s, args, 0);
1389: break;
1390: case INDEX_op_qemu_ld8s:
1391: tcg_out_qemu_ld(s, args, 0 | 4);
1392: break;
1393: case INDEX_op_qemu_ld16u:
1394: tcg_out_qemu_ld(s, args, 1);
1395: break;
1396: case INDEX_op_qemu_ld16s:
1397: tcg_out_qemu_ld(s, args, 1 | 4);
1398: break;
1.1.1.4 root 1399: case INDEX_op_qemu_ld32:
1.1 root 1400: tcg_out_qemu_ld(s, args, 2);
1401: break;
1402: case INDEX_op_qemu_ld64:
1403: tcg_out_qemu_ld(s, args, 3);
1404: break;
1405: case INDEX_op_qemu_st8:
1406: tcg_out_qemu_st(s, args, 0);
1407: break;
1408: case INDEX_op_qemu_st16:
1409: tcg_out_qemu_st(s, args, 1);
1410: break;
1411: case INDEX_op_qemu_st32:
1412: tcg_out_qemu_st(s, args, 2);
1413: break;
1414: case INDEX_op_qemu_st64:
1415: tcg_out_qemu_st(s, args, 3);
1416: break;
1417:
1418: default:
1419: tcg_abort();
1420: }
1421: }
1422:
1423: static const TCGTargetOpDef mips_op_defs[] = {
1424: { INDEX_op_exit_tb, { } },
1425: { INDEX_op_goto_tb, { } },
1426: { INDEX_op_call, { "C" } },
1427: { INDEX_op_jmp, { "r" } },
1428: { INDEX_op_br, { } },
1429:
1430: { INDEX_op_mov_i32, { "r", "r" } },
1431: { INDEX_op_movi_i32, { "r" } },
1432: { INDEX_op_ld8u_i32, { "r", "r" } },
1433: { INDEX_op_ld8s_i32, { "r", "r" } },
1434: { INDEX_op_ld16u_i32, { "r", "r" } },
1435: { INDEX_op_ld16s_i32, { "r", "r" } },
1436: { INDEX_op_ld_i32, { "r", "r" } },
1437: { INDEX_op_st8_i32, { "rZ", "r" } },
1438: { INDEX_op_st16_i32, { "rZ", "r" } },
1439: { INDEX_op_st_i32, { "rZ", "r" } },
1440:
1441: { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
1442: { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1443: { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1444: { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1445: { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1446: { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1447: { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1448: { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
1449:
1450: { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
1.1.1.4 root 1451: { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
1.1 root 1452: { INDEX_op_not_i32, { "r", "rZ" } },
1453: { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1454: { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1455:
1456: { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
1457: { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
1458: { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
1459:
1.1.1.4 root 1460: { INDEX_op_ext8s_i32, { "r", "rZ" } },
1461: { INDEX_op_ext16s_i32, { "r", "rZ" } },
1462:
1.1 root 1463: { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1.1.1.4 root 1464: { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
1465: { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
1.1 root 1466:
1467: { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1468: { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1469: { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1470:
1471: #if TARGET_LONG_BITS == 32
1472: { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1473: { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1474: { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1475: { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1.1.1.4 root 1476: { INDEX_op_qemu_ld32, { "L", "lZ" } },
1.1 root 1477: { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1478:
1479: { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1480: { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1481: { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1482: { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1483: #else
1484: { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1485: { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1486: { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1487: { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1.1.1.4 root 1488: { INDEX_op_qemu_ld32, { "L", "lZ", "lZ" } },
1.1 root 1489: { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1490:
1491: { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1492: { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1493: { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1494: { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1495: #endif
1496: { -1 },
1497: };
1498:
1499: static int tcg_target_callee_save_regs[] = {
1.1.1.6 root 1500: TCG_REG_S0, /* used for the global env (TCG_AREG0) */
1.1 root 1501: TCG_REG_S1,
1502: TCG_REG_S2,
1503: TCG_REG_S3,
1504: TCG_REG_S4,
1505: TCG_REG_S5,
1506: TCG_REG_S6,
1507: TCG_REG_S7,
1508: TCG_REG_GP,
1.1.1.3 root 1509: TCG_REG_FP,
1.1 root 1510: TCG_REG_RA, /* should be last for ABI compliance */
1511: };
1512:
1513: /* Generate global QEMU prologue and epilogue code */
1.1.1.4 root 1514: static void tcg_target_qemu_prologue(TCGContext *s)
1.1 root 1515: {
1516: int i, frame_size;
1517:
1518: /* reserve some stack space */
1519: frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1520: + TCG_STATIC_CALL_ARGS_SIZE;
1521: frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1522: ~(TCG_TARGET_STACK_ALIGN - 1);
1523:
1524: /* TB prologue */
1525: tcg_out_addi(s, TCG_REG_SP, -frame_size);
1526: for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1527: tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1528: TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1529: }
1530:
1531: /* Call generated code */
1.1.1.6 root 1532: tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
1533: tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1.1 root 1534: tb_ret_addr = s->code_ptr;
1535:
1536: /* TB epilogue */
1537: for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1538: tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1539: TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1540: }
1541:
1542: tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1543: tcg_out_addi(s, TCG_REG_SP, frame_size);
1544: }
1545:
1.1.1.4 root 1546: static void tcg_target_init(TCGContext *s)
1.1 root 1547: {
1548: tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1549: tcg_regset_set(tcg_target_call_clobber_regs,
1550: (1 << TCG_REG_V0) |
1551: (1 << TCG_REG_V1) |
1552: (1 << TCG_REG_A0) |
1553: (1 << TCG_REG_A1) |
1554: (1 << TCG_REG_A2) |
1555: (1 << TCG_REG_A3) |
1556: (1 << TCG_REG_T1) |
1557: (1 << TCG_REG_T2) |
1558: (1 << TCG_REG_T3) |
1559: (1 << TCG_REG_T4) |
1560: (1 << TCG_REG_T5) |
1561: (1 << TCG_REG_T6) |
1562: (1 << TCG_REG_T7) |
1563: (1 << TCG_REG_T8) |
1564: (1 << TCG_REG_T9));
1565:
1566: tcg_regset_clear(s->reserved_regs);
1567: tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1568: tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0); /* kernel use only */
1569: tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1); /* kernel use only */
1570: tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT); /* internal use */
1571: tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0); /* internal use */
1572: tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */
1573: tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
1574:
1575: tcg_add_target_add_op_defs(mips_op_defs);
1.1.1.8 ! root 1576: tcg_set_frame(s, TCG_AREG0, offsetof(CPUArchState, temp_buf),
1.1.1.6 root 1577: CPU_TEMP_BUF_NLONGS * sizeof(long));
1.1 root 1578: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.