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

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: 
                    366: static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
                    367:                               int arg1, tcg_target_long arg2)
                    368: {
                    369:     if (type == TCG_TYPE_I32)
                    370:         tcg_out_modrm_offset(s, 0x8b, ret, arg1, arg2); /* movl */
                    371:     else
                    372:         tcg_out_modrm_offset(s, 0x8b | P_REXW, ret, arg1, arg2); /* movq */
                    373: }
                    374: 
                    375: static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
                    376:                               int arg1, tcg_target_long arg2)
                    377: {
                    378:     if (type == TCG_TYPE_I32)
                    379:         tcg_out_modrm_offset(s, 0x89, arg, arg1, arg2); /* movl */
                    380:     else
                    381:         tcg_out_modrm_offset(s, 0x89 | P_REXW, arg, arg1, arg2); /* movq */
                    382: }
                    383: 
                    384: static inline void tgen_arithi32(TCGContext *s, int c, int r0, int32_t val)
                    385: {
                    386:     if (val == (int8_t)val) {
                    387:         tcg_out_modrm(s, 0x83, c, r0);
                    388:         tcg_out8(s, val);
                    389:     } else if (c == ARITH_AND && val == 0xffu) {
                    390:         /* movzbl */
                    391:         tcg_out_modrm(s, 0xb6 | P_EXT | P_REXB, r0, r0);
                    392:     } else if (c == ARITH_AND && val == 0xffffu) {
                    393:         /* movzwl */
                    394:         tcg_out_modrm(s, 0xb7 | P_EXT, r0, r0);
                    395:     } else {
                    396:         tcg_out_modrm(s, 0x81, c, r0);
                    397:         tcg_out32(s, val);
                    398:     }
                    399: }
                    400: 
                    401: static inline void tgen_arithi64(TCGContext *s, int c, int r0, int64_t val)
                    402: {
                    403:     if (val == (int8_t)val) {
                    404:         tcg_out_modrm(s, 0x83 | P_REXW, c, r0);
                    405:         tcg_out8(s, val);
                    406:     } else if (c == ARITH_AND && val == 0xffu) {
                    407:         /* movzbl */
                    408:         tcg_out_modrm(s, 0xb6 | P_EXT | P_REXW, r0, r0);
                    409:     } else if (c == ARITH_AND && val == 0xffffu) {
                    410:         /* movzwl */
                    411:         tcg_out_modrm(s, 0xb7 | P_EXT | P_REXW, r0, r0);
                    412:     } else if (c == ARITH_AND && val == 0xffffffffu) {
                    413:         /* 32-bit mov zero extends */
                    414:         tcg_out_modrm(s, 0x8b, r0, r0);
                    415:     } else if (val == (int32_t)val) {
                    416:         tcg_out_modrm(s, 0x81 | P_REXW, c, r0);
                    417:         tcg_out32(s, val);
                    418:     } else if (c == ARITH_AND && val == (uint32_t)val) {
                    419:         tcg_out_modrm(s, 0x81, c, r0);
                    420:         tcg_out32(s, val);
                    421:     } else {
                    422:         tcg_abort();
                    423:     }
                    424: }
                    425: 
                    426: static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
                    427: {
                    428:     if (val != 0)
                    429:         tgen_arithi64(s, ARITH_ADD, reg, val);
                    430: }
                    431: 
                    432: static void tcg_out_jxx(TCGContext *s, int opc, int label_index)
                    433: {
                    434:     int32_t val, val1;
                    435:     TCGLabel *l = &s->labels[label_index];
                    436:     
                    437:     if (l->has_value) {
                    438:         val = l->u.value - (tcg_target_long)s->code_ptr;
                    439:         val1 = val - 2;
                    440:         if ((int8_t)val1 == val1) {
                    441:             if (opc == -1)
                    442:                 tcg_out8(s, 0xeb);
                    443:             else
                    444:                 tcg_out8(s, 0x70 + opc);
                    445:             tcg_out8(s, val1);
                    446:         } else {
                    447:             if (opc == -1) {
                    448:                 tcg_out8(s, 0xe9);
                    449:                 tcg_out32(s, val - 5);
                    450:             } else {
                    451:                 tcg_out8(s, 0x0f);
                    452:                 tcg_out8(s, 0x80 + opc);
                    453:                 tcg_out32(s, val - 6);
                    454:             }
                    455:         }
                    456:     } else {
                    457:         if (opc == -1) {
                    458:             tcg_out8(s, 0xe9);
                    459:         } else {
                    460:             tcg_out8(s, 0x0f);
                    461:             tcg_out8(s, 0x80 + opc);
                    462:         }
                    463:         tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
                    464:         s->code_ptr += 4;
                    465:     }
                    466: }
                    467: 
                    468: static void tcg_out_brcond(TCGContext *s, int cond, 
                    469:                            TCGArg arg1, TCGArg arg2, int const_arg2,
                    470:                            int label_index, int rexw)
                    471: {
                    472:     if (const_arg2) {
                    473:         if (arg2 == 0) {
                    474:             /* test r, r */
                    475:             tcg_out_modrm(s, 0x85 | rexw, arg1, arg1);
                    476:         } else {
                    477:             if (rexw)
                    478:                 tgen_arithi64(s, ARITH_CMP, arg1, arg2);
                    479:             else
                    480:                 tgen_arithi32(s, ARITH_CMP, arg1, arg2);
                    481:         }
                    482:     } else {
                    483:         tcg_out_modrm(s, 0x01 | (ARITH_CMP << 3) | rexw, arg2, arg1);
                    484:     }
                    485:     tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index);
                    486: }
                    487: 
                    488: #if defined(CONFIG_SOFTMMU)
                    489: 
                    490: #include "../../softmmu_defs.h"
                    491: 
                    492: static void *qemu_ld_helpers[4] = {
                    493:     __ldb_mmu,
                    494:     __ldw_mmu,
                    495:     __ldl_mmu,
                    496:     __ldq_mmu,
                    497: };
                    498: 
                    499: static void *qemu_st_helpers[4] = {
                    500:     __stb_mmu,
                    501:     __stw_mmu,
                    502:     __stl_mmu,
                    503:     __stq_mmu,
                    504: };
                    505: #endif
                    506: 
                    507: static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
                    508:                             int opc)
                    509: {
                    510:     int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw;
                    511: #if defined(CONFIG_SOFTMMU)
                    512:     uint8_t *label1_ptr, *label2_ptr;
                    513: #endif
                    514: 
                    515:     data_reg = *args++;
                    516:     addr_reg = *args++;
                    517:     mem_index = *args;
                    518:     s_bits = opc & 3;
                    519: 
                    520:     r0 = TCG_REG_RDI;
                    521:     r1 = TCG_REG_RSI;
                    522: 
                    523: #if TARGET_LONG_BITS == 32
                    524:     rexw = 0;
                    525: #else
                    526:     rexw = P_REXW;
                    527: #endif
                    528: #if defined(CONFIG_SOFTMMU)
                    529:     /* mov */
                    530:     tcg_out_modrm(s, 0x8b | rexw, r1, addr_reg);
                    531: 
                    532:     /* mov */
                    533:     tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
                    534:  
                    535:     tcg_out_modrm(s, 0xc1 | rexw, 5, r1); /* shr $x, r1 */
                    536:     tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); 
                    537:     
                    538:     tcg_out_modrm(s, 0x81 | rexw, 4, r0); /* andl $x, r0 */
                    539:     tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
                    540:     
                    541:     tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
                    542:     tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
                    543: 
                    544:     /* lea offset(r1, env), r1 */
                    545:     tcg_out_modrm_offset2(s, 0x8d | P_REXW, r1, r1, TCG_AREG0, 0,
                    546:                           offsetof(CPUState, tlb_table[mem_index][0].addr_read));
                    547: 
                    548:     /* cmp 0(r1), r0 */
                    549:     tcg_out_modrm_offset(s, 0x3b | rexw, r0, r1, 0);
                    550:     
                    551:     /* mov */
                    552:     tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
                    553:     
                    554:     /* je label1 */
                    555:     tcg_out8(s, 0x70 + JCC_JE);
                    556:     label1_ptr = s->code_ptr;
                    557:     s->code_ptr++;
                    558: 
                    559:     /* XXX: move that code at the end of the TB */
                    560:     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RSI, mem_index);
                    561:     tcg_out8(s, 0xe8);
                    562:     tcg_out32(s, (tcg_target_long)qemu_ld_helpers[s_bits] - 
                    563:               (tcg_target_long)s->code_ptr - 4);
                    564: 
                    565:     switch(opc) {
                    566:     case 0 | 4:
                    567:         /* movsbq */
                    568:         tcg_out_modrm(s, 0xbe | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
                    569:         break;
                    570:     case 1 | 4:
                    571:         /* movswq */
                    572:         tcg_out_modrm(s, 0xbf | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
                    573:         break;
                    574:     case 2 | 4:
                    575:         /* movslq */
                    576:         tcg_out_modrm(s, 0x63 | P_REXW, data_reg, TCG_REG_RAX);
                    577:         break;
                    578:     case 0:
                    579:         /* movzbq */
                    580:         tcg_out_modrm(s, 0xb6 | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
                    581:         break;
                    582:     case 1:
                    583:         /* movzwq */
                    584:         tcg_out_modrm(s, 0xb7 | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
                    585:         break;
                    586:     case 2:
                    587:     default:
                    588:         /* movl */
                    589:         tcg_out_modrm(s, 0x8b, data_reg, TCG_REG_RAX);
                    590:         break;
                    591:     case 3:
                    592:         tcg_out_mov(s, data_reg, TCG_REG_RAX);
                    593:         break;
                    594:     }
                    595: 
                    596:     /* jmp label2 */
                    597:     tcg_out8(s, 0xeb);
                    598:     label2_ptr = s->code_ptr;
                    599:     s->code_ptr++;
                    600:     
                    601:     /* label1: */
                    602:     *label1_ptr = s->code_ptr - label1_ptr - 1;
                    603: 
                    604:     /* add x(r1), r0 */
                    605:     tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - 
                    606:                          offsetof(CPUTLBEntry, addr_read));
                    607: #else
                    608:     r0 = addr_reg;
                    609: #endif    
                    610: 
                    611: #ifdef TARGET_WORDS_BIGENDIAN
                    612:     bswap = 1;
                    613: #else
                    614:     bswap = 0;
                    615: #endif
                    616:     switch(opc) {
                    617:     case 0:
                    618:         /* movzbl */
                    619:         tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, 0);
                    620:         break;
                    621:     case 0 | 4:
                    622:         /* movsbX */
                    623:         tcg_out_modrm_offset(s, 0xbe | P_EXT | rexw, data_reg, r0, 0);
                    624:         break;
                    625:     case 1:
                    626:         /* movzwl */
                    627:         tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0);
                    628:         if (bswap) {
                    629:             /* rolw $8, data_reg */
                    630:             tcg_out8(s, 0x66); 
                    631:             tcg_out_modrm(s, 0xc1, 0, data_reg);
                    632:             tcg_out8(s, 8);
                    633:         }
                    634:         break;
                    635:     case 1 | 4:
                    636:         if (bswap) {
                    637:             /* movzwl */
                    638:             tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0);
                    639:             /* rolw $8, data_reg */
                    640:             tcg_out8(s, 0x66); 
                    641:             tcg_out_modrm(s, 0xc1, 0, data_reg);
                    642:             tcg_out8(s, 8);
                    643: 
                    644:             /* movswX data_reg, data_reg */
                    645:             tcg_out_modrm(s, 0xbf | P_EXT | rexw, data_reg, data_reg);
                    646:         } else {
                    647:             /* movswX */
                    648:             tcg_out_modrm_offset(s, 0xbf | P_EXT | rexw, data_reg, r0, 0);
                    649:         }
                    650:         break;
                    651:     case 2:
                    652:         /* movl (r0), data_reg */
                    653:         tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0);
                    654:         if (bswap) {
                    655:             /* bswap */
                    656:             tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0);
                    657:         }
                    658:         break;
                    659:     case 2 | 4:
                    660:         if (bswap) {
                    661:             /* movl (r0), data_reg */
                    662:             tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0);
                    663:             /* bswap */
                    664:             tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0);
                    665:             /* movslq */
                    666:             tcg_out_modrm(s, 0x63 | P_REXW, data_reg, data_reg);
                    667:         } else {
                    668:             /* movslq */
                    669:             tcg_out_modrm_offset(s, 0x63 | P_REXW, data_reg, r0, 0);
                    670:         }
                    671:         break;
                    672:     case 3:
                    673:         /* movq (r0), data_reg */
                    674:         tcg_out_modrm_offset(s, 0x8b | P_REXW, data_reg, r0, 0);
                    675:         if (bswap) {
                    676:             /* bswap */
                    677:             tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT | P_REXW, 0, data_reg, 0);
                    678:         }
                    679:         break;
                    680:     default:
                    681:         tcg_abort();
                    682:     }
                    683: 
                    684: #if defined(CONFIG_SOFTMMU)
                    685:     /* label2: */
                    686:     *label2_ptr = s->code_ptr - label2_ptr - 1;
                    687: #endif
                    688: }
                    689: 
                    690: static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
                    691:                             int opc)
                    692: {
                    693:     int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw;
                    694: #if defined(CONFIG_SOFTMMU)
                    695:     uint8_t *label1_ptr, *label2_ptr;
                    696: #endif
                    697: 
                    698:     data_reg = *args++;
                    699:     addr_reg = *args++;
                    700:     mem_index = *args;
                    701: 
                    702:     s_bits = opc;
                    703: 
                    704:     r0 = TCG_REG_RDI;
                    705:     r1 = TCG_REG_RSI;
                    706: 
                    707: #if TARGET_LONG_BITS == 32
                    708:     rexw = 0;
                    709: #else
                    710:     rexw = P_REXW;
                    711: #endif
                    712: #if defined(CONFIG_SOFTMMU)
                    713:     /* mov */
                    714:     tcg_out_modrm(s, 0x8b | rexw, r1, addr_reg);
                    715: 
                    716:     /* mov */
                    717:     tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
                    718:  
                    719:     tcg_out_modrm(s, 0xc1 | rexw, 5, r1); /* shr $x, r1 */
                    720:     tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); 
                    721:     
                    722:     tcg_out_modrm(s, 0x81 | rexw, 4, r0); /* andl $x, r0 */
                    723:     tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
                    724:     
                    725:     tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
                    726:     tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
                    727: 
                    728:     /* lea offset(r1, env), r1 */
                    729:     tcg_out_modrm_offset2(s, 0x8d | P_REXW, r1, r1, TCG_AREG0, 0,
                    730:                           offsetof(CPUState, tlb_table[mem_index][0].addr_write));
                    731: 
                    732:     /* cmp 0(r1), r0 */
                    733:     tcg_out_modrm_offset(s, 0x3b | rexw, r0, r1, 0);
                    734:     
                    735:     /* mov */
                    736:     tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
                    737:     
                    738:     /* je label1 */
                    739:     tcg_out8(s, 0x70 + JCC_JE);
                    740:     label1_ptr = s->code_ptr;
                    741:     s->code_ptr++;
                    742: 
                    743:     /* XXX: move that code at the end of the TB */
                    744:     switch(opc) {
                    745:     case 0:
                    746:         /* movzbl */
                    747:         tcg_out_modrm(s, 0xb6 | P_EXT | P_REXB, TCG_REG_RSI, data_reg);
                    748:         break;
                    749:     case 1:
                    750:         /* movzwl */
                    751:         tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_RSI, data_reg);
                    752:         break;
                    753:     case 2:
                    754:         /* movl */
                    755:         tcg_out_modrm(s, 0x8b, TCG_REG_RSI, data_reg);
                    756:         break;
                    757:     default:
                    758:     case 3:
                    759:         tcg_out_mov(s, TCG_REG_RSI, data_reg);
                    760:         break;
                    761:     }
                    762:     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
                    763:     tcg_out8(s, 0xe8);
                    764:     tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] - 
                    765:               (tcg_target_long)s->code_ptr - 4);
                    766: 
                    767:     /* jmp label2 */
                    768:     tcg_out8(s, 0xeb);
                    769:     label2_ptr = s->code_ptr;
                    770:     s->code_ptr++;
                    771:     
                    772:     /* label1: */
                    773:     *label1_ptr = s->code_ptr - label1_ptr - 1;
                    774: 
                    775:     /* add x(r1), r0 */
                    776:     tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - 
                    777:                          offsetof(CPUTLBEntry, addr_write));
                    778: #else
                    779:     r0 = addr_reg;
                    780: #endif
                    781: 
                    782: #ifdef TARGET_WORDS_BIGENDIAN
                    783:     bswap = 1;
                    784: #else
                    785:     bswap = 0;
                    786: #endif
                    787:     switch(opc) {
                    788:     case 0:
                    789:         /* movb */
                    790:         tcg_out_modrm_offset(s, 0x88 | P_REXB, data_reg, r0, 0);
                    791:         break;
                    792:     case 1:
                    793:         if (bswap) {
                    794:             tcg_out_modrm(s, 0x8b, r1, data_reg); /* movl */
                    795:             tcg_out8(s, 0x66); /* rolw $8, %ecx */
                    796:             tcg_out_modrm(s, 0xc1, 0, r1);
                    797:             tcg_out8(s, 8);
                    798:             data_reg = r1;
                    799:         }
                    800:         /* movw */
                    801:         tcg_out8(s, 0x66);
                    802:         tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0);
                    803:         break;
                    804:     case 2:
                    805:         if (bswap) {
                    806:             tcg_out_modrm(s, 0x8b, r1, data_reg); /* movl */
                    807:             /* bswap data_reg */
                    808:             tcg_out_opc(s, (0xc8 + r1) | P_EXT, 0, r1, 0);
                    809:             data_reg = r1;
                    810:         }
                    811:         /* movl */
                    812:         tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0);
                    813:         break;
                    814:     case 3:
                    815:         if (bswap) {
                    816:             tcg_out_mov(s, r1, data_reg);
                    817:             /* bswap data_reg */
                    818:             tcg_out_opc(s, (0xc8 + r1) | P_EXT | P_REXW, 0, r1, 0);
                    819:             data_reg = r1;
                    820:         }
                    821:         /* movq */
                    822:         tcg_out_modrm_offset(s, 0x89 | P_REXW, data_reg, r0, 0);
                    823:         break;
                    824:     default:
                    825:         tcg_abort();
                    826:     }
                    827: 
                    828: #if defined(CONFIG_SOFTMMU)
                    829:     /* label2: */
                    830:     *label2_ptr = s->code_ptr - label2_ptr - 1;
                    831: #endif
                    832: }
                    833: 
                    834: static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
                    835:                               const int *const_args)
                    836: {
                    837:     int c;
                    838:     
                    839:     switch(opc) {
                    840:     case INDEX_op_exit_tb:
                    841:         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RAX, args[0]);
                    842:         tcg_out8(s, 0xe9); /* jmp tb_ret_addr */
                    843:         tcg_out32(s, tb_ret_addr - s->code_ptr - 4);
                    844:         break;
                    845:     case INDEX_op_goto_tb:
                    846:         if (s->tb_jmp_offset) {
                    847:             /* direct jump method */
                    848:             tcg_out8(s, 0xe9); /* jmp im */
                    849:             s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
                    850:             tcg_out32(s, 0);
                    851:         } else {
                    852:             /* indirect jump method */
                    853:             /* jmp Ev */
                    854:             tcg_out_modrm_offset(s, 0xff, 4, -1, 
                    855:                                  (tcg_target_long)(s->tb_next + 
                    856:                                                    args[0]));
                    857:         }
                    858:         s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
                    859:         break;
                    860:     case INDEX_op_call:
                    861:         if (const_args[0]) {
                    862:             tcg_out8(s, 0xe8);
                    863:             tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
                    864:         } else {
                    865:             tcg_out_modrm(s, 0xff, 2, args[0]);
                    866:         }
                    867:         break;
                    868:     case INDEX_op_jmp:
                    869:         if (const_args[0]) {
                    870:             tcg_out8(s, 0xe9);
                    871:             tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
                    872:         } else {
                    873:             tcg_out_modrm(s, 0xff, 4, args[0]);
                    874:         }
                    875:         break;
                    876:     case INDEX_op_br:
                    877:         tcg_out_jxx(s, JCC_JMP, args[0]);
                    878:         break;
                    879:     case INDEX_op_movi_i32:
                    880:         tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]);
                    881:         break;
                    882:     case INDEX_op_movi_i64:
                    883:         tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
                    884:         break;
                    885:     case INDEX_op_ld8u_i32:
                    886:     case INDEX_op_ld8u_i64:
                    887:         /* movzbl */
                    888:         tcg_out_modrm_offset(s, 0xb6 | P_EXT, args[0], args[1], args[2]);
                    889:         break;
                    890:     case INDEX_op_ld8s_i32:
                    891:         /* movsbl */
                    892:         tcg_out_modrm_offset(s, 0xbe | P_EXT, args[0], args[1], args[2]);
                    893:         break;
                    894:     case INDEX_op_ld8s_i64:
                    895:         /* movsbq */
                    896:         tcg_out_modrm_offset(s, 0xbe | P_EXT | P_REXW, args[0], args[1], args[2]);
                    897:         break;
                    898:     case INDEX_op_ld16u_i32:
                    899:     case INDEX_op_ld16u_i64:
                    900:         /* movzwl */
                    901:         tcg_out_modrm_offset(s, 0xb7 | P_EXT, args[0], args[1], args[2]);
                    902:         break;
                    903:     case INDEX_op_ld16s_i32:
                    904:         /* movswl */
                    905:         tcg_out_modrm_offset(s, 0xbf | P_EXT, args[0], args[1], args[2]);
                    906:         break;
                    907:     case INDEX_op_ld16s_i64:
                    908:         /* movswq */
                    909:         tcg_out_modrm_offset(s, 0xbf | P_EXT | P_REXW, args[0], args[1], args[2]);
                    910:         break;
                    911:     case INDEX_op_ld_i32:
                    912:     case INDEX_op_ld32u_i64:
                    913:         /* movl */
                    914:         tcg_out_modrm_offset(s, 0x8b, args[0], args[1], args[2]);
                    915:         break;
                    916:     case INDEX_op_ld32s_i64:
                    917:         /* movslq */
                    918:         tcg_out_modrm_offset(s, 0x63 | P_REXW, args[0], args[1], args[2]);
                    919:         break;
                    920:     case INDEX_op_ld_i64:
                    921:         /* movq */
                    922:         tcg_out_modrm_offset(s, 0x8b | P_REXW, args[0], args[1], args[2]);
                    923:         break;
                    924:         
                    925:     case INDEX_op_st8_i32:
                    926:     case INDEX_op_st8_i64:
                    927:         /* movb */
                    928:         tcg_out_modrm_offset(s, 0x88 | P_REXB, args[0], args[1], args[2]);
                    929:         break;
                    930:     case INDEX_op_st16_i32:
                    931:     case INDEX_op_st16_i64:
                    932:         /* movw */
                    933:         tcg_out8(s, 0x66);
                    934:         tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
                    935:         break;
                    936:     case INDEX_op_st_i32:
                    937:     case INDEX_op_st32_i64:
                    938:         /* movl */
                    939:         tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
                    940:         break;
                    941:     case INDEX_op_st_i64:
                    942:         /* movq */
                    943:         tcg_out_modrm_offset(s, 0x89 | P_REXW, args[0], args[1], args[2]);
                    944:         break;
                    945: 
                    946:     case INDEX_op_sub_i32:
                    947:         c = ARITH_SUB;
                    948:         goto gen_arith32;
                    949:     case INDEX_op_and_i32:
                    950:         c = ARITH_AND;
                    951:         goto gen_arith32;
                    952:     case INDEX_op_or_i32:
                    953:         c = ARITH_OR;
                    954:         goto gen_arith32;
                    955:     case INDEX_op_xor_i32:
                    956:         c = ARITH_XOR;
                    957:         goto gen_arith32;
                    958:     case INDEX_op_add_i32:
                    959:         c = ARITH_ADD;
                    960:     gen_arith32:
                    961:         if (const_args[2]) {
                    962:             tgen_arithi32(s, c, args[0], args[2]);
                    963:         } else {
                    964:             tcg_out_modrm(s, 0x01 | (c << 3), args[2], args[0]);
                    965:         }
                    966:         break;
                    967: 
                    968:     case INDEX_op_sub_i64:
                    969:         c = ARITH_SUB;
                    970:         goto gen_arith64;
                    971:     case INDEX_op_and_i64:
                    972:         c = ARITH_AND;
                    973:         goto gen_arith64;
                    974:     case INDEX_op_or_i64:
                    975:         c = ARITH_OR;
                    976:         goto gen_arith64;
                    977:     case INDEX_op_xor_i64:
                    978:         c = ARITH_XOR;
                    979:         goto gen_arith64;
                    980:     case INDEX_op_add_i64:
                    981:         c = ARITH_ADD;
                    982:     gen_arith64:
                    983:         if (const_args[2]) {
                    984:             tgen_arithi64(s, c, args[0], args[2]);
                    985:         } else {
                    986:             tcg_out_modrm(s, 0x01 | (c << 3) | P_REXW, args[2], args[0]);
                    987:         }
                    988:         break;
                    989: 
                    990:     case INDEX_op_mul_i32:
                    991:         if (const_args[2]) {
                    992:             int32_t val;
                    993:             val = args[2];
                    994:             if (val == (int8_t)val) {
                    995:                 tcg_out_modrm(s, 0x6b, args[0], args[0]);
                    996:                 tcg_out8(s, val);
                    997:             } else {
                    998:                 tcg_out_modrm(s, 0x69, args[0], args[0]);
                    999:                 tcg_out32(s, val);
                   1000:             }
                   1001:         } else {
                   1002:             tcg_out_modrm(s, 0xaf | P_EXT, args[0], args[2]);
                   1003:         }
                   1004:         break;
                   1005:     case INDEX_op_mul_i64:
                   1006:         if (const_args[2]) {
                   1007:             int32_t val;
                   1008:             val = args[2];
                   1009:             if (val == (int8_t)val) {
                   1010:                 tcg_out_modrm(s, 0x6b | P_REXW, args[0], args[0]);
                   1011:                 tcg_out8(s, val);
                   1012:             } else {
                   1013:                 tcg_out_modrm(s, 0x69 | P_REXW, args[0], args[0]);
                   1014:                 tcg_out32(s, val);
                   1015:             }
                   1016:         } else {
                   1017:             tcg_out_modrm(s, 0xaf | P_EXT | P_REXW, args[0], args[2]);
                   1018:         }
                   1019:         break;
                   1020:     case INDEX_op_div2_i32:
                   1021:         tcg_out_modrm(s, 0xf7, 7, args[4]);
                   1022:         break;
                   1023:     case INDEX_op_divu2_i32:
                   1024:         tcg_out_modrm(s, 0xf7, 6, args[4]);
                   1025:         break;
                   1026:     case INDEX_op_div2_i64:
                   1027:         tcg_out_modrm(s, 0xf7 | P_REXW, 7, args[4]);
                   1028:         break;
                   1029:     case INDEX_op_divu2_i64:
                   1030:         tcg_out_modrm(s, 0xf7 | P_REXW, 6, args[4]);
                   1031:         break;
                   1032: 
                   1033:     case INDEX_op_shl_i32:
                   1034:         c = SHIFT_SHL;
                   1035:     gen_shift32:
                   1036:         if (const_args[2]) {
                   1037:             if (args[2] == 1) {
                   1038:                 tcg_out_modrm(s, 0xd1, c, args[0]);
                   1039:             } else {
                   1040:                 tcg_out_modrm(s, 0xc1, c, args[0]);
                   1041:                 tcg_out8(s, args[2]);
                   1042:             }
                   1043:         } else {
                   1044:             tcg_out_modrm(s, 0xd3, c, args[0]);
                   1045:         }
                   1046:         break;
                   1047:     case INDEX_op_shr_i32:
                   1048:         c = SHIFT_SHR;
                   1049:         goto gen_shift32;
                   1050:     case INDEX_op_sar_i32:
                   1051:         c = SHIFT_SAR;
                   1052:         goto gen_shift32;
1.1.1.2 ! root     1053:     case INDEX_op_rotl_i32:
        !          1054:         c = SHIFT_ROL;
        !          1055:         goto gen_shift32;
        !          1056:     case INDEX_op_rotr_i32:
        !          1057:         c = SHIFT_ROR;
        !          1058:         goto gen_shift32;
        !          1059: 
1.1       root     1060:     case INDEX_op_shl_i64:
                   1061:         c = SHIFT_SHL;
                   1062:     gen_shift64:
                   1063:         if (const_args[2]) {
                   1064:             if (args[2] == 1) {
                   1065:                 tcg_out_modrm(s, 0xd1 | P_REXW, c, args[0]);
                   1066:             } else {
                   1067:                 tcg_out_modrm(s, 0xc1 | P_REXW, c, args[0]);
                   1068:                 tcg_out8(s, args[2]);
                   1069:             }
                   1070:         } else {
                   1071:             tcg_out_modrm(s, 0xd3 | P_REXW, c, args[0]);
                   1072:         }
                   1073:         break;
                   1074:     case INDEX_op_shr_i64:
                   1075:         c = SHIFT_SHR;
                   1076:         goto gen_shift64;
                   1077:     case INDEX_op_sar_i64:
                   1078:         c = SHIFT_SAR;
                   1079:         goto gen_shift64;
1.1.1.2 ! root     1080:     case INDEX_op_rotl_i64:
        !          1081:         c = SHIFT_ROL;
        !          1082:         goto gen_shift64;
        !          1083:     case INDEX_op_rotr_i64:
        !          1084:         c = SHIFT_ROR;
        !          1085:         goto gen_shift64;
        !          1086: 
1.1       root     1087:     case INDEX_op_brcond_i32:
                   1088:         tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], 
                   1089:                        args[3], 0);
                   1090:         break;
                   1091:     case INDEX_op_brcond_i64:
                   1092:         tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], 
                   1093:                        args[3], P_REXW);
                   1094:         break;
                   1095: 
1.1.1.2 ! root     1096:     case INDEX_op_bswap16_i32:
        !          1097:     case INDEX_op_bswap16_i64:
        !          1098:         tcg_out8(s, 0x66);
        !          1099:         tcg_out_modrm(s, 0xc1, SHIFT_ROL, args[0]);
        !          1100:         tcg_out8(s, 8);
        !          1101:         break;
        !          1102:     case INDEX_op_bswap32_i32:
        !          1103:     case INDEX_op_bswap32_i64:
1.1       root     1104:         tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT, 0, args[0], 0);
                   1105:         break;
1.1.1.2 ! root     1106:     case INDEX_op_bswap64_i64:
1.1       root     1107:         tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT | P_REXW, 0, args[0], 0);
                   1108:         break;
                   1109: 
                   1110:     case INDEX_op_neg_i32:
                   1111:         tcg_out_modrm(s, 0xf7, 3, args[0]);
                   1112:         break;
                   1113:     case INDEX_op_neg_i64:
                   1114:         tcg_out_modrm(s, 0xf7 | P_REXW, 3, args[0]);
                   1115:         break;
                   1116: 
1.1.1.2 ! root     1117:     case INDEX_op_not_i32:
        !          1118:         tcg_out_modrm(s, 0xf7, 2, args[0]);
        !          1119:         break;
        !          1120:     case INDEX_op_not_i64:
        !          1121:         tcg_out_modrm(s, 0xf7 | P_REXW, 2, args[0]);
        !          1122:         break;
        !          1123: 
1.1       root     1124:     case INDEX_op_ext8s_i32:
                   1125:         tcg_out_modrm(s, 0xbe | P_EXT | P_REXB, args[0], args[1]);
                   1126:         break;
                   1127:     case INDEX_op_ext16s_i32:
                   1128:         tcg_out_modrm(s, 0xbf | P_EXT, args[0], args[1]);
                   1129:         break;
                   1130:     case INDEX_op_ext8s_i64:
                   1131:         tcg_out_modrm(s, 0xbe | P_EXT | P_REXW, args[0], args[1]);
                   1132:         break;
                   1133:     case INDEX_op_ext16s_i64:
                   1134:         tcg_out_modrm(s, 0xbf | P_EXT | P_REXW, args[0], args[1]);
                   1135:         break;
                   1136:     case INDEX_op_ext32s_i64:
                   1137:         tcg_out_modrm(s, 0x63 | P_REXW, args[0], args[1]);
                   1138:         break;
                   1139: 
                   1140:     case INDEX_op_qemu_ld8u:
                   1141:         tcg_out_qemu_ld(s, args, 0);
                   1142:         break;
                   1143:     case INDEX_op_qemu_ld8s:
                   1144:         tcg_out_qemu_ld(s, args, 0 | 4);
                   1145:         break;
                   1146:     case INDEX_op_qemu_ld16u:
                   1147:         tcg_out_qemu_ld(s, args, 1);
                   1148:         break;
                   1149:     case INDEX_op_qemu_ld16s:
                   1150:         tcg_out_qemu_ld(s, args, 1 | 4);
                   1151:         break;
                   1152:     case INDEX_op_qemu_ld32u:
                   1153:         tcg_out_qemu_ld(s, args, 2);
                   1154:         break;
                   1155:     case INDEX_op_qemu_ld32s:
                   1156:         tcg_out_qemu_ld(s, args, 2 | 4);
                   1157:         break;
                   1158:     case INDEX_op_qemu_ld64:
                   1159:         tcg_out_qemu_ld(s, args, 3);
                   1160:         break;
                   1161:         
                   1162:     case INDEX_op_qemu_st8:
                   1163:         tcg_out_qemu_st(s, args, 0);
                   1164:         break;
                   1165:     case INDEX_op_qemu_st16:
                   1166:         tcg_out_qemu_st(s, args, 1);
                   1167:         break;
                   1168:     case INDEX_op_qemu_st32:
                   1169:         tcg_out_qemu_st(s, args, 2);
                   1170:         break;
                   1171:     case INDEX_op_qemu_st64:
                   1172:         tcg_out_qemu_st(s, args, 3);
                   1173:         break;
                   1174: 
                   1175:     default:
                   1176:         tcg_abort();
                   1177:     }
                   1178: }
                   1179: 
                   1180: static int tcg_target_callee_save_regs[] = {
                   1181:     TCG_REG_RBP,
                   1182:     TCG_REG_RBX,
                   1183:     TCG_REG_R12,
                   1184:     TCG_REG_R13,
                   1185:     /*    TCG_REG_R14, */ /* currently used for the global env, so no
                   1186:                              need to save */
                   1187:     TCG_REG_R15,
                   1188: };
                   1189: 
                   1190: static inline void tcg_out_push(TCGContext *s, int reg)
                   1191: {
                   1192:     tcg_out_opc(s, (0x50 + (reg & 7)), 0, reg, 0);
                   1193: }
                   1194: 
                   1195: static inline void tcg_out_pop(TCGContext *s, int reg)
                   1196: {
                   1197:     tcg_out_opc(s, (0x58 + (reg & 7)), 0, reg, 0);
                   1198: }
                   1199: 
                   1200: /* Generate global QEMU prologue and epilogue code */
                   1201: void tcg_target_qemu_prologue(TCGContext *s)
                   1202: {
                   1203:     int i, frame_size, push_size, stack_addend;
                   1204: 
                   1205:     /* TB prologue */
                   1206:     /* save all callee saved registers */
                   1207:     for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
                   1208:         tcg_out_push(s, tcg_target_callee_save_regs[i]);
                   1209: 
                   1210:     }
                   1211:     /* reserve some stack space */
                   1212:     push_size = 8 + ARRAY_SIZE(tcg_target_callee_save_regs) * 8;
                   1213:     frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
                   1214:     frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & 
                   1215:         ~(TCG_TARGET_STACK_ALIGN - 1);
                   1216:     stack_addend = frame_size - push_size;
                   1217:     tcg_out_addi(s, TCG_REG_RSP, -stack_addend);
                   1218: 
                   1219:     tcg_out_modrm(s, 0xff, 4, TCG_REG_RDI); /* jmp *%rdi */
                   1220:     
                   1221:     /* TB epilogue */
                   1222:     tb_ret_addr = s->code_ptr;
                   1223:     tcg_out_addi(s, TCG_REG_RSP, stack_addend);
                   1224:     for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
                   1225:         tcg_out_pop(s, tcg_target_callee_save_regs[i]);
                   1226:     }
                   1227:     tcg_out8(s, 0xc3); /* ret */
                   1228: }
                   1229: 
                   1230: static const TCGTargetOpDef x86_64_op_defs[] = {
                   1231:     { INDEX_op_exit_tb, { } },
                   1232:     { INDEX_op_goto_tb, { } },
                   1233:     { INDEX_op_call, { "ri" } }, /* XXX: might need a specific constant constraint */
                   1234:     { INDEX_op_jmp, { "ri" } }, /* XXX: might need a specific constant constraint */
                   1235:     { INDEX_op_br, { } },
                   1236: 
                   1237:     { INDEX_op_mov_i32, { "r", "r" } },
                   1238:     { INDEX_op_movi_i32, { "r" } },
                   1239:     { INDEX_op_ld8u_i32, { "r", "r" } },
                   1240:     { INDEX_op_ld8s_i32, { "r", "r" } },
                   1241:     { INDEX_op_ld16u_i32, { "r", "r" } },
                   1242:     { INDEX_op_ld16s_i32, { "r", "r" } },
                   1243:     { INDEX_op_ld_i32, { "r", "r" } },
                   1244:     { INDEX_op_st8_i32, { "r", "r" } },
                   1245:     { INDEX_op_st16_i32, { "r", "r" } },
                   1246:     { INDEX_op_st_i32, { "r", "r" } },
                   1247: 
                   1248:     { INDEX_op_add_i32, { "r", "0", "ri" } },
                   1249:     { INDEX_op_mul_i32, { "r", "0", "ri" } },
                   1250:     { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
                   1251:     { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
                   1252:     { INDEX_op_sub_i32, { "r", "0", "ri" } },
                   1253:     { INDEX_op_and_i32, { "r", "0", "ri" } },
                   1254:     { INDEX_op_or_i32, { "r", "0", "ri" } },
                   1255:     { INDEX_op_xor_i32, { "r", "0", "ri" } },
                   1256: 
                   1257:     { INDEX_op_shl_i32, { "r", "0", "ci" } },
                   1258:     { INDEX_op_shr_i32, { "r", "0", "ci" } },
                   1259:     { INDEX_op_sar_i32, { "r", "0", "ci" } },
1.1.1.2 ! root     1260:     { INDEX_op_rotl_i32, { "r", "0", "ci" } },
        !          1261:     { INDEX_op_rotr_i32, { "r", "0", "ci" } },
1.1       root     1262: 
                   1263:     { INDEX_op_brcond_i32, { "r", "ri" } },
                   1264: 
                   1265:     { INDEX_op_mov_i64, { "r", "r" } },
                   1266:     { INDEX_op_movi_i64, { "r" } },
                   1267:     { INDEX_op_ld8u_i64, { "r", "r" } },
                   1268:     { INDEX_op_ld8s_i64, { "r", "r" } },
                   1269:     { INDEX_op_ld16u_i64, { "r", "r" } },
                   1270:     { INDEX_op_ld16s_i64, { "r", "r" } },
                   1271:     { INDEX_op_ld32u_i64, { "r", "r" } },
                   1272:     { INDEX_op_ld32s_i64, { "r", "r" } },
                   1273:     { INDEX_op_ld_i64, { "r", "r" } },
                   1274:     { INDEX_op_st8_i64, { "r", "r" } },
                   1275:     { INDEX_op_st16_i64, { "r", "r" } },
                   1276:     { INDEX_op_st32_i64, { "r", "r" } },
                   1277:     { INDEX_op_st_i64, { "r", "r" } },
                   1278: 
                   1279:     { INDEX_op_add_i64, { "r", "0", "re" } },
                   1280:     { INDEX_op_mul_i64, { "r", "0", "re" } },
                   1281:     { INDEX_op_div2_i64, { "a", "d", "0", "1", "r" } },
                   1282:     { INDEX_op_divu2_i64, { "a", "d", "0", "1", "r" } },
                   1283:     { INDEX_op_sub_i64, { "r", "0", "re" } },
                   1284:     { INDEX_op_and_i64, { "r", "0", "reZ" } },
                   1285:     { INDEX_op_or_i64, { "r", "0", "re" } },
                   1286:     { INDEX_op_xor_i64, { "r", "0", "re" } },
                   1287: 
                   1288:     { INDEX_op_shl_i64, { "r", "0", "ci" } },
                   1289:     { INDEX_op_shr_i64, { "r", "0", "ci" } },
                   1290:     { INDEX_op_sar_i64, { "r", "0", "ci" } },
1.1.1.2 ! root     1291:     { INDEX_op_rotl_i64, { "r", "0", "ci" } },
        !          1292:     { INDEX_op_rotr_i64, { "r", "0", "ci" } },
1.1       root     1293: 
                   1294:     { INDEX_op_brcond_i64, { "r", "re" } },
                   1295: 
1.1.1.2 ! root     1296:     { INDEX_op_bswap16_i32, { "r", "0" } },
        !          1297:     { INDEX_op_bswap16_i64, { "r", "0" } },
        !          1298:     { INDEX_op_bswap32_i32, { "r", "0" } },
        !          1299:     { INDEX_op_bswap32_i64, { "r", "0" } },
        !          1300:     { INDEX_op_bswap64_i64, { "r", "0" } },
1.1       root     1301: 
                   1302:     { INDEX_op_neg_i32, { "r", "0" } },
                   1303:     { INDEX_op_neg_i64, { "r", "0" } },
                   1304: 
1.1.1.2 ! root     1305:     { INDEX_op_not_i32, { "r", "0" } },
        !          1306:     { INDEX_op_not_i64, { "r", "0" } },
        !          1307: 
1.1       root     1308:     { INDEX_op_ext8s_i32, { "r", "r"} },
                   1309:     { INDEX_op_ext16s_i32, { "r", "r"} },
                   1310:     { INDEX_op_ext8s_i64, { "r", "r"} },
                   1311:     { INDEX_op_ext16s_i64, { "r", "r"} },
                   1312:     { INDEX_op_ext32s_i64, { "r", "r"} },
                   1313: 
                   1314:     { INDEX_op_qemu_ld8u, { "r", "L" } },
                   1315:     { INDEX_op_qemu_ld8s, { "r", "L" } },
                   1316:     { INDEX_op_qemu_ld16u, { "r", "L" } },
                   1317:     { INDEX_op_qemu_ld16s, { "r", "L" } },
                   1318:     { INDEX_op_qemu_ld32u, { "r", "L" } },
                   1319:     { INDEX_op_qemu_ld32s, { "r", "L" } },
                   1320:     { INDEX_op_qemu_ld64, { "r", "L" } },
                   1321: 
                   1322:     { INDEX_op_qemu_st8, { "L", "L" } },
                   1323:     { INDEX_op_qemu_st16, { "L", "L" } },
                   1324:     { INDEX_op_qemu_st32, { "L", "L" } },
                   1325:     { INDEX_op_qemu_st64, { "L", "L", "L" } },
                   1326: 
                   1327:     { -1 },
                   1328: };
                   1329: 
                   1330: void tcg_target_init(TCGContext *s)
                   1331: {
                   1332:     /* fail safe */
                   1333:     if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
                   1334:         tcg_abort();
                   1335: 
                   1336:     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
                   1337:     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
                   1338:     tcg_regset_set32(tcg_target_call_clobber_regs, 0,
                   1339:                      (1 << TCG_REG_RDI) | 
                   1340:                      (1 << TCG_REG_RSI) | 
                   1341:                      (1 << TCG_REG_RDX) |
                   1342:                      (1 << TCG_REG_RCX) |
                   1343:                      (1 << TCG_REG_R8) |
                   1344:                      (1 << TCG_REG_R9) |
                   1345:                      (1 << TCG_REG_RAX) |
                   1346:                      (1 << TCG_REG_R10) |
                   1347:                      (1 << TCG_REG_R11));
                   1348:     
                   1349:     tcg_regset_clear(s->reserved_regs);
                   1350:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_RSP);
                   1351: 
                   1352:     tcg_add_target_add_op_defs(x86_64_op_defs);
                   1353: }

unix.superglobalmegacorp.com

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