emul/8086: add INT hooks

This commit is contained in:
Virgil Dupras 2020-10-24 21:50:44 -04:00
parent 939c018792
commit 942a50a86d
6 changed files with 116 additions and 78 deletions

2
emul/8086/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/forth
/forth.bin

View File

@ -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)

View File

@ -22,6 +22,7 @@
#include <stdint.h>
#include <stdio.h>
#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));
}

View File

@ -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();

3
emul/8086/foo.asm Normal file
View File

@ -0,0 +1,3 @@
mov al, 'X'
int 1
hlt

View File

@ -2,21 +2,40 @@
#include <stdio.h>
#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;
}