diff --git a/bios/main.s b/bios/main.s new file mode 100644 index 0000000..eae3f92 --- /dev/null +++ b/bios/main.s @@ -0,0 +1,18 @@ +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .bss +STACKSIZE = 512 +.comm stack, STACKSIZE + +.sect .text +_start: + sei ! disable interrupt + + ! setup stack + ldy.l #stack + STACKSIZE + txs + + diff --git a/configure.ac b/configure.ac index 7afb2c2..392daac 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,18 @@ AC_INIT([65oo2], [1.0]) +AC_CANONICAL_HOST + AM_INIT_AUTOMAKE([foreign subdir-objects]) -AC_CANONICAL_HOST +AC_CONFIG_HEADERS([config.h]) + +case "$host_os" in + cygwin*|mingw*) + OS_TYPE=windows;; + *) + OS_TYPE=unknown;; +esac +AM_CONDITIONAL([OS_WINDOWS], test "$OS_TYPE" = "windows") AC_LANG(C) AC_PROG_CC @@ -12,10 +22,41 @@ AC_PROG_RANLIB AM_PROG_AS AM_PROG_AR AM_PROG_CC_C_O +PKG_PROG_PKG_CONFIG +AC_CHECK_TOOLS(WINDRES, [windres], :) + +AC_ARG_ENABLE([ata-vga], + [AS_HELP_STRING([--enable-ata-vga], [enable VGA (default=yes)])], + [WANT_ATA_VGA=$enableval], [WANT_ATA_VGA=yes]) +AC_ARG_ENABLE([ata-ethernet], + [AS_HELP_STRING([--enable-ata-ethernet], [enable ethernet device (default=yes)])], + [WANT_ATA_ETHERNET=$enableval], [WANT_ATA_ETHERNET=yes]) + +AC_ARG_ENABLE(mmu, + [AS_HELP_STRING([--enable-mmu], [enable MMU (default=yes)])], + [WANT_MMU=$enableval], [WANT_MMU=yes]) +AC_ARG_ENABLE(jit, + [AS_HELP_STRING([--enable-jit], [enable JIT compiler (default=no)])], + [WANT_JIT=$enableval], [WANT_JIT=no]) AC_CHECK_INCLUDES_DEFAULT AC_C_CONST +AM_CONDITIONAL([USE_ATA_VGA], test "$WANT_ATA_VGA" = "yes") +if test "$WANT_ATA_VGA" = "yes"; then + AC_DEFINE([ATA_VGA], [1], [Enable VGA device]) + PKG_CHECK_MODULES([SDL2], [sdl2]) + +fi + +AM_CONDITIONAL([USE_ATA_ETHERNET], test "$WANT_ATA_ETHERNET" = "yes") +if test "$WANT_ATA_ETHERNET" = "yes"; then + AC_DEFINE([ATA_ETERNET], [1], [Enable Ethernet device]) +fi + +AM_CONDITIONAL([USE_MMU], test "$WANT_MMU" = "yes") +AM_CONDITIONAL([USE_JIT], test "$WANT_JIT" = "yes") + AC_CONFIG_FILES([ Makefile lib/Makefile diff --git a/disas/Makefile.am b/disas/Makefile.am index 854cd05..ef68a59 100644 --- a/disas/Makefile.am +++ b/disas/Makefile.am @@ -1,5 +1,7 @@ +include res/Makefrag.am + bin_PROGRAMS = disas disas_SOURCES = main.c disas_CFLAGS =-I$(top_srcdir) -disas_LDADD = ../lib/lib65oo2.a \ No newline at end of file +disas_LDADD = ../lib/lib65oo2.a $(RES) \ No newline at end of file diff --git a/disas/main.c b/disas/main.c index 4b41cf7..89314e3 100644 --- a/disas/main.c +++ b/disas/main.c @@ -90,35 +90,67 @@ fatal(const char *str, ...) exit(EXIT_FAILURE); } +void +decode_target_suffix(uint8_t attr) +{ + fprintf(output, "."); + if (IS_TARGET_ZEXT(attr)) + { + fprintf(output, "U"); + } + + switch (GET_TARGET_SIZE(attr)) + { + case SIZE_BYTE: + fprintf(output, "B"); + break; + case SIZE_WORD: + fprintf(output, "W"); + break; + case SIZE_LONG: + fprintf(output, "L"); + break; + } +} + +void +decode_address(uint8_t attr) +{ + switch (GET_ADDRESS_SIZE(attr)) + { + case SIZE_BYTE: + fprintf(output, " %%%X", readu8()); + break; + case SIZE_WORD: + fprintf(output, " %%%hX", readu16()); + break; + case SIZE_LONG: + fprintf(output, " %%%X", readu32()); + break; + default: + break; + } +} + void decode_imm(uint8_t opcode) { uint8_t attr; attr = readu8(); - if ((attr & 0x3) == 0x3) - { - fprintf(output, "???\n"); - return; - } - fprintf(output, "%s.", opcode_str[opcode]); - - if (attr & 0x4) + fprintf(output, "%s", opcode_str[opcode]); + decode_target_suffix(attr); + switch (GET_TARGET_SIZE(attr)) { - fprintf(output, "U"); - } - - switch (attr & 0x3) - { - case 0x0: - fprintf(output, "B #$%X\n", readu8()); + case SIZE_BYTE: + fprintf(output, " #$%X\n", readu8()); break; - case 0x1: - fprintf(output, "W #$%hX\n", readu16()); + case SIZE_WORD: + fprintf(output, " #$%hX\n", readu16()); break; - case 0x2: - fprintf(output, "L #$%X\n", readu32()); + case SIZE_LONG: + fprintf(output, " #$%X\n", readu32()); break; default: break; @@ -130,8 +162,32 @@ decode_ind(uint8_t opcode) { uint8_t attr; + fprintf(output, "%s", opcode_str[opcode]); attr = readu8(); - (void)attr; + if (opcode != OP_JMP_ind) + { + decode_target_suffix(attr); + } + if (opcode_addr[opcode] & (OP_ADDR_X | OP_ADDR_Y)) + { + fprintf(output, " ("); + } + else + { + fprintf(output, " "); + } + + decode_address(attr); + + if (opcode_addr[opcode] & OP_ADDR_X) + { + fprintf(output, ", X)"); + } + else if (opcode_addr[opcode] & OP_ADDR_Y) + { + fprintf(output, "), Y"); + } + fprintf(output, "\n"); } void @@ -139,8 +195,24 @@ decode_abs(uint8_t opcode) { uint8_t attr; + fprintf(output, "%s", opcode_str[opcode]); attr = readu8(); - (void)attr; + if (opcode != OP_JSR_abs + || opcode != OP_JMP_abs) + { + decode_target_suffix(attr); + } + decode_address(attr); + + if (opcode_addr[opcode] & OP_ADDR_X) + { + fprintf(output, ", X"); + } + else if (opcode_addr[opcode] & OP_ADDR_Y) + { + fprintf(output, ", Y"); + } + fprintf(output, "\n"); } void diff --git a/disas/res/Makefrag.am b/disas/res/Makefrag.am new file mode 100644 index 0000000..56c68fe --- /dev/null +++ b/disas/res/Makefrag.am @@ -0,0 +1,8 @@ +if OS_WINDOWS +RES = windows.$(OBJEXT) +else +RES = +endif + +windows.$(OBJEXT): res/windows.rc + $(WINDRES) $< $@ diff --git a/disas/res/disas.ico b/disas/res/disas.ico new file mode 100644 index 0000000..3d5d5ed Binary files /dev/null and b/disas/res/disas.ico differ diff --git a/disas/res/disas.png b/disas/res/disas.png new file mode 100644 index 0000000..9454e1a Binary files /dev/null and b/disas/res/disas.png differ diff --git a/disas/res/windows.rc b/disas/res/windows.rc new file mode 100644 index 0000000..d23b204 --- /dev/null +++ b/disas/res/windows.rc @@ -0,0 +1 @@ +1 ICON "disas.ico" diff --git a/lib/op.h b/lib/op.h index 48f52b3..33fee5f 100644 --- a/lib/op.h +++ b/lib/op.h @@ -39,6 +39,30 @@ # define OP_BMI_rel 0x30 # define OP_AND_ind_y 0x31 +# define OP_JMP_abs 0x4C +# define OP_JMP_ind 0x6C + +/* + * size encoding + */ +# define SIZE_BYTE 0x0 +# define SIZE_WORD 0x1 +# define SIZE_LONG 0x2 + +# define TARGET_ZEXT (1 << 2) +# define TARGET_SIZE_BYTE SIZE_BYTE +# define TARGET_SIZE_WORD SIZE_WORD +# define TARGET_SIZE_LONG SIZE_LONG + +# define ADDRESS_SIZE_BYTE (SIZE_BYTE << 3) +# define ADDRESS_SIZE_WORD (SIZE_WORD << 3) +# define ADDRESS_SIZE_LONG (SIZE_LONG << 3) + +# define GET_TARGET_SIZE(x) ((x) & 0x03) +# define GET_ADDRESS_SIZE(x) (((x) >> 3) & 0x03) +# define IS_TARGET_ZEXT(x) ((x) & TARGET_ZEXT) + + extern const uint8_t opcode_addr[]; extern const char *opcode_str[]; diff --git a/vm/Makefile.am b/vm/Makefile.am index 4568631..cb2a849 100644 --- a/vm/Makefile.am +++ b/vm/Makefile.am @@ -1,5 +1,11 @@ +include jit/Makefrag.am +include ata/Makefrag.am +include res/Makefrag.am + +noinst_LIBRARIES = $(LIBJIT) $(LIB_ATA) + bin_PROGRAMS = vm -vm_SOURCES = main.c jit.c x64/x64.S +vm_SOURCES = main.c vm_CFLAGS =-I$(top_srcdir) -vm_LDADD = ../lib/lib65oo2.a +vm_LDADD = ../lib/lib65oo2.a $(LIBJIT) $(LIB_ATA) $(RES) diff --git a/vm/ata/Makefrag.am b/vm/ata/Makefrag.am new file mode 100644 index 0000000..b4f3817 --- /dev/null +++ b/vm/ata/Makefrag.am @@ -0,0 +1,7 @@ +LIB_ATA = libata.a + +libata_a_SOURCES = ata/ata.c ata/rtc.c + +if USE_ATA_VGA +libata_a_SOURCES += ata/vga.c +endif diff --git a/vm/ata/ata.c b/vm/ata/ata.c new file mode 100644 index 0000000..a0a9b1a --- /dev/null +++ b/vm/ata/ata.c @@ -0,0 +1,27 @@ +#include "ata.h" +#include "config.h" + +extern AtaDevice rtc_dev; +#ifdef ATA_ETHERNET +extern AtaDevice ethernet_dev; +#endif /* ATA_ETHERNET */ +#ifdef ATA_VGA +extern AtaDevice vga_dev; +#endif /* ATA_VGA */ + + +AtaDevice *devices[] = { + &rtc_dev, +#ifdef ATA_ETHERNET + ðernet_dev, +#endif /* ATA_ETHERNET */ +#ifdef ATA_VGA + &vga_dev, +#endif /* ATA_VGA */ + NULL +}; + +void +ata_bus_initialize(void) +{ +} diff --git a/vm/ata/ata.h b/vm/ata/ata.h new file mode 100644 index 0000000..4858c94 --- /dev/null +++ b/vm/ata/ata.h @@ -0,0 +1,19 @@ +#ifndef VM_ATA_ATA_H +# define VM_ATA_ATA_H 1 + +# include + +typedef void (*IoWrite)(uint8_t offset, uint8_t data); +typedef uint8_t (*IoRead)(uint8_t offset); + +typedef struct +{ + char const *name; + uint16_t start; + uint16_t end; + void *state; + IoWrite io_write; + IoRead io_read; +} AtaDevice; + +#endif /* VM_ATA_ATA_H */ diff --git a/vm/ata/ethernet.c b/vm/ata/ethernet.c new file mode 100644 index 0000000..233a1bd --- /dev/null +++ b/vm/ata/ethernet.c @@ -0,0 +1,14 @@ +#include "isa.h" + +static const uint8_t mac_addr[6] = { + 0x53, 0x54, 0x41, 0x4C, 0x49, 0x4E +}; + +AtaDevice ethernet_dev = { + "TinyEthernet", + 0x360, + 0x36F, + NULL, + NULL, + NULL +}; diff --git a/vm/ata/rtc.c b/vm/ata/rtc.c new file mode 100644 index 0000000..c88747c --- /dev/null +++ b/vm/ata/rtc.c @@ -0,0 +1,45 @@ +#include +#include "ata.h" + +#define REG_SECS 0x00 +#define REG_MINS 0x00 +#define REG_HOURS 0x00 +#define REG_WKDAY 0x06 +#define REG_DAY 0x07 +#define REG_YEAR 0x09 +#define REG_CENTURY 0x032 +#define REG_STATUSA 0x0A +#define REG_STATUSB 0x0B + +static uint8_t current_reg = 0x00; + +void +rtc_write(uint8_t addr, uint8_t value) +{ + if (addr == 0) + { + current_reg = value; + } +} + +uint8_t +rtc_read(uint8_t addr) +{ + time_t time; + struct tm tm; + + localtime(&time); + + (void)time; + (void)tm; + + return (0x00); +} + +AtaDevice rtc_dev = { + "RTC", + 0x070, + 0x071, + NULL, + NULL +}; diff --git a/vm/ata/serial.c b/vm/ata/serial.c new file mode 100644 index 0000000..3bfee6c --- /dev/null +++ b/vm/ata/serial.c @@ -0,0 +1,25 @@ +#include "ata.h" + +AtaDevice com3_dev = { + "COM3", + 0x3E0, + 0x3EF, + NULL, + NULL +}; + +AtaDevice com2_dev = { + "COM2", + 0x2F8, + 0x2FF, + NULL, + NULL, +}; + +AtaDevice com1_dev = { + "COM1", + 0x3F8, + 0x3FF, + NULL, + NULL, +}; diff --git a/vm/ata/vga.c b/vm/ata/vga.c new file mode 100644 index 0000000..258d1af --- /dev/null +++ b/vm/ata/vga.c @@ -0,0 +1,22 @@ +#include "ata.h" + +enum VGA_REG { + REG_CRTC_ADDR, + REG_CRTC_DATA, + REG_INPUT_STATUS1, + REG_FEAT_CTRL, + REG_ATTR_ADDR, + REG_ATTR_DATA, +}; + +enum VGA_CRTC { + XXX +}; + +AtaDevice vga_dev = { + "TinyVGA", + 0x3C0, + 0x3CF, + NULL, + NULL, +}; diff --git a/vm/bus.c b/vm/bus.c new file mode 100644 index 0000000..ce1a0d5 --- /dev/null +++ b/vm/bus.c @@ -0,0 +1,19 @@ +void +bus_initialize(void) +{ +} + +void +bus_read(void) +{ +} + +void +bus_write(void) +{ +} + +void +bus_reset(void) +{ +} diff --git a/vm/jit/Makefrag.am b/vm/jit/Makefrag.am new file mode 100644 index 0000000..98c4d97 --- /dev/null +++ b/vm/jit/Makefrag.am @@ -0,0 +1,7 @@ +if USE_JIT +LIBJIT = libjit.a +else +LIBJIT = +endif + +libjit_a_SOURCES = jit/jit.c jit/x64/x64.S diff --git a/vm/jit.c b/vm/jit/jit.c similarity index 100% rename from vm/jit.c rename to vm/jit/jit.c diff --git a/vm/jit.h b/vm/jit/jit.h similarity index 100% rename from vm/jit.h rename to vm/jit/jit.h diff --git a/vm/x64/register.h b/vm/jit/x64/register.h similarity index 100% rename from vm/x64/register.h rename to vm/jit/x64/register.h diff --git a/vm/x64/x64.S b/vm/jit/x64/x64.S similarity index 100% rename from vm/x64/x64.S rename to vm/jit/x64/x64.S diff --git a/vm/main.c b/vm/main.c index abcb908..26a92f3 100644 --- a/vm/main.c +++ b/vm/main.c @@ -1,8 +1,18 @@ #include #include +static const char *prg_name; + +void +usage(void) +{ + printf("Usage: %s [-hV] [-b bios]\n"); +} + int main(int argc, char **argv) { + prg_name = argv[0]; + return (EXIT_SUCCESS); } diff --git a/vm/res/Makefrag.am b/vm/res/Makefrag.am new file mode 100644 index 0000000..56c68fe --- /dev/null +++ b/vm/res/Makefrag.am @@ -0,0 +1,8 @@ +if OS_WINDOWS +RES = windows.$(OBJEXT) +else +RES = +endif + +windows.$(OBJEXT): res/windows.rc + $(WINDRES) $< $@ diff --git a/vm/res/vm.ico b/vm/res/vm.ico new file mode 100644 index 0000000..ee39312 Binary files /dev/null and b/vm/res/vm.ico differ diff --git a/vm/res/vm.png b/vm/res/vm.png new file mode 100644 index 0000000..a94c78c Binary files /dev/null and b/vm/res/vm.png differ diff --git a/vm/res/windows.rc b/vm/res/windows.rc new file mode 100644 index 0000000..e3f43de --- /dev/null +++ b/vm/res/windows.rc @@ -0,0 +1 @@ +1 ICON "vm.ico"