/[gxemul]/trunk/src/cpus/cpu_x86_instr.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/cpus/cpu_x86_instr.c

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

revision 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC revision 24 by dpavlin, Mon Oct 8 16:19:56 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_x86_instr.c,v 1.5 2006/02/09 22:55:20 debug Exp $   *  $Id: cpu_x86_instr.c,v 1.13 2006/04/22 18:07:30 debug Exp $
29   *   *
30   *  x86/amd64 instructions.   *  x86/amd64 instructions.
31   *   *
# Line 48  X(nop) Line 48  X(nop)
48  /*****************************************************************************/  /*****************************************************************************/
49    
50    
51    /*
52     *  sti, cli, std, cld, stc, clc:  Set/clear flag bits.
53     */
54    X(stc) { cpu->cd.x86.rflags |= X86_FLAGS_CF; }
55    X(clc) { cpu->cd.x86.rflags &= ~X86_FLAGS_CF; }
56    X(std) { cpu->cd.x86.rflags |= X86_FLAGS_DF; }
57    X(cld) { cpu->cd.x86.rflags &= ~X86_FLAGS_DF; }
58    X(sti) { cpu->cd.x86.rflags |= X86_FLAGS_IF; }
59    X(cli) { cpu->cd.x86.rflags &= ~X86_FLAGS_IF; }
60    
61    
62    /*
63     *  cpuid
64     */
65    X(cpuid)
66    {
67            x86_cpuid(cpu);
68    }
69    
70    
71    /*
72     *  inc, dec
73     */
74    X(inc_ax)
75    {
76            MODE_uint_t r = cpu->cd.x86.r[X86_R_AX], r2 = r + 1;
77            cpu->cd.x86.r[X86_R_AX] = (r & ~0xffff) + (r2 & 0xffff);
78    }
79    X(inc_cx)
80    {
81            MODE_uint_t r = cpu->cd.x86.r[X86_R_CX], r2 = r + 1;
82            cpu->cd.x86.r[X86_R_CX] = (r & ~0xffff) + (r2 & 0xffff);
83    }
84    X(inc_dx)
85    {
86            MODE_uint_t r = cpu->cd.x86.r[X86_R_DX], r2 = r + 1;
87            cpu->cd.x86.r[X86_R_DX] = (r & ~0xffff) + (r2 & 0xffff);
88    }
89    X(inc_bx)
90    {
91            MODE_uint_t r = cpu->cd.x86.r[X86_R_BX], r2 = r + 1;
92            cpu->cd.x86.r[X86_R_BX] = (r & ~0xffff) + (r2 & 0xffff);
93    }
94    X(inc_sp)
95    {
96            MODE_uint_t r = cpu->cd.x86.r[X86_R_SP], r2 = r + 1;
97            cpu->cd.x86.r[X86_R_SP] = (r & ~0xffff) + (r2 & 0xffff);
98    }
99    X(inc_bp)
100    {
101            MODE_uint_t r = cpu->cd.x86.r[X86_R_BP], r2 = r + 1;
102            cpu->cd.x86.r[X86_R_BP] = (r & ~0xffff) + (r2 & 0xffff);
103    }
104    X(inc_si)
105    {
106            MODE_uint_t r = cpu->cd.x86.r[X86_R_SI], r2 = r + 1;
107            cpu->cd.x86.r[X86_R_SI] = (r & ~0xffff) + (r2 & 0xffff);
108    }
109    X(inc_di)
110    {
111            MODE_uint_t r = cpu->cd.x86.r[X86_R_DI], r2 = r + 1;
112            cpu->cd.x86.r[X86_R_DI] = (r & ~0xffff) + (r2 & 0xffff);
113    }
114    X(inc_eax) { cpu->cd.x86.r[X86_R_AX] ++; }
115    X(inc_ecx) { cpu->cd.x86.r[X86_R_CX] ++; }
116    X(inc_edx) { cpu->cd.x86.r[X86_R_DX] ++; }
117    X(inc_ebx) { cpu->cd.x86.r[X86_R_BX] ++; }
118    X(inc_esp) { cpu->cd.x86.r[X86_R_SP] ++; }
119    X(inc_ebp) { cpu->cd.x86.r[X86_R_BP] ++; }
120    X(inc_esi) { cpu->cd.x86.r[X86_R_SI] ++; }
121    X(inc_edi) { cpu->cd.x86.r[X86_R_DI] ++; }
122    
123    
124    /*
125     *  mov_reg_imm_8:
126     *
127     *  arg[1] = imm8
128     *  arg[2] = pointer to a _byte_ inside an emulated register
129     */
130    X(mov_reg_imm_8)
131    {
132            *((uint8_t *)ic->arg[2]) = ic->arg[1];
133    }
134    
135    
136    /*
137     *  mov_reg_imm_16, _32
138     */
139    X(mov_reg_imm_16)
140    {
141            reg(ic->arg[2]) &= ~0xffff;
142            reg(ic->arg[2]) |= ic->arg[1];
143    }
144    X(mov_reg_imm_32)
145    {
146            reg(ic->arg[2]) = (uint32_t)ic->arg[1];
147    }
148    
149    
150    /*****************************************************************************/
151    
152    
153  X(end_of_page)  X(end_of_page)
154  {  {
155          /*  Update the PC:  (offset 0, but on the next page)  */          /*  Update the PC:  (offset 0, but on the next page)  */
# Line 65  X(end_of_page) Line 167  X(end_of_page)
167  /*****************************************************************************/  /*****************************************************************************/
168    
169    
170    #ifdef GET_NEXT_BYTE
171    #undef GET_NEXT_BYTE
172    #endif
173    #ifdef MODE32
174    #define GET_NEXT_BYTE get_next_byte32
175    #else
176    #define GET_NEXT_BYTE get_next_byte64
177    #endif
178    /*  Get the next instruction byte; return 1 on success, 0 on failure  */
179    int GET_NEXT_BYTE(struct cpu *cpu, unsigned char *byte, MODE_uint_t addr)
180    {
181            unsigned char *page;
182    
183            /*  Read the instruction word from memory:  */
184    #ifdef MODE32
185            page = cpu->cd.x86.host_load[addr >> 12];
186    #else
187            {
188                    const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
189                    const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
190                    const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
191                    uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
192                    uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
193                    uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
194                        DYNTRANS_L3N)) & mask3;
195                    struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.x86.l1_64[x1];
196                    struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
197                    page = l3->host_load[x3];
198            }
199    #endif
200    
201            if (page != NULL) {
202                    /*  fatal("TRANSLATION HIT!\n");  */
203                    (*byte) = page[addr & 0xfff];
204            } else {
205                    /*  fatal("TRANSLATION MISS!\n");  */
206                    if (!cpu->memory_rw(cpu, cpu->mem, addr, byte,
207                        1, MEM_READ, CACHE_INSTRUCTION)) {
208                            /*  exception occurred, or similar  */
209                            return 0;
210                    }
211            }
212    
213            return 1;
214    }
215    
216    
217    #ifndef GNB
218    #define GNB     { if (len >= sizeof(ib))                        \
219                            goto bad;                               \
220                      if (!GET_NEXT_BYTE(cpu, &ib[len++], addr++))  \
221                            goto gnb_failed;                        \
222                    }
223    #endif
224    
225    
226    #ifndef GET_OP
227    #define GET_OP  opimm = 0;                                      \
228                    {                                               \
229                            int i;                                  \
230                            for (i=0; i<oplen; i++) {               \
231                                    GNB;                            \
232                                    opimm |= (ib[len-1] << (i*8));  \
233                            }                                       \
234                    }
235    #endif
236    
237    
238  /*  /*
239   *  x86_instr_to_be_translated():   *  x86_instr_to_be_translated():
240   *   *
# Line 75  X(end_of_page) Line 245  X(end_of_page)
245   */   */
246  X(to_be_translated)  X(to_be_translated)
247  {  {
248          uint64_t addr, low_pc;          MODE_uint_t addr, orig_addr, low_pc;
249  #ifdef DYNTRANS_BACKEND          int main_opcode, secondary_opcode, len, mode16, oplen;
250          int simple = 0;          uint32_t opimm;
 #endif  
         unsigned char *page;  
         int main_opcode;  
251          unsigned char ib[17];          unsigned char ib[17];
252          /* void (*samepage_function)(struct cpu *, struct x86_instr_call *); */          /* void (*samepage_function)(struct cpu *, struct x86_instr_call *); */
253    
# Line 90  X(to_be_translated) Line 257  X(to_be_translated)
257          addr = cpu->pc & ~(X86_IC_ENTRIES_PER_PAGE-1);          addr = cpu->pc & ~(X86_IC_ENTRIES_PER_PAGE-1);
258          addr += low_pc;          addr += low_pc;
259          cpu->pc = addr;          cpu->pc = addr;
260            orig_addr = addr;
261    
262          if (!cpu->cd.x86.descr_cache[X86_S_CS].valid) {          if (!cpu->cd.x86.descr_cache[X86_S_CS].valid) {
263                  fatal("x86_cpu_run_instr(): Invalid CS descriptor?\n");                  fatal("x86_cpu_run_instr(): Invalid CS descriptor?\n");
# Line 99  X(to_be_translated) Line 267  X(to_be_translated)
267          cpu->cd.x86.cursegment = X86_S_CS;          cpu->cd.x86.cursegment = X86_S_CS;
268          cpu->cd.x86.seg_override = 0;          cpu->cd.x86.seg_override = 0;
269    
         /*  Read the instruction word from memory:  */  
         page = cpu->cd.x86.host_load[addr >> 12];  
   
         if (page != NULL) {  
                 /*  fatal("TRANSLATION HIT!\n");  */  
                 ib[0] = page[addr & 0xfff];  
         } else {  
                 /*  fatal("TRANSLATION MISS!\n");  */  
                 if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],  
                     1, MEM_READ, CACHE_INSTRUCTION)) {  
                         fatal("to_be_translated(): read failed: TODO\n");  
                         goto bad;  
                 }  
         }  
   
         fatal("X86: ib[0] = 0x%02x\n", ib[0]);  
   
270    
271  #define DYNTRANS_TO_BE_TRANSLATED_HEAD  #define DYNTRANS_TO_BE_TRANSLATED_HEAD
272  #include "cpu_dyntrans.c"  #include "cpu_dyntrans.c"
# Line 126  X(to_be_translated) Line 277  X(to_be_translated)
277           *  Translate the instruction:           *  Translate the instruction:
278           */           */
279    
280            ic->arg[0] = len = 0;
281    
282  /*  TODO  */          if (LONG_MODE) {
283                    fatal("LONG MODE: TODO\n");
284                    goto bad;
285            }
286    
287            mode16 = REAL_MODE;
288    
289          main_opcode = ib[0];          /*  Parse prefix bytes, and get the main (first) opcode byte:  */
290            for (;;) {
291                    GNB; main_opcode = ib[len - 1];
292                    if (main_opcode == 0x66) {
293                            mode16 = !mode16;
294                    } else {
295                            /*  Found a non-prefix byte? Then break.  */
296                            break;
297                    }
298            }
299    
300            oplen = mode16? sizeof(uint16_t) : sizeof(uint32_t);
301    
302          switch (main_opcode) {          switch (main_opcode) {
303    
304            case 0x0f:
305                    GNB; secondary_opcode = ib[len-1];
306                    switch (secondary_opcode) {
307    
308                    case 0xa2:
309                            ic->f = instr(cpuid);
310                            break;
311    
312                    default:fatal("unimplemented 0x0f opcode 0x%02x\n",
313                                secondary_opcode);
314                            goto bad;
315                    }
316                    break;
317    
318            case 0x40:      /*  inc ax  etc.  */
319            case 0x41:
320            case 0x42:
321            case 0x43:
322            case 0x44:
323            case 0x45:
324            case 0x46:
325            case 0x47:
326                    if (mode16) {
327                            switch (main_opcode) {
328                            case 0x40: ic->f = instr(inc_ax); break;
329                            case 0x41: ic->f = instr(inc_cx); break;
330                            case 0x42: ic->f = instr(inc_dx); break;
331                            case 0x43: ic->f = instr(inc_bx); break;
332                            case 0x44: ic->f = instr(inc_sp); break;
333                            case 0x45: ic->f = instr(inc_bp); break;
334                            case 0x46: ic->f = instr(inc_si); break;
335                            case 0x47: ic->f = instr(inc_di); break;
336                            }
337                    } else {
338                            switch (main_opcode) {
339                            case 0x40: ic->f = instr(inc_eax); break;
340                            case 0x41: ic->f = instr(inc_ecx); break;
341                            case 0x42: ic->f = instr(inc_edx); break;
342                            case 0x43: ic->f = instr(inc_ebx); break;
343                            case 0x44: ic->f = instr(inc_esp); break;
344                            case 0x45: ic->f = instr(inc_ebp); break;
345                            case 0x46: ic->f = instr(inc_esi); break;
346                            case 0x47: ic->f = instr(inc_edi); break;
347                            }
348                    }
349                    break;
350    
351            case 0x90:      /*  nop  */
352                    ic->f = instr(nop);
353                    break;
354    
355            case 0xb0:      /*  mov al,imm  etc.  */
356            case 0xb1:
357            case 0xb2:
358            case 0xb3:
359            case 0xb4:
360            case 0xb5:
361            case 0xb6:
362            case 0xb7:
363                    GNB;
364                    ic->arg[1] = ib[len - 1];
365                    /*  Calculate for little endian first:  */
366                    ic->arg[2] = (size_t)&cpu->cd.x86.r[main_opcode & 3];
367                    if (main_opcode >= 0xb4)
368                            ic->arg[2] ++;
369    #ifdef HOST_BIG_ENDIAN
370                    /*  Switch byte order:  */
371                    ic->arg[2] = (ic->arg[2] & ~(sizeof(uint64_t)-1)) +
372                        sizeof(uint64_t) - 1 - (ic->arg[2] & (sizeof(uint64_t)-1));
373    #endif
374                    ic->f = instr(mov_reg_imm_8);
375                    break;
376    
377            case 0xb8:      /*  mov ax,imm  etc.  */
378            case 0xb9:
379            case 0xba:
380            case 0xbb:
381            case 0xbc:
382            case 0xbd:
383            case 0xbe:
384            case 0xbf:
385                    GET_OP;
386                    ic->arg[1] = opimm;
387                    ic->arg[2] = (size_t)&cpu->cd.x86.r[main_opcode - 0xb8];
388                    if (mode16)
389                            ic->f = instr(mov_reg_imm_16);
390                    else
391                            ic->f = instr(mov_reg_imm_32);
392                    break;
393    
394            case 0xf8:      /*  clc  */
395            case 0xf9:      /*  stc  */
396            case 0xfa:      /*  cli  */
397            case 0xfb:      /*  sti  */
398            case 0xfc:      /*  cld  */
399            case 0xfd:      /*  std  */
400                    switch (main_opcode) {
401                    case 0xf8: ic->f = instr(sti); break;
402                    case 0xf9: ic->f = instr(stc); break;
403                    case 0xfa: ic->f = instr(cli); break;
404                    case 0xfb: ic->f = instr(sti); break;
405                    case 0xfc: ic->f = instr(cld); break;
406                    case 0xfd: ic->f = instr(std); break;
407                    }
408                    break;
409    
410          default:goto bad;          default:goto bad;
411          }          }
412    
413    
414            if (((addr-1) & ~0xfff) != (orig_addr & ~0xfff)) {
415                    fatal("Instruction crosses page boundary. TODO\n");
416                    exit(1);
417            }
418    
419            if (len > sizeof(ib)) {
420                    fatal("INTERNAL ERROR in cpu_x86_instr.c! len = %i\n", len);
421                    exit(1);
422            }
423    
424            ic->arg[0] = len;
425            goto ok;
426    
427    
428    /*  We get here if get_next_byte failed (i.e. an excepion occured while
429        crossing a page-boundary...)  */
430    gnb_failed:
431            ic->f = instr(to_be_translated);
432            ic->arg[0] = 0;
433            /*  The program counter etc. should already have been updated.  */
434            return;
435    
436    ok:
437    
438  #define DYNTRANS_TO_BE_TRANSLATED_TAIL  #define DYNTRANS_TO_BE_TRANSLATED_TAIL
439  #include "cpu_dyntrans.c"  #include "cpu_dyntrans.c"
440  #undef  DYNTRANS_TO_BE_TRANSLATED_TAIL  #undef  DYNTRANS_TO_BE_TRANSLATED_TAIL

Legend:
Removed from v.22  
changed lines
  Added in v.24

  ViewVC Help
Powered by ViewVC 1.1.26