/[qemu]/qemu/translate-i386.c
ViewVC logotype

Diff of /qemu/translate-i386.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.59 by bellard, Thu Aug 21 23:25:21 2003 UTC revision 1.60 by bellard, Wed Sep 17 22:56:30 2003 UTC
# Line 60  typedef struct DisasContext { Line 60  typedef struct DisasContext {
60      int cpl;      int cpl;
61      int iopl;      int iopl;
62      int tf;     /* TF cpu flag */      int tf;     /* TF cpu flag */
63        int jmp_opt; /* use direct block chaining for direct jumps */
64      int mem_index; /* select memory access functions */      int mem_index; /* select memory access functions */
65      struct TranslationBlock *tb;      struct TranslationBlock *tb;
66      int popl_esp_hack; /* for correct popl with esp base handling */      int popl_esp_hack; /* for correct popl with esp base handling */
67  } DisasContext;  } DisasContext;
68    
69    static void gen_eob(DisasContext *s);
70    static void gen_jmp(DisasContext *s, unsigned int eip);
71    
72  /* i386 arith/logic operations */  /* i386 arith/logic operations */
73  enum {  enum {
74      OP_ADDL,      OP_ADDL,
# Line 635  static GenOpFunc *gen_op_st_T0_A0[3 * 3] Line 639  static GenOpFunc *gen_op_st_T0_A0[3 * 3]
639      gen_op_stl_user_T0_A0,      gen_op_stl_user_T0_A0,
640  };  };
641    
 /* the _a32 and _a16 string operations use A0 as the base register. */  
   
 #define STRINGOP_NB 9  
   
 #define STRINGOP(x) \  
     gen_op_ ## x ## b_fast, \  
     gen_op_ ## x ## w_fast, \  
     gen_op_ ## x ## l_fast, \  
     gen_op_ ## x ## b_a32, \  
     gen_op_ ## x ## w_a32, \  
     gen_op_ ## x ## l_a32, \  
     gen_op_ ## x ## b_a16, \  
     gen_op_ ## x ## w_a16, \  
     gen_op_ ## x ## l_a16,  
       
 static GenOpFunc *gen_op_scas[STRINGOP_NB * 3] = {  
     STRINGOP(repz_scas)  
     STRINGOP(repnz_scas)  
 };  
   
 static GenOpFunc *gen_op_cmps[STRINGOP_NB * 3] = {  
     STRINGOP(repz_cmps)  
     STRINGOP(repnz_cmps)  
 };  
   
642  static inline void gen_string_movl_A0_ESI(DisasContext *s)  static inline void gen_string_movl_A0_ESI(DisasContext *s)
643  {  {
644      int override;      int override;
# Line 712  static GenOpFunc2 *gen_op_jz_ecx[2] = { Line 691  static GenOpFunc2 *gen_op_jz_ecx[2] = {
691      gen_op_jz_ecxl,      gen_op_jz_ecxl,
692  };  };
693            
694    static GenOpFunc1 *gen_op_jz_ecx_im[2] = {
695        gen_op_jz_ecxw_im,
696        gen_op_jz_ecxl_im,
697    };
698    
699  static GenOpFunc *gen_op_dec_ECX[2] = {  static GenOpFunc *gen_op_dec_ECX[2] = {
700      gen_op_decw_ECX,      gen_op_decw_ECX,
701      gen_op_decl_ECX,      gen_op_decl_ECX,
702  };  };
703    
704  static GenOpFunc2 *gen_op_string_jnz_sub[2][3] = {  static GenOpFunc1 *gen_op_string_jnz_sub[2][3] = {
705      {      {
706          gen_op_string_jnz_subb,          gen_op_string_jnz_subb,
707          gen_op_string_jnz_subw,          gen_op_string_jnz_subw,
# Line 730  static GenOpFunc2 *gen_op_string_jnz_sub Line 714  static GenOpFunc2 *gen_op_string_jnz_sub
714      },      },
715  };  };
716    
717    static GenOpFunc1 *gen_op_string_jnz_sub_im[2][3] = {
718        {
719            gen_op_string_jnz_subb_im,
720            gen_op_string_jnz_subw_im,
721            gen_op_string_jnz_subl_im,
722        },
723        {
724            gen_op_string_jz_subb_im,
725            gen_op_string_jz_subw_im,
726            gen_op_string_jz_subl_im,
727        },
728    };
729    
730  static GenOpFunc *gen_op_in_DX_T0[3] = {  static GenOpFunc *gen_op_in_DX_T0[3] = {
731      gen_op_inb_DX_T0,      gen_op_inb_DX_T0,
732      gen_op_inw_DX_T0,      gen_op_inw_DX_T0,
# Line 758  static inline void gen_movs(DisasContext Line 755  static inline void gen_movs(DisasContext
755      }      }
756  }  }
757    
758  /* same method as Valgrind : we generate jumps to current or next  static inline void gen_update_cc_op(DisasContext *s)
    instruction */  
 static inline void gen_repz_movs(DisasContext *s, int ot,  
                                  unsigned int cur_eip, unsigned int next_eip)  
759  {  {
760      if (s->cc_op != CC_OP_DYNAMIC)      if (s->cc_op != CC_OP_DYNAMIC) {
761          gen_op_set_cc_op(s->cc_op);          gen_op_set_cc_op(s->cc_op);
762      gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);          s->cc_op = CC_OP_DYNAMIC;
763      gen_movs(s, ot);      }
764      gen_op_dec_ECX[s->aflag]();  }
765      gen_op_jmp_tb_next((long)s->tb, cur_eip);  
766      s->is_jmp = 3;  static inline void gen_jz_ecx_string(DisasContext *s, unsigned int next_eip)
767    {
768        if (s->jmp_opt) {
769            gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
770        } else {
771            /* XXX: does not work with gdbstub "ice" single step - not a
772               serious problem */
773            gen_op_jz_ecx_im[s->aflag](next_eip);
774        }
775  }  }
776    
777  static inline void gen_stos(DisasContext *s, int ot)  static inline void gen_stos(DisasContext *s, int ot)
# Line 785  static inline void gen_stos(DisasContext Line 787  static inline void gen_stos(DisasContext
787      }      }
788  }  }
789    
 static inline void gen_repz_stos(DisasContext *s, int ot,  
                                  unsigned int cur_eip, unsigned int next_eip)  
 {  
     if (s->cc_op != CC_OP_DYNAMIC)  
         gen_op_set_cc_op(s->cc_op);  
     gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);  
     gen_stos(s, ot);  
     gen_op_dec_ECX[s->aflag]();  
     gen_op_jmp_tb_next((long)s->tb, cur_eip);  
     s->is_jmp = 3;  
 }  
   
790  static inline void gen_lods(DisasContext *s, int ot)  static inline void gen_lods(DisasContext *s, int ot)
791  {  {
792      gen_string_movl_A0_ESI(s);      gen_string_movl_A0_ESI(s);
# Line 810  static inline void gen_lods(DisasContext Line 800  static inline void gen_lods(DisasContext
800      }      }
801  }  }
802    
 static inline void gen_repz_lods(DisasContext *s, int ot,  
                                  unsigned int cur_eip, unsigned int next_eip)  
 {  
     if (s->cc_op != CC_OP_DYNAMIC)  
         gen_op_set_cc_op(s->cc_op);  
     gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);  
     gen_lods(s, ot);  
     gen_op_dec_ECX[s->aflag]();  
     gen_op_jmp_tb_next((long)s->tb, cur_eip);  
     s->is_jmp = 3;  
 }  
   
803  static inline void gen_scas(DisasContext *s, int ot)  static inline void gen_scas(DisasContext *s, int ot)
804  {  {
805      gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();      gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
# Line 836  static inline void gen_scas(DisasContext Line 814  static inline void gen_scas(DisasContext
814      }      }
815  }  }
816    
 #if 0  
 static inline void gen_repz_scas(DisasContext *s, int ot,  
                                  unsigned int cur_eip, unsigned int next_eip,  
                                  int nz)  
 {  
     if (s->cc_op != CC_OP_DYNAMIC)  
         gen_op_set_cc_op(s->cc_op);  
     gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);  
     gen_scas(s, ot);  
     gen_op_set_cc_op(CC_OP_SUBB + ot);  
     gen_op_string_jnz_sub[nz][ot]((long)s->tb, next_eip);  
     gen_op_dec_ECX[s->aflag]();  
     gen_op_jmp_tb_next((long)s->tb, cur_eip);  
     s->is_jmp = 3;  
 }  
 #endif  
   
817  static inline void gen_cmps(DisasContext *s, int ot)  static inline void gen_cmps(DisasContext *s, int ot)
818  {  {
819      gen_string_movl_A0_ESI(s);      gen_string_movl_A0_ESI(s);
# Line 883  static inline void gen_ins(DisasContext Line 844  static inline void gen_ins(DisasContext
844      }      }
845  }  }
846    
 static inline void gen_repz_ins(DisasContext *s, int ot,  
                                  unsigned int cur_eip, unsigned int next_eip)  
 {  
     if (s->cc_op != CC_OP_DYNAMIC)  
         gen_op_set_cc_op(s->cc_op);  
     gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);  
     gen_ins(s, ot);  
     gen_op_dec_ECX[s->aflag]();  
     gen_op_jmp_tb_next((long)s->tb, cur_eip);  
     s->is_jmp = 3;  
 }  
   
847  static inline void gen_outs(DisasContext *s, int ot)  static inline void gen_outs(DisasContext *s, int ot)
848  {  {
849      gen_string_movl_A0_ESI(s);      gen_string_movl_A0_ESI(s);
# Line 908  static inline void gen_outs(DisasContext Line 857  static inline void gen_outs(DisasContext
857      }      }
858  }  }
859    
860  static inline void gen_repz_outs(DisasContext *s, int ot,  /* same method as Valgrind : we generate jumps to current or next
861                                   unsigned int cur_eip, unsigned int next_eip)     instruction */
862  {  #define GEN_REPZ(op)                                                          \
863      if (s->cc_op != CC_OP_DYNAMIC)  static inline void gen_repz_ ## op(DisasContext *s, int ot,                   \
864          gen_op_set_cc_op(s->cc_op);                                   unsigned int cur_eip, unsigned int next_eip) \
865      gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);  {                                                                             \
866      gen_outs(s, ot);      gen_update_cc_op(s);                                                      \
867      gen_op_dec_ECX[s->aflag]();      gen_jz_ecx_string(s, next_eip);                                           \
868      gen_op_jmp_tb_next((long)s->tb, cur_eip);      gen_ ## op(s, ot);                                                        \
869      s->is_jmp = 3;      gen_op_dec_ECX[s->aflag]();                                               \
870  }      /* a loop would cause two single step exceptions if ECX = 1               \
871           before rep string_insn */                                              \
872  static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)      if (!s->jmp_opt)                                                          \
873  {          gen_op_jz_ecx_im[s->aflag](next_eip);                                 \
874      int index, override;      gen_jmp(s, cur_eip);                                                      \
875    }
876      override = s->override;  
877      if (s->aflag) {  #define GEN_REPZ2(op)                                                         \
878          /* 32 bit address */  static inline void gen_repz_ ## op(DisasContext *s, int ot,                   \
879          if (s->addseg && override < 0)                                     unsigned int cur_eip,                      \
880              override = R_DS;                                     unsigned int next_eip,                     \
881          if (override >= 0) {                                     int nz)                                    \
882              gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));  {                                                                             \
883              index = 3 + ot;      gen_update_cc_op(s);                                                      \
884          } else {      gen_jz_ecx_string(s, next_eip);                                           \
885              index = ot;      gen_ ## op(s, ot);                                                        \
886          }      gen_op_dec_ECX[s->aflag]();                                               \
887      } else {      gen_op_set_cc_op(CC_OP_SUBB + ot);                                        \
888          if (override < 0)      if (!s->jmp_opt)                                                          \
889              override = R_DS;          gen_op_string_jnz_sub_im[nz][ot](next_eip);                           \
890          gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));      else                                                                      \
891          /* 16 address, always override */          gen_op_string_jnz_sub[nz][ot]((long)s->tb);                           \
892          index = 6 + ot;      if (!s->jmp_opt)                                                          \
893      }          gen_op_jz_ecx_im[s->aflag](next_eip);                                 \
894      func[index]();      gen_jmp(s, cur_eip);                                                      \
895  }  }
896    
897  static inline void gen_string_es(DisasContext *s, int ot, GenOpFunc **func)  GEN_REPZ(movs)
898  {  GEN_REPZ(stos)
899      int index;  GEN_REPZ(lods)
900                GEN_REPZ(ins)
901      if (s->aflag) {  GEN_REPZ(outs)
902          if (s->addseg) {  GEN_REPZ2(scas)
903              index = 3 + ot;  GEN_REPZ2(cmps)
         } else {  
             index = ot;  
         }  
     } else {  
         index = 6 + ot;  
     }  
     func[index]();  
 }  
   
904    
905  static GenOpFunc *gen_op_in[3] = {  static GenOpFunc *gen_op_in[3] = {
906      gen_op_inb_T0_T1,      gen_op_inb_T0_T1,
# Line 1420  static inline void gen_jcc(DisasContext Line 1360  static inline void gen_jcc(DisasContext
1360    
1361      inv = b & 1;      inv = b & 1;
1362      jcc_op = (b >> 1) & 7;      jcc_op = (b >> 1) & 7;
1363      switch(s->cc_op) {      
1364          /* we optimize the cmp/jcc case */      if (s->jmp_opt) {
1365      case CC_OP_SUBB:          switch(s->cc_op) {
1366      case CC_OP_SUBW:              /* we optimize the cmp/jcc case */
1367      case CC_OP_SUBL:          case CC_OP_SUBB:
1368          func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];          case CC_OP_SUBW:
1369          break;          case CC_OP_SUBL:
1370                        func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
         /* some jumps are easy to compute */  
     case CC_OP_ADDB:  
     case CC_OP_ADDW:  
     case CC_OP_ADDL:  
     case CC_OP_ADCB:  
     case CC_OP_ADCW:  
     case CC_OP_ADCL:  
     case CC_OP_SBBB:  
     case CC_OP_SBBW:  
     case CC_OP_SBBL:  
     case CC_OP_LOGICB:  
     case CC_OP_LOGICW:  
     case CC_OP_LOGICL:  
     case CC_OP_INCB:  
     case CC_OP_INCW:  
     case CC_OP_INCL:  
     case CC_OP_DECB:  
     case CC_OP_DECW:  
     case CC_OP_DECL:  
     case CC_OP_SHLB:  
     case CC_OP_SHLW:  
     case CC_OP_SHLL:  
     case CC_OP_SARB:  
     case CC_OP_SARW:  
     case CC_OP_SARL:  
         switch(jcc_op) {  
         case JCC_Z:  
             func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];  
1371              break;              break;
1372          case JCC_S:              
1373              func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];              /* some jumps are easy to compute */
1374            case CC_OP_ADDB:
1375            case CC_OP_ADDW:
1376            case CC_OP_ADDL:
1377            case CC_OP_ADCB:
1378            case CC_OP_ADCW:
1379            case CC_OP_ADCL:
1380            case CC_OP_SBBB:
1381            case CC_OP_SBBW:
1382            case CC_OP_SBBL:
1383            case CC_OP_LOGICB:
1384            case CC_OP_LOGICW:
1385            case CC_OP_LOGICL:
1386            case CC_OP_INCB:
1387            case CC_OP_INCW:
1388            case CC_OP_INCL:
1389            case CC_OP_DECB:
1390            case CC_OP_DECW:
1391            case CC_OP_DECL:
1392            case CC_OP_SHLB:
1393            case CC_OP_SHLW:
1394            case CC_OP_SHLL:
1395            case CC_OP_SARB:
1396            case CC_OP_SARW:
1397            case CC_OP_SARL:
1398                switch(jcc_op) {
1399                case JCC_Z:
1400                    func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1401                    break;
1402                case JCC_S:
1403                    func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1404                    break;
1405                default:
1406                    func = NULL;
1407                    break;
1408                }
1409              break;              break;
1410          default:          default:
1411              func = NULL;              func = NULL;
1412              break;              break;
1413          }          }
         break;  
     default:  
         func = NULL;  
         break;  
     }  
1414    
1415      if (s->cc_op != CC_OP_DYNAMIC)          if (s->cc_op != CC_OP_DYNAMIC)
1416          gen_op_set_cc_op(s->cc_op);              gen_op_set_cc_op(s->cc_op);
1417    
1418      if (!func) {          if (!func) {
1419          gen_setcc_slow[jcc_op]();              gen_setcc_slow[jcc_op]();
1420          func = gen_op_jcc;              func = gen_op_jcc;
1421      }          }
1422            
1423      tb = s->tb;          tb = s->tb;
1424      if (!inv) {          if (!inv) {
1425          func((long)tb, val, next_eip);              func((long)tb, val, next_eip);
1426            } else {
1427                func((long)tb, next_eip, val);
1428            }
1429            s->is_jmp = 3;
1430      } else {      } else {
1431          func((long)tb, next_eip, val);          if (s->cc_op != CC_OP_DYNAMIC) {
1432                gen_op_set_cc_op(s->cc_op);
1433                s->cc_op = CC_OP_DYNAMIC;
1434            }
1435            gen_setcc_slow[jcc_op]();
1436            if (!inv) {
1437                gen_op_jcc_im(val, next_eip);
1438            } else {
1439                gen_op_jcc_im(next_eip, val);
1440            }
1441            gen_eob(s);
1442      }      }
     s->is_jmp = 3;  
1443  }  }
1444    
1445  static void gen_setcc(DisasContext *s, int b)  static void gen_setcc(DisasContext *s, int b)
# Line 1557  static void gen_movl_seg_T0(DisasContext Line 1512  static void gen_movl_seg_T0(DisasContext
1512         stop as a special handling must be done to disable hardware         stop as a special handling must be done to disable hardware
1513         interrupts for the next instruction */         interrupts for the next instruction */
1514      if (seg_reg == R_SS || (!s->addseg && seg_reg < R_FS))      if (seg_reg == R_SS || (!s->addseg && seg_reg < R_FS))
1515          s->is_jmp = 2;          s->is_jmp = 3;
1516  }  }
1517    
1518  /* generate a push. It depends on ss32, addseg and dflag */  /* generate a push. It depends on ss32, addseg and dflag */
# Line 1727  static void gen_exception(DisasContext * Line 1682  static void gen_exception(DisasContext *
1682          gen_op_set_cc_op(s->cc_op);          gen_op_set_cc_op(s->cc_op);
1683      gen_op_jmp_im(cur_eip);      gen_op_jmp_im(cur_eip);
1684      gen_op_raise_exception(trapno);      gen_op_raise_exception(trapno);
1685      s->is_jmp = 1;      s->is_jmp = 3;
1686  }  }
1687    
1688  /* an interrupt is different from an exception because of the  /* an interrupt is different from an exception because of the
# Line 1739  static void gen_interrupt(DisasContext * Line 1694  static void gen_interrupt(DisasContext *
1694          gen_op_set_cc_op(s->cc_op);          gen_op_set_cc_op(s->cc_op);
1695      gen_op_jmp_im(cur_eip);      gen_op_jmp_im(cur_eip);
1696      gen_op_raise_interrupt(intno, next_eip);      gen_op_raise_interrupt(intno, next_eip);
1697      s->is_jmp = 1;      s->is_jmp = 3;
1698  }  }
1699    
1700  static void gen_debug(DisasContext *s, unsigned int cur_eip)  static void gen_debug(DisasContext *s, unsigned int cur_eip)
# Line 1748  static void gen_debug(DisasContext *s, u Line 1703  static void gen_debug(DisasContext *s, u
1703          gen_op_set_cc_op(s->cc_op);          gen_op_set_cc_op(s->cc_op);
1704      gen_op_jmp_im(cur_eip);      gen_op_jmp_im(cur_eip);
1705      gen_op_debug();      gen_op_debug();
1706      s->is_jmp = 1;      s->is_jmp = 3;
1707    }
1708    
1709    /* generate a generic end of block. Trace exception is also generated
1710       if needed */
1711    static void gen_eob(DisasContext *s)
1712    {
1713        if (s->cc_op != CC_OP_DYNAMIC)
1714            gen_op_set_cc_op(s->cc_op);
1715        if (s->tf) {
1716            gen_op_raise_exception(EXCP01_SSTP);
1717        } else {
1718            gen_op_movl_T0_0();
1719            gen_op_exit_tb();
1720        }
1721        s->is_jmp = 3;
1722  }  }
1723    
1724  /* generate a jump to eip. No segment change must happen before as a  /* generate a jump to eip. No segment change must happen before as a
# Line 1757  static void gen_jmp(DisasContext *s, uns Line 1727  static void gen_jmp(DisasContext *s, uns
1727  {  {
1728      TranslationBlock *tb = s->tb;      TranslationBlock *tb = s->tb;
1729    
1730      if (s->cc_op != CC_OP_DYNAMIC)      if (s->jmp_opt) {
1731          gen_op_set_cc_op(s->cc_op);          if (s->cc_op != CC_OP_DYNAMIC)
1732      gen_op_jmp_tb_next((long)tb, eip);              gen_op_set_cc_op(s->cc_op);
1733      s->is_jmp = 3;          gen_op_jmp((long)tb, eip);
1734            s->is_jmp = 3;
1735        } else {
1736            gen_op_jmp_im(eip);
1737            gen_eob(s);
1738        }
1739  }  }
1740    
1741  /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr  /* convert one instruction. s->is_jmp is set if the translation must
1742     is set to true if the instruction sets the PC (last instruction of     be stopped. Return the next pc value */
1743     a basic block) */  static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
 long disas_insn(DisasContext *s, uint8_t *pc_start)  
1744  {  {
1745      int b, prefixes, aflag, dflag;      int b, prefixes, aflag, dflag;
1746      int shift, ot;      int shift, ot;
# Line 2106  long disas_insn(DisasContext *s, uint8_t Line 2080  long disas_insn(DisasContext *s, uint8_t
2080              next_eip = s->pc - s->cs_base;              next_eip = s->pc - s->cs_base;
2081              gen_op_movl_T0_im(next_eip);              gen_op_movl_T0_im(next_eip);
2082              gen_push_T0(s);              gen_push_T0(s);
2083              s->is_jmp = 1;              gen_eob(s);
2084              break;              break;
2085          case 3: /* lcall Ev */          case 3: /*< lcall Ev */
2086              gen_op_ld_T1_A0[ot + s->mem_index]();              gen_op_ld_T1_A0[ot + s->mem_index]();
2087              gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));              gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2088              gen_op_ld_T0_A0[OT_WORD + s->mem_index]();              gen_op_ld_T0_A0[OT_WORD + s->mem_index]();
# Line 2121  long disas_insn(DisasContext *s, uint8_t Line 2095  long disas_insn(DisasContext *s, uint8_t
2095              } else {              } else {
2096                  gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);                  gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
2097              }              }
2098              s->is_jmp = 1;              gen_eob(s);
2099              break;              break;
2100          case 4: /* jmp Ev */          case 4: /* jmp Ev */
2101              if (s->dflag == 0)              if (s->dflag == 0)
2102                  gen_op_andl_T0_ffff();                  gen_op_andl_T0_ffff();
2103              gen_op_jmp_T0();              gen_op_jmp_T0();
2104              s->is_jmp = 1;              gen_eob(s);
2105              break;              break;
2106          case 5: /* ljmp Ev */          case 5: /* ljmp Ev */
2107              gen_op_ld_T1_A0[ot + s->mem_index]();              gen_op_ld_T1_A0[ot + s->mem_index]();
# Line 2144  long disas_insn(DisasContext *s, uint8_t Line 2118  long disas_insn(DisasContext *s, uint8_t
2118                  gen_op_movl_T0_T1();                  gen_op_movl_T0_T1();
2119                  gen_op_jmp_T0();                  gen_op_jmp_T0();
2120              }              }
2121              s->is_jmp = 1;              gen_eob(s);
2122              break;              break;
2123          case 6: /* push Ev */          case 6: /* push Ev */
2124              gen_push_T0(s);              gen_push_T0(s);
# Line 2366  long disas_insn(DisasContext *s, uint8_t Line 2340  long disas_insn(DisasContext *s, uint8_t
2340          if (reg == R_SS) {          if (reg == R_SS) {
2341              /* if reg == SS, inhibit interrupts/trace */              /* if reg == SS, inhibit interrupts/trace */
2342              gen_op_set_inhibit_irq();              gen_op_set_inhibit_irq();
2343                s->tf = 0;
2344            }
2345            if (s->is_jmp) {
2346                gen_op_jmp_im(s->pc - s->cs_base);
2347                gen_eob(s);
2348          }          }
2349          break;          break;
2350      case 0x1a1: /* pop fs */      case 0x1a1: /* pop fs */
# Line 2373  long disas_insn(DisasContext *s, uint8_t Line 2352  long disas_insn(DisasContext *s, uint8_t
2352          gen_pop_T0(s);          gen_pop_T0(s);
2353          gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);          gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
2354          gen_pop_update(s);          gen_pop_update(s);
2355            if (s->is_jmp) {
2356                gen_op_jmp_im(s->pc - s->cs_base);
2357                gen_eob(s);
2358            }
2359          break;          break;
2360    
2361          /**************************/          /**************************/
# Line 2428  long disas_insn(DisasContext *s, uint8_t Line 2411  long disas_insn(DisasContext *s, uint8_t
2411          if (reg == R_SS) {          if (reg == R_SS) {
2412              /* if reg == SS, inhibit interrupts/trace */              /* if reg == SS, inhibit interrupts/trace */
2413              gen_op_set_inhibit_irq();              gen_op_set_inhibit_irq();
2414                s->tf = 0;
2415            }
2416            if (s->is_jmp) {
2417                gen_op_jmp_im(s->pc - s->cs_base);
2418                gen_eob(s);
2419          }          }
2420          break;          break;
2421      case 0x8c: /* mov Gv, seg */      case 0x8c: /* mov Gv, seg */
# Line 2635  long disas_insn(DisasContext *s, uint8_t Line 2623  long disas_insn(DisasContext *s, uint8_t
2623          gen_movl_seg_T0(s, op, pc_start - s->cs_base);          gen_movl_seg_T0(s, op, pc_start - s->cs_base);
2624          /* then put the data */          /* then put the data */
2625          gen_op_mov_reg_T1[ot][reg]();          gen_op_mov_reg_T1[ot][reg]();
2626            if (s->is_jmp) {
2627                gen_op_jmp_im(s->pc - s->cs_base);
2628                gen_eob(s);
2629            }
2630          break;          break;
2631                    
2632          /************************/          /************************/
# Line 3191  long disas_insn(DisasContext *s, uint8_t Line 3183  long disas_insn(DisasContext *s, uint8_t
3183          else          else
3184                  ot = dflag ? OT_LONG : OT_WORD;                  ot = dflag ? OT_LONG : OT_WORD;
3185          if (prefixes & PREFIX_REPNZ) {          if (prefixes & PREFIX_REPNZ) {
3186              if (s->cc_op != CC_OP_DYNAMIC)              gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
                 gen_op_set_cc_op(s->cc_op);  
             gen_string_es(s, ot, gen_op_scas + STRINGOP_NB);  
             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */  
3187          } else if (prefixes & PREFIX_REPZ) {          } else if (prefixes & PREFIX_REPZ) {
3188              if (s->cc_op != CC_OP_DYNAMIC)              gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
                 gen_op_set_cc_op(s->cc_op);  
             gen_string_es(s, ot, gen_op_scas);  
             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */  
3189          } else {          } else {
3190              gen_scas(s, ot);              gen_scas(s, ot);
3191              s->cc_op = CC_OP_SUBB + ot;              s->cc_op = CC_OP_SUBB + ot;
# Line 3213  long disas_insn(DisasContext *s, uint8_t Line 3199  long disas_insn(DisasContext *s, uint8_t
3199          else          else
3200              ot = dflag ? OT_LONG : OT_WORD;              ot = dflag ? OT_LONG : OT_WORD;
3201          if (prefixes & PREFIX_REPNZ) {          if (prefixes & PREFIX_REPNZ) {
3202              if (s->cc_op != CC_OP_DYNAMIC)              gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
                 gen_op_set_cc_op(s->cc_op);  
             gen_string_ds(s, ot, gen_op_cmps + STRINGOP_NB);  
             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */  
3203          } else if (prefixes & PREFIX_REPZ) {          } else if (prefixes & PREFIX_REPZ) {
3204              if (s->cc_op != CC_OP_DYNAMIC)              gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
                 gen_op_set_cc_op(s->cc_op);  
             gen_string_ds(s, ot, gen_op_cmps);  
             s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */  
3205          } else {          } else {
3206              gen_cmps(s, ot);              gen_cmps(s, ot);
3207              s->cc_op = CC_OP_SUBB + ot;              s->cc_op = CC_OP_SUBB + ot;
# Line 3333  long disas_insn(DisasContext *s, uint8_t Line 3313  long disas_insn(DisasContext *s, uint8_t
3313          if (s->dflag == 0)          if (s->dflag == 0)
3314              gen_op_andl_T0_ffff();              gen_op_andl_T0_ffff();
3315          gen_op_jmp_T0();          gen_op_jmp_T0();
3316          s->is_jmp = 1;          gen_eob(s);
3317          break;          break;
3318      case 0xc3: /* ret */      case 0xc3: /* ret */
3319          gen_pop_T0(s);          gen_pop_T0(s);
# Line 3341  long disas_insn(DisasContext *s, uint8_t Line 3321  long disas_insn(DisasContext *s, uint8_t
3321          if (s->dflag == 0)          if (s->dflag == 0)
3322              gen_op_andl_T0_ffff();              gen_op_andl_T0_ffff();
3323          gen_op_jmp_T0();          gen_op_jmp_T0();
3324          s->is_jmp = 1;          gen_eob(s);
3325          break;          break;
3326      case 0xca: /* lret im */      case 0xca: /* lret im */
3327          val = ldsw(s->pc);          val = ldsw(s->pc);
# Line 3368  long disas_insn(DisasContext *s, uint8_t Line 3348  long disas_insn(DisasContext *s, uint8_t
3348              /* add stack offset */              /* add stack offset */
3349              gen_stack_update(s, val + (4 << s->dflag));              gen_stack_update(s, val + (4 << s->dflag));
3350          }          }
3351          s->is_jmp = 1;          gen_eob(s);
3352          break;          break;
3353      case 0xcb: /* lret */      case 0xcb: /* lret */
3354          val = 0;          val = 0;
# Line 3387  long disas_insn(DisasContext *s, uint8_t Line 3367  long disas_insn(DisasContext *s, uint8_t
3367              gen_op_iret_protected(s->dflag);              gen_op_iret_protected(s->dflag);
3368              s->cc_op = CC_OP_EFLAGS;              s->cc_op = CC_OP_EFLAGS;
3369          }          }
3370          s->is_jmp = 1;          gen_eob(s);
3371          break;          break;
3372      case 0xe8: /* call im */      case 0xe8: /* call im */
3373          {          {
# Line 3512  long disas_insn(DisasContext *s, uint8_t Line 3492  long disas_insn(DisasContext *s, uint8_t
3492              }              }
3493              gen_pop_update(s);              gen_pop_update(s);
3494              s->cc_op = CC_OP_EFLAGS;              s->cc_op = CC_OP_EFLAGS;
3495              s->is_jmp = 2; /* abort translation because TF flag may change */              /* abort translation because TF flag may change */
3496                gen_op_jmp_im(s->pc - s->cs_base);
3497                gen_eob(s);
3498          }          }
3499          break;          break;
3500      case 0x9e: /* sahf */      case 0x9e: /* sahf */
# Line 3713  long disas_insn(DisasContext *s, uint8_t Line 3695  long disas_insn(DisasContext *s, uint8_t
3695      case 0xfb: /* sti */      case 0xfb: /* sti */
3696          if (!s->vm86) {          if (!s->vm86) {
3697              if (s->cpl <= s->iopl) {              if (s->cpl <= s->iopl) {
3698                gen_sti:
3699                  gen_op_sti();                  gen_op_sti();
3700                  /* interruptions are enabled only the first insn after sti */                  /* interruptions are enabled only the first insn after sti */
3701                  gen_op_set_inhibit_irq();                  gen_op_set_inhibit_irq();
3702                  s->is_jmp = 2; /* give a chance to handle pending irqs */                  /* give a chance to handle pending irqs */
3703                    gen_op_jmp_im(s->pc - s->cs_base);
3704                    gen_eob(s);
3705              } else {              } else {
3706                  gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);                  gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3707              }              }
3708          } else {          } else {
3709              if (s->iopl == 3) {              if (s->iopl == 3) {
3710                  gen_op_sti();                  goto gen_sti;
                 /* interruptions are enabled only the first insn after sti */  
                 gen_op_set_inhibit_irq();  
                 s->is_jmp = 2; /* give a chance to handle pending irqs */  
3711              } else {              } else {
3712                  gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);                  gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3713              }              }
# Line 3769  long disas_insn(DisasContext *s, uint8_t Line 3751  long disas_insn(DisasContext *s, uint8_t
3751          if (s->dflag == 0)          if (s->dflag == 0)
3752              val &= 0xffff;              val &= 0xffff;
3753          gen_op_loop[s->aflag][b & 3](val, next_eip);          gen_op_loop[s->aflag][b & 3](val, next_eip);
3754          s->is_jmp = 1;          gen_eob(s);
3755          break;          break;
3756      case 0x130: /* wrmsr */      case 0x130: /* wrmsr */
3757      case 0x132: /* rdmsr */      case 0x132: /* rdmsr */
# Line 3796  long disas_insn(DisasContext *s, uint8_t Line 3778  long disas_insn(DisasContext *s, uint8_t
3778                  gen_op_set_cc_op(s->cc_op);                  gen_op_set_cc_op(s->cc_op);
3779              gen_op_jmp_im(s->pc - s->cs_base);              gen_op_jmp_im(s->pc - s->cs_base);
3780              gen_op_hlt();              gen_op_hlt();
3781              s->is_jmp = 1;              s->is_jmp = 3;
3782          }          }
3783          break;          break;
3784      case 0x100:      case 0x100:
# Line 3968  long disas_insn(DisasContext *s, uint8_t Line 3950  long disas_insn(DisasContext *s, uint8_t
3950                  if (b & 2) {                  if (b & 2) {
3951                      gen_op_mov_TN_reg[OT_LONG][0][rm]();                      gen_op_mov_TN_reg[OT_LONG][0][rm]();
3952                      gen_op_movl_crN_T0(reg);                      gen_op_movl_crN_T0(reg);
3953                      s->is_jmp = 2;                      gen_op_jmp_im(s->pc - s->cs_base);
3954                        gen_eob(s);
3955                  } else {                  } else {
3956                      gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg]));                      gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg]));
3957                      gen_op_mov_reg_T0[OT_LONG][rm]();                      gen_op_mov_reg_T0[OT_LONG][rm]();
# Line 3995  long disas_insn(DisasContext *s, uint8_t Line 3978  long disas_insn(DisasContext *s, uint8_t
3978              if (b & 2) {              if (b & 2) {
3979                  gen_op_mov_TN_reg[OT_LONG][0][rm]();                  gen_op_mov_TN_reg[OT_LONG][0][rm]();
3980                  gen_op_movl_drN_T0(reg);                  gen_op_movl_drN_T0(reg);
3981                  s->is_jmp = 2;                  gen_op_jmp_im(s->pc - s->cs_base);
3982                    gen_eob(s);
3983              } else {              } else {
3984                  gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg]));                  gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg]));
3985                  gen_op_mov_reg_T0[OT_LONG][rm]();                  gen_op_mov_reg_T0[OT_LONG][rm]();
# Line 4015  long disas_insn(DisasContext *s, uint8_t Line 3999  long disas_insn(DisasContext *s, uint8_t
3999      /* lock generation */      /* lock generation */
4000      if (s->prefix & PREFIX_LOCK)      if (s->prefix & PREFIX_LOCK)
4001          gen_op_unlock();          gen_op_unlock();
4002      return (long)s->pc;      return s->pc;
4003   illegal_op:   illegal_op:
4004      /* XXX: ensure that no lock was generated */      /* XXX: ensure that no lock was generated */
4005      return -1;      gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
4006        return s->pc;
4007  }  }
4008    
4009  #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)  #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
# Line 4265  static uint16_t opc_write_flags[NB_OPS] Line 4250  static uint16_t opc_write_flags[NB_OPS]
4250      [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,      [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
4251      [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,      [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
4252    
 #undef STRINGOP  
 #define STRINGOP(x) \  
     [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \  
     [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \  
     [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \  
     [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \  
     [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \  
     [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \  
     [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \  
     [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \  
     [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,  
   
     STRINGOP(repz_scas)  
     STRINGOP(repnz_scas)  
     STRINGOP(repz_cmps)  
     STRINGOP(repnz_cmps)  
   
4253      [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,      [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
4254      [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,      [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
4255      [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,      [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
# Line 4383  static inline int gen_intermediate_code_ Line 4351  static inline int gen_intermediate_code_
4351      uint8_t *pc_ptr;      uint8_t *pc_ptr;
4352      uint16_t *gen_opc_end;      uint16_t *gen_opc_end;
4353      int flags, j, lj;      int flags, j, lj;
     long ret;  
4354      uint8_t *pc_start;      uint8_t *pc_start;
4355      uint8_t *cs_base;      uint8_t *cs_base;
4356            
# Line 4413  static inline int gen_intermediate_code_ Line 4380  static inline int gen_intermediate_code_
4380          else          else
4381              dc->mem_index = 3;              dc->mem_index = 3;
4382      }      }
4383        dc->jmp_opt = !(dc->tf || env->singlestep_enabled
4384    #ifndef CONFIG_SOFT_MMU
4385                        || (flags & HF_SOFTMMU_MASK)
4386    #endif
4387                        );
4388      gen_opc_ptr = gen_opc_buf;      gen_opc_ptr = gen_opc_buf;
4389      gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;      gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
4390      gen_opparam_ptr = gen_opparam_buf;      gen_opparam_ptr = gen_opparam_buf;
# Line 4428  static inline int gen_intermediate_code_ Line 4399  static inline int gen_intermediate_code_
4399      if (flags & HF_INHIBIT_IRQ_MASK) {      if (flags & HF_INHIBIT_IRQ_MASK) {
4400          gen_op_reset_inhibit_irq();          gen_op_reset_inhibit_irq();
4401      }      }
4402      do {      for(;;) {
4403          if (env->nb_breakpoints > 0) {          if (env->nb_breakpoints > 0) {
4404              for(j = 0; j < env->nb_breakpoints; j++) {              for(j = 0; j < env->nb_breakpoints; j++) {
4405                  if (env->breakpoints[j] == (unsigned long)pc_ptr) {                  if (env->breakpoints[j] == (unsigned long)pc_ptr) {
4406                      gen_debug(dc, pc_ptr - dc->cs_base);                      gen_debug(dc, pc_ptr - dc->cs_base);
4407                      goto the_end;                      break;
4408                  }                  }
4409              }              }
4410          }          }
# Line 4448  static inline int gen_intermediate_code_ Line 4419  static inline int gen_intermediate_code_
4419              gen_opc_cc_op[lj] = dc->cc_op;              gen_opc_cc_op[lj] = dc->cc_op;
4420              gen_opc_instr_start[lj] = 1;              gen_opc_instr_start[lj] = 1;
4421          }          }
4422          ret = disas_insn(dc, pc_ptr);          pc_ptr = disas_insn(dc, pc_ptr);
4423          if (ret == -1) {          /* stop translation if indicated */
4424              /* we trigger an illegal instruction operation only if it          if (dc->is_jmp)
4425                 is the first instruction. Otherwise, we simply stop              break;
                generating the code just before it */  
             if (pc_ptr == pc_start)  
                 return -1;  
             else  
                 break;  
         }  
         pc_ptr = (void *)ret;  
4426          /* if single step mode, we generate only one instruction and          /* if single step mode, we generate only one instruction and
4427             generate an exception */             generate an exception */
4428          if (dc->tf)          if (dc->tf) {
4429                gen_op_jmp_im(pc_ptr - dc->cs_base);
4430                gen_eob(dc);
4431                break;
4432            }
4433            /* if too long translation, stop generation too */
4434            if (gen_opc_ptr >= gen_opc_end ||
4435                (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
4436                gen_op_jmp_im(pc_ptr - dc->cs_base);
4437                gen_eob(dc);
4438              break;              break;
     } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&  
              (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));  
     if (!dc->tf && dc->is_jmp == DISAS_NEXT) {  
         gen_jmp(dc, ret - (unsigned long)dc->cs_base);  
     }  
   
     /* we must store the eflags state if it is not already done */  
     if (dc->is_jmp != DISAS_TB_JUMP) {  
         if (dc->cc_op != CC_OP_DYNAMIC)  
             gen_op_set_cc_op(dc->cc_op);  
         if (dc->is_jmp != DISAS_JUMP) {  
             /* we add an additionnal jmp to update the simulated PC */  
             gen_op_jmp_im(ret - (unsigned long)dc->cs_base);  
4439          }          }
     }  
     if (dc->tf) {  
         gen_op_raise_exception(EXCP01_SSTP);  
     }  
  the_end:  
     if (dc->is_jmp != DISAS_TB_JUMP) {  
         /* indicate that the hash table must be used to find the next TB */  
         gen_op_movl_T0_0();  
         gen_op_exit_tb();  
4440      }      }
4441      *gen_opc_ptr = INDEX_op_end;      *gen_opc_ptr = INDEX_op_end;
4442      /* we don't forget to fill the last values */      /* we don't forget to fill the last values */

Legend:
Removed from v.1.59  
changed lines
  Added in v.1.60

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26