/[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.37 by bellard, Sun May 25 23:10:30 2003 UTC revision 1.38 by bellard, Tue May 27 23:24:27 2003 UTC
# Line 160  enum { Line 160  enum {
160  };  };
161    
162  enum {  enum {
163  #define DEF(s, n) INDEX_op_ ## s,  #define DEF(s, n, copy_size) INDEX_op_ ## s,
164  #include "opc-i386.h"  #include "opc-i386.h"
165  #undef DEF  #undef DEF
166      NB_OPS,      NB_OPS,
# Line 1215  static void gen_setcc(DisasContext *s, i Line 1215  static void gen_setcc(DisasContext *s, i
1215  }  }
1216    
1217  /* move T0 to seg_reg and compute if the CPU state may change */  /* move T0 to seg_reg and compute if the CPU state may change */
1218  static void gen_movl_seg_T0(DisasContext *s, int seg_reg)  static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
1219  {  {
1220      gen_op_movl_seg_T0(seg_reg);      if (!s->vm86)
1221            gen_op_movl_seg_T0(seg_reg, cur_eip);
1222        else
1223            gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]),
1224                                  offsetof(CPUX86State,seg_cache[seg_reg].base));
1225      if (!s->addseg && seg_reg < R_FS)      if (!s->addseg && seg_reg < R_FS)
1226          s->is_jmp = 2; /* abort translation because the register may          s->is_jmp = 2; /* abort translation because the register may
1227                            have a non zero base */                            have a non zero base */
# Line 1374  static void gen_exception(DisasContext * Line 1378  static void gen_exception(DisasContext *
1378      s->is_jmp = 1;      s->is_jmp = 1;
1379  }  }
1380    
1381    /* an interrupt is different from an exception because of the
1382       priviledge checks */
1383    static void gen_interrupt(DisasContext *s, int intno,
1384                              unsigned int cur_eip, unsigned int next_eip)
1385    {
1386        if (s->cc_op != CC_OP_DYNAMIC)
1387            gen_op_set_cc_op(s->cc_op);
1388        gen_op_jmp_im(cur_eip);
1389        gen_op_raise_interrupt(intno, next_eip);
1390        s->is_jmp = 1;
1391    }
1392    
1393  /* 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
1394     direct call to the next block may occur */     direct call to the next block may occur */
1395  static void gen_jmp(DisasContext *s, unsigned int eip)  static void gen_jmp(DisasContext *s, unsigned int eip)
# Line 1650  long disas_insn(DisasContext *s, uint8_t Line 1666  long disas_insn(DisasContext *s, uint8_t
1666          case 6: /* div */          case 6: /* div */
1667              switch(ot) {              switch(ot) {
1668              case OT_BYTE:              case OT_BYTE:
1669                  gen_op_divb_AL_T0();                  gen_op_divb_AL_T0(pc_start - s->cs_base);
1670                  break;                  break;
1671              case OT_WORD:              case OT_WORD:
1672                  gen_op_divw_AX_T0();                  gen_op_divw_AX_T0(pc_start - s->cs_base);
1673                  break;                  break;
1674              default:              default:
1675              case OT_LONG:              case OT_LONG:
1676                  gen_op_divl_EAX_T0();                  gen_op_divl_EAX_T0(pc_start - s->cs_base);
1677                  break;                  break;
1678              }              }
1679              break;              break;
1680          case 7: /* idiv */          case 7: /* idiv */
1681              switch(ot) {              switch(ot) {
1682              case OT_BYTE:              case OT_BYTE:
1683                  gen_op_idivb_AL_T0();                  gen_op_idivb_AL_T0(pc_start - s->cs_base);
1684                  break;                  break;
1685              case OT_WORD:              case OT_WORD:
1686                  gen_op_idivw_AX_T0();                  gen_op_idivw_AX_T0(pc_start - s->cs_base);
1687                  break;                  break;
1688              default:              default:
1689              case OT_LONG:              case OT_LONG:
1690                  gen_op_idivl_EAX_T0();                  gen_op_idivl_EAX_T0(pc_start - s->cs_base);
1691                  break;                  break;
1692              }              }
1693              break;              break;
# Line 1738  long disas_insn(DisasContext *s, uint8_t Line 1754  long disas_insn(DisasContext *s, uint8_t
1754              gen_op_ld_T1_A0[ot]();              gen_op_ld_T1_A0[ot]();
1755              gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));              gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1756              gen_op_lduw_T0_A0();              gen_op_lduw_T0_A0();
1757              gen_movl_seg_T0(s, R_CS);              gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
1758              gen_op_movl_T0_T1();              gen_op_movl_T0_T1();
1759              gen_op_jmp_T0();              gen_op_jmp_T0();
1760              s->is_jmp = 1;              s->is_jmp = 1;
# Line 1753  long disas_insn(DisasContext *s, uint8_t Line 1769  long disas_insn(DisasContext *s, uint8_t
1769              gen_op_ld_T1_A0[ot]();              gen_op_ld_T1_A0[ot]();
1770              gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));              gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1771              gen_op_lduw_T0_A0();              gen_op_lduw_T0_A0();
1772              gen_movl_seg_T0(s, R_CS);              gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
1773              gen_op_movl_T0_T1();              gen_op_movl_T0_T1();
1774              gen_op_jmp_T0();              gen_op_jmp_T0();
1775              s->is_jmp = 1;              s->is_jmp = 1;
# Line 1970  long disas_insn(DisasContext *s, uint8_t Line 1986  long disas_insn(DisasContext *s, uint8_t
1986      case 0x17: /* pop ss */      case 0x17: /* pop ss */
1987      case 0x1f: /* pop ds */      case 0x1f: /* pop ds */
1988          gen_pop_T0(s);          gen_pop_T0(s);
1989          gen_movl_seg_T0(s, b >> 3);          gen_movl_seg_T0(s, b >> 3, pc_start - s->cs_base);
1990          gen_pop_update(s);          gen_pop_update(s);
1991          break;          break;
1992      case 0x1a1: /* pop fs */      case 0x1a1: /* pop fs */
1993      case 0x1a9: /* pop gs */      case 0x1a9: /* pop gs */
1994          gen_pop_T0(s);          gen_pop_T0(s);
1995          gen_movl_seg_T0(s, (b >> 3) & 7);          gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
1996          gen_pop_update(s);          gen_pop_update(s);
1997          break;          break;
1998    
# Line 2030  long disas_insn(DisasContext *s, uint8_t Line 2046  long disas_insn(DisasContext *s, uint8_t
2046          gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);          gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2047          if (reg >= 6 || reg == R_CS)          if (reg >= 6 || reg == R_CS)
2048              goto illegal_op;              goto illegal_op;
2049          gen_movl_seg_T0(s, reg);          gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2050          break;          break;
2051      case 0x8c: /* mov Gv, seg */      case 0x8c: /* mov Gv, seg */
2052          ot = dflag ? OT_LONG : OT_WORD;          ot = dflag ? OT_LONG : OT_WORD;
# Line 2231  long disas_insn(DisasContext *s, uint8_t Line 2247  long disas_insn(DisasContext *s, uint8_t
2247          gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));          gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2248          /* load the segment first to handle exceptions properly */          /* load the segment first to handle exceptions properly */
2249          gen_op_lduw_T0_A0();          gen_op_lduw_T0_A0();
2250          gen_movl_seg_T0(s, op);          gen_movl_seg_T0(s, op, pc_start - s->cs_base);
2251          /* then put the data */          /* then put the data */
2252          gen_op_mov_reg_T1[ot][reg]();          gen_op_mov_reg_T1[ot][reg]();
2253          break;          break;
# Line 2914  long disas_insn(DisasContext *s, uint8_t Line 2930  long disas_insn(DisasContext *s, uint8_t
2930          gen_pop_update(s);          gen_pop_update(s);
2931          /* pop selector */          /* pop selector */
2932          gen_pop_T0(s);          gen_pop_T0(s);
2933          gen_movl_seg_T0(s, R_CS);          gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
2934          gen_pop_update(s);          gen_pop_update(s);
2935          /* add stack offset */          /* add stack offset */
2936          if (s->ss32)          if (s->ss32)
# Line 2933  long disas_insn(DisasContext *s, uint8_t Line 2949  long disas_insn(DisasContext *s, uint8_t
2949          gen_pop_update(s);          gen_pop_update(s);
2950          /* pop selector */          /* pop selector */
2951          gen_pop_T0(s);          gen_pop_T0(s);
2952          gen_movl_seg_T0(s, R_CS);          gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
2953          gen_pop_update(s);          gen_pop_update(s);
2954          s->is_jmp = 1;          s->is_jmp = 1;
2955          break;          break;
# Line 2950  long disas_insn(DisasContext *s, uint8_t Line 2966  long disas_insn(DisasContext *s, uint8_t
2966              gen_pop_update(s);              gen_pop_update(s);
2967              /* pop selector */              /* pop selector */
2968              gen_pop_T0(s);              gen_pop_T0(s);
2969              gen_movl_seg_T0(s, R_CS);              gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
2970              gen_pop_update(s);              gen_pop_update(s);
2971              /* pop eflags */              /* pop eflags */
2972              gen_pop_T0(s);              gen_pop_T0(s);
# Line 2995  long disas_insn(DisasContext *s, uint8_t Line 3011  long disas_insn(DisasContext *s, uint8_t
3011    
3012              /* change cs and pc */              /* change cs and pc */
3013              gen_op_movl_T0_im(selector);              gen_op_movl_T0_im(selector);
3014              gen_movl_seg_T0(s, R_CS);              gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
3015              gen_op_jmp_im((unsigned long)offset);              gen_op_jmp_im((unsigned long)offset);
3016              s->is_jmp = 1;              s->is_jmp = 1;
3017          }          }
# Line 3018  long disas_insn(DisasContext *s, uint8_t Line 3034  long disas_insn(DisasContext *s, uint8_t
3034                            
3035              /* change cs and pc */              /* change cs and pc */
3036              gen_op_movl_T0_im(selector);              gen_op_movl_T0_im(selector);
3037              gen_movl_seg_T0(s, R_CS);              gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
3038              gen_op_jmp_im((unsigned long)offset);              gen_op_jmp_im((unsigned long)offset);
3039              s->is_jmp = 1;              s->is_jmp = 1;
3040          }          }
# Line 3255  long disas_insn(DisasContext *s, uint8_t Line 3271  long disas_insn(DisasContext *s, uint8_t
3271      case 0x9b: /* fwait */      case 0x9b: /* fwait */
3272          break;          break;
3273      case 0xcc: /* int3 */      case 0xcc: /* int3 */
3274          gen_exception(s, EXCP03_INT3, s->pc - s->cs_base);          gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
3275          break;          break;
3276      case 0xcd: /* int N */      case 0xcd: /* int N */
3277          val = ldub(s->pc++);          val = ldub(s->pc++);
3278          if (s->cc_op != CC_OP_DYNAMIC)          /* XXX: add error code for vm86 GPF */
3279              gen_op_set_cc_op(s->cc_op);          if (!s->vm86)
3280          gen_op_int_im(val, pc_start - s->cs_base);              gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
3281          s->is_jmp = 1;          else
3282                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3283          break;          break;
3284      case 0xce: /* into */      case 0xce: /* into */
3285          if (s->cc_op != CC_OP_DYNAMIC)          if (s->cc_op != CC_OP_DYNAMIC)
# Line 3309  long disas_insn(DisasContext *s, uint8_t Line 3326  long disas_insn(DisasContext *s, uint8_t
3326          gen_op_mov_reg_T0[ot][reg]();          gen_op_mov_reg_T0[ot][reg]();
3327          gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);          gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3328          if (ot == OT_WORD)          if (ot == OT_WORD)
3329              gen_op_boundw();              gen_op_boundw(pc_start - s->cs_base);
3330          else          else
3331              gen_op_boundl();              gen_op_boundl(pc_start - s->cs_base);
3332          break;          break;
3333      case 0x1c8 ... 0x1cf: /* bswap reg */      case 0x1c8 ... 0x1cf: /* bswap reg */
3334          reg = b & 7;          reg = b & 7;
# Line 3670  static void optimize_flags(uint16_t *opc Line 3687  static void optimize_flags(uint16_t *opc
3687    
3688  #ifdef DEBUG_DISAS  #ifdef DEBUG_DISAS
3689  static const char *op_str[] = {  static const char *op_str[] = {
3690  #define DEF(s, n) #s,  #define DEF(s, n, copy_size) #s,
3691  #include "opc-i386.h"  #include "opc-i386.h"
3692  #undef DEF  #undef DEF
3693  };  };
3694    
3695  static uint8_t op_nb_args[] = {  static uint8_t op_nb_args[] = {
3696  #define DEF(s, n) n,  #define DEF(s, n, copy_size) n,
3697  #include "opc-i386.h"  #include "opc-i386.h"
3698  #undef DEF  #undef DEF
3699  };  };
# Line 3706  static void dump_ops(const uint16_t *opc Line 3723  static void dump_ops(const uint16_t *opc
3723    
3724  #endif  #endif
3725    
 /* XXX: make this buffer thread safe */  
3726  /* XXX: make safe guess about sizes */  /* XXX: make safe guess about sizes */
3727  #define MAX_OP_PER_INSTR 32  #define MAX_OP_PER_INSTR 32
3728  #define OPC_BUF_SIZE 512  #define OPC_BUF_SIZE 512
# Line 3716  static void dump_ops(const uint16_t *opc Line 3732  static void dump_ops(const uint16_t *opc
3732    
3733  static uint16_t gen_opc_buf[OPC_BUF_SIZE];  static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3734  static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];  static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3735    static uint32_t gen_opc_pc[OPC_BUF_SIZE];
3736    static uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
3737    
3738  /* return non zero if the very first instruction is invalid so that  /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
3739     the virtual CPU can trigger an exception.     basic block 'tb'. If search_pc is TRUE, also generate PC
3740       information for each intermediate instruction. */
3741     '*code_size_ptr' contains the target code size including the  static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc)
    instruction which triggered an exception, except in case of invalid  
    illegal opcode. It must never exceed one target page.  
     
    '*gen_code_size_ptr' contains the size of the generated code (host  
    code).  
 */  
 int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,  
                      int *gen_code_size_ptr,  
                      uint8_t *pc_start,  uint8_t *cs_base, int flags,  
                      int *code_size_ptr, TranslationBlock *tb)  
3742  {  {
3743      DisasContext dc1, *dc = &dc1;      DisasContext dc1, *dc = &dc1;
3744      uint8_t *pc_ptr;      uint8_t *pc_ptr;
3745      uint16_t *gen_opc_end;      uint16_t *gen_opc_end;
3746      int gen_code_size;      int flags, j, lj;
3747      long ret;      long ret;
3748        uint8_t *pc_start;
3749        uint8_t *cs_base;
3750            
3751      /* generate intermediate code */      /* generate intermediate code */
3752        pc_start = (uint8_t *)tb->pc;
3753        cs_base = (uint8_t *)tb->cs_base;
3754        flags = tb->flags;
3755          
3756      dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;      dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3757      dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;      dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3758      dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;      dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
# Line 3758  int cpu_x86_gen_code(uint8_t *gen_code_b Line 3771  int cpu_x86_gen_code(uint8_t *gen_code_b
3771    
3772      dc->is_jmp = 0;      dc->is_jmp = 0;
3773      pc_ptr = pc_start;      pc_ptr = pc_start;
3774        lj = -1;
3775      do {      do {
3776            if (search_pc) {
3777                j = gen_opc_ptr - gen_opc_buf;
3778                if (lj < j) {
3779                    lj++;
3780                    while (lj < j)
3781                        gen_opc_instr_start[lj++] = 0;
3782                    gen_opc_pc[lj] = (uint32_t)pc_ptr;
3783                    gen_opc_instr_start[lj] = 1;
3784                }
3785            }
3786          ret = disas_insn(dc, pc_ptr);          ret = disas_insn(dc, pc_ptr);
3787          if (ret == -1) {          if (ret == -1) {
3788              /* we trigger an illegal instruction operation only if it              /* we trigger an illegal instruction operation only if it
# Line 3819  int cpu_x86_gen_code(uint8_t *gen_code_b Line 3843  int cpu_x86_gen_code(uint8_t *gen_code_b
3843          fprintf(logfile, "\n");          fprintf(logfile, "\n");
3844      }      }
3845  #endif  #endif
3846        if (!search_pc)
3847            tb->size = pc_ptr - pc_start;
3848        return 0;
3849    }
3850    
3851    
3852    /* return non zero if the very first instruction is invalid so that
3853       the virtual CPU can trigger an exception.
3854    
3855       '*gen_code_size_ptr' contains the size of the generated code (host
3856       code).
3857    */
3858    int cpu_x86_gen_code(TranslationBlock *tb,
3859                         int max_code_size, int *gen_code_size_ptr)
3860    {
3861        uint8_t *gen_code_buf;
3862        int gen_code_size;
3863    
3864        if (gen_intermediate_code(tb, 0) < 0)
3865            return -1;
3866    
3867      /* generate machine code */      /* generate machine code */
3868      tb->tb_next_offset[0] = 0xffff;      tb->tb_next_offset[0] = 0xffff;
3869      tb->tb_next_offset[1] = 0xffff;      tb->tb_next_offset[1] = 0xffff;
3870        gen_code_buf = tb->tc_ptr;
3871      gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,      gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
3872  #ifdef USE_DIRECT_JUMP  #ifdef USE_DIRECT_JUMP
3873                                  tb->tb_jmp_offset,                                  tb->tb_jmp_offset,
# Line 3831  int cpu_x86_gen_code(uint8_t *gen_code_b Line 3876  int cpu_x86_gen_code(uint8_t *gen_code_b
3876  #endif  #endif
3877                                  gen_opc_buf, gen_opparam_buf);                                  gen_opc_buf, gen_opparam_buf);
3878      flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));      flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3879        
3880      *gen_code_size_ptr = gen_code_size;      *gen_code_size_ptr = gen_code_size;
     *code_size_ptr = pc_ptr - pc_start;  
3881  #ifdef DEBUG_DISAS  #ifdef DEBUG_DISAS
3882      if (loglevel) {      if (loglevel) {
3883          fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);          fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3884          disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);          disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);
3885          fprintf(logfile, "\n");          fprintf(logfile, "\n");
3886          fflush(logfile);          fflush(logfile);
3887      }      }
# Line 3845  int cpu_x86_gen_code(uint8_t *gen_code_b Line 3889  int cpu_x86_gen_code(uint8_t *gen_code_b
3889      return 0;      return 0;
3890  }  }
3891    
3892    static const unsigned short opc_copy_size[] = {
3893    #define DEF(s, n, copy_size) copy_size,
3894    #include "opc-i386.h"
3895    #undef DEF
3896    };
3897    
3898    /* The simulated PC corresponding to
3899       'searched_pc' in the generated code is searched. 0 is returned if
3900       found. *found_pc contains the found PC.
3901     */
3902    int cpu_x86_search_pc(TranslationBlock *tb,
3903                          uint32_t *found_pc, unsigned long searched_pc)
3904    {
3905        int j, c;
3906        unsigned long tc_ptr;
3907        uint16_t *opc_ptr;
3908    
3909        if (gen_intermediate_code(tb, 1) < 0)
3910            return -1;
3911        
3912        /* find opc index corresponding to search_pc */
3913        tc_ptr = (unsigned long)tb->tc_ptr;
3914        if (searched_pc < tc_ptr)
3915            return -1;
3916        j = 0;
3917        opc_ptr = gen_opc_buf;
3918        for(;;) {
3919            c = *opc_ptr;
3920            if (c == INDEX_op_end)
3921                return -1;
3922            tc_ptr += opc_copy_size[c];
3923            if (searched_pc < tc_ptr)
3924                break;
3925            opc_ptr++;
3926        }
3927        j = opc_ptr - gen_opc_buf;
3928        /* now find start of instruction before */
3929        while (gen_opc_instr_start[j] == 0)
3930            j--;
3931        *found_pc = gen_opc_pc[j];
3932        return 0;
3933    }
3934    
3935    
3936  CPUX86State *cpu_x86_init(void)  CPUX86State *cpu_x86_init(void)
3937  {  {
3938      CPUX86State *env;      CPUX86State *env;

Legend:
Removed from v.1.37  
changed lines
  Added in v.1.38

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