Statistics
| Branch: | Revision:

root / tcg / mips / tcg-target.c @ 4cb26382

History | View | Annotate | Download (41.6 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
#endif
221
        break;
222
    case 'S': /* qemu_st constraint */
223
        ct->ct |= TCG_CT_REG;
224
        tcg_regset_set(ct->u.regs, 0xffffffff);
225
#if defined(CONFIG_SOFTMMU)
226
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
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_SPECIAL  = 0x00 << 26,
274
    OPC_BEQ      = 0x04 << 26,
275
    OPC_BNE      = 0x05 << 26,
276
    OPC_ADDIU    = 0x09 << 26,
277
    OPC_SLTI     = 0x0A << 26,
278
    OPC_SLTIU    = 0x0B << 26,
279
    OPC_ANDI     = 0x0C << 26,
280
    OPC_ORI      = 0x0D << 26,
281
    OPC_XORI     = 0x0E << 26,
282
    OPC_LUI      = 0x0F << 26,
283
    OPC_LB       = 0x20 << 26,
284
    OPC_LH       = 0x21 << 26,
285
    OPC_LW       = 0x23 << 26,
286
    OPC_LBU      = 0x24 << 26,
287
    OPC_LHU      = 0x25 << 26,
288
    OPC_LWU      = 0x27 << 26,
289
    OPC_SB       = 0x28 << 26,
290
    OPC_SH       = 0x29 << 26,
291
    OPC_SW       = 0x2B << 26,
292
    OPC_SLL      = OPC_SPECIAL | 0x00,
293
    OPC_SRL      = OPC_SPECIAL | 0x02,
294
    OPC_SRA      = OPC_SPECIAL | 0x03,
295
    OPC_SLLV     = OPC_SPECIAL | 0x04,
296
    OPC_SRLV     = OPC_SPECIAL | 0x06,
297
    OPC_SRAV     = OPC_SPECIAL | 0x07,
298
    OPC_JR       = OPC_SPECIAL | 0x08,
299
    OPC_JALR     = OPC_SPECIAL | 0x09,
300
    OPC_MFHI     = OPC_SPECIAL | 0x10,
301
    OPC_MFLO     = OPC_SPECIAL | 0x12,
302
    OPC_MULT     = OPC_SPECIAL | 0x18,
303
    OPC_MULTU    = OPC_SPECIAL | 0x19,
304
    OPC_DIV      = OPC_SPECIAL | 0x1A,
305
    OPC_DIVU     = OPC_SPECIAL | 0x1B,
306
    OPC_ADDU     = OPC_SPECIAL | 0x21,
307
    OPC_SUBU     = OPC_SPECIAL | 0x23,
308
    OPC_AND      = OPC_SPECIAL | 0x24,
309
    OPC_OR       = OPC_SPECIAL | 0x25,
310
    OPC_XOR      = OPC_SPECIAL | 0x26,
311
    OPC_NOR      = OPC_SPECIAL | 0x27,
312
    OPC_SLT      = OPC_SPECIAL | 0x2A,
313
    OPC_SLTU     = OPC_SPECIAL | 0x2B,
314
};
315

    
316
/*
317
 * Type reg
318
 */
319
static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int rt)
320
{
321
    int32_t inst;
322

    
323
    inst = opc;
324
    inst |= (rs & 0x1F) << 21;
325
    inst |= (rt & 0x1F) << 16;
326
    inst |= (rd & 0x1F) << 11;
327
    tcg_out32(s, inst);
328
}
329

    
330
/*
331
 * Type immediate
332
 */
333
static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int imm)
334
{
335
    int32_t inst;
336

    
337
    inst = opc;
338
    inst |= (rs & 0x1F) << 21;
339
    inst |= (rt & 0x1F) << 16;
340
    inst |= (imm & 0xffff);
341
    tcg_out32(s, inst);
342
}
343

    
344
/*
345
 * Type sa
346
 */
347
static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa)
348
{
349
    int32_t inst;
350

    
351
    inst = opc;
352
    inst |= (rt & 0x1F) << 16;
353
    inst |= (rd & 0x1F) << 11;
354
    inst |= (sa & 0x1F) <<  6;
355
    tcg_out32(s, inst);
356

    
357
}
358

    
359
static inline void tcg_out_nop(TCGContext *s)
360
{
361
    tcg_out32(s, 0);
362
}
363

    
364
static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
365
{
366
    tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
367
}
368

    
369
static inline void tcg_out_movi(TCGContext *s, TCGType type,
370
                                int reg, int32_t arg)
371
{
372
    if (arg == (int16_t)arg) {
373
        tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
374
    } else if (arg == (uint16_t)arg) {
375
        tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
376
    } else {
377
        tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
378
        tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
379
    }
380
}
381

    
382
static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
383
{
384
    /* ret and arg can't be register at */
385
    if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
386
        tcg_abort();
387
    }
388

    
389
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
390
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
391

    
392
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
393
    tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
394
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
395
}
396

    
397
static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
398
{
399
    /* ret and arg can't be register at */
400
    if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
401
        tcg_abort();
402
    }
403

    
404
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
405
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
406

    
407
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
408
    tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
409
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
410
}
411

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

    
419
    tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
420

    
421
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
422
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
423

    
424
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
425
    tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
426
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
427

    
428
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
429
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
430
    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
431
}
432

    
433
static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
434
                              int arg1, tcg_target_long arg2)
435
{
436
    if (arg2 == (int16_t) arg2) {
437
        tcg_out_opc_imm(s, opc, arg, arg1, arg2);
438
    } else {
439
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
440
        tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
441
        tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
442
    }
443
}
444

    
445
static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
446
                              int arg1, tcg_target_long arg2)
447
{
448
    tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
449
}
450

    
451
static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
452
                              int arg1, tcg_target_long arg2)
453
{
454
    tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
455
}
456

    
457
static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
458
{
459
    if (val == (int16_t)val) {
460
        tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
461
    } else {
462
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
463
        tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
464
    }
465
}
466

    
467
static void tcg_out_brcond(TCGContext *s, int cond, int arg1,
468
                           int arg2, int label_index)
469
{
470
    TCGLabel *l = &s->labels[label_index];
471

    
472
    switch (cond) {
473
    case TCG_COND_EQ:
474
        tcg_out_opc_imm(s, OPC_BEQ, arg1, arg2, 0);
475
        break;
476
    case TCG_COND_NE:
477
        tcg_out_opc_imm(s, OPC_BNE, arg1, arg2, 0);
478
        break;
479
    case TCG_COND_LT:
480
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
481
        tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
482
        break;
483
    case TCG_COND_LTU:
484
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
485
        tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
486
        break;
487
    case TCG_COND_GE:
488
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
489
        tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
490
        break;
491
    case TCG_COND_GEU:
492
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
493
        tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
494
        break;
495
    case TCG_COND_LE:
496
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
497
        tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
498
        break;
499
    case TCG_COND_LEU:
500
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
501
        tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO, 0);
502
        break;
503
    case TCG_COND_GT:
504
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
505
        tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
506
        break;
507
    case TCG_COND_GTU:
508
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
509
        tcg_out_opc_imm(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO, 0);
510
        break;
511
    default:
512
        tcg_abort();
513
        break;
514
    }
515
    if (l->has_value) {
516
        reloc_pc16(s->code_ptr - 4, l->u.value);
517
    } else {
518
        tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
519
    }
520
    tcg_out_nop(s);
521
}
522

    
523
/* XXX: we implement it at the target level to avoid having to
524
   handle cross basic blocks temporaries */
525
static void tcg_out_brcond2(TCGContext *s, int cond, int arg1,
526
                            int arg2, int arg3, int arg4, int label_index)
527
{
528
    void *label_ptr;
529

    
530
    switch(cond) {
531
    case TCG_COND_NE:
532
        tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
533
        tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
534
        return;
535
    case TCG_COND_EQ:
536
        break;
537
    case TCG_COND_LT:
538
    case TCG_COND_LE:
539
        tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
540
        break;
541
    case TCG_COND_GT:
542
    case TCG_COND_GE:
543
        tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
544
        break;
545
    case TCG_COND_LTU:
546
    case TCG_COND_LEU:
547
        tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
548
        break;
549
    case TCG_COND_GTU:
550
    case TCG_COND_GEU:
551
        tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
552
        break;
553
    default:
554
        tcg_abort();
555
    }
556

    
557
    label_ptr = s->code_ptr;
558
    tcg_out_opc_imm(s, OPC_BNE, arg2, arg4, 0);
559
    tcg_out_nop(s);
560

    
561
    switch(cond) {
562
    case TCG_COND_EQ:
563
        tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
564
        break;
565
    case TCG_COND_LT:
566
    case TCG_COND_LTU:
567
        tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
568
        break;
569
    case TCG_COND_LE:
570
    case TCG_COND_LEU:
571
        tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
572
        break;
573
    case TCG_COND_GT:
574
    case TCG_COND_GTU:
575
        tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
576
        break;
577
    case TCG_COND_GE:
578
    case TCG_COND_GEU:
579
        tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
580
        break;
581
    default:
582
        tcg_abort();
583
    }
584

    
585
    reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
586
}
587

    
588
static void tcg_out_setcond(TCGContext *s, int cond, int ret,
589
                            int arg1, int arg2)
590
{
591
    switch (cond) {
592
    case TCG_COND_EQ:
593
        if (arg1 == 0) {
594
            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg2, 1);
595
        } else if (arg2 == 0) {
596
            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
597
        } else {
598
            tcg_out_opc_reg(s, OPC_XOR, TCG_REG_AT, arg1, arg2);
599
            tcg_out_opc_imm(s, OPC_SLTIU, ret, TCG_REG_AT, 1);
600
        }
601
        break;
602
    case TCG_COND_NE:
603
        if (arg1 == 0) {
604
            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg2);
605
        } else if (arg2 == 0) {
606
            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
607
        } else {
608
            tcg_out_opc_reg(s, OPC_XOR, TCG_REG_AT, arg1, arg2);
609
            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, TCG_REG_AT);
610
        }
611
        break;
612
    case TCG_COND_LT:
613
        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
614
        break;
615
    case TCG_COND_LTU:
616
        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
617
        break;
618
    case TCG_COND_GE:
619
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
620
        tcg_out_opc_imm(s, OPC_XORI, ret, TCG_REG_AT, 1);
621
        break;
622
    case TCG_COND_GEU:
623
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
624
        tcg_out_opc_imm(s, OPC_XORI, ret, TCG_REG_AT, 1);
625
        break;
626
    case TCG_COND_LE:
627
        tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
628
        tcg_out_opc_imm(s, OPC_XORI, ret, TCG_REG_AT, 1);
629
        break;
630
    case TCG_COND_LEU:
631
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
632
        tcg_out_opc_imm(s, OPC_XORI, ret, TCG_REG_AT, 1);
633
        break;
634
    case TCG_COND_GT:
635
        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
636
        break;
637
    case TCG_COND_GTU:
638
        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
639
        break;
640
    default:
641
        tcg_abort();
642
        break;
643
    }
644
}
645

    
646
#if defined(CONFIG_SOFTMMU)
647

    
648
#include "../../softmmu_defs.h"
649

    
650
static void *qemu_ld_helpers[4] = {
651
    __ldb_mmu,
652
    __ldw_mmu,
653
    __ldl_mmu,
654
    __ldq_mmu,
655
};
656

    
657
static void *qemu_st_helpers[4] = {
658
    __stb_mmu,
659
    __stw_mmu,
660
    __stl_mmu,
661
    __stq_mmu,
662
};
663
#endif
664

    
665
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
666
                            int opc)
667
{
668
    int addr_regl, addr_reg1, addr_meml;
669
    int data_regl, data_regh, data_reg1, data_reg2;
670
    int mem_index, s_bits;
671
#if defined(CONFIG_SOFTMMU)
672
    void *label1_ptr, *label2_ptr;
673
    int sp_args;
674
#endif
675
#if TARGET_LONG_BITS == 64
676
# if defined(CONFIG_SOFTMMU)
677
    uint8_t *label3_ptr;
678
# endif
679
    int addr_regh, addr_reg2, addr_memh;
680
#endif
681
    data_regl = *args++;
682
    if (opc == 3)
683
        data_regh = *args++;
684
    else
685
        data_regh = 0;
686
    addr_regl = *args++;
687
#if TARGET_LONG_BITS == 64
688
    addr_regh = *args++;
689
#endif
690
    mem_index = *args;
691
    s_bits = opc & 3;
692

    
693
    if (opc == 3) {
694
#if defined(TCG_TARGET_WORDS_BIGENDIAN)
695
        data_reg1 = data_regh;
696
        data_reg2 = data_regl;
697
#else
698
        data_reg1 = data_regl;
699
        data_reg2 = data_regh;
700
#endif
701
    } else {
702
        data_reg1 = data_regl;
703
        data_reg2 = 0;
704
    }
705
#if TARGET_LONG_BITS == 64
706
# if defined(TCG_TARGET_WORDS_BIGENDIAN)
707
    addr_reg1 = addr_regh;
708
    addr_reg2 = addr_regl;
709
    addr_memh = 0;
710
    addr_meml = 4;
711
# else
712
    addr_reg1 = addr_regl;
713
    addr_reg2 = addr_regh;
714
    addr_memh = 4;
715
    addr_meml = 0;
716
# endif
717
#else
718
    addr_reg1 = addr_regl;
719
    addr_meml = 0;
720
#endif
721

    
722
#if defined(CONFIG_SOFTMMU)
723
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
724
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
725
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
726
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
727
                    offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_meml);
728
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
729
    tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
730

    
731
# if TARGET_LONG_BITS == 64
732
    label3_ptr = s->code_ptr;
733
    tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0);
734
    tcg_out_nop(s);
735

    
736
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
737
                    offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh);
738

    
739
    label1_ptr = s->code_ptr;
740
    tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0);
741
    tcg_out_nop(s);
742

    
743
    reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
744
# else
745
    label1_ptr = s->code_ptr;
746
    tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0);
747
    tcg_out_nop(s);
748
# endif
749

    
750
    /* slow path */
751
    sp_args = TCG_REG_A0;
752
    tcg_out_mov(s, sp_args++, addr_reg1);
753
# if TARGET_LONG_BITS == 64
754
    tcg_out_mov(s, sp_args++, addr_reg2);
755
# endif
756
    tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
757
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
758
    tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
759
    tcg_out_nop(s);
760

    
761
    switch(opc) {
762
    case 0:
763
        tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
764
        break;
765
    case 0 | 4:
766
        tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 24);
767
        tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 24);
768
        break;
769
    case 1:
770
        tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
771
        break;
772
    case 1 | 4:
773
        tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 16);
774
        tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 16);
775
        break;
776
    case 2:
777
        tcg_out_mov(s, data_reg1, TCG_REG_V0);
778
        break;
779
    case 3:
780
        tcg_out_mov(s, data_reg2, TCG_REG_V1);
781
        tcg_out_mov(s, data_reg1, TCG_REG_V0);
782
        break;
783
    default:
784
        tcg_abort();
785
    }
786

    
787
    label2_ptr = s->code_ptr;
788
    tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0);
789
    tcg_out_nop(s);
790

    
791
    /* label1: fast path */
792
    reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
793

    
794
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_V0, TCG_REG_A0,
795
                    offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
796
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
797

    
798
    addr_reg1 = TCG_REG_V0;
799
#endif
800

    
801
    switch(opc) {
802
    case 0:
803
        tcg_out_opc_imm(s, OPC_LBU, data_reg1, addr_reg1, 0);
804
        break;
805
    case 0 | 4:
806
        tcg_out_opc_imm(s, OPC_LB, data_reg1, addr_reg1, 0);
807
        break;
808
    case 1:
809
        if (TCG_NEED_BSWAP) {
810
            tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, addr_reg1, 0);
811
            tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
812
        } else {
813
            tcg_out_opc_imm(s, OPC_LHU, data_reg1, addr_reg1, 0);
814
        }
815
        break;
816
    case 1 | 4:
817
        if (TCG_NEED_BSWAP) {
818
            tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, addr_reg1, 0);
819
            tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
820
        } else {
821
            tcg_out_opc_imm(s, OPC_LH, data_reg1, addr_reg1, 0);
822
        }
823
        break;
824
    case 2:
825
        if (TCG_NEED_BSWAP) {
826
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 0);
827
            tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
828
        } else {
829
            tcg_out_opc_imm(s, OPC_LW, data_reg1, addr_reg1, 0);
830
        }
831
        break;
832
    case 3:
833
#if !defined(CONFIG_SOFTMMU)
834
        tcg_out_mov(s, TCG_REG_V0, addr_reg1);
835
        addr_reg1 = TCG_REG_V0;
836
#endif
837
        if (TCG_NEED_BSWAP) {
838
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 4);
839
            tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
840
            tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 0);
841
            tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
842
        } else {
843
            tcg_out_opc_imm(s, OPC_LW, data_reg1, addr_reg1, 0);
844
            tcg_out_opc_imm(s, OPC_LW, data_reg2, addr_reg1, 4);
845
        }
846
        break;
847
    default:
848
        tcg_abort();
849
    }
850

    
851
#if defined(CONFIG_SOFTMMU)
852
    reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
853
#endif
854
}
855

    
856
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
857
                            int opc)
858
{
859
    int addr_regl, addr_reg1, addr_meml;
860
    int data_regl, data_regh, data_reg1, data_reg2;
861
    int mem_index, s_bits;
862
#if defined(CONFIG_SOFTMMU)
863
    uint8_t *label1_ptr, *label2_ptr;
864
    int sp_args;
865
#endif
866
#if TARGET_LONG_BITS == 64
867
# if defined(CONFIG_SOFTMMU)
868
    uint8_t *label3_ptr;
869
# endif
870
    int addr_regh, addr_reg2, addr_memh;
871
#endif
872

    
873
    data_regl = *args++;
874
    if (opc == 3) {
875
        data_regh = *args++;
876
#if defined(TCG_TARGET_WORDS_BIGENDIAN)
877
        data_reg1 = data_regh;
878
        data_reg2 = data_regl;
879
#else
880
        data_reg1 = data_regl;
881
        data_reg2 = data_regh;
882
#endif
883
    } else {
884
        data_reg1 = data_regl;
885
        data_reg2 = 0;
886
        data_regh = 0;
887
    }
888
    addr_regl = *args++;
889
#if TARGET_LONG_BITS == 64
890
    addr_regh = *args++;
891
# if defined(TCG_TARGET_WORDS_BIGENDIAN)
892
    addr_reg1 = addr_regh;
893
    addr_reg2 = addr_regl;
894
    addr_memh = 0;
895
    addr_meml = 4;
896
# else
897
    addr_reg1 = addr_regl;
898
    addr_reg2 = addr_regh;
899
    addr_memh = 4;
900
    addr_meml = 0;
901
# endif
902
#else
903
    addr_reg1 = addr_regl;
904
    addr_meml = 0;
905
#endif
906
    mem_index = *args;
907
    s_bits = opc;
908

    
909
#if defined(CONFIG_SOFTMMU)
910
    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
911
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
912
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
913
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
914
                    offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_meml);
915
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
916
    tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
917

    
918
# if TARGET_LONG_BITS == 64
919
    label3_ptr = s->code_ptr;
920
    tcg_out_opc_imm(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT, 0);
921
    tcg_out_nop(s);
922

    
923
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
924
                    offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh);
925

    
926
    label1_ptr = s->code_ptr;
927
    tcg_out_opc_imm(s, OPC_BEQ, addr_regh, TCG_REG_AT, 0);
928
    tcg_out_nop(s);
929

    
930
    reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
931
# else
932
    label1_ptr = s->code_ptr;
933
    tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT, 0);
934
    tcg_out_nop(s);
935
# endif
936

    
937
    /* slow path */
938
    sp_args = TCG_REG_A0;
939
    tcg_out_mov(s, sp_args++, addr_reg1);
940
# if TARGET_LONG_BITS == 64
941
    tcg_out_mov(s, sp_args++, addr_reg2);
942
# endif
943
    switch(opc) {
944
    case 0:
945
        tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xff);
946
        break;
947
    case 1:
948
        tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
949
        break;
950
    case 2:
951
        tcg_out_mov(s, sp_args++, data_reg1);
952
        break;
953
    case 3:
954
        sp_args = (sp_args + 1) & ~1;
955
        tcg_out_mov(s, sp_args++, data_reg1);
956
        tcg_out_mov(s, sp_args++, data_reg2);
957
        break;
958
    default:
959
        tcg_abort();
960
    }
961
    if (sp_args > TCG_REG_A3) {
962
        /* Push mem_index on the stack */
963
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, mem_index);
964
        tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 16);
965
    } else {
966
        tcg_out_movi(s, TCG_TYPE_I32, sp_args, mem_index);
967
    }
968

    
969
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
970
    tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
971
    tcg_out_nop(s);
972

    
973
    label2_ptr = s->code_ptr;
974
    tcg_out_opc_imm(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO, 0);
975
    tcg_out_nop(s);
976

    
977
    /* label1: fast path */
978
    reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
979

    
980
    tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
981
                    offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
982
    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
983

    
984
    addr_reg1 = TCG_REG_A0;
985
#endif
986

    
987
    switch(opc) {
988
    case 0:
989
        tcg_out_opc_imm(s, OPC_SB, data_reg1, addr_reg1, 0);
990
        break;
991
    case 1:
992
        if (TCG_NEED_BSWAP) {
993
            tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
994
            tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, addr_reg1, 0);
995
        } else {
996
            tcg_out_opc_imm(s, OPC_SH, data_reg1, addr_reg1, 0);
997
        }
998
        break;
999
    case 2:
1000
        if (TCG_NEED_BSWAP) {
1001
            tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1002
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 0);
1003
        } else {
1004
            tcg_out_opc_imm(s, OPC_SW, data_reg1, addr_reg1, 0);
1005
        }
1006
        break;
1007
    case 3:
1008
        if (TCG_NEED_BSWAP) {
1009
            tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
1010
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 0);
1011
            tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1012
            tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 4);
1013
        } else {
1014
            tcg_out_opc_imm(s, OPC_SW, data_reg1, addr_reg1, 0);
1015
            tcg_out_opc_imm(s, OPC_SW, data_reg2, addr_reg1, 4);
1016
        }
1017
        break;
1018
    default:
1019
        tcg_abort();
1020
    }
1021

    
1022
#if defined(CONFIG_SOFTMMU)
1023
    reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
1024
#endif
1025
}
1026

    
1027
static inline void tcg_out_op(TCGContext *s, int opc,
1028
                              const TCGArg *args, const int *const_args)
1029
{
1030
    switch(opc) {
1031
    case INDEX_op_exit_tb:
1032
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
1033
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
1034
        tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1035
        tcg_out_nop(s);
1036
        break;
1037
    case INDEX_op_goto_tb:
1038
        if (s->tb_jmp_offset) {
1039
            /* direct jump method */
1040
            tcg_abort();
1041
        } else {
1042
            /* indirect jump method */
1043
            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
1044
            tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
1045
            tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
1046
        }
1047
        tcg_out_nop(s);
1048
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1049
        break;
1050
    case INDEX_op_call:
1051
        tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
1052
        tcg_out_nop(s);
1053
        break;
1054
    case INDEX_op_jmp:
1055
        tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
1056
        tcg_out_nop(s);
1057
        break;
1058
    case INDEX_op_br:
1059
        tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
1060
        break;
1061

    
1062
    case INDEX_op_mov_i32:
1063
        tcg_out_mov(s, args[0], args[1]);
1064
        break;
1065
    case INDEX_op_movi_i32:
1066
        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1067
        break;
1068

    
1069
    case INDEX_op_ld8u_i32:
1070
        tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1071
        break;
1072
    case INDEX_op_ld8s_i32:
1073
        tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
1074
        break;
1075
    case INDEX_op_ld16u_i32:
1076
        tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
1077
        break;
1078
    case INDEX_op_ld16s_i32:
1079
        tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
1080
        break;
1081
    case INDEX_op_ld_i32:
1082
        tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
1083
        break;
1084
    case INDEX_op_st8_i32:
1085
        tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
1086
        break;
1087
    case INDEX_op_st16_i32:
1088
        tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
1089
        break;
1090
    case INDEX_op_st_i32:
1091
        tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
1092
        break;
1093

    
1094
    case INDEX_op_add_i32:
1095
        if (const_args[2]) {
1096
            tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
1097
        } else {
1098
            tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
1099
        }
1100
        break;
1101
    case INDEX_op_add2_i32:
1102
        if (const_args[4]) {
1103
            tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
1104
        } else {
1105
            tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
1106
        }
1107
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
1108
        if (const_args[5]) {
1109
            tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
1110
        } else {
1111
             tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
1112
        }
1113
        tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1114
        tcg_out_mov(s, args[0], TCG_REG_AT);
1115
        break;
1116
    case INDEX_op_sub_i32:
1117
        if (const_args[2]) {
1118
            tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
1119
        } else {
1120
            tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
1121
        }
1122
        break;
1123
    case INDEX_op_sub2_i32:
1124
        if (const_args[4]) {
1125
            tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
1126
        } else {
1127
            tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
1128
        }
1129
        tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
1130
        if (const_args[5]) {
1131
            tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
1132
        } else {
1133
             tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
1134
        }
1135
        tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1136
        tcg_out_mov(s, args[0], TCG_REG_AT);
1137
        break;
1138
    case INDEX_op_mul_i32:
1139
        tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
1140
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1141
        break;
1142
    case INDEX_op_mulu2_i32:
1143
        tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
1144
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1145
        tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
1146
        break;
1147
    case INDEX_op_div_i32:
1148
        tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1149
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1150
        break;
1151
    case INDEX_op_divu_i32:
1152
        tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1153
        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
1154
        break;
1155
    case INDEX_op_rem_i32:
1156
        tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
1157
        tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1158
        break;
1159
    case INDEX_op_remu_i32:
1160
        tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
1161
        tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
1162
        break;
1163

    
1164
    case INDEX_op_and_i32:
1165
        if (const_args[2]) {
1166
            tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
1167
        } else {
1168
            tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
1169
        }
1170
        break;
1171
    case INDEX_op_or_i32:
1172
        if (const_args[2]) {
1173
            tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
1174
        } else {
1175
            tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
1176
        }
1177
        break;
1178
    case INDEX_op_not_i32:
1179
        tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[1]);
1180
        break;
1181
    case INDEX_op_xor_i32:
1182
        if (const_args[2]) {
1183
            tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
1184
        } else {
1185
            tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
1186
        }
1187
        break;
1188

    
1189
    case INDEX_op_sar_i32:
1190
        if (const_args[2]) {
1191
            tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
1192
        } else {
1193
            tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
1194
        }
1195
        break;
1196
    case INDEX_op_shl_i32:
1197
        if (const_args[2]) {
1198
            tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
1199
        } else {
1200
            tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
1201
        }
1202
        break;
1203
    case INDEX_op_shr_i32:
1204
        if (const_args[2]) {
1205
            tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
1206
        } else {
1207
            tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
1208
        }
1209
        break;
1210

    
1211
    case INDEX_op_brcond_i32:
1212
        tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
1213
        break;
1214
    case INDEX_op_brcond2_i32:
1215
        tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
1216
        break;
1217

    
1218
    case INDEX_op_setcond_i32:
1219
        tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
1220
        break;
1221

    
1222
    case INDEX_op_qemu_ld8u:
1223
        tcg_out_qemu_ld(s, args, 0);
1224
        break;
1225
    case INDEX_op_qemu_ld8s:
1226
        tcg_out_qemu_ld(s, args, 0 | 4);
1227
        break;
1228
    case INDEX_op_qemu_ld16u:
1229
        tcg_out_qemu_ld(s, args, 1);
1230
        break;
1231
    case INDEX_op_qemu_ld16s:
1232
        tcg_out_qemu_ld(s, args, 1 | 4);
1233
        break;
1234
    case INDEX_op_qemu_ld32u:
1235
        tcg_out_qemu_ld(s, args, 2);
1236
        break;
1237
    case INDEX_op_qemu_ld64:
1238
        tcg_out_qemu_ld(s, args, 3);
1239
        break;
1240
    case INDEX_op_qemu_st8:
1241
        tcg_out_qemu_st(s, args, 0);
1242
        break;
1243
    case INDEX_op_qemu_st16:
1244
        tcg_out_qemu_st(s, args, 1);
1245
        break;
1246
    case INDEX_op_qemu_st32:
1247
        tcg_out_qemu_st(s, args, 2);
1248
        break;
1249
    case INDEX_op_qemu_st64:
1250
        tcg_out_qemu_st(s, args, 3);
1251
        break;
1252

    
1253
    default:
1254
        tcg_abort();
1255
    }
1256
}
1257

    
1258
static const TCGTargetOpDef mips_op_defs[] = {
1259
    { INDEX_op_exit_tb, { } },
1260
    { INDEX_op_goto_tb, { } },
1261
    { INDEX_op_call, { "C" } },
1262
    { INDEX_op_jmp, { "r" } },
1263
    { INDEX_op_br, { } },
1264

    
1265
    { INDEX_op_mov_i32, { "r", "r" } },
1266
    { INDEX_op_movi_i32, { "r" } },
1267
    { INDEX_op_ld8u_i32, { "r", "r" } },
1268
    { INDEX_op_ld8s_i32, { "r", "r" } },
1269
    { INDEX_op_ld16u_i32, { "r", "r" } },
1270
    { INDEX_op_ld16s_i32, { "r", "r" } },
1271
    { INDEX_op_ld_i32, { "r", "r" } },
1272
    { INDEX_op_st8_i32, { "rZ", "r" } },
1273
    { INDEX_op_st16_i32, { "rZ", "r" } },
1274
    { INDEX_op_st_i32, { "rZ", "r" } },
1275

    
1276
    { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
1277
    { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1278
    { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1279
    { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1280
    { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1281
    { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1282
    { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1283
    { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
1284

    
1285
    { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
1286
    { INDEX_op_not_i32, { "r", "rZ" } },
1287
    { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1288
    { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1289

    
1290
    { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
1291
    { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
1292
    { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
1293

    
1294
    { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1295
    { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
1296

    
1297
    { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1298
    { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
1299
    { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1300

    
1301
#if TARGET_LONG_BITS == 32
1302
    { INDEX_op_qemu_ld8u, { "L", "lZ" } },
1303
    { INDEX_op_qemu_ld8s, { "L", "lZ" } },
1304
    { INDEX_op_qemu_ld16u, { "L", "lZ" } },
1305
    { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1306
    { INDEX_op_qemu_ld32u, { "L", "lZ" } },
1307
    { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
1308

    
1309
    { INDEX_op_qemu_st8, { "SZ", "SZ" } },
1310
    { INDEX_op_qemu_st16, { "SZ", "SZ" } },
1311
    { INDEX_op_qemu_st32, { "SZ", "SZ" } },
1312
    { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
1313
#else
1314
    { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
1315
    { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
1316
    { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
1317
    { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1318
    { INDEX_op_qemu_ld32u, { "L", "lZ", "lZ" } },
1319
    { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
1320

    
1321
    { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
1322
    { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
1323
    { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
1324
    { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
1325
#endif
1326
    { -1 },
1327
};
1328

    
1329
static int tcg_target_callee_save_regs[] = {
1330
    TCG_REG_S0,
1331
    TCG_REG_S1,
1332
    TCG_REG_S2,
1333
    TCG_REG_S3,
1334
    TCG_REG_S4,
1335
    TCG_REG_S5,
1336
    TCG_REG_S6,
1337
    TCG_REG_S7,
1338
    TCG_REG_GP,
1339
    /* TCG_REG_FP, */ /* currently used for the global env, so np
1340
                         need to save */
1341
    TCG_REG_RA,       /* should be last for ABI compliance */
1342
};
1343

    
1344
/* Generate global QEMU prologue and epilogue code */
1345
void tcg_target_qemu_prologue(TCGContext *s)
1346
{
1347
    int i, frame_size;
1348

    
1349
    /* reserve some stack space */
1350
    frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1351
                 + TCG_STATIC_CALL_ARGS_SIZE;
1352
    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1353
                 ~(TCG_TARGET_STACK_ALIGN - 1);
1354

    
1355
    /* TB prologue */
1356
    tcg_out_addi(s, TCG_REG_SP, -frame_size);
1357
    for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1358
        tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1359
                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1360
    }
1361

    
1362
    /* Call generated code */
1363
    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_A0, 0);
1364
    tcg_out_nop(s);
1365
    tb_ret_addr = s->code_ptr;
1366

    
1367
    /* TB epilogue */
1368
    for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1369
        tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1370
                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1371
    }
1372

    
1373
    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1374
    tcg_out_addi(s, TCG_REG_SP, frame_size);
1375
}
1376

    
1377
void tcg_target_init(TCGContext *s)
1378
{
1379
    tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1380
    tcg_regset_set(tcg_target_call_clobber_regs,
1381
                   (1 << TCG_REG_V0) |
1382
                   (1 << TCG_REG_V1) |
1383
                   (1 << TCG_REG_A0) |
1384
                   (1 << TCG_REG_A1) |
1385
                   (1 << TCG_REG_A2) |
1386
                   (1 << TCG_REG_A3) |
1387
                   (1 << TCG_REG_T1) |
1388
                   (1 << TCG_REG_T2) |
1389
                   (1 << TCG_REG_T3) |
1390
                   (1 << TCG_REG_T4) |
1391
                   (1 << TCG_REG_T5) |
1392
                   (1 << TCG_REG_T6) |
1393
                   (1 << TCG_REG_T7) |
1394
                   (1 << TCG_REG_T8) |
1395
                   (1 << TCG_REG_T9));
1396

    
1397
    tcg_regset_clear(s->reserved_regs);
1398
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1399
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0);   /* kernel use only */
1400
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1);   /* kernel use only */
1401
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT);   /* internal use */
1402
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0);   /* internal use */
1403
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA);   /* return address */
1404
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);   /* stack pointer */
1405

    
1406
    tcg_add_target_add_op_defs(mips_op_defs);
1407
}