]>
git.ipfire.org Git - u-boot.git/blob - board/MAI/bios_emulator/scitech/src/v86bios/v86.c
2 * Copyright 1999 Egbert Eich
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the authors not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. The authors makes no representations
11 * about the suitability of this software for any purpose. It is provided
12 * "as is" without express or implied warranty.
14 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
27 #include <asm/unistd.h>
33 #include "AsmMacros.h"
35 struct vm86_struct vm86s
;
37 static int vm86_GP_fault(void);
38 static int vm86_do_int(int num
);
39 static void dump_code(void);
40 static void dump_registers(void);
41 static void stack_trace(void);
42 static int vm86_rep(struct vm86_struct
*ptr
);
44 #define CPU_REG(x) (vm86s.regs.##x)
45 #define CPU_REG_LW(reg) (*((CARD16 *)&CPU_REG(reg)))
46 #define CPU_REG_HW(reg) (*((CARD16 *)&CPU_REG(reg) + 1))
47 #define CPU_REG_LB(reg) (*(CARD8 *)&CPU_REG(e##reg))
48 #define SEG_ADR(type, seg, reg) type((CPU_REG_LW(seg) << 4) \
58 if (!Config
.PrintPort
&& !Config
.IoStatistics
) {
59 P
.inb
= (CARD8(*)(CARD16
))inb
;
60 P
.inw
= (CARD16(*)(CARD16
))inw
;
61 P
.inl
= (CARD32(*)(CARD16
))inl
;
62 P
.outb
= (void(*)(CARD16
,CARD8
))outb
;
63 P
.outw
= (void(*)(CARD16
,CARD16
))outw
;
64 P
.outl
= (void(*)(CARD16
,CARD32
))outl
;
77 setup_vm86(unsigned long bios_start
, i86biosRegsPtr regs
)
82 vm86s
.flags
= VM86_SCREEN_BITMAP
;
84 vm86s
.screen_bitmap
= 0;
85 vm86s
.cpu_type
= CPU_586
;
86 memset(&vm86s
.int_revectored
, 0xff,sizeof(vm86s
.int_revectored
)) ;
87 memset(&vm86s
.int21_revectored
, 0xff,sizeof(vm86s
.int21_revectored
)) ;
89 eip
= bios_start
& 0xFFFF;
90 cs
= (bios_start
& 0xFF0000) >> 4;
92 CPU_REG(eax
) = regs
->ax
;
93 CPU_REG(ebx
) = regs
->bx
;
94 CPU_REG(ecx
) = regs
->cx
;
95 CPU_REG(edx
) = regs
->dx
;
97 CPU_REG(edi
) = regs
->di
;
101 CPU_REG(esp
) = 0x100;
102 CPU_REG(ss
) = 0x30; /* This is the standard pc bios stack */
103 CPU_REG(es
) = regs
->es
;
104 CPU_REG(ds
) = 0x40; /* standard pc ds */
107 CPU_REG(eflags
) |= (VIF_MASK
| VIP_MASK
);
111 collect_bios_regs(i86biosRegsPtr regs
)
113 regs
->ax
= CPU_REG(eax
);
114 regs
->bx
= CPU_REG(ebx
);
115 regs
->cx
= CPU_REG(ecx
);
116 regs
->dx
= CPU_REG(edx
);
117 regs
->es
= CPU_REG(es
);
118 regs
->ds
= CPU_REG(ds
);
119 regs
->di
= CPU_REG(edi
);
120 regs
->si
= CPU_REG(esi
);
131 /* retval = SYS_vm86old(&vm86s); */
132 /* retval = syscall(SYS_vm86old,&vm86s); */
134 retval
= vm86_rep(&vm86s
);
136 switch (VM86_TYPE(retval
)) {
138 if (!vm86_GP_fault()) return 0;
141 fprintf(stderr
,"vm86_sti :-((\n");
146 if (!vm86_do_int(VM86_ARG(retval
))) {
147 fprintf(stderr
,"\nUnknown vm86_int: %X\n\n",VM86_ARG(retval
));
151 /* I'm not sure yet what to do if we can handle ints */
154 fprintf(stderr
,"received signal\n");
157 fprintf(stderr
,"unknown type(0x%x)=0x%x\n",
158 VM86_ARG(retval
),VM86_TYPE(retval
));
168 static jmp_buf x86_esc
;
176 do_x86(unsigned long bios_start
, i86biosRegsPtr regs
)
178 static void (*org_handler
)(int);
180 setup_vm86(bios_start
, regs
);
181 if (setjmp(x86_esc
) == 0) {
182 org_handler
= signal(2,vmexit
);
184 signal(2,org_handler
);
185 collect_bios_regs(regs
);
187 signal(2,org_handler
);
188 printf("interrupted at 0x%x\n",((CARD16
)CPU_REG(cs
)) << 4
189 | (CARD16
)CPU_REG(eip
));
193 /* get the linear address */
194 #define LIN_PREF_SI ((pref_seg << 4) + CPU_REG_LW(esi))
196 #define LWECX (prefix66 ^ prefix67 ? CPU_REG(ecx) : CPU_REG_LW(ecx))
201 unsigned char *csp
, *lina
;
204 int done
,is_rep
,prefix66
,prefix67
;
207 csp
= lina
= SEG_ADR((unsigned char *), cs
, ip
);
209 printf("exception: \n");
214 prefix66
= prefix67
= 0;
217 /* eat up prefixes */
221 case 0x66: /* operand prefix */ prefix66
=1; break;
222 case 0x67: /* address prefix */ prefix67
=1; break;
223 case 0x2e: /* CS */ pref_seg
=CPU_REG(cs
); break;
224 case 0x3e: /* DS */ pref_seg
=CPU_REG(ds
); break;
225 case 0x26: /* ES */ pref_seg
=CPU_REG(es
); break;
226 case 0x36: /* SS */ pref_seg
=CPU_REG(ss
); break;
227 case 0x65: /* GS */ pref_seg
=CPU_REG(gs
); break;
228 case 0x64: /* FS */ pref_seg
=CPU_REG(fs
); break;
229 case 0xf2: /* repnz */
230 case 0xf3: /* rep */ is_rep
=1; break;
234 csp
--; /* oops one too many */
235 org_eip
= CPU_REG(eip
);
236 CPU_REG_LW(eip
) += (csp
- lina
);
240 case 0x6c: /* insb */
241 /* NOTE: ES can't be overwritten; prefixes 66,67 should use esi,edi,ecx
242 * but is anyone using extended regs in real mode? */
243 /* WARNING: no test for DI wrapping! */
244 CPU_REG_LW(edi
) += port_rep_inb(CPU_REG_LW(edx
),
245 SEG_ADR((CARD8
*),es
,di
),
246 CPU_REG_LW(eflags
)&DF
,
248 if (is_rep
) LWECX
= 0;
252 case 0x6d: /* (rep) insw / insd */
253 /* NOTE: ES can't be overwritten */
254 /* WARNING: no test for _DI wrapping! */
256 CPU_REG_LW(edi
) += port_rep_inl(CPU_REG_LW(edx
),
257 SEG_ADR((CARD32
*),es
,di
),
258 CPU_REG_LW(eflags
)&DF
,
262 CPU_REG_LW(edi
) += port_rep_inw(CPU_REG_LW(edx
),
263 SEG_ADR((CARD16
*),es
,di
),
264 CPU_REG_LW(eflags
)&DF
,
267 if (is_rep
) LWECX
= 0;
271 case 0x6e: /* (rep) outsb */
272 if (pref_seg
< 0) pref_seg
= CPU_REG_LW(ds
);
273 /* WARNING: no test for _SI wrapping! */
274 CPU_REG_LW(esi
) += port_rep_outb(CPU_REG_LW(edx
),(CARD8
*)LIN_PREF_SI
,
275 CPU_REG_LW(eflags
)&DF
,
277 if (is_rep
) LWECX
= 0;
281 case 0x6f: /* (rep) outsw / outsd */
282 if (pref_seg
< 0) pref_seg
= CPU_REG_LW(ds
);
283 /* WARNING: no test for _SI wrapping! */
285 CPU_REG_LW(esi
) += port_rep_outl(CPU_REG_LW(edx
),
286 (CARD32
*)LIN_PREF_SI
,
287 CPU_REG_LW(eflags
)&DF
,
291 CPU_REG_LW(esi
) += port_rep_outw(CPU_REG_LW(edx
),
292 (CARD16
*)LIN_PREF_SI
,
293 CPU_REG_LW(eflags
)&DF
,
296 if (is_rep
) LWECX
= 0;
300 case 0xe5: /* inw xx, inl xx */
301 if (prefix66
) CPU_REG(eax
) = P
.inl((int) csp
[1]);
302 else CPU_REG_LW(eax
) = P
.inw((int) csp
[1]);
303 CPU_REG_LW(eip
) += 2;
305 case 0xe4: /* inb xx */
306 CPU_REG_LW(eax
) &= ~(CARD32
)0xff;
307 CPU_REG_LB(ax
) |= P
.inb((int) csp
[1]);
308 CPU_REG_LW(eip
) += 2;
310 case 0xed: /* inw dx, inl dx */
311 if (prefix66
) CPU_REG(eax
) = P
.inl(CPU_REG_LW(edx
));
312 else CPU_REG_LW(eax
) = P
.inw(CPU_REG_LW(edx
));
313 CPU_REG_LW(eip
) += 1;
315 case 0xec: /* inb dx */
316 CPU_REG_LW(eax
) &= ~(CARD32
)0xff;
317 CPU_REG_LB(ax
) |= P
.inb(CPU_REG_LW(edx
));
318 CPU_REG_LW(eip
) += 1;
321 case 0xe7: /* outw xx */
322 if (prefix66
) P
.outl((int)csp
[1], CPU_REG(eax
));
323 else P
.outw((int)csp
[1], CPU_REG_LW(eax
));
324 CPU_REG_LW(eip
) += 2;
326 case 0xe6: /* outb xx */
327 P
.outb((int) csp
[1], CPU_REG_LB(ax
));
328 CPU_REG_LW(eip
) += 2;
330 case 0xef: /* outw dx */
331 if (prefix66
) P
.outl(CPU_REG_LW(edx
), CPU_REG(eax
));
332 else P
.outw(CPU_REG_LW(edx
), CPU_REG_LW(eax
));
333 CPU_REG_LW(eip
) += 1;
335 case 0xee: /* outb dx */
336 P
.outb(CPU_REG_LW(edx
), CPU_REG_LB(ax
));
337 CPU_REG_LW(eip
) += 1;
342 printf("hlt at %p\n", lina
);
347 fprintf(stderr
,"CPU 0x0f Trap at eip=0x%lx\n",CPU_REG(eip
));
351 case 0xf0: /* lock */
353 fprintf(stderr
,"unknown reason for exception\n");
358 fprintf(stderr
,"cannot continue\n");
360 } /* end of switch() */
370 i_printf("int 0x%x received: ax:0x%lx",num
,CPU_REG(eax
));
372 i_printf(" at: 0x%x\n",getIP());
376 /* try to run bios interrupt */
378 /* if not installed fall back */
379 #define COPY(x) regs.##x = CPU_REG(x)
380 #define COPY_R(x) CPU_REG(x) = regs.##x
399 if (!(val
= int_handler(num
,®s
)))
400 if (!(val
= run_bios_int(num
,®s
)))
429 unsigned char *lina
= SEG_ADR((unsigned char *), cs
, ip
);
431 fprintf(stderr
,"code at 0x%8.8x: ",(CARD32
)lina
);
432 for (i
=0; i
<0x10; i
++)
433 fprintf(stderr
,"%2.2x ",*(lina
+ i
));
434 fprintf(stderr
,"\n ");
436 fprintf(stderr
,"%2.2x ",*(lina
+ i
));
437 fprintf(stderr
,"\n");
440 #define PRINT(x) fprintf(stderr,#x":%4.4x ",CPU_REG_LW(x))
441 #define PRINT_FLAGS(x) fprintf(stderr,#x":%8.8x ",CPU_REG_LW(x))
453 fprintf(stderr
,"\n");
462 fprintf(stderr
,"\n");
469 unsigned char *stack
= SEG_ADR((unsigned char *), ss
, sp
);
471 fprintf(stderr
,"stack at 0x%8.8lx:\n",(unsigned long)stack
);
472 for (i
=0; i
< 0x10; i
++)
473 fprintf(stderr
,"%2.2x ",*(stack
+ i
));
474 fprintf(stderr
,"\n");
479 vm86_rep(struct vm86_struct
*ptr
)
484 __asm__
__volatile__("int $0x80\n"
485 :"=a" (__res
):"a" ((int)113),
486 "b" ((struct vm86_struct
*)ptr
));
496 #define pushw(base, ptr, val) \
497 __asm__ __volatile__( \
499 "movb %h2,(%1,%0)\n\t" \
503 : "r" (base), "q" (val), "0" (ptr))
506 run_bios_int(int num
, struct regs86
*regs
)
513 static int firsttime
= 1;
515 /* check if bios vector is initialized */
516 if (((CARD16
*)0)[(num
<<1)+1] == 0x0000) { /* SYS_BIOS_SEG ?*/
518 i_printf("card BIOS not loaded\n");
530 i_printf("calling card BIOS at: ");
531 ssp
= (CARD16
*)(CPU_REG(ss
)<<4);
532 sp
= (CARD32
) CPU_REG_LW(esp
);
534 eflags
= regs
->eflags
;
535 eflags
= ((eflags
& VIF_MASK
) != 0)
536 ? (eflags
| IF_MASK
) : (eflags
& ~(CARD32
) IF_MASK
);
537 pushw(ssp
, sp
, eflags
);
538 pushw(ssp
, sp
, regs
->cs
);
539 pushw(ssp
, sp
, (CARD16
)regs
->eip
);
541 regs
->cs
= ((CARD16
*) 0)[(num
<< 1) + 1];
542 regs
->eip
= (regs
->eip
& 0xFFFF0000) | ((CARD16
*) 0)[num
<< 1];
543 i_printf("0x%x:%lx\n",regs
->cs
,regs
->eip
);
547 regs
->eflags
= regs
->eflags
548 & ~(VIF_MASK
| TF_MASK
| IF_MASK
| NT_MASK
);
555 return ((CARD32
*)0)[num
];
561 return (CPU_REG(cs
) << 4) + CPU_REG(eip
);