Annotation of qemu/tcg/ppc/tcg-target.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.