tcg-target.c 32.5 KB
Newer Older
B
blueswir1 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
/*
 * Tiny Code Generator for QEMU
 *
 * Copyright (c) 2008 Fabrice Bellard
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
    "%g0",
    "%g1",
    "%g2",
    "%g3",
    "%g4",
    "%g5",
    "%g6",
    "%g7",
    "%o0",
    "%o1",
    "%o2",
    "%o3",
    "%o4",
    "%o5",
    "%o6",
    "%o7",
    "%l0",
    "%l1",
    "%l2",
    "%l3",
    "%l4",
    "%l5",
    "%l6",
    "%l7",
    "%i0",
    "%i1",
    "%i2",
    "%i3",
    "%i4",
    "%i5",
    "%i6",
    "%i7",
};

60
static const int tcg_target_reg_alloc_order[] = {
B
blueswir1 已提交
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
    TCG_REG_L0,
    TCG_REG_L1,
    TCG_REG_L2,
    TCG_REG_L3,
    TCG_REG_L4,
    TCG_REG_L5,
    TCG_REG_L6,
    TCG_REG_L7,
    TCG_REG_I0,
    TCG_REG_I1,
    TCG_REG_I2,
    TCG_REG_I3,
    TCG_REG_I4,
};

static const int tcg_target_call_iarg_regs[6] = {
    TCG_REG_O0,
    TCG_REG_O1,
    TCG_REG_O2,
    TCG_REG_O3,
    TCG_REG_O4,
    TCG_REG_O5,
};

static const int tcg_target_call_oarg_regs[2] = {
    TCG_REG_O0,
    TCG_REG_O1,
};

B
blueswir1 已提交
90
static inline int check_fit_tl(tcg_target_long val, unsigned int bits)
91
{
B
blueswir1 已提交
92 93 94 95 96 97 98
    return (val << ((sizeof(tcg_target_long) * 8 - bits))
            >> (sizeof(tcg_target_long) * 8 - bits)) == val;
}

static inline int check_fit_i32(uint32_t val, unsigned int bits)
{
    return ((val << (32 - bits)) >> (32 - bits)) == val;
99 100
}

B
blueswir1 已提交
101
static void patch_reloc(uint8_t *code_ptr, int type,
A
aurel32 已提交
102
                        tcg_target_long value, tcg_target_long addend)
B
blueswir1 已提交
103
{
A
aurel32 已提交
104
    value += addend;
B
blueswir1 已提交
105 106 107 108 109 110
    switch (type) {
    case R_SPARC_32:
        if (value != (uint32_t)value)
            tcg_abort();
        *(uint32_t *)code_ptr = value;
        break;
111 112 113
    case R_SPARC_WDISP22:
        value -= (long)code_ptr;
        value >>= 2;
B
blueswir1 已提交
114
        if (!check_fit_tl(value, 22))
115 116 117
            tcg_abort();
        *(uint32_t *)code_ptr = ((*(uint32_t *)code_ptr) & ~0x3fffff) | value;
        break;
B
blueswir1 已提交
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
    default:
        tcg_abort();
    }
}

/* maximum number of register used for input function arguments */
static inline int tcg_target_get_call_iarg_regs_count(int flags)
{
    return 6;
}

/* parse target specific constraints */
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
{
    const char *ct_str;

    ct_str = *pct_str;
    switch (ct_str[0]) {
    case 'r':
    case 'L': /* qemu_ld/st constraint */
        ct->ct |= TCG_CT_REG;
        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
140 141
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_I0);
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_I1);
B
blueswir1 已提交
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
        break;
    case 'I':
        ct->ct |= TCG_CT_CONST_S11;
        break;
    case 'J':
        ct->ct |= TCG_CT_CONST_S13;
        break;
    default:
        return -1;
    }
    ct_str++;
    *pct_str = ct_str;
    return 0;
}

/* test if a constant matches the constraint */
static inline int tcg_target_const_match(tcg_target_long val,
                                         const TCGArgConstraint *arg_ct)
{
    int ct;

    ct = arg_ct->ct;
    if (ct & TCG_CT_CONST)
        return 1;
B
blueswir1 已提交
166
    else if ((ct & TCG_CT_CONST_S11) && check_fit_tl(val, 11))
B
blueswir1 已提交
167
        return 1;
B
blueswir1 已提交
168
    else if ((ct & TCG_CT_CONST_S13) && check_fit_tl(val, 13))
B
blueswir1 已提交
169 170 171 172 173 174 175 176 177 178 179 180 181 182
        return 1;
    else
        return 0;
}

#define INSN_OP(x)  ((x) << 30)
#define INSN_OP2(x) ((x) << 22)
#define INSN_OP3(x) ((x) << 19)
#define INSN_OPF(x) ((x) << 5)
#define INSN_RD(x)  ((x) << 25)
#define INSN_RS1(x) ((x) << 14)
#define INSN_RS2(x) (x)

#define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff))
183
#define INSN_OFF22(x) (((x) >> 2) & 0x3fffff)
B
blueswir1 已提交
184

185
#define INSN_COND(x, a) (((x) << 25) | ((a) << 29))
186 187 188 189 190 191 192 193
#define COND_N     0x0
#define COND_E     0x1
#define COND_LE    0x2
#define COND_L     0x3
#define COND_LEU   0x4
#define COND_CS    0x5
#define COND_NEG   0x6
#define COND_VS    0x7
194
#define COND_A     0x8
195 196 197 198 199 200 201
#define COND_NE    0x9
#define COND_G     0xa
#define COND_GE    0xb
#define COND_GU    0xc
#define COND_CC    0xd
#define COND_POS   0xe
#define COND_VC    0xf
202
#define BA         (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2))
B
blueswir1 已提交
203 204 205 206

#define ARITH_ADD  (INSN_OP(2) | INSN_OP3(0x00))
#define ARITH_AND  (INSN_OP(2) | INSN_OP3(0x01))
#define ARITH_OR   (INSN_OP(2) | INSN_OP3(0x02))
207
#define ARITH_ORCC (INSN_OP(2) | INSN_OP3(0x12))
B
blueswir1 已提交
208
#define ARITH_XOR  (INSN_OP(2) | INSN_OP3(0x03))
209 210
#define ARITH_SUB  (INSN_OP(2) | INSN_OP3(0x04))
#define ARITH_SUBCC (INSN_OP(2) | INSN_OP3(0x14))
B
blueswir1 已提交
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
#define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x10))
#define ARITH_SUBX (INSN_OP(2) | INSN_OP3(0x0c))
#define ARITH_UMUL (INSN_OP(2) | INSN_OP3(0x0a))
#define ARITH_UDIV (INSN_OP(2) | INSN_OP3(0x0e))
#define ARITH_SDIV (INSN_OP(2) | INSN_OP3(0x0f))
#define ARITH_MULX (INSN_OP(2) | INSN_OP3(0x09))
#define ARITH_UDIVX (INSN_OP(2) | INSN_OP3(0x0d))
#define ARITH_SDIVX (INSN_OP(2) | INSN_OP3(0x2d))

#define SHIFT_SLL  (INSN_OP(2) | INSN_OP3(0x25))
#define SHIFT_SRL  (INSN_OP(2) | INSN_OP3(0x26))
#define SHIFT_SRA  (INSN_OP(2) | INSN_OP3(0x27))

#define SHIFT_SLLX (INSN_OP(2) | INSN_OP3(0x25) | (1 << 12))
#define SHIFT_SRLX (INSN_OP(2) | INSN_OP3(0x26) | (1 << 12))
#define SHIFT_SRAX (INSN_OP(2) | INSN_OP3(0x27) | (1 << 12))

#define WRY        (INSN_OP(2) | INSN_OP3(0x30))
#define JMPL       (INSN_OP(2) | INSN_OP3(0x38))
#define SAVE       (INSN_OP(2) | INSN_OP3(0x3c))
#define RESTORE    (INSN_OP(2) | INSN_OP3(0x3d))
#define SETHI      (INSN_OP(0) | INSN_OP2(0x4))
#define CALL       INSN_OP(1)
#define LDUB       (INSN_OP(3) | INSN_OP3(0x01))
#define LDSB       (INSN_OP(3) | INSN_OP3(0x09))
#define LDUH       (INSN_OP(3) | INSN_OP3(0x02))
#define LDSH       (INSN_OP(3) | INSN_OP3(0x0a))
#define LDUW       (INSN_OP(3) | INSN_OP3(0x00))
#define LDSW       (INSN_OP(3) | INSN_OP3(0x08))
#define LDX        (INSN_OP(3) | INSN_OP3(0x0b))
#define STB        (INSN_OP(3) | INSN_OP3(0x05))
#define STH        (INSN_OP(3) | INSN_OP3(0x06))
#define STW        (INSN_OP(3) | INSN_OP3(0x04))
#define STX        (INSN_OP(3) | INSN_OP3(0x0e))

246 247 248 249 250 251 252 253 254 255 256 257 258 259
static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2,
                                 int op)
{
    tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) |
              INSN_RS2(rs2));
}

static inline void tcg_out_arithi(TCGContext *s, int rd, int rs1, int offset,
                                  int op)
{
    tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) |
              INSN_IMM13(offset));
}

B
blueswir1 已提交
260 261
static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
{
262 263 264 265 266 267
    tcg_out_arith(s, ret, arg, TCG_REG_G0, ARITH_OR);
}

static inline void tcg_out_sethi(TCGContext *s, int ret, uint32_t arg)
{
    tcg_out32(s, SETHI | INSN_RD(ret) | ((arg & 0xfffffc00) >> 10));
B
blueswir1 已提交
268 269
}

B
blueswir1 已提交
270 271 272 273 274 275
static inline void tcg_out_movi_imm13(TCGContext *s, int ret, uint32_t arg)
{
    tcg_out_arithi(s, ret, TCG_REG_G0, arg, ARITH_OR);
}

static inline void tcg_out_movi_imm32(TCGContext *s, int ret, uint32_t arg)
B
blueswir1 已提交
276
{
B
blueswir1 已提交
277
    if (check_fit_i32(arg, 13))
B
blueswir1 已提交
278
        tcg_out_movi_imm13(s, ret, arg);
B
blueswir1 已提交
279
    else {
280
        tcg_out_sethi(s, ret, arg);
B
blueswir1 已提交
281
        if (arg & 0x3ff)
B
blueswir1 已提交
282
            tcg_out_arithi(s, ret, ret, arg & 0x3ff, ARITH_OR);
B
blueswir1 已提交
283 284 285
    }
}

B
blueswir1 已提交
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
static inline void tcg_out_movi(TCGContext *s, TCGType type,
                                int ret, tcg_target_long arg)
{
#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
    if (!check_fit_tl(arg, 32) && (arg & ~0xffffffffULL) != 0) {
        // XXX ret may be I5, need another temp
        tcg_out_movi_imm32(s, TCG_REG_I5, arg >> 32);
        tcg_out_arithi(s, TCG_REG_I5, TCG_REG_I5, 32, SHIFT_SLLX);
        tcg_out_movi_imm32(s, ret, arg);
        tcg_out_arith(s, ret, ret, TCG_REG_I5, ARITH_OR);
    } else
#endif
        tcg_out_movi_imm32(s, ret, arg);
}

B
blueswir1 已提交
301 302 303
static inline void tcg_out_ld_raw(TCGContext *s, int ret,
                                  tcg_target_long arg)
{
304
    tcg_out_sethi(s, ret, arg);
B
blueswir1 已提交
305 306 307 308
    tcg_out32(s, LDUW | INSN_RD(ret) | INSN_RS1(ret) |
              INSN_IMM13(arg & 0x3ff));
}

309 310 311
static inline void tcg_out_ld_ptr(TCGContext *s, int ret,
                                  tcg_target_long arg)
{
B
blueswir1 已提交
312 313
    if (!check_fit_tl(arg, 10))
        tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ffULL);
314 315 316 317
#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
    tcg_out32(s, LDX | INSN_RD(ret) | INSN_RS1(ret) |
              INSN_IMM13(arg & 0x3ff));
#else
B
blueswir1 已提交
318 319
    tcg_out32(s, LDUW | INSN_RD(ret) | INSN_RS1(ret) |
              INSN_IMM13(arg & 0x3ff));
320 321 322
#endif
}

B
blueswir1 已提交
323 324
static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset, int op)
{
B
blueswir1 已提交
325
    if (check_fit_tl(offset, 13))
B
blueswir1 已提交
326 327
        tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) |
                  INSN_IMM13(offset));
328 329 330 331 332
    else {
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, offset);
        tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(TCG_REG_I5) |
                  INSN_RS2(addr));
    }
B
blueswir1 已提交
333 334
}

335
static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
B
blueswir1 已提交
336 337
                              int arg1, tcg_target_long arg2)
{
338 339 340 341
    if (type == TCG_TYPE_I32)
        tcg_out_ldst(s, ret, arg1, arg2, LDUW);
    else
        tcg_out_ldst(s, ret, arg1, arg2, LDX);
B
blueswir1 已提交
342 343
}

344
static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
B
blueswir1 已提交
345 346
                              int arg1, tcg_target_long arg2)
{
347 348 349 350
    if (type == TCG_TYPE_I32)
        tcg_out_ldst(s, arg, arg1, arg2, STW);
    else
        tcg_out_ldst(s, arg, arg1, arg2, STX);
B
blueswir1 已提交
351 352 353 354 355 356 357 358 359 360 361 362 363
}

static inline void tcg_out_sety(TCGContext *s, tcg_target_long val)
{
    if (val == 0 || val == -1)
        tcg_out32(s, WRY | INSN_IMM13(val));
    else
        fprintf(stderr, "unimplemented sety %ld\n", (long)val);
}

static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
{
    if (val != 0) {
B
blueswir1 已提交
364
        if (check_fit_tl(val, 13))
B
blueswir1 已提交
365
            tcg_out_arithi(s, reg, reg, val, ARITH_ADD);
366 367 368 369
        else {
            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, val);
            tcg_out_arith(s, reg, reg, TCG_REG_I5, ARITH_ADD);
        }
B
blueswir1 已提交
370 371 372 373 374
    }
}

static inline void tcg_out_nop(TCGContext *s)
{
375
    tcg_out_sethi(s, TCG_REG_G0, 0);
B
blueswir1 已提交
376 377
}

378 379 380 381 382 383 384
static void tcg_out_branch(TCGContext *s, int opc, int label_index)
{
    int32_t val;
    TCGLabel *l = &s->labels[label_index];

    if (l->has_value) {
        val = l->u.value - (tcg_target_long)s->code_ptr;
385
        tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2)
386
                      | INSN_OFF22(l->u.value - (unsigned long)s->code_ptr)));
387 388 389 390
    } else {
        tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP22, label_index, 0);
        tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) | 0));
    }
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
}

static const uint8_t tcg_cond_to_bcond[10] = {
    [TCG_COND_EQ] = COND_E,
    [TCG_COND_NE] = COND_NE,
    [TCG_COND_LT] = COND_L,
    [TCG_COND_GE] = COND_GE,
    [TCG_COND_LE] = COND_LE,
    [TCG_COND_GT] = COND_G,
    [TCG_COND_LTU] = COND_CS,
    [TCG_COND_GEU] = COND_CC,
    [TCG_COND_LEU] = COND_LEU,
    [TCG_COND_GTU] = COND_GU,
};

static void tcg_out_brcond(TCGContext *s, int cond,
                           TCGArg arg1, TCGArg arg2, int const_arg2,
                           int label_index)
{
    if (const_arg2 && arg2 == 0)
411
        /* orcc %g0, r, %g0 */
412
        tcg_out_arith(s, TCG_REG_G0, TCG_REG_G0, arg1, ARITH_ORCC);
413 414 415 416 417 418 419
    else
        /* subcc r1, r2, %g0 */
        tcg_out_arith(s, TCG_REG_G0, arg1, arg2, ARITH_SUBCC);
    tcg_out_branch(s, tcg_cond_to_bcond[cond], label_index);
    tcg_out_nop(s);
}

420 421
/* Generate global QEMU prologue and epilogue code */
void tcg_target_qemu_prologue(TCGContext *s)
422 423 424
{
    tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) |
              INSN_IMM13(-TCG_TARGET_STACK_MINFRAME));
425
    tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I0) |
426 427
              INSN_RS2(TCG_REG_G0));
    tcg_out_nop(s);
428 429
}

430 431 432 433 434 435 436 437 438 439 440 441
#if defined(CONFIG_SOFTMMU)
extern void __ldb_mmu(void);
extern void __ldw_mmu(void);
extern void __ldl_mmu(void);
extern void __ldq_mmu(void);

extern void __stb_mmu(void);
extern void __stw_mmu(void);
extern void __stl_mmu(void);
extern void __stq_mmu(void);


442
static const void * const qemu_ld_helpers[4] = {
443 444 445 446 447 448
    __ldb_mmu,
    __ldw_mmu,
    __ldl_mmu,
    __ldq_mmu,
};

449
static const void * const qemu_st_helpers[4] = {
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
    __stb_mmu,
    __stw_mmu,
    __stl_mmu,
    __stq_mmu,
};
#endif

static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
                            int opc)
{
    int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, ld_op;
#if defined(CONFIG_SOFTMMU)
    uint8_t *label1_ptr, *label2_ptr;
#endif

    data_reg = *args++;
    addr_reg = *args++;
    mem_index = *args;
    s_bits = opc & 3;

    r0 = TCG_REG_I0;
    r1 = TCG_REG_I1;

#if TARGET_LONG_BITS == 32
    ld_op = LDUW;
#else
    ld_op = LDX;
#endif

#if defined(CONFIG_SOFTMMU)
    /* srl addr_reg, x, r1 */
    tcg_out_arithi(s, r1, addr_reg, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS,
                   SHIFT_SRL);
    /* and addr_reg, x, r0 */
    tcg_out_arithi(s, r0, addr_reg, TARGET_PAGE_MASK | ((1 << s_bits) - 1),
                   ARITH_AND);

    /* and r1, x, r1 */
    tcg_out_arithi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS,
                   ARITH_AND);

    /* add r1, x, r1 */
    tcg_out_arithi(s, r1, r1, offsetof(CPUState, tlb_table[mem_index][0].addr_read),
                   ARITH_ADD);

    /* ld [env + r1], r1 */
    tcg_out_ldst(s, r1, TCG_AREG0, r1, ld_op);

    /* subcc r0, r1, %g0 */
    tcg_out_arith(s, TCG_REG_G0, r0, r1, ARITH_SUBCC);

    /* will become:
       be label1 */
    label1_ptr = s->code_ptr;
    tcg_out32(s, 0);

    /* mov (delay slot)*/
    tcg_out_mov(s, r0, addr_reg);

    /* XXX: move that code at the end of the TB */
    tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_ld_helpers[s_bits]
                           - (tcg_target_ulong)s->code_ptr) >> 2)
                         & 0x3fffffff));
    /* mov (delay slot)*/
    tcg_out_movi(s, TCG_TYPE_I32, r1, mem_index);

    switch(opc) {
    case 0 | 4:
        /* sll i0, 24/56, i0 */
        tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0,
                       sizeof(tcg_target_long) * 8 - 8, SHIFT_SLL);
        /* sra i0, 24/56, data_reg */
        tcg_out_arithi(s, data_reg, TCG_REG_I0,
                       sizeof(tcg_target_long) * 8 - 8, SHIFT_SRA);
        break;
    case 1 | 4:
        /* sll i0, 16/48, i0 */
        tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0,
                       sizeof(tcg_target_long) * 8 - 16, SHIFT_SLL);
        /* sra i0, 16/48, data_reg */
        tcg_out_arithi(s, data_reg, TCG_REG_I0,
                       sizeof(tcg_target_long) * 8 - 16, SHIFT_SRA);
        break;
    case 2 | 4:
        /* sll i0, 32, i0 */
        tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0, 32, SHIFT_SLL);
        /* sra i0, 32, data_reg */
        tcg_out_arithi(s, data_reg, TCG_REG_I0, 32, SHIFT_SRA);
        break;
    case 0:
    case 1:
    case 2:
    case 3:
    default:
        /* mov */
        tcg_out_mov(s, data_reg, TCG_REG_I0);
        break;
    }

    /* will become:
       ba label2 */
    label2_ptr = s->code_ptr;
    tcg_out32(s, 0);

    /* label1: */
555
    *label1_ptr = (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2) |
556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
                   INSN_OFF22((unsigned long)label1_ptr -
                              (unsigned long)s->code_ptr));

    /* ld [r1 + x], r1 */
    tcg_out_ldst(s, r1, r1, offsetof(CPUTLBEntry, addend) -
                 offsetof(CPUTLBEntry, addr_read), ld_op);
    /* add x(r1), r0 */
    tcg_out_arith(s, r0, r1, r0, ARITH_ADD);
#else
    r0 = addr_reg;
#endif

#ifdef TARGET_WORDS_BIGENDIAN
    bswap = 0;
#else
    bswap = 1;
#endif
    switch(opc) {
    case 0:
        /* ldub [r0], data_reg */
        tcg_out_ldst(s, data_reg, r0, 0, LDUB);
        break;
    case 0 | 4:
        /* ldsb [r0], data_reg */
        tcg_out_ldst(s, data_reg, r0, 0, LDSB);
        break;
    case 1:
        /* lduh [r0], data_reg */
        tcg_out_ldst(s, data_reg, r0, 0, LDUH);
        if (bswap) {
            fprintf(stderr, "unimplemented %s with bswap\n", __func__);
        }
        break;
    case 1 | 4:
        /* ldsh [r0], data_reg */
        tcg_out_ldst(s, data_reg, r0, 0, LDSH);
        if (bswap) {
            fprintf(stderr, "unimplemented %s with bswap\n", __func__);
        }
        break;
    case 2:
        /* lduw [r0], data_reg */
        tcg_out_ldst(s, data_reg, r0, 0, LDUW);
        if (bswap) {
            fprintf(stderr, "unimplemented %s with bswap\n", __func__);
        }
        break;
    case 2 | 4:
        /* ldsw [r0], data_reg */
        tcg_out_ldst(s, data_reg, r0, 0, LDSW);
        if (bswap) {
            fprintf(stderr, "unimplemented %s with bswap\n", __func__);
        }
        break;
    case 3:
        /* ldx [r0], data_reg */
        tcg_out_ldst(s, data_reg, r0, 0, LDX);
        if (bswap) {
            fprintf(stderr, "unimplemented %s with bswap\n", __func__);
        }
        break;
    default:
        tcg_abort();
    }

#if defined(CONFIG_SOFTMMU)
    /* label2: */
623
    *label2_ptr = (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2) |
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726
                   INSN_OFF22((unsigned long)label2_ptr -
                              (unsigned long)s->code_ptr));
#endif
}

static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
                            int opc)
{
    int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, ld_op;
#if defined(CONFIG_SOFTMMU)
    uint8_t *label1_ptr, *label2_ptr;
#endif

    data_reg = *args++;
    addr_reg = *args++;
    mem_index = *args;

    s_bits = opc;

    r0 = TCG_REG_I5;
    r1 = TCG_REG_I4;

#if TARGET_LONG_BITS == 32
    ld_op = LDUW;
#else
    ld_op = LDX;
#endif

#if defined(CONFIG_SOFTMMU)
    /* srl addr_reg, x, r1 */
    tcg_out_arithi(s, r1, addr_reg, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS,
                   SHIFT_SRL);
    /* and addr_reg, x, r0 */
    tcg_out_arithi(s, r0, addr_reg, TARGET_PAGE_MASK | ((1 << s_bits) - 1),
                   ARITH_AND);

    /* and r1, x, r1 */
    tcg_out_arithi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS,
                   ARITH_AND);

    /* add r1, x, r1 */
    tcg_out_arithi(s, r1, r1,
                   offsetof(CPUState, tlb_table[mem_index][0].addr_write),
                   ARITH_ADD);

    /* ld [env + r1], r1 */
    tcg_out_ldst(s, r1, TCG_AREG0, r1, ld_op);

    /* subcc r0, r1, %g0 */
    tcg_out_arith(s, TCG_REG_G0, r0, r1, ARITH_SUBCC);

    /* will become:
       be label1 */
    label1_ptr = s->code_ptr;
    tcg_out32(s, 0);
    /* mov (delay slot)*/
    tcg_out_mov(s, r0, addr_reg);

    switch(opc) {
    case 0 | 4:
        /* sll i0, 24/56, i0 */
        tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0,
                       sizeof(tcg_target_long) * 8 - 8, SHIFT_SLL);
        /* sra i0, 24/56, data_reg */
        tcg_out_arithi(s, data_reg, TCG_REG_I0,
                       sizeof(tcg_target_long) * 8 - 8, SHIFT_SRA);
        break;
    case 1 | 4:
        /* sll i0, 16/48, i0 */
        tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0,
                       sizeof(tcg_target_long) * 8 - 16, SHIFT_SLL);
        /* sra i0, 16/48, data_reg */
        tcg_out_arithi(s, data_reg, TCG_REG_I0,
                       sizeof(tcg_target_long) * 8 - 16, SHIFT_SRA);
        break;
    case 2 | 4:
        /* sll i0, 32, i0 */
        tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0, 32, SHIFT_SLL);
        /* sra i0, 32, data_reg */
        tcg_out_arithi(s, data_reg, TCG_REG_I0, 32, SHIFT_SRA);
        break;
    case 0:
    case 1:
    case 2:
    case 3:
    default:
        /* mov */
        tcg_out_mov(s, data_reg, TCG_REG_I0);
        break;
    }

    tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_st_helpers[s_bits]
                           - (tcg_target_ulong)s->code_ptr) >> 2)
                         & 0x3fffffff));
    /* mov (delay slot)*/
    tcg_out_movi(s, TCG_TYPE_I32, r1, mem_index);

    /* will become:
       ba label2 */
    label2_ptr = s->code_ptr;
    tcg_out32(s, 0);

    /* label1: */
727
    *label1_ptr = (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2) |
728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
                   INSN_OFF22((unsigned long)label1_ptr -
                              (unsigned long)s->code_ptr));

    /* ld [r1 + x], r1 */
    tcg_out_ldst(s, r1, r1, offsetof(CPUTLBEntry, addend) -
                 offsetof(CPUTLBEntry, addr_write), ld_op);
    /* add x(r1), r0 */
    tcg_out_arith(s, r0, r1, r0, ARITH_ADD);
#else
    r0 = addr_reg;
#endif

#ifdef TARGET_WORDS_BIGENDIAN
    bswap = 0;
#else
    bswap = 1;
#endif
    switch(opc) {
    case 0:
        /* stb data_reg, [r0] */
        tcg_out_ldst(s, data_reg, r0, 0, STB);
        break;
    case 1:
        if (bswap) {
            fprintf(stderr, "unimplemented %s with bswap\n", __func__);
        }
        /* sth data_reg, [r0] */
        tcg_out_ldst(s, data_reg, r0, 0, STH);
        break;
    case 2:
        if (bswap) {
            fprintf(stderr, "unimplemented %s with bswap\n", __func__);
        }
        /* stw data_reg, [r0] */
        tcg_out_ldst(s, data_reg, r0, 0, STW);
        break;
    case 3:
        if (bswap) {
            fprintf(stderr, "unimplemented %s with bswap\n", __func__);
        }
        /* stx data_reg, [r0] */
        tcg_out_ldst(s, data_reg, r0, 0, STX);
        break;
    default:
        tcg_abort();
    }

#if defined(CONFIG_SOFTMMU)
    /* label2: */
777
    *label2_ptr = (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2) |
778 779 780 781 782
                   INSN_OFF22((unsigned long)label2_ptr -
                              (unsigned long)s->code_ptr));
#endif
}

B
blueswir1 已提交
783 784 785 786 787 788 789
static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
                              const int *const_args)
{
    int c;

    switch (opc) {
    case INDEX_op_exit_tb:
790 791
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I0, args[0]);
        tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I7) |
B
blueswir1 已提交
792
                  INSN_IMM13(8));
793 794
        tcg_out32(s, RESTORE | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_G0) |
                      INSN_RS2(TCG_REG_G0));
B
blueswir1 已提交
795 796 797 798
        break;
    case INDEX_op_goto_tb:
        if (s->tb_jmp_offset) {
            /* direct jump method */
799
            tcg_out_sethi(s, TCG_REG_I5, args[0] & 0xffffe000);
800 801
            tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I5) |
                      INSN_IMM13((args[0] & 0x1fff)));
B
blueswir1 已提交
802 803 804
            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
        } else {
            /* indirect jump method */
805 806 807
            tcg_out_ld_ptr(s, TCG_REG_I5, (tcg_target_long)(s->tb_next + args[0]));
            tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I5) |
                      INSN_RS2(TCG_REG_G0));
B
blueswir1 已提交
808
        }
809
        tcg_out_nop(s);
B
blueswir1 已提交
810 811 812 813 814 815 816 817 818
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
        break;
    case INDEX_op_call:
        if (const_args[0]) {
            tcg_out32(s, CALL | ((((tcg_target_ulong)args[0]
                                  - (tcg_target_ulong)s->code_ptr) >> 2)
                                 & 0x3fffffff));
            tcg_out_nop(s);
        } else {
819 820
            tcg_out_ld_ptr(s, TCG_REG_I5, (tcg_target_long)(s->tb_next + args[0]));
            tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_I5) |
821
                      INSN_RS2(TCG_REG_G0));
B
blueswir1 已提交
822 823 824 825 826
            tcg_out_nop(s);
        }
        break;
    case INDEX_op_jmp:
    case INDEX_op_br:
827 828
        tcg_out_branch(s, COND_A, args[0]);
        tcg_out_nop(s);
B
blueswir1 已提交
829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855
        break;
    case INDEX_op_movi_i32:
        tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]);
        break;

#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
#define OP_32_64(x)                             \
        glue(glue(case INDEX_op_, x), _i32:)    \
        glue(glue(case INDEX_op_, x), _i64:)
#else
#define OP_32_64(x)                             \
        glue(glue(case INDEX_op_, x), _i32:)
#endif
        OP_32_64(ld8u);
        tcg_out_ldst(s, args[0], args[1], args[2], LDUB);
        break;
        OP_32_64(ld8s);
        tcg_out_ldst(s, args[0], args[1], args[2], LDSB);
        break;
        OP_32_64(ld16u);
        tcg_out_ldst(s, args[0], args[1], args[2], LDUH);
        break;
        OP_32_64(ld16s);
        tcg_out_ldst(s, args[0], args[1], args[2], LDSH);
        break;
    case INDEX_op_ld_i32:
#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
856
    case INDEX_op_ld32u_i64:
B
blueswir1 已提交
857 858 859 860 861 862 863 864 865 866 867
#endif
        tcg_out_ldst(s, args[0], args[1], args[2], LDUW);
        break;
        OP_32_64(st8);
        tcg_out_ldst(s, args[0], args[1], args[2], STB);
        break;
        OP_32_64(st16);
        tcg_out_ldst(s, args[0], args[1], args[2], STH);
        break;
    case INDEX_op_st_i32:
#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
868
    case INDEX_op_st32_i64:
B
blueswir1 已提交
869 870 871
#endif
        tcg_out_ldst(s, args[0], args[1], args[2], STW);
        break;
872 873 874
        OP_32_64(add);
        c = ARITH_ADD;
        goto gen_arith32;
B
blueswir1 已提交
875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918
        OP_32_64(sub);
        c = ARITH_SUB;
        goto gen_arith32;
        OP_32_64(and);
        c = ARITH_AND;
        goto gen_arith32;
        OP_32_64(or);
        c = ARITH_OR;
        goto gen_arith32;
        OP_32_64(xor);
        c = ARITH_XOR;
        goto gen_arith32;
    case INDEX_op_shl_i32:
        c = SHIFT_SLL;
        goto gen_arith32;
    case INDEX_op_shr_i32:
        c = SHIFT_SRL;
        goto gen_arith32;
    case INDEX_op_sar_i32:
        c = SHIFT_SRA;
        goto gen_arith32;
    case INDEX_op_mul_i32:
        c = ARITH_UMUL;
        goto gen_arith32;
    case INDEX_op_div2_i32:
#if defined(__sparc_v9__) || defined(__sparc_v8plus__)
        c = ARITH_SDIVX;
        goto gen_arith32;
#else
        tcg_out_sety(s, 0);
        c = ARITH_SDIV;
        goto gen_arith32;
#endif
    case INDEX_op_divu2_i32:
#if defined(__sparc_v9__) || defined(__sparc_v8plus__)
        c = ARITH_UDIVX;
        goto gen_arith32;
#else
        tcg_out_sety(s, 0);
        c = ARITH_UDIV;
        goto gen_arith32;
#endif

    case INDEX_op_brcond_i32:
919 920
        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
                       args[3]);
B
blueswir1 已提交
921 922 923
        break;

    case INDEX_op_qemu_ld8u:
924
        tcg_out_qemu_ld(s, args, 0);
B
blueswir1 已提交
925 926
        break;
    case INDEX_op_qemu_ld8s:
927
        tcg_out_qemu_ld(s, args, 0 | 4);
B
blueswir1 已提交
928 929
        break;
    case INDEX_op_qemu_ld16u:
930
        tcg_out_qemu_ld(s, args, 1);
B
blueswir1 已提交
931 932
        break;
    case INDEX_op_qemu_ld16s:
933
        tcg_out_qemu_ld(s, args, 1 | 4);
B
blueswir1 已提交
934 935
        break;
    case INDEX_op_qemu_ld32u:
936
        tcg_out_qemu_ld(s, args, 2);
B
blueswir1 已提交
937 938
        break;
    case INDEX_op_qemu_ld32s:
939
        tcg_out_qemu_ld(s, args, 2 | 4);
B
blueswir1 已提交
940 941
        break;
    case INDEX_op_qemu_st8:
942
        tcg_out_qemu_st(s, args, 0);
B
blueswir1 已提交
943 944
        break;
    case INDEX_op_qemu_st16:
945
        tcg_out_qemu_st(s, args, 1);
B
blueswir1 已提交
946 947
        break;
    case INDEX_op_qemu_st32:
948
        tcg_out_qemu_st(s, args, 2);
B
blueswir1 已提交
949 950 951 952 953 954
        break;

#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
    case INDEX_op_movi_i64:
        tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
        break;
955 956 957
    case INDEX_op_ld32s_i64:
        tcg_out_ldst(s, args[0], args[1], args[2], LDSW);
        break;
B
blueswir1 已提交
958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976
    case INDEX_op_ld_i64:
        tcg_out_ldst(s, args[0], args[1], args[2], LDX);
        break;
    case INDEX_op_st_i64:
        tcg_out_ldst(s, args[0], args[1], args[2], STX);
        break;
    case INDEX_op_shl_i64:
        c = SHIFT_SLLX;
        goto gen_arith32;
    case INDEX_op_shr_i64:
        c = SHIFT_SRLX;
        goto gen_arith32;
    case INDEX_op_sar_i64:
        c = SHIFT_SRAX;
        goto gen_arith32;
    case INDEX_op_mul_i64:
        c = ARITH_MULX;
        goto gen_arith32;
    case INDEX_op_div2_i64:
977
        c = ARITH_SDIVX;
B
blueswir1 已提交
978 979 980 981 982 983
        goto gen_arith32;
    case INDEX_op_divu2_i64:
        c = ARITH_UDIVX;
        goto gen_arith32;

    case INDEX_op_brcond_i64:
984 985
        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
                       args[3]);
B
blueswir1 已提交
986 987
        break;
    case INDEX_op_qemu_ld64:
988
        tcg_out_qemu_ld(s, args, 3);
B
blueswir1 已提交
989 990
        break;
    case INDEX_op_qemu_st64:
991
        tcg_out_qemu_st(s, args, 3);
B
blueswir1 已提交
992 993 994
        break;

#endif
995 996 997 998 999 1000 1001 1002
    gen_arith32:
        if (const_args[2]) {
            tcg_out_arithi(s, args[0], args[1], args[2], c);
        } else {
            tcg_out_arith(s, args[0], args[1], args[2], c);
        }
        break;

B
blueswir1 已提交
1003 1004 1005 1006 1007 1008 1009 1010
    default:
        fprintf(stderr, "unknown opcode 0x%x\n", opc);
        tcg_abort();
    }
}

static const TCGTargetOpDef sparc_op_defs[] = {
    { INDEX_op_exit_tb, { } },
1011
    { INDEX_op_goto_tb, { } },
B
blueswir1 已提交
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
    { INDEX_op_call, { "ri" } },
    { INDEX_op_jmp, { "ri" } },
    { INDEX_op_br, { } },

    { INDEX_op_mov_i32, { "r", "r" } },
    { INDEX_op_movi_i32, { "r" } },
    { INDEX_op_ld8u_i32, { "r", "r" } },
    { INDEX_op_ld8s_i32, { "r", "r" } },
    { INDEX_op_ld16u_i32, { "r", "r" } },
    { INDEX_op_ld16s_i32, { "r", "r" } },
    { INDEX_op_ld_i32, { "r", "r" } },
    { INDEX_op_st8_i32, { "r", "r" } },
    { INDEX_op_st16_i32, { "r", "r" } },
    { INDEX_op_st_i32, { "r", "r" } },

1027 1028
    { INDEX_op_add_i32, { "r", "r", "rJ" } },
    { INDEX_op_mul_i32, { "r", "r", "rJ" } },
B
blueswir1 已提交
1029 1030
    { INDEX_op_div2_i32, { "r", "r", "0", "1", "r" } },
    { INDEX_op_divu2_i32, { "r", "r", "0", "1", "r" } },
1031 1032 1033 1034
    { INDEX_op_sub_i32, { "r", "r", "rJ" } },
    { INDEX_op_and_i32, { "r", "r", "rJ" } },
    { INDEX_op_or_i32, { "r", "r", "rJ" } },
    { INDEX_op_xor_i32, { "r", "r", "rJ" } },
B
blueswir1 已提交
1035

1036 1037 1038
    { INDEX_op_shl_i32, { "r", "r", "rJ" } },
    { INDEX_op_shr_i32, { "r", "r", "rJ" } },
    { INDEX_op_sar_i32, { "r", "r", "rJ" } },
B
blueswir1 已提交
1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067

    { INDEX_op_brcond_i32, { "r", "ri" } },

    { INDEX_op_qemu_ld8u, { "r", "L" } },
    { INDEX_op_qemu_ld8s, { "r", "L" } },
    { INDEX_op_qemu_ld16u, { "r", "L" } },
    { INDEX_op_qemu_ld16s, { "r", "L" } },
    { INDEX_op_qemu_ld32u, { "r", "L" } },
    { INDEX_op_qemu_ld32s, { "r", "L" } },

    { INDEX_op_qemu_st8, { "L", "L" } },
    { INDEX_op_qemu_st16, { "L", "L" } },
    { INDEX_op_qemu_st32, { "L", "L" } },

#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
    { INDEX_op_mov_i64, { "r", "r" } },
    { INDEX_op_movi_i64, { "r" } },
    { INDEX_op_ld8u_i64, { "r", "r" } },
    { INDEX_op_ld8s_i64, { "r", "r" } },
    { INDEX_op_ld16u_i64, { "r", "r" } },
    { INDEX_op_ld16s_i64, { "r", "r" } },
    { INDEX_op_ld32u_i64, { "r", "r" } },
    { INDEX_op_ld32s_i64, { "r", "r" } },
    { INDEX_op_ld_i64, { "r", "r" } },
    { INDEX_op_st8_i64, { "r", "r" } },
    { INDEX_op_st16_i64, { "r", "r" } },
    { INDEX_op_st32_i64, { "r", "r" } },
    { INDEX_op_st_i64, { "r", "r" } },

1068 1069
    { INDEX_op_add_i64, { "r", "r", "rJ" } },
    { INDEX_op_mul_i64, { "r", "r", "rJ" } },
B
blueswir1 已提交
1070 1071
    { INDEX_op_div2_i64, { "r", "r", "0", "1", "r" } },
    { INDEX_op_divu2_i64, { "r", "r", "0", "1", "r" } },
1072 1073 1074 1075
    { INDEX_op_sub_i64, { "r", "r", "rJ" } },
    { INDEX_op_and_i64, { "r", "r", "rJ" } },
    { INDEX_op_or_i64, { "r", "r", "rJ" } },
    { INDEX_op_xor_i64, { "r", "r", "rJ" } },
B
blueswir1 已提交
1076

1077 1078 1079
    { INDEX_op_shl_i64, { "r", "r", "rJ" } },
    { INDEX_op_shr_i64, { "r", "r", "rJ" } },
    { INDEX_op_sar_i64, { "r", "r", "rJ" } },
B
blueswir1 已提交
1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092

    { INDEX_op_brcond_i64, { "r", "ri" } },
#endif
    { -1 },
};

void tcg_target_init(TCGContext *s)
{
    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
#endif
    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1093 1094 1095 1096 1097 1098 1099
                     (1 << TCG_REG_G1) |
                     (1 << TCG_REG_G2) |
                     (1 << TCG_REG_G3) |
                     (1 << TCG_REG_G4) |
                     (1 << TCG_REG_G5) |
                     (1 << TCG_REG_G6) |
                     (1 << TCG_REG_G7) |
B
blueswir1 已提交
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109
                     (1 << TCG_REG_O0) |
                     (1 << TCG_REG_O1) |
                     (1 << TCG_REG_O2) |
                     (1 << TCG_REG_O3) |
                     (1 << TCG_REG_O4) |
                     (1 << TCG_REG_O5) |
                     (1 << TCG_REG_O7));

    tcg_regset_clear(s->reserved_regs);
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_G0);
1110
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_I5); // for internal use
B
blueswir1 已提交
1111 1112 1113 1114 1115 1116
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_I6);
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_I7);
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_O6);
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_O7);
    tcg_add_target_add_op_defs(sparc_op_defs);
}