197 lines
2.9 KiB
C
197 lines
2.9 KiB
C
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdint.h>
|
||
|
#include <stdarg.h>
|
||
|
#include "lib/op.h"
|
||
|
|
||
|
#define OP_ADDR_MODE (OP_ADDR_IMPL | OP_ADDR_REL | OP_ADDR_IND \
|
||
|
| OP_ADDR_IMM | OP_ADDR_ABS)
|
||
|
|
||
|
char *prg_name;
|
||
|
FILE *input;
|
||
|
FILE *output;
|
||
|
|
||
|
uint8_t
|
||
|
readu8(void)
|
||
|
{
|
||
|
uint8_t val;
|
||
|
|
||
|
if (fread(&val, 1, 1, input) != 1)
|
||
|
{
|
||
|
return (-1); /* XXX: TODO */
|
||
|
}
|
||
|
|
||
|
return (val);
|
||
|
}
|
||
|
|
||
|
uint16_t
|
||
|
readu16(void)
|
||
|
{
|
||
|
uint16_t val;
|
||
|
|
||
|
if (fread(&val, 1, 2, input) != 2)
|
||
|
{
|
||
|
return (-1); /* XXX: TODO */
|
||
|
}
|
||
|
|
||
|
return (val);
|
||
|
}
|
||
|
|
||
|
uint32_t
|
||
|
readu32(void)
|
||
|
{
|
||
|
uint32_t val;
|
||
|
|
||
|
if (fread(&val, 1, 4, input) != 4)
|
||
|
{
|
||
|
return (-1); /* XXX: TODO */
|
||
|
}
|
||
|
|
||
|
return (val);
|
||
|
}
|
||
|
|
||
|
int16_t
|
||
|
read16(void)
|
||
|
{
|
||
|
int16_t val;
|
||
|
|
||
|
if (fread(&val, 1, 2, input) != 2)
|
||
|
{
|
||
|
return (-1); /* XXX: TODO */
|
||
|
}
|
||
|
|
||
|
return (val);
|
||
|
}
|
||
|
|
||
|
int32_t
|
||
|
read32(void)
|
||
|
{
|
||
|
int32_t val;
|
||
|
|
||
|
if (fread(&val, 1, 4, input) != 4)
|
||
|
{
|
||
|
return (-1); /* XXX: TODO */
|
||
|
}
|
||
|
|
||
|
return (val);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
fatal(const char *str, ...)
|
||
|
{
|
||
|
va_list ap;
|
||
|
|
||
|
fprintf(stderr, "%s: ", prg_name);
|
||
|
va_start(ap, str);
|
||
|
vfprintf(stderr, str, ap);
|
||
|
va_end(ap);
|
||
|
fprintf(stderr, "\n");
|
||
|
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
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]);
|
||
|
|
||
|
switch (attr & 0x3)
|
||
|
{
|
||
|
case 0x0:
|
||
|
fprintf(output, "B #%X\n", readu8());
|
||
|
break;
|
||
|
case 0x1:
|
||
|
fprintf(output, "W #%hX\n", readu16());
|
||
|
break;
|
||
|
case 0x2:
|
||
|
fprintf(output, "D #%X\n", readu32());
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
decode_ind(uint8_t opcode)
|
||
|
{
|
||
|
uint8_t attr;
|
||
|
|
||
|
attr = readu8();
|
||
|
(void)attr;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
decode_abs(uint8_t opcode)
|
||
|
{
|
||
|
uint8_t attr;
|
||
|
|
||
|
attr = readu8();
|
||
|
(void)attr;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
decode(void)
|
||
|
{
|
||
|
uint8_t opcode;
|
||
|
int16_t relative;
|
||
|
|
||
|
do {
|
||
|
opcode = readu8();
|
||
|
switch (opcode_addr[opcode] & OP_ADDR_MODE)
|
||
|
{
|
||
|
case OP_ADDR_IMPL:
|
||
|
fprintf(output, "%s\n", opcode_str[opcode]);
|
||
|
break;
|
||
|
case OP_ADDR_REL:
|
||
|
relative = read16();
|
||
|
fprintf(output, "%s $%hX\n", opcode_str[opcode], relative);
|
||
|
break;
|
||
|
case OP_ADDR_IMM:
|
||
|
decode_imm(opcode);
|
||
|
break;
|
||
|
case OP_ADDR_IND:
|
||
|
decode_ind(opcode);
|
||
|
break;
|
||
|
case OP_ADDR_ABS:
|
||
|
decode_abs(opcode);
|
||
|
break;
|
||
|
default:
|
||
|
fprintf(output, "???\n", opcode);
|
||
|
break;
|
||
|
}
|
||
|
} while (!feof(input));
|
||
|
}
|
||
|
|
||
|
int
|
||
|
main(int argc, char **argv)
|
||
|
{
|
||
|
prg_name = argv[0];
|
||
|
input = stdin;
|
||
|
output = stdout;
|
||
|
|
||
|
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]);
|
||
|
}
|
||
|
|
||
|
decode();
|
||
|
|
||
|
return (EXIT_SUCCESS);
|
||
|
}
|