tcg-target.c revision 8b23a6c7e1aee255004dd19098d4c2462b61b849
1/* 2 * Tiny Code Generator for QEMU 3 * 4 * Copyright (c) 2008 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25#define TCG_CT_CONST_U32 0x100 26 27static uint8_t *tb_ret_addr; 28 29#define FAST_PATH 30 31#if TARGET_PHYS_ADDR_BITS == 32 32#define LD_ADDEND LWZ 33#else 34#define LD_ADDEND LD 35#endif 36 37#if TARGET_LONG_BITS == 32 38#define LD_ADDR LWZU 39#define CMP_L 0 40#else 41#define LD_ADDR LDU 42#define CMP_L (1<<21) 43#endif 44 45static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { 46 "r0", 47 "r1", 48 "rp", 49 "r3", 50 "r4", 51 "r5", 52 "r6", 53 "r7", 54 "r8", 55 "r9", 56 "r10", 57 "r11", 58 "r12", 59 "r13", 60 "r14", 61 "r15", 62 "r16", 63 "r17", 64 "r18", 65 "r19", 66 "r20", 67 "r21", 68 "r22", 69 "r23", 70 "r24", 71 "r25", 72 "r26", 73 "r27", 74 "r28", 75 "r29", 76 "r30", 77 "r31" 78}; 79 80static const int tcg_target_reg_alloc_order[] = { 81 TCG_REG_R14, 82 TCG_REG_R15, 83 TCG_REG_R16, 84 TCG_REG_R17, 85 TCG_REG_R18, 86 TCG_REG_R19, 87 TCG_REG_R20, 88 TCG_REG_R21, 89 TCG_REG_R22, 90 TCG_REG_R23, 91 TCG_REG_R28, 92 TCG_REG_R29, 93 TCG_REG_R30, 94 TCG_REG_R31, 95 TCG_REG_R3, 96 TCG_REG_R4, 97 TCG_REG_R5, 98 TCG_REG_R6, 99 TCG_REG_R7, 100 TCG_REG_R8, 101 TCG_REG_R9, 102 TCG_REG_R10, 103 TCG_REG_R11, 104 TCG_REG_R12, 105 TCG_REG_R13, 106 TCG_REG_R0, 107 TCG_REG_R1, 108 TCG_REG_R2, 109 TCG_REG_R24, 110 TCG_REG_R25, 111 TCG_REG_R26, 112 TCG_REG_R27 113}; 114 115static const int tcg_target_call_iarg_regs[] = { 116 TCG_REG_R3, 117 TCG_REG_R4, 118 TCG_REG_R5, 119 TCG_REG_R6, 120 TCG_REG_R7, 121 TCG_REG_R8, 122 TCG_REG_R9, 123 TCG_REG_R10 124}; 125 126static const int tcg_target_call_oarg_regs[2] = { 127 TCG_REG_R3 128}; 129 130static const int tcg_target_callee_save_regs[] = { 131 TCG_REG_R14, 132 TCG_REG_R15, 133 TCG_REG_R16, 134 TCG_REG_R17, 135 TCG_REG_R18, 136 TCG_REG_R19, 137 TCG_REG_R20, 138 TCG_REG_R21, 139 TCG_REG_R22, 140 TCG_REG_R23, 141 TCG_REG_R28, 142 TCG_REG_R29, 143 TCG_REG_R30, 144 TCG_REG_R31 145}; 146 147static uint32_t reloc_pc24_val (void *pc, tcg_target_long target) 148{ 149 tcg_target_long disp; 150 151 disp = target - (tcg_target_long) pc; 152 if ((disp << 38) >> 38 != disp) 153 tcg_abort (); 154 155 return disp & 0x3fffffc; 156} 157 158static void reloc_pc24 (void *pc, tcg_target_long target) 159{ 160 *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3fffffc) 161 | reloc_pc24_val (pc, target); 162} 163 164static uint16_t reloc_pc14_val (void *pc, tcg_target_long target) 165{ 166 tcg_target_long disp; 167 168 disp = target - (tcg_target_long) pc; 169 if (disp != (int16_t) disp) 170 tcg_abort (); 171 172 return disp & 0xfffc; 173} 174 175static void reloc_pc14 (void *pc, tcg_target_long target) 176{ 177 *(uint32_t *) pc = (*(uint32_t *) pc & ~0xfffc) 178 | reloc_pc14_val (pc, target); 179} 180 181static void patch_reloc (uint8_t *code_ptr, int type, 182 tcg_target_long value, tcg_target_long addend) 183{ 184 value += addend; 185 switch (type) { 186 case R_PPC_REL14: 187 reloc_pc14 (code_ptr, value); 188 break; 189 case R_PPC_REL24: 190 reloc_pc24 (code_ptr, value); 191 break; 192 default: 193 tcg_abort (); 194 } 195} 196 197/* maximum number of register used for input function arguments */ 198static int tcg_target_get_call_iarg_regs_count (int flags) 199{ 200 return sizeof (tcg_target_call_iarg_regs) / sizeof (tcg_target_call_iarg_regs[0]); 201} 202 203/* parse target specific constraints */ 204static int target_parse_constraint (TCGArgConstraint *ct, const char **pct_str) 205{ 206 const char *ct_str; 207 208 ct_str = *pct_str; 209 switch (ct_str[0]) { 210 case 'A': case 'B': case 'C': case 'D': 211 ct->ct |= TCG_CT_REG; 212 tcg_regset_set_reg (ct->u.regs, 3 + ct_str[0] - 'A'); 213 break; 214 case 'r': 215 ct->ct |= TCG_CT_REG; 216 tcg_regset_set32 (ct->u.regs, 0, 0xffffffff); 217 break; 218 case 'L': /* qemu_ld constraint */ 219 ct->ct |= TCG_CT_REG; 220 tcg_regset_set32 (ct->u.regs, 0, 0xffffffff); 221 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3); 222#ifdef CONFIG_SOFTMMU 223 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4); 224#endif 225 break; 226 case 'S': /* qemu_st constraint */ 227 ct->ct |= TCG_CT_REG; 228 tcg_regset_set32 (ct->u.regs, 0, 0xffffffff); 229 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3); 230#ifdef CONFIG_SOFTMMU 231 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R4); 232 tcg_regset_reset_reg (ct->u.regs, TCG_REG_R5); 233#endif 234 break; 235 case 'Z': 236 ct->ct |= TCG_CT_CONST_U32; 237 break; 238 default: 239 return -1; 240 } 241 ct_str++; 242 *pct_str = ct_str; 243 return 0; 244} 245 246/* test if a constant matches the constraint */ 247static int tcg_target_const_match (tcg_target_long val, 248 const TCGArgConstraint *arg_ct) 249{ 250 int ct; 251 252 ct = arg_ct->ct; 253 if (ct & TCG_CT_CONST) 254 return 1; 255 else if ((ct & TCG_CT_CONST_U32) && (val == (uint32_t) val)) 256 return 1; 257 return 0; 258} 259 260#define OPCD(opc) ((opc)<<26) 261#define XO19(opc) (OPCD(19)|((opc)<<1)) 262#define XO30(opc) (OPCD(30)|((opc)<<2)) 263#define XO31(opc) (OPCD(31)|((opc)<<1)) 264#define XO58(opc) (OPCD(58)|(opc)) 265#define XO62(opc) (OPCD(62)|(opc)) 266 267#define B OPCD( 18) 268#define BC OPCD( 16) 269#define LBZ OPCD( 34) 270#define LHZ OPCD( 40) 271#define LHA OPCD( 42) 272#define LWZ OPCD( 32) 273#define STB OPCD( 38) 274#define STH OPCD( 44) 275#define STW OPCD( 36) 276 277#define STD XO62( 0) 278#define STDU XO62( 1) 279#define STDX XO31(149) 280 281#define LD XO58( 0) 282#define LDX XO31( 21) 283#define LDU XO58( 1) 284#define LWA XO58( 2) 285#define LWAX XO31(341) 286 287#define ADDI OPCD( 14) 288#define ADDIS OPCD( 15) 289#define ORI OPCD( 24) 290#define ORIS OPCD( 25) 291#define XORI OPCD( 26) 292#define XORIS OPCD( 27) 293#define ANDI OPCD( 28) 294#define ANDIS OPCD( 29) 295#define MULLI OPCD( 7) 296#define CMPLI OPCD( 10) 297#define CMPI OPCD( 11) 298 299#define LWZU OPCD( 33) 300#define STWU OPCD( 37) 301 302#define RLWINM OPCD( 21) 303 304#define RLDICL XO30( 0) 305#define RLDICR XO30( 1) 306 307#define BCLR XO19( 16) 308#define BCCTR XO19(528) 309#define CRAND XO19(257) 310#define CRANDC XO19(129) 311#define CRNAND XO19(225) 312#define CROR XO19(449) 313 314#define EXTSB XO31(954) 315#define EXTSH XO31(922) 316#define EXTSW XO31(986) 317#define ADD XO31(266) 318#define ADDE XO31(138) 319#define ADDC XO31( 10) 320#define AND XO31( 28) 321#define SUBF XO31( 40) 322#define SUBFC XO31( 8) 323#define SUBFE XO31(136) 324#define OR XO31(444) 325#define XOR XO31(316) 326#define MULLW XO31(235) 327#define MULHWU XO31( 11) 328#define DIVW XO31(491) 329#define DIVWU XO31(459) 330#define CMP XO31( 0) 331#define CMPL XO31( 32) 332#define LHBRX XO31(790) 333#define LWBRX XO31(534) 334#define STHBRX XO31(918) 335#define STWBRX XO31(662) 336#define MFSPR XO31(339) 337#define MTSPR XO31(467) 338#define SRAWI XO31(824) 339#define NEG XO31(104) 340 341#define MULLD XO31(233) 342#define MULHD XO31( 73) 343#define MULHDU XO31( 9) 344#define DIVD XO31(489) 345#define DIVDU XO31(457) 346 347#define LBZX XO31( 87) 348#define LHZX XO31(276) 349#define LHAX XO31(343) 350#define LWZX XO31( 23) 351#define STBX XO31(215) 352#define STHX XO31(407) 353#define STWX XO31(151) 354 355#define SPR(a,b) ((((a)<<5)|(b))<<11) 356#define LR SPR(8, 0) 357#define CTR SPR(9, 0) 358 359#define SLW XO31( 24) 360#define SRW XO31(536) 361#define SRAW XO31(792) 362 363#define SLD XO31( 27) 364#define SRD XO31(539) 365#define SRAD XO31(794) 366#define SRADI XO31(413<<1) 367 368#define LMW OPCD( 46) 369#define STMW OPCD( 47) 370 371#define TW XO31( 4) 372#define TRAP (TW | TO (31)) 373 374#define RT(r) ((r)<<21) 375#define RS(r) ((r)<<21) 376#define RA(r) ((r)<<16) 377#define RB(r) ((r)<<11) 378#define TO(t) ((t)<<21) 379#define SH(s) ((s)<<11) 380#define MB(b) ((b)<<6) 381#define ME(e) ((e)<<1) 382#define BO(o) ((o)<<21) 383#define MB64(b) ((b)<<5) 384 385#define LK 1 386 387#define TAB(t,a,b) (RT(t) | RA(a) | RB(b)) 388#define SAB(s,a,b) (RS(s) | RA(a) | RB(b)) 389 390#define BF(n) ((n)<<23) 391#define BI(n, c) (((c)+((n)*4))<<16) 392#define BT(n, c) (((c)+((n)*4))<<21) 393#define BA(n, c) (((c)+((n)*4))<<16) 394#define BB(n, c) (((c)+((n)*4))<<11) 395 396#define BO_COND_TRUE BO (12) 397#define BO_COND_FALSE BO ( 4) 398#define BO_ALWAYS BO (20) 399 400enum { 401 CR_LT, 402 CR_GT, 403 CR_EQ, 404 CR_SO 405}; 406 407static const uint32_t tcg_to_bc[10] = { 408 [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE, 409 [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE, 410 [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE, 411 [TCG_COND_GE] = BC | BI (7, CR_LT) | BO_COND_FALSE, 412 [TCG_COND_LE] = BC | BI (7, CR_GT) | BO_COND_FALSE, 413 [TCG_COND_GT] = BC | BI (7, CR_GT) | BO_COND_TRUE, 414 [TCG_COND_LTU] = BC | BI (7, CR_LT) | BO_COND_TRUE, 415 [TCG_COND_GEU] = BC | BI (7, CR_LT) | BO_COND_FALSE, 416 [TCG_COND_LEU] = BC | BI (7, CR_GT) | BO_COND_FALSE, 417 [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE, 418}; 419 420static void tcg_out_mov (TCGContext *s, int ret, int arg) 421{ 422 tcg_out32 (s, OR | SAB (arg, ret, arg)); 423} 424 425static void tcg_out_rld (TCGContext *s, int op, int ra, int rs, int sh, int mb) 426{ 427 sh = SH (sh & 0x1f) | (((sh >> 5) & 1) << 1); 428 mb = MB64 ((mb >> 5) | ((mb << 1) & 0x3f)); 429 tcg_out32 (s, op | RA (ra) | RS (rs) | sh | mb); 430} 431 432static void tcg_out_movi32 (TCGContext *s, int ret, int32_t arg) 433{ 434 if (arg == (int16_t) arg) 435 tcg_out32 (s, ADDI | RT (ret) | RA (0) | (arg & 0xffff)); 436 else { 437 tcg_out32 (s, ADDIS | RT (ret) | RA (0) | ((arg >> 16) & 0xffff)); 438 if (arg & 0xffff) 439 tcg_out32 (s, ORI | RS (ret) | RA (ret) | (arg & 0xffff)); 440 } 441} 442 443static void tcg_out_movi (TCGContext *s, TCGType type, 444 int ret, tcg_target_long arg) 445{ 446 int32_t arg32 = arg; 447 448 if (type == TCG_TYPE_I32 || arg == arg32) { 449 tcg_out_movi32 (s, ret, arg32); 450 } 451 else { 452 if ((uint64_t) arg >> 32) { 453 uint16_t h16 = arg >> 16; 454 uint16_t l16 = arg; 455 456 tcg_out_movi32 (s, ret, arg >> 32); 457 tcg_out_rld (s, RLDICR, ret, ret, 32, 31); 458 if (h16) tcg_out32 (s, ORIS | RS (ret) | RA (ret) | h16); 459 if (l16) tcg_out32 (s, ORI | RS (ret) | RA (ret) | l16); 460 } 461 else { 462 tcg_out_movi32 (s, ret, arg32); 463 if (arg32 < 0) 464 tcg_out_rld (s, RLDICL, ret, ret, 0, 32); 465 } 466 } 467} 468 469static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg) 470{ 471 int reg; 472 473 if (const_arg) { 474 reg = 2; 475 tcg_out_movi (s, TCG_TYPE_I64, reg, arg); 476 } 477 else reg = arg; 478 479 tcg_out32 (s, LD | RT (0) | RA (reg)); 480 tcg_out32 (s, MTSPR | RA (0) | CTR); 481 tcg_out32 (s, LD | RT (11) | RA (reg) | 16); 482 tcg_out32 (s, LD | RT (2) | RA (reg) | 8); 483 tcg_out32 (s, BCCTR | BO_ALWAYS | LK); 484} 485 486static void tcg_out_ldst (TCGContext *s, int ret, int addr, 487 int offset, int op1, int op2) 488{ 489 if (offset == (int16_t) offset) 490 tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff)); 491 else { 492 tcg_out_movi (s, TCG_TYPE_I64, 0, offset); 493 tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0)); 494 } 495} 496 497static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target) 498{ 499 tcg_target_long disp; 500 501 disp = target - (tcg_target_long) s->code_ptr; 502 if ((disp << 38) >> 38 == disp) 503 tcg_out32 (s, B | (disp & 0x3fffffc) | mask); 504 else { 505 tcg_out_movi (s, TCG_TYPE_I64, 0, (tcg_target_long) target); 506 tcg_out32 (s, MTSPR | RS (0) | CTR); 507 tcg_out32 (s, BCCTR | BO_ALWAYS | mask); 508 } 509} 510 511#if defined (CONFIG_SOFTMMU) 512 513#include "../../softmmu_defs.h" 514 515static void *qemu_ld_helpers[4] = { 516 __ldb_mmu, 517 __ldw_mmu, 518 __ldl_mmu, 519 __ldq_mmu, 520}; 521 522static void *qemu_st_helpers[4] = { 523 __stb_mmu, 524 __stw_mmu, 525 __stl_mmu, 526 __stq_mmu, 527}; 528 529static void tcg_out_tlb_read (TCGContext *s, int r0, int r1, int r2, 530 int addr_reg, int s_bits, int offset) 531{ 532#if TARGET_LONG_BITS == 32 533 tcg_out_rld (s, RLDICL, addr_reg, addr_reg, 0, 32); 534 535 tcg_out32 (s, (RLWINM 536 | RA (r0) 537 | RS (addr_reg) 538 | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS)) 539 | MB (32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS)) 540 | ME (31 - CPU_TLB_ENTRY_BITS) 541 ) 542 ); 543 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0)); 544 tcg_out32 (s, (LWZU | RT (r1) | RA (r0) | offset)); 545 tcg_out32 (s, (RLWINM 546 | RA (r2) 547 | RS (addr_reg) 548 | SH (0) 549 | MB ((32 - s_bits) & 31) 550 | ME (31 - TARGET_PAGE_BITS) 551 ) 552 ); 553#else 554 tcg_out_rld (s, RLDICL, r0, addr_reg, 555 64 - TARGET_PAGE_BITS, 556 64 - CPU_TLB_BITS); 557 tcg_out_rld (s, RLDICR, r0, r0, 558 CPU_TLB_ENTRY_BITS, 559 63 - CPU_TLB_ENTRY_BITS); 560 561 tcg_out32 (s, ADD | TAB (r0, r0, TCG_AREG0)); 562 tcg_out32 (s, LD_ADDR | RT (r1) | RA (r0) | offset); 563 564 if (!s_bits) { 565 tcg_out_rld (s, RLDICR, r2, addr_reg, 0, 63 - TARGET_PAGE_BITS); 566 } 567 else { 568 tcg_out_rld (s, RLDICL, r2, addr_reg, 569 64 - TARGET_PAGE_BITS, 570 TARGET_PAGE_BITS - s_bits); 571 tcg_out_rld (s, RLDICL, r2, r2, TARGET_PAGE_BITS, 0); 572 } 573#endif 574} 575#endif 576 577static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) 578{ 579 int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap; 580#ifdef CONFIG_SOFTMMU 581 int r2; 582 void *label1_ptr, *label2_ptr; 583#endif 584 585 data_reg = *args++; 586 addr_reg = *args++; 587 mem_index = *args; 588 s_bits = opc & 3; 589 590#ifdef CONFIG_SOFTMMU 591 r0 = 3; 592 r1 = 4; 593 r2 = 0; 594 595 tcg_out_tlb_read (s, r0, r1, r2, addr_reg, s_bits, 596 offsetof (CPUState, tlb_table[mem_index][0].addr_read)); 597 598 tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L); 599 600 label1_ptr = s->code_ptr; 601#ifdef FAST_PATH 602 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE); 603#endif 604 605 /* slow path */ 606 tcg_out_mov (s, 3, addr_reg); 607 tcg_out_movi (s, TCG_TYPE_I64, 4, mem_index); 608 609 tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1); 610 611 switch (opc) { 612 case 0|4: 613 tcg_out32 (s, EXTSB | RA (data_reg) | RS (3)); 614 break; 615 case 1|4: 616 tcg_out32 (s, EXTSH | RA (data_reg) | RS (3)); 617 break; 618 case 2|4: 619 tcg_out32 (s, EXTSW | RA (data_reg) | RS (3)); 620 break; 621 case 0: 622 case 1: 623 case 2: 624 case 3: 625 if (data_reg != 3) 626 tcg_out_mov (s, data_reg, 3); 627 break; 628 } 629 label2_ptr = s->code_ptr; 630 tcg_out32 (s, B); 631 632 /* label1: fast path */ 633#ifdef FAST_PATH 634 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr); 635#endif 636 637 /* r0 now contains &env->tlb_table[mem_index][index].addr_read */ 638 tcg_out32 (s, (LD_ADDEND 639 | RT (r0) 640 | RA (r0) 641 | (offsetof (CPUTLBEntry, addend) 642 - offsetof (CPUTLBEntry, addr_read)) 643 )); 644 /* r0 = env->tlb_table[mem_index][index].addend */ 645 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg)); 646 /* r0 = env->tlb_table[mem_index][index].addend + addr */ 647 648#else /* !CONFIG_SOFTMMU */ 649#if TARGET_LONG_BITS == 32 650 tcg_out_rld (s, RLDICL, addr_reg, addr_reg, 0, 32); 651#endif 652 r0 = addr_reg; 653 r1 = 3; 654#endif 655 656#ifdef TARGET_WORDS_BIGENDIAN 657 bswap = 0; 658#else 659 bswap = 1; 660#endif 661 switch (opc) { 662 default: 663 case 0: 664 tcg_out32 (s, LBZ | RT (data_reg) | RA (r0)); 665 break; 666 case 0|4: 667 tcg_out32 (s, LBZ | RT (data_reg) | RA (r0)); 668 tcg_out32 (s, EXTSB | RA (data_reg) | RS (data_reg)); 669 break; 670 case 1: 671 if (bswap) tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0)); 672 else tcg_out32 (s, LHZ | RT (data_reg) | RA (r0)); 673 break; 674 case 1|4: 675 if (bswap) { 676 tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0)); 677 tcg_out32 (s, EXTSH | RA (data_reg) | RS (data_reg)); 678 } 679 else tcg_out32 (s, LHA | RT (data_reg) | RA (r0)); 680 break; 681 case 2: 682 if (bswap) tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0)); 683 else tcg_out32 (s, LWZ | RT (data_reg)| RA (r0)); 684 break; 685 case 2|4: 686 if (bswap) { 687 tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0)); 688 tcg_out32 (s, EXTSW | RA (data_reg) | RS (data_reg)); 689 } 690 else tcg_out32 (s, LWA | RT (data_reg)| RA (r0)); 691 break; 692 case 3: 693 if (bswap) { 694 tcg_out32 (s, LWBRX | RT (0) | RB (r0)); 695 tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4); 696 tcg_out32 (s, LWBRX | RT (data_reg) | RB (r1)); 697 tcg_out_rld (s, RLDICR, data_reg, data_reg, 32, 31); 698 tcg_out32 (s, OR | SAB (0, data_reg, data_reg)); 699 } 700 else tcg_out32 (s, LD | RT (data_reg) | RA (r0)); 701 break; 702 } 703 704#ifdef CONFIG_SOFTMMU 705 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr); 706#endif 707} 708 709static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) 710{ 711 int addr_reg, r0, r1, data_reg, mem_index, bswap; 712#ifdef CONFIG_SOFTMMU 713 int r2; 714 void *label1_ptr, *label2_ptr; 715#endif 716 717 data_reg = *args++; 718 addr_reg = *args++; 719 mem_index = *args; 720 721#ifdef CONFIG_SOFTMMU 722 r0 = 3; 723 r1 = 4; 724 r2 = 0; 725 726 tcg_out_tlb_read (s, r0, r1, r2, addr_reg, opc, 727 offsetof (CPUState, tlb_table[mem_index][0].addr_write)); 728 729 tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1) | CMP_L); 730 731 label1_ptr = s->code_ptr; 732#ifdef FAST_PATH 733 tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE); 734#endif 735 736 /* slow path */ 737 tcg_out_mov (s, 3, addr_reg); 738 tcg_out_rld (s, RLDICL, 4, data_reg, 0, 64 - (1 << (3 + opc))); 739 tcg_out_movi (s, TCG_TYPE_I64, 5, mem_index); 740 741 tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1); 742 743 label2_ptr = s->code_ptr; 744 tcg_out32 (s, B); 745 746 /* label1: fast path */ 747#ifdef FAST_PATH 748 reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr); 749#endif 750 751 tcg_out32 (s, (LD_ADDEND 752 | RT (r0) 753 | RA (r0) 754 | (offsetof (CPUTLBEntry, addend) 755 - offsetof (CPUTLBEntry, addr_write)) 756 )); 757 /* r0 = env->tlb_table[mem_index][index].addend */ 758 tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg)); 759 /* r0 = env->tlb_table[mem_index][index].addend + addr */ 760 761#else /* !CONFIG_SOFTMMU */ 762#if TARGET_LONG_BITS == 32 763 tcg_out_rld (s, RLDICL, addr_reg, addr_reg, 0, 32); 764#endif 765 r1 = 3; 766 r0 = addr_reg; 767#endif 768 769#ifdef TARGET_WORDS_BIGENDIAN 770 bswap = 0; 771#else 772 bswap = 1; 773#endif 774 switch (opc) { 775 case 0: 776 tcg_out32 (s, STB | RS (data_reg) | RA (r0)); 777 break; 778 case 1: 779 if (bswap) tcg_out32 (s, STHBRX | RS (data_reg) | RA (0) | RB (r0)); 780 else tcg_out32 (s, STH | RS (data_reg) | RA (r0)); 781 break; 782 case 2: 783 if (bswap) tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0)); 784 else tcg_out32 (s, STW | RS (data_reg) | RA (r0)); 785 break; 786 case 3: 787 if (bswap) { 788 tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0)); 789 tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4); 790 tcg_out_rld (s, RLDICL, 0, data_reg, 32, 0); 791 tcg_out32 (s, STWBRX | RS (0) | RA (0) | RB (r1)); 792 } 793 else tcg_out32 (s, STD | RS (data_reg) | RA (r0)); 794 break; 795 } 796 797#ifdef CONFIG_SOFTMMU 798 reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr); 799#endif 800} 801 802void tcg_target_qemu_prologue (TCGContext *s) 803{ 804 int i, frame_size; 805 uint64_t addr; 806 807 frame_size = 0 808 + 8 /* back chain */ 809 + 8 /* CR */ 810 + 8 /* LR */ 811 + 8 /* compiler doubleword */ 812 + 8 /* link editor doubleword */ 813 + 8 /* TOC save area */ 814 + TCG_STATIC_CALL_ARGS_SIZE 815 + ARRAY_SIZE (tcg_target_callee_save_regs) * 8 816 ; 817 frame_size = (frame_size + 15) & ~15; 818 819 /* First emit adhoc function descriptor */ 820 addr = (uint64_t) s->code_ptr + 24; 821 tcg_out32 (s, addr >> 32); tcg_out32 (s, addr); /* entry point */ 822 s->code_ptr += 16; /* skip TOC and environment pointer */ 823 824 /* Prologue */ 825 tcg_out32 (s, MFSPR | RT (0) | LR); 826 tcg_out32 (s, STDU | RS (1) | RA (1) | (-frame_size & 0xffff)); 827 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i) 828 tcg_out32 (s, (STD 829 | RS (tcg_target_callee_save_regs[i]) 830 | RA (1) 831 | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE) 832 ) 833 ); 834 tcg_out32 (s, STD | RS (0) | RA (1) | (frame_size + 16)); 835 836 tcg_out32 (s, MTSPR | RS (3) | CTR); 837 tcg_out32 (s, BCCTR | BO_ALWAYS); 838 839 /* Epilogue */ 840 tb_ret_addr = s->code_ptr; 841 842 for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i) 843 tcg_out32 (s, (LD 844 | RT (tcg_target_callee_save_regs[i]) 845 | RA (1) 846 | (i * 8 + 48 + TCG_STATIC_CALL_ARGS_SIZE) 847 ) 848 ); 849 tcg_out32 (s, LD | RT (0) | RA (1) | (frame_size + 16)); 850 tcg_out32 (s, MTSPR | RS (0) | LR); 851 tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size); 852 tcg_out32 (s, BCLR | BO_ALWAYS); 853} 854 855static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1, 856 tcg_target_long arg2) 857{ 858 if (type == TCG_TYPE_I32) 859 tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX); 860 else 861 tcg_out_ldst (s, ret, arg1, arg2, LD, LDX); 862} 863 864static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1, 865 tcg_target_long arg2) 866{ 867 if (type == TCG_TYPE_I32) 868 tcg_out_ldst (s, arg, arg1, arg2, STW, STWX); 869 else 870 tcg_out_ldst (s, arg, arg1, arg2, STD, STDX); 871} 872 873static void ppc_addi32 (TCGContext *s, int rt, int ra, tcg_target_long si) 874{ 875 if (!si && rt == ra) 876 return; 877 878 if (si == (int16_t) si) 879 tcg_out32 (s, ADDI | RT (rt) | RA (ra) | (si & 0xffff)); 880 else { 881 uint16_t h = ((si >> 16) & 0xffff) + ((uint16_t) si >> 15); 882 tcg_out32 (s, ADDIS | RT (rt) | RA (ra) | h); 883 tcg_out32 (s, ADDI | RT (rt) | RA (rt) | (si & 0xffff)); 884 } 885} 886 887static void ppc_addi64 (TCGContext *s, int rt, int ra, tcg_target_long si) 888{ 889 /* XXX: suboptimal */ 890 if (si == (int16_t) si 891 || (((uint64_t) si >> 31) == 0) && (si & 0x8000) == 0) 892 ppc_addi32 (s, rt, ra, si); 893 else { 894 tcg_out_movi (s, TCG_TYPE_I64, 0, si); 895 tcg_out32 (s, ADD | RT (rt) | RA (ra)); 896 } 897} 898 899static void tcg_out_addi (TCGContext *s, int reg, tcg_target_long val) 900{ 901 ppc_addi64 (s, reg, reg, val); 902} 903 904static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2, 905 int const_arg2, int cr, int arch64) 906{ 907 int imm; 908 uint32_t op; 909 910 switch (cond) { 911 case TCG_COND_EQ: 912 case TCG_COND_NE: 913 if (const_arg2) { 914 if ((int16_t) arg2 == arg2) { 915 op = CMPI; 916 imm = 1; 917 break; 918 } 919 else if ((uint16_t) arg2 == arg2) { 920 op = CMPLI; 921 imm = 1; 922 break; 923 } 924 } 925 op = CMPL; 926 imm = 0; 927 break; 928 929 case TCG_COND_LT: 930 case TCG_COND_GE: 931 case TCG_COND_LE: 932 case TCG_COND_GT: 933 if (const_arg2) { 934 if ((int16_t) arg2 == arg2) { 935 op = CMPI; 936 imm = 1; 937 break; 938 } 939 } 940 op = CMP; 941 imm = 0; 942 break; 943 944 case TCG_COND_LTU: 945 case TCG_COND_GEU: 946 case TCG_COND_LEU: 947 case TCG_COND_GTU: 948 if (const_arg2) { 949 if ((uint16_t) arg2 == arg2) { 950 op = CMPLI; 951 imm = 1; 952 break; 953 } 954 } 955 op = CMPL; 956 imm = 0; 957 break; 958 959 default: 960 tcg_abort (); 961 } 962 op |= BF (cr) | (arch64 << 21); 963 964 if (imm) 965 tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff)); 966 else { 967 if (const_arg2) { 968 tcg_out_movi (s, TCG_TYPE_I64, 0, arg2); 969 tcg_out32 (s, op | RA (arg1) | RB (0)); 970 } 971 else 972 tcg_out32 (s, op | RA (arg1) | RB (arg2)); 973 } 974 975} 976 977static void tcg_out_bc (TCGContext *s, int bc, int label_index) 978{ 979 TCGLabel *l = &s->labels[label_index]; 980 981 if (l->has_value) 982 tcg_out32 (s, bc | reloc_pc14_val (s->code_ptr, l->u.value)); 983 else { 984 uint16_t val = *(uint16_t *) &s->code_ptr[2]; 985 986 /* Thanks to Andrzej Zaborowski */ 987 tcg_out32 (s, bc | (val & 0xfffc)); 988 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0); 989 } 990} 991 992static void tcg_out_brcond (TCGContext *s, int cond, 993 TCGArg arg1, TCGArg arg2, int const_arg2, 994 int label_index, int arch64) 995{ 996 tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7, arch64); 997 tcg_out_bc (s, tcg_to_bc[cond], label_index); 998} 999 1000void ppc_tb_set_jmp_target (unsigned long jmp_addr, unsigned long addr) 1001{ 1002 TCGContext s; 1003 unsigned long patch_size; 1004 1005 s.code_ptr = (uint8_t *) jmp_addr; 1006 tcg_out_b (&s, 0, addr); 1007 patch_size = s.code_ptr - (uint8_t *) jmp_addr; 1008 flush_icache_range (jmp_addr, jmp_addr + patch_size); 1009} 1010 1011static void tcg_out_op (TCGContext *s, int opc, const TCGArg *args, 1012 const int *const_args) 1013{ 1014 int c; 1015 1016 switch (opc) { 1017 case INDEX_op_exit_tb: 1018 tcg_out_movi (s, TCG_TYPE_I64, TCG_REG_R3, args[0]); 1019 tcg_out_b (s, 0, (tcg_target_long) tb_ret_addr); 1020 break; 1021 case INDEX_op_goto_tb: 1022 if (s->tb_jmp_offset) { 1023 /* direct jump method */ 1024 1025 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; 1026 s->code_ptr += 28; 1027 } 1028 else { 1029 tcg_abort (); 1030 } 1031 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; 1032 break; 1033 case INDEX_op_br: 1034 { 1035 TCGLabel *l = &s->labels[args[0]]; 1036 1037 if (l->has_value) { 1038 tcg_out_b (s, 0, l->u.value); 1039 } 1040 else { 1041 uint32_t val = *(uint32_t *) s->code_ptr; 1042 1043 /* Thanks to Andrzej Zaborowski */ 1044 tcg_out32 (s, B | (val & 0x3fffffc)); 1045 tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0); 1046 } 1047 } 1048 break; 1049 case INDEX_op_call: 1050 tcg_out_call (s, args[0], const_args[0]); 1051 break; 1052 case INDEX_op_jmp: 1053 if (const_args[0]) { 1054 tcg_out_b (s, 0, args[0]); 1055 } 1056 else { 1057 tcg_out32 (s, MTSPR | RS (args[0]) | CTR); 1058 tcg_out32 (s, BCCTR | BO_ALWAYS); 1059 } 1060 break; 1061 case INDEX_op_movi_i32: 1062 tcg_out_movi (s, TCG_TYPE_I32, args[0], args[1]); 1063 break; 1064 case INDEX_op_movi_i64: 1065 tcg_out_movi (s, TCG_TYPE_I64, args[0], args[1]); 1066 break; 1067 case INDEX_op_ld8u_i32: 1068 case INDEX_op_ld8u_i64: 1069 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX); 1070 break; 1071 case INDEX_op_ld8s_i32: 1072 case INDEX_op_ld8s_i64: 1073 tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX); 1074 tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0])); 1075 break; 1076 case INDEX_op_ld16u_i32: 1077 case INDEX_op_ld16u_i64: 1078 tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX); 1079 break; 1080 case INDEX_op_ld16s_i32: 1081 case INDEX_op_ld16s_i64: 1082 tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX); 1083 break; 1084 case INDEX_op_ld_i32: 1085 case INDEX_op_ld32u_i64: 1086 tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX); 1087 break; 1088 case INDEX_op_ld32s_i64: 1089 tcg_out_ldst (s, args[0], args[1], args[2], LWA, LWAX); 1090 break; 1091 case INDEX_op_ld_i64: 1092 tcg_out_ldst (s, args[0], args[1], args[2], LD, LDX); 1093 break; 1094 case INDEX_op_st8_i32: 1095 case INDEX_op_st8_i64: 1096 tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX); 1097 break; 1098 case INDEX_op_st16_i32: 1099 case INDEX_op_st16_i64: 1100 tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX); 1101 break; 1102 case INDEX_op_st_i32: 1103 case INDEX_op_st32_i64: 1104 tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX); 1105 break; 1106 case INDEX_op_st_i64: 1107 tcg_out_ldst (s, args[0], args[1], args[2], STD, STDX); 1108 break; 1109 1110 case INDEX_op_add_i32: 1111 if (const_args[2]) 1112 ppc_addi32 (s, args[0], args[1], args[2]); 1113 else 1114 tcg_out32 (s, ADD | TAB (args[0], args[1], args[2])); 1115 break; 1116 case INDEX_op_sub_i32: 1117 if (const_args[2]) 1118 ppc_addi32 (s, args[0], args[1], -args[2]); 1119 else 1120 tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1])); 1121 break; 1122 1123 case INDEX_op_and_i64: 1124 case INDEX_op_and_i32: 1125 if (const_args[2]) { 1126 if ((args[2] & 0xffff) == args[2]) 1127 tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | args[2]); 1128 else if ((args[2] & 0xffff0000) == args[2]) 1129 tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0]) 1130 | ((args[2] >> 16) & 0xffff)); 1131 else { 1132 tcg_out_movi (s, (opc == INDEX_op_and_i32 1133 ? TCG_TYPE_I32 1134 : TCG_TYPE_I64), 1135 0, args[2]); 1136 tcg_out32 (s, AND | SAB (args[1], args[0], 0)); 1137 } 1138 } 1139 else 1140 tcg_out32 (s, AND | SAB (args[1], args[0], args[2])); 1141 break; 1142 case INDEX_op_or_i64: 1143 case INDEX_op_or_i32: 1144 if (const_args[2]) { 1145 if (args[2] & 0xffff) { 1146 tcg_out32 (s, ORI | RS (args[1]) | RA (args[0]) 1147 | (args[2] & 0xffff)); 1148 if (args[2] >> 16) 1149 tcg_out32 (s, ORIS | RS (args[0]) | RA (args[0]) 1150 | ((args[2] >> 16) & 0xffff)); 1151 } 1152 else { 1153 tcg_out32 (s, ORIS | RS (args[1]) | RA (args[0]) 1154 | ((args[2] >> 16) & 0xffff)); 1155 } 1156 } 1157 else 1158 tcg_out32 (s, OR | SAB (args[1], args[0], args[2])); 1159 break; 1160 case INDEX_op_xor_i64: 1161 case INDEX_op_xor_i32: 1162 if (const_args[2]) { 1163 if ((args[2] & 0xffff) == args[2]) 1164 tcg_out32 (s, XORI | RS (args[1]) | RA (args[0]) 1165 | (args[2] & 0xffff)); 1166 else if ((args[2] & 0xffff0000) == args[2]) 1167 tcg_out32 (s, XORIS | RS (args[1]) | RA (args[0]) 1168 | ((args[2] >> 16) & 0xffff)); 1169 else { 1170 tcg_out_movi (s, (opc == INDEX_op_and_i32 1171 ? TCG_TYPE_I32 1172 : TCG_TYPE_I64), 1173 0, args[2]); 1174 tcg_out32 (s, XOR | SAB (args[1], args[0], 0)); 1175 } 1176 } 1177 else 1178 tcg_out32 (s, XOR | SAB (args[1], args[0], args[2])); 1179 break; 1180 1181 case INDEX_op_mul_i32: 1182 if (const_args[2]) { 1183 if (args[2] == (int16_t) args[2]) 1184 tcg_out32 (s, MULLI | RT (args[0]) | RA (args[1]) 1185 | (args[2] & 0xffff)); 1186 else { 1187 tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]); 1188 tcg_out32 (s, MULLW | TAB (args[0], args[1], 0)); 1189 } 1190 } 1191 else 1192 tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2])); 1193 break; 1194 1195 case INDEX_op_div_i32: 1196 tcg_out32 (s, DIVW | TAB (args[0], args[1], args[2])); 1197 break; 1198 1199 case INDEX_op_divu_i32: 1200 tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2])); 1201 break; 1202 1203 case INDEX_op_rem_i32: 1204 tcg_out32 (s, DIVW | TAB (0, args[1], args[2])); 1205 tcg_out32 (s, MULLW | TAB (0, 0, args[2])); 1206 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); 1207 break; 1208 1209 case INDEX_op_remu_i32: 1210 tcg_out32 (s, DIVWU | TAB (0, args[1], args[2])); 1211 tcg_out32 (s, MULLW | TAB (0, 0, args[2])); 1212 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); 1213 break; 1214 1215 case INDEX_op_shl_i32: 1216 if (const_args[2]) { 1217 tcg_out32 (s, (RLWINM 1218 | RA (args[0]) 1219 | RS (args[1]) 1220 | SH (args[2]) 1221 | MB (0) 1222 | ME (31 - args[2]) 1223 ) 1224 ); 1225 } 1226 else 1227 tcg_out32 (s, SLW | SAB (args[1], args[0], args[2])); 1228 break; 1229 case INDEX_op_shr_i32: 1230 if (const_args[2]) { 1231 tcg_out32 (s, (RLWINM 1232 | RA (args[0]) 1233 | RS (args[1]) 1234 | SH (32 - args[2]) 1235 | MB (args[2]) 1236 | ME (31) 1237 ) 1238 ); 1239 } 1240 else 1241 tcg_out32 (s, SRW | SAB (args[1], args[0], args[2])); 1242 break; 1243 case INDEX_op_sar_i32: 1244 if (const_args[2]) 1245 tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2])); 1246 else 1247 tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2])); 1248 break; 1249 1250 case INDEX_op_brcond_i32: 1251 tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3], 0); 1252 break; 1253 1254 case INDEX_op_brcond_i64: 1255 tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3], 1); 1256 break; 1257 1258 case INDEX_op_neg_i32: 1259 case INDEX_op_neg_i64: 1260 tcg_out32 (s, NEG | RT (args[0]) | RA (args[1])); 1261 break; 1262 1263 case INDEX_op_add_i64: 1264 if (const_args[2]) 1265 ppc_addi64 (s, args[0], args[1], args[2]); 1266 else 1267 tcg_out32 (s, ADD | TAB (args[0], args[1], args[2])); 1268 break; 1269 case INDEX_op_sub_i64: 1270 if (const_args[2]) 1271 ppc_addi64 (s, args[0], args[1], -args[2]); 1272 else 1273 tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1])); 1274 break; 1275 1276 case INDEX_op_shl_i64: 1277 if (const_args[2]) 1278 tcg_out_rld (s, RLDICR, args[0], args[1], args[2], 63 - args[2]); 1279 else 1280 tcg_out32 (s, SLD | SAB (args[1], args[0], args[2])); 1281 break; 1282 case INDEX_op_shr_i64: 1283 if (const_args[2]) 1284 tcg_out_rld (s, RLDICL, args[0], args[1], 64 - args[2], args[2]); 1285 else 1286 tcg_out32 (s, SRD | SAB (args[1], args[0], args[2])); 1287 break; 1288 case INDEX_op_sar_i64: 1289 if (const_args[2]) { 1290 int sh = SH (args[2] & 0x1f) | (((args[2] >> 5) & 1) << 1); 1291 tcg_out32 (s, SRADI | RA (args[0]) | RS (args[1]) | sh); 1292 } 1293 else 1294 tcg_out32 (s, SRAD | SAB (args[1], args[0], args[2])); 1295 break; 1296 1297 case INDEX_op_mul_i64: 1298 tcg_out32 (s, MULLD | TAB (args[0], args[1], args[2])); 1299 break; 1300 case INDEX_op_div_i64: 1301 tcg_out32 (s, DIVD | TAB (args[0], args[1], args[2])); 1302 break; 1303 case INDEX_op_divu_i64: 1304 tcg_out32 (s, DIVDU | TAB (args[0], args[1], args[2])); 1305 break; 1306 case INDEX_op_rem_i64: 1307 tcg_out32 (s, DIVD | TAB (0, args[1], args[2])); 1308 tcg_out32 (s, MULLD | TAB (0, 0, args[2])); 1309 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); 1310 break; 1311 case INDEX_op_remu_i64: 1312 tcg_out32 (s, DIVDU | TAB (0, args[1], args[2])); 1313 tcg_out32 (s, MULLD | TAB (0, 0, args[2])); 1314 tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); 1315 break; 1316 1317 case INDEX_op_qemu_ld8u: 1318 tcg_out_qemu_ld (s, args, 0); 1319 break; 1320 case INDEX_op_qemu_ld8s: 1321 tcg_out_qemu_ld (s, args, 0 | 4); 1322 break; 1323 case INDEX_op_qemu_ld16u: 1324 tcg_out_qemu_ld (s, args, 1); 1325 break; 1326 case INDEX_op_qemu_ld16s: 1327 tcg_out_qemu_ld (s, args, 1 | 4); 1328 break; 1329 case INDEX_op_qemu_ld32u: 1330 tcg_out_qemu_ld (s, args, 2); 1331 break; 1332 case INDEX_op_qemu_ld32s: 1333 tcg_out_qemu_ld (s, args, 2 | 4); 1334 break; 1335 case INDEX_op_qemu_ld64: 1336 tcg_out_qemu_ld (s, args, 3); 1337 break; 1338 case INDEX_op_qemu_st8: 1339 tcg_out_qemu_st (s, args, 0); 1340 break; 1341 case INDEX_op_qemu_st16: 1342 tcg_out_qemu_st (s, args, 1); 1343 break; 1344 case INDEX_op_qemu_st32: 1345 tcg_out_qemu_st (s, args, 2); 1346 break; 1347 case INDEX_op_qemu_st64: 1348 tcg_out_qemu_st (s, args, 3); 1349 break; 1350 1351 case INDEX_op_ext8s_i32: 1352 case INDEX_op_ext8s_i64: 1353 c = EXTSB; 1354 goto gen_ext; 1355 case INDEX_op_ext16s_i32: 1356 case INDEX_op_ext16s_i64: 1357 c = EXTSH; 1358 goto gen_ext; 1359 case INDEX_op_ext32s_i64: 1360 c = EXTSW; 1361 goto gen_ext; 1362 gen_ext: 1363 tcg_out32 (s, c | RS (args[1]) | RA (args[0])); 1364 break; 1365 1366 default: 1367 tcg_dump_ops (s, stderr); 1368 tcg_abort (); 1369 } 1370} 1371 1372static const TCGTargetOpDef ppc_op_defs[] = { 1373 { INDEX_op_exit_tb, { } }, 1374 { INDEX_op_goto_tb, { } }, 1375 { INDEX_op_call, { "ri" } }, 1376 { INDEX_op_jmp, { "ri" } }, 1377 { INDEX_op_br, { } }, 1378 1379 { INDEX_op_mov_i32, { "r", "r" } }, 1380 { INDEX_op_mov_i64, { "r", "r" } }, 1381 { INDEX_op_movi_i32, { "r" } }, 1382 { INDEX_op_movi_i64, { "r" } }, 1383 1384 { INDEX_op_ld8u_i32, { "r", "r" } }, 1385 { INDEX_op_ld8s_i32, { "r", "r" } }, 1386 { INDEX_op_ld16u_i32, { "r", "r" } }, 1387 { INDEX_op_ld16s_i32, { "r", "r" } }, 1388 { INDEX_op_ld_i32, { "r", "r" } }, 1389 { INDEX_op_ld_i64, { "r", "r" } }, 1390 { INDEX_op_st8_i32, { "r", "r" } }, 1391 { INDEX_op_st8_i64, { "r", "r" } }, 1392 { INDEX_op_st16_i32, { "r", "r" } }, 1393 { INDEX_op_st16_i64, { "r", "r" } }, 1394 { INDEX_op_st_i32, { "r", "r" } }, 1395 { INDEX_op_st_i64, { "r", "r" } }, 1396 { INDEX_op_st32_i64, { "r", "r" } }, 1397 1398 { INDEX_op_ld8u_i64, { "r", "r" } }, 1399 { INDEX_op_ld8s_i64, { "r", "r" } }, 1400 { INDEX_op_ld16u_i64, { "r", "r" } }, 1401 { INDEX_op_ld16s_i64, { "r", "r" } }, 1402 { INDEX_op_ld32u_i64, { "r", "r" } }, 1403 { INDEX_op_ld32s_i64, { "r", "r" } }, 1404 { INDEX_op_ld_i64, { "r", "r" } }, 1405 1406 { INDEX_op_add_i32, { "r", "r", "ri" } }, 1407 { INDEX_op_mul_i32, { "r", "r", "ri" } }, 1408 { INDEX_op_div_i32, { "r", "r", "r" } }, 1409 { INDEX_op_divu_i32, { "r", "r", "r" } }, 1410 { INDEX_op_rem_i32, { "r", "r", "r" } }, 1411 { INDEX_op_remu_i32, { "r", "r", "r" } }, 1412 { INDEX_op_sub_i32, { "r", "r", "ri" } }, 1413 { INDEX_op_and_i32, { "r", "r", "ri" } }, 1414 { INDEX_op_or_i32, { "r", "r", "ri" } }, 1415 { INDEX_op_xor_i32, { "r", "r", "ri" } }, 1416 1417 { INDEX_op_shl_i32, { "r", "r", "ri" } }, 1418 { INDEX_op_shr_i32, { "r", "r", "ri" } }, 1419 { INDEX_op_sar_i32, { "r", "r", "ri" } }, 1420 1421 { INDEX_op_brcond_i32, { "r", "ri" } }, 1422 { INDEX_op_brcond_i64, { "r", "ri" } }, 1423 1424 { INDEX_op_neg_i32, { "r", "r" } }, 1425 1426 { INDEX_op_add_i64, { "r", "r", "ri" } }, 1427 { INDEX_op_sub_i64, { "r", "r", "ri" } }, 1428 { INDEX_op_and_i64, { "r", "r", "rZ" } }, 1429 { INDEX_op_or_i64, { "r", "r", "rZ" } }, 1430 { INDEX_op_xor_i64, { "r", "r", "rZ" } }, 1431 1432 { INDEX_op_shl_i64, { "r", "r", "ri" } }, 1433 { INDEX_op_shr_i64, { "r", "r", "ri" } }, 1434 { INDEX_op_sar_i64, { "r", "r", "ri" } }, 1435 1436 { INDEX_op_mul_i64, { "r", "r", "r" } }, 1437 { INDEX_op_div_i64, { "r", "r", "r" } }, 1438 { INDEX_op_divu_i64, { "r", "r", "r" } }, 1439 { INDEX_op_rem_i64, { "r", "r", "r" } }, 1440 { INDEX_op_remu_i64, { "r", "r", "r" } }, 1441 1442 { INDEX_op_neg_i64, { "r", "r" } }, 1443 1444 { INDEX_op_qemu_ld8u, { "r", "L" } }, 1445 { INDEX_op_qemu_ld8s, { "r", "L" } }, 1446 { INDEX_op_qemu_ld16u, { "r", "L" } }, 1447 { INDEX_op_qemu_ld16s, { "r", "L" } }, 1448 { INDEX_op_qemu_ld32u, { "r", "L" } }, 1449 { INDEX_op_qemu_ld32s, { "r", "L" } }, 1450 { INDEX_op_qemu_ld64, { "r", "L" } }, 1451 1452 { INDEX_op_qemu_st8, { "S", "S" } }, 1453 { INDEX_op_qemu_st16, { "S", "S" } }, 1454 { INDEX_op_qemu_st32, { "S", "S" } }, 1455 { INDEX_op_qemu_st64, { "S", "S", "S" } }, 1456 1457 { INDEX_op_ext8s_i32, { "r", "r" } }, 1458 { INDEX_op_ext16s_i32, { "r", "r" } }, 1459 { INDEX_op_ext8s_i64, { "r", "r" } }, 1460 { INDEX_op_ext16s_i64, { "r", "r" } }, 1461 { INDEX_op_ext32s_i64, { "r", "r" } }, 1462 1463 { -1 }, 1464}; 1465 1466void tcg_target_init (TCGContext *s) 1467{ 1468 tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff); 1469 tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff); 1470 tcg_regset_set32 (tcg_target_call_clobber_regs, 0, 1471 (1 << TCG_REG_R0) | 1472 (1 << TCG_REG_R3) | 1473 (1 << TCG_REG_R4) | 1474 (1 << TCG_REG_R5) | 1475 (1 << TCG_REG_R6) | 1476 (1 << TCG_REG_R7) | 1477 (1 << TCG_REG_R8) | 1478 (1 << TCG_REG_R9) | 1479 (1 << TCG_REG_R10) | 1480 (1 << TCG_REG_R11) | 1481 (1 << TCG_REG_R12) 1482 ); 1483 1484 tcg_regset_clear (s->reserved_regs); 1485 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R0); 1486 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R1); 1487 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R2); 1488 tcg_regset_set_reg (s->reserved_regs, TCG_REG_R13); 1489 1490 tcg_add_target_add_op_defs (ppc_op_defs); 1491} 1492