Statistics
| Branch: | Revision:

root / tcg / mips / tcg-target.c @ 18fec301

History | View | Annotate | Download (49.1 kB)

1
/*
2
 * Tiny Code Generator for QEMU
3
 *
4
 * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
5
 * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
6
 * Based on i386/tcg-target.c - Copyright (c) 2008 Fabrice Bellard
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
# if defined(CONFIG_TCG_PASS_AREG0) && (TARGET_LONG_BITS == 64)
221
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
222
# endif
223
#endif
224
        break;
225
    case 'S': /* qemu_st constraint */
226
        ct->ct |= TCG_CT_REG;
227
        tcg_regset_set(ct->u.regs, 0xffffffff);
228
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
229
#if defined(CONFIG_SOFTMMU)
230
# if (defined(CONFIG_TCG_PASS_AREG0) && TARGET_LONG_BITS == 32) || \
231
     (!defined(CONFIG_TCG_PASS_AREG0) && TARGET_LONG_BITS == 64)
232
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
233
# endif
234
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
235
# if defined(CONFIG_TCG_PASS_AREG0) && TARGET_LONG_BITS == 64
236
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3);
237
# endif
238
#endif
239
        break;
240
    case 'I':
241
        ct->ct |= TCG_CT_CONST_U16;
242
        break;
243
    case 'J':
244
        ct->ct |= TCG_CT_CONST_S16;
245
        break;
246
    case 'Z':
247
        /* We are cheating a bit here, using the fact that the register
248
           ZERO is also the register number 0. Hence there is no need
249
           to check for const_args in each instruction. */
250
        ct->ct |= TCG_CT_CONST_ZERO;
251
        break;
252
    default:
253
        return -1;
254
    }
255
    ct_str++;
256
    *pct_str = ct_str;
257
    return 0;
258
}
259

    
260
/* test if a constant matches the constraint */
261
static inline int tcg_target_const_match(tcg_target_long val,
262
                                         const TCGArgConstraint *arg_ct)
263
{
264
    int ct;
265
    ct = arg_ct->ct;
266
    if (ct & TCG_CT_CONST)
267
        return 1;
268
    else if ((ct & TCG_CT_CONST_ZERO) && val == 0)
269
        return 1;
270
    else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val)
271
        return 1;
272
    else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val)
273
        return 1;
274
    else
275
        return 0;
276
}
277

    
278
/* instruction opcodes */
279
enum {
280
    OPC_BEQ      = 0x04 << 26,
281
    OPC_BNE      = 0x05 << 26,
282
    OPC_ADDIU    = 0x09 << 26,
283
    OPC_SLTI     = 0x0A << 26,
284
    OPC_SLTIU    = 0x0B << 26,
285
    OPC_ANDI     = 0x0C << 26,
286
    OPC_ORI      = 0x0D << 26,
287
    OPC_XORI     = 0x0E << 26,
288
    OPC_LUI      = 0x0F << 26,
289
    OPC_LB       = 0x20 << 26,
290
    OPC_LH       = 0x21 << 26,
291
    OPC_LW       = 0x23 << 26,
292
    OPC_LBU      = 0x24 << 26,
293
    OPC_LHU      = 0x25 << 26,
294
    OPC_LWU      = 0x27 << 26,
295
    OPC_SB       = 0x28 << 26,
296
    OPC_SH       = 0x29 << 26,
297
    OPC_SW       = 0x2B << 26,
298

    
299
    OPC_SPECIAL  = 0x00 << 26,
300
    OPC_SLL      = OPC_SPECIAL | 0x00,
301
    OPC_SRL      = OPC_SPECIAL | 0x02,
302
    OPC_SRA      = OPC_SPECIAL | 0x03,
303
    OPC_SLLV     = OPC_SPECIAL | 0x04,
304
    OPC_SRLV     = OPC_SPECIAL | 0x06,
305
    OPC_SRAV     = OPC_SPECIAL | 0x07,
306
    OPC_JR       = OPC_SPECIAL | 0x08,
307
    OPC_JALR     = OPC_SPECIAL | 0x09,
308
    OPC_MFHI     = OPC_SPECIAL | 0x10,
309
    OPC_MFLO     = OPC_SPECIAL | 0x12,
310
    OPC_MULT     = OPC_SPECIAL | 0x18,
311
    OPC_MULTU    = OPC_SPECIAL | 0x19,
312
    OPC_DIV      = OPC_SPECIAL | 0x1A,
313
    OPC_DIVU     = OPC_SPECIAL | 0x1B,
314
    OPC_ADDU     = OPC_SPECIAL | 0x21,
315
    OPC_SUBU     = OPC_SPECIAL | 0x23,
316
    OPC_AND      = OPC_SPECIAL | 0x24,
317
    OPC_OR       = OPC_SPECIAL | 0x25,
318
    OPC_XOR      = OPC_SPECIAL | 0x26,
319
    OPC_NOR      = OPC_SPECIAL | 0x27,
320
    OPC_SLT      = OPC_SPECIAL | 0x2A,
321
    OPC_SLTU     = OPC_SPECIAL | 0x2B,
322

    
323
    OPC_SPECIAL3 = 0x1f << 26,
324
    OPC_SEB      = OPC_SPECIAL3 | 0x420,
325
    OPC_SEH      = OPC_SPECIAL3 | 0x620,
326
};
327

    
328
/*
329
 * Type reg
330
 */
331
static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int rt)
332
{
333
    int32_t inst;
334

    
335
    inst = opc;
336
    inst |= (rs & 0x1F) << 21;
337
    inst |= (rt & 0x1F) << 16;
338
    inst |= (rd & 0x1F) << 11;
339
    tcg_out32(s, inst);
340
}
341

    
342
/*
343
 * Type immediate
344
 */
345
static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int imm)
346
{
347
    int32_t inst;
348

    
349
    inst = opc;
350
    inst |= (rs & 0x1F) << 21;
351
    inst |= (rt & 0x1F) << 16;
352
    inst |= (imm & 0xffff);
353
    tcg_out32(s, inst);
354
}
355

    
356
/*
357
 * Type branch
358
 */
359
static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
360
{
361
    /* We pay attention here to not modify the branch target by reading
362
       the existing value and using it again. This ensure that caches and
363
       memory are kept coherent during retranslation. */
364
    uint16_t offset = (uint16_t)(*(uint32_t *) s->code_ptr);
365

    
366
    tcg_out_opc_imm(s, opc, rt, rs, offset);
367
}
368

    
369
/*
370
 * Type sa
371
 */
372
static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa)
373
{
374
    int32_t inst;
375

    
376
    inst = opc;
377
    inst |= (rt & 0x1F) << 16;
378
    inst |= (rd & 0x1F) << 11;
379
    inst |= (sa & 0x1F) <<  6;
380
    tcg_out32(s, inst);
381

    
382
}
383

    
384
static inline void tcg_out_nop(TCGContext *s)
385
{
386
    tcg_out32(s, 0);
387
}
388

    
389
static inline void tcg_out_mov(TCGContext *s, TCGType type,
390
                               TCGReg ret, TCGReg arg)
391
{
392
    /* Simple reg-reg move, optimising out the 'do nothing' case */
393
    if (ret != arg) {
394
        tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
395
    }
396
}
397

    
398
static inline void tcg_out_movi(TCGContext *s, TCGType type,
399
                                TCGReg reg, tcg_target_long arg)
400
{
401
    if (arg == (int16_t)arg) {
402
        tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
403
    } else if (arg == (uint16_t)arg) {
404
        tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
405
    } else {
406
        tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
407
        tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
408
    }
409
}
410

    
411
static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
412
{
413
    /* ret and arg can't be register at */
414
    if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
415
        tcg_abort();
416
    }
417

    
418
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
419
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
420

    
421
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
422
    tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
423
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
424
}
425

    
426
static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
427
{
428
    /* ret and arg can't be register at */
429
    if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
430
        tcg_abort();
431
    }
432

    
433
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
434
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
435

    
436
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
437
    tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
438
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
439
}
440

    
441
static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
442
{
443
    /* ret and arg must be different and can't be register at */
444
    if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
445
        tcg_abort();
446
    }
447

    
448
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
449

    
450
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
451
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
452

    
453
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
454
    tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
455
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
456

    
457
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
458
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
459
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
460
}
461

    
462
static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg)
463
{
464
#ifdef _MIPS_ARCH_MIPS32R2
465
    tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
466
#else
467
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
468
    tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24);
469
#endif
470
}
471

    
472
static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg)
473
{
474
#ifdef _MIPS_ARCH_MIPS32R2
475
    tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
476
#else
477
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
478
    tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
479
#endif
480
}
481

    
482
static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
483
                              int arg1, tcg_target_long arg2)
484
{
485
    if (arg2 == (int16_t) arg2) {
486
        tcg_out_opc_imm(s, opc, arg, arg1, arg2);
487
    } else {
488
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
489
        tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
490
        tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
491
    }
492
}
493

    
494
static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
495
                              TCGReg arg1, tcg_target_long arg2)
496
{
497
    tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
498
}
499

    
500
static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
501
                              TCGReg arg1, tcg_target_long arg2)
502
{
503
    tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
504
}
505

    
506
static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
507
{
508
    if (val == (int16_t)val) {
509
        tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
510
    } else {
511
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
512
        tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
513
    }
514
}
515

    
516
/* Helper routines for marshalling helper function arguments into
517
 * the correct registers and stack.
518
 * arg_num is where we want to put this argument, and is updated to be ready
519
 * for the next call. arg is the argument itself. Note that arg_num 0..3 is
520
 * real registers, 4+ on stack.
521
 *
522
 * We provide routines for arguments which are: immediate, 32 bit
523
 * value in register, 16 and 8 bit values in register (which must be zero
524
 * extended before use) and 64 bit value in a lo:hi register pair.
525
 */
526
#define DEFINE_TCG_OUT_CALL_IARG(NAME, ARGPARAM)                               \
527
    static inline void NAME(TCGContext *s, int *arg_num, ARGPARAM)             \
528
    {                                                                          \
529
    if (*arg_num < 4) {                                                        \
530
        DEFINE_TCG_OUT_CALL_IARG_GET_ARG(tcg_target_call_iarg_regs[*arg_num]); \
531
    } else {                                                                   \
532
        DEFINE_TCG_OUT_CALL_IARG_GET_ARG(TCG_REG_AT);                          \
533
        tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 4 * (*arg_num));   \
534
    }                                                                          \
535
    (*arg_num)++;                                                              \
536
}
537
#define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \
538
    tcg_out_opc_imm(s, OPC_ANDI, A, arg, 0xff);
539
DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_reg8, TCGReg arg)
540
#undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG
541
#define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \
542
    tcg_out_opc_imm(s, OPC_ANDI, A, arg, 0xffff);
543
DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_reg16, TCGReg arg)
544
#undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG
545
#define DEFINE_TCG_OUT_CALL_IARG_GET_ARG(A) \
546
    tcg_out_movi(s, TCG_TYPE_I32, A, arg);
547
DEFINE_TCG_OUT_CALL_IARG(tcg_out_call_iarg_imm32, uint32_t arg)
548
#undef DEFINE_TCG_OUT_CALL_IARG_GET_ARG
549

    
550
/* We don't use the macro for this one to avoid an unnecessary reg-reg
551
   move when storing to the stack. */
552
static inline void tcg_out_call_iarg_reg32(TCGContext *s, int *arg_num,
553
                                           TCGReg arg)
554
{
555
    if (*arg_num < 4) {
556
        tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[*arg_num], arg);
557
    } else {
558
        tcg_out_st(s, TCG_TYPE_I32, arg, TCG_REG_SP, 4 * (*arg_num));
559
    }
560
    (*arg_num)++;
561
}
562

    
563
static inline void tcg_out_call_iarg_reg64(TCGContext *s, int *arg_num,
564
                                           TCGReg arg_low, TCGReg arg_high)
565
{
566
    (*arg_num) = (*arg_num + 1) & ~1;
567

    
568
#if defined(TCG_TARGET_WORDS_BIGENDIAN)
569
    tcg_out_call_iarg_reg32(s, arg_num, arg_high);
570
    tcg_out_call_iarg_reg32(s, arg_num, arg_low);
571
#else
572
    tcg_out_call_iarg_reg32(s, arg_num, arg_low);
573
    tcg_out_call_iarg_reg32(s, arg_num, arg_high);
574
#endif
575
}
576

    
577
static void tcg_out_brcond(TCGContext *s, TCGCond cond, int arg1,
578
                           int arg2, int label_index)
579
{
580
    TCGLabel *l = &s->labels[label_index];
581

    
582
    switch (cond) {
583
    case TCG_COND_EQ:
584
        tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
585
        break;
586
    case TCG_COND_NE:
587
        tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
588
        break;
589
    case TCG_COND_LT:
590
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
591
        tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
592
        break;
593
    case TCG_COND_LTU:
594
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
595
        tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
596
        break;
597
    case TCG_COND_GE:
598
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
599
        tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
600
        break;
601
    case TCG_COND_GEU:
602
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
603
        tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
604
        break;
605
    case TCG_COND_LE:
606
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
607
        tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
608
        break;
609
    case TCG_COND_LEU:
610
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
611
        tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
612
        break;
613
    case TCG_COND_GT:
614
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
615
        tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
616
        break;
617
    case TCG_COND_GTU:
618
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
619
        tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
620
        break;
621
    default:
622
        tcg_abort();
623
        break;
624
    }
625
    if (l->has_value) {
626
        reloc_pc16(s->code_ptr - 4, l->u.value);
627
    } else {
628
        tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
629
    }
630
    tcg_out_nop(s);
631
}
632

    
633
/* XXX: we implement it at the target level to avoid having to
634
   handle cross basic blocks temporaries */
635
static void tcg_out_brcond2(TCGContext *s, TCGCond cond, int arg1,
636
                            int arg2, int arg3, int arg4, int label_index)
637
{
638
    void *label_ptr;
639

    
640
    switch(cond) {
641
    case TCG_COND_NE:
642
        tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
643
        tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
644
        return;
645
    case TCG_COND_EQ:
646
        break;
647
    case TCG_COND_LT:
648
    case TCG_COND_LE:
649
        tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
650
        break;
651
    case TCG_COND_GT:
652
    case TCG_COND_GE:
653
        tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
654
        break;
655
    case TCG_COND_LTU:
656
    case TCG_COND_LEU:
657
        tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
658
        break;
659
    case TCG_COND_GTU:
660
    case TCG_COND_GEU:
661
        tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
662
        break;
663
    default:
664
        tcg_abort();
665
    }
666

    
667
    label_ptr = s->code_ptr;
668
    tcg_out_opc_br(s, OPC_BNE, arg2, arg4);
669
    tcg_out_nop(s);
670

    
671
    switch(cond) {
672
    case TCG_COND_EQ:
673
        tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
674
        break;
675
    case TCG_COND_LT:
676
    case TCG_COND_LTU:
677
        tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
678
        break;
679
    case TCG_COND_LE:
680
    case TCG_COND_LEU:
681
        tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
682
        break;
683
    case TCG_COND_GT:
684
    case TCG_COND_GTU:
685
        tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
686
        break;
687
    case TCG_COND_GE:
688
    case TCG_COND_GEU:
689
        tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
690
        break;
691
    default:
692
        tcg_abort();
693
    }
694

    
695
    reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
696
}
697

    
698
static void tcg_out_setcond(TCGContext *s, TCGCond cond, int ret,
699
                            int arg1, int arg2)
700
{
701
    switch (cond) {
702
    case TCG_COND_EQ:
703
        if (arg1 == 0) {
704
            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg2, 1);
705
        } else if (arg2 == 0) {
706
            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
707
        } else {
708
            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
709
            tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
710
        }
711
        break;
712
    case TCG_COND_NE:
713
        if (arg1 == 0) {
714
            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg2);
715
        } else if (arg2 == 0) {
716
            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
717
        } else {
718
            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
719
            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
720
        }
721
        break;
722
    case TCG_COND_LT:
723
        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
724
        break;
725
    case TCG_COND_LTU:
726
        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
727
        break;
728
    case TCG_COND_GE:
729
        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
730
        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
731
        break;
732
    case TCG_COND_GEU:
733
        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
734
        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
735
        break;
736
    case TCG_COND_LE:
737
        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
738
        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
739
        break;
740
    case TCG_COND_LEU:
741
        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
742
        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
743
        break;
744
    case TCG_COND_GT:
745
        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
746
        break;
747
    case TCG_COND_GTU:
748
        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
749
        break;
750
    default:
751
        tcg_abort();
752
        break;
753
    }
754
}
755

    
756
/* XXX: we implement it at the target level to avoid having to
757
   handle cross basic blocks temporaries */
758
static void tcg_out_setcond2(TCGContext *s, TCGCond cond, int ret,
759
                             int arg1, int arg2, int arg3, int arg4)
760
{
761
    switch (cond) {
762
    case TCG_COND_EQ:
763
        tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_AT, arg2, arg4);
764
        tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg1, arg3);
765
        tcg_out_opc_reg(s, OPC_AND, ret, TCG_REG_AT, TCG_REG_T0);
766
        return;
767
    case TCG_COND_NE:
768
        tcg_out_setcond(s, TCG_COND_NE, TCG_REG_AT, arg2, arg4);
769
        tcg_out_setcond(s, TCG_COND_NE, TCG_REG_T0, arg1, arg3);
770
        tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_AT, TCG_REG_T0);
771
        return;
772
    case TCG_COND_LT:
773
    case TCG_COND_LE:
774
        tcg_out_setcond(s, TCG_COND_LT, TCG_REG_AT, arg2, arg4);
775
        break;
776
    case TCG_COND_GT:
777
    case TCG_COND_GE:
778
        tcg_out_setcond(s, TCG_COND_GT, TCG_REG_AT, arg2, arg4);
779
        break;
780
    case TCG_COND_LTU:
781
    case TCG_COND_LEU:
782
        tcg_out_setcond(s, TCG_COND_LTU, TCG_REG_AT, arg2, arg4);
783
        break;
784
    case TCG_COND_GTU:
785
    case TCG_COND_GEU:
786
        tcg_out_setcond(s, TCG_COND_GTU, TCG_REG_AT, arg2, arg4);
787
        break;
788
    default:
789
        tcg_abort();
790
        break;
791
    }
792

    
793
    tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg2, arg4);
794

    
795
    switch(cond) {
796
    case TCG_COND_LT:
797
    case TCG_COND_LTU:
798
        tcg_out_setcond(s, TCG_COND_LTU, ret, arg1, arg3);
799
        break;
800
    case TCG_COND_LE:
801
    case TCG_COND_LEU:
802
        tcg_out_setcond(s, TCG_COND_LEU, ret, arg1, arg3);
803
        break;
804
    case TCG_COND_GT:
805
    case TCG_COND_GTU:
806
        tcg_out_setcond(s, TCG_COND_GTU, ret, arg1, arg3);
807
        break;
808
    case TCG_COND_GE:
809
    case TCG_COND_GEU:
810
        tcg_out_setcond(s, TCG_COND_GEU, ret, arg1, arg3);
811
        break;
812
    default:
813
        tcg_abort();
814
    }
815

    
816
    tcg_out_opc_reg(s, OPC_AND, ret, ret, TCG_REG_T0);
817
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
818
}
819

    
820
#if defined(CONFIG_SOFTMMU)
821

    
822
#include "../../softmmu_defs.h"
823

    
824
#ifdef CONFIG_TCG_PASS_AREG0
825
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
826
   int mmu_idx) */
827
static const void * const qemu_ld_helpers[4] = {
828
    helper_ldb_mmu,
829
    helper_ldw_mmu,
830
    helper_ldl_mmu,
831
    helper_ldq_mmu,
832
};
833

    
834
/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
835
   uintxx_t val, int mmu_idx) */
836
static const void * const qemu_st_helpers[4] = {
837
    helper_stb_mmu,
838
    helper_stw_mmu,
839
    helper_stl_mmu,
840
    helper_stq_mmu,
841
};
842
#else
843
/* legacy helper signature: __ld_mmu(target_ulong addr, int
844
   mmu_idx) */
845
static void *qemu_ld_helpers[4] = {
846
    __ldb_mmu,
847
    __ldw_mmu,
848
    __ldl_mmu,
849
    __ldq_mmu,
850
};
851

    
852
/* legacy helper signature: __st_mmu(target_ulong addr, uintxx_t val,
853
   int mmu_idx) */
854
static void *qemu_st_helpers[4] = {
855
    __stb_mmu,
856
    __stw_mmu,
857
    __stl_mmu,
858
    __stq_mmu,
859
};
860
#endif
861
#endif
862

    
863
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
864
                            int opc)
865
{
866
    int addr_regl, addr_meml;
867
    int data_regl, data_regh, data_reg1, data_reg2;
868
    int mem_index, s_bits;
869
#if defined(CONFIG_SOFTMMU)
870
    void *label1_ptr, *label2_ptr;
871
    int arg_num;
872
#endif
873
#if TARGET_LONG_BITS == 64
874
# if defined(CONFIG_SOFTMMU)
875
    uint8_t *label3_ptr;
876
# endif
877
    int addr_regh, addr_memh;
878
#endif
879
    data_regl = *args++;
880
    if (opc == 3)
881
        data_regh = *args++;
882
    else
883
        data_regh = 0;
884
    addr_regl = *args++;
885
#if TARGET_LONG_BITS == 64
886
    addr_regh = *args++;
887
#endif
888
    mem_index = *args;
889
    s_bits = opc & 3;
890

    
891
    if (opc == 3) {
892
#if defined(TCG_TARGET_WORDS_BIGENDIAN)
893
        data_reg1 = data_regh;
894
        data_reg2 = data_regl;
895
#else
896
        data_reg1 = data_regl;
897
        data_reg2 = data_regh;
898
#endif
899
    } else {
900
        data_reg1 = data_regl;
901
        data_reg2 = 0;
902
    }
903
#if TARGET_LONG_BITS == 64
904
# if defined(TCG_TARGET_WORDS_BIGENDIAN)
905
    addr_memh = 0;
906
    addr_meml = 4;
907
# else
908
    addr_memh = 4;
909
    addr_meml = 0;
910
# endif
911
#else
912
    addr_meml = 0;
913
#endif
914

    
915
#if defined(CONFIG_SOFTMMU)
916
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
917
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
918
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
919
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
920
                    offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + addr_meml);
921
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
922
    tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
923

    
924
# if TARGET_LONG_BITS == 64
925
    label3_ptr = s->code_ptr;
926
    tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
927
    tcg_out_nop(s);
928

    
929
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
930
                    offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + addr_memh);
931

    
932
    label1_ptr = s->code_ptr;
933
    tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
934
    tcg_out_nop(s);
935

    
936
    reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
937
# else
938
    label1_ptr = s->code_ptr;
939
    tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
940
    tcg_out_nop(s);
941
# endif
942

    
943
    /* slow path */
944
    arg_num = 0;
945
# ifdef CONFIG_TCG_PASS_AREG0
946
    tcg_out_call_iarg_reg32(s, &arg_num, TCG_AREG0);
947
# endif
948
# if TARGET_LONG_BITS == 64
949
    tcg_out_call_iarg_reg64(s, &arg_num, addr_regl, addr_regh);
950
# else
951
    tcg_out_call_iarg_reg32(s, &arg_num, addr_regl);
952
# endif
953
    tcg_out_call_iarg_imm32(s, &arg_num, mem_index);
954
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
955
    tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
956
    tcg_out_nop(s);
957

    
958
    switch(opc) {
959
    case 0:
960
        tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
961
        break;
962
    case 0 | 4:
963
        tcg_out_ext8s(s, data_reg1, TCG_REG_V0);
964
        break;
965
    case 1:
966
        tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
967
        break;
968
    case 1 | 4:
969
        tcg_out_ext16s(s, data_reg1, TCG_REG_V0);
970
        break;
971
    case 2:
972
        tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
973
        break;
974
    case 3:
975
        tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_V1);
976
        tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
977
        break;
978
    default:
979
        tcg_abort();
980
    }
981

    
982
    label2_ptr = s->code_ptr;
983
    tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
984
    tcg_out_nop(s);
985

    
986
    /* label1: fast path */
987
    reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
988

    
989
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
990
                    offsetof(CPUArchState, tlb_table[mem_index][0].addend));
991
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
992
#else
993
    if (GUEST_BASE == (int16_t)GUEST_BASE) {
994
        tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_V0, addr_regl, GUEST_BASE);
995
    } else {
996
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, GUEST_BASE);
997
        tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
998
    }
999
#endif
1000

    
1001
    switch(opc) {
1002
    case 0:
1003
        tcg_out_opc_imm(s, OPC_LBU, data_reg1, TCG_REG_V0, 0);
1004
        break;
1005
    case 0 | 4:
1006
        tcg_out_opc_imm(s, OPC_LB, data_reg1, TCG_REG_V0, 0);
1007
        break;
1008
    case 1:
1009
        if (TCG_NEED_BSWAP) {
1010
            tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
1011
            tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
1012
        } else {
1013
            tcg_out_opc_imm(s, OPC_LHU, data_reg1, TCG_REG_V0, 0);
1014
        }
1015
        break;
1016
    case 1 | 4:
1017
        if (TCG_NEED_BSWAP) {
1018
            tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
1019
            tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
1020
        } else {
1021
            tcg_out_opc_imm(s, OPC_LH, data_reg1, TCG_REG_V0, 0);
1022
        }
1023
        break;
1024
    case 2:
1025
        if (TCG_NEED_BSWAP) {
1026
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
1027
            tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
1028
        } else {
1029
            tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
1030
        }
1031
        break;
1032
    case 3:
1033
        if (TCG_NEED_BSWAP) {
1034
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 4);
1035
            tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
1036
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
1037
            tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
1038
        } else {
1039
            tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
1040
            tcg_out_opc_imm(s, OPC_LW, data_reg2, TCG_REG_V0, 4);
1041
        }
1042
        break;
1043
    default:
1044
        tcg_abort();
1045
    }
1046

    
1047
#if defined(CONFIG_SOFTMMU)
1048
    reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1049
#endif
1050
}
1051

    
1052
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
1053
                            int opc)
1054
{
1055
    int addr_regl, addr_meml;
1056
    int data_regl, data_regh, data_reg1, data_reg2;
1057
    int mem_index, s_bits;
1058
#if defined(CONFIG_SOFTMMU)
1059
    uint8_t *label1_ptr, *label2_ptr;
1060
    int arg_num;
1061
#endif
1062
#if TARGET_LONG_BITS == 64
1063
# if defined(CONFIG_SOFTMMU)
1064
    uint8_t *label3_ptr;
1065
# endif
1066
    int addr_regh, addr_memh;
1067
#endif
1068

    
1069
    data_regl = *args++;
1070
    if (opc == 3) {
1071
        data_regh = *args++;
1072
#if defined(TCG_TARGET_WORDS_BIGENDIAN)
1073
        data_reg1 = data_regh;
1074
        data_reg2 = data_regl;
1075
#else
1076
        data_reg1 = data_regl;
1077
        data_reg2 = data_regh;
1078
#endif
1079
    } else {
1080
        data_reg1 = data_regl;
1081
        data_reg2 = 0;
1082
        data_regh = 0;
1083
    }
1084
    addr_regl = *args++;
1085
#if TARGET_LONG_BITS == 64
1086
    addr_regh = *args++;
1087
# if defined(TCG_TARGET_WORDS_BIGENDIAN)
1088
    addr_memh = 0;
1089
    addr_meml = 4;
1090
# else
1091
    addr_memh = 4;
1092
    addr_meml = 0;
1093
# endif
1094
#else
1095
    addr_meml = 0;
1096
#endif
1097
    mem_index = *args;
1098
    s_bits = opc;
1099

    
1100
#if defined(CONFIG_SOFTMMU)
1101
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1102
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
1103
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
1104
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1105
                    offsetof(CPUArchState, tlb_table[mem_index][0].addr_write) + addr_meml);
1106
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
1107
    tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
1108

    
1109
# if TARGET_LONG_BITS == 64
1110
    label3_ptr = s->code_ptr;
1111
    tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
1112
    tcg_out_nop(s);
1113

    
1114
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
1115
                    offsetof(CPUArchState, tlb_table[mem_index][0].addr_write) + addr_memh);
1116

    
1117
    label1_ptr = s->code_ptr;
1118
    tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1119
    tcg_out_nop(s);
1120

    
1121
    reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
1122
# else
1123
    label1_ptr = s->code_ptr;
1124
    tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1125
    tcg_out_nop(s);
1126
# endif
1127

    
1128
    /* slow path */
1129
    arg_num = 0;
1130
# ifdef CONFIG_TCG_PASS_AREG0
1131
    tcg_out_call_iarg_reg32(s, &arg_num, TCG_AREG0);
1132
# endif
1133
# if TARGET_LONG_BITS == 64
1134
    tcg_out_call_iarg_reg64(s, &arg_num, addr_regl, addr_regh);
1135
# else
1136
    tcg_out_call_iarg_reg32(s, &arg_num, addr_regl);
1137
# endif
1138
    switch(opc) {
1139
    case 0:
1140
        tcg_out_call_iarg_reg8(s, &arg_num, data_regl);
1141
        break;
1142
    case 1:
1143
        tcg_out_call_iarg_reg16(s, &arg_num, data_regl);
1144
        break;
1145
    case 2:
1146
        tcg_out_call_iarg_reg32(s, &arg_num, data_regl);
1147
        break;
1148
    case 3:
1149
        tcg_out_call_iarg_reg64(s, &arg_num, data_regl, data_regh);
1150
        break;
1151
    default:
1152
        tcg_abort();
1153
    }
1154
    tcg_out_call_iarg_imm32(s, &arg_num, mem_index);
1155
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
1156
    tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1157
    tcg_out_nop(s);
1158

    
1159
    label2_ptr = s->code_ptr;
1160
    tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1161
    tcg_out_nop(s);
1162

    
1163
    /* label1: fast path */
1164
    reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
1165

    
1166
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1167
                    offsetof(CPUArchState, tlb_table[mem_index][0].addend));
1168
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1169
#else
1170
    if (GUEST_BASE == (int16_t)GUEST_BASE) {
1171
        tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, addr_regl, GUEST_BASE);
1172
    } else {
1173
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, GUEST_BASE);
1174
        tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1175
    }
1176

    
1177
#endif
1178

    
1179
    switch(opc) {
1180
    case 0:
1181
        tcg_out_opc_imm(s, OPC_SB, data_reg1, TCG_REG_A0, 0);
1182
        break;
1183
    case 1:
1184
        if (TCG_NEED_BSWAP) {
1185
            tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
1186
            tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, TCG_REG_A0, 0);
1187
        } else {
1188
            tcg_out_opc_imm(s, OPC_SH, data_reg1, TCG_REG_A0, 0);
1189
        }
1190
        break;
1191
    case 2:
1192
        if (TCG_NEED_BSWAP) {
1193
            tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1194
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1195
        } else {
1196
            tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1197
        }
1198
        break;
1199
    case 3:
1200
        if (TCG_NEED_BSWAP) {
1201
            tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
1202
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1203
            tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1204
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 4);
1205
        } else {
1206
            tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1207
            tcg_out_opc_imm(s, OPC_SW, data_reg2, TCG_REG_A0, 4);
1208
        }
1209
        break;
1210
    default:
1211
        tcg_abort();
1212
    }
1213

    
1214
#if defined(CONFIG_SOFTMMU)
1215
    reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1216
#endif
1217
}
1218

    
1219
static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1220
                              const TCGArg *args, const int *const_args)
1221
{
1222
    switch(opc) {
1223
    case INDEX_op_exit_tb:
1224
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
1225
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
1226
        tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1227
        tcg_out_nop(s);
1228
        break;
1229
    case INDEX_op_goto_tb:
1230
        if (s->tb_jmp_offset) {
1231
            /* direct jump method */
1232
            tcg_abort();
1233
        } else {
1234
            /* indirect jump method */
1235
            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
1236
            tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
1237
            tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1238
        }
1239
        tcg_out_nop(s);
1240
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1241
        break;
1242
    case INDEX_op_call:
1243
        tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
1244
        tcg_out_nop(s);
1245
        break;
1246
    case INDEX_op_jmp:
1247
        tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
1248
        tcg_out_nop(s);
1249
        break;
1250
    case INDEX_op_br:
1251
        tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1252
        break;
1253

    
1254
    case INDEX_op_mov_i32:
1255
        tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
1256
        break;
1257
    case INDEX_op_movi_i32:
1258
        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1259
        break;
1260

    
1261
    case INDEX_op_ld8u_i32:
1262
        tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1263
        break;
1264
    case INDEX_op_ld8s_i32:
1265
        tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1266
        break;
1267
    case INDEX_op_ld16u_i32:
1268
        tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1269
        break;
1270
    case INDEX_op_ld16s_i32:
1271
        tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1272
        break;
1273
    case INDEX_op_ld_i32:
1274
        tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1275
        break;
1276
    case INDEX_op_st8_i32:
1277
        tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1278
        break;
1279
    case INDEX_op_st16_i32:
1280
        tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1281
        break;
1282
    case INDEX_op_st_i32:
1283
        tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1284
        break;
1285

    
1286
    case INDEX_op_add_i32:
1287
        if (const_args[2]) {
1288
            tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1289
        } else {
1290
            tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1291
        }
1292
        break;
1293
    case INDEX_op_add2_i32:
1294
        if (const_args[4]) {
1295
            tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1296
        } else {
1297
            tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1298
        }
1299
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1300
        if (const_args[5]) {
1301
            tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1302
        } else {
1303
             tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1304
        }
1305
        tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1306
        tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1307
        break;
1308
    case INDEX_op_sub_i32:
1309
        if (const_args[2]) {
1310
            tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1311
        } else {
1312
            tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1313
        }
1314
        break;
1315
    case INDEX_op_sub2_i32:
1316
        if (const_args[4]) {
1317
            tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1318
        } else {
1319
            tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1320
        }
1321
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1322
        if (const_args[5]) {
1323
            tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1324
        } else {
1325
             tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1326
        }
1327
        tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1328
        tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1329
        break;
1330
    case INDEX_op_mul_i32:
1331
        tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1332
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1333
        break;
1334
    case INDEX_op_mulu2_i32:
1335
        tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1336
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1337
        tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1338
        break;
1339
    case INDEX_op_div_i32:
1340
        tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1341
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1342
        break;
1343
    case INDEX_op_divu_i32:
1344
        tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1345
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1346
        break;
1347
    case INDEX_op_rem_i32:
1348
        tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1349
        tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1350
        break;
1351
    case INDEX_op_remu_i32:
1352
        tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1353
        tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1354
        break;
1355

    
1356
    case INDEX_op_and_i32:
1357
        if (const_args[2]) {
1358
            tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1359
        } else {
1360
            tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1361
        }
1362
        break;
1363
    case INDEX_op_or_i32:
1364
        if (const_args[2]) {
1365
            tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1366
        } else {
1367
            tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1368
        }
1369
        break;
1370
    case INDEX_op_nor_i32:
1371
        tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[2]);
1372
        break;
1373
    case INDEX_op_not_i32:
1374
        tcg_out_opc_reg(s, OPC_NOR, args[0], TCG_REG_ZERO, args[1]);
1375
        break;
1376
    case INDEX_op_xor_i32:
1377
        if (const_args[2]) {
1378
            tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1379
        } else {
1380
            tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1381
        }
1382
        break;
1383

    
1384
    case INDEX_op_sar_i32:
1385
        if (const_args[2]) {
1386
            tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1387
        } else {
1388
            tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1389
        }
1390
        break;
1391
    case INDEX_op_shl_i32:
1392
        if (const_args[2]) {
1393
            tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1394
        } else {
1395
            tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1396
        }
1397
        break;
1398
    case INDEX_op_shr_i32:
1399
        if (const_args[2]) {
1400
            tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1401
        } else {
1402
            tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1403
        }
1404
        break;
1405

    
1406
    case INDEX_op_ext8s_i32:
1407
        tcg_out_ext8s(s, args[0], args[1]);
1408
        break;
1409
    case INDEX_op_ext16s_i32:
1410
        tcg_out_ext16s(s, args[0], args[1]);
1411
        break;
1412

    
1413
    case INDEX_op_brcond_i32:
1414
        tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1415
        break;
1416
    case INDEX_op_brcond2_i32:
1417
        tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1418
        break;
1419

    
1420
    case INDEX_op_setcond_i32:
1421
        tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
1422
        break;
1423
    case INDEX_op_setcond2_i32:
1424
        tcg_out_setcond2(s, args[5], args[0], args[1], args[2], args[3], args[4]);
1425
        break;
1426

    
1427
    case INDEX_op_qemu_ld8u:
1428
        tcg_out_qemu_ld(s, args, 0);
1429
        break;
1430
    case INDEX_op_qemu_ld8s:
1431
        tcg_out_qemu_ld(s, args, 0 | 4);
1432
        break;
1433
    case INDEX_op_qemu_ld16u:
1434
        tcg_out_qemu_ld(s, args, 1);
1435
        break;
1436
    case INDEX_op_qemu_ld16s:
1437
        tcg_out_qemu_ld(s, args, 1 | 4);
1438
        break;
1439
    case INDEX_op_qemu_ld32:
1440
        tcg_out_qemu_ld(s, args, 2);
1441
        break;
1442
    case INDEX_op_qemu_ld64:
1443
        tcg_out_qemu_ld(s, args, 3);
1444
        break;
1445
    case INDEX_op_qemu_st8:
1446
        tcg_out_qemu_st(s, args, 0);
1447
        break;
1448
    case INDEX_op_qemu_st16:
1449
        tcg_out_qemu_st(s, args, 1);
1450
        break;
1451
    case INDEX_op_qemu_st32:
1452
        tcg_out_qemu_st(s, args, 2);
1453
        break;
1454
    case INDEX_op_qemu_st64:
1455
        tcg_out_qemu_st(s, args, 3);
1456
        break;
1457

    
1458
    default:
1459
        tcg_abort();
1460
    }
1461
}
1462

    
1463
static const TCGTargetOpDef mips_op_defs[] = {
1464
    { INDEX_op_exit_tb, { } },
1465
    { INDEX_op_goto_tb, { } },
1466
    { INDEX_op_call, { "C" } },
1467
    { INDEX_op_jmp, { "r" } },
1468
    { INDEX_op_br, { } },
1469

    
1470
    { INDEX_op_mov_i32, { "r", "r" } },
1471
    { INDEX_op_movi_i32, { "r" } },
1472
    { INDEX_op_ld8u_i32, { "r", "r" } },
1473
    { INDEX_op_ld8s_i32, { "r", "r" } },
1474
    { INDEX_op_ld16u_i32, { "r", "r" } },
1475
    { INDEX_op_ld16s_i32, { "r", "r" } },
1476
    { INDEX_op_ld_i32, { "r", "r" } },
1477
    { INDEX_op_st8_i32, { "rZ", "r" } },
1478
    { INDEX_op_st16_i32, { "rZ", "r" } },
1479
    { INDEX_op_st_i32, { "rZ", "r" } },
1480

    
1481
    { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
1482
    { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1483
    { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1484
    { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1485
    { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1486
    { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1487
    { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1488
    { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
1489

    
1490
    { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
1491
    { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
1492
    { INDEX_op_not_i32, { "r", "rZ" } },
1493
    { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1494
    { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1495

    
1496
    { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
1497
    { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
1498
    { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
1499

    
1500
    { INDEX_op_ext8s_i32, { "r", "rZ" } },
1501
    { INDEX_op_ext16s_i32, { "r", "rZ" } },
1502

    
1503
    { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1504
    { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
1505
    { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
1506

    
1507
    { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1508
    { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1509
    { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1510

    
1511
#if TARGET_LONG_BITS == 32
1512
    { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1513
    { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1514
    { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1515
    { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1516
    { INDEX_op_qemu_ld32, { "L", "lZ" } },
1517
    { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1518

    
1519
    { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1520
    { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1521
    { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1522
    { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1523
#else
1524
    { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1525
    { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1526
    { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1527
    { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1528
    { INDEX_op_qemu_ld32, { "L", "lZ", "lZ" } },
1529
    { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1530

    
1531
    { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1532
    { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1533
    { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1534
    { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1535
#endif
1536
    { -1 },
1537
};
1538

    
1539
static int tcg_target_callee_save_regs[] = {
1540
    TCG_REG_S0,       /* used for the global env (TCG_AREG0) */
1541
    TCG_REG_S1,
1542
    TCG_REG_S2,
1543
    TCG_REG_S3,
1544
    TCG_REG_S4,
1545
    TCG_REG_S5,
1546
    TCG_REG_S6,
1547
    TCG_REG_S7,
1548
    TCG_REG_GP,
1549
    TCG_REG_FP,
1550
    TCG_REG_RA,       /* should be last for ABI compliance */
1551
};
1552

    
1553
/* Generate global QEMU prologue and epilogue code */
1554
static void tcg_target_qemu_prologue(TCGContext *s)
1555
{
1556
    int i, frame_size;
1557

    
1558
    /* reserve some stack space */
1559
    frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1560
                 + TCG_STATIC_CALL_ARGS_SIZE;
1561
    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1562
                 ~(TCG_TARGET_STACK_ALIGN - 1);
1563

    
1564
    /* TB prologue */
1565
    tcg_out_addi(s, TCG_REG_SP, -frame_size);
1566
    for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1567
        tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1568
                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1569
    }
1570

    
1571
    /* Call generated code */
1572
    tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
1573
    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1574
    tb_ret_addr = s->code_ptr;
1575

    
1576
    /* TB epilogue */
1577
    for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1578
        tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1579
                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1580
    }
1581

    
1582
    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1583
    tcg_out_addi(s, TCG_REG_SP, frame_size);
1584
}
1585

    
1586
static void tcg_target_init(TCGContext *s)
1587
{
1588
    tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1589
    tcg_regset_set(tcg_target_call_clobber_regs,
1590
                   (1 << TCG_REG_V0) |
1591
                   (1 << TCG_REG_V1) |
1592
                   (1 << TCG_REG_A0) |
1593
                   (1 << TCG_REG_A1) |
1594
                   (1 << TCG_REG_A2) |
1595
                   (1 << TCG_REG_A3) |
1596
                   (1 << TCG_REG_T1) |
1597
                   (1 << TCG_REG_T2) |
1598
                   (1 << TCG_REG_T3) |
1599
                   (1 << TCG_REG_T4) |
1600
                   (1 << TCG_REG_T5) |
1601
                   (1 << TCG_REG_T6) |
1602
                   (1 << TCG_REG_T7) |
1603
                   (1 << TCG_REG_T8) |
1604
                   (1 << TCG_REG_T9));
1605

    
1606
    tcg_regset_clear(s->reserved_regs);
1607
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1608
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0);   /* kernel use only */
1609
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1);   /* kernel use only */
1610
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT);   /* internal use */
1611
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0);   /* internal use */
1612
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA);   /* return address */
1613
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);   /* stack pointer */
1614

    
1615
    tcg_add_target_add_op_defs(mips_op_defs);
1616
    tcg_set_frame(s, TCG_AREG0, offsetof(CPUArchState, temp_buf),
1617
                  CPU_TEMP_BUF_NLONGS * sizeof(long));
1618
}