Commit 2662e13f683c5a315edb81e5418d41fd9536aef6

Authored by bellard
1 parent 560f92cc

ppc TCG target (malc)

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4584 c046a42c-6fe2-441c-8c8c-71466251a162
tcg/ppc/tcg-target.c 0 → 100644
  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 +static uint8_t *tb_ret_addr;
  26 +
  27 +#define TCG_CT_PC14 0x100
  28 +#define TCG_CT_PC24 0x200
  29 +
  30 +#define FAST_PATH
  31 +#if TARGET_PHYS_ADDR_BITS <= 32
  32 +#define ADDEND_OFFSET 0
  33 +#else
  34 +#define ADDEND_OFFSET 4
  35 +#endif
  36 +
  37 +static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
  38 + "r0",
  39 + "r1",
  40 + "rp",
  41 + "r3",
  42 + "r4",
  43 + "r5",
  44 + "r6",
  45 + "r7",
  46 + "r8",
  47 + "r9",
  48 + "r10",
  49 + "r11",
  50 + "r12",
  51 + "r13",
  52 + "r14",
  53 + "r15",
  54 + "r16",
  55 + "r17",
  56 + "r18",
  57 + "r19",
  58 + "r20",
  59 + "r21",
  60 + "r22",
  61 + "r23",
  62 + "r24",
  63 + "r25",
  64 + "r26",
  65 + "r27",
  66 + "r28",
  67 + "r29",
  68 + "r30",
  69 + "r31"
  70 +};
  71 +
  72 +static const int tcg_target_reg_alloc_order[] = {
  73 + TCG_REG_R0,
  74 + TCG_REG_R1,
  75 + TCG_REG_R2,
  76 + TCG_REG_R3,
  77 + TCG_REG_R4,
  78 + TCG_REG_R5,
  79 + TCG_REG_R6,
  80 + TCG_REG_R7,
  81 + TCG_REG_R8,
  82 + TCG_REG_R9,
  83 + TCG_REG_R10,
  84 + TCG_REG_R11,
  85 + TCG_REG_R12,
  86 + TCG_REG_R13,
  87 + TCG_REG_R14,
  88 + TCG_REG_R15,
  89 + TCG_REG_R16,
  90 + TCG_REG_R17,
  91 + TCG_REG_R18,
  92 + TCG_REG_R19,
  93 + TCG_REG_R20,
  94 + TCG_REG_R21,
  95 + TCG_REG_R22,
  96 + TCG_REG_R23,
  97 + TCG_REG_R24,
  98 + TCG_REG_R25,
  99 + TCG_REG_R26,
  100 + TCG_REG_R27,
  101 + TCG_REG_R28,
  102 + TCG_REG_R29,
  103 + TCG_REG_R30,
  104 + TCG_REG_R31
  105 +};
  106 +
  107 +static const int tcg_target_call_iarg_regs[] = {
  108 + TCG_REG_R3,
  109 + TCG_REG_R4,
  110 + TCG_REG_R5,
  111 + TCG_REG_R6,
  112 + TCG_REG_R7,
  113 + TCG_REG_R8,
  114 + TCG_REG_R9,
  115 + TCG_REG_R10
  116 +};
  117 +
  118 +static const int tcg_target_call_oarg_regs[2] = {
  119 + TCG_REG_R3,
  120 + TCG_REG_R4
  121 +};
  122 +
  123 +static const int tcg_target_callee_save_regs[] = {
  124 + TCG_REG_R13, /* sould r13 be saved? */
  125 + TCG_REG_R14,
  126 + TCG_REG_R15,
  127 + TCG_REG_R16,
  128 + TCG_REG_R17,
  129 + TCG_REG_R18,
  130 + TCG_REG_R19,
  131 + TCG_REG_R20,
  132 + TCG_REG_R21,
  133 + TCG_REG_R22,
  134 + TCG_REG_R23,
  135 + TCG_REG_R28,
  136 + TCG_REG_R29,
  137 + TCG_REG_R30,
  138 + TCG_REG_R31
  139 +};
  140 +
  141 +static uint32_t reloc_pc24_val (void *pc, tcg_target_long target)
  142 +{
  143 + return (target - (tcg_target_long) pc) & 0x3fffffc;
  144 +}
  145 +
  146 +static void reloc_pc24 (void *pc, tcg_target_long target)
  147 +{
  148 + *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3fffffc)
  149 + | reloc_pc24_val (pc, target);
  150 +}
  151 +
  152 +static uint16_t reloc_pc14_val (void *pc, tcg_target_long target)
  153 +{
  154 + return (target - (tcg_target_long) pc) & 0xfffc;
  155 +}
  156 +
  157 +static void reloc_pc14 (void *pc, tcg_target_long target)
  158 +{
  159 + *(uint32_t *) pc = (*(uint32_t *) pc & ~0xfffc)
  160 + | reloc_pc14_val (pc, target);
  161 +}
  162 +
  163 +static void patch_reloc(uint8_t *code_ptr, int type,
  164 + tcg_target_long value, tcg_target_long addend)
  165 +{
  166 + value += addend;
  167 + switch (type) {
  168 + case R_PPC_REL14:
  169 + reloc_pc14 (code_ptr, value);
  170 + break;
  171 + case R_PPC_REL24:
  172 + reloc_pc24 (code_ptr, value);
  173 + break;
  174 + default:
  175 + tcg_abort();
  176 + }
  177 +}
  178 +
  179 +/* maximum number of register used for input function arguments */
  180 +static int tcg_target_get_call_iarg_regs_count(int flags)
  181 +{
  182 + return sizeof (tcg_target_call_iarg_regs) / sizeof (tcg_target_call_iarg_regs[0]);
  183 +}
  184 +
  185 +/* parse target specific constraints */
  186 +static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
  187 +{
  188 + const char *ct_str;
  189 +
  190 + ct_str = *pct_str;
  191 + switch (ct_str[0]) {
  192 + case 'r':
  193 + ct->ct |= TCG_CT_REG;
  194 + tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
  195 + break;
  196 + case 'L': /* qemu_ld constraint */
  197 + ct->ct |= TCG_CT_REG;
  198 + tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
  199 + tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
  200 + tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
  201 + break;
  202 + case 'K': /* qemu_st[8..32] constraint */
  203 + ct->ct |= TCG_CT_REG;
  204 + tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
  205 + tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
  206 + tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
  207 + tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
  208 +#if TARGET_LONG_BITS == 64
  209 + tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
  210 +#endif
  211 + break;
  212 + case 'M': /* qemu_st64 constraint */
  213 + ct->ct |= TCG_CT_REG;
  214 + tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
  215 + tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
  216 + tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
  217 + tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
  218 + tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
  219 + tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7);
  220 + break;
  221 + case 'J': /* 24 bit displacement */
  222 + ct->ct |= TCG_CT_PC24;
  223 + break;
  224 + case 'j': /* 16 bit displacement */
  225 + ct->ct |= TCG_CT_PC14;
  226 + break;
  227 + default:
  228 + return -1;
  229 + }
  230 + ct_str++;
  231 + *pct_str = ct_str;
  232 + return 0;
  233 +}
  234 +
  235 +/* test if a constant matches the constraint */
  236 +static int tcg_target_const_match(tcg_target_long val,
  237 + const TCGArgConstraint *arg_ct)
  238 +{
  239 + int ct;
  240 +
  241 + ct = arg_ct->ct;
  242 + if (ct & TCG_CT_CONST)
  243 + return 1;
  244 + else if (ct & TCG_CT_PC14) {
  245 + return val == (int16_t) val;
  246 + }
  247 + else if (ct & TCG_CT_PC24) {
  248 + if (val < 0) return val > -0x800000;
  249 + return val < 0x7fffff;
  250 + }
  251 + return 0;
  252 +}
  253 +
  254 +#define OPCD(opc) ((opc)<<26)
  255 +#define XO31(opc) (OPCD(31)|((opc)<<1))
  256 +#define XO19(opc) (OPCD(19)|((opc)<<1))
  257 +
  258 +#define B OPCD(18)
  259 +#define BC OPCD(16)
  260 +#define LBZ OPCD(34)
  261 +#define LHZ OPCD(40)
  262 +#define LHA OPCD(42)
  263 +#define LWZ OPCD(32)
  264 +#define STB OPCD(38)
  265 +#define STH OPCD(44)
  266 +#define STW OPCD(36)
  267 +
  268 +#define ADDI OPCD(14)
  269 +#define ADDIS OPCD(15)
  270 +#define ORI OPCD(24)
  271 +#define ORIS OPCD(25)
  272 +#define XORI OPCD(26)
  273 +#define XORIS OPCD(27)
  274 +#define ANDI OPCD(28)
  275 +#define ANDIS OPCD(29)
  276 +#define MULLI OPCD( 7)
  277 +#define CMPLI OPCD(10)
  278 +#define CMPI OPCD(11)
  279 +
  280 +#define LWZU OPCD(33)
  281 +#define STWU OPCD(37)
  282 +
  283 +#define RLWINM OPCD(21)
  284 +
  285 +#define BCLR XO19(16)
  286 +#define BCCTR XO19(528)
  287 +#define CRAND XO19(257)
  288 +
  289 +#define EXTSB XO31(954)
  290 +#define EXTSH XO31(922)
  291 +#define ADD XO31(266)
  292 +#define ADDE XO31(138)
  293 +#define ADDC XO31( 10)
  294 +#define AND XO31( 28)
  295 +#define SUBF XO31( 40)
  296 +#define SUBFC XO31( 8)
  297 +#define SUBFE XO31(136)
  298 +#define OR XO31(444)
  299 +#define XOR XO31(316)
  300 +#define MULLW XO31(235)
  301 +#define MULHWU XO31( 11)
  302 +#define DIVW XO31(491)
  303 +#define DIVWU XO31(459)
  304 +#define CMP XO31( 0)
  305 +#define CMPL XO31( 32)
  306 +#define LHBRX XO31(790)
  307 +#define LWBRX XO31(534)
  308 +#define STHBRX XO31(918)
  309 +#define STWBRX XO31(662)
  310 +#define MFSPR XO31(339)
  311 +#define MTSPR XO31(467)
  312 +#define SRAWI XO31(824)
  313 +#define NEG XO31(104)
  314 +
  315 +#define LBZX XO31( 87)
  316 +#define LHZX XO31(276)
  317 +#define LHAX XO31(343)
  318 +#define LWZX XO31( 23)
  319 +#define STBX XO31(215)
  320 +#define STHX XO31(407)
  321 +#define STWX XO31(151)
  322 +
  323 +#define SPR(a,b) ((((a)<<5)|(b))<<11)
  324 +#define LR SPR(8, 0)
  325 +#define CTR SPR(9, 0)
  326 +
  327 +#define SLW XO31( 24)
  328 +#define SRW XO31(536)
  329 +#define SRAW XO31(792)
  330 +
  331 +#define LMW OPCD(46)
  332 +#define STMW OPCD(47)
  333 +
  334 +#define TW XO31(4)
  335 +#define TRAP (TW | TO (31))
  336 +
  337 +#define RT(r) ((r)<<21)
  338 +#define RS(r) ((r)<<21)
  339 +#define RA(r) ((r)<<16)
  340 +#define RB(r) ((r)<<11)
  341 +#define TO(t) ((t)<<21)
  342 +#define SH(s) ((s)<<11)
  343 +#define MB(b) ((b)<<6)
  344 +#define ME(e) ((e)<<1)
  345 +#define BO(o) ((o)<<21)
  346 +
  347 +#define LK 1
  348 +
  349 +#define TAB(t,a,b) (RT(t) | RA(a) | RB(b))
  350 +#define SAB(s,a,b) (RS(s) | RA(a) | RB(b))
  351 +
  352 +#define BF(n) ((n)<<23)
  353 +#define BI(n, c) (((c)+((n)*4))<<16)
  354 +#define BT(n, c) (((c)+((n)*4))<<21)
  355 +#define BA(n, c) (((c)+((n)*4))<<16)
  356 +#define BB(n, c) (((c)+((n)*4))<<11)
  357 +
  358 +#define BO_COND_TRUE BO (12)
  359 +#define BO_COND_FALSE BO (4)
  360 +#define BO_ALWAYS BO (20)
  361 +
  362 +enum {
  363 + CR_LT,
  364 + CR_GT,
  365 + CR_EQ,
  366 + CR_SO
  367 +};
  368 +
  369 +static const uint32_t tcg_to_bc[10] = {
  370 + [TCG_COND_EQ] = BC | BI (7, CR_EQ) | BO_COND_TRUE,
  371 + [TCG_COND_NE] = BC | BI (7, CR_EQ) | BO_COND_FALSE,
  372 + [TCG_COND_LT] = BC | BI (7, CR_LT) | BO_COND_TRUE,
  373 + [TCG_COND_GE] = BC | BI (7, CR_LT) | BO_COND_FALSE,
  374 + [TCG_COND_LE] = BC | BI (7, CR_GT) | BO_COND_FALSE,
  375 + [TCG_COND_GT] = BC | BI (7, CR_GT) | BO_COND_TRUE,
  376 + [TCG_COND_LTU] = BC | BI (7, CR_LT) | BO_COND_TRUE,
  377 + [TCG_COND_GEU] = BC | BI (7, CR_LT) | BO_COND_FALSE,
  378 + [TCG_COND_LEU] = BC | BI (7, CR_GT) | BO_COND_FALSE,
  379 + [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
  380 +};
  381 +
  382 +static void tcg_out_mov(TCGContext *s, int ret, int arg)
  383 +{
  384 + tcg_out32 (s, OR | SAB (arg, ret, arg));
  385 +}
  386 +
  387 +static void tcg_out_movi(TCGContext *s, TCGType type,
  388 + int ret, tcg_target_long arg)
  389 +{
  390 + if (arg == (int16_t) arg)
  391 + tcg_out32 (s, ADDI | RT (ret) | RA (0) | (arg & 0xffff));
  392 + else {
  393 + tcg_out32 (s, ADDIS | RT (ret) | RA (0) | ((arg >> 16) & 0xffff));
  394 + if (arg & 0xffff)
  395 + tcg_out32 (s, ORI | RT (ret) | RA (ret) | (arg & 0xffff));
  396 + }
  397 +}
  398 +
  399 +static void tcg_out_ldst (TCGContext *s, int ret, int addr,
  400 + int offset, int op1, int op2)
  401 +{
  402 + if (offset == (int16_t) offset)
  403 + tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff));
  404 + else {
  405 + tcg_out_movi (s, TCG_TYPE_I32, 0, offset);
  406 + tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0));
  407 + }
  408 +}
  409 +
  410 +#if defined(CONFIG_SOFTMMU)
  411 +extern void __ldb_mmu(void);
  412 +extern void __ldw_mmu(void);
  413 +extern void __ldl_mmu(void);
  414 +extern void __ldq_mmu(void);
  415 +
  416 +extern void __stb_mmu(void);
  417 +extern void __stw_mmu(void);
  418 +extern void __stl_mmu(void);
  419 +extern void __stq_mmu(void);
  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, int opc)
  437 +{
  438 + int addr_reg, data_reg, data_reg2, r0, mem_index, s_bits, bswap;
  439 +#ifdef CONFIG_SOFTMMU
  440 + int r1, r2;
  441 + void *label1_ptr, *label2_ptr;
  442 +#endif
  443 +#if TARGET_LONG_BITS == 64
  444 + int addr_reg2;
  445 +#endif
  446 +
  447 + data_reg = *args++;
  448 + if (opc == 3)
  449 + data_reg2 = *args++;
  450 + else
  451 + data_reg2 = 0;
  452 + addr_reg = *args++;
  453 +#if TARGET_LONG_BITS == 64
  454 + addr_reg2 = *args++;
  455 +#endif
  456 + mem_index = *args;
  457 + s_bits = opc & 3;
  458 +
  459 +#ifdef CONFIG_SOFTMMU
  460 + r0 = 3;
  461 + r1 = 4;
  462 + r2 = 0;
  463 +
  464 + tcg_out32 (s, (RLWINM
  465 + | RA (r0)
  466 + | RS (addr_reg)
  467 + | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
  468 + | MB (32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS))
  469 + | ME (31 - CPU_TLB_ENTRY_BITS)
  470 + )
  471 + );
  472 + tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0));
  473 + tcg_out32 (s, (LWZU
  474 + | RT (r1)
  475 + | RA (r0)
  476 + | offsetof (CPUState, tlb_table[mem_index][0].addr_read)
  477 + )
  478 + );
  479 + tcg_out32 (s, (RLWINM
  480 + | RA (r2)
  481 + | RS (addr_reg)
  482 + | SH (0)
  483 + | MB ((32 - s_bits) & 31)
  484 + | ME (31 - TARGET_PAGE_BITS)
  485 + )
  486 + );
  487 +
  488 + tcg_out32 (s, CMP | BF (7) | RA (r2) | RB (r1));
  489 +#if TARGET_LONG_BITS == 64
  490 + tcg_out32 (s, LWZ | RT (r1) | RA (r0) | 4);
  491 + tcg_out32 (s, CMP | BF (6) | RA (addr_reg2) | RB (r1));
  492 + tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
  493 +#endif
  494 +
  495 + label1_ptr = s->code_ptr;
  496 +#ifdef FAST_PATH
  497 + tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
  498 +#endif
  499 +
  500 + /* slow path */
  501 +#if TARGET_LONG_BITS == 32
  502 + tcg_out_mov (s, 3, addr_reg);
  503 + tcg_out_movi (s, TCG_TYPE_I32, 4, mem_index);
  504 +#else
  505 + tcg_out_mov (s, 3, addr_reg2);
  506 + tcg_out_mov (s, 4, addr_reg);
  507 + tcg_out_movi (s, TCG_TYPE_I32, 5, mem_index);
  508 +#endif
  509 +
  510 + tcg_out32 (s, B | reloc_pc24_val (s->code_ptr,
  511 + (tcg_target_long) qemu_ld_helpers[s_bits]) | LK);
  512 + switch (opc) {
  513 + case 0|4:
  514 + tcg_out32 (s, EXTSB | RA (data_reg) | RS (3));
  515 + break;
  516 + case 1|4:
  517 + tcg_out32 (s, EXTSH | RA (data_reg) | RS (3));
  518 + break;
  519 + case 0:
  520 + case 1:
  521 + case 2:
  522 + if (data_reg != 3)
  523 + tcg_out_mov (s, data_reg, 3);
  524 + break;
  525 + case 3:
  526 + if (data_reg == 3) {
  527 + if (data_reg2 == 4) {
  528 + tcg_out_mov (s, 0, 4);
  529 + tcg_out_mov (s, 4, 3);
  530 + tcg_out_mov (s, 3, 0);
  531 + }
  532 + else {
  533 + tcg_out_mov (s, data_reg2, 3);
  534 + tcg_out_mov (s, 3, 4);
  535 + }
  536 + }
  537 + else {
  538 + if (data_reg != 4) tcg_out_mov (s, data_reg, 4);
  539 + if (data_reg2 != 3) tcg_out_mov (s, data_reg2, 3);
  540 + }
  541 + break;
  542 + }
  543 + label2_ptr = s->code_ptr;
  544 + tcg_out32 (s, B);
  545 +
  546 + /* label1: fast path */
  547 +#ifdef FAST_PATH
  548 + reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
  549 +#endif
  550 +
  551 + /* r0 now contains &env->tlb_table[mem_index][index].addr_read */
  552 + tcg_out32 (s, (LWZ
  553 + | RT (r0)
  554 + | RA (r0)
  555 + | (ADDEND_OFFSET + offsetof (CPUTLBEntry, addend)
  556 + - offsetof (CPUTLBEntry, addr_read))
  557 + ));
  558 + /* r0 = env->tlb_table[mem_index][index].addend */
  559 + tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
  560 + /* r0 = env->tlb_table[mem_index][index].addend + addr */
  561 +
  562 +#else /* !CONFIG_SOFTMMU */
  563 + r0 = addr_reg;
  564 +#endif
  565 +
  566 +#ifdef TARGET_WORDS_BIGENDIAN
  567 + bswap = 0;
  568 +#else
  569 + bswap = 1;
  570 +#endif
  571 + switch (opc) {
  572 + default:
  573 + case 0:
  574 + tcg_out32 (s, LBZ | RT (data_reg) | RA (r0));
  575 + break;
  576 + case 0|4:
  577 + tcg_out32 (s, LBZ | RT (data_reg) | RA (r0));
  578 + tcg_out32 (s, EXTSB | RA (data_reg) | RS (data_reg));
  579 + break;
  580 + case 1:
  581 + if (bswap) tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0));
  582 + else tcg_out32 (s, LHZ | RT (data_reg) | RA (r0));
  583 + break;
  584 + case 1|4:
  585 + if (bswap) {
  586 + tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0));
  587 + tcg_out32 (s, EXTSH | RA (data_reg) | RS (data_reg));
  588 + }
  589 + else tcg_out32 (s, LHA | RT (data_reg) | RA (r0));
  590 + break;
  591 + case 2:
  592 + if (bswap) tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
  593 + else tcg_out32 (s, LWZ | RT (data_reg)| RA (r0));
  594 + break;
  595 + case 3:
  596 + if (bswap) {
  597 + if (r0 == data_reg) {
  598 + tcg_out32 (s, LWBRX | RT (0) | RB (r0));
  599 + tcg_out32 (s, ADDI | RT (r0) | RA (r0) | 4);
  600 + tcg_out32 (s, LWBRX | RT (data_reg2) | RB (r0));
  601 + tcg_out_mov (s, data_reg, 0);
  602 + }
  603 + else {
  604 + tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
  605 + tcg_out32 (s, ADDI | RT (r0) | RA (r0) | 4);
  606 + tcg_out32 (s, LWBRX | RT (data_reg2) | RB (r0));
  607 + }
  608 + }
  609 + else {
  610 + if (r0 == data_reg2) {
  611 + tcg_out32 (s, LWZ | RT (0) | RA (r0));
  612 + tcg_out32 (s, LWZ | RT (data_reg) | RA (r0) | 4);
  613 + tcg_out_mov (s, data_reg2, 0);
  614 + }
  615 + else {
  616 + tcg_out32 (s, LWZ | RT (data_reg2) | RA (r0));
  617 + tcg_out32 (s, LWZ | RT (data_reg) | RA (r0) | 4);
  618 + }
  619 + }
  620 + break;
  621 + }
  622 +
  623 +#ifdef CONFIG_SOFTMMU
  624 + reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
  625 +#endif
  626 +}
  627 +
  628 +static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
  629 +{
  630 + int addr_reg, r0, r1, data_reg, data_reg2, mem_index, bswap;
  631 +#ifdef CONFIG_SOFTMMU
  632 + int r2, ir;
  633 + void *label1_ptr, *label2_ptr;
  634 +#endif
  635 +#if TARGET_LONG_BITS == 64
  636 + int addr_reg2;
  637 +#endif
  638 +
  639 + data_reg = *args++;
  640 + if (opc == 3)
  641 + data_reg2 = *args++;
  642 + else
  643 + data_reg2 = 0;
  644 + addr_reg = *args++;
  645 +#if TARGET_LONG_BITS == 64
  646 + addr_reg2 = *args++;
  647 +#endif
  648 + mem_index = *args;
  649 +
  650 +#ifdef CONFIG_SOFTMMU
  651 + r0 = 3;
  652 + r1 = 4;
  653 + r2 = 0;
  654 +
  655 + tcg_out32 (s, (RLWINM
  656 + | RA (r0)
  657 + | RS (addr_reg)
  658 + | SH (32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS))
  659 + | MB (32 - (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS))
  660 + | ME (31 - CPU_TLB_ENTRY_BITS)
  661 + )
  662 + );
  663 + tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (TCG_AREG0));
  664 + tcg_out32 (s, (LWZU
  665 + | RT (r1)
  666 + | RA (r0)
  667 + | offsetof (CPUState, tlb_table[mem_index][0].addr_write)
  668 + )
  669 + );
  670 + tcg_out32 (s, (RLWINM
  671 + | RA (r2)
  672 + | RS (addr_reg)
  673 + | SH (0)
  674 + | MB ((32 - opc) & 31)
  675 + | ME (31 - TARGET_PAGE_BITS)
  676 + )
  677 + );
  678 +
  679 + tcg_out32 (s, CMP | (7 << 23) | RA (r2) | RB (r1));
  680 +#if TARGET_LONG_BITS == 64
  681 + tcg_out32 (s, LWZ | RT (r1) | RA (r0) | 4);
  682 + tcg_out32 (s, CMP | BF (6) | RA (addr_reg2) | RB (r1));
  683 + tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ));
  684 +#endif
  685 +
  686 + label1_ptr = s->code_ptr;
  687 +#ifdef FAST_PATH
  688 + tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
  689 +#endif
  690 +
  691 + /* slow path */
  692 +#if TARGET_LONG_BITS == 32
  693 + tcg_out_mov (s, 3, addr_reg);
  694 + ir = 4;
  695 +#else
  696 + tcg_out_mov (s, 3, addr_reg2);
  697 + tcg_out_mov (s, 4, addr_reg);
  698 + ir = 5;
  699 +#endif
  700 +
  701 + switch (opc) {
  702 + case 0:
  703 + tcg_out32 (s, (RLWINM
  704 + | RA (ir)
  705 + | RS (data_reg)
  706 + | SH (0)
  707 + | MB (24)
  708 + | ME (31)));
  709 + break;
  710 + case 1:
  711 + tcg_out32 (s, (RLWINM
  712 + | RA (ir)
  713 + | RS (data_reg)
  714 + | SH (0)
  715 + | MB (16)
  716 + | ME (31)));
  717 + break;
  718 + case 2:
  719 + tcg_out_mov (s, ir, data_reg);
  720 + break;
  721 + case 3:
  722 + tcg_out_mov (s, 5, data_reg2);
  723 + tcg_out_mov (s, 6, data_reg);
  724 + ir = 6;
  725 + break;
  726 + }
  727 + ir++;
  728 +
  729 + tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index);
  730 + tcg_out32 (s, B | reloc_pc24_val (s->code_ptr,
  731 + (tcg_target_long) qemu_st_helpers[opc]) | LK);
  732 + label2_ptr = s->code_ptr;
  733 + tcg_out32 (s, B);
  734 +
  735 + /* label1: fast path */
  736 +#ifdef FAST_PATH
  737 + reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
  738 +#endif
  739 +
  740 + tcg_out32 (s, (LWZ
  741 + | RT (r0)
  742 + | RA (r0)
  743 + | (ADDEND_OFFSET + offsetof (CPUTLBEntry, addend)
  744 + - offsetof (CPUTLBEntry, addr_write))
  745 + ));
  746 + /* r0 = env->tlb_table[mem_index][index].addend */
  747 + tcg_out32 (s, ADD | RT (r0) | RA (r0) | RB (addr_reg));
  748 + /* r0 = env->tlb_table[mem_index][index].addend + addr */
  749 +
  750 +#else /* !CONFIG_SOFTMMU */
  751 + r1 = 4;
  752 + r0 = addr_reg;
  753 +#endif
  754 +
  755 +#ifdef TARGET_WORDS_BIGENDIAN
  756 + bswap = 0;
  757 +#else
  758 + bswap = 1;
  759 +#endif
  760 + switch (opc) {
  761 + case 0:
  762 + tcg_out32 (s, STB | RS (data_reg) | RA (r0));
  763 + break;
  764 + case 1:
  765 + if (bswap) tcg_out32 (s, STHBRX | RS (data_reg) | RA (0) | RB (r0));
  766 + else tcg_out32 (s, STH | RS (data_reg) | RA (r0));
  767 + break;
  768 + case 2:
  769 + if (bswap) tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0));
  770 + else tcg_out32 (s, STW | RS (data_reg) | RA (r0));
  771 + break;
  772 + case 3:
  773 + if (bswap) {
  774 + tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
  775 + tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0));
  776 + tcg_out32 (s, STWBRX | RS (data_reg2) | RA (0) | RB (r1));
  777 + }
  778 + else {
  779 + tcg_out32 (s, STW | RS (data_reg2) | RA (r0));
  780 + tcg_out32 (s, STW | RS (data_reg) | RA (r0) | 4);
  781 + }
  782 + break;
  783 + }
  784 +
  785 +#ifdef CONFIG_SOFTMMU
  786 + reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
  787 +#endif
  788 +}
  789 +
  790 +void tcg_target_qemu_prologue (TCGContext *s)
  791 +{
  792 + int i, frame_size;
  793 +
  794 + frame_size = 0
  795 + + 4 /* back chain */
  796 + + 4 /* LR */
  797 + + TCG_STATIC_CALL_ARGS_SIZE
  798 + + ARRAY_SIZE (tcg_target_callee_save_regs) * 4
  799 + ;
  800 + frame_size = (frame_size + 15) & ~15;
  801 +
  802 + tcg_out32 (s, MFSPR | RT (0) | LR);
  803 + tcg_out32 (s, STWU | RS (1) | RA (1) | (-frame_size & 0xffff));
  804 + for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
  805 + tcg_out32 (s, (STW
  806 + | RS (tcg_target_callee_save_regs[i])
  807 + | RA (1)
  808 + | (i * 4 + 8 + TCG_STATIC_CALL_ARGS_SIZE)
  809 + )
  810 + );
  811 + tcg_out32 (s, STW | RS (0) | RA (1) | (frame_size - 4));
  812 +
  813 + tcg_out32 (s, MTSPR | RS (3) | CTR);
  814 + tcg_out32 (s, BCCTR | BO_ALWAYS);
  815 + tb_ret_addr = s->code_ptr;
  816 +
  817 + for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
  818 + tcg_out32 (s, (LWZ
  819 + | RT (tcg_target_callee_save_regs[i])
  820 + | RA (1)
  821 + | (i * 4 + 8 + TCG_STATIC_CALL_ARGS_SIZE)
  822 + )
  823 + );
  824 + tcg_out32 (s, LWZ | RT (0) | RA (1) | (frame_size - 4));
  825 + tcg_out32 (s, MTSPR | RS (0) | LR);
  826 + tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
  827 + tcg_out32 (s, BCLR | BO_ALWAYS);
  828 +}
  829 +
  830 +static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
  831 + tcg_target_long arg2)
  832 +{
  833 + tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
  834 +}
  835 +
  836 +static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1,
  837 + tcg_target_long arg2)
  838 +{
  839 + tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
  840 +}
  841 +
  842 +static void ppc_addi (TCGContext *s, int rt, int ra, tcg_target_long si)
  843 +{
  844 + if (!si && rt == ra)
  845 + return;
  846 +
  847 + if (si == (int16_t) si)
  848 + tcg_out32 (s, ADDI | RT (rt) | RA (ra) | (si & 0xffff));
  849 + else {
  850 + uint16_t h = ((si >> 16) & 0xffff) + ((uint16_t) si >> 15);
  851 + tcg_out32 (s, ADDIS | RT (rt) | RA (ra) | h);
  852 + tcg_out32 (s, ADDI | RT (rt) | RA (rt) | (si & 0xffff));
  853 + }
  854 +}
  855 +
  856 +static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
  857 +{
  858 + ppc_addi (s, reg, reg, val);
  859 +}
  860 +
  861 +static void tcg_out_brcond(TCGContext *s, int cond,
  862 + TCGArg arg1, TCGArg arg2, int const_arg2,
  863 + int label_index)
  864 +{
  865 + TCGLabel *l = &s->labels[label_index];
  866 + int imm;
  867 + uint32_t op;
  868 +
  869 + imm = const_arg2 ? ((int16_t) arg2 == arg2) : 0;
  870 + switch (cond) {
  871 + case TCG_COND_EQ: op = imm ? CMPLI : CMPL; break;
  872 + case TCG_COND_NE: op = imm ? CMPLI : CMPL; break;
  873 + case TCG_COND_LT: op = imm ? CMPI : CMP; break;
  874 + case TCG_COND_GE: op = imm ? CMPI : CMP; break;
  875 + case TCG_COND_LE: op = imm ? CMPI : CMP; break;
  876 + case TCG_COND_GT: op = imm ? CMPI : CMP; break;
  877 + case TCG_COND_LTU: op = imm ? CMPLI : CMPL; break;
  878 + case TCG_COND_GEU: op = imm ? CMPLI : CMPL; break;
  879 + case TCG_COND_LEU: op = imm ? CMPLI : CMPL; break;
  880 + case TCG_COND_GTU: op = imm ? CMPLI : CMPL; break;
  881 + default:
  882 + tcg_abort ();
  883 + }
  884 + op |= BF (7);
  885 +
  886 + if (imm)
  887 + tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff));
  888 + else {
  889 + if (const_arg2) {
  890 + tcg_out_movi (s, TCG_TYPE_I32, 0, arg2);
  891 + tcg_out32 (s, op | RA (arg1) | RB (0));
  892 + }
  893 + else
  894 + tcg_out32 (s, op | RA (arg1) | RB (arg2));
  895 + }
  896 +
  897 + if (l->has_value) {
  898 + tcg_out32 (s, tcg_to_bc[cond] | reloc_pc14_val (s->code_ptr,
  899 + l->u.value));
  900 + }
  901 + else {
  902 + tcg_out32 (s, tcg_to_bc[cond]);
  903 + tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0);
  904 + }
  905 +}
  906 +
  907 +/* brcond2 is taken verbatim from i386 tcg-target */
  908 +/* XXX: we implement it at the target level to avoid having to
  909 + handle cross basic blocks temporaries */
  910 +static void tcg_out_brcond2(TCGContext *s,
  911 + const TCGArg *args, const int *const_args)
  912 +{
  913 + int label_next;
  914 + label_next = gen_new_label();
  915 + switch(args[4]) {
  916 + case TCG_COND_EQ:
  917 + tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2], label_next);
  918 + tcg_out_brcond(s, TCG_COND_EQ, args[1], args[3], const_args[3], args[5]);
  919 + break;
  920 + case TCG_COND_NE:
  921 + tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2], args[5]);
  922 + tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], args[5]);
  923 + break;
  924 + case TCG_COND_LT:
  925 + tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]);
  926 + tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
  927 + tcg_out_brcond(s, TCG_COND_LT, args[0], args[2], const_args[2], args[5]);
  928 + break;
  929 + case TCG_COND_LE:
  930 + tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]);
  931 + tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
  932 + tcg_out_brcond(s, TCG_COND_LE, args[0], args[2], const_args[2], args[5]);
  933 + break;
  934 + case TCG_COND_GT:
  935 + tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]);
  936 + tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
  937 + tcg_out_brcond(s, TCG_COND_GT, args[0], args[2], const_args[2], args[5]);
  938 + break;
  939 + case TCG_COND_GE:
  940 + tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]);
  941 + tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
  942 + tcg_out_brcond(s, TCG_COND_GE, args[0], args[2], const_args[2], args[5]);
  943 + break;
  944 + case TCG_COND_LTU:
  945 + tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]);
  946 + tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
  947 + tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2], args[5]);
  948 + break;
  949 + case TCG_COND_LEU:
  950 + tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]);
  951 + tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
  952 + tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2], args[5]);
  953 + break;
  954 + case TCG_COND_GTU:
  955 + tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]);
  956 + tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
  957 + tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2], args[5]);
  958 + break;
  959 + case TCG_COND_GEU:
  960 + tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]);
  961 + tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);
  962 + tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2], args[5]);
  963 + break;
  964 + default:
  965 + tcg_abort();
  966 + }
  967 + tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
  968 +}
  969 +
  970 +static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
  971 + const int *const_args)
  972 +{
  973 + switch (opc) {
  974 + case INDEX_op_exit_tb:
  975 + tcg_out_movi (s, TCG_TYPE_I32, TCG_REG_R3, args[0]);
  976 + tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, (tcg_target_long) tb_ret_addr));
  977 + break;
  978 + case INDEX_op_goto_tb:
  979 + if (s->tb_jmp_offset) {
  980 + /* direct jump method */
  981 + s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
  982 + tcg_out32 (s, B | 4);
  983 + } else {
  984 + tcg_abort ();
  985 + }
  986 + s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
  987 + break;
  988 + case INDEX_op_br:
  989 + {
  990 + TCGLabel *l = &s->labels[args[0]];
  991 +
  992 + if (l->has_value) {
  993 + tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, l->u.value));
  994 + }
  995 + else {
  996 + tcg_out32 (s, B);
  997 + tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0);
  998 + }
  999 + }
  1000 + break;
  1001 + case INDEX_op_call:
  1002 + if (const_args[0]) {
  1003 + tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, args[0]) | LK);
  1004 + }
  1005 + else {
  1006 + tcg_out32 (s, MTSPR | RS (args[0]) | LR);
  1007 + tcg_out32 (s, BCLR | BO_ALWAYS | LK);
  1008 + }
  1009 + break;
  1010 + case INDEX_op_jmp:
  1011 + if (const_args[0]) {
  1012 + tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, args[0]));
  1013 + }
  1014 + else {
  1015 + tcg_out32 (s, MTSPR | RS (args[0]) | CTR);
  1016 + tcg_out32 (s, BCCTR | BO_ALWAYS);
  1017 + }
  1018 + break;
  1019 + case INDEX_op_movi_i32:
  1020 + tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
  1021 + break;
  1022 + case INDEX_op_ld8u_i32:
  1023 + tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
  1024 + break;
  1025 + case INDEX_op_ld8s_i32:
  1026 + tcg_out_ldst (s, args[0], args[1], args[2], LBZ, LBZX);
  1027 + tcg_out32 (s, EXTSB | RS (args[0]) | RA (args[0]));
  1028 + break;
  1029 + case INDEX_op_ld16u_i32:
  1030 + tcg_out_ldst (s, args[0], args[1], args[2], LHZ, LHZX);
  1031 + break;
  1032 + case INDEX_op_ld16s_i32:
  1033 + tcg_out_ldst (s, args[0], args[1], args[2], LHA, LHAX);
  1034 + break;
  1035 + case INDEX_op_ld_i32:
  1036 + tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX);
  1037 + break;
  1038 + case INDEX_op_st8_i32:
  1039 + tcg_out_ldst (s, args[0], args[1], args[2], STB, STBX);
  1040 + break;
  1041 + case INDEX_op_st16_i32:
  1042 + tcg_out_ldst (s, args[0], args[1], args[2], STH, STHX);
  1043 + break;
  1044 + case INDEX_op_st_i32:
  1045 + tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX);
  1046 + break;
  1047 +
  1048 + case INDEX_op_add_i32:
  1049 + if (const_args[2])
  1050 + ppc_addi (s, args[0], args[1], args[2]);
  1051 + else
  1052 + tcg_out32 (s, ADD | TAB (args[0], args[1], args[2]));
  1053 + break;
  1054 + case INDEX_op_sub_i32:
  1055 + if (const_args[2])
  1056 + ppc_addi (s, args[0], args[1], -args[2]);
  1057 + else
  1058 + tcg_out32 (s, SUBF | TAB (args[0], args[2], args[1]));
  1059 + break;
  1060 +
  1061 + case INDEX_op_and_i32:
  1062 + if (const_args[2]) {
  1063 + if (!args[2])
  1064 + tcg_out_movi (s, TCG_TYPE_I32, args[0], 0);
  1065 + else {
  1066 + if ((args[2] & 0xffff) == args[2])
  1067 + tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | args[2]);
  1068 + else if ((args[2] & 0xffff0000) == args[2])
  1069 + tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0])
  1070 + | ((args[2] >> 16) & 0xffff));
  1071 + else if (args[2] == 0xffffffff) {
  1072 + if (args[0] != args[1])
  1073 + tcg_out_mov (s, args[0], args[1]);
  1074 + }
  1075 + else {
  1076 + tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
  1077 + tcg_out32 (s, AND | SAB (args[1], args[0], 0));
  1078 + }
  1079 + }
  1080 + }
  1081 + else
  1082 + tcg_out32 (s, AND | SAB (args[1], args[0], args[2]));
  1083 + break;
  1084 + case INDEX_op_or_i32:
  1085 + if (const_args[2]) {
  1086 + if (args[2]) {
  1087 + if (args[2] & 0xffff) {
  1088 + tcg_out32 (s, ORI | RS (args[1]) | RA (args[0]) | (args[2] & 0xffff));
  1089 + if (args[2] >> 16)
  1090 + tcg_out32 (s, ORIS | RS (args[0]) | RA (args[0])
  1091 + | ((args[2] >> 16) & 0xffff));
  1092 + }
  1093 + else {
  1094 + tcg_out32 (s, ORIS | RS (args[1]) | RA (args[0])
  1095 + | ((args[2] >> 16) & 0xffff));
  1096 + }
  1097 + }
  1098 + else {
  1099 + if (args[0] != args[1])
  1100 + tcg_out_mov (s, args[0], args[1]);
  1101 + }
  1102 + }
  1103 + else
  1104 + tcg_out32 (s, OR | SAB (args[1], args[0], args[2]));
  1105 + break;
  1106 + case INDEX_op_xor_i32:
  1107 + if (const_args[2]) {
  1108 + if (args[2]) {
  1109 + if ((args[2] & 0xffff) == args[2])
  1110 + tcg_out32 (s, XORI | RS (args[1]) | RA (args[0])
  1111 + | (args[2] & 0xffff));
  1112 + else if ((args[2] & 0xffff0000) == args[2])
  1113 + tcg_out32 (s, XORIS | RS (args[1]) | RA (args[0])
  1114 + | ((args[2] >> 16) & 0xffff));
  1115 + else {
  1116 + tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
  1117 + tcg_out32 (s, XOR | SAB (args[1], args[0], 0));
  1118 + }
  1119 + }
  1120 + else {
  1121 + if (args[0] != args[1])
  1122 + tcg_out_mov (s, args[0], args[1]);
  1123 + }
  1124 + }
  1125 + else
  1126 + tcg_out32 (s, XOR | SAB (args[1], args[0], args[2]));
  1127 + break;
  1128 +
  1129 + case INDEX_op_mul_i32:
  1130 + if (const_args[2]) {
  1131 + if (args[2] == (int16_t) args[2])
  1132 + tcg_out32 (s, MULLI | RT (args[0]) | RA (args[1])
  1133 + | (args[2] & 0xffff));
  1134 + else {
  1135 + tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]);
  1136 + tcg_out32 (s, MULLW | TAB (args[0], args[1], 0));
  1137 + }
  1138 + }
  1139 + else
  1140 + tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2]));
  1141 + break;
  1142 + case INDEX_op_mulu2_i32:
  1143 + if (args[0] == args[2] || args[0] == args[3]) {
  1144 + tcg_out32 (s, MULLW | TAB (0, args[2], args[3]));
  1145 + tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
  1146 + tcg_out_mov (s, args[0], 0);
  1147 + }
  1148 + else {
  1149 + tcg_out32 (s, MULLW | TAB (args[0], args[2], args[3]));
  1150 + tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
  1151 + }
  1152 + break;
  1153 + case INDEX_op_div2_i32:
  1154 + if (args[0] == args[2] || args[0] == args[3]) {
  1155 + tcg_out32 (s, DIVW | TAB (0, args[2], args[3]));
  1156 + tcg_out32 (s, MULLW | TAB (0, 0, args[3]));
  1157 + tcg_out32 (s, SUBF | TAB (0, 0, args[2]));
  1158 + tcg_out32 (s, DIVW | TAB (args[0], args[2], args[3]));
  1159 + tcg_out_mov (s, args[1], 0);
  1160 + }
  1161 + else {
  1162 + tcg_out32 (s, DIVW | TAB (args[0], args[2], args[3]));
  1163 + tcg_out32 (s, MULLW | TAB (0, args[0], args[3]));
  1164 + tcg_out32 (s, SUBF | TAB (args[1], 0, args[2]));
  1165 + }
  1166 + break;
  1167 + case INDEX_op_divu2_i32:
  1168 + if (args[0] == args[2] || args[0] == args[3]) {
  1169 + tcg_out32 (s, DIVWU | TAB (0, args[2], args[3]));
  1170 + tcg_out32 (s, MULLW | TAB (0, 0, args[3]));
  1171 + tcg_out32 (s, SUBF | TAB (0, 0, args[2]));
  1172 + tcg_out32 (s, DIVWU | TAB (args[0], args[2], args[3]));
  1173 + tcg_out_mov (s, args[1], 0);
  1174 + }
  1175 + else {
  1176 + tcg_out32 (s, DIVWU | TAB (args[0], args[2], args[3]));
  1177 + tcg_out32 (s, MULLW | TAB (0, args[0], args[3]));
  1178 + tcg_out32 (s, SUBF | TAB (args[1], 0, args[2]));
  1179 + }
  1180 + break;
  1181 +
  1182 + case INDEX_op_shl_i32:
  1183 + if (const_args[2]) {
  1184 + if (args[2])
  1185 + tcg_out32 (s, (RLWINM
  1186 + | RA (args[0])
  1187 + | RS (args[1])
  1188 + | SH (args[2])
  1189 + | MB (0)
  1190 + | ME (31 - args[2])
  1191 + )
  1192 + );
  1193 + else
  1194 + tcg_out_mov (s, args[0], args[1]);
  1195 + }
  1196 + else
  1197 + tcg_out32 (s, SLW | SAB (args[1], args[0], args[2]));
  1198 + break;
  1199 + case INDEX_op_shr_i32:
  1200 + if (const_args[2]) {
  1201 + if (args[2])
  1202 + tcg_out32 (s, (RLWINM
  1203 + | RA (args[0])
  1204 + | RS (args[1])
  1205 + | SH (32 - args[2])
  1206 + | MB (args[2])
  1207 + | ME (31)
  1208 + )
  1209 + );
  1210 + else
  1211 + tcg_out_mov (s, args[0], args[1]);
  1212 + }
  1213 + else
  1214 + tcg_out32 (s, SRW | SAB (args[1], args[0], args[2]));
  1215 + break;
  1216 + case INDEX_op_sar_i32:
  1217 + if (const_args[2])
  1218 + tcg_out32 (s, SRAWI | RS (args[1]) | RA (args[0]) | SH (args[2]));
  1219 + else
  1220 + tcg_out32 (s, SRAW | SAB (args[1], args[0], args[2]));
  1221 + break;
  1222 +
  1223 + case INDEX_op_add2_i32:
  1224 + if (args[0] == args[3] || args[0] == args[5]) {
  1225 + tcg_out32 (s, ADDC | TAB (0, args[2], args[4]));
  1226 + tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
  1227 + tcg_out_mov (s, args[0], 0);
  1228 + }
  1229 + else {
  1230 + tcg_out32 (s, ADDC | TAB (args[0], args[2], args[4]));
  1231 + tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
  1232 + }
  1233 + break;
  1234 + case INDEX_op_sub2_i32:
  1235 + if (args[0] == args[3] || args[0] == args[5]) {
  1236 + tcg_out32 (s, SUBFC | TAB (0, args[4], args[2]));
  1237 + tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
  1238 + tcg_out_mov (s, args[0], 0);
  1239 + }
  1240 + else {
  1241 + tcg_out32 (s, SUBFC | TAB (args[0], args[4], args[2]));
  1242 + tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
  1243 + }
  1244 + break;
  1245 +
  1246 + case INDEX_op_brcond_i32:
  1247 + /*
  1248 + args[0] = r0
  1249 + args[1] = r1
  1250 + args[2] = cond
  1251 + args[3] = r1 is const
  1252 + args[4] = label_index
  1253 + */
  1254 + tcg_out_brcond (s, args[2], args[0], args[1], const_args[1], args[3]);
  1255 + break;
  1256 + case INDEX_op_brcond2_i32:
  1257 + tcg_out_brcond2(s, args, const_args);
  1258 + break;
  1259 +
  1260 + case INDEX_op_neg_i32:
  1261 + tcg_out32 (s, NEG | RT (args[0]) | RA (args[1]));
  1262 + break;
  1263 +
  1264 + case INDEX_op_qemu_ld8u:
  1265 + tcg_out_qemu_ld(s, args, 0);
  1266 + break;
  1267 + case INDEX_op_qemu_ld8s:
  1268 + tcg_out_qemu_ld(s, args, 0 | 4);
  1269 + break;
  1270 + case INDEX_op_qemu_ld16u:
  1271 + tcg_out_qemu_ld(s, args, 1);
  1272 + break;
  1273 + case INDEX_op_qemu_ld16s:
  1274 + tcg_out_qemu_ld(s, args, 1 | 4);
  1275 + break;
  1276 + case INDEX_op_qemu_ld32u:
  1277 + tcg_out_qemu_ld(s, args, 2);
  1278 + break;
  1279 + case INDEX_op_qemu_ld64:
  1280 + tcg_out_qemu_ld(s, args, 3);
  1281 + break;
  1282 + case INDEX_op_qemu_st8:
  1283 + tcg_out_qemu_st(s, args, 0);
  1284 + break;
  1285 + case INDEX_op_qemu_st16:
  1286 + tcg_out_qemu_st(s, args, 1);
  1287 + break;
  1288 + case INDEX_op_qemu_st32:
  1289 + tcg_out_qemu_st(s, args, 2);
  1290 + break;
  1291 + case INDEX_op_qemu_st64:
  1292 + tcg_out_qemu_st(s, args, 3);
  1293 + break;
  1294 +
  1295 + default:
  1296 + tcg_dump_ops (s, stderr);
  1297 + tcg_abort ();
  1298 + }
  1299 +}
  1300 +
  1301 +static const TCGTargetOpDef ppc_op_defs[] = {
  1302 + { INDEX_op_exit_tb, { } },
  1303 + { INDEX_op_goto_tb, { } },
  1304 + { INDEX_op_call, { "rJ" } },
  1305 + { INDEX_op_jmp, { "rJ" } },
  1306 + { INDEX_op_br, { } },
  1307 +
  1308 + { INDEX_op_mov_i32, { "r", "r" } },
  1309 + { INDEX_op_movi_i32, { "r" } },
  1310 + { INDEX_op_ld8u_i32, { "r", "r" } },
  1311 + { INDEX_op_ld8s_i32, { "r", "r" } },
  1312 + { INDEX_op_ld16u_i32, { "r", "r" } },
  1313 + { INDEX_op_ld16s_i32, { "r", "r" } },
  1314 + { INDEX_op_ld_i32, { "r", "r" } },
  1315 + { INDEX_op_st8_i32, { "r", "r" } },
  1316 + { INDEX_op_st16_i32, { "r", "r" } },
  1317 + { INDEX_op_st_i32, { "r", "r" } },
  1318 +
  1319 + { INDEX_op_add_i32, { "r", "r", "ri" } },
  1320 + { INDEX_op_mul_i32, { "r", "r", "ri" } },
  1321 + { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
  1322 + { INDEX_op_div2_i32, { "r", "r", "r", "r", "r" } },
  1323 + { INDEX_op_divu2_i32, { "r", "r", "r", "r", "r" } },
  1324 + { INDEX_op_sub_i32, { "r", "r", "ri" } },
  1325 + { INDEX_op_and_i32, { "r", "r", "ri" } },
  1326 + { INDEX_op_or_i32, { "r", "r", "ri" } },
  1327 + { INDEX_op_xor_i32, { "r", "r", "ri" } },
  1328 +
  1329 + { INDEX_op_shl_i32, { "r", "r", "ri" } },
  1330 + { INDEX_op_shr_i32, { "r", "r", "ri" } },
  1331 + { INDEX_op_sar_i32, { "r", "r", "ri" } },
  1332 +
  1333 + { INDEX_op_brcond_i32, { "r", "ri" } },
  1334 +
  1335 + { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
  1336 + { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
  1337 + { INDEX_op_brcond2_i32, { "r", "r", "r", "r" } },
  1338 +
  1339 + { INDEX_op_neg_i32, { "r", "r" } },
  1340 +
  1341 +#if TARGET_LONG_BITS == 32
  1342 + { INDEX_op_qemu_ld8u, { "r", "L" } },
  1343 + { INDEX_op_qemu_ld8s, { "r", "L" } },
  1344 + { INDEX_op_qemu_ld16u, { "r", "L" } },
  1345 + { INDEX_op_qemu_ld16s, { "r", "L" } },
  1346 + { INDEX_op_qemu_ld32u, { "r", "L" } },
  1347 + { INDEX_op_qemu_ld32s, { "r", "L" } },
  1348 + { INDEX_op_qemu_ld64, { "r", "r", "L" } },
  1349 +
  1350 + { INDEX_op_qemu_st8, { "K", "K" } },
  1351 + { INDEX_op_qemu_st16, { "K", "K" } },
  1352 + { INDEX_op_qemu_st32, { "K", "K" } },
  1353 + { INDEX_op_qemu_st64, { "M", "M", "M" } },
  1354 +#else
  1355 + { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
  1356 + { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
  1357 + { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
  1358 + { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
  1359 + { INDEX_op_qemu_ld32u, { "r", "L", "L" } },
  1360 + { INDEX_op_qemu_ld32s, { "r", "L", "L" } },
  1361 + { INDEX_op_qemu_ld64, { "r", "L", "L", "L" } },
  1362 +
  1363 + { INDEX_op_qemu_st8, { "K", "K", "K" } },
  1364 + { INDEX_op_qemu_st16, { "K", "K", "K" } },
  1365 + { INDEX_op_qemu_st32, { "K", "K", "K" } },
  1366 + { INDEX_op_qemu_st64, { "M", "M", "M", "M" } },
  1367 +#endif
  1368 +
  1369 + { -1 },
  1370 +};
  1371 +
  1372 +void tcg_target_init(TCGContext *s)
  1373 +{
  1374 + tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
  1375 + tcg_regset_set32(tcg_target_call_clobber_regs, 0,
  1376 + (1 << TCG_REG_R0) |
  1377 + (1 << TCG_REG_R3) |
  1378 + (1 << TCG_REG_R4) |
  1379 + (1 << TCG_REG_R5) |
  1380 + (1 << TCG_REG_R6) |
  1381 + (1 << TCG_REG_R7) |
  1382 + (1 << TCG_REG_R8) |
  1383 + (1 << TCG_REG_R9) |
  1384 + (1 << TCG_REG_R10) |
  1385 + (1 << TCG_REG_R11) |
  1386 + (1 << TCG_REG_R12)
  1387 + );
  1388 +
  1389 + tcg_regset_clear(s->reserved_regs);
  1390 + tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);
  1391 + tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1);
  1392 + tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2);
  1393 +
  1394 + tcg_add_target_add_op_defs(ppc_op_defs);
  1395 +}
... ...
tcg/ppc/tcg-target.h 0 → 100644
  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 +#define TCG_TARGET_PPC 1
  25 +
  26 +#define TCG_TARGET_REG_BITS 32
  27 +#define TCG_TARGET_WORDS_BIGENDIAN
  28 +#define TCG_TARGET_NB_REGS 32
  29 +
  30 +enum {
  31 + TCG_REG_R0 = 0,
  32 + TCG_REG_R1,
  33 + TCG_REG_R2,
  34 + TCG_REG_R3,
  35 + TCG_REG_R4,
  36 + TCG_REG_R5,
  37 + TCG_REG_R6,
  38 + TCG_REG_R7,
  39 + TCG_REG_R8,
  40 + TCG_REG_R9,
  41 + TCG_REG_R10,
  42 + TCG_REG_R11,
  43 + TCG_REG_R12,
  44 + TCG_REG_R13,
  45 + TCG_REG_R14,
  46 + TCG_REG_R15,
  47 + TCG_REG_R16,
  48 + TCG_REG_R17,
  49 + TCG_REG_R18,
  50 + TCG_REG_R19,
  51 + TCG_REG_R20,
  52 + TCG_REG_R21,
  53 + TCG_REG_R22,
  54 + TCG_REG_R23,
  55 + TCG_REG_R24,
  56 + TCG_REG_R25,
  57 + TCG_REG_R26,
  58 + TCG_REG_R27,
  59 + TCG_REG_R28,
  60 + TCG_REG_R29,
  61 + TCG_REG_R30,
  62 + TCG_REG_R31
  63 +};
  64 +
  65 +/* used for function call generation */
  66 +#define TCG_REG_CALL_STACK TCG_REG_R1
  67 +#define TCG_TARGET_STACK_ALIGN 16
  68 +#define TCG_TARGET_CALL_STACK_OFFSET 8
  69 +#define TCG_TARGET_CALL_ALIGN_ARGS 1
  70 +
  71 +/* optional instructions */
  72 +#define TCG_TARGET_HAS_neg_i32
  73 +
  74 +#define TCG_AREG0 TCG_REG_R27
  75 +#define TCG_AREG1 TCG_REG_R24
  76 +#define TCG_AREG2 TCG_REG_R25
  77 +#define TCG_AREG3 TCG_REG_R26
  78 +
  79 +/* taken directly from tcg-dyngen.c */
  80 +#define MIN_CACHE_LINE_SIZE 8 /* conservative value */
  81 +
  82 +static inline void flush_icache_range(unsigned long start, unsigned long stop)
  83 +{
  84 + unsigned long p;
  85 +
  86 + start &= ~(MIN_CACHE_LINE_SIZE - 1);
  87 + stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
  88 +
  89 + for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
  90 + asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
  91 + }
  92 + asm volatile ("sync" : : : "memory");
  93 + for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
  94 + asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
  95 + }
  96 + asm volatile ("sync" : : : "memory");
  97 + asm volatile ("isync" : : : "memory");
  98 +}
... ...