Basic cli handling
This commit is contained in:
parent
d53f1cbfe0
commit
262a211da9
11
configure.ac
11
configure.ac
|
@ -1,4 +1,7 @@
|
||||||
AC_INIT([65oo2], [1.0])
|
AC_INIT([65∞2], [1.0],
|
||||||
|
[https://git.cute.engineering/d0p1/65oo2/issues],
|
||||||
|
[65oo2],
|
||||||
|
[https://git.cute.engineering/d0p1/65oo2])
|
||||||
|
|
||||||
AC_CANONICAL_HOST
|
AC_CANONICAL_HOST
|
||||||
|
|
||||||
|
@ -25,6 +28,9 @@ AM_PROG_CC_C_O
|
||||||
PKG_PROG_PKG_CONFIG
|
PKG_PROG_PKG_CONFIG
|
||||||
AC_CHECK_TOOLS(WINDRES, [windres], :)
|
AC_CHECK_TOOLS(WINDRES, [windres], :)
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES([SDL2], [sdl2])
|
||||||
|
SDL2_LIBS=${SDL2_LIBS/-mwindows/}
|
||||||
|
|
||||||
AC_ARG_ENABLE([ata-vga],
|
AC_ARG_ENABLE([ata-vga],
|
||||||
[AS_HELP_STRING([--enable-ata-vga], [enable VGA (default=yes)])],
|
[AS_HELP_STRING([--enable-ata-vga], [enable VGA (default=yes)])],
|
||||||
[WANT_ATA_VGA=$enableval], [WANT_ATA_VGA=yes])
|
[WANT_ATA_VGA=$enableval], [WANT_ATA_VGA=yes])
|
||||||
|
@ -40,13 +46,12 @@ AC_ARG_ENABLE(jit,
|
||||||
[WANT_JIT=$enableval], [WANT_JIT=no])
|
[WANT_JIT=$enableval], [WANT_JIT=no])
|
||||||
|
|
||||||
AC_CHECK_INCLUDES_DEFAULT
|
AC_CHECK_INCLUDES_DEFAULT
|
||||||
|
AC_CHECK_HEADERS([libgen.h])
|
||||||
AC_C_CONST
|
AC_C_CONST
|
||||||
|
|
||||||
AM_CONDITIONAL([USE_ATA_VGA], test "$WANT_ATA_VGA" = "yes")
|
AM_CONDITIONAL([USE_ATA_VGA], test "$WANT_ATA_VGA" = "yes")
|
||||||
if test "$WANT_ATA_VGA" = "yes"; then
|
if test "$WANT_ATA_VGA" = "yes"; then
|
||||||
AC_DEFINE([ATA_VGA], [1], [Enable VGA device])
|
AC_DEFINE([ATA_VGA], [1], [Enable VGA device])
|
||||||
PKG_CHECK_MODULES([SDL2], [sdl2])
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AM_CONDITIONAL([USE_ATA_ETHERNET], test "$WANT_ATA_ETHERNET" = "yes")
|
AM_CONDITIONAL([USE_ATA_ETHERNET], test "$WANT_ATA_ETHERNET" = "yes")
|
||||||
|
|
407
disas/main.c
407
disas/main.c
|
@ -1,11 +1,15 @@
|
||||||
|
#include "config.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#ifdef HAVE_LIBGEN_H
|
||||||
|
# include <libgen.h>
|
||||||
|
#endif /* HAVE_LIBGEN_H */
|
||||||
#include "lib/op.h"
|
#include "lib/op.h"
|
||||||
|
|
||||||
#define OP_ADDR_MODE (OP_ADDR_IMPL | OP_ADDR_REL | OP_ADDR_IND \
|
#define OP_ADDR_MODE (OP_ADDR_IMPL | OP_ADDR_REL | OP_ADDR_IND \
|
||||||
| OP_ADDR_IMM | OP_ADDR_ABS)
|
| OP_ADDR_IMM | OP_ADDR_ABS)
|
||||||
|
|
||||||
char *prg_name;
|
char *prg_name;
|
||||||
FILE *input;
|
FILE *input;
|
||||||
|
@ -14,261 +18,318 @@ FILE *output;
|
||||||
uint8_t
|
uint8_t
|
||||||
readu8(void)
|
readu8(void)
|
||||||
{
|
{
|
||||||
uint8_t val;
|
uint8_t val;
|
||||||
|
|
||||||
if (fread(&val, 1, 1, input) != 1)
|
if (fread(&val, 1, 1, input) != 1)
|
||||||
{
|
{
|
||||||
return (-1); /* XXX: TODO */
|
return (-1); /* XXX: TODO */
|
||||||
}
|
}
|
||||||
|
|
||||||
return (val);
|
return (val);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t
|
uint16_t
|
||||||
readu16(void)
|
readu16(void)
|
||||||
{
|
{
|
||||||
uint16_t val;
|
uint16_t val;
|
||||||
|
|
||||||
if (fread(&val, 1, 2, input) != 2)
|
if (fread(&val, 1, 2, input) != 2)
|
||||||
{
|
{
|
||||||
return (-1); /* XXX: TODO */
|
return (-1); /* XXX: TODO */
|
||||||
}
|
}
|
||||||
|
|
||||||
return (val);
|
return (val);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
readu32(void)
|
readu32(void)
|
||||||
{
|
{
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
|
|
||||||
if (fread(&val, 1, 4, input) != 4)
|
if (fread(&val, 1, 4, input) != 4)
|
||||||
{
|
{
|
||||||
return (-1); /* XXX: TODO */
|
return (-1); /* XXX: TODO */
|
||||||
}
|
}
|
||||||
|
|
||||||
return (val);
|
return (val);
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t
|
int16_t
|
||||||
read16(void)
|
read16(void)
|
||||||
{
|
{
|
||||||
int16_t val;
|
int16_t val;
|
||||||
|
|
||||||
if (fread(&val, 1, 2, input) != 2)
|
if (fread(&val, 1, 2, input) != 2)
|
||||||
{
|
{
|
||||||
return (-1); /* XXX: TODO */
|
return (-1); /* XXX: TODO */
|
||||||
}
|
}
|
||||||
|
|
||||||
return (val);
|
return (val);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
read32(void)
|
read32(void)
|
||||||
{
|
{
|
||||||
int32_t val;
|
int32_t val;
|
||||||
|
|
||||||
if (fread(&val, 1, 4, input) != 4)
|
if (fread(&val, 1, 4, input) != 4)
|
||||||
{
|
{
|
||||||
return (-1); /* XXX: TODO */
|
return (-1); /* XXX: TODO */
|
||||||
}
|
}
|
||||||
|
|
||||||
return (val);
|
return (val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fatal(const char *str, ...)
|
fatal(const char *str, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
fprintf(stderr, "%s: ", prg_name);
|
fprintf(stderr, "%s: ", prg_name);
|
||||||
va_start(ap, str);
|
va_start(ap, str);
|
||||||
vfprintf(stderr, str, ap);
|
vfprintf(stderr, str, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
decode_target_suffix(uint8_t attr)
|
decode_target_suffix(uint8_t attr)
|
||||||
{
|
{
|
||||||
fprintf(output, ".");
|
fprintf(output, ".");
|
||||||
if (IS_TARGET_ZEXT(attr))
|
if (IS_TARGET_ZEXT(attr))
|
||||||
{
|
{
|
||||||
fprintf(output, "U");
|
fprintf(output, "U");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (GET_TARGET_SIZE(attr))
|
switch (GET_TARGET_SIZE(attr))
|
||||||
{
|
{
|
||||||
case SIZE_BYTE:
|
case SIZE_BYTE:
|
||||||
fprintf(output, "B");
|
fprintf(output, "B");
|
||||||
break;
|
break;
|
||||||
case SIZE_WORD:
|
case SIZE_WORD:
|
||||||
fprintf(output, "W");
|
fprintf(output, "W");
|
||||||
break;
|
break;
|
||||||
case SIZE_LONG:
|
case SIZE_LONG:
|
||||||
fprintf(output, "L");
|
fprintf(output, "L");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
decode_address(uint8_t attr)
|
decode_address(uint8_t attr)
|
||||||
{
|
{
|
||||||
switch (GET_ADDRESS_SIZE(attr))
|
switch (GET_ADDRESS_SIZE(attr))
|
||||||
{
|
{
|
||||||
case SIZE_BYTE:
|
case SIZE_BYTE:
|
||||||
fprintf(output, " %%%X", readu8());
|
fprintf(output, " %%%X", readu8());
|
||||||
break;
|
break;
|
||||||
case SIZE_WORD:
|
case SIZE_WORD:
|
||||||
fprintf(output, " %%%hX", readu16());
|
fprintf(output, " %%%hX", readu16());
|
||||||
break;
|
break;
|
||||||
case SIZE_LONG:
|
case SIZE_LONG:
|
||||||
fprintf(output, " %%%X", readu32());
|
fprintf(output, " %%%X", readu32());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
decode_imm(uint8_t opcode)
|
decode_imm(uint8_t opcode)
|
||||||
{
|
{
|
||||||
uint8_t attr;
|
uint8_t attr;
|
||||||
|
|
||||||
attr = readu8();
|
attr = readu8();
|
||||||
|
|
||||||
fprintf(output, "%s", opcode_str[opcode]);
|
fprintf(output, "%s", opcode_str[opcode]);
|
||||||
decode_target_suffix(attr);
|
decode_target_suffix(attr);
|
||||||
switch (GET_TARGET_SIZE(attr))
|
switch (GET_TARGET_SIZE(attr))
|
||||||
{
|
{
|
||||||
case SIZE_BYTE:
|
case SIZE_BYTE:
|
||||||
fprintf(output, " #$%X\n", readu8());
|
fprintf(output, " #$%X\n", readu8());
|
||||||
break;
|
break;
|
||||||
case SIZE_WORD:
|
case SIZE_WORD:
|
||||||
fprintf(output, " #$%hX\n", readu16());
|
fprintf(output, " #$%hX\n", readu16());
|
||||||
break;
|
break;
|
||||||
case SIZE_LONG:
|
case SIZE_LONG:
|
||||||
fprintf(output, " #$%X\n", readu32());
|
fprintf(output, " #$%X\n", readu32());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
decode_ind(uint8_t opcode)
|
decode_ind(uint8_t opcode)
|
||||||
{
|
{
|
||||||
uint8_t attr;
|
uint8_t attr;
|
||||||
|
|
||||||
fprintf(output, "%s", opcode_str[opcode]);
|
fprintf(output, "%s", opcode_str[opcode]);
|
||||||
attr = readu8();
|
attr = readu8();
|
||||||
if (opcode != OP_JMP_ind)
|
if (opcode != OP_JMP_ind)
|
||||||
{
|
{
|
||||||
decode_target_suffix(attr);
|
decode_target_suffix(attr);
|
||||||
}
|
}
|
||||||
if (opcode_addr[opcode] & (OP_ADDR_X | OP_ADDR_Y))
|
if (opcode_addr[opcode] & (OP_ADDR_X | OP_ADDR_Y))
|
||||||
{
|
{
|
||||||
fprintf(output, " (");
|
fprintf(output, " (");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(output, " ");
|
fprintf(output, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
decode_address(attr);
|
decode_address(attr);
|
||||||
|
|
||||||
if (opcode_addr[opcode] & OP_ADDR_X)
|
if (opcode_addr[opcode] & OP_ADDR_X)
|
||||||
{
|
{
|
||||||
fprintf(output, ", X)");
|
fprintf(output, ", X)");
|
||||||
}
|
}
|
||||||
else if (opcode_addr[opcode] & OP_ADDR_Y)
|
else if (opcode_addr[opcode] & OP_ADDR_Y)
|
||||||
{
|
{
|
||||||
fprintf(output, "), Y");
|
fprintf(output, "), Y");
|
||||||
}
|
}
|
||||||
fprintf(output, "\n");
|
fprintf(output, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
decode_abs(uint8_t opcode)
|
decode_abs(uint8_t opcode)
|
||||||
{
|
{
|
||||||
uint8_t attr;
|
uint8_t attr;
|
||||||
|
|
||||||
fprintf(output, "%s", opcode_str[opcode]);
|
fprintf(output, "%s", opcode_str[opcode]);
|
||||||
attr = readu8();
|
attr = readu8();
|
||||||
if (opcode != OP_JSR_abs
|
if (opcode != OP_JSR_abs
|
||||||
|| opcode != OP_JMP_abs)
|
|| opcode != OP_JMP_abs)
|
||||||
{
|
{
|
||||||
decode_target_suffix(attr);
|
decode_target_suffix(attr);
|
||||||
}
|
}
|
||||||
decode_address(attr);
|
decode_address(attr);
|
||||||
|
|
||||||
if (opcode_addr[opcode] & OP_ADDR_X)
|
if (opcode_addr[opcode] & OP_ADDR_X)
|
||||||
{
|
{
|
||||||
fprintf(output, ", X");
|
fprintf(output, ", X");
|
||||||
}
|
}
|
||||||
else if (opcode_addr[opcode] & OP_ADDR_Y)
|
else if (opcode_addr[opcode] & OP_ADDR_Y)
|
||||||
{
|
{
|
||||||
fprintf(output, ", Y");
|
fprintf(output, ", Y");
|
||||||
}
|
}
|
||||||
fprintf(output, "\n");
|
fprintf(output, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
decode(void)
|
decode(void)
|
||||||
{
|
{
|
||||||
uint8_t opcode;
|
uint8_t opcode;
|
||||||
int16_t relative;
|
int16_t relative;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
opcode = readu8();
|
opcode = readu8();
|
||||||
if (feof(input)) return;
|
if (feof(input)) return;
|
||||||
switch (opcode_addr[opcode] & OP_ADDR_MODE)
|
switch (opcode_addr[opcode] & OP_ADDR_MODE)
|
||||||
{
|
{
|
||||||
case OP_ADDR_IMPL:
|
case OP_ADDR_IMPL:
|
||||||
fprintf(output, "%s\n", opcode_str[opcode]);
|
if (opcode_addr[opcode] & OP_ADDR_A)
|
||||||
break;
|
{
|
||||||
case OP_ADDR_REL:
|
fprintf(output, "%s A\n", opcode_str[opcode]);
|
||||||
relative = read16();
|
}
|
||||||
fprintf(output, "%s $%hX\n", opcode_str[opcode], relative);
|
else
|
||||||
break;
|
{
|
||||||
case OP_ADDR_IMM:
|
fprintf(output, "%s\n", opcode_str[opcode]);
|
||||||
decode_imm(opcode);
|
}
|
||||||
break;
|
break;
|
||||||
case OP_ADDR_IND:
|
case OP_ADDR_REL:
|
||||||
decode_ind(opcode);
|
relative = read16();
|
||||||
break;
|
fprintf(output, "%s $%hX\n", opcode_str[opcode], relative);
|
||||||
case OP_ADDR_ABS:
|
break;
|
||||||
decode_abs(opcode);
|
case OP_ADDR_IMM:
|
||||||
break;
|
decode_imm(opcode);
|
||||||
default:
|
break;
|
||||||
fprintf(output, "???\n", opcode);
|
case OP_ADDR_IND:
|
||||||
break;
|
decode_ind(opcode);
|
||||||
}
|
break;
|
||||||
} while (!feof(input));
|
case OP_ADDR_ABS:
|
||||||
|
decode_abs(opcode);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(output, "???\n", opcode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (!feof(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
usage(int retcode)
|
||||||
|
{
|
||||||
|
if (retcode == EXIT_FAILURE)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Try '%s -h' for more information.\n", prg_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Usage: %s [-hV] [INPUT] [OUTPUT]\n", prg_name);
|
||||||
|
printf("Disassemble INPUT to OUTPUT\n\n");
|
||||||
|
printf("With no INPUT read standard input.\n");
|
||||||
|
printf("With no OUTPUT write standard output.\n\n");
|
||||||
|
printf("\t-h\tdisplay this help and exit\n");
|
||||||
|
printf("\t-V\toutput version information\n");
|
||||||
|
printf("\nReport bugs to <%s>\n", PACKAGE_BUGREPORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(retcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
version(void)
|
||||||
|
{
|
||||||
|
printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
prg_name = argv[0];
|
#ifdef HAVE_LIBGEN_H
|
||||||
input = stdin;
|
prg_name = basename(argv[0]);
|
||||||
output = stdout;
|
#else
|
||||||
|
prg_name = argv[0];
|
||||||
|
#endif /* HAVE_LIBGEN_H */
|
||||||
|
input = stdin;
|
||||||
|
output = stdout;
|
||||||
|
|
||||||
if (argc > 2)
|
while ((argc > 1) && (argv[1][0] == '-'))
|
||||||
{
|
{
|
||||||
output = fopen(argv[2], "w");
|
switch (argv[1][1])
|
||||||
if (output == NULL) fatal("can't open %s.", argv[2]);
|
{
|
||||||
}
|
case 'h':
|
||||||
|
usage(EXIT_SUCCESS);
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
version();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(EXIT_FAILURE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (argc > 1)
|
argv++;
|
||||||
{
|
argc--;
|
||||||
input = fopen(argv[1], "rb");
|
}
|
||||||
if (input == NULL) fatal("can't open %s.", argv[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
decode();
|
if (argc > 2)
|
||||||
|
{
|
||||||
|
output = fopen(argv[2], "w");
|
||||||
|
if (output == NULL) fatal("can't open %s.", argv[2]);
|
||||||
|
}
|
||||||
|
if (argc > 1)
|
||||||
|
{
|
||||||
|
input = fopen(argv[1], "rb");
|
||||||
|
if (input == NULL) fatal("can't open %s.", argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
return (EXIT_SUCCESS);
|
decode();
|
||||||
|
return (EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
42
lib/op.c
42
lib/op.c
|
@ -12,7 +12,7 @@ const uint8_t opcode_addr[OP_MAX] = {
|
||||||
/* */ 0xFF,
|
/* */ 0xFF,
|
||||||
/* PHP */ OP_ADDR_IMPL,
|
/* PHP */ OP_ADDR_IMPL,
|
||||||
/* ORA */ OP_ADDR_IMM,
|
/* ORA */ OP_ADDR_IMM,
|
||||||
/* ASL */ OP_ADDR_IMPL,
|
/* ASL */ OP_ADDR_IMPL | OP_ADDR_A,
|
||||||
/* */ 0xFF,
|
/* */ 0xFF,
|
||||||
/* */ 0xFF,
|
/* */ 0xFF,
|
||||||
/* ORA */ OP_ADDR_ABS,
|
/* ORA */ OP_ADDR_ABS,
|
||||||
|
@ -48,7 +48,7 @@ const uint8_t opcode_addr[OP_MAX] = {
|
||||||
/* */ 0xFF,
|
/* */ 0xFF,
|
||||||
/* PLP */ OP_ADDR_IMPL,
|
/* PLP */ OP_ADDR_IMPL,
|
||||||
/* AND */ OP_ADDR_IMM,
|
/* AND */ OP_ADDR_IMM,
|
||||||
/* ROL */ OP_ADDR_IMPL,
|
/* ROL */ OP_ADDR_IMPL | OP_ADDR_A,
|
||||||
/* */ 0xFF,
|
/* */ 0xFF,
|
||||||
/* BIT */ OP_ADDR_ABS,
|
/* BIT */ OP_ADDR_ABS,
|
||||||
/* AND */ OP_ADDR_ABS,
|
/* AND */ OP_ADDR_ABS,
|
||||||
|
@ -84,7 +84,7 @@ const uint8_t opcode_addr[OP_MAX] = {
|
||||||
/* */ 0xFF,
|
/* */ 0xFF,
|
||||||
/* PHA */ OP_ADDR_IMPL,
|
/* PHA */ OP_ADDR_IMPL,
|
||||||
/* EOR */ OP_ADDR_IMM,
|
/* EOR */ OP_ADDR_IMM,
|
||||||
/* LSR */ OP_ADDR_IMPL,
|
/* LSR */ OP_ADDR_IMPL | OP_ADDR_A,
|
||||||
/* */ 0xFF,
|
/* */ 0xFF,
|
||||||
/* JMP */ OP_ADDR_ABS,
|
/* JMP */ OP_ADDR_ABS,
|
||||||
/* EOR */ OP_ADDR_ABS,
|
/* EOR */ OP_ADDR_ABS,
|
||||||
|
@ -112,7 +112,7 @@ const uint8_t opcode_addr[OP_MAX] = {
|
||||||
/* 6- */
|
/* 6- */
|
||||||
/* RTS */ OP_ADDR_IMPL,
|
/* RTS */ OP_ADDR_IMPL,
|
||||||
/* ADC */ OP_ADDR_IND | OP_ADDR_X,
|
/* ADC */ OP_ADDR_IND | OP_ADDR_X,
|
||||||
/* */ 0xFF,
|
/* PER */ OP_ADDR_IMPL,
|
||||||
/* */ 0xFF,
|
/* */ 0xFF,
|
||||||
/* */ 0xFF,
|
/* */ 0xFF,
|
||||||
/* ADC */ 0xFF,
|
/* ADC */ 0xFF,
|
||||||
|
@ -120,7 +120,7 @@ const uint8_t opcode_addr[OP_MAX] = {
|
||||||
/* */ 0xFF,
|
/* */ 0xFF,
|
||||||
/* PLA */ OP_ADDR_IMPL,
|
/* PLA */ OP_ADDR_IMPL,
|
||||||
/* ADC */ OP_ADDR_IMM,
|
/* ADC */ OP_ADDR_IMM,
|
||||||
/* ROR */ OP_ADDR_IMPL,
|
/* ROR */ OP_ADDR_IMPL | OP_ADDR_A,
|
||||||
/* */ 0xFF,
|
/* */ 0xFF,
|
||||||
/* JMP */ OP_ADDR_IND,
|
/* JMP */ OP_ADDR_IND,
|
||||||
/* ADC */ OP_ADDR_ABS,
|
/* ADC */ OP_ADDR_ABS,
|
||||||
|
@ -291,20 +291,20 @@ const uint8_t opcode_addr[OP_MAX] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *opcode_str[OP_MAX] = {
|
const char *opcode_str[OP_MAX] = {
|
||||||
"BRK", "ORA", NULL, NULL, NULL, "ORA", "ASL", NULL, "PHP", "ORA", "ASLA", NULL, NULL, "ORA", "ASL", NULL,
|
"BRK", "ORA", NULL, NULL, NULL, "ORA", "ASL", NULL, "PHP", "ORA", "ASL", NULL, NULL, "ORA", "ASL", NULL,
|
||||||
"BPL", "ORA", NULL, NULL, NULL, "ORA", "ASL", NULL, "CLC", "ORA", NULL, NULL, NULL, "ORA", "ASL", NULL,
|
"BPL", "ORA", NULL, NULL, NULL, "ORA", "ASL", NULL, "CLC", "ORA", NULL, NULL, NULL, "ORA", "ASL", NULL,
|
||||||
"JSR", "AND", NULL, NULL, "BIT", "AND", "ROL", NULL, "PLP", "AND", "ROLA", NULL, "BIT", "AND", "ROL", NULL,
|
"JSR", "AND", NULL, NULL, "BIT", "AND", "ROL", NULL, "PLP", "AND", "ROL", NULL, "BIT", "AND", "ROL", NULL,
|
||||||
"BMI", "AND", NULL, NULL, NULL, "AND", "ROL", NULL, "SEC", "AND", NULL, NULL, NULL, "AND", "ROL", NULL,
|
"BMI", "AND", NULL, NULL, NULL, "AND", "ROL", NULL, "SEC", "AND", NULL, NULL, NULL, "AND", "ROL", NULL,
|
||||||
"RTI", "EOR", NULL, NULL, NULL, "EOR", "LSR", NULL, "PHA", "EOR", "LSRA", NULL, "JMP", "EOR", "LSR", NULL,
|
"RTI", "EOR", NULL, NULL, NULL, "EOR", "LSR", NULL, "PHA", "EOR", "LSR", NULL, "JMP", "EOR", "LSR", NULL,
|
||||||
"BVC", "EOR", NULL, NULL, NULL, "EOR", "LSR", NULL, "CLI", "EOR", NULL, NULL, NULL, "EOR", "LSR", NULL,
|
"BVC", "EOR", NULL, NULL, NULL, "EOR", "LSR", NULL, "CLI", "EOR", NULL, NULL, NULL, "EOR", "LSR", NULL,
|
||||||
"RTS", "ADC", NULL, NULL, NULL, "ADC", "ROR", NULL, "PLA", "ADC", "RORA", NULL, "JMP", "ADC", "ROR", NULL,
|
"RTS", "ADC", "PER", NULL, NULL, "ADC", "ROR", NULL, "PLA", "ADC", "ROR", NULL, "JMP", "ADC", "ROR", NULL,
|
||||||
"BVS", "ADC", NULL, NULL, NULL, "ADC", "ROR", NULL, "SEI", "ADC", NULL, NULL, NULL, "ADC", "ROR", NULL,
|
"BVS", "ADC", NULL, NULL, NULL, "ADC", "ROR", NULL, "SEI", "ADC", NULL, NULL, NULL, "ADC", "ROR", NULL,
|
||||||
NULL, "STA", NULL, NULL, "STY", "STA", "STX", NULL, "DEY", NULL, "TXA", NULL, "STY", "STA", "STX", NULL,
|
NULL, "STA", NULL, NULL, "STY", "STA", "STX", NULL, "DEY", NULL, "TXA", NULL, "STY", "STA", "STX", NULL,
|
||||||
"BCC", "STA", NULL, NULL, "STY", "STA", "STX", NULL, "TYA", "STA", "TXS", NULL, NULL, "STA", NULL, NULL,
|
"BCC", "STA", NULL, NULL, "STY", "STA", "STX", NULL, "TYA", "STA", "TXS", NULL, NULL, "STA", NULL, NULL,
|
||||||
"LDY", "LDA", "LDX", NULL, "LDY", "LDA", "LDX", NULL, "TAY", "LDA", "TAX", NULL, "LDY", "LDA", "LDX", NULL,
|
"LDY", "LDA", "LDX", NULL, "LDY", "LDA", "LDX", NULL, "TAY", "LDA", "TAX", NULL, "LDY", "LDA", "LDX", NULL,
|
||||||
"BCS", "LDA", NULL, NULL, "LDY", "LDA", "LDX", NULL, "CLV", "LDA", "TSX", NULL, "LDY", "LDA", "LDX", NULL,
|
"BCS", "LDA", NULL, NULL, "LDY", "LDA", "LDX", NULL, "CLV", "LDA", "TSX", NULL, "LDY", "LDA", "LDX", NULL,
|
||||||
"CPY", "CMP", NULL, NULL, "CPY", "CMP", "DEC", NULL, "INY", "CMP", "DEX", NULL, "CPY", "CMP", "DEC", NULL,
|
"CPY", "CMP", NULL, NULL, "CPY", "CMP", "DEC", NULL, "INY", "CMP", "DEX", NULL, "CPY", "CMP", "DEC", NULL,
|
||||||
"BNE", "CMP", NULL, NULL, NULL, "CMP", "DEC", NULL, "CLD", "CMP", NULL, NULL, NULL, "CMP", "DEC", NULL,
|
"BNE", "CMP", NULL, NULL, NULL, "CMP", "DEC", NULL, "CLD", "CMP", NULL, NULL, NULL, "CMP", "DEC", NULL,
|
||||||
"CPX", "SBC", NULL, NULL, "CPX", "SBC", "INC", NULL, "INX", "SBC", "NOP", NULL, "CPX", "SBC", "INC", NULL,
|
"CPX", "SBC", NULL, NULL, "CPX", "SBC", "INC", NULL, "INX", "SBC", "NOP", NULL, "CPX", "SBC", "INC", NULL,
|
||||||
"BEQ", "SBC", NULL, NULL, NULL, "SBC", "INC", NULL, "SED", "SBC", NULL, NULL, NULL, "SBC", "INC", NULL
|
"BEQ", "SBC", NULL, NULL, NULL, "SBC", "INC", NULL, "SED", "SBC", NULL, NULL, NULL, "SBC", "INC", NULL
|
||||||
};
|
};
|
||||||
|
|
1
lib/op.h
1
lib/op.h
|
@ -12,6 +12,7 @@
|
||||||
# define OP_ADDR_ABS 1 << 3
|
# define OP_ADDR_ABS 1 << 3
|
||||||
# define OP_ADDR_X 1 << 4
|
# define OP_ADDR_X 1 << 4
|
||||||
# define OP_ADDR_Y 1 << 5
|
# define OP_ADDR_Y 1 << 5
|
||||||
|
# define OP_ADDR_A 1 << 6
|
||||||
|
|
||||||
# define OP_BRK_impl 0x00
|
# define OP_BRK_impl 0x00
|
||||||
# define OP_ORA_x_ind 0x01
|
# define OP_ORA_x_ind 0x01
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
include jit/Makefrag.am
|
include jit/Makefrag.am
|
||||||
include ata/Makefrag.am
|
include ata/Makefrag.am
|
||||||
include res/Makefrag.am
|
include res/Makefrag.am
|
||||||
|
|
||||||
noinst_LIBRARIES = $(LIBJIT) $(LIB_ATA)
|
noinst_LIBRARIES = $(LIBJIT) $(LIB_ATA)
|
||||||
|
|
||||||
bin_PROGRAMS = vm
|
bin_PROGRAMS = vm
|
||||||
|
|
||||||
vm_SOURCES = main.c
|
vm_SOURCES = main.c
|
||||||
vm_CFLAGS =-I$(top_srcdir)
|
vm_CFLAGS =-I$(top_srcdir) $(SDL2_CFLAGS)
|
||||||
vm_LDADD = ../lib/lib65oo2.a $(LIBJIT) $(LIB_ATA) $(RES)
|
vm_LDADD = ../lib/lib65oo2.a $(LIBJIT) $(LIB_ATA) $(RES) $(SDL2_LIBS)
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
LIB_ATA = libata.a
|
LIB_ATA = libata.a
|
||||||
|
|
||||||
libata_a_SOURCES = ata/ata.c ata/rtc.c
|
libata_a_SOURCES = ata/ata.c ata/rtc.c
|
||||||
|
|
||||||
if USE_ATA_VGA
|
if USE_ATA_VGA
|
||||||
libata_a_SOURCES += ata/vga.c
|
libata_a_SOURCES += ata/vga.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if USE_ATA_ETHERNET
|
||||||
|
libata_a_SOURCES += ata/ethernet.c
|
||||||
|
endif
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
#include "isa.h"
|
#include "ata.h"
|
||||||
|
|
||||||
static const uint8_t mac_addr[6] = {
|
static const uint8_t mac_addr[6] = {
|
||||||
0x53, 0x54, 0x41, 0x4C, 0x49, 0x4E
|
0x53, 0x54, 0x41, 0x4C, 0x49, 0x4E
|
||||||
};
|
};
|
||||||
|
|
||||||
AtaDevice ethernet_dev = {
|
AtaDevice ethernet_dev = {
|
||||||
"TinyEthernet",
|
"TinyEthernet",
|
||||||
0x360,
|
0x360,
|
||||||
0x36F,
|
0x36F,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
90
vm/ata/rtc.c
90
vm/ata/rtc.c
|
@ -1,45 +1,45 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "ata.h"
|
#include "ata.h"
|
||||||
|
|
||||||
#define REG_SECS 0x00
|
#define REG_SECS 0x00
|
||||||
#define REG_MINS 0x00
|
#define REG_MINS 0x00
|
||||||
#define REG_HOURS 0x00
|
#define REG_HOURS 0x00
|
||||||
#define REG_WKDAY 0x06
|
#define REG_WKDAY 0x06
|
||||||
#define REG_DAY 0x07
|
#define REG_DAY 0x07
|
||||||
#define REG_YEAR 0x09
|
#define REG_YEAR 0x09
|
||||||
#define REG_CENTURY 0x032
|
#define REG_CENTURY 0x32
|
||||||
#define REG_STATUSA 0x0A
|
#define REG_STATUSA 0x0A
|
||||||
#define REG_STATUSB 0x0B
|
#define REG_STATUSB 0x0B
|
||||||
|
|
||||||
static uint8_t current_reg = 0x00;
|
static uint8_t current_reg = 0x00;
|
||||||
|
|
||||||
void
|
void
|
||||||
rtc_write(uint8_t addr, uint8_t value)
|
rtc_write(uint8_t addr, uint8_t value)
|
||||||
{
|
{
|
||||||
if (addr == 0)
|
if (addr == 0)
|
||||||
{
|
{
|
||||||
current_reg = value;
|
current_reg = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
rtc_read(uint8_t addr)
|
rtc_read(uint8_t addr)
|
||||||
{
|
{
|
||||||
time_t time;
|
time_t time;
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
|
|
||||||
localtime(&time);
|
localtime(&time);
|
||||||
|
|
||||||
(void)time;
|
(void)time;
|
||||||
(void)tm;
|
(void)tm;
|
||||||
|
|
||||||
return (0x00);
|
return (0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
AtaDevice rtc_dev = {
|
AtaDevice rtc_dev = {
|
||||||
"RTC",
|
"RTC",
|
||||||
0x070,
|
0x070,
|
||||||
0x071,
|
0x071,
|
||||||
NULL,
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
16
vm/bus.h
Normal file
16
vm/bus.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef VM_BUS_H
|
||||||
|
# define VM_BUS_H 1
|
||||||
|
|
||||||
|
# include <stddef.h>
|
||||||
|
# include <stdint.h>
|
||||||
|
|
||||||
|
typedef int (*BusRead)(uint32_t addr, void *data, size_t sz);
|
||||||
|
typedef int (*BusWrite)(uint32_t addr, const void *data, size_t sz);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
BusRead read;
|
||||||
|
BusWrite write;
|
||||||
|
} Bus;
|
||||||
|
|
||||||
|
#endif /* !VM_BUS_H */
|
23
vm/cpu.c
Normal file
23
vm/cpu.c
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "cpu.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
invalid_opcode(Cpu *cpu)
|
||||||
|
{
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cpu_execute(Cpu *cpu)
|
||||||
|
{
|
||||||
|
uint8_t opcode;
|
||||||
|
|
||||||
|
switch (opcode)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
invalid_opcode();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu->PC += 1;
|
||||||
|
}
|
16
vm/cpu.h
Normal file
16
vm/cpu.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef VM_CPU_H
|
||||||
|
# define VM_CPU_H 1
|
||||||
|
|
||||||
|
# include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t PC;
|
||||||
|
uint32_t A;
|
||||||
|
uint32_t X;
|
||||||
|
uint32_t Y;
|
||||||
|
uint8_t SR;
|
||||||
|
uint32_t SP;
|
||||||
|
} Cpu;
|
||||||
|
|
||||||
|
#endif /* !VM_CPU_H */
|
83
vm/main.c
83
vm/main.c
|
@ -1,18 +1,65 @@
|
||||||
#include <stdlib.h>
|
#include "config.h"
|
||||||
#include <stdio.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
static const char *prg_name;
|
#ifdef HAVE_LIBGEN_H
|
||||||
|
# include <libgen.h>
|
||||||
void
|
#endif /* HAVE_LIBGEN_H */
|
||||||
usage(void)
|
#include <SDL.h>
|
||||||
{
|
|
||||||
printf("Usage: %s [-hV] [-b bios]\n");
|
static const char *prg_name;
|
||||||
}
|
|
||||||
|
static void
|
||||||
int
|
usage(int retcode)
|
||||||
main(int argc, char **argv)
|
{
|
||||||
{
|
if (retcode == EXIT_FAILURE)
|
||||||
prg_name = argv[0];
|
{
|
||||||
|
fprintf(stderr,
|
||||||
return (EXIT_SUCCESS);
|
"Try '%s -h' for more information.\n", prg_name);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Usage: %s [-hV] [-b bios]\n", prg_name);
|
||||||
|
printf("\t-h\tdisplay this help and exit\n");
|
||||||
|
printf("\t-V\toutput version information\n");
|
||||||
|
printf("\nReport bugs to <%s>\n", PACKAGE_BUGREPORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(retcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
version(void)
|
||||||
|
{
|
||||||
|
printf("%S version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_LIBGEN_H
|
||||||
|
prg_name = basename(argv[0]);
|
||||||
|
#else
|
||||||
|
prg_name = argv[0];
|
||||||
|
#endif /* HAVE_LIBGEN_H */
|
||||||
|
|
||||||
|
while ((argc > 1) && (argv[1][0] == '-'))
|
||||||
|
{
|
||||||
|
switch (argv[1][1])
|
||||||
|
{
|
||||||
|
case 'h':
|
||||||
|
usage(EXIT_SUCCESS);
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
version();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(EXIT_FAILURE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
argv++;
|
||||||
|
argc--;
|
||||||
|
}
|
||||||
|
return (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
32
vm/net/tap-linux.c
Normal file
32
vm/net/tap-linux.c
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#include <linux/if_tun.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* man 7 netdevice
|
||||||
|
* man 4 tap
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
tap_new(void)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
struct ifreq req;
|
||||||
|
|
||||||
|
fd = open("/dev/net/tun", O_RDWR);
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(struct ifreq));
|
||||||
|
req.ifr_flags = IFF_TAP | IFF_NO_PI;
|
||||||
|
/*
|
||||||
|
* malloc(IFNAMSIZ);
|
||||||
|
* tun_alloc(xxxx, IFF_TAP);
|
||||||
|
*/
|
||||||
|
strncpy(req.ifr_name, "todo", 5);
|
||||||
|
if (ioctl(fd, TUNSETIFF, &req) < 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue