Commit f5ef6aacd4043525c41bb37a02693011a168c14a
1 parent
21b20814
Implement qemu_ld/st, fix brcond, handle more corner cases
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4463 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
395 additions
and
29 deletions
tcg/sparc/tcg-target.c
| @@ -87,6 +87,12 @@ static const int tcg_target_call_oarg_regs[2] = { | @@ -87,6 +87,12 @@ static const int tcg_target_call_oarg_regs[2] = { | ||
| 87 | TCG_REG_O1, | 87 | TCG_REG_O1, |
| 88 | }; | 88 | }; |
| 89 | 89 | ||
| 90 | +static inline int check_fit(tcg_target_long val, unsigned int bits) | ||
| 91 | +{ | ||
| 92 | + return ((val << ((sizeof(tcg_target_long) * 8 - bits)) | ||
| 93 | + >> (sizeof(tcg_target_long) * 8 - bits)) == val); | ||
| 94 | +} | ||
| 95 | + | ||
| 90 | static void patch_reloc(uint8_t *code_ptr, int type, | 96 | static void patch_reloc(uint8_t *code_ptr, int type, |
| 91 | tcg_target_long value, tcg_target_long addend) | 97 | tcg_target_long value, tcg_target_long addend) |
| 92 | { | 98 | { |
| @@ -97,6 +103,13 @@ static void patch_reloc(uint8_t *code_ptr, int type, | @@ -97,6 +103,13 @@ static void patch_reloc(uint8_t *code_ptr, int type, | ||
| 97 | tcg_abort(); | 103 | tcg_abort(); |
| 98 | *(uint32_t *)code_ptr = value; | 104 | *(uint32_t *)code_ptr = value; |
| 99 | break; | 105 | break; |
| 106 | + case R_SPARC_WDISP22: | ||
| 107 | + value -= (long)code_ptr; | ||
| 108 | + value >>= 2; | ||
| 109 | + if (!check_fit(value, 22)) | ||
| 110 | + tcg_abort(); | ||
| 111 | + *(uint32_t *)code_ptr = ((*(uint32_t *)code_ptr) & ~0x3fffff) | value; | ||
| 112 | + break; | ||
| 100 | default: | 113 | default: |
| 101 | tcg_abort(); | 114 | tcg_abort(); |
| 102 | } | 115 | } |
| @@ -119,6 +132,8 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) | @@ -119,6 +132,8 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) | ||
| 119 | case 'L': /* qemu_ld/st constraint */ | 132 | case 'L': /* qemu_ld/st constraint */ |
| 120 | ct->ct |= TCG_CT_REG; | 133 | ct->ct |= TCG_CT_REG; |
| 121 | tcg_regset_set32(ct->u.regs, 0, 0xffffffff); | 134 | tcg_regset_set32(ct->u.regs, 0, 0xffffffff); |
| 135 | + tcg_regset_reset_reg(ct->u.regs, TCG_REG_I0); | ||
| 136 | + tcg_regset_reset_reg(ct->u.regs, TCG_REG_I1); | ||
| 122 | break; | 137 | break; |
| 123 | case 'I': | 138 | case 'I': |
| 124 | ct->ct |= TCG_CT_CONST_S11; | 139 | ct->ct |= TCG_CT_CONST_S11; |
| @@ -134,12 +149,6 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) | @@ -134,12 +149,6 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) | ||
| 134 | return 0; | 149 | return 0; |
| 135 | } | 150 | } |
| 136 | 151 | ||
| 137 | -static inline int check_fit(tcg_target_long val, unsigned int bits) | ||
| 138 | -{ | ||
| 139 | - return ((val << ((sizeof(tcg_target_long) * 8 - bits)) | ||
| 140 | - >> (sizeof(tcg_target_long) * 8 - bits)) == val); | ||
| 141 | -} | ||
| 142 | - | ||
| 143 | /* test if a constant matches the constraint */ | 152 | /* test if a constant matches the constraint */ |
| 144 | static inline int tcg_target_const_match(tcg_target_long val, | 153 | static inline int tcg_target_const_match(tcg_target_long val, |
| 145 | const TCGArgConstraint *arg_ct) | 154 | const TCGArgConstraint *arg_ct) |
| @@ -192,8 +201,8 @@ static inline int tcg_target_const_match(tcg_target_long val, | @@ -192,8 +201,8 @@ static inline int tcg_target_const_match(tcg_target_long val, | ||
| 192 | #define ARITH_ANDCC (INSN_OP(2) | INSN_OP3(0x11)) | 201 | #define ARITH_ANDCC (INSN_OP(2) | INSN_OP3(0x11)) |
| 193 | #define ARITH_OR (INSN_OP(2) | INSN_OP3(0x02)) | 202 | #define ARITH_OR (INSN_OP(2) | INSN_OP3(0x02)) |
| 194 | #define ARITH_XOR (INSN_OP(2) | INSN_OP3(0x03)) | 203 | #define ARITH_XOR (INSN_OP(2) | INSN_OP3(0x03)) |
| 195 | -#define ARITH_SUB (INSN_OP(2) | INSN_OP3(0x08)) | ||
| 196 | -#define ARITH_SUBCC (INSN_OP(2) | INSN_OP3(0x18)) | 204 | +#define ARITH_SUB (INSN_OP(2) | INSN_OP3(0x04)) |
| 205 | +#define ARITH_SUBCC (INSN_OP(2) | INSN_OP3(0x14)) | ||
| 197 | #define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x10)) | 206 | #define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x10)) |
| 198 | #define ARITH_SUBX (INSN_OP(2) | INSN_OP3(0x0c)) | 207 | #define ARITH_SUBX (INSN_OP(2) | INSN_OP3(0x0c)) |
| 199 | #define ARITH_UMUL (INSN_OP(2) | INSN_OP3(0x0a)) | 208 | #define ARITH_UMUL (INSN_OP(2) | INSN_OP3(0x0a)) |
| @@ -333,8 +342,10 @@ static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) | @@ -333,8 +342,10 @@ static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) | ||
| 333 | if (val != 0) { | 342 | if (val != 0) { |
| 334 | if (check_fit(val, 13)) | 343 | if (check_fit(val, 13)) |
| 335 | tcg_out_arithi(s, reg, reg, val, ARITH_ADD); | 344 | tcg_out_arithi(s, reg, reg, val, ARITH_ADD); |
| 336 | - else | ||
| 337 | - fprintf(stderr, "unimplemented addi %ld\n", (long)val); | 345 | + else { |
| 346 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, val); | ||
| 347 | + tcg_out_arith(s, reg, reg, TCG_REG_I5, ARITH_ADD); | ||
| 348 | + } | ||
| 338 | } | 349 | } |
| 339 | } | 350 | } |
| 340 | 351 | ||
| @@ -350,10 +361,12 @@ static void tcg_out_branch(TCGContext *s, int opc, int label_index) | @@ -350,10 +361,12 @@ static void tcg_out_branch(TCGContext *s, int opc, int label_index) | ||
| 350 | 361 | ||
| 351 | if (l->has_value) { | 362 | if (l->has_value) { |
| 352 | val = l->u.value - (tcg_target_long)s->code_ptr; | 363 | val = l->u.value - (tcg_target_long)s->code_ptr; |
| 353 | - tcg_out32(s, (INSN_OP(0) | opc | INSN_OP2(0x2) | 364 | + tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) |
| 354 | | INSN_OFF22(l->u.value - (unsigned long)s->code_ptr))); | 365 | | INSN_OFF22(l->u.value - (unsigned long)s->code_ptr))); |
| 355 | - } else | ||
| 356 | - fprintf(stderr, "unimplemented branch\n"); | 366 | + } else { |
| 367 | + tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP22, label_index, 0); | ||
| 368 | + tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) | 0)); | ||
| 369 | + } | ||
| 357 | } | 370 | } |
| 358 | 371 | ||
| 359 | static const uint8_t tcg_cond_to_bcond[10] = { | 372 | static const uint8_t tcg_cond_to_bcond[10] = { |
| @@ -375,7 +388,7 @@ static void tcg_out_brcond(TCGContext *s, int cond, | @@ -375,7 +388,7 @@ static void tcg_out_brcond(TCGContext *s, int cond, | ||
| 375 | { | 388 | { |
| 376 | if (const_arg2 && arg2 == 0) | 389 | if (const_arg2 && arg2 == 0) |
| 377 | /* andcc r, r, %g0 */ | 390 | /* andcc r, r, %g0 */ |
| 378 | - tcg_out_arithi(s, TCG_REG_G0, arg1, arg1, ARITH_ANDCC); | 391 | + tcg_out_arith(s, TCG_REG_G0, arg1, arg1, ARITH_ANDCC); |
| 379 | else | 392 | else |
| 380 | /* subcc r1, r2, %g0 */ | 393 | /* subcc r1, r2, %g0 */ |
| 381 | tcg_out_arith(s, TCG_REG_G0, arg1, arg2, ARITH_SUBCC); | 394 | tcg_out_arith(s, TCG_REG_G0, arg1, arg2, ARITH_SUBCC); |
| @@ -393,6 +406,359 @@ void tcg_target_qemu_prologue(TCGContext *s) | @@ -393,6 +406,359 @@ void tcg_target_qemu_prologue(TCGContext *s) | ||
| 393 | tcg_out_nop(s); | 406 | tcg_out_nop(s); |
| 394 | } | 407 | } |
| 395 | 408 | ||
| 409 | +#if defined(CONFIG_SOFTMMU) | ||
| 410 | +extern void __ldb_mmu(void); | ||
| 411 | +extern void __ldw_mmu(void); | ||
| 412 | +extern void __ldl_mmu(void); | ||
| 413 | +extern void __ldq_mmu(void); | ||
| 414 | + | ||
| 415 | +extern void __stb_mmu(void); | ||
| 416 | +extern void __stw_mmu(void); | ||
| 417 | +extern void __stl_mmu(void); | ||
| 418 | +extern void __stq_mmu(void); | ||
| 419 | + | ||
| 420 | + | ||
| 421 | +static void *qemu_ld_helpers[4] = { | ||
| 422 | + __ldb_mmu, | ||
| 423 | + __ldw_mmu, | ||
| 424 | + __ldl_mmu, | ||
| 425 | + __ldq_mmu, | ||
| 426 | +}; | ||
| 427 | + | ||
| 428 | +static void *qemu_st_helpers[4] = { | ||
| 429 | + __stb_mmu, | ||
| 430 | + __stw_mmu, | ||
| 431 | + __stl_mmu, | ||
| 432 | + __stq_mmu, | ||
| 433 | +}; | ||
| 434 | +#endif | ||
| 435 | + | ||
| 436 | +static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, | ||
| 437 | + int opc) | ||
| 438 | +{ | ||
| 439 | + int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, ld_op; | ||
| 440 | +#if defined(CONFIG_SOFTMMU) | ||
| 441 | + uint8_t *label1_ptr, *label2_ptr; | ||
| 442 | +#endif | ||
| 443 | + | ||
| 444 | + data_reg = *args++; | ||
| 445 | + addr_reg = *args++; | ||
| 446 | + mem_index = *args; | ||
| 447 | + s_bits = opc & 3; | ||
| 448 | + | ||
| 449 | + r0 = TCG_REG_I0; | ||
| 450 | + r1 = TCG_REG_I1; | ||
| 451 | + | ||
| 452 | +#if TARGET_LONG_BITS == 32 | ||
| 453 | + ld_op = LDUW; | ||
| 454 | +#else | ||
| 455 | + ld_op = LDX; | ||
| 456 | +#endif | ||
| 457 | + | ||
| 458 | +#if defined(CONFIG_SOFTMMU) | ||
| 459 | + /* srl addr_reg, x, r1 */ | ||
| 460 | + tcg_out_arithi(s, r1, addr_reg, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS, | ||
| 461 | + SHIFT_SRL); | ||
| 462 | + /* and addr_reg, x, r0 */ | ||
| 463 | + tcg_out_arithi(s, r0, addr_reg, TARGET_PAGE_MASK | ((1 << s_bits) - 1), | ||
| 464 | + ARITH_AND); | ||
| 465 | + | ||
| 466 | + /* and r1, x, r1 */ | ||
| 467 | + tcg_out_arithi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, | ||
| 468 | + ARITH_AND); | ||
| 469 | + | ||
| 470 | + /* add r1, x, r1 */ | ||
| 471 | + tcg_out_arithi(s, r1, r1, offsetof(CPUState, tlb_table[mem_index][0].addr_read), | ||
| 472 | + ARITH_ADD); | ||
| 473 | + | ||
| 474 | + /* ld [env + r1], r1 */ | ||
| 475 | + tcg_out_ldst(s, r1, TCG_AREG0, r1, ld_op); | ||
| 476 | + | ||
| 477 | + /* subcc r0, r1, %g0 */ | ||
| 478 | + tcg_out_arith(s, TCG_REG_G0, r0, r1, ARITH_SUBCC); | ||
| 479 | + | ||
| 480 | + /* will become: | ||
| 481 | + be label1 */ | ||
| 482 | + label1_ptr = s->code_ptr; | ||
| 483 | + tcg_out32(s, 0); | ||
| 484 | + | ||
| 485 | + /* mov (delay slot)*/ | ||
| 486 | + tcg_out_mov(s, r0, addr_reg); | ||
| 487 | + | ||
| 488 | + /* XXX: move that code at the end of the TB */ | ||
| 489 | + tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_ld_helpers[s_bits] | ||
| 490 | + - (tcg_target_ulong)s->code_ptr) >> 2) | ||
| 491 | + & 0x3fffffff)); | ||
| 492 | + /* mov (delay slot)*/ | ||
| 493 | + tcg_out_movi(s, TCG_TYPE_I32, r1, mem_index); | ||
| 494 | + | ||
| 495 | + switch(opc) { | ||
| 496 | + case 0 | 4: | ||
| 497 | + /* sll i0, 24/56, i0 */ | ||
| 498 | + tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0, | ||
| 499 | + sizeof(tcg_target_long) * 8 - 8, SHIFT_SLL); | ||
| 500 | + /* sra i0, 24/56, data_reg */ | ||
| 501 | + tcg_out_arithi(s, data_reg, TCG_REG_I0, | ||
| 502 | + sizeof(tcg_target_long) * 8 - 8, SHIFT_SRA); | ||
| 503 | + break; | ||
| 504 | + case 1 | 4: | ||
| 505 | + /* sll i0, 16/48, i0 */ | ||
| 506 | + tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0, | ||
| 507 | + sizeof(tcg_target_long) * 8 - 16, SHIFT_SLL); | ||
| 508 | + /* sra i0, 16/48, data_reg */ | ||
| 509 | + tcg_out_arithi(s, data_reg, TCG_REG_I0, | ||
| 510 | + sizeof(tcg_target_long) * 8 - 16, SHIFT_SRA); | ||
| 511 | + break; | ||
| 512 | + case 2 | 4: | ||
| 513 | + /* sll i0, 32, i0 */ | ||
| 514 | + tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0, 32, SHIFT_SLL); | ||
| 515 | + /* sra i0, 32, data_reg */ | ||
| 516 | + tcg_out_arithi(s, data_reg, TCG_REG_I0, 32, SHIFT_SRA); | ||
| 517 | + break; | ||
| 518 | + case 0: | ||
| 519 | + case 1: | ||
| 520 | + case 2: | ||
| 521 | + case 3: | ||
| 522 | + default: | ||
| 523 | + /* mov */ | ||
| 524 | + tcg_out_mov(s, data_reg, TCG_REG_I0); | ||
| 525 | + break; | ||
| 526 | + } | ||
| 527 | + | ||
| 528 | + /* will become: | ||
| 529 | + ba label2 */ | ||
| 530 | + label2_ptr = s->code_ptr; | ||
| 531 | + tcg_out32(s, 0); | ||
| 532 | + | ||
| 533 | + /* label1: */ | ||
| 534 | + *label1_ptr = (INSN_OP(0) | COND_A | INSN_OP2(0x2) | | ||
| 535 | + INSN_OFF22((unsigned long)label1_ptr - | ||
| 536 | + (unsigned long)s->code_ptr)); | ||
| 537 | + | ||
| 538 | + /* ld [r1 + x], r1 */ | ||
| 539 | + tcg_out_ldst(s, r1, r1, offsetof(CPUTLBEntry, addend) - | ||
| 540 | + offsetof(CPUTLBEntry, addr_read), ld_op); | ||
| 541 | + /* add x(r1), r0 */ | ||
| 542 | + tcg_out_arith(s, r0, r1, r0, ARITH_ADD); | ||
| 543 | +#else | ||
| 544 | + r0 = addr_reg; | ||
| 545 | +#endif | ||
| 546 | + | ||
| 547 | +#ifdef TARGET_WORDS_BIGENDIAN | ||
| 548 | + bswap = 0; | ||
| 549 | +#else | ||
| 550 | + bswap = 1; | ||
| 551 | +#endif | ||
| 552 | + switch(opc) { | ||
| 553 | + case 0: | ||
| 554 | + /* ldub [r0], data_reg */ | ||
| 555 | + tcg_out_ldst(s, data_reg, r0, 0, LDUB); | ||
| 556 | + break; | ||
| 557 | + case 0 | 4: | ||
| 558 | + /* ldsb [r0], data_reg */ | ||
| 559 | + tcg_out_ldst(s, data_reg, r0, 0, LDSB); | ||
| 560 | + break; | ||
| 561 | + case 1: | ||
| 562 | + /* lduh [r0], data_reg */ | ||
| 563 | + tcg_out_ldst(s, data_reg, r0, 0, LDUH); | ||
| 564 | + if (bswap) { | ||
| 565 | + fprintf(stderr, "unimplemented %s with bswap\n", __func__); | ||
| 566 | + } | ||
| 567 | + break; | ||
| 568 | + case 1 | 4: | ||
| 569 | + /* ldsh [r0], data_reg */ | ||
| 570 | + tcg_out_ldst(s, data_reg, r0, 0, LDSH); | ||
| 571 | + if (bswap) { | ||
| 572 | + fprintf(stderr, "unimplemented %s with bswap\n", __func__); | ||
| 573 | + } | ||
| 574 | + break; | ||
| 575 | + case 2: | ||
| 576 | + /* lduw [r0], data_reg */ | ||
| 577 | + tcg_out_ldst(s, data_reg, r0, 0, LDUW); | ||
| 578 | + if (bswap) { | ||
| 579 | + fprintf(stderr, "unimplemented %s with bswap\n", __func__); | ||
| 580 | + } | ||
| 581 | + break; | ||
| 582 | + case 2 | 4: | ||
| 583 | + /* ldsw [r0], data_reg */ | ||
| 584 | + tcg_out_ldst(s, data_reg, r0, 0, LDSW); | ||
| 585 | + if (bswap) { | ||
| 586 | + fprintf(stderr, "unimplemented %s with bswap\n", __func__); | ||
| 587 | + } | ||
| 588 | + break; | ||
| 589 | + case 3: | ||
| 590 | + /* ldx [r0], data_reg */ | ||
| 591 | + tcg_out_ldst(s, data_reg, r0, 0, LDX); | ||
| 592 | + if (bswap) { | ||
| 593 | + fprintf(stderr, "unimplemented %s with bswap\n", __func__); | ||
| 594 | + } | ||
| 595 | + break; | ||
| 596 | + default: | ||
| 597 | + tcg_abort(); | ||
| 598 | + } | ||
| 599 | + | ||
| 600 | +#if defined(CONFIG_SOFTMMU) | ||
| 601 | + /* label2: */ | ||
| 602 | + *label2_ptr = (INSN_OP(0) | COND_A | INSN_OP2(0x2) | | ||
| 603 | + INSN_OFF22((unsigned long)label2_ptr - | ||
| 604 | + (unsigned long)s->code_ptr)); | ||
| 605 | +#endif | ||
| 606 | +} | ||
| 607 | + | ||
| 608 | +static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, | ||
| 609 | + int opc) | ||
| 610 | +{ | ||
| 611 | + int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, ld_op; | ||
| 612 | +#if defined(CONFIG_SOFTMMU) | ||
| 613 | + uint8_t *label1_ptr, *label2_ptr; | ||
| 614 | +#endif | ||
| 615 | + | ||
| 616 | + data_reg = *args++; | ||
| 617 | + addr_reg = *args++; | ||
| 618 | + mem_index = *args; | ||
| 619 | + | ||
| 620 | + s_bits = opc; | ||
| 621 | + | ||
| 622 | + r0 = TCG_REG_I5; | ||
| 623 | + r1 = TCG_REG_I4; | ||
| 624 | + | ||
| 625 | +#if TARGET_LONG_BITS == 32 | ||
| 626 | + ld_op = LDUW; | ||
| 627 | +#else | ||
| 628 | + ld_op = LDX; | ||
| 629 | +#endif | ||
| 630 | + | ||
| 631 | +#if defined(CONFIG_SOFTMMU) | ||
| 632 | + /* srl addr_reg, x, r1 */ | ||
| 633 | + tcg_out_arithi(s, r1, addr_reg, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS, | ||
| 634 | + SHIFT_SRL); | ||
| 635 | + /* and addr_reg, x, r0 */ | ||
| 636 | + tcg_out_arithi(s, r0, addr_reg, TARGET_PAGE_MASK | ((1 << s_bits) - 1), | ||
| 637 | + ARITH_AND); | ||
| 638 | + | ||
| 639 | + /* and r1, x, r1 */ | ||
| 640 | + tcg_out_arithi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, | ||
| 641 | + ARITH_AND); | ||
| 642 | + | ||
| 643 | + /* add r1, x, r1 */ | ||
| 644 | + tcg_out_arithi(s, r1, r1, | ||
| 645 | + offsetof(CPUState, tlb_table[mem_index][0].addr_write), | ||
| 646 | + ARITH_ADD); | ||
| 647 | + | ||
| 648 | + /* ld [env + r1], r1 */ | ||
| 649 | + tcg_out_ldst(s, r1, TCG_AREG0, r1, ld_op); | ||
| 650 | + | ||
| 651 | + /* subcc r0, r1, %g0 */ | ||
| 652 | + tcg_out_arith(s, TCG_REG_G0, r0, r1, ARITH_SUBCC); | ||
| 653 | + | ||
| 654 | + /* will become: | ||
| 655 | + be label1 */ | ||
| 656 | + label1_ptr = s->code_ptr; | ||
| 657 | + tcg_out32(s, 0); | ||
| 658 | + /* mov (delay slot)*/ | ||
| 659 | + tcg_out_mov(s, r0, addr_reg); | ||
| 660 | + | ||
| 661 | + switch(opc) { | ||
| 662 | + case 0 | 4: | ||
| 663 | + /* sll i0, 24/56, i0 */ | ||
| 664 | + tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0, | ||
| 665 | + sizeof(tcg_target_long) * 8 - 8, SHIFT_SLL); | ||
| 666 | + /* sra i0, 24/56, data_reg */ | ||
| 667 | + tcg_out_arithi(s, data_reg, TCG_REG_I0, | ||
| 668 | + sizeof(tcg_target_long) * 8 - 8, SHIFT_SRA); | ||
| 669 | + break; | ||
| 670 | + case 1 | 4: | ||
| 671 | + /* sll i0, 16/48, i0 */ | ||
| 672 | + tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0, | ||
| 673 | + sizeof(tcg_target_long) * 8 - 16, SHIFT_SLL); | ||
| 674 | + /* sra i0, 16/48, data_reg */ | ||
| 675 | + tcg_out_arithi(s, data_reg, TCG_REG_I0, | ||
| 676 | + sizeof(tcg_target_long) * 8 - 16, SHIFT_SRA); | ||
| 677 | + break; | ||
| 678 | + case 2 | 4: | ||
| 679 | + /* sll i0, 32, i0 */ | ||
| 680 | + tcg_out_arithi(s, TCG_REG_I0, TCG_REG_I0, 32, SHIFT_SLL); | ||
| 681 | + /* sra i0, 32, data_reg */ | ||
| 682 | + tcg_out_arithi(s, data_reg, TCG_REG_I0, 32, SHIFT_SRA); | ||
| 683 | + break; | ||
| 684 | + case 0: | ||
| 685 | + case 1: | ||
| 686 | + case 2: | ||
| 687 | + case 3: | ||
| 688 | + default: | ||
| 689 | + /* mov */ | ||
| 690 | + tcg_out_mov(s, data_reg, TCG_REG_I0); | ||
| 691 | + break; | ||
| 692 | + } | ||
| 693 | + | ||
| 694 | + tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_st_helpers[s_bits] | ||
| 695 | + - (tcg_target_ulong)s->code_ptr) >> 2) | ||
| 696 | + & 0x3fffffff)); | ||
| 697 | + /* mov (delay slot)*/ | ||
| 698 | + tcg_out_movi(s, TCG_TYPE_I32, r1, mem_index); | ||
| 699 | + | ||
| 700 | + /* will become: | ||
| 701 | + ba label2 */ | ||
| 702 | + label2_ptr = s->code_ptr; | ||
| 703 | + tcg_out32(s, 0); | ||
| 704 | + | ||
| 705 | + /* label1: */ | ||
| 706 | + *label1_ptr = (INSN_OP(0) | COND_A | INSN_OP2(0x2) | | ||
| 707 | + INSN_OFF22((unsigned long)label1_ptr - | ||
| 708 | + (unsigned long)s->code_ptr)); | ||
| 709 | + | ||
| 710 | + /* ld [r1 + x], r1 */ | ||
| 711 | + tcg_out_ldst(s, r1, r1, offsetof(CPUTLBEntry, addend) - | ||
| 712 | + offsetof(CPUTLBEntry, addr_write), ld_op); | ||
| 713 | + /* add x(r1), r0 */ | ||
| 714 | + tcg_out_arith(s, r0, r1, r0, ARITH_ADD); | ||
| 715 | +#else | ||
| 716 | + r0 = addr_reg; | ||
| 717 | +#endif | ||
| 718 | + | ||
| 719 | +#ifdef TARGET_WORDS_BIGENDIAN | ||
| 720 | + bswap = 0; | ||
| 721 | +#else | ||
| 722 | + bswap = 1; | ||
| 723 | +#endif | ||
| 724 | + switch(opc) { | ||
| 725 | + case 0: | ||
| 726 | + /* stb data_reg, [r0] */ | ||
| 727 | + tcg_out_ldst(s, data_reg, r0, 0, STB); | ||
| 728 | + break; | ||
| 729 | + case 1: | ||
| 730 | + if (bswap) { | ||
| 731 | + fprintf(stderr, "unimplemented %s with bswap\n", __func__); | ||
| 732 | + } | ||
| 733 | + /* sth data_reg, [r0] */ | ||
| 734 | + tcg_out_ldst(s, data_reg, r0, 0, STH); | ||
| 735 | + break; | ||
| 736 | + case 2: | ||
| 737 | + if (bswap) { | ||
| 738 | + fprintf(stderr, "unimplemented %s with bswap\n", __func__); | ||
| 739 | + } | ||
| 740 | + /* stw data_reg, [r0] */ | ||
| 741 | + tcg_out_ldst(s, data_reg, r0, 0, STW); | ||
| 742 | + break; | ||
| 743 | + case 3: | ||
| 744 | + if (bswap) { | ||
| 745 | + fprintf(stderr, "unimplemented %s with bswap\n", __func__); | ||
| 746 | + } | ||
| 747 | + /* stx data_reg, [r0] */ | ||
| 748 | + tcg_out_ldst(s, data_reg, r0, 0, STX); | ||
| 749 | + break; | ||
| 750 | + default: | ||
| 751 | + tcg_abort(); | ||
| 752 | + } | ||
| 753 | + | ||
| 754 | +#if defined(CONFIG_SOFTMMU) | ||
| 755 | + /* label2: */ | ||
| 756 | + *label2_ptr = (INSN_OP(0) | COND_A | INSN_OP2(0x2) | | ||
| 757 | + INSN_OFF22((unsigned long)label2_ptr - | ||
| 758 | + (unsigned long)s->code_ptr)); | ||
| 759 | +#endif | ||
| 760 | +} | ||
| 761 | + | ||
| 396 | static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | 762 | static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |
| 397 | const int *const_args) | 763 | const int *const_args) |
| 398 | { | 764 | { |
| @@ -437,10 +803,9 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | @@ -437,10 +803,9 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | ||
| 437 | } | 803 | } |
| 438 | break; | 804 | break; |
| 439 | case INDEX_op_jmp: | 805 | case INDEX_op_jmp: |
| 440 | - fprintf(stderr, "unimplemented jmp\n"); | ||
| 441 | - break; | ||
| 442 | case INDEX_op_br: | 806 | case INDEX_op_br: |
| 443 | - fprintf(stderr, "unimplemented br\n"); | 807 | + tcg_out_branch(s, COND_A, args[0]); |
| 808 | + tcg_out_nop(s); | ||
| 444 | break; | 809 | break; |
| 445 | case INDEX_op_movi_i32: | 810 | case INDEX_op_movi_i32: |
| 446 | tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]); | 811 | tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]); |
| @@ -536,31 +901,31 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | @@ -536,31 +901,31 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | ||
| 536 | break; | 901 | break; |
| 537 | 902 | ||
| 538 | case INDEX_op_qemu_ld8u: | 903 | case INDEX_op_qemu_ld8u: |
| 539 | - fprintf(stderr, "unimplemented qld\n"); | 904 | + tcg_out_qemu_ld(s, args, 0); |
| 540 | break; | 905 | break; |
| 541 | case INDEX_op_qemu_ld8s: | 906 | case INDEX_op_qemu_ld8s: |
| 542 | - fprintf(stderr, "unimplemented qld\n"); | 907 | + tcg_out_qemu_ld(s, args, 0 | 4); |
| 543 | break; | 908 | break; |
| 544 | case INDEX_op_qemu_ld16u: | 909 | case INDEX_op_qemu_ld16u: |
| 545 | - fprintf(stderr, "unimplemented qld\n"); | 910 | + tcg_out_qemu_ld(s, args, 1); |
| 546 | break; | 911 | break; |
| 547 | case INDEX_op_qemu_ld16s: | 912 | case INDEX_op_qemu_ld16s: |
| 548 | - fprintf(stderr, "unimplemented qld\n"); | 913 | + tcg_out_qemu_ld(s, args, 1 | 4); |
| 549 | break; | 914 | break; |
| 550 | case INDEX_op_qemu_ld32u: | 915 | case INDEX_op_qemu_ld32u: |
| 551 | - fprintf(stderr, "unimplemented qld\n"); | 916 | + tcg_out_qemu_ld(s, args, 2); |
| 552 | break; | 917 | break; |
| 553 | case INDEX_op_qemu_ld32s: | 918 | case INDEX_op_qemu_ld32s: |
| 554 | - fprintf(stderr, "unimplemented qld\n"); | 919 | + tcg_out_qemu_ld(s, args, 2 | 4); |
| 555 | break; | 920 | break; |
| 556 | case INDEX_op_qemu_st8: | 921 | case INDEX_op_qemu_st8: |
| 557 | - fprintf(stderr, "unimplemented qst\n"); | 922 | + tcg_out_qemu_st(s, args, 0); |
| 558 | break; | 923 | break; |
| 559 | case INDEX_op_qemu_st16: | 924 | case INDEX_op_qemu_st16: |
| 560 | - fprintf(stderr, "unimplemented qst\n"); | 925 | + tcg_out_qemu_st(s, args, 1); |
| 561 | break; | 926 | break; |
| 562 | case INDEX_op_qemu_st32: | 927 | case INDEX_op_qemu_st32: |
| 563 | - fprintf(stderr, "unimplemented qst\n"); | 928 | + tcg_out_qemu_st(s, args, 2); |
| 564 | break; | 929 | break; |
| 565 | 930 | ||
| 566 | #if defined(__sparc_v9__) && !defined(__sparc_v8plus__) | 931 | #if defined(__sparc_v9__) && !defined(__sparc_v8plus__) |
| @@ -596,13 +961,14 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | @@ -596,13 +961,14 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | ||
| 596 | goto gen_arith32; | 961 | goto gen_arith32; |
| 597 | 962 | ||
| 598 | case INDEX_op_brcond_i64: | 963 | case INDEX_op_brcond_i64: |
| 599 | - fprintf(stderr, "unimplemented brcond\n"); | 964 | + tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], |
| 965 | + args[3]); | ||
| 600 | break; | 966 | break; |
| 601 | case INDEX_op_qemu_ld64: | 967 | case INDEX_op_qemu_ld64: |
| 602 | - fprintf(stderr, "unimplemented qld\n"); | 968 | + tcg_out_qemu_ld(s, args, 3); |
| 603 | break; | 969 | break; |
| 604 | case INDEX_op_qemu_st64: | 970 | case INDEX_op_qemu_st64: |
| 605 | - fprintf(stderr, "unimplemented qst\n"); | 971 | + tcg_out_qemu_st(s, args, 3); |
| 606 | break; | 972 | break; |
| 607 | 973 | ||
| 608 | #endif | 974 | #endif |