From 942a50a86d5ed59bac921a1d3ff483ae15ee5ca0 Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Sat, 24 Oct 2020 21:50:44 -0400 Subject: [PATCH] emul/8086: add INT hooks --- emul/8086/.gitignore | 2 ++ emul/8086/Makefile | 12 ++++---- emul/8086/cpu.c | 80 +++++++++++++--------------------------------------- emul/8086/cpu.h | 56 +++++++++++++++++++++++++++++++++++- emul/8086/foo.asm | 3 ++ emul/8086/forth.c | 41 +++++++++++++++++++-------- 6 files changed, 116 insertions(+), 78 deletions(-) create mode 100644 emul/8086/.gitignore create mode 100644 emul/8086/foo.asm diff --git a/emul/8086/.gitignore b/emul/8086/.gitignore new file mode 100644 index 0000000..00dbdb8 --- /dev/null +++ b/emul/8086/.gitignore @@ -0,0 +1,2 @@ +/forth +/forth.bin diff --git a/emul/8086/Makefile b/emul/8086/Makefile index 40f6f5c..7768963 100644 --- a/emul/8086/Makefile +++ b/emul/8086/Makefile @@ -7,14 +7,16 @@ BLKFS = $(CDIR)/blkfs .PHONY: all all: $(TARGETS) -forth: forth.c $(OBJS) - $(CC) forth.c $(OBJS) -lncurses -o $@ +forth: forth.c forth.bin $(OBJS) + $(CC) -DFBIN_PATH=\"`pwd`/forth.bin\" forth.c $(OBJS) -lncurses -o $@ -emul.o: emul.c forth.bin $(BLKFS) +emul.o: emul.c $(BLKFS) $(CC) -DFBIN_PATH=\"`pwd`/forth.bin\" -DBLKFS_PATH=\"`pwd`/$(BLKFS)\" -c -o emul.o emul.c -forth.bin: xcomp.fs $(STAGE) $(BLKFS) - $(CDIR)/stage < xcomp.fs > $@ +forth.bin: foo.asm + nasm -o $@ foo.asm +#forth.bin: xcomp.fs $(STAGE) $(BLKFS) +# $(CDIR)/stage < xcomp.fs > $@ $(BLKFS): $(STAGE) diff --git a/emul/8086/cpu.c b/emul/8086/cpu.c index 77b2385..41d6543 100755 --- a/emul/8086/cpu.c +++ b/emul/8086/cpu.c @@ -22,6 +22,7 @@ #include #include +#include "cpu.h" // Defines below are from config.h //be sure to only define ONE of the CPU_* options at any given time, or @@ -49,58 +50,11 @@ #define CPU_SET_HIGH_FLAGS #endif -#define regax 0 -#define regcx 1 -#define regdx 2 -#define regbx 3 -#define regsp 4 -#define regbp 5 -#define regsi 6 -#define regdi 7 -#define reges 0 -#define regcs 1 -#define regss 2 -#define regds 3 - -#ifdef __BIG_ENDIAN__ -#define regal 1 -#define regah 0 -#define regcl 3 -#define regch 2 -#define regdl 5 -#define regdh 4 -#define regbl 7 -#define regbh 6 -#else -#define regal 0 -#define regah 1 -#define regcl 2 -#define regch 3 -#define regdl 4 -#define regdh 5 -#define regbl 6 -#define regbh 7 -#endif - -union _bytewordregs_ { - uint16_t wordregs[8]; - uint8_t byteregs[8]; -}; - #define StepIP(x) ip += x -#define getmem8(x, y) read86(segbase(x) + y) -#define getmem16(x, y) readw86(segbase(x) + y) -#define putmem8(x, y, z) write86(segbase(x) + y, z) -#define putmem16(x, y, z) writew86(segbase(x) + y, z) #define signext(value) (int16_t)(int8_t)(value) #define signext32(value) (int32_t)(int16_t)(value) -#define getreg16(regid) regs.wordregs[regid] -#define getreg8(regid) regs.byteregs[byteregtable[regid]] -#define putreg16(regid, writeval) regs.wordregs[regid] = writeval -#define putreg8(regid, writeval) regs.byteregs[byteregtable[regid]] = writeval #define getsegreg(regid) segregs[regid] #define putsegreg(regid, writeval) segregs[regid] = writeval -#define segbase(x) ((uint32_t) x << 4) #define makeflagsword() \ ( \ @@ -174,6 +128,7 @@ static const uint8_t parity[0x100] = { }; uint8_t RAM[0x100000]; +INTHOOK INTHOOKS[0x100] = {0}; uint8_t opcode, segoverride, reptype, hltstate = 0; uint16_t segregs[4], savecs, saveip, ip, useseg, oldsp; uint8_t tempcf, oldcf, cf, pf, af, zf, sf, tf, ifl, df, of, mode, reg, rm; @@ -186,29 +141,29 @@ union _bytewordregs_ regs; uint8_t portram[0x10000]; -void intcall86 (uint8_t intnum); +void intcall86(uint8_t intnum); static void portout (uint16_t portnum, uint8_t value) {} static void portout16 (uint16_t portnum, uint16_t value) {} static uint8_t portin (uint16_t portnum) { return 0; } static uint16_t portin16 (uint16_t portnum) { return 0; } -static void write86 (uint32_t addr32, uint8_t value) { +void write86 (uint32_t addr32, uint8_t value) { tempaddr32 = addr32 & 0xFFFFF; RAM[tempaddr32] = value; } -static void writew86 (uint32_t addr32, uint16_t value) { - write86 (addr32, (uint8_t) value); - write86 (addr32 + 1, (uint8_t) (value >> 8) ); +void writew86 (uint32_t addr32, uint16_t value) { + write86(addr32, (uint8_t) value); + write86(addr32 + 1, (uint8_t) (value >> 8) ); } -static uint8_t read86 (uint32_t addr32) { +uint8_t read86 (uint32_t addr32) { addr32 &= 0xFFFFF; return (RAM[addr32]); } -static uint16_t readw86 (uint32_t addr32) { +uint16_t readw86 (uint32_t addr32) { return ( (uint16_t) read86 (addr32) | (uint16_t) (read86 (addr32 + 1) << 8) ); } @@ -1242,9 +1197,17 @@ static void op_grp5() { } } -void intcall86 (uint8_t intnum) { +void intcall86(uint8_t intnum) { + if (intnum == 0) { + fprintf(stderr, "INT 0 called, halting\n"); + hltstate = 1; + return; + } + if (INTHOOKS[intnum] != NULL) { + INTHOOKS[intnum](); + return; + } fprintf(stderr, "Unknown INT called: %x\n", intnum); - hltstate = 1; /*push (makeflagsword() ); push (segregs[regcs]); push (ip); @@ -3437,8 +3400,3 @@ void reset86() { ip = 0; hltstate = 0; } - -void printregs() { - fprintf(stderr, "AL: %x\n", getreg8(regal)); -} - diff --git a/emul/8086/cpu.h b/emul/8086/cpu.h index 0b9b5dd..dc10759 100755 --- a/emul/8086/cpu.h +++ b/emul/8086/cpu.h @@ -1,3 +1,57 @@ +#pragma once +#define regax 0 +#define regcx 1 +#define regdx 2 +#define regbx 3 +#define regsp 4 +#define regbp 5 +#define regsi 6 +#define regdi 7 +#define reges 0 +#define regcs 1 +#define regss 2 +#define regds 3 + +#ifdef __BIG_ENDIAN__ +#define regal 1 +#define regah 0 +#define regcl 3 +#define regch 2 +#define regdl 5 +#define regdh 4 +#define regbl 7 +#define regbh 6 +#else +#define regal 0 +#define regah 1 +#define regcl 2 +#define regch 3 +#define regdl 4 +#define regdh 5 +#define regbl 6 +#define regbh 7 +#endif + +#define segbase(x) ((uint32_t) x << 4) +#define getmem8(x, y) read86(segbase(x) + y) +#define getmem16(x, y) readw86(segbase(x) + y) +#define putmem8(x, y, z) write86(segbase(x) + y, z) +#define putmem16(x, y, z) writew86(segbase(x) + y, z) +#define getreg16(regid) regs.wordregs[regid] +#define getreg8(regid) regs.byteregs[byteregtable[regid]] +#define putreg16(regid, writeval) regs.wordregs[regid] = writeval +#define putreg8(regid, writeval) regs.byteregs[byteregtable[regid]] = writeval + +typedef void (*INTHOOK) (); +union _bytewordregs_ { + uint16_t wordregs[8]; + uint8_t byteregs[8]; +}; + + +void write86 (uint32_t addr32, uint8_t value); +void writew86 (uint32_t addr32, uint16_t value); +uint8_t read86 (uint32_t addr32); +uint16_t readw86 (uint32_t addr32); void exec86(int execloops); void reset86(); -void printregs(); diff --git a/emul/8086/foo.asm b/emul/8086/foo.asm new file mode 100644 index 0000000..8d672c4 --- /dev/null +++ b/emul/8086/foo.asm @@ -0,0 +1,3 @@ +mov al, 'X' +int 1 +hlt diff --git a/emul/8086/forth.c b/emul/8086/forth.c index 4e121a9..10a9536 100644 --- a/emul/8086/forth.c +++ b/emul/8086/forth.c @@ -2,21 +2,40 @@ #include #include "cpu.h" -extern uint8_t RAM[0x100000]; +#ifndef FBIN_PATH +#error FBIN_PATH needed +#endif + +extern uint8_t byteregtable[8]; +extern union _bytewordregs_ regs; +extern INTHOOK INTHOOKS[0x100]; + +/* we have a fake INT API: +INT 1: EMIT. AL = char to spit +INT 2: KEY. AL = char read +*/ + +void int1() { + putchar(getreg8(regal)); +} int main(int argc, char *argv[]) { - int i = 0; - int ch = 0; - + INTHOOKS[1] = int1; reset86(); - ch = getchar(); - while (ch != EOF) { - RAM[i++] = ch; - ch = getchar(); + // initialize memory + FILE *bfp = fopen(FBIN_PATH, "r"); + if (!bfp) { + fprintf(stderr, "Can't open forth.bin\n"); + return 1; } - printregs(); - exec86(1); - printregs(); + int i = 0; + int c = getc(bfp); + while (c != EOF) { + write86(i++, c); + c = getc(bfp); + } + fclose(bfp); + exec86(100); return 0; }