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

1.1       root        1: /*
                      2:  * Tiny Code Generator for QEMU
                      3:  *
                      4:  * Copyright (c) 2008 Fabrice Bellard
                      5:  *
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to deal
                      8:  * in the Software without restriction, including without limitation the rights
                      9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     10:  * copies of the Software, and to permit persons to whom the Software is
                     11:  * furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     22:  * THE SOFTWARE.
                     23:  */
                     24: 
                     25: #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.