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