5750793 [rkeene@sledge /home/rkeene/devel/old/vmi586]$ cat -n main.c
  1 /*
  2   Everyone else is writing i80x86 virtual machines, why not me too?
  3     -- rkeene [010719991500] rkeene@suspend.net
  4            rkeene (Roy Keene),   rkeene@suspend.net
  5 help from, saurik (Jay Freeman), saurik@saurik.com
  6 and        #asm on the IRC network of EFnet.
  7 
  8 Lets see..
  9 
 10 doopcodereal()      Used to execute an opcode (or group of opcodes) in real mode.
 11 opcode*()       Used to execute a specific opcode.
 12 
 13 writemembyte()      Used to write to an area of memmory.
 14 readmembyte()       Used to read an area of memmory.
 15 changeval()     Change two parts of a register.
 16 getval()        Put two parts of a register together.
 17 changevalext()      Change three parts of a register.
 18 
 19 Partially implemented opcodes  [opcode*()]:
 20 0x00, 0x0f, 0xe4
 21 
 22 Fully implemented opcodes  [opcode*()]:
 23 0x04, 0x05, 0x06, 0x14, 0x15, 0x24, 0x25, 0x27, 0x2f, 0x37, 0x3f, 0x50, 0x8b, 
 24 0x98, 0xb8, 0xbe, 0xbf, 0xd4, 0xd5, 0xf3, 0xf5, 0xf7, 0xf8, 0xfc
 25 
 26 */
 27 
 28 #include <stdio.h>
 29 #include <stdlib.h>
 30 #include <math.h>
 31 #define VERSION "0.01"
 32 /* 
 33    Default to 4.0megs of RAM.
 34 */
 35 #ifndef RAMSIZE
 36 #define RAMSIZE 4194304
 37 #endif
 38 
 39 /* General Purpose regs */
 40 unsigned char   ah=0;
 41 unsigned char   bh=0;
 42 unsigned char   ch=0;
 43 unsigned char   dh=0;
 44 unsigned char   al=0;
 45 unsigned char   bl=0;
 46 unsigned char   cl=0;
 47 unsigned char   dl=0;
 48 int ip=0;
 49 int si=0;
 50 int di=0;
 51 int bp=0;
 52 int sp=0;
 53 int     ax=0;
 54 int bx=0;
 55 int cx=0;
 56 int dx=0;
 57 long    eax=0;
 58 long    ebx=0;
 59 long    ecx=0;
 60 long    edx=0;
 61 long    esi=0;
 62 long    edi=0;
 63 long    ebp=0;
 64 long    esp=0;
 65 long    eip=0;
 66 
 67 /* Flags */
 68 int af=0;
 69 int cf=0;
 70 int df=0;
 71 int IF=0;
 72 int eflags=         0x00000000;
 73 int eflags_reset=   0x00000002;
 74 int eflags_id=  0x00200000;
 75 int eflags_vip= 0x00100000;
 76 int eflags_vif= 0x00080000;
 77 int eflags_ac=  0x00040000;
 78 int eflags_vm=  0x00020000;
 79 int eflags_rf=  0x00010000;
 80 int eflags_nt=  0x00004000;
 81 int eflags_iopl3=   0x00003000;
 82 int eflags_iopl2=   0x00002000;
 83 int eflags_iopl1=   0x00001000;
 84 int eflags_iopl0=   0x00000000;
 85 int eflags_of=  0x00000800;
 86 int eflags_di=  0x00000400; 
 87 int     eflags_if=  0x00000200;
 88 int eflags_tf=  0x00000100;
 89 int eflags_sf=  0x00000080;
 90 int eflags_zf=  0x00000040;
 91 int eflags_af=  0x00000010;
 92 int eflags_pf=  0x00000004;
 93 int eflags_cf=  0x00000001;
 94 
 95 /* Segment Regs */
 96 long    cs=0;
 97 long    ss=0;
 98 long    ds=0;
 99 long    es=0;
100 long    fs=0;
101 long    gs=0;
102 
103 /* Table Regs */
104 int gdtr=0;
105 int idtr=0;
106 int ldtr=0;
107 int tr=0;
108 
109 /* Control regs */
110 int     cr0=0;
111 int     cr1=0;
112 int     cr2=0;
113 int     cr3=0;
114 int     cr4=0;
115 int     cr5=0;
116 int     cr6=0;
117 int     cr7=0;
118 
119 /* Debug Regs */
120 int dr0=0;
121 int dr1=0;
122 int dr2=0;
123 int dr3=0;
124 int dr4=0;
125 int dr5=0;
126 int dr6=0;
127 int dr7=0;
128 
129 /* Program Variables */
130 long    *retptr[8][3];
131 #if (defined GO32) || (defined WIN32)
132 char    biosfile[255]="bios.ram";
133 #else
134 char    biosfile[255]="io/VGABIOS-elpin-2.20";
135 #endif
136 #if (USEFILE==1)
137 FILE    *memfd;
138 char    memfile[255]="io/vmi586.mem";
139 #else
140 unsigned char   memarray[RAMSIZE];
141 #endif
142 int stack[8192];
143 void    (*(regs[255]))();
144 unsigned long absaddr;
145 #ifdef CHECK_INSTRUCTIONS
146 char    INSTRUCTION[256]={1,0,0,0,1,1,1,0,0,0,0,
147     0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,
148     0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,
149     0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
150     0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,
151     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
152     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
153     0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
154     0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
155     0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,
156     1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
157     0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
158     0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,1,0,0,
159     0,1,0,0,0};
160 #endif
161 
162 
163 /*
164    Remember to pass the locations to ext, high, and low.
165    mesh==1 if setting ax,ah,al
166    mesh==0 if setting eax
167 */
168 void changevalext(unsigned long *ext, int *high, int *low, unsigned int nval, int mesh)
169 {
170   unsigned int tmpv=0;
171 #if (DEBUG>=1)
172   printf("changeval(%i, %i, %i, %i)\n called",(unsigned int) *ext,*high,*low,nval);
173 #endif
174   tmpv=nval;
175   tmpv-=((tmpv>>16)<<16);
176   *high=tmpv>>8;
177   tmpv-=(*high<<8);
178   *low=tmpv;
179   if (mesh==0) { *ext=nval; } else { *ext=((*ext>>16)<<16)+(*high<<8)+(*low); }
180   return;
181 }
182 
183 /*
184    Pass memlocs.
185 */
186 void changeval(int *high, int *low, int nv)
187 {
188   unsigned int tmpv=0;
189 #if (DEBUG>=1)
190   printf("changeval(%i, %i, %i)\n called",*high,*low,nv);
191 #endif
192   tmpv=nv;
193   *high=tmpv>>8;
194   tmpv-=(*high<<8);
195   *low=tmpv;
196   return;
197 }
198 
199 /*
200    Assemble high and low bytes into a word.
201 */
202 int getval(int high, int low)
203 {
204   return((high<<8)+(low));
205 }
206 
207 /*
208   A standard interface to memmory, very slow for now (1byte at a time).
209   Probably will be changed later, joy.
210 */
211 void writemembyte(unsigned long location, int value)
212 {
213 #if (DEBUG>=3)
214   printf("Writing %c(%i) to %i\n",value,value,(unsigned int) location); 
215 #endif
216 #if (USEFILE==1)
217   fseek(memfd,location,SEEK_SET);
218   fputc(value,memfd);
219 #else
220   memarray[location]=value;
221 #endif
222 }
223 
224 /*
225   Read memmory the standard way.
226 */
227 unsigned int readmembyte(unsigned long location)
228 {
229 #if (DEBUG>=3)
230   printf("Reading byte from %i, ",(unsigned int) location);
231 #endif
232 #if (USEFILE==1)
233   fseek(memfd,location,SEEK_SET);
234 #if (DEBUG>=3)
235   printf("(%i)\n",fgetc(memfd));
236   fseek(memfd,location,SEEK_SET);
237 #endif
238   return(fgetc(memfd));
239 #else
240 #if (DEBUG>=3)
241   printf("(%i)\n",memarray[location]);
242 #endif
243   return (memarray[location]);
244 #endif
245 }
246 
247 void doopcodereal(unsigned int bcs, unsigned long offset, long length)
248 {
249   unsigned int opcodeval=0;
250   cs=bcs;
251   for (ip=offset;ip<length;ip++)
252   {
253     absaddr=((cs<<16)+ip);
254     opcodeval=readmembyte(absaddr);
255 #ifdef CHECK_INSTRUCTIONS
256     if (INSTRUCTION[opcodeval]!=1) { 
257 #if (DEBUG>=1)
258       printf("Opcode not implemented (%i)\n",opcodeval); 
259 #endif
260     } else { 
261       (regs[opcodeval])(); 
262     }
263 #else
264     (regs[opcodeval])();
265 #endif
266   }
267 }
268 
269 /*
270     #de     0   divide error
271     #db     1   debug
272     #bp     3   breakpoint
273     #of     4   overflow
274     #br     5   BOUND overflow
275     #ud     6   undefined opcode
276     #nm     7   no math coprossor
277     #df     8   double fault
278     #ts     10  invlaid ts
279     #np     11  segment not present
280     #ss     12  stack segfault
281     #gp     13  general protection
282     #pf     14  page fault
283     #mf     16  math fault
284     #ac     17  alignment check
285     #mc     19  machine check
286 */
287 void callint(int intpt) {
288   int intloc;
289   intloc=readmembyte(intpt*4);
290 #if (DEBUG>=2)
291   printf("Interrupt %i called.  Running segment %i\n", intpt, intloc);
292 #endif
293   doopcodereal(intloc,0,65535);
294   return;
295 }
296 
297 
298 
299 void opcode00(void) { 
300   writemembyte((bx+si),al+readmembyte(bx+si)); ip+=1;
301 #if (DEBUG>=2) 
302   printf("00   add [%i],%i\n",(bx+si),al);
303 #endif
304 }
305 void opcode04(void) {
306   ip++;
307   al+=readmembyte(absaddr+1);
308   ax=(((ax>>8)<<8)+al);
309   eax=(((eax>>8)<<8)+al);
310 #if (DEBUG>=2)
311   printf("04   add\n");
312 #endif
313 }
314 void opcode05(void) {
315   if ((cr0 & 1)==0) { 
316     ip+=2;
317     ax+=((readmembyte(absaddr+2)<<8)+readmembyte(absaddr+1));
318     eax=((eax>>16)<<16)+ax;
319     ah=(ax>>8);
320     al=(ax-(ah<<8));
321 #if (DEBUG>=2)
322     printf("05   add\n");
323 #endif
324     return;
325   } else {
326     ip+=4;
327     eax+=(readmembyte(absaddr+4)<<24)+(readmembyte(absaddr+3)<<16)+(readmembyte(absaddr+2)<<8)+readmembyte(absaddr+1);
328     ax=((eax<<16)>>16);
329     ah=(ax>>8);
330     al=(ax-(ah<<8));
331 #if (DEBUG>=2)
332     printf("05   add\n");
333 #endif
334     return;
335   }  
336 }
337 void opcode06(void) {
338   stack[sp]=es>>8; stack[sp+1]=es-((es>>8)<<8); sp=sp+2;
339 #if (DEBUG>=2) 
340   printf("06   push es\n");
341 #endif
342 }
343 void opcode0f(void) {
344   int tmpA;
345   tmpA=(readmembyte(absaddr+1));
346   if (tmpA>=0xc8) {
347     ip+=4;
348     *retptr[tmpA][3]=((*retptr[tmpA][3])>>24)+((*retptr[tmpA][3] & 0xFF)<<24)+((*retptr[tmpA][3] &
	0x0000FF00)<<8)+((*retptr[tmpA][3] & 0x00FF0000)>>8);
349     *retptr[tmpA][2]=(*retptr[tmpA][3] & 0xFFFF);
350     if (tmpA>4) { 
351       *retptr[tmpA][0]=(*retptr[tmpA][2] & 0xFF);
352       *retptr[tmpA][1]=(*retptr[tmpA][2] & 0xFF00);
353     }
354 #if (DEBUG>=2)
355     printf("0FC8 bswap %i\n", tmpA+65);
356 #endif
357     return;
358   }
359   if (tmpA==0xa3) {
360 /*
361 Need to write BT sometime... 
362 */
363     return;
364   }
365   if (tmpA==0x06) {
366 #if (DEBUG>=2)
367     printf("0F06 CLTS\n");
368 #endif
369   }
370   if (tmpA==0xa2) {
371     if (eax==0) {
372       eax=1; ax=1; ah=0; al=1;
373       bl=0x47; bh=0x65; bx=0x6547; ebx=0x756e6547;
374       cl=0x6e; ch=0x74; cx=0x746e; ecx=0x6c65746e;
375       dl=0x69; dh=0x6e; dx=0x6e69; edx=0x49656e69;
376     }
377 #if (DEBUG>=2)
378     printf("0FA2 CPUId\n");
379 #endif
380   }
381 #if (DEBUG>=2)
382   printf("Unksupported form of 0x0F, %i\n",tmpA);
383 #endif
384 }
385 void opcode14(void) {
386   ip++;
387   al+=readmembyte(absaddr+1)+cf;
388   ax=(ah<<8)+(al);
389   eax=((eax>>16)<<16)+ax;
390 #if (DEBUG>=2)
391   printf("14   adc al,...\n");
392 #endif
393 }
394 void opcode15(void) {
395   if ((cr0 & 1)==0) { 
396     ip+=2;
397     ax+=((readmembyte(absaddr+2)<<8)+readmembyte(absaddr+1))+cf;
398     eax=((eax>>16)<<16)+ax;
399     ah=(ax>>8);
400     al=(ax-(ah<<8));
401 #if (DEBUG>=2)
402     printf("15   adc ax,...\n");
403 #endif
404     return;
405   } else {
406     ip+=4;
407    
	eax+=(readmembyte(absaddr+4)<<24)+(readmembyte(absaddr+3)<<16)+(readmembyte(absaddr+2)<<8)+readmembyte(absaddr+1)+cf;
408     ax=((eax<<16)>>16);
409     ah=(ax>>8);
410     al=(ax-(ah<<8));
411 #if (DEBUG>=2)
412     printf("15   adc eax,...\n");
413 #endif
414     return;
415   }
416 }
417 void opcode24(void) {
418   ip++;
419   al=(al & readmembyte(absaddr+1));
420 #if (DEBUG>=2)
421   printf("24   and al,...\n");
422 #endif
423 }
424 void opcode25(void) {
425   if ((cr0 & 1)==0) { 
426     ip+=2;
427     ax=(ax & ((readmembyte(absaddr+2)<<8)+readmembyte(absaddr+1)));
428     eax=((eax>>16)<<16)+ax;
429     ah=(ax>>8);
430     al=(ax-(ah<<8));
431 #if (DEBUG>=2)
432     printf("25   and ax,...\n");
433 #endif
434     return;
435   } else {
436     ip+=4;
437     eax=(eax &
	((readmembyte(absaddr+4)<<24)+(readmembyte(absaddr+3)<<16)+(readmembyte(absaddr+2)<<8)+readmembyte(absaddr+1)));
438     ax=((eax<<16)>>16);
439     ah=(ax>>8);
440     al=(ax-(ah<<8));
441 #if (DEBUG>=2)
442     printf("25   and eax,...\n");
443 #endif
444     return;
445   }  
446 }
447 void opcode27(void) {
448   if (((al & 0x0f)>9) || af==1) {
449     al+=6;
450     af=1;
451   } else {
452     af=0;
453   }
454   if (((al & 0xf0)>0x90) || cf==1) {
455     al+=0x60;
456     cf=1;
457   } else {
458     cf=0;
459   }
460 #if (DEBUG>=2)
461   printf("27   daa\n");
462 #endif
463 }
464 void opcode2f(void) {
465   if (((al & 0xf)>9) || af==1) {
466     al-=6;
467     af=1;
468   } else { af=0; }
469   if ((al>0x9f) || cf==1) {
470     al-=0x60;
471     cf=1;
472   } else { cf=0; }
473 
474 }
475 void opcode37(void)
476 {
477   if (((al & 0x0f) > 9) || (af==1)) {
478     al+=6;
479     ah+=1;
480     af=1; cf=1;
481   } else {
482     af=0; cf=0;
483   }
484   al=(al & 0x0f);
485 #if (DEBUG>=2)
486   printf("37   aaa\n");
487 #endif
488 }
489 void opcode3f(void) {
490   if (((al & 0x0f)>9) || (af==1)) {
491     al-=6;
492     ah-=1;
493     af=1;cf=1;
494   } else {
495     af=0;cf=0;
496   }
497   al=(al & 0x0f);
498 #if (DEBUG>=2)
499   printf("3F   aas\n");
500 #endif
501 }
502 void opcode50(void)
503 { 
504   stack[sp]=ah; stack[sp+1]=al; sp=sp+2; 
505 #if (DEBUG>=2) 
506   printf("50   push ax\n");
507 #endif
508 }   
509 void opcode8b(void)
510 {
511   cx=si;
512   ip++;
513 #if (DEBUG>=2) 
514   printf("8BCE mov cx,si\n");
515 #endif
516 }
517 void opcode98(void) {
518   if ((cr0 & 1)==0) {
519     if ((al>7)==1) { ah=255; } else { ah=0; }
520     ax=(ah<<8)+(al);
521     eax=((eax>>16)<<16)+ax;
522 #if (DEBUG>=2)
523     printf("98   CBW\n");
524 #endif
525     return;
526   } else {
527     if ((ax>>15)==1) { eax=((65535<<16)+ax); } else { eax=ax; }
528 #if (DEBUG>=2)
529     printf("98   CDWE\n");
530 #endif
531   }
532 }
533 void opcodeb8(void) 
534 {
535   ax=(readmembyte(absaddr+2)<<8)+(readmembyte(absaddr+1));
536   ah=ax>>8;
537   al=(ax-((ax>>8)<<8));
538   eax=((eax>>16)<<16)+ax;
539   ip+=2;
540 #if (DEBUG>=2)
541   printf("B8   mov ax,%i\n",ax);
542 #endif
543 }
544 void opcodebe(void)
545 {
546   si=(readmembyte(absaddr+2)<<8)+(readmembyte(absaddr+1));
547   esi=((esi>>16)<<16)+si;
548   ip+=2;
549 #if (DEBUG>=2) 
550   printf("BE   mov si,%i\n",si);
551 #endif
552 }
553 void opcodebf(void)
554 {
555   di=(readmembyte(absaddr+2)<<8)+(readmembyte(absaddr+1));
556   edi=((edi>>16)<<16)+di;
557   ip+=2;
558 #if (DEBUG>=2) 
559   printf("BF   mov di,%i\n",di);
560 #endif
561 }
562 void opcoded4(void) {
563   int tmpA,tmpB;
564   ip++;
565   tmpA=al; tmpB=readmembyte(absaddr+1);
566   if (tmpB==0) { callint(0); return; }  /* Divide overflow. */
567   ah=tmpA/tmpB;
568   al=tmpA % tmpB;
569 #if (DEBUG>=2)
570   printf("D4   aam\n");
571 #endif
572 }
573 void opcoded5(void) {
574   ip++;
575   ah=0;
576   al=((al+ah+readmembyte(absaddr+1)) & 0xff);
577   ax=getval(ah,al);
578   eax=((eax>>16)<<16)+ax;
579 #if (DEBUG>=2)
580   printf("D5   aad\n");
581 #endif
582 }
583 
584 void opcodee4(void) {
585   int tmpA;
586   tmpA=readmembyte(absaddr+1);
587   ip+=1;
588   
589 #if (DEBUG>=2)
590   printf("E4   in");
591 #endif
592 }
593 
594 void opcodef3(void)
595 {     
596 #if (DEBUG>=1)
597   printf("F3   repz --- NOT SUPPORTED\n");
598 #endif
599 }
600 void opcodef5(void) {
601   cf=(cf*-1)+1;
602 #if (DEBUG>=2)
603   printf("F5   cfc\n");
604 #endif
605 }
606 void opcodef7(void)
607 {
608   cx=(cx^0xffff)+1;
609   ip++;
610 #if (DEBUG>=2)
611   printf("F7D9 neg cx\n");
612 #endif
613 }
614 void opcodef8(void) {
615   cf=0;
616 #if (DEBUG>=2)
617   printf("F8   clc\n");
618 #endif
619 }
620 void opcodefc(void)
621 {
622   df=0;
623 #if (DEBUG>=1)
624   printf("FC   cld\n");
625 #endif
626 }
627 
628 
629 
630 void make_regs_and_ops(void) {
631   regs[0x00]=opcode00;
632   regs[0x04]=opcode04;
633   regs[0x05]=opcode05;
634   regs[0x06]=opcode06;
635   regs[0x0f]=opcode0f;
636   regs[0x14]=opcode14;
637   regs[0x15]=opcode15;
638   regs[0x24]=opcode24;
639   regs[0x25]=opcode25;
640   regs[0x27]=opcode27;
641   regs[0x2f]=opcode2f;
642   regs[0x37]=opcode37;
643   regs[0x3f]=opcode3f;
644   regs[0x50]=opcode50;
645   regs[0x8b]=opcode8b;
646   regs[0x98]=opcode98;
647   regs[0xb8]=opcodeb8;
648   regs[0xbe]=opcodebe;
649   regs[0xbf]=opcodebf;
650   regs[0xd4]=opcoded4;
651   regs[0xd5]=opcoded5;
652   regs[0xe4]=opcodee4;
653   regs[0xf3]=opcodef3;
654   regs[0xf5]=opcodef5;
655   regs[0xf7]=opcodef7;
656   regs[0xf8]=opcodef8;
657   regs[0xfc]=opcodefc;
658 
659 /* Setup pointers to registers in the standard way. */
660   retptr[0][0]=(long *) &al;
661   retptr[1][0]=(long *) &cl;
662   retptr[2][0]=(long *) &dl;
663   retptr[3][0]=(long *) &bl;
664   retptr[0][1]=(long *) &al;
665   retptr[1][1]=(long *) &cl;
666   retptr[2][1]=(long *) &dl;
667   retptr[3][1]=(long *) &bl;
668   retptr[0][2]=(long *) &ax;
669   retptr[1][2]=(long *) &cx;
670   retptr[2][2]=(long *) &dx;
671   retptr[3][2]=(long *) &bx;
672   retptr[4][2]=(long *) &sp;
673   retptr[5][2]=(long *) &bp;
674   retptr[6][2]=(long *) &si;
675   retptr[7][2]=(long *) &di;
676   retptr[0][3]=(long *) &eax;
677   retptr[1][3]=(long *) &ecx;
678   retptr[2][3]=(long *) &edx;
679   retptr[3][3]=(long *) &ebx;
680   retptr[4][3]=(long *) &esp;
681   retptr[5][3]=(long *) &ebp;
682   retptr[6][3]=(long *) &esi;
683   retptr[7][3]=(long *) &edi;
684 
685 }
686 
687 int main(void)
688 {
689   FILE *biosId;
690   int i;
691   printf("Creating virtual memmory using a");
692 #if (USEFILE==1)
693   memfd=fopen(memfile,"w+");
694   printf(" file");
695 #else
696   printf("n array");
697 #endif
698   printf(", %ikb\nLoading startup program %s\n",RAMSIZE/1024,biosfile);
699   make_regs_and_ops();
700   biosId=fopen(biosfile,"r");
701   for (i=0;i<32768;i++)
702   {
703     writemembyte(((1<<16)+i),fgetc(biosId));
704   }
705   doopcodereal(1,0,32768);
706   return(0);
707 }

main.c is the source.
5750794 [rkeene@sledge /home/rkeene/devel/old/vmi586]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 1999-08-01 00:38:19