/[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.35 by bellard, Fri May 16 13:46:28 2003 UTC revision 1.36 by bellard, Sun May 25 16:46:15 2003 UTC
# Line 31  Line 31 
31    
32  #define IN_OP_I386  #define IN_OP_I386
33  #include "cpu-i386.h"  #include "cpu-i386.h"
34    #include "exec.h"
35    
36  /* XXX: move that elsewhere */  /* XXX: move that elsewhere */
37  static uint16_t *gen_opc_ptr;  static uint16_t *gen_opc_ptr;
38  static uint32_t *gen_opparam_ptr;  static uint32_t *gen_opparam_ptr;
39  int __op_param1, __op_param2, __op_param3;  int __op_param1, __op_param2, __op_param3;
40    #ifdef USE_DIRECT_JUMP
41    int __op_jmp0, __op_jmp1;
42    #endif
43    
44  #ifdef __i386__  #ifdef __i386__
45  static inline void flush_icache_range(unsigned long start, unsigned long stop)  static inline void flush_icache_range(unsigned long start, unsigned long stop)
# Line 67  static void inline flush_icache_range(un Line 71  static void inline flush_icache_range(un
71      stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);      stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
72            
73      for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {      for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
74          asm ("dcbst 0,%0;" : : "r"(p) : "memory");          asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
75      }      }
76      asm ("sync");      asm volatile ("sync" : : : "memory");
77      for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {      for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
78          asm ("icbi 0,%0; sync;" : : "r"(p) : "memory");          asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
79      }      }
80      asm ("sync");      asm volatile ("sync" : : : "memory");
81      asm ("isync");      asm volatile ("isync" : : : "memory");
82  }  }
83  #endif  #endif
84    
# Line 129  typedef struct DisasContext { Line 133  typedef struct DisasContext {
133      int cpl;      int cpl;
134      int iopl;      int iopl;
135      int tf;     /* TF cpu flag */      int tf;     /* TF cpu flag */
136        TranslationBlock *tb;
137  } DisasContext;  } DisasContext;
138    
139  /* i386 arith/logic operations */  /* i386 arith/logic operations */
# Line 192  enum { Line 197  enum {
197  typedef void (GenOpFunc)(void);  typedef void (GenOpFunc)(void);
198  typedef void (GenOpFunc1)(long);  typedef void (GenOpFunc1)(long);
199  typedef void (GenOpFunc2)(long, long);  typedef void (GenOpFunc2)(long, long);
200    typedef void (GenOpFunc3)(long, long, long);
201                                            
202  static GenOpFunc *gen_op_mov_reg_T0[3][8] = {  static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
203      [OT_BYTE] = {      [OT_BYTE] = {
# Line 699  enum { Line 705  enum {
705      JCC_LE,      JCC_LE,
706  };  };
707    
708  static GenOpFunc2 *gen_jcc_slow[8] = {  static GenOpFunc3 *gen_jcc_sub[3][8] = {
     gen_op_jo_cc,  
     gen_op_jb_cc,  
     gen_op_jz_cc,  
     gen_op_jbe_cc,  
     gen_op_js_cc,  
     gen_op_jp_cc,  
     gen_op_jl_cc,  
     gen_op_jle_cc,  
 };  
       
 static GenOpFunc2 *gen_jcc_sub[3][8] = {  
709      [OT_BYTE] = {      [OT_BYTE] = {
710          NULL,          NULL,
711          gen_op_jb_subb,          gen_op_jb_subb,
# Line 1090  static inline uint32_t insn_get(DisasCon Line 1085  static inline uint32_t insn_get(DisasCon
1085    
1086  static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)  static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
1087  {  {
1088        TranslationBlock *tb;
1089      int inv, jcc_op;      int inv, jcc_op;
1090      GenOpFunc2 *func;      GenOpFunc3 *func;
1091    
1092      inv = b & 1;      inv = b & 1;
1093      jcc_op = (b >> 1) & 7;      jcc_op = (b >> 1) & 7;
# Line 1101  static inline void gen_jcc(DisasContext Line 1097  static inline void gen_jcc(DisasContext
1097      case CC_OP_SUBW:      case CC_OP_SUBW:
1098      case CC_OP_SUBL:      case CC_OP_SUBL:
1099          func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];          func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
         if (!func)  
             goto slow_jcc;  
1100          break;          break;
1101                    
1102          /* some jumps are easy to compute */          /* some jumps are easy to compute */
# Line 1138  static inline void gen_jcc(DisasContext Line 1132  static inline void gen_jcc(DisasContext
1132              func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];              func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1133              break;              break;
1134          default:          default:
1135              goto slow_jcc;              func = NULL;
1136                break;
1137          }          }
1138          break;          break;
1139      default:      default:
1140      slow_jcc:          func = NULL;
         if (s->cc_op != CC_OP_DYNAMIC)  
             gen_op_set_cc_op(s->cc_op);  
         func = gen_jcc_slow[jcc_op];  
1141          break;          break;
1142      }      }
1143    
1144        if (s->cc_op != CC_OP_DYNAMIC)
1145            gen_op_set_cc_op(s->cc_op);
1146    
1147        if (!func) {
1148            gen_setcc_slow[jcc_op]();
1149            func = gen_op_jcc;
1150        }
1151        
1152        tb = s->tb;
1153      if (!inv) {      if (!inv) {
1154          func(val, next_eip);          func((long)tb, val, next_eip);
1155      } else {      } else {
1156          func(next_eip, val);          func((long)tb, next_eip, val);
1157      }      }
1158        s->is_jmp = 3;
1159  }  }
1160    
1161  static void gen_setcc(DisasContext *s, int b)  static void gen_setcc(DisasContext *s, int b)
# Line 1372  static void gen_exception(DisasContext * Line 1375  static void gen_exception(DisasContext *
1375      s->is_jmp = 1;      s->is_jmp = 1;
1376  }  }
1377    
1378    /* generate a jump to eip. No segment change must happen before as a
1379       direct call to the next block may occur */
1380    static void gen_jmp(DisasContext *s, unsigned int eip)
1381    {
1382        TranslationBlock *tb = s->tb;
1383    
1384        if (s->cc_op != CC_OP_DYNAMIC)
1385            gen_op_set_cc_op(s->cc_op);
1386        gen_op_jmp_tb_next((long)tb, eip);
1387        s->is_jmp = 3;
1388    }
1389    
1390  /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr  /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1391     is set to true if the instruction sets the PC (last instruction of     is set to true if the instruction sets the PC (last instruction of
1392     a basic block) */     a basic block) */
# Line 2964  long disas_insn(DisasContext *s, uint8_t Line 2979  long disas_insn(DisasContext *s, uint8_t
2979                  val &= 0xffff;                  val &= 0xffff;
2980              gen_op_movl_T0_im(next_eip);              gen_op_movl_T0_im(next_eip);
2981              gen_push_T0(s);              gen_push_T0(s);
2982              gen_op_jmp_im(val);              gen_jmp(s, val);
             s->is_jmp = 1;  
2983          }          }
2984          break;          break;
2985      case 0x9a: /* lcall im */      case 0x9a: /* lcall im */
# Line 2996  long disas_insn(DisasContext *s, uint8_t Line 3010  long disas_insn(DisasContext *s, uint8_t
3010          val += s->pc - s->cs_base;          val += s->pc - s->cs_base;
3011          if (s->dflag == 0)          if (s->dflag == 0)
3012              val = val & 0xffff;              val = val & 0xffff;
3013          gen_op_jmp_im(val);          gen_jmp(s, val);
         s->is_jmp = 1;  
3014          break;          break;
3015      case 0xea: /* ljmp im */      case 0xea: /* ljmp im */
3016          {          {
# Line 3019  long disas_insn(DisasContext *s, uint8_t Line 3032  long disas_insn(DisasContext *s, uint8_t
3032          val += s->pc - s->cs_base;          val += s->pc - s->cs_base;
3033          if (s->dflag == 0)          if (s->dflag == 0)
3034              val = val & 0xffff;              val = val & 0xffff;
3035          gen_op_jmp_im(val);          gen_jmp(s, val);
         s->is_jmp = 1;  
3036          break;          break;
3037      case 0x70 ... 0x7f: /* jcc Jb */      case 0x70 ... 0x7f: /* jcc Jb */
3038          val = (int8_t)insn_get(s, OT_BYTE);          val = (int8_t)insn_get(s, OT_BYTE);
# Line 3037  long disas_insn(DisasContext *s, uint8_t Line 3049  long disas_insn(DisasContext *s, uint8_t
3049          if (s->dflag == 0)          if (s->dflag == 0)
3050              val &= 0xffff;              val &= 0xffff;
3051          gen_jcc(s, b, val, next_eip);          gen_jcc(s, b, val, next_eip);
         s->is_jmp = 1;  
3052          break;          break;
3053    
3054      case 0x190 ... 0x19f: /* setcc Gv */      case 0x190 ... 0x19f: /* setcc Gv */
# Line 3393  static uint16_t opc_read_flags[NB_OPS] = Line 3404  static uint16_t opc_read_flags[NB_OPS] =
3404    
3405      [INDEX_op_into] = CC_O,      [INDEX_op_into] = CC_O,
3406    
     [INDEX_op_jo_cc] = CC_O,  
     [INDEX_op_jb_cc] = CC_C,  
     [INDEX_op_jz_cc] = CC_Z,  
     [INDEX_op_jbe_cc] = CC_Z | CC_C,  
     [INDEX_op_js_cc] = CC_S,  
     [INDEX_op_jp_cc] = CC_P,  
     [INDEX_op_jl_cc] = CC_O | CC_S,  
     [INDEX_op_jle_cc] = CC_O | CC_S | CC_Z,  
   
3407      [INDEX_op_jb_subb] = CC_C,      [INDEX_op_jb_subb] = CC_C,
3408      [INDEX_op_jb_subw] = CC_C,      [INDEX_op_jb_subw] = CC_C,
3409      [INDEX_op_jb_subl] = CC_C,      [INDEX_op_jb_subl] = CC_C,
# Line 3730  static uint32_t gen_opparam_buf[OPPARAM_ Line 3732  static uint32_t gen_opparam_buf[OPPARAM_
3732  int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,  int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
3733                       int *gen_code_size_ptr,                       int *gen_code_size_ptr,
3734                       uint8_t *pc_start,  uint8_t *cs_base, int flags,                       uint8_t *pc_start,  uint8_t *cs_base, int flags,
3735                       int *code_size_ptr)                       int *code_size_ptr, TranslationBlock *tb)
3736  {  {
3737      DisasContext dc1, *dc = &dc1;      DisasContext dc1, *dc = &dc1;
3738      uint8_t *pc_ptr;      uint8_t *pc_ptr;
# Line 3750  int cpu_x86_gen_code(uint8_t *gen_code_b Line 3752  int cpu_x86_gen_code(uint8_t *gen_code_b
3752      dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;      dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;
3753      dc->cc_op = CC_OP_DYNAMIC;      dc->cc_op = CC_OP_DYNAMIC;
3754      dc->cs_base = cs_base;      dc->cs_base = cs_base;
3755        dc->tb = tb;
3756    
3757      gen_opc_ptr = gen_opc_buf;      gen_opc_ptr = gen_opc_buf;
3758      gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;      gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
# Line 3776  int cpu_x86_gen_code(uint8_t *gen_code_b Line 3779  int cpu_x86_gen_code(uint8_t *gen_code_b
3779      } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&      } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
3780               (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));               (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
3781      /* we must store the eflags state if it is not already done */      /* we must store the eflags state if it is not already done */
3782      if (dc->cc_op != CC_OP_DYNAMIC)      if (dc->is_jmp != 3) {
3783          gen_op_set_cc_op(dc->cc_op);          if (dc->cc_op != CC_OP_DYNAMIC)
3784      if (dc->is_jmp != 1) {              gen_op_set_cc_op(dc->cc_op);
3785          /* we add an additionnal jmp to update the simulated PC */          if (dc->is_jmp != 1) {
3786          gen_op_jmp_im(ret - (unsigned long)dc->cs_base);              /* we add an additionnal jmp to update the simulated PC */
3787                gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
3788            }
3789      }      }
3790      if (dc->tf) {      if (dc->tf) {
3791          gen_op_raise_exception(EXCP01_SSTP);          gen_op_raise_exception(EXCP01_SSTP);
3792      }      }
3793        if (dc->is_jmp != 3) {
3794            /* indicate that the hash table must be used to find the next TB */
3795            gen_op_movl_T0_0();
3796        }
3797    
3798      *gen_opc_ptr = INDEX_op_end;      *gen_opc_ptr = INDEX_op_end;
3799    
# Line 3814  int cpu_x86_gen_code(uint8_t *gen_code_b Line 3823  int cpu_x86_gen_code(uint8_t *gen_code_b
3823  #endif  #endif
3824    
3825      /* generate machine code */      /* generate machine code */
3826      gen_code_size = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf);      tb->tb_next_offset[0] = 0xffff;
3827        tb->tb_next_offset[1] = 0xffff;
3828        gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
3829    #ifdef USE_DIRECT_JUMP
3830                                    tb->tb_jmp_offset,
3831    #else
3832                                    NULL,
3833    #endif
3834                                    gen_opc_buf, gen_opparam_buf);
3835      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));
3836    
3837      *gen_code_size_ptr = gen_code_size;      *gen_code_size_ptr = gen_code_size;
3838      *code_size_ptr = pc_ptr - pc_start;      *code_size_ptr = pc_ptr - pc_start;
3839  #ifdef DEBUG_DISAS  #ifdef DEBUG_DISAS

Legend:
Removed from v.1.35  
changed lines
  Added in v.1.36

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