Annotation of qemu/target-i386/translate-copy.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *  i386 on i386 translation
                      3:  * 
                      4:  *  Copyright (c) 2003 Fabrice Bellard
                      5:  *
                      6:  * This library is free software; you can redistribute it and/or
                      7:  * modify it under the terms of the GNU Lesser General Public
                      8:  * License as published by the Free Software Foundation; either
                      9:  * version 2 of the License, or (at your option) any later version.
                     10:  *
                     11:  * This library is distributed in the hope that it will be useful,
                     12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     14:  * Lesser General Public License for more details.
                     15:  *
                     16:  * You should have received a copy of the GNU Lesser General Public
                     17:  * License along with this library; if not, write to the Free Software
                     18:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     19:  */
                     20: #include "config.h"
                     21: 
                     22: #include <stdarg.h>
                     23: #include <stdlib.h>
                     24: #include <stdio.h>
                     25: #include <string.h>
                     26: #include <inttypes.h>
                     27: #include <assert.h>
                     28: 
                     29: #include "cpu.h"
                     30: #include "exec-all.h"
                     31: #include "disas.h"
                     32: 
                     33: #ifdef USE_CODE_COPY
                     34: 
                     35: #include <signal.h>
                     36: #include <sys/mman.h>
                     37: #include <sys/ucontext.h>
                     38: 
                     39: extern char exec_loop;
                     40: 
                     41: /* operand size */
                     42: enum {
                     43:     OT_BYTE = 0,
                     44:     OT_WORD,
                     45:     OT_LONG, 
                     46:     OT_QUAD,
                     47: };
                     48: 
                     49: #define PREFIX_REPZ   0x01
                     50: #define PREFIX_REPNZ  0x02
                     51: #define PREFIX_LOCK   0x04
                     52: #define PREFIX_DATA   0x08
                     53: #define PREFIX_ADR    0x10
                     54: 
                     55: typedef struct DisasContext {
                     56:     /* current insn context */
                     57:     int override; /* -1 if no override */
                     58:     int prefix;
                     59:     int aflag, dflag;
                     60:     target_ulong pc; /* pc = eip + cs_base */
                     61:     int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
                     62:                    static state change (stop translation) */
                     63:     /* code output */
                     64:     uint8_t *gen_code_ptr;
                     65:     uint8_t *gen_code_start;
                     66:     
                     67:     /* current block context */
                     68:     target_ulong cs_base; /* base of CS segment */
                     69:     int pe;     /* protected mode */
                     70:     int code32; /* 32 bit code segment */
                     71:     int f_st;   /* currently unused */
                     72:     int vm86;   /* vm86 mode */
                     73:     int cpl;
                     74:     int iopl;
                     75:     int flags;
                     76:     struct TranslationBlock *tb;
                     77: } DisasContext;
                     78: 
                     79: #define CPU_FIELD_OFFSET(field) offsetof(CPUState, field)
                     80: 
                     81: #define CPU_SEG 0x64 /* fs override */
                     82: 
                     83: static inline void gb(DisasContext *s, uint32_t val)
                     84: {
                     85:     *s->gen_code_ptr++ = val;
                     86: }
                     87: 
                     88: static inline void gw(DisasContext *s, uint32_t val)
                     89: {
                     90:     *s->gen_code_ptr++ = val;
                     91:     *s->gen_code_ptr++ = val >> 8;
                     92: }
                     93: 
                     94: static inline void gl(DisasContext *s, uint32_t val)
                     95: {
                     96:     *s->gen_code_ptr++ = val;
                     97:     *s->gen_code_ptr++ = val >> 8;
                     98:     *s->gen_code_ptr++ = val >> 16;
                     99:     *s->gen_code_ptr++ = val >> 24;
                    100: }
                    101: 
                    102: static inline void gjmp(DisasContext *s, long val)
                    103: {
                    104:     gb(s, 0xe9); /* jmp */
                    105:     gl(s, val - (long)(s->gen_code_ptr + 4));
                    106: }
                    107: 
                    108: static inline void gen_movl_addr_im(DisasContext *s, 
                    109:                                     uint32_t addr, uint32_t val)
                    110: {
                    111:     gb(s, CPU_SEG); /* seg movl im, addr */
                    112:     gb(s, 0xc7); 
                    113:     gb(s, 0x05);
                    114:     gl(s, addr);
                    115:     gl(s, val);
                    116: }
                    117: 
                    118: static inline void gen_movw_addr_im(DisasContext *s, 
                    119:                                     uint32_t addr, uint32_t val)
                    120: {
                    121:     gb(s, CPU_SEG); /* seg movl im, addr */
                    122:     gb(s, 0x66); 
                    123:     gb(s, 0xc7); 
                    124:     gb(s, 0x05);
                    125:     gl(s, addr);
                    126:     gw(s, val);
                    127: }
                    128: 
                    129: 
                    130: static void gen_jmp(DisasContext *s, uint32_t target_eip)
                    131: {
                    132:     TranslationBlock *tb = s->tb;
                    133: 
                    134:     gb(s, 0xe9); /* jmp */
                    135:     tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;
                    136:     gl(s, 0);
                    137: 
                    138:     tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;
                    139:     gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);
                    140:     gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);
                    141:     gjmp(s, (long)&exec_loop);
                    142: 
                    143:     s->is_jmp = 1;
                    144: }
                    145: 
                    146: static void gen_jcc(DisasContext *s, int op,
                    147:                     uint32_t target_eip, uint32_t next_eip)
                    148: {
                    149:     TranslationBlock *tb = s->tb;
                    150: 
                    151:     gb(s, 0x0f); /* jcc */
                    152:     gb(s, 0x80 + op);
                    153:     tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;
                    154:     gl(s, 0);
                    155:     gb(s, 0xe9); /* jmp */
                    156:     tb->tb_jmp_offset[1] = s->gen_code_ptr - s->gen_code_start;
                    157:     gl(s, 0);
                    158:     
                    159:     tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;
                    160:     gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);
                    161:     gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);
                    162:     gjmp(s, (long)&exec_loop);
                    163: 
                    164:     tb->tb_next_offset[1] = s->gen_code_ptr - s->gen_code_start;
                    165:     gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), next_eip);
                    166:     gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb | 1);
                    167:     gjmp(s, (long)&exec_loop);
                    168: 
                    169:     s->is_jmp = 1;
                    170: }
                    171: 
                    172: static void gen_eob(DisasContext *s)
                    173: {
                    174:     gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), 0);
                    175:     gjmp(s, (long)&exec_loop);
                    176: 
                    177:     s->is_jmp = 1;
                    178: }
                    179: 
                    180: static inline void gen_lea_modrm(DisasContext *s, int modrm)
                    181: {
                    182:     int havesib;
                    183:     int base, disp;
                    184:     int index;
                    185:     int scale;
                    186:     int mod, rm, code;
                    187: 
                    188:     mod = (modrm >> 6) & 3;
                    189:     rm = modrm & 7;
                    190: 
                    191:     if (s->aflag) {
                    192: 
                    193:         havesib = 0;
                    194:         base = rm;
                    195:         index = 0;
                    196:         scale = 0;
                    197:         
                    198:         if (base == 4) {
                    199:             havesib = 1;
                    200:             code = ldub_code(s->pc++);
                    201:             scale = (code >> 6) & 3;
                    202:             index = (code >> 3) & 7;
                    203:             base = code & 7;
                    204:         }
                    205: 
                    206:         switch (mod) {
                    207:         case 0:
                    208:             if (base == 5) {
                    209:                 base = -1;
                    210:                 disp = ldl_code(s->pc);
                    211:                 s->pc += 4;
                    212:             } else {
                    213:                 disp = 0;
                    214:             }
                    215:             break;
                    216:         case 1:
                    217:             disp = (int8_t)ldub_code(s->pc++);
                    218:             break;
                    219:         default:
                    220:         case 2:
                    221:             disp = ldl_code(s->pc);
                    222:             s->pc += 4;
                    223:             break;
                    224:         }
                    225:         
                    226:     } else {
                    227:         switch (mod) {
                    228:         case 0:
                    229:             if (rm == 6) {
                    230:                 disp = lduw_code(s->pc);
                    231:                 s->pc += 2;
                    232:             } else {
                    233:                 disp = 0;
                    234:             }
                    235:             break;
                    236:         case 1:
                    237:             disp = (int8_t)ldub_code(s->pc++);
                    238:             break;
                    239:         default:
                    240:         case 2:
                    241:             disp = lduw_code(s->pc);
                    242:             s->pc += 2;
                    243:             break;
                    244:         }
                    245:     }
                    246: }
                    247: 
                    248: static inline void parse_modrm(DisasContext *s, int modrm)
                    249: {
                    250:     if ((modrm & 0xc0) != 0xc0)
                    251:         gen_lea_modrm(s, modrm);        
                    252: }
                    253: 
                    254: static inline uint32_t insn_get(DisasContext *s, int ot)
                    255: {
                    256:     uint32_t ret;
                    257: 
                    258:     switch(ot) {
                    259:     case OT_BYTE:
                    260:         ret = ldub_code(s->pc);
                    261:         s->pc++;
                    262:         break;
                    263:     case OT_WORD:
                    264:         ret = lduw_code(s->pc);
                    265:         s->pc += 2;
                    266:         break;
                    267:     default:
                    268:     case OT_LONG:
                    269:         ret = ldl_code(s->pc);
                    270:         s->pc += 4;
                    271:         break;
                    272:     }
                    273:     return ret;
                    274: }
                    275: 
                    276: /* convert one instruction. s->is_jmp is set if the translation must
                    277:    be stopped.  */
                    278: static int disas_insn(DisasContext *s)
                    279: {
                    280:     target_ulong pc_start, pc_tmp, pc_start_insn;
                    281:     int b, prefixes, aflag, dflag, next_eip, val;
                    282:     int ot;
                    283:     int modrm, mod, op, rm;
                    284: 
                    285:     pc_start = s->pc;
                    286:     prefixes = 0;
                    287:     aflag = s->code32;
                    288:     dflag = s->code32;
                    289:     s->override = -1;
                    290:  next_byte:
                    291:     b = ldub_code(s->pc);
                    292:     s->pc++;
                    293:     /* check prefixes */
                    294:     switch (b) {
                    295:     case 0xf3:
                    296:         prefixes |= PREFIX_REPZ;
                    297:         goto next_byte;
                    298:     case 0xf2:
                    299:         prefixes |= PREFIX_REPNZ;
                    300:         goto next_byte;
                    301:     case 0xf0:
                    302:         prefixes |= PREFIX_LOCK;
                    303:         goto next_byte;
                    304:     case 0x2e:
                    305:         s->override = R_CS;
                    306:         goto next_byte;
                    307:     case 0x36:
                    308:         s->override = R_SS;
                    309:         goto next_byte;
                    310:     case 0x3e:
                    311:         s->override = R_DS;
                    312:         goto next_byte;
                    313:     case 0x26:
                    314:         s->override = R_ES;
                    315:         goto next_byte;
                    316:     case 0x64:
                    317:         s->override = R_FS;
                    318:         goto next_byte;
                    319:     case 0x65:
                    320:         s->override = R_GS;
                    321:         goto next_byte;
                    322:     case 0x66:
                    323:         prefixes |= PREFIX_DATA;
                    324:         goto next_byte;
                    325:     case 0x67:
                    326:         prefixes |= PREFIX_ADR;
                    327:         goto next_byte;
                    328:     }
                    329: 
                    330:     if (prefixes & PREFIX_DATA)
                    331:         dflag ^= 1;
                    332:     if (prefixes & PREFIX_ADR)
                    333:         aflag ^= 1;
                    334: 
                    335:     s->prefix = prefixes;
                    336:     s->aflag = aflag;
                    337:     s->dflag = dflag;
                    338: 
                    339:     /* lock generation */
                    340:     if (prefixes & PREFIX_LOCK)
                    341:         goto unsupported_op;
                    342:     if (s->override == R_FS || s->override == R_GS || s->override == R_CS)
                    343:         goto unsupported_op;
                    344: 
                    345:     pc_start_insn = s->pc - 1;
                    346:     /* now check op code */
                    347:  reswitch:
                    348:     switch(b) {
                    349:     case 0x0f:
                    350:         /**************************/
                    351:         /* extended op code */
                    352:         b = ldub_code(s->pc++) | 0x100;
                    353:         goto reswitch;
                    354:         
                    355:         /**************************/
                    356:         /* arith & logic */
                    357:     case 0x00 ... 0x05:
                    358:     case 0x08 ... 0x0d:
                    359:     case 0x10 ... 0x15:
                    360:     case 0x18 ... 0x1d:
                    361:     case 0x20 ... 0x25:
                    362:     case 0x28 ... 0x2d:
                    363:     case 0x30 ... 0x35:
                    364:     case 0x38 ... 0x3d:
                    365:         {
                    366:             int f;
                    367:             f = (b >> 1) & 3;
                    368: 
                    369:             if ((b & 1) == 0)
                    370:                 ot = OT_BYTE;
                    371:             else
                    372:                 ot = dflag ? OT_LONG : OT_WORD;
                    373:             
                    374:             switch(f) {
                    375:             case 0: /* OP Ev, Gv */
                    376:                 modrm = ldub_code(s->pc++);
                    377:                 parse_modrm(s, modrm);
                    378:                 break;
                    379:             case 1: /* OP Gv, Ev */
                    380:                 modrm = ldub_code(s->pc++);
                    381:                 parse_modrm(s, modrm);
                    382:                 break;
                    383:             case 2: /* OP A, Iv */
                    384:                 insn_get(s, ot);
                    385:                 break;
                    386:             }
                    387:         }
                    388:         break;
                    389: 
                    390:     case 0x80: /* GRP1 */
                    391:     case 0x81:
                    392:     case 0x82:
                    393:     case 0x83:
                    394:         {
                    395:             if ((b & 1) == 0)
                    396:                 ot = OT_BYTE;
                    397:             else
                    398:                 ot = dflag ? OT_LONG : OT_WORD;
                    399:             
                    400:             modrm = ldub_code(s->pc++);
                    401:             parse_modrm(s, modrm);
                    402: 
                    403:             switch(b) {
                    404:             default:
                    405:             case 0x80:
                    406:             case 0x81:
                    407:             case 0x82:
                    408:                 insn_get(s, ot);
                    409:                 break;
                    410:             case 0x83:
                    411:                 insn_get(s, OT_BYTE);
                    412:                 break;
                    413:             }
                    414:         }
                    415:         break;
                    416: 
                    417:         /**************************/
                    418:         /* inc, dec, and other misc arith */
                    419:     case 0x40 ... 0x47: /* inc Gv */
                    420:         break;
                    421:     case 0x48 ... 0x4f: /* dec Gv */
                    422:         break;
                    423:     case 0xf6: /* GRP3 */
                    424:     case 0xf7:
                    425:         if ((b & 1) == 0)
                    426:             ot = OT_BYTE;
                    427:         else
                    428:             ot = dflag ? OT_LONG : OT_WORD;
                    429: 
                    430:         modrm = ldub_code(s->pc++);
                    431:         op = (modrm >> 3) & 7;
                    432:         parse_modrm(s, modrm);
                    433: 
                    434:         switch(op) {
                    435:         case 0: /* test */
                    436:             insn_get(s, ot);
                    437:             break;
                    438:         case 2: /* not */
                    439:             break;
                    440:         case 3: /* neg */
                    441:             break;
                    442:         case 4: /* mul */
                    443:             break;
                    444:         case 5: /* imul */
                    445:             break;
                    446:         case 6: /* div */
                    447:             break;
                    448:         case 7: /* idiv */
                    449:             break;
                    450:         default:
                    451:             goto illegal_op;
                    452:         }
                    453:         break;
                    454: 
                    455:     case 0xfe: /* GRP4 */
                    456:     case 0xff: /* GRP5 */
                    457:         if ((b & 1) == 0)
                    458:             ot = OT_BYTE;
                    459:         else
                    460:             ot = dflag ? OT_LONG : OT_WORD;
                    461: 
                    462:         modrm = ldub_code(s->pc++);
                    463:         mod = (modrm >> 6) & 3;
                    464:         op = (modrm >> 3) & 7;
                    465:         if (op >= 2 && b == 0xfe) {
                    466:             goto illegal_op;
                    467:         }
                    468:         pc_tmp = s->pc;
                    469:         parse_modrm(s, modrm);
                    470: 
                    471:         switch(op) {
                    472:         case 0: /* inc Ev */
                    473:             break;
                    474:         case 1: /* dec Ev */
                    475:             break;
                    476:         case 2: /* call Ev */
                    477:             /* XXX: optimize and handle MEM exceptions specifically
                    478:                fs movl %eax, regs[0] 
                    479:                movl Ev, %eax 
                    480:                pushl next_eip
                    481:                fs movl %eax, eip
                    482:             */
                    483:             goto unsupported_op;
                    484:         case 3: /* lcall Ev */
                    485:             goto unsupported_op;
                    486:         case 4: /* jmp Ev */
                    487:             /* XXX: optimize and handle MEM exceptions specifically
                    488:                fs movl %eax, regs[0] 
                    489:                movl Ev, %eax 
                    490:                fs movl %eax, eip
                    491:             */
                    492:             goto unsupported_op;
                    493:         case 5: /* ljmp Ev */
                    494:             goto unsupported_op;
                    495:         case 6: /* push Ev */
                    496:             break;
                    497:         default:
                    498:             goto illegal_op;
                    499:         }
                    500:         break;
                    501:     case 0xa8: /* test eAX, Iv */
                    502:     case 0xa9:
                    503:         if ((b & 1) == 0)
                    504:             ot = OT_BYTE;
                    505:         else
                    506:             ot = dflag ? OT_LONG : OT_WORD;
                    507:         insn_get(s, ot);
                    508:         break;
                    509:         
                    510:     case 0x98: /* CWDE/CBW */
                    511:         break;
                    512:     case 0x99: /* CDQ/CWD */
                    513:         break;
                    514:     case 0x1af: /* imul Gv, Ev */
                    515:     case 0x69: /* imul Gv, Ev, I */
                    516:     case 0x6b:
                    517:         ot = dflag ? OT_LONG : OT_WORD;
                    518:         modrm = ldub_code(s->pc++);
                    519:         parse_modrm(s, modrm);
                    520:         if (b == 0x69) {
                    521:             insn_get(s, ot);
                    522:         } else if (b == 0x6b) {
                    523:             insn_get(s, OT_BYTE);
                    524:         } else {
                    525:         }
                    526:         break;
                    527: 
                    528:     case 0x84: /* test Ev, Gv */
                    529:     case 0x85: 
                    530:         
                    531:     case 0x1c0:
                    532:     case 0x1c1: /* xadd Ev, Gv */
                    533: 
                    534:     case 0x1b0:
                    535:     case 0x1b1: /* cmpxchg Ev, Gv */
                    536: 
                    537:     case 0x8f: /* pop Ev */
                    538: 
                    539:     case 0x88:
                    540:     case 0x89: /* mov Gv, Ev */
                    541: 
                    542:     case 0x8a:
                    543:     case 0x8b: /* mov Ev, Gv */
                    544: 
                    545:     case 0x1b6: /* movzbS Gv, Eb */
                    546:     case 0x1b7: /* movzwS Gv, Eb */
                    547:     case 0x1be: /* movsbS Gv, Eb */
                    548:     case 0x1bf: /* movswS Gv, Eb */
                    549: 
                    550:     case 0x86:
                    551:     case 0x87: /* xchg Ev, Gv */
                    552: 
                    553:     case 0xd0:
                    554:     case 0xd1: /* shift Ev,1 */
                    555: 
                    556:     case 0xd2:
                    557:     case 0xd3: /* shift Ev,cl */
                    558: 
                    559:     case 0x1a5: /* shld cl */
                    560:     case 0x1ad: /* shrd cl */
                    561: 
                    562:     case 0x190 ... 0x19f: /* setcc Gv */
                    563: 
                    564:     /* XXX: emulate cmov if not available ? */
                    565:     case 0x140 ... 0x14f: /* cmov Gv, Ev */
                    566: 
                    567:     case 0x1a3: /* bt Gv, Ev */
                    568:     case 0x1ab: /* bts */
                    569:     case 0x1b3: /* btr */
                    570:     case 0x1bb: /* btc */
                    571: 
                    572:     case 0x1bc: /* bsf */
                    573:     case 0x1bd: /* bsr */
                    574: 
                    575:         modrm = ldub_code(s->pc++);
                    576:         parse_modrm(s, modrm);
                    577:         break;
                    578: 
                    579:     case 0x1c7: /* cmpxchg8b */
                    580:         modrm = ldub_code(s->pc++);
                    581:         mod = (modrm >> 6) & 3;
                    582:         if (mod == 3)
                    583:             goto illegal_op;
                    584:         parse_modrm(s, modrm);
                    585:         break;
                    586:         
                    587:         /**************************/
                    588:         /* push/pop */
                    589:     case 0x50 ... 0x57: /* push */
                    590:     case 0x58 ... 0x5f: /* pop */
                    591:     case 0x60: /* pusha */
                    592:     case 0x61: /* popa */
                    593:         break;
                    594: 
                    595:     case 0x68: /* push Iv */
                    596:     case 0x6a:
                    597:         ot = dflag ? OT_LONG : OT_WORD;
                    598:         if (b == 0x68)
                    599:             insn_get(s, ot);
                    600:         else
                    601:             insn_get(s, OT_BYTE);
                    602:         break;
                    603:     case 0xc8: /* enter */
                    604:         lduw_code(s->pc);
                    605:         s->pc += 2;
                    606:         ldub_code(s->pc++);
                    607:         break;
                    608:     case 0xc9: /* leave */
                    609:         break;
                    610: 
                    611:     case 0x06: /* push es */
                    612:     case 0x0e: /* push cs */
                    613:     case 0x16: /* push ss */
                    614:     case 0x1e: /* push ds */
                    615:         /* XXX: optimize:
                    616:          push segs[n].selector
                    617:         */
                    618:         goto unsupported_op;
                    619:     case 0x1a0: /* push fs */
                    620:     case 0x1a8: /* push gs */
                    621:         goto unsupported_op;
                    622:     case 0x07: /* pop es */
                    623:     case 0x17: /* pop ss */
                    624:     case 0x1f: /* pop ds */
                    625:         goto unsupported_op;
                    626:     case 0x1a1: /* pop fs */
                    627:     case 0x1a9: /* pop gs */
                    628:         goto unsupported_op;
                    629:     case 0x8e: /* mov seg, Gv */
                    630:         /* XXX: optimize:
                    631:            fs movl r, regs[]
                    632:            movl segs[].selector, r
                    633:            mov r, Gv
                    634:            fs movl regs[], r
                    635:         */
                    636:         goto unsupported_op;
                    637:     case 0x8c: /* mov Gv, seg */
                    638:         goto unsupported_op;
                    639:     case 0xc4: /* les Gv */
                    640:         op = R_ES;
                    641:         goto do_lxx;
                    642:     case 0xc5: /* lds Gv */
                    643:         op = R_DS;
                    644:         goto do_lxx;
                    645:     case 0x1b2: /* lss Gv */
                    646:         op = R_SS;
                    647:         goto do_lxx;
                    648:     case 0x1b4: /* lfs Gv */
                    649:         op = R_FS;
                    650:         goto do_lxx;
                    651:     case 0x1b5: /* lgs Gv */
                    652:         op = R_GS;
                    653:     do_lxx:
                    654:         goto unsupported_op;
                    655:         /************************/
                    656:         /* floats */
                    657:     case 0xd8 ... 0xdf: 
                    658: #if 1
                    659:         /* currently not stable enough */
                    660:         goto unsupported_op;
                    661: #else
                    662:         if (s->flags & (HF_EM_MASK | HF_TS_MASK))
                    663:             goto unsupported_op;
                    664: #endif
                    665: #if 0
                    666:         /* for testing FPU context switch */
                    667:         {
                    668:             static int count;
                    669:             count = (count + 1) % 3;
                    670:             if (count != 0)
                    671:                 goto unsupported_op;
                    672:         }
                    673: #endif
                    674:         modrm = ldub_code(s->pc++);
                    675:         mod = (modrm >> 6) & 3;
                    676:         rm = modrm & 7;
                    677:         op = ((b & 7) << 3) | ((modrm >> 3) & 7);
                    678:         if (mod != 3) {
                    679:             /* memory op */
                    680:             parse_modrm(s, modrm);
                    681:             switch(op) {
                    682:             case 0x00 ... 0x07: /* fxxxs */
                    683:             case 0x10 ... 0x17: /* fixxxl */
                    684:             case 0x20 ... 0x27: /* fxxxl */
                    685:             case 0x30 ... 0x37: /* fixxx */
                    686:                 break;
                    687:             case 0x08: /* flds */
                    688:             case 0x0a: /* fsts */
                    689:             case 0x0b: /* fstps */
                    690:             case 0x18: /* fildl */
                    691:             case 0x1a: /* fistl */
                    692:             case 0x1b: /* fistpl */
                    693:             case 0x28: /* fldl */
                    694:             case 0x2a: /* fstl */
                    695:             case 0x2b: /* fstpl */
                    696:             case 0x38: /* filds */
                    697:             case 0x3a: /* fists */
                    698:             case 0x3b: /* fistps */
                    699:             case 0x0c: /* fldenv mem */
                    700:             case 0x0d: /* fldcw mem */
                    701:             case 0x0e: /* fnstenv mem */
                    702:             case 0x0f: /* fnstcw mem */
                    703:             case 0x1d: /* fldt mem */
                    704:             case 0x1f: /* fstpt mem */
                    705:             case 0x2c: /* frstor mem */
                    706:             case 0x2e: /* fnsave mem */
                    707:             case 0x2f: /* fnstsw mem */
                    708:             case 0x3c: /* fbld */
                    709:             case 0x3e: /* fbstp */
                    710:             case 0x3d: /* fildll */
                    711:             case 0x3f: /* fistpll */
                    712:                 break;
                    713:             default:
                    714:                 goto illegal_op;
                    715:             }
                    716:         } else {
                    717:             /* register float ops */
                    718:             switch(op) {
                    719:             case 0x08: /* fld sti */
                    720:             case 0x09: /* fxchg sti */
                    721:                 break;
                    722:             case 0x0a: /* grp d9/2 */
                    723:                 switch(rm) {
                    724:                 case 0: /* fnop */
                    725:                     break;
                    726:                 default:
                    727:                     goto illegal_op;
                    728:                 }
                    729:                 break;
                    730:             case 0x0c: /* grp d9/4 */
                    731:                 switch(rm) {
                    732:                 case 0: /* fchs */
                    733:                 case 1: /* fabs */
                    734:                 case 4: /* ftst */
                    735:                 case 5: /* fxam */
                    736:                     break;
                    737:                 default:
                    738:                     goto illegal_op;
                    739:                 }
                    740:                 break;
                    741:             case 0x0d: /* grp d9/5 */
                    742:                 switch(rm) {
                    743:                 case 0:
                    744:                 case 1:
                    745:                 case 2:
                    746:                 case 3:
                    747:                 case 4:
                    748:                 case 5:
                    749:                 case 6:
                    750:                     break;
                    751:                 default:
                    752:                     goto illegal_op;
                    753:                 }
                    754:                 break;
                    755:             case 0x0e: /* grp d9/6 */
                    756:                 break;
                    757:             case 0x0f: /* grp d9/7 */
                    758:                 break;
                    759:             case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
                    760:             case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
                    761:             case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
                    762:                 break;
                    763:             case 0x02: /* fcom */
                    764:                 break;
                    765:             case 0x03: /* fcomp */
                    766:                 break;
                    767:             case 0x15: /* da/5 */
                    768:                 switch(rm) {
                    769:                 case 1: /* fucompp */
                    770:                     break;
                    771:                 default:
                    772:                     goto illegal_op;
                    773:                 }
                    774:                 break;
                    775:             case 0x1c:
                    776:                 switch(rm) {
                    777:                 case 0: /* feni (287 only, just do nop here) */
                    778:                 case 1: /* fdisi (287 only, just do nop here) */
                    779:                     goto unsupported_op;
                    780:                 case 2: /* fclex */
                    781:                 case 3: /* fninit */
                    782:                 case 4: /* fsetpm (287 only, just do nop here) */
                    783:                     break;
                    784:                 default:
                    785:                     goto illegal_op;
                    786:                 }
                    787:                 break;
                    788:             case 0x1d: /* fucomi */
                    789:                 break;
                    790:             case 0x1e: /* fcomi */
                    791:                 break;
                    792:             case 0x28: /* ffree sti */
                    793:                 break;
                    794:             case 0x2a: /* fst sti */
                    795:                 break;
                    796:             case 0x2b: /* fstp sti */
                    797:                 break;
                    798:             case 0x2c: /* fucom st(i) */
                    799:                 break;
                    800:             case 0x2d: /* fucomp st(i) */
                    801:                 break;
                    802:             case 0x33: /* de/3 */
                    803:                 switch(rm) {
                    804:                 case 1: /* fcompp */
                    805:                     break;
                    806:                 default:
                    807:                     goto illegal_op;
                    808:                 }
                    809:                 break;
                    810:             case 0x3c: /* df/4 */
                    811:                 switch(rm) {
                    812:                 case 0:
                    813:                     break;
                    814:                 default:
                    815:                     goto illegal_op;
                    816:                 }
                    817:                 break;
                    818:             case 0x3d: /* fucomip */
                    819:                 break;
                    820:             case 0x3e: /* fcomip */
                    821:                 break;
                    822:             case 0x10 ... 0x13: /* fcmovxx */
                    823:             case 0x18 ... 0x1b:
                    824:                 break;
                    825:             default:
                    826:                 goto illegal_op;
                    827:             }
                    828:         }
                    829:         s->tb->cflags |= CF_TB_FP_USED;
                    830:         break;
                    831: 
                    832:         /**************************/
                    833:         /* mov */
                    834:     case 0xc6:
                    835:     case 0xc7: /* mov Ev, Iv */
                    836:         if ((b & 1) == 0)
                    837:             ot = OT_BYTE;
                    838:         else
                    839:             ot = dflag ? OT_LONG : OT_WORD;
                    840:         modrm = ldub_code(s->pc++);
                    841:         parse_modrm(s, modrm);
                    842:         insn_get(s, ot);
                    843:         break;
                    844: 
                    845:     case 0x8d: /* lea */
                    846:         ot = dflag ? OT_LONG : OT_WORD;
                    847:         modrm = ldub_code(s->pc++);
                    848:         mod = (modrm >> 6) & 3;
                    849:         if (mod == 3)
                    850:             goto illegal_op;
                    851:         parse_modrm(s, modrm);
                    852:         break;
                    853:         
                    854:     case 0xa0: /* mov EAX, Ov */
                    855:     case 0xa1:
                    856:     case 0xa2: /* mov Ov, EAX */
                    857:     case 0xa3:
                    858:         if ((b & 1) == 0)
                    859:             ot = OT_BYTE;
                    860:         else
                    861:             ot = dflag ? OT_LONG : OT_WORD;
                    862:         if (s->aflag)
                    863:             insn_get(s, OT_LONG);
                    864:         else
                    865:             insn_get(s, OT_WORD);
                    866:         break;
                    867:     case 0xd7: /* xlat */
                    868:         break;
                    869:     case 0xb0 ... 0xb7: /* mov R, Ib */
                    870:         insn_get(s, OT_BYTE);
                    871:         break;
                    872:     case 0xb8 ... 0xbf: /* mov R, Iv */
                    873:         ot = dflag ? OT_LONG : OT_WORD;
                    874:         insn_get(s, ot);
                    875:         break;
                    876: 
                    877:     case 0x91 ... 0x97: /* xchg R, EAX */
                    878:         break;
                    879: 
                    880:         /************************/
                    881:         /* shifts */
                    882:     case 0xc0:
                    883:     case 0xc1: /* shift Ev,imm */
                    884: 
                    885:     case 0x1a4: /* shld imm */
                    886:     case 0x1ac: /* shrd imm */
                    887:         modrm = ldub_code(s->pc++);
                    888:         parse_modrm(s, modrm);
                    889:         ldub_code(s->pc++);
                    890:         break;
                    891:         
                    892:         /************************/
                    893:         /* string ops */
                    894: 
                    895:     case 0xa4: /* movsS */
                    896:     case 0xa5:
                    897:         break;
                    898:         
                    899:     case 0xaa: /* stosS */
                    900:     case 0xab:
                    901:         break;
                    902: 
                    903:     case 0xac: /* lodsS */
                    904:     case 0xad:
                    905:         break;
                    906: 
                    907:     case 0xae: /* scasS */
                    908:     case 0xaf:
                    909:         break;
                    910: 
                    911:     case 0xa6: /* cmpsS */
                    912:     case 0xa7:
                    913:         break;
                    914: 
                    915:     case 0x6c: /* insS */
                    916:     case 0x6d:
                    917:         goto unsupported_op;
                    918: 
                    919:     case 0x6e: /* outsS */
                    920:     case 0x6f:
                    921:         goto unsupported_op;
                    922: 
                    923:         /************************/
                    924:         /* port I/O */
                    925:     case 0xe4:
                    926:     case 0xe5:
                    927:         goto unsupported_op;
                    928: 
                    929:     case 0xe6:
                    930:     case 0xe7:
                    931:         goto unsupported_op;
                    932: 
                    933:     case 0xec:
                    934:     case 0xed:
                    935:         goto unsupported_op;
                    936: 
                    937:     case 0xee:
                    938:     case 0xef:
                    939:         goto unsupported_op;
                    940: 
                    941:         /************************/
                    942:         /* control */
                    943: #if 0
                    944:     case 0xc2: /* ret im */
                    945:         val = ldsw_code(s->pc);
                    946:         s->pc += 2;
                    947:         gen_pop_T0(s);
                    948:         gen_stack_update(s, val + (2 << s->dflag));
                    949:         if (s->dflag == 0)
                    950:             gen_op_andl_T0_ffff();
                    951:         gen_op_jmp_T0();
                    952:         gen_eob(s);
                    953:         break;
                    954: #endif
                    955: 
                    956:     case 0xc3: /* ret */
                    957:         gb(s, CPU_SEG);
                    958:         if (!s->dflag)  
                    959:             gb(s, 0x66); /* d16 */
                    960:         gb(s, 0x8f); /* pop addr */
                    961:         gb(s, 0x05);
                    962:         gl(s, CPU_FIELD_OFFSET(eip));
                    963:         if (!s->dflag) {
                    964:             /* reset high bits of EIP */
                    965:             gen_movw_addr_im(s, CPU_FIELD_OFFSET(eip) + 2, 0);
                    966:         }
                    967:         gen_eob(s);
                    968:         goto no_copy;
                    969:     case 0xca: /* lret im */
                    970:     case 0xcb: /* lret */
                    971:     case 0xcf: /* iret */
                    972:     case 0x9a: /* lcall im */
                    973:     case 0xea: /* ljmp im */
                    974:         goto unsupported_op;
                    975: 
                    976:     case 0xe8: /* call im */
                    977:         ot = dflag ? OT_LONG : OT_WORD;
                    978:         val = insn_get(s, ot);
                    979:         next_eip = s->pc - s->cs_base;
                    980:         val += next_eip;
                    981:         if (s->dflag) {
                    982:             gb(s, 0x68); /* pushl imm */
                    983:             gl(s, next_eip);
                    984:         } else {
                    985:             gb(s, 0x66); /* pushw imm */
                    986:             gb(s, 0x68);
                    987:             gw(s, next_eip);
                    988:             val &= 0xffff;
                    989:         }
                    990:         gen_jmp(s, val);
                    991:         goto no_copy;
                    992:     case 0xe9: /* jmp */
                    993:         ot = dflag ? OT_LONG : OT_WORD;
                    994:         val = insn_get(s, ot);
                    995:         val += s->pc - s->cs_base;
                    996:         if (s->dflag == 0)
                    997:             val = val & 0xffff;
                    998:         gen_jmp(s, val);
                    999:         goto no_copy;
                   1000:     case 0xeb: /* jmp Jb */
                   1001:         val = (int8_t)insn_get(s, OT_BYTE);
                   1002:         val += s->pc - s->cs_base;
                   1003:         if (s->dflag == 0)
                   1004:             val = val & 0xffff;
                   1005:         gen_jmp(s, val);
                   1006:         goto no_copy;
                   1007:     case 0x70 ... 0x7f: /* jcc Jb */
                   1008:         val = (int8_t)insn_get(s, OT_BYTE);
                   1009:         goto do_jcc;
                   1010:     case 0x180 ... 0x18f: /* jcc Jv */
                   1011:         if (dflag) {
                   1012:             val = insn_get(s, OT_LONG);
                   1013:         } else {
                   1014:             val = (int16_t)insn_get(s, OT_WORD); 
                   1015:         }
                   1016:     do_jcc:
                   1017:         next_eip = s->pc - s->cs_base;
                   1018:         val += next_eip;
                   1019:         if (s->dflag == 0)
                   1020:             val &= 0xffff;
                   1021:         gen_jcc(s, b & 0xf, val, next_eip);
                   1022:         goto no_copy;
                   1023: 
                   1024:         /************************/
                   1025:         /* flags */
                   1026:     case 0x9c: /* pushf */
                   1027:         /* XXX: put specific code ? */
                   1028:         goto unsupported_op;
                   1029:     case 0x9d: /* popf */
                   1030:         goto unsupported_op;
                   1031: 
                   1032:     case 0x9e: /* sahf */
                   1033:     case 0x9f: /* lahf */
                   1034:     case 0xf5: /* cmc */
                   1035:     case 0xf8: /* clc */
                   1036:     case 0xf9: /* stc */
                   1037:     case 0xfc: /* cld */
                   1038:     case 0xfd: /* std */
                   1039:         break;
                   1040: 
                   1041:         /************************/
                   1042:         /* bit operations */
                   1043:     case 0x1ba: /* bt/bts/btr/btc Gv, im */
                   1044:         ot = dflag ? OT_LONG : OT_WORD;
                   1045:         modrm = ldub_code(s->pc++);
                   1046:         op = (modrm >> 3) & 7;
                   1047:         parse_modrm(s, modrm);
                   1048:         /* load shift */
                   1049:         ldub_code(s->pc++);
                   1050:         if (op < 4)
                   1051:             goto illegal_op;
                   1052:         break;
                   1053:         /************************/
                   1054:         /* bcd */
                   1055:     case 0x27: /* daa */
                   1056:         break;
                   1057:     case 0x2f: /* das */
                   1058:         break;
                   1059:     case 0x37: /* aaa */
                   1060:         break;
                   1061:     case 0x3f: /* aas */
                   1062:         break;
                   1063:     case 0xd4: /* aam */
                   1064:         ldub_code(s->pc++);
                   1065:         break;
                   1066:     case 0xd5: /* aad */
                   1067:         ldub_code(s->pc++);
                   1068:         break;
                   1069:         /************************/
                   1070:         /* misc */
                   1071:     case 0x90: /* nop */
                   1072:         break;
                   1073:     case 0x9b: /* fwait */
                   1074:         if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) == 
                   1075:             (HF_MP_MASK | HF_TS_MASK)) {
                   1076:             goto unsupported_op;
                   1077:         }
                   1078:         break;
                   1079:     case 0xcc: /* int3 */
                   1080:         goto unsupported_op;
                   1081:     case 0xcd: /* int N */
                   1082:         goto unsupported_op;
                   1083:     case 0xce: /* into */
                   1084:         goto unsupported_op;
                   1085:     case 0xf1: /* icebp (undocumented, exits to external debugger) */
                   1086:         goto unsupported_op;
                   1087:     case 0xfa: /* cli */
                   1088:         goto unsupported_op;
                   1089:     case 0xfb: /* sti */
                   1090:         goto unsupported_op;
                   1091:     case 0x62: /* bound */
                   1092:         modrm = ldub_code(s->pc++);
                   1093:         mod = (modrm >> 6) & 3;
                   1094:         if (mod == 3)
                   1095:             goto illegal_op;
                   1096:         parse_modrm(s, modrm);
                   1097:         break;
                   1098:     case 0x1c8 ... 0x1cf: /* bswap reg */
                   1099:         break;
                   1100:     case 0xd6: /* salc */
                   1101:         break;
                   1102:     case 0xe0: /* loopnz */
                   1103:     case 0xe1: /* loopz */
                   1104:     case 0xe2: /* loop */
                   1105:     case 0xe3: /* jecxz */
                   1106:         goto unsupported_op;
                   1107: 
                   1108:     case 0x130: /* wrmsr */
                   1109:     case 0x132: /* rdmsr */
                   1110:         goto unsupported_op;
                   1111:     case 0x131: /* rdtsc */
                   1112:         goto unsupported_op;
                   1113:     case 0x1a2: /* cpuid */
                   1114:         goto unsupported_op;
                   1115:     case 0xf4: /* hlt */
                   1116:         goto unsupported_op;
                   1117:     case 0x100:
                   1118:         goto unsupported_op;
                   1119:     case 0x101:
                   1120:         goto unsupported_op;
                   1121:     case 0x108: /* invd */
                   1122:     case 0x109: /* wbinvd */
                   1123:         goto unsupported_op;
                   1124:     case 0x63: /* arpl */
                   1125:         goto unsupported_op;
                   1126:     case 0x102: /* lar */
                   1127:     case 0x103: /* lsl */
                   1128:         goto unsupported_op;
                   1129:     case 0x118:
                   1130:         goto unsupported_op;
                   1131:     case 0x120: /* mov reg, crN */
                   1132:     case 0x122: /* mov crN, reg */
                   1133:         goto unsupported_op;
                   1134:     case 0x121: /* mov reg, drN */
                   1135:     case 0x123: /* mov drN, reg */
                   1136:         goto unsupported_op;
                   1137:     case 0x106: /* clts */
                   1138:         goto unsupported_op;
                   1139:     default:
                   1140:         goto illegal_op;
                   1141:     }
                   1142: 
                   1143:     /* just copy the code */
                   1144: 
                   1145:     /* no override yet */
                   1146:     if (!s->dflag)
                   1147:         gb(s, 0x66);
                   1148:     if (!s->aflag)
                   1149:         gb(s, 0x67);
                   1150:     if (prefixes & PREFIX_REPZ)
                   1151:         gb(s, 0xf3);
                   1152:     else if (prefixes & PREFIX_REPNZ)
                   1153:         gb(s, 0xf2);
                   1154:     {
                   1155:         int len, i;
                   1156:         len = s->pc - pc_start_insn;
                   1157:         for(i = 0; i < len; i++) {
                   1158:             *s->gen_code_ptr++ = ldub_code(pc_start_insn + i);
                   1159:         }
                   1160:     }
                   1161:  no_copy:
                   1162:     return 0;
                   1163:  illegal_op:
                   1164:  unsupported_op:
                   1165:     /* fall back to slower code gen necessary */
                   1166:     s->pc = pc_start;
                   1167:     return -1;
                   1168: }
                   1169: 
                   1170: #define GEN_CODE_MAX_SIZE      8192
                   1171: #define GEN_CODE_MAX_INSN_SIZE 512
                   1172: 
                   1173: static inline int gen_intermediate_code_internal(CPUState *env,
                   1174:                                                  TranslationBlock *tb, 
                   1175:                                                  uint8_t *gen_code_ptr,
                   1176:                                                  int *gen_code_size_ptr,
                   1177:                                                  int search_pc,
                   1178:                                                  uint8_t *tc_ptr)
                   1179: {
                   1180:     DisasContext dc1, *dc = &dc1;
                   1181:     target_ulong pc_insn, pc_start, cs_base;
                   1182:     uint8_t *gen_code_end;
                   1183:     int flags, ret;
                   1184: 
                   1185:     if (env->nb_breakpoints > 0 ||
                   1186:         env->singlestep_enabled)
                   1187:         return -1;
                   1188:     flags = tb->flags;
                   1189:     if (flags & (HF_TF_MASK | HF_ADDSEG_MASK | 
                   1190:                  HF_SOFTMMU_MASK | HF_INHIBIT_IRQ_MASK))
                   1191:         return -1;
                   1192:     if (!(flags & HF_SS32_MASK))
                   1193:         return -1;
                   1194:     if (tb->cflags & CF_SINGLE_INSN)
                   1195:         return -1;
                   1196:     gen_code_end = gen_code_ptr + 
                   1197:         GEN_CODE_MAX_SIZE - GEN_CODE_MAX_INSN_SIZE;
                   1198:     dc->gen_code_ptr = gen_code_ptr;
                   1199:     dc->gen_code_start = gen_code_ptr;
                   1200: 
                   1201:     /* generate intermediate code */
                   1202:     pc_start = tb->pc;
                   1203:     cs_base = tb->cs_base;
                   1204:     dc->pc = pc_start;
                   1205:     dc->cs_base = cs_base;
                   1206:     dc->pe = (flags >> HF_PE_SHIFT) & 1;
                   1207:     dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
                   1208:     dc->f_st = 0;
                   1209:     dc->vm86 = (flags >> VM_SHIFT) & 1;
                   1210:     dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
                   1211:     dc->iopl = (flags >> IOPL_SHIFT) & 3;
                   1212:     dc->tb = tb;
                   1213:     dc->flags = flags;
                   1214: 
                   1215:     dc->is_jmp = 0;
                   1216: 
                   1217:     for(;;) {
                   1218:         pc_insn = dc->pc;
                   1219:         ret = disas_insn(dc);
                   1220:         if (ret < 0) {
                   1221:             /* unsupported insn */
                   1222:             if (dc->pc == pc_start) {
                   1223:                 /* if first instruction, signal that no copying was done */
                   1224:                 return -1;
                   1225:             } else {
                   1226:                 gen_jmp(dc, dc->pc - dc->cs_base);
                   1227:                 dc->is_jmp = 1;
                   1228:             }
                   1229:         }
                   1230:         if (search_pc) {
                   1231:             /* search pc mode */
                   1232:             if (tc_ptr < dc->gen_code_ptr) {
                   1233:                 env->eip = pc_insn - cs_base;
                   1234:                 return 0;
                   1235:             }
                   1236:         }
                   1237:         /* stop translation if indicated */
                   1238:         if (dc->is_jmp)
                   1239:             break;
                   1240:         /* if too long translation, stop generation */
                   1241:         if (dc->gen_code_ptr >= gen_code_end ||
                   1242:             (dc->pc - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
                   1243:             gen_jmp(dc, dc->pc - dc->cs_base);
                   1244:             break;
                   1245:         }
                   1246:     }
                   1247:     
                   1248: #ifdef DEBUG_DISAS
                   1249:     if (loglevel & CPU_LOG_TB_IN_ASM) {
                   1250:         fprintf(logfile, "----------------\n");
                   1251:         fprintf(logfile, "IN: COPY: %s fpu=%d\n", 
                   1252:                 lookup_symbol(pc_start),
                   1253:                 tb->cflags & CF_TB_FP_USED ? 1 : 0);
                   1254:        target_disas(logfile, pc_start, dc->pc - pc_start, !dc->code32);
                   1255:         fprintf(logfile, "\n");
                   1256:     }
                   1257: #endif
                   1258: 
                   1259:     if (!search_pc) {
                   1260:         *gen_code_size_ptr = dc->gen_code_ptr - dc->gen_code_start;
                   1261:         tb->size = dc->pc - pc_start;
                   1262:         tb->cflags |= CF_CODE_COPY;
                   1263:         return 0;
                   1264:     } else {
                   1265:         return -1;
                   1266:     }
                   1267: }
                   1268: 
                   1269: /* generate code by just copying data. Return -1 if cannot generate
                   1270:    any code. Return 0 if code was generated */
                   1271: int cpu_gen_code_copy(CPUState *env, TranslationBlock *tb,
                   1272:                       int max_code_size, int *gen_code_size_ptr)
                   1273: {
                   1274:     /* generate machine code */
                   1275:     tb->tb_next_offset[0] = 0xffff;
                   1276:     tb->tb_next_offset[1] = 0xffff;
                   1277: #ifdef USE_DIRECT_JUMP
                   1278:     /* the following two entries are optional (only used for string ops) */
                   1279:     tb->tb_jmp_offset[2] = 0xffff;
                   1280:     tb->tb_jmp_offset[3] = 0xffff;
                   1281: #endif
                   1282:     return gen_intermediate_code_internal(env, tb, 
                   1283:                                           tb->tc_ptr, gen_code_size_ptr,
                   1284:                                           0, NULL);
                   1285: }
                   1286: 
                   1287: static uint8_t dummy_gen_code_buf[GEN_CODE_MAX_SIZE];
                   1288: 
                   1289: int cpu_restore_state_copy(TranslationBlock *tb, 
                   1290:                            CPUState *env, unsigned long searched_pc,
                   1291:                            void *puc)
                   1292: {
                   1293:     struct ucontext *uc = puc;
                   1294:     int ret, eflags;
                   1295: 
                   1296:     /* find opc index corresponding to search_pc */
                   1297:     if (searched_pc < (unsigned long)tb->tc_ptr)
                   1298:         return -1;
                   1299:     searched_pc = searched_pc - (long)tb->tc_ptr + (long)dummy_gen_code_buf;
                   1300:     ret = gen_intermediate_code_internal(env, tb, 
                   1301:                                          dummy_gen_code_buf, NULL,
                   1302:                                          1, (uint8_t *)searched_pc);
                   1303:     if (ret < 0)
                   1304:         return ret;
                   1305:     /* restore all the CPU state from the CPU context from the
                   1306:        signal. The FPU context stays in the host CPU. */
                   1307:     
                   1308:     env->regs[R_EAX] = uc->uc_mcontext.gregs[REG_EAX];
                   1309:     env->regs[R_ECX] = uc->uc_mcontext.gregs[REG_ECX];
                   1310:     env->regs[R_EDX] = uc->uc_mcontext.gregs[REG_EDX];
                   1311:     env->regs[R_EBX] = uc->uc_mcontext.gregs[REG_EBX];
                   1312:     env->regs[R_ESP] = uc->uc_mcontext.gregs[REG_ESP];
                   1313:     env->regs[R_EBP] = uc->uc_mcontext.gregs[REG_EBP];
                   1314:     env->regs[R_ESI] = uc->uc_mcontext.gregs[REG_ESI];
                   1315:     env->regs[R_EDI] = uc->uc_mcontext.gregs[REG_EDI];
                   1316:     eflags = uc->uc_mcontext.gregs[REG_EFL];
                   1317:     env->df = 1 - (2 * ((eflags >> 10) & 1));
                   1318:     env->cc_src = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
                   1319:     env->cc_op = CC_OP_EFLAGS;
                   1320:     return 0;
                   1321: }
                   1322: 
                   1323: #endif /* USE_CODE_COPY */

unix.superglobalmegacorp.com