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

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

unix.superglobalmegacorp.com

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