Annotation of qemu/tcg/x86_64/tcg-target.c, revision 1.1.1.3

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: #ifndef NDEBUG
                     26: static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
                     27:     "%rax",
                     28:     "%rcx",
                     29:     "%rdx",
                     30:     "%rbx",
                     31:     "%rsp",
                     32:     "%rbp",
                     33:     "%rsi",
                     34:     "%rdi",
                     35:     "%r8",
                     36:     "%r9",
                     37:     "%r10",
                     38:     "%r11",
                     39:     "%r12",
                     40:     "%r13",
                     41:     "%r14",
                     42:     "%r15",
                     43: };
                     44: #endif
                     45: 
                     46: static const int tcg_target_reg_alloc_order[] = {
                     47:     TCG_REG_RBP,
                     48:     TCG_REG_RBX,
                     49:     TCG_REG_R12,
                     50:     TCG_REG_R13,
                     51:     TCG_REG_R14,
                     52:     TCG_REG_R15,
1.1.1.2   root       53:     TCG_REG_R10,
                     54:     TCG_REG_R11,
                     55:     TCG_REG_R9,
                     56:     TCG_REG_R8,
                     57:     TCG_REG_RCX,
                     58:     TCG_REG_RDX,
                     59:     TCG_REG_RSI,
                     60:     TCG_REG_RDI,
                     61:     TCG_REG_RAX,
1.1       root       62: };
                     63: 
                     64: static const int tcg_target_call_iarg_regs[6] = {
                     65:     TCG_REG_RDI,
                     66:     TCG_REG_RSI,
                     67:     TCG_REG_RDX,
                     68:     TCG_REG_RCX,
                     69:     TCG_REG_R8,
                     70:     TCG_REG_R9,
                     71: };
                     72: 
                     73: static const int tcg_target_call_oarg_regs[2] = {
                     74:     TCG_REG_RAX, 
                     75:     TCG_REG_RDX 
                     76: };
                     77: 
                     78: static uint8_t *tb_ret_addr;
                     79: 
                     80: static void patch_reloc(uint8_t *code_ptr, int type, 
                     81:                         tcg_target_long value, tcg_target_long addend)
                     82: {
                     83:     value += addend;
                     84:     switch(type) {
                     85:     case R_X86_64_32:
                     86:         if (value != (uint32_t)value)
                     87:             tcg_abort();
                     88:         *(uint32_t *)code_ptr = value;
                     89:         break;
                     90:     case R_X86_64_32S:
                     91:         if (value != (int32_t)value)
                     92:             tcg_abort();
                     93:         *(uint32_t *)code_ptr = value;
                     94:         break;
                     95:     case R_386_PC32:
                     96:         value -= (long)code_ptr;
                     97:         if (value != (int32_t)value)
                     98:             tcg_abort();
                     99:         *(uint32_t *)code_ptr = value;
                    100:         break;
                    101:     default:
                    102:         tcg_abort();
                    103:     }
                    104: }
                    105: 
                    106: /* maximum number of register used for input function arguments */
                    107: static inline int tcg_target_get_call_iarg_regs_count(int flags)
                    108: {
                    109:     return 6;
                    110: }
                    111: 
                    112: /* parse target specific constraints */
                    113: static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
                    114: {
                    115:     const char *ct_str;
                    116: 
                    117:     ct_str = *pct_str;
                    118:     switch(ct_str[0]) {
                    119:     case 'a':
                    120:         ct->ct |= TCG_CT_REG;
                    121:         tcg_regset_set_reg(ct->u.regs, TCG_REG_RAX);
                    122:         break;
                    123:     case 'b':
                    124:         ct->ct |= TCG_CT_REG;
                    125:         tcg_regset_set_reg(ct->u.regs, TCG_REG_RBX);
                    126:         break;
                    127:     case 'c':
                    128:         ct->ct |= TCG_CT_REG;
                    129:         tcg_regset_set_reg(ct->u.regs, TCG_REG_RCX);
                    130:         break;
                    131:     case 'd':
                    132:         ct->ct |= TCG_CT_REG;
                    133:         tcg_regset_set_reg(ct->u.regs, TCG_REG_RDX);
                    134:         break;
                    135:     case 'S':
                    136:         ct->ct |= TCG_CT_REG;
                    137:         tcg_regset_set_reg(ct->u.regs, TCG_REG_RSI);
                    138:         break;
                    139:     case 'D':
                    140:         ct->ct |= TCG_CT_REG;
                    141:         tcg_regset_set_reg(ct->u.regs, TCG_REG_RDI);
                    142:         break;
                    143:     case 'q':
                    144:         ct->ct |= TCG_CT_REG;
                    145:         tcg_regset_set32(ct->u.regs, 0, 0xf);
                    146:         break;
                    147:     case 'r':
                    148:         ct->ct |= TCG_CT_REG;
                    149:         tcg_regset_set32(ct->u.regs, 0, 0xffff);
                    150:         break;
                    151:     case 'L': /* qemu_ld/st constraint */
                    152:         ct->ct |= TCG_CT_REG;
                    153:         tcg_regset_set32(ct->u.regs, 0, 0xffff);
                    154:         tcg_regset_reset_reg(ct->u.regs, TCG_REG_RSI);
                    155:         tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDI);
                    156:         break;
                    157:     case 'e':
                    158:         ct->ct |= TCG_CT_CONST_S32;
                    159:         break;
                    160:     case 'Z':
                    161:         ct->ct |= TCG_CT_CONST_U32;
                    162:         break;
                    163:     default:
                    164:         return -1;
                    165:     }
                    166:     ct_str++;
                    167:     *pct_str = ct_str;
                    168:     return 0;
                    169: }
                    170: 
                    171: /* test if a constant matches the constraint */
                    172: static inline int tcg_target_const_match(tcg_target_long val,
                    173:                                          const TCGArgConstraint *arg_ct)
                    174: {
                    175:     int ct;
                    176:     ct = arg_ct->ct;
                    177:     if (ct & TCG_CT_CONST)
                    178:         return 1;
                    179:     else if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val)
                    180:         return 1;
                    181:     else if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val)
                    182:         return 1;
                    183:     else
                    184:         return 0;
                    185: }
                    186: 
                    187: #define ARITH_ADD 0
                    188: #define ARITH_OR  1
                    189: #define ARITH_ADC 2
                    190: #define ARITH_SBB 3
                    191: #define ARITH_AND 4
                    192: #define ARITH_SUB 5
                    193: #define ARITH_XOR 6
                    194: #define ARITH_CMP 7
                    195: 
1.1.1.2   root      196: #define SHIFT_ROL 0
                    197: #define SHIFT_ROR 1
1.1       root      198: #define SHIFT_SHL 4
                    199: #define SHIFT_SHR 5
                    200: #define SHIFT_SAR 7
                    201: 
                    202: #define JCC_JMP (-1)
                    203: #define JCC_JO  0x0
                    204: #define JCC_JNO 0x1
                    205: #define JCC_JB  0x2
                    206: #define JCC_JAE 0x3
                    207: #define JCC_JE  0x4
                    208: #define JCC_JNE 0x5
                    209: #define JCC_JBE 0x6
                    210: #define JCC_JA  0x7
                    211: #define JCC_JS  0x8
                    212: #define JCC_JNS 0x9
                    213: #define JCC_JP  0xa
                    214: #define JCC_JNP 0xb
                    215: #define JCC_JL  0xc
                    216: #define JCC_JGE 0xd
                    217: #define JCC_JLE 0xe
                    218: #define JCC_JG  0xf
                    219: 
                    220: #define P_EXT   0x100 /* 0x0f opcode prefix */
                    221: #define P_REXW  0x200 /* set rex.w = 1 */
                    222: #define P_REXB  0x400 /* force rex use for byte registers */
                    223:                                   
                    224: static const uint8_t tcg_cond_to_jcc[10] = {
                    225:     [TCG_COND_EQ] = JCC_JE,
                    226:     [TCG_COND_NE] = JCC_JNE,
                    227:     [TCG_COND_LT] = JCC_JL,
                    228:     [TCG_COND_GE] = JCC_JGE,
                    229:     [TCG_COND_LE] = JCC_JLE,
                    230:     [TCG_COND_GT] = JCC_JG,
                    231:     [TCG_COND_LTU] = JCC_JB,
                    232:     [TCG_COND_GEU] = JCC_JAE,
                    233:     [TCG_COND_LEU] = JCC_JBE,
                    234:     [TCG_COND_GTU] = JCC_JA,
                    235: };
                    236: 
                    237: static inline void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
                    238: {
                    239:     int rex;
                    240:     rex = ((opc >> 6) & 0x8) | ((r >> 1) & 0x4) | 
                    241:         ((x >> 2) & 2) | ((rm >> 3) & 1);
                    242:     if (rex || (opc & P_REXB)) {
                    243:         tcg_out8(s, rex | 0x40);
                    244:     }
                    245:     if (opc & P_EXT)
                    246:         tcg_out8(s, 0x0f);
1.1.1.2   root      247:     tcg_out8(s, opc & 0xff);
1.1       root      248: }
                    249: 
                    250: static inline void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
                    251: {
                    252:     tcg_out_opc(s, opc, r, rm, 0);
                    253:     tcg_out8(s, 0xc0 | ((r & 7) << 3) | (rm & 7));
                    254: }
                    255: 
                    256: /* rm < 0 means no register index plus (-rm - 1 immediate bytes) */
                    257: static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm, 
                    258:                                         tcg_target_long offset)
                    259: {
                    260:     if (rm < 0) {
                    261:         tcg_target_long val;
                    262:         tcg_out_opc(s, opc, r, 0, 0);
                    263:         val = offset - ((tcg_target_long)s->code_ptr + 5 + (-rm - 1));
                    264:         if (val == (int32_t)val) {
                    265:             /* eip relative */
                    266:             tcg_out8(s, 0x05 | ((r & 7) << 3));
                    267:             tcg_out32(s, val);
                    268:         } else if (offset == (int32_t)offset) {
                    269:             tcg_out8(s, 0x04 | ((r & 7) << 3));
                    270:             tcg_out8(s, 0x25); /* sib */
                    271:             tcg_out32(s, offset);
                    272:         } else {
                    273:             tcg_abort();
                    274:         }
                    275:     } else if (offset == 0 && (rm & 7) != TCG_REG_RBP) {
                    276:         tcg_out_opc(s, opc, r, rm, 0);
                    277:         if ((rm & 7) == TCG_REG_RSP) {
                    278:             tcg_out8(s, 0x04 | ((r & 7) << 3));
                    279:             tcg_out8(s, 0x24);
                    280:         } else {
                    281:             tcg_out8(s, 0x00 | ((r & 7) << 3) | (rm & 7));
                    282:         }
                    283:     } else if ((int8_t)offset == offset) {
                    284:         tcg_out_opc(s, opc, r, rm, 0);
                    285:         if ((rm & 7) == TCG_REG_RSP) {
                    286:             tcg_out8(s, 0x44 | ((r & 7) << 3));
                    287:             tcg_out8(s, 0x24);
                    288:         } else {
                    289:             tcg_out8(s, 0x40 | ((r & 7) << 3) | (rm & 7));
                    290:         }
                    291:         tcg_out8(s, offset);
                    292:     } else {
                    293:         tcg_out_opc(s, opc, r, rm, 0);
                    294:         if ((rm & 7) == TCG_REG_RSP) {
                    295:             tcg_out8(s, 0x84 | ((r & 7) << 3));
                    296:             tcg_out8(s, 0x24);
                    297:         } else {
                    298:             tcg_out8(s, 0x80 | ((r & 7) << 3) | (rm & 7));
                    299:         }
                    300:         tcg_out32(s, offset);
                    301:     }
                    302: }
                    303: 
                    304: #if defined(CONFIG_SOFTMMU)
                    305: /* XXX: incomplete. index must be different from ESP */
                    306: static void tcg_out_modrm_offset2(TCGContext *s, int opc, int r, int rm, 
                    307:                                   int index, int shift,
                    308:                                   tcg_target_long offset)
                    309: {
                    310:     int mod;
                    311:     if (rm == -1)
                    312:         tcg_abort();
                    313:     if (offset == 0 && (rm & 7) != TCG_REG_RBP) {
                    314:         mod = 0;
                    315:     } else if (offset == (int8_t)offset) {
                    316:         mod = 0x40;
                    317:     } else if (offset == (int32_t)offset) {
                    318:         mod = 0x80;
                    319:     } else {
                    320:         tcg_abort();
                    321:     }
                    322:     if (index == -1) {
                    323:         tcg_out_opc(s, opc, r, rm, 0);
                    324:         if ((rm & 7) == TCG_REG_RSP) {
                    325:             tcg_out8(s, mod | ((r & 7) << 3) | 0x04);
                    326:             tcg_out8(s, 0x04 | (rm & 7));
                    327:         } else {
                    328:             tcg_out8(s, mod | ((r & 7) << 3) | (rm & 7));
                    329:         }
                    330:     } else {
                    331:         tcg_out_opc(s, opc, r, rm, index);
                    332:         tcg_out8(s, mod | ((r & 7) << 3) | 0x04);
                    333:         tcg_out8(s, (shift << 6) | ((index & 7) << 3) | (rm & 7));
                    334:     }
                    335:     if (mod == 0x40) {
                    336:         tcg_out8(s, offset);
                    337:     } else if (mod == 0x80) {
                    338:         tcg_out32(s, offset);
                    339:     }
                    340: }
                    341: #endif
                    342: 
                    343: static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
                    344: {
                    345:     tcg_out_modrm(s, 0x8b | P_REXW, ret, arg);
                    346: }
                    347: 
                    348: static inline void tcg_out_movi(TCGContext *s, TCGType type, 
                    349:                                 int ret, tcg_target_long arg)
                    350: {
                    351:     if (arg == 0) {
                    352:         tcg_out_modrm(s, 0x01 | (ARITH_XOR << 3), ret, ret); /* xor r0,r0 */
                    353:     } else if (arg == (uint32_t)arg || type == TCG_TYPE_I32) {
                    354:         tcg_out_opc(s, 0xb8 + (ret & 7), 0, ret, 0);
                    355:         tcg_out32(s, arg);
                    356:     } else if (arg == (int32_t)arg) {
                    357:         tcg_out_modrm(s, 0xc7 | P_REXW, 0, ret);
                    358:         tcg_out32(s, arg);
                    359:     } else {
                    360:         tcg_out_opc(s, (0xb8 + (ret & 7)) | P_REXW, 0, ret, 0);
                    361:         tcg_out32(s, arg);
                    362:         tcg_out32(s, arg >> 32);
                    363:     }
                    364: }
                    365: 
1.1.1.3 ! root      366: static void tcg_out_goto(TCGContext *s, int call, uint8_t *target)
        !           367: {
        !           368:     int32_t disp;
        !           369: 
        !           370:     disp = target - s->code_ptr - 5;
        !           371:     if (disp == (target - s->code_ptr - 5)) {
        !           372:         tcg_out8(s, call ? 0xe8 : 0xe9);
        !           373:         tcg_out32(s, disp);
        !           374:     } else {
        !           375:         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R10, (tcg_target_long) target);
        !           376:         tcg_out_modrm(s, 0xff, call ? 2 : 4, TCG_REG_R10);
        !           377:     }
        !           378: }
        !           379: 
1.1       root      380: static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
                    381:                               int arg1, tcg_target_long arg2)
                    382: {
                    383:     if (type == TCG_TYPE_I32)
                    384:         tcg_out_modrm_offset(s, 0x8b, ret, arg1, arg2); /* movl */
                    385:     else
                    386:         tcg_out_modrm_offset(s, 0x8b | P_REXW, ret, arg1, arg2); /* movq */
                    387: }
                    388: 
                    389: static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
                    390:                               int arg1, tcg_target_long arg2)
                    391: {
                    392:     if (type == TCG_TYPE_I32)
                    393:         tcg_out_modrm_offset(s, 0x89, arg, arg1, arg2); /* movl */
                    394:     else
                    395:         tcg_out_modrm_offset(s, 0x89 | P_REXW, arg, arg1, arg2); /* movq */
                    396: }
                    397: 
                    398: static inline void tgen_arithi32(TCGContext *s, int c, int r0, int32_t val)
                    399: {
1.1.1.3 ! root      400:     if ((c == ARITH_ADD && val == 1) || (c == ARITH_SUB && val == -1)) {
        !           401:         /* inc */
        !           402:         tcg_out_modrm(s, 0xff, 0, r0);
        !           403:     } else if ((c == ARITH_ADD && val == -1) || (c == ARITH_SUB && val == 1)) {
        !           404:         /* dec */
        !           405:         tcg_out_modrm(s, 0xff, 1, r0);
        !           406:     } else if (val == (int8_t)val) {
1.1       root      407:         tcg_out_modrm(s, 0x83, c, r0);
                    408:         tcg_out8(s, val);
                    409:     } else if (c == ARITH_AND && val == 0xffu) {
                    410:         /* movzbl */
                    411:         tcg_out_modrm(s, 0xb6 | P_EXT | P_REXB, r0, r0);
                    412:     } else if (c == ARITH_AND && val == 0xffffu) {
                    413:         /* movzwl */
                    414:         tcg_out_modrm(s, 0xb7 | P_EXT, r0, r0);
                    415:     } else {
                    416:         tcg_out_modrm(s, 0x81, c, r0);
                    417:         tcg_out32(s, val);
                    418:     }
                    419: }
                    420: 
                    421: static inline void tgen_arithi64(TCGContext *s, int c, int r0, int64_t val)
                    422: {
1.1.1.3 ! root      423:     if ((c == ARITH_ADD && val == 1) || (c == ARITH_SUB && val == -1)) {
        !           424:         /* inc */
        !           425:         tcg_out_modrm(s, 0xff | P_REXW, 0, r0);
        !           426:     } else if ((c == ARITH_ADD && val == -1) || (c == ARITH_SUB && val == 1)) {
        !           427:         /* dec */
        !           428:         tcg_out_modrm(s, 0xff | P_REXW, 1, r0);
        !           429:     } else if (val == (int8_t)val) {
1.1       root      430:         tcg_out_modrm(s, 0x83 | P_REXW, c, r0);
                    431:         tcg_out8(s, val);
                    432:     } else if (c == ARITH_AND && val == 0xffu) {
                    433:         /* movzbl */
                    434:         tcg_out_modrm(s, 0xb6 | P_EXT | P_REXW, r0, r0);
                    435:     } else if (c == ARITH_AND && val == 0xffffu) {
                    436:         /* movzwl */
                    437:         tcg_out_modrm(s, 0xb7 | P_EXT | P_REXW, r0, r0);
                    438:     } else if (c == ARITH_AND && val == 0xffffffffu) {
                    439:         /* 32-bit mov zero extends */
                    440:         tcg_out_modrm(s, 0x8b, r0, r0);
                    441:     } else if (val == (int32_t)val) {
                    442:         tcg_out_modrm(s, 0x81 | P_REXW, c, r0);
                    443:         tcg_out32(s, val);
                    444:     } else if (c == ARITH_AND && val == (uint32_t)val) {
                    445:         tcg_out_modrm(s, 0x81, c, r0);
                    446:         tcg_out32(s, val);
                    447:     } else {
                    448:         tcg_abort();
                    449:     }
                    450: }
                    451: 
                    452: static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
                    453: {
                    454:     if (val != 0)
                    455:         tgen_arithi64(s, ARITH_ADD, reg, val);
                    456: }
                    457: 
                    458: static void tcg_out_jxx(TCGContext *s, int opc, int label_index)
                    459: {
                    460:     int32_t val, val1;
                    461:     TCGLabel *l = &s->labels[label_index];
                    462:     
                    463:     if (l->has_value) {
                    464:         val = l->u.value - (tcg_target_long)s->code_ptr;
                    465:         val1 = val - 2;
                    466:         if ((int8_t)val1 == val1) {
                    467:             if (opc == -1)
                    468:                 tcg_out8(s, 0xeb);
                    469:             else
                    470:                 tcg_out8(s, 0x70 + opc);
                    471:             tcg_out8(s, val1);
                    472:         } else {
                    473:             if (opc == -1) {
                    474:                 tcg_out8(s, 0xe9);
                    475:                 tcg_out32(s, val - 5);
                    476:             } else {
                    477:                 tcg_out8(s, 0x0f);
                    478:                 tcg_out8(s, 0x80 + opc);
                    479:                 tcg_out32(s, val - 6);
                    480:             }
                    481:         }
                    482:     } else {
                    483:         if (opc == -1) {
                    484:             tcg_out8(s, 0xe9);
                    485:         } else {
                    486:             tcg_out8(s, 0x0f);
                    487:             tcg_out8(s, 0x80 + opc);
                    488:         }
                    489:         tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
                    490:         s->code_ptr += 4;
                    491:     }
                    492: }
                    493: 
                    494: static void tcg_out_brcond(TCGContext *s, int cond, 
                    495:                            TCGArg arg1, TCGArg arg2, int const_arg2,
                    496:                            int label_index, int rexw)
                    497: {
                    498:     if (const_arg2) {
                    499:         if (arg2 == 0) {
                    500:             /* test r, r */
                    501:             tcg_out_modrm(s, 0x85 | rexw, arg1, arg1);
                    502:         } else {
                    503:             if (rexw)
                    504:                 tgen_arithi64(s, ARITH_CMP, arg1, arg2);
                    505:             else
                    506:                 tgen_arithi32(s, ARITH_CMP, arg1, arg2);
                    507:         }
                    508:     } else {
                    509:         tcg_out_modrm(s, 0x01 | (ARITH_CMP << 3) | rexw, arg2, arg1);
                    510:     }
                    511:     tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index);
                    512: }
                    513: 
                    514: #if defined(CONFIG_SOFTMMU)
                    515: 
                    516: #include "../../softmmu_defs.h"
                    517: 
                    518: static void *qemu_ld_helpers[4] = {
                    519:     __ldb_mmu,
                    520:     __ldw_mmu,
                    521:     __ldl_mmu,
                    522:     __ldq_mmu,
                    523: };
                    524: 
                    525: static void *qemu_st_helpers[4] = {
                    526:     __stb_mmu,
                    527:     __stw_mmu,
                    528:     __stl_mmu,
                    529:     __stq_mmu,
                    530: };
                    531: #endif
                    532: 
                    533: static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
                    534:                             int opc)
                    535: {
                    536:     int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw;
1.1.1.3 ! root      537:     int32_t offset;
1.1       root      538: #if defined(CONFIG_SOFTMMU)
                    539:     uint8_t *label1_ptr, *label2_ptr;
                    540: #endif
                    541: 
                    542:     data_reg = *args++;
                    543:     addr_reg = *args++;
                    544:     mem_index = *args;
                    545:     s_bits = opc & 3;
                    546: 
                    547:     r0 = TCG_REG_RDI;
                    548:     r1 = TCG_REG_RSI;
                    549: 
                    550: #if TARGET_LONG_BITS == 32
                    551:     rexw = 0;
                    552: #else
                    553:     rexw = P_REXW;
                    554: #endif
                    555: #if defined(CONFIG_SOFTMMU)
                    556:     /* mov */
                    557:     tcg_out_modrm(s, 0x8b | rexw, r1, addr_reg);
                    558: 
                    559:     /* mov */
                    560:     tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
                    561:  
                    562:     tcg_out_modrm(s, 0xc1 | rexw, 5, r1); /* shr $x, r1 */
                    563:     tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); 
                    564:     
                    565:     tcg_out_modrm(s, 0x81 | rexw, 4, r0); /* andl $x, r0 */
                    566:     tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
                    567:     
                    568:     tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
                    569:     tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
                    570: 
                    571:     /* lea offset(r1, env), r1 */
                    572:     tcg_out_modrm_offset2(s, 0x8d | P_REXW, r1, r1, TCG_AREG0, 0,
                    573:                           offsetof(CPUState, tlb_table[mem_index][0].addr_read));
                    574: 
                    575:     /* cmp 0(r1), r0 */
                    576:     tcg_out_modrm_offset(s, 0x3b | rexw, r0, r1, 0);
                    577:     
                    578:     /* mov */
                    579:     tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
                    580:     
                    581:     /* je label1 */
                    582:     tcg_out8(s, 0x70 + JCC_JE);
                    583:     label1_ptr = s->code_ptr;
                    584:     s->code_ptr++;
                    585: 
                    586:     /* XXX: move that code at the end of the TB */
                    587:     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RSI, mem_index);
1.1.1.3 ! root      588:     tcg_out_goto(s, 1, qemu_ld_helpers[s_bits]);
1.1       root      589: 
                    590:     switch(opc) {
                    591:     case 0 | 4:
                    592:         /* movsbq */
                    593:         tcg_out_modrm(s, 0xbe | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
                    594:         break;
                    595:     case 1 | 4:
                    596:         /* movswq */
                    597:         tcg_out_modrm(s, 0xbf | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
                    598:         break;
                    599:     case 2 | 4:
                    600:         /* movslq */
                    601:         tcg_out_modrm(s, 0x63 | P_REXW, data_reg, TCG_REG_RAX);
                    602:         break;
                    603:     case 0:
                    604:         /* movzbq */
                    605:         tcg_out_modrm(s, 0xb6 | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
                    606:         break;
                    607:     case 1:
                    608:         /* movzwq */
                    609:         tcg_out_modrm(s, 0xb7 | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
                    610:         break;
                    611:     case 2:
                    612:     default:
                    613:         /* movl */
                    614:         tcg_out_modrm(s, 0x8b, data_reg, TCG_REG_RAX);
                    615:         break;
                    616:     case 3:
                    617:         tcg_out_mov(s, data_reg, TCG_REG_RAX);
                    618:         break;
                    619:     }
                    620: 
                    621:     /* jmp label2 */
                    622:     tcg_out8(s, 0xeb);
                    623:     label2_ptr = s->code_ptr;
                    624:     s->code_ptr++;
                    625:     
                    626:     /* label1: */
                    627:     *label1_ptr = s->code_ptr - label1_ptr - 1;
                    628: 
                    629:     /* add x(r1), r0 */
                    630:     tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - 
                    631:                          offsetof(CPUTLBEntry, addr_read));
1.1.1.3 ! root      632:     offset = 0;
1.1       root      633: #else
1.1.1.3 ! root      634:     if (GUEST_BASE == (int32_t)GUEST_BASE) {
        !           635:         r0 = addr_reg;
        !           636:         offset = GUEST_BASE;
        !           637:     } else {
        !           638:         offset = 0;
        !           639:         /* movq $GUEST_BASE, r0 */
        !           640:         tcg_out_opc(s, (0xb8 + (r0 & 7)) | P_REXW, 0, r0, 0);
        !           641:         tcg_out32(s, GUEST_BASE);
        !           642:         tcg_out32(s, GUEST_BASE >> 32);
        !           643:         /* addq addr_reg, r0 */
        !           644:         tcg_out_modrm(s, 0x01 | P_REXW, addr_reg, r0);
        !           645:     }
1.1       root      646: #endif    
                    647: 
                    648: #ifdef TARGET_WORDS_BIGENDIAN
                    649:     bswap = 1;
                    650: #else
                    651:     bswap = 0;
                    652: #endif
                    653:     switch(opc) {
                    654:     case 0:
                    655:         /* movzbl */
1.1.1.3 ! root      656:         tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, offset);
1.1       root      657:         break;
                    658:     case 0 | 4:
                    659:         /* movsbX */
1.1.1.3 ! root      660:         tcg_out_modrm_offset(s, 0xbe | P_EXT | rexw, data_reg, r0, offset);
1.1       root      661:         break;
                    662:     case 1:
                    663:         /* movzwl */
1.1.1.3 ! root      664:         tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, offset);
1.1       root      665:         if (bswap) {
                    666:             /* rolw $8, data_reg */
                    667:             tcg_out8(s, 0x66); 
                    668:             tcg_out_modrm(s, 0xc1, 0, data_reg);
                    669:             tcg_out8(s, 8);
                    670:         }
                    671:         break;
                    672:     case 1 | 4:
                    673:         if (bswap) {
                    674:             /* movzwl */
1.1.1.3 ! root      675:             tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, offset);
1.1       root      676:             /* rolw $8, data_reg */
                    677:             tcg_out8(s, 0x66); 
                    678:             tcg_out_modrm(s, 0xc1, 0, data_reg);
                    679:             tcg_out8(s, 8);
                    680: 
                    681:             /* movswX data_reg, data_reg */
                    682:             tcg_out_modrm(s, 0xbf | P_EXT | rexw, data_reg, data_reg);
                    683:         } else {
                    684:             /* movswX */
1.1.1.3 ! root      685:             tcg_out_modrm_offset(s, 0xbf | P_EXT | rexw, data_reg, r0, offset);
1.1       root      686:         }
                    687:         break;
                    688:     case 2:
                    689:         /* movl (r0), data_reg */
1.1.1.3 ! root      690:         tcg_out_modrm_offset(s, 0x8b, data_reg, r0, offset);
1.1       root      691:         if (bswap) {
                    692:             /* bswap */
                    693:             tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0);
                    694:         }
                    695:         break;
                    696:     case 2 | 4:
                    697:         if (bswap) {
                    698:             /* movl (r0), data_reg */
1.1.1.3 ! root      699:             tcg_out_modrm_offset(s, 0x8b, data_reg, r0, offset);
1.1       root      700:             /* bswap */
                    701:             tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0);
                    702:             /* movslq */
                    703:             tcg_out_modrm(s, 0x63 | P_REXW, data_reg, data_reg);
                    704:         } else {
                    705:             /* movslq */
1.1.1.3 ! root      706:             tcg_out_modrm_offset(s, 0x63 | P_REXW, data_reg, r0, offset);
1.1       root      707:         }
                    708:         break;
                    709:     case 3:
                    710:         /* movq (r0), data_reg */
1.1.1.3 ! root      711:         tcg_out_modrm_offset(s, 0x8b | P_REXW, data_reg, r0, offset);
1.1       root      712:         if (bswap) {
                    713:             /* bswap */
                    714:             tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT | P_REXW, 0, data_reg, 0);
                    715:         }
                    716:         break;
                    717:     default:
                    718:         tcg_abort();
                    719:     }
                    720: 
                    721: #if defined(CONFIG_SOFTMMU)
                    722:     /* label2: */
                    723:     *label2_ptr = s->code_ptr - label2_ptr - 1;
                    724: #endif
                    725: }
                    726: 
                    727: static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
                    728:                             int opc)
                    729: {
                    730:     int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw;
1.1.1.3 ! root      731:     int32_t offset;
1.1       root      732: #if defined(CONFIG_SOFTMMU)
                    733:     uint8_t *label1_ptr, *label2_ptr;
                    734: #endif
                    735: 
                    736:     data_reg = *args++;
                    737:     addr_reg = *args++;
                    738:     mem_index = *args;
                    739: 
                    740:     s_bits = opc;
                    741: 
                    742:     r0 = TCG_REG_RDI;
                    743:     r1 = TCG_REG_RSI;
                    744: 
                    745: #if TARGET_LONG_BITS == 32
                    746:     rexw = 0;
                    747: #else
                    748:     rexw = P_REXW;
                    749: #endif
                    750: #if defined(CONFIG_SOFTMMU)
                    751:     /* mov */
                    752:     tcg_out_modrm(s, 0x8b | rexw, r1, addr_reg);
                    753: 
                    754:     /* mov */
                    755:     tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
                    756:  
                    757:     tcg_out_modrm(s, 0xc1 | rexw, 5, r1); /* shr $x, r1 */
                    758:     tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); 
                    759:     
                    760:     tcg_out_modrm(s, 0x81 | rexw, 4, r0); /* andl $x, r0 */
                    761:     tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
                    762:     
                    763:     tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
                    764:     tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
                    765: 
                    766:     /* lea offset(r1, env), r1 */
                    767:     tcg_out_modrm_offset2(s, 0x8d | P_REXW, r1, r1, TCG_AREG0, 0,
                    768:                           offsetof(CPUState, tlb_table[mem_index][0].addr_write));
                    769: 
                    770:     /* cmp 0(r1), r0 */
                    771:     tcg_out_modrm_offset(s, 0x3b | rexw, r0, r1, 0);
                    772:     
                    773:     /* mov */
                    774:     tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
                    775:     
                    776:     /* je label1 */
                    777:     tcg_out8(s, 0x70 + JCC_JE);
                    778:     label1_ptr = s->code_ptr;
                    779:     s->code_ptr++;
                    780: 
                    781:     /* XXX: move that code at the end of the TB */
                    782:     switch(opc) {
                    783:     case 0:
                    784:         /* movzbl */
                    785:         tcg_out_modrm(s, 0xb6 | P_EXT | P_REXB, TCG_REG_RSI, data_reg);
                    786:         break;
                    787:     case 1:
                    788:         /* movzwl */
                    789:         tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_RSI, data_reg);
                    790:         break;
                    791:     case 2:
                    792:         /* movl */
                    793:         tcg_out_modrm(s, 0x8b, TCG_REG_RSI, data_reg);
                    794:         break;
                    795:     default:
                    796:     case 3:
                    797:         tcg_out_mov(s, TCG_REG_RSI, data_reg);
                    798:         break;
                    799:     }
                    800:     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
1.1.1.3 ! root      801:     tcg_out_goto(s, 1, qemu_st_helpers[s_bits]);
1.1       root      802: 
                    803:     /* jmp label2 */
                    804:     tcg_out8(s, 0xeb);
                    805:     label2_ptr = s->code_ptr;
                    806:     s->code_ptr++;
                    807:     
                    808:     /* label1: */
                    809:     *label1_ptr = s->code_ptr - label1_ptr - 1;
                    810: 
                    811:     /* add x(r1), r0 */
                    812:     tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - 
                    813:                          offsetof(CPUTLBEntry, addr_write));
1.1.1.3 ! root      814:     offset = 0;
1.1       root      815: #else
1.1.1.3 ! root      816:     if (GUEST_BASE == (int32_t)GUEST_BASE) {
        !           817:         r0 = addr_reg;
        !           818:         offset = GUEST_BASE;
        !           819:     } else {
        !           820:         offset = 0;
        !           821:         /* movq $GUEST_BASE, r0 */
        !           822:         tcg_out_opc(s, (0xb8 + (r0 & 7)) | P_REXW, 0, r0, 0);
        !           823:         tcg_out32(s, GUEST_BASE);
        !           824:         tcg_out32(s, GUEST_BASE >> 32);
        !           825:         /* addq addr_reg, r0 */
        !           826:         tcg_out_modrm(s, 0x01 | P_REXW, addr_reg, r0);
        !           827:     }
1.1       root      828: #endif
                    829: 
                    830: #ifdef TARGET_WORDS_BIGENDIAN
                    831:     bswap = 1;
                    832: #else
                    833:     bswap = 0;
                    834: #endif
                    835:     switch(opc) {
                    836:     case 0:
                    837:         /* movb */
1.1.1.3 ! root      838:         tcg_out_modrm_offset(s, 0x88 | P_REXB, data_reg, r0, offset);
1.1       root      839:         break;
                    840:     case 1:
                    841:         if (bswap) {
                    842:             tcg_out_modrm(s, 0x8b, r1, data_reg); /* movl */
                    843:             tcg_out8(s, 0x66); /* rolw $8, %ecx */
                    844:             tcg_out_modrm(s, 0xc1, 0, r1);
                    845:             tcg_out8(s, 8);
                    846:             data_reg = r1;
                    847:         }
                    848:         /* movw */
                    849:         tcg_out8(s, 0x66);
1.1.1.3 ! root      850:         tcg_out_modrm_offset(s, 0x89, data_reg, r0, offset);
1.1       root      851:         break;
                    852:     case 2:
                    853:         if (bswap) {
                    854:             tcg_out_modrm(s, 0x8b, r1, data_reg); /* movl */
                    855:             /* bswap data_reg */
                    856:             tcg_out_opc(s, (0xc8 + r1) | P_EXT, 0, r1, 0);
                    857:             data_reg = r1;
                    858:         }
                    859:         /* movl */
1.1.1.3 ! root      860:         tcg_out_modrm_offset(s, 0x89, data_reg, r0, offset);
1.1       root      861:         break;
                    862:     case 3:
                    863:         if (bswap) {
                    864:             tcg_out_mov(s, r1, data_reg);
                    865:             /* bswap data_reg */
                    866:             tcg_out_opc(s, (0xc8 + r1) | P_EXT | P_REXW, 0, r1, 0);
                    867:             data_reg = r1;
                    868:         }
                    869:         /* movq */
1.1.1.3 ! root      870:         tcg_out_modrm_offset(s, 0x89 | P_REXW, data_reg, r0, offset);
1.1       root      871:         break;
                    872:     default:
                    873:         tcg_abort();
                    874:     }
                    875: 
                    876: #if defined(CONFIG_SOFTMMU)
                    877:     /* label2: */
                    878:     *label2_ptr = s->code_ptr - label2_ptr - 1;
                    879: #endif
                    880: }
                    881: 
                    882: static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
                    883:                               const int *const_args)
                    884: {
                    885:     int c;
                    886:     
                    887:     switch(opc) {
                    888:     case INDEX_op_exit_tb:
                    889:         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RAX, args[0]);
1.1.1.3 ! root      890:         tcg_out_goto(s, 0, tb_ret_addr);
1.1       root      891:         break;
                    892:     case INDEX_op_goto_tb:
                    893:         if (s->tb_jmp_offset) {
                    894:             /* direct jump method */
                    895:             tcg_out8(s, 0xe9); /* jmp im */
                    896:             s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
                    897:             tcg_out32(s, 0);
                    898:         } else {
                    899:             /* indirect jump method */
                    900:             /* jmp Ev */
                    901:             tcg_out_modrm_offset(s, 0xff, 4, -1, 
                    902:                                  (tcg_target_long)(s->tb_next + 
                    903:                                                    args[0]));
                    904:         }
                    905:         s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
                    906:         break;
                    907:     case INDEX_op_call:
                    908:         if (const_args[0]) {
1.1.1.3 ! root      909:             tcg_out_goto(s, 1, (void *) args[0]);
1.1       root      910:         } else {
                    911:             tcg_out_modrm(s, 0xff, 2, args[0]);
                    912:         }
                    913:         break;
                    914:     case INDEX_op_jmp:
                    915:         if (const_args[0]) {
1.1.1.3 ! root      916:             tcg_out_goto(s, 0, (void *) args[0]);
1.1       root      917:         } else {
                    918:             tcg_out_modrm(s, 0xff, 4, args[0]);
                    919:         }
                    920:         break;
                    921:     case INDEX_op_br:
                    922:         tcg_out_jxx(s, JCC_JMP, args[0]);
                    923:         break;
                    924:     case INDEX_op_movi_i32:
                    925:         tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]);
                    926:         break;
                    927:     case INDEX_op_movi_i64:
                    928:         tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
                    929:         break;
                    930:     case INDEX_op_ld8u_i32:
                    931:     case INDEX_op_ld8u_i64:
                    932:         /* movzbl */
                    933:         tcg_out_modrm_offset(s, 0xb6 | P_EXT, args[0], args[1], args[2]);
                    934:         break;
                    935:     case INDEX_op_ld8s_i32:
                    936:         /* movsbl */
                    937:         tcg_out_modrm_offset(s, 0xbe | P_EXT, args[0], args[1], args[2]);
                    938:         break;
                    939:     case INDEX_op_ld8s_i64:
                    940:         /* movsbq */
                    941:         tcg_out_modrm_offset(s, 0xbe | P_EXT | P_REXW, args[0], args[1], args[2]);
                    942:         break;
                    943:     case INDEX_op_ld16u_i32:
                    944:     case INDEX_op_ld16u_i64:
                    945:         /* movzwl */
                    946:         tcg_out_modrm_offset(s, 0xb7 | P_EXT, args[0], args[1], args[2]);
                    947:         break;
                    948:     case INDEX_op_ld16s_i32:
                    949:         /* movswl */
                    950:         tcg_out_modrm_offset(s, 0xbf | P_EXT, args[0], args[1], args[2]);
                    951:         break;
                    952:     case INDEX_op_ld16s_i64:
                    953:         /* movswq */
                    954:         tcg_out_modrm_offset(s, 0xbf | P_EXT | P_REXW, args[0], args[1], args[2]);
                    955:         break;
                    956:     case INDEX_op_ld_i32:
                    957:     case INDEX_op_ld32u_i64:
                    958:         /* movl */
                    959:         tcg_out_modrm_offset(s, 0x8b, args[0], args[1], args[2]);
                    960:         break;
                    961:     case INDEX_op_ld32s_i64:
                    962:         /* movslq */
                    963:         tcg_out_modrm_offset(s, 0x63 | P_REXW, args[0], args[1], args[2]);
                    964:         break;
                    965:     case INDEX_op_ld_i64:
                    966:         /* movq */
                    967:         tcg_out_modrm_offset(s, 0x8b | P_REXW, args[0], args[1], args[2]);
                    968:         break;
                    969:         
                    970:     case INDEX_op_st8_i32:
                    971:     case INDEX_op_st8_i64:
                    972:         /* movb */
                    973:         tcg_out_modrm_offset(s, 0x88 | P_REXB, args[0], args[1], args[2]);
                    974:         break;
                    975:     case INDEX_op_st16_i32:
                    976:     case INDEX_op_st16_i64:
                    977:         /* movw */
                    978:         tcg_out8(s, 0x66);
                    979:         tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
                    980:         break;
                    981:     case INDEX_op_st_i32:
                    982:     case INDEX_op_st32_i64:
                    983:         /* movl */
                    984:         tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
                    985:         break;
                    986:     case INDEX_op_st_i64:
                    987:         /* movq */
                    988:         tcg_out_modrm_offset(s, 0x89 | P_REXW, args[0], args[1], args[2]);
                    989:         break;
                    990: 
                    991:     case INDEX_op_sub_i32:
                    992:         c = ARITH_SUB;
                    993:         goto gen_arith32;
                    994:     case INDEX_op_and_i32:
                    995:         c = ARITH_AND;
                    996:         goto gen_arith32;
                    997:     case INDEX_op_or_i32:
                    998:         c = ARITH_OR;
                    999:         goto gen_arith32;
                   1000:     case INDEX_op_xor_i32:
                   1001:         c = ARITH_XOR;
                   1002:         goto gen_arith32;
                   1003:     case INDEX_op_add_i32:
                   1004:         c = ARITH_ADD;
                   1005:     gen_arith32:
                   1006:         if (const_args[2]) {
                   1007:             tgen_arithi32(s, c, args[0], args[2]);
                   1008:         } else {
                   1009:             tcg_out_modrm(s, 0x01 | (c << 3), args[2], args[0]);
                   1010:         }
                   1011:         break;
                   1012: 
                   1013:     case INDEX_op_sub_i64:
                   1014:         c = ARITH_SUB;
                   1015:         goto gen_arith64;
                   1016:     case INDEX_op_and_i64:
                   1017:         c = ARITH_AND;
                   1018:         goto gen_arith64;
                   1019:     case INDEX_op_or_i64:
                   1020:         c = ARITH_OR;
                   1021:         goto gen_arith64;
                   1022:     case INDEX_op_xor_i64:
                   1023:         c = ARITH_XOR;
                   1024:         goto gen_arith64;
                   1025:     case INDEX_op_add_i64:
                   1026:         c = ARITH_ADD;
                   1027:     gen_arith64:
                   1028:         if (const_args[2]) {
                   1029:             tgen_arithi64(s, c, args[0], args[2]);
                   1030:         } else {
                   1031:             tcg_out_modrm(s, 0x01 | (c << 3) | P_REXW, args[2], args[0]);
                   1032:         }
                   1033:         break;
                   1034: 
                   1035:     case INDEX_op_mul_i32:
                   1036:         if (const_args[2]) {
                   1037:             int32_t val;
                   1038:             val = args[2];
                   1039:             if (val == (int8_t)val) {
                   1040:                 tcg_out_modrm(s, 0x6b, args[0], args[0]);
                   1041:                 tcg_out8(s, val);
                   1042:             } else {
                   1043:                 tcg_out_modrm(s, 0x69, args[0], args[0]);
                   1044:                 tcg_out32(s, val);
                   1045:             }
                   1046:         } else {
                   1047:             tcg_out_modrm(s, 0xaf | P_EXT, args[0], args[2]);
                   1048:         }
                   1049:         break;
                   1050:     case INDEX_op_mul_i64:
                   1051:         if (const_args[2]) {
                   1052:             int32_t val;
                   1053:             val = args[2];
                   1054:             if (val == (int8_t)val) {
                   1055:                 tcg_out_modrm(s, 0x6b | P_REXW, args[0], args[0]);
                   1056:                 tcg_out8(s, val);
                   1057:             } else {
                   1058:                 tcg_out_modrm(s, 0x69 | P_REXW, args[0], args[0]);
                   1059:                 tcg_out32(s, val);
                   1060:             }
                   1061:         } else {
                   1062:             tcg_out_modrm(s, 0xaf | P_EXT | P_REXW, args[0], args[2]);
                   1063:         }
                   1064:         break;
                   1065:     case INDEX_op_div2_i32:
                   1066:         tcg_out_modrm(s, 0xf7, 7, args[4]);
                   1067:         break;
                   1068:     case INDEX_op_divu2_i32:
                   1069:         tcg_out_modrm(s, 0xf7, 6, args[4]);
                   1070:         break;
                   1071:     case INDEX_op_div2_i64:
                   1072:         tcg_out_modrm(s, 0xf7 | P_REXW, 7, args[4]);
                   1073:         break;
                   1074:     case INDEX_op_divu2_i64:
                   1075:         tcg_out_modrm(s, 0xf7 | P_REXW, 6, args[4]);
                   1076:         break;
                   1077: 
                   1078:     case INDEX_op_shl_i32:
                   1079:         c = SHIFT_SHL;
                   1080:     gen_shift32:
                   1081:         if (const_args[2]) {
                   1082:             if (args[2] == 1) {
                   1083:                 tcg_out_modrm(s, 0xd1, c, args[0]);
                   1084:             } else {
                   1085:                 tcg_out_modrm(s, 0xc1, c, args[0]);
                   1086:                 tcg_out8(s, args[2]);
                   1087:             }
                   1088:         } else {
                   1089:             tcg_out_modrm(s, 0xd3, c, args[0]);
                   1090:         }
                   1091:         break;
                   1092:     case INDEX_op_shr_i32:
                   1093:         c = SHIFT_SHR;
                   1094:         goto gen_shift32;
                   1095:     case INDEX_op_sar_i32:
                   1096:         c = SHIFT_SAR;
                   1097:         goto gen_shift32;
1.1.1.2   root     1098:     case INDEX_op_rotl_i32:
                   1099:         c = SHIFT_ROL;
                   1100:         goto gen_shift32;
                   1101:     case INDEX_op_rotr_i32:
                   1102:         c = SHIFT_ROR;
                   1103:         goto gen_shift32;
                   1104: 
1.1       root     1105:     case INDEX_op_shl_i64:
                   1106:         c = SHIFT_SHL;
                   1107:     gen_shift64:
                   1108:         if (const_args[2]) {
                   1109:             if (args[2] == 1) {
                   1110:                 tcg_out_modrm(s, 0xd1 | P_REXW, c, args[0]);
                   1111:             } else {
                   1112:                 tcg_out_modrm(s, 0xc1 | P_REXW, c, args[0]);
                   1113:                 tcg_out8(s, args[2]);
                   1114:             }
                   1115:         } else {
                   1116:             tcg_out_modrm(s, 0xd3 | P_REXW, c, args[0]);
                   1117:         }
                   1118:         break;
                   1119:     case INDEX_op_shr_i64:
                   1120:         c = SHIFT_SHR;
                   1121:         goto gen_shift64;
                   1122:     case INDEX_op_sar_i64:
                   1123:         c = SHIFT_SAR;
                   1124:         goto gen_shift64;
1.1.1.2   root     1125:     case INDEX_op_rotl_i64:
                   1126:         c = SHIFT_ROL;
                   1127:         goto gen_shift64;
                   1128:     case INDEX_op_rotr_i64:
                   1129:         c = SHIFT_ROR;
                   1130:         goto gen_shift64;
                   1131: 
1.1       root     1132:     case INDEX_op_brcond_i32:
                   1133:         tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], 
                   1134:                        args[3], 0);
                   1135:         break;
                   1136:     case INDEX_op_brcond_i64:
                   1137:         tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], 
                   1138:                        args[3], P_REXW);
                   1139:         break;
                   1140: 
1.1.1.2   root     1141:     case INDEX_op_bswap16_i32:
                   1142:     case INDEX_op_bswap16_i64:
                   1143:         tcg_out8(s, 0x66);
                   1144:         tcg_out_modrm(s, 0xc1, SHIFT_ROL, args[0]);
                   1145:         tcg_out8(s, 8);
                   1146:         break;
                   1147:     case INDEX_op_bswap32_i32:
                   1148:     case INDEX_op_bswap32_i64:
1.1       root     1149:         tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT, 0, args[0], 0);
                   1150:         break;
1.1.1.2   root     1151:     case INDEX_op_bswap64_i64:
1.1       root     1152:         tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT | P_REXW, 0, args[0], 0);
                   1153:         break;
                   1154: 
                   1155:     case INDEX_op_neg_i32:
                   1156:         tcg_out_modrm(s, 0xf7, 3, args[0]);
                   1157:         break;
                   1158:     case INDEX_op_neg_i64:
                   1159:         tcg_out_modrm(s, 0xf7 | P_REXW, 3, args[0]);
                   1160:         break;
                   1161: 
1.1.1.2   root     1162:     case INDEX_op_not_i32:
                   1163:         tcg_out_modrm(s, 0xf7, 2, args[0]);
                   1164:         break;
                   1165:     case INDEX_op_not_i64:
                   1166:         tcg_out_modrm(s, 0xf7 | P_REXW, 2, args[0]);
                   1167:         break;
                   1168: 
1.1       root     1169:     case INDEX_op_ext8s_i32:
                   1170:         tcg_out_modrm(s, 0xbe | P_EXT | P_REXB, args[0], args[1]);
                   1171:         break;
                   1172:     case INDEX_op_ext16s_i32:
                   1173:         tcg_out_modrm(s, 0xbf | P_EXT, args[0], args[1]);
                   1174:         break;
                   1175:     case INDEX_op_ext8s_i64:
                   1176:         tcg_out_modrm(s, 0xbe | P_EXT | P_REXW, args[0], args[1]);
                   1177:         break;
                   1178:     case INDEX_op_ext16s_i64:
                   1179:         tcg_out_modrm(s, 0xbf | P_EXT | P_REXW, args[0], args[1]);
                   1180:         break;
                   1181:     case INDEX_op_ext32s_i64:
                   1182:         tcg_out_modrm(s, 0x63 | P_REXW, args[0], args[1]);
                   1183:         break;
1.1.1.3 ! root     1184:     case INDEX_op_ext8u_i32:
        !          1185:         tcg_out_modrm(s, 0xb6 | P_EXT | P_REXB, args[0], args[1]);
        !          1186:         break;
        !          1187:     case INDEX_op_ext16u_i32:
        !          1188:         tcg_out_modrm(s, 0xb7 | P_EXT, args[0], args[1]);
        !          1189:         break;
        !          1190:     case INDEX_op_ext8u_i64:
        !          1191:         tcg_out_modrm(s, 0xb6 | P_EXT | P_REXW, args[0], args[1]);
        !          1192:         break;
        !          1193:     case INDEX_op_ext16u_i64:
        !          1194:         tcg_out_modrm(s, 0xb7 | P_EXT | P_REXW, args[0], args[1]);
        !          1195:         break;
        !          1196:     case INDEX_op_ext32u_i64:
        !          1197:         tcg_out_modrm(s, 0x8b, args[0], args[1]);
        !          1198:         break;
1.1       root     1199: 
                   1200:     case INDEX_op_qemu_ld8u:
                   1201:         tcg_out_qemu_ld(s, args, 0);
                   1202:         break;
                   1203:     case INDEX_op_qemu_ld8s:
                   1204:         tcg_out_qemu_ld(s, args, 0 | 4);
                   1205:         break;
                   1206:     case INDEX_op_qemu_ld16u:
                   1207:         tcg_out_qemu_ld(s, args, 1);
                   1208:         break;
                   1209:     case INDEX_op_qemu_ld16s:
                   1210:         tcg_out_qemu_ld(s, args, 1 | 4);
                   1211:         break;
                   1212:     case INDEX_op_qemu_ld32u:
                   1213:         tcg_out_qemu_ld(s, args, 2);
                   1214:         break;
                   1215:     case INDEX_op_qemu_ld32s:
                   1216:         tcg_out_qemu_ld(s, args, 2 | 4);
                   1217:         break;
                   1218:     case INDEX_op_qemu_ld64:
                   1219:         tcg_out_qemu_ld(s, args, 3);
                   1220:         break;
                   1221:         
                   1222:     case INDEX_op_qemu_st8:
                   1223:         tcg_out_qemu_st(s, args, 0);
                   1224:         break;
                   1225:     case INDEX_op_qemu_st16:
                   1226:         tcg_out_qemu_st(s, args, 1);
                   1227:         break;
                   1228:     case INDEX_op_qemu_st32:
                   1229:         tcg_out_qemu_st(s, args, 2);
                   1230:         break;
                   1231:     case INDEX_op_qemu_st64:
                   1232:         tcg_out_qemu_st(s, args, 3);
                   1233:         break;
                   1234: 
                   1235:     default:
                   1236:         tcg_abort();
                   1237:     }
                   1238: }
                   1239: 
                   1240: static int tcg_target_callee_save_regs[] = {
                   1241:     TCG_REG_RBP,
                   1242:     TCG_REG_RBX,
                   1243:     TCG_REG_R12,
                   1244:     TCG_REG_R13,
                   1245:     /*    TCG_REG_R14, */ /* currently used for the global env, so no
                   1246:                              need to save */
                   1247:     TCG_REG_R15,
                   1248: };
                   1249: 
                   1250: static inline void tcg_out_push(TCGContext *s, int reg)
                   1251: {
                   1252:     tcg_out_opc(s, (0x50 + (reg & 7)), 0, reg, 0);
                   1253: }
                   1254: 
                   1255: static inline void tcg_out_pop(TCGContext *s, int reg)
                   1256: {
                   1257:     tcg_out_opc(s, (0x58 + (reg & 7)), 0, reg, 0);
                   1258: }
                   1259: 
                   1260: /* Generate global QEMU prologue and epilogue code */
                   1261: void tcg_target_qemu_prologue(TCGContext *s)
                   1262: {
                   1263:     int i, frame_size, push_size, stack_addend;
                   1264: 
                   1265:     /* TB prologue */
                   1266:     /* save all callee saved registers */
                   1267:     for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
                   1268:         tcg_out_push(s, tcg_target_callee_save_regs[i]);
                   1269: 
                   1270:     }
                   1271:     /* reserve some stack space */
                   1272:     push_size = 8 + ARRAY_SIZE(tcg_target_callee_save_regs) * 8;
                   1273:     frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
                   1274:     frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & 
                   1275:         ~(TCG_TARGET_STACK_ALIGN - 1);
                   1276:     stack_addend = frame_size - push_size;
                   1277:     tcg_out_addi(s, TCG_REG_RSP, -stack_addend);
                   1278: 
                   1279:     tcg_out_modrm(s, 0xff, 4, TCG_REG_RDI); /* jmp *%rdi */
                   1280:     
                   1281:     /* TB epilogue */
                   1282:     tb_ret_addr = s->code_ptr;
                   1283:     tcg_out_addi(s, TCG_REG_RSP, stack_addend);
                   1284:     for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
                   1285:         tcg_out_pop(s, tcg_target_callee_save_regs[i]);
                   1286:     }
                   1287:     tcg_out8(s, 0xc3); /* ret */
                   1288: }
                   1289: 
                   1290: static const TCGTargetOpDef x86_64_op_defs[] = {
                   1291:     { INDEX_op_exit_tb, { } },
                   1292:     { INDEX_op_goto_tb, { } },
                   1293:     { INDEX_op_call, { "ri" } }, /* XXX: might need a specific constant constraint */
                   1294:     { INDEX_op_jmp, { "ri" } }, /* XXX: might need a specific constant constraint */
                   1295:     { INDEX_op_br, { } },
                   1296: 
                   1297:     { INDEX_op_mov_i32, { "r", "r" } },
                   1298:     { INDEX_op_movi_i32, { "r" } },
                   1299:     { INDEX_op_ld8u_i32, { "r", "r" } },
                   1300:     { INDEX_op_ld8s_i32, { "r", "r" } },
                   1301:     { INDEX_op_ld16u_i32, { "r", "r" } },
                   1302:     { INDEX_op_ld16s_i32, { "r", "r" } },
                   1303:     { INDEX_op_ld_i32, { "r", "r" } },
                   1304:     { INDEX_op_st8_i32, { "r", "r" } },
                   1305:     { INDEX_op_st16_i32, { "r", "r" } },
                   1306:     { INDEX_op_st_i32, { "r", "r" } },
                   1307: 
                   1308:     { INDEX_op_add_i32, { "r", "0", "ri" } },
                   1309:     { INDEX_op_mul_i32, { "r", "0", "ri" } },
                   1310:     { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
                   1311:     { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
                   1312:     { INDEX_op_sub_i32, { "r", "0", "ri" } },
                   1313:     { INDEX_op_and_i32, { "r", "0", "ri" } },
                   1314:     { INDEX_op_or_i32, { "r", "0", "ri" } },
                   1315:     { INDEX_op_xor_i32, { "r", "0", "ri" } },
                   1316: 
                   1317:     { INDEX_op_shl_i32, { "r", "0", "ci" } },
                   1318:     { INDEX_op_shr_i32, { "r", "0", "ci" } },
                   1319:     { INDEX_op_sar_i32, { "r", "0", "ci" } },
1.1.1.2   root     1320:     { INDEX_op_rotl_i32, { "r", "0", "ci" } },
                   1321:     { INDEX_op_rotr_i32, { "r", "0", "ci" } },
1.1       root     1322: 
                   1323:     { INDEX_op_brcond_i32, { "r", "ri" } },
                   1324: 
                   1325:     { INDEX_op_mov_i64, { "r", "r" } },
                   1326:     { INDEX_op_movi_i64, { "r" } },
                   1327:     { INDEX_op_ld8u_i64, { "r", "r" } },
                   1328:     { INDEX_op_ld8s_i64, { "r", "r" } },
                   1329:     { INDEX_op_ld16u_i64, { "r", "r" } },
                   1330:     { INDEX_op_ld16s_i64, { "r", "r" } },
                   1331:     { INDEX_op_ld32u_i64, { "r", "r" } },
                   1332:     { INDEX_op_ld32s_i64, { "r", "r" } },
                   1333:     { INDEX_op_ld_i64, { "r", "r" } },
                   1334:     { INDEX_op_st8_i64, { "r", "r" } },
                   1335:     { INDEX_op_st16_i64, { "r", "r" } },
                   1336:     { INDEX_op_st32_i64, { "r", "r" } },
                   1337:     { INDEX_op_st_i64, { "r", "r" } },
                   1338: 
                   1339:     { INDEX_op_add_i64, { "r", "0", "re" } },
                   1340:     { INDEX_op_mul_i64, { "r", "0", "re" } },
                   1341:     { INDEX_op_div2_i64, { "a", "d", "0", "1", "r" } },
                   1342:     { INDEX_op_divu2_i64, { "a", "d", "0", "1", "r" } },
                   1343:     { INDEX_op_sub_i64, { "r", "0", "re" } },
                   1344:     { INDEX_op_and_i64, { "r", "0", "reZ" } },
                   1345:     { INDEX_op_or_i64, { "r", "0", "re" } },
                   1346:     { INDEX_op_xor_i64, { "r", "0", "re" } },
                   1347: 
                   1348:     { INDEX_op_shl_i64, { "r", "0", "ci" } },
                   1349:     { INDEX_op_shr_i64, { "r", "0", "ci" } },
                   1350:     { INDEX_op_sar_i64, { "r", "0", "ci" } },
1.1.1.2   root     1351:     { INDEX_op_rotl_i64, { "r", "0", "ci" } },
                   1352:     { INDEX_op_rotr_i64, { "r", "0", "ci" } },
1.1       root     1353: 
                   1354:     { INDEX_op_brcond_i64, { "r", "re" } },
                   1355: 
1.1.1.2   root     1356:     { INDEX_op_bswap16_i32, { "r", "0" } },
                   1357:     { INDEX_op_bswap16_i64, { "r", "0" } },
                   1358:     { INDEX_op_bswap32_i32, { "r", "0" } },
                   1359:     { INDEX_op_bswap32_i64, { "r", "0" } },
                   1360:     { INDEX_op_bswap64_i64, { "r", "0" } },
1.1       root     1361: 
                   1362:     { INDEX_op_neg_i32, { "r", "0" } },
                   1363:     { INDEX_op_neg_i64, { "r", "0" } },
                   1364: 
1.1.1.2   root     1365:     { INDEX_op_not_i32, { "r", "0" } },
                   1366:     { INDEX_op_not_i64, { "r", "0" } },
                   1367: 
1.1       root     1368:     { INDEX_op_ext8s_i32, { "r", "r"} },
                   1369:     { INDEX_op_ext16s_i32, { "r", "r"} },
                   1370:     { INDEX_op_ext8s_i64, { "r", "r"} },
                   1371:     { INDEX_op_ext16s_i64, { "r", "r"} },
                   1372:     { INDEX_op_ext32s_i64, { "r", "r"} },
1.1.1.3 ! root     1373:     { INDEX_op_ext8u_i32, { "r", "r"} },
        !          1374:     { INDEX_op_ext16u_i32, { "r", "r"} },
        !          1375:     { INDEX_op_ext8u_i64, { "r", "r"} },
        !          1376:     { INDEX_op_ext16u_i64, { "r", "r"} },
        !          1377:     { INDEX_op_ext32u_i64, { "r", "r"} },
1.1       root     1378: 
                   1379:     { INDEX_op_qemu_ld8u, { "r", "L" } },
                   1380:     { INDEX_op_qemu_ld8s, { "r", "L" } },
                   1381:     { INDEX_op_qemu_ld16u, { "r", "L" } },
                   1382:     { INDEX_op_qemu_ld16s, { "r", "L" } },
                   1383:     { INDEX_op_qemu_ld32u, { "r", "L" } },
                   1384:     { INDEX_op_qemu_ld32s, { "r", "L" } },
                   1385:     { INDEX_op_qemu_ld64, { "r", "L" } },
                   1386: 
                   1387:     { INDEX_op_qemu_st8, { "L", "L" } },
                   1388:     { INDEX_op_qemu_st16, { "L", "L" } },
                   1389:     { INDEX_op_qemu_st32, { "L", "L" } },
1.1.1.3 ! root     1390:     { INDEX_op_qemu_st64, { "L", "L" } },
1.1       root     1391: 
                   1392:     { -1 },
                   1393: };
                   1394: 
                   1395: void tcg_target_init(TCGContext *s)
                   1396: {
                   1397:     /* fail safe */
                   1398:     if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
                   1399:         tcg_abort();
                   1400: 
                   1401:     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
                   1402:     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
                   1403:     tcg_regset_set32(tcg_target_call_clobber_regs, 0,
                   1404:                      (1 << TCG_REG_RDI) | 
                   1405:                      (1 << TCG_REG_RSI) | 
                   1406:                      (1 << TCG_REG_RDX) |
                   1407:                      (1 << TCG_REG_RCX) |
                   1408:                      (1 << TCG_REG_R8) |
                   1409:                      (1 << TCG_REG_R9) |
                   1410:                      (1 << TCG_REG_RAX) |
                   1411:                      (1 << TCG_REG_R10) |
                   1412:                      (1 << TCG_REG_R11));
                   1413:     
                   1414:     tcg_regset_clear(s->reserved_regs);
                   1415:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_RSP);
                   1416: 
                   1417:     tcg_add_target_add_op_defs(x86_64_op_defs);
                   1418: }

unix.superglobalmegacorp.com

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