ack/plat/pc86/emu/main.c
David Given c6b9446722 Check in the x86emu-based emulator. Sadly, just like the 8086tiny-based
emulator, FPU instructions aren't supported.
2018-06-04 16:19:45 +09:00

145 lines
2.7 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "x86emu.h"
static uint8_t ram[1025*1024];
static int floppy_fd;
static X86EMU_intrFuncs intr_funcs[256];
void printk(const char* format, ...)
{
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
}
static void unknown_interrupt_cb(int num)
{
printk("unknown interrupt 0x%02x\n", num);
exit(1);
}
static void ignored_interrupt_cb(int num)
{
M.x86.R_AX = 0;
}
static void int10_cb(int num)
{
switch (M.x86.R_AH)
{
case 0x0e: /* print char al */
putchar(M.x86.R_AL);
fflush(stdout);
break;
default:
printk("unknown int10 service 0x%02x\n", M.x86.R_AH);
exit(1);
}
}
static void int13_cb(int num)
{
if (M.x86.R_DL != 0)
{
/* unknown disk */
M.x86.R_AX = 1;
return;
}
switch (M.x86.R_AH)
{
case 0x02: /* read sector */
{
/* On entry:
* al: number of sectors
* bx: address
* ch: track
* cl: sector
* dh: head number
* dl: disk
*/
uint8_t count = M.x86.R_AL;
uint32_t address = (M.x86.R_DS << 4) + M.x86.R_BX;
uint8_t sector = M.x86.R_CL;
uint8_t track = M.x86.R_CH;
uint8_t head = M.x86.R_DH;
uint32_t lba = track*18*2 + head*18 + (sector-1);
//printf("CHS %d.%d.%d -> lba 0x%x\n", track, head, sector, lba);
pread(floppy_fd, &ram[address], count*512, lba*512);
M.x86.R_AX = 0;
CLEAR_FLAG(F_CF);
}
case 0x08: /* probe disk al */
M.x86.R_AX = 0;
M.x86.R_CL = 18; /* maximum sector number */
M.x86.R_DH = 1; /* maximum head number */
/* there's other stuff we should set as well */
break;
default:
printk("unknown int13 service 0x%02x\n", M.x86.R_AH);
exit(1);
}
}
int main(int argc, const char* argv[])
{
if (argc != 2)
{
printk("syntax: pc86emu <fdimage.img>\n");
exit(1);
}
floppy_fd = open(argv[1], O_RDONLY);
if (floppy_fd == -1)
{
printk("could not open disk image: %s\n", strerror(errno));
exit(1);
}
/* Initialise the processor. */
M.mem_base = (uintptr_t) ram;
M.mem_size = sizeof(ram);
/* Load the boot sector at 0x07c0:0000. */
for (int i=0; i<512; i++)
{
uint8_t b;
read(floppy_fd, &b, 1);
wrb(0x7c00 + i, b);
}
/* Initialise. */
for (int i=0; i<256; i++)
intr_funcs[i] = unknown_interrupt_cb;
intr_funcs[0x10] = int10_cb;
intr_funcs[0x13] = int13_cb;
intr_funcs[0x14] = ignored_interrupt_cb; /* serial port stuff */
//M.x86.debug = DEBUG_TRACE_F|DEBUG_STEP_F|DEBUG_DECODE_F;
M.x86.debug = 0;
M.x86.R_CS = 0x07c0;
M.x86.R_IP = 0x0000;
M.x86.R_DL = 0; /* boot drive */
X86EMU_setupIntrFuncs(intr_funcs);
X86EMU_exec();
return 0;
}