2021-01-29 14:17:59 -05:00
|
|
|
#include <stdio.h>
|
|
|
|
|
2021-01-29 14:35:59 -05:00
|
|
|
/*
|
2021-01-29 14:17:59 -05:00
|
|
|
Copyright (c) 2021 Devine Lu Linvega
|
|
|
|
|
|
|
|
Permission to use, copy, modify, and distribute this software for any
|
|
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
WITH REGARD TO THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2021-01-30 00:56:19 -05:00
|
|
|
#define FLAG_HALT 0x01
|
|
|
|
#define FLAG_ZERO 0x02
|
|
|
|
#define FLAG_CARRY 0x04
|
|
|
|
#define FLAG_TRAPS 0x08
|
|
|
|
|
2021-01-29 14:35:59 -05:00
|
|
|
#define STACK_DEPTH 256
|
2021-01-29 15:14:37 -05:00
|
|
|
|
|
|
|
typedef unsigned char Uint8;
|
|
|
|
|
|
|
|
typedef struct {
|
2021-01-30 00:56:19 -05:00
|
|
|
Uint8 literal;
|
|
|
|
Uint8 status, counter;
|
|
|
|
Uint8 memory[STACK_DEPTH];
|
|
|
|
Uint8 mptr, sptr;
|
|
|
|
Uint8 stack[STACK_DEPTH];
|
|
|
|
Uint8 address[STACK_DEPTH];
|
2021-01-29 15:14:37 -05:00
|
|
|
} Computer;
|
|
|
|
|
2021-01-30 00:56:19 -05:00
|
|
|
void
|
|
|
|
setflag(Computer *cpu, char flag, int b)
|
|
|
|
{
|
|
|
|
if(b)
|
|
|
|
cpu->status |= flag;
|
|
|
|
else
|
|
|
|
cpu->status &= (~flag);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
getflag(Computer *cpu, char flag)
|
|
|
|
{
|
|
|
|
return cpu->status & flag;
|
|
|
|
}
|
2021-01-29 14:35:59 -05:00
|
|
|
|
|
|
|
void
|
2021-01-29 16:59:16 -05:00
|
|
|
echo(Uint8 *s, Uint8 len, char *name)
|
2021-01-29 14:35:59 -05:00
|
|
|
{
|
|
|
|
int i;
|
2021-01-29 16:59:16 -05:00
|
|
|
printf("%s\n", name);
|
2021-01-29 15:14:37 -05:00
|
|
|
for(i = 0; i < len; ++i) {
|
2021-01-29 14:35:59 -05:00
|
|
|
if(i % 16 == 0)
|
|
|
|
printf("\n");
|
2021-01-30 00:56:19 -05:00
|
|
|
printf("%02x ", s[i]);
|
2021-01-29 14:35:59 -05:00
|
|
|
}
|
2021-01-30 00:56:19 -05:00
|
|
|
printf("\n\n");
|
2021-01-29 14:35:59 -05:00
|
|
|
}
|
|
|
|
|
2021-01-29 15:14:37 -05:00
|
|
|
void
|
2021-01-30 00:56:19 -05:00
|
|
|
op_push(Uint8 *s, Uint8 *ptr, Uint8 v)
|
2021-01-29 15:14:37 -05:00
|
|
|
{
|
2021-01-30 00:56:19 -05:00
|
|
|
s[*ptr] = v;
|
|
|
|
(*ptr) += 1;
|
2021-01-29 15:14:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-01-30 00:56:19 -05:00
|
|
|
op_pop(Uint8 *s, Uint8 *ptr)
|
2021-01-29 15:14:37 -05:00
|
|
|
{
|
2021-01-30 00:56:19 -05:00
|
|
|
s[*ptr--] = 0x00;
|
2021-01-29 15:14:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
reset(Computer *cpu)
|
|
|
|
{
|
2021-01-30 00:56:19 -05:00
|
|
|
int i;
|
|
|
|
cpu->status = 0x00;
|
|
|
|
cpu->counter = 0x00;
|
|
|
|
cpu->mptr = 0x00;
|
|
|
|
cpu->sptr = 0x00;
|
|
|
|
cpu->literal = 0x00;
|
|
|
|
for(i = 0; i < 256; i++)
|
|
|
|
cpu->stack[i] = 0x00;
|
2021-01-29 15:14:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2021-01-30 00:56:19 -05:00
|
|
|
error(char *name)
|
2021-01-29 15:14:37 -05:00
|
|
|
{
|
2021-01-30 00:56:19 -05:00
|
|
|
printf("Error: %s\n", name);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
load(Computer *cpu, FILE *f)
|
|
|
|
{
|
|
|
|
fread(cpu->memory, sizeof(cpu->memory), 1, f);
|
|
|
|
}
|
2021-01-29 16:59:16 -05:00
|
|
|
|
2021-01-30 00:56:19 -05:00
|
|
|
void
|
|
|
|
eval(Computer *cpu)
|
|
|
|
{
|
|
|
|
Uint8 instr = cpu->memory[cpu->mptr++];
|
|
|
|
|
|
|
|
if(cpu->literal > 0) {
|
|
|
|
printf("push: %02x[%d](%d)\n", instr, cpu->literal, cpu->sptr);
|
|
|
|
op_push(cpu->stack, &cpu->sptr, instr);
|
|
|
|
cpu->literal--;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
switch(instr) {
|
|
|
|
case 0x0: setflag(cpu, FLAG_HALT, 1); break;
|
|
|
|
case 0x1: cpu->literal += 4; break;
|
|
|
|
default: printf("Unknown instruction: #%02x\n", instr);
|
|
|
|
}
|
2021-01-29 15:14:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-01-30 00:56:19 -05:00
|
|
|
run(Computer *cpu)
|
2021-01-29 15:14:37 -05:00
|
|
|
{
|
2021-01-30 00:56:19 -05:00
|
|
|
int i;
|
|
|
|
while((cpu->status & FLAG_HALT) == 0)
|
|
|
|
eval(cpu);
|
|
|
|
/* debug */
|
|
|
|
printf("ended @ %d | ", cpu->counter);
|
|
|
|
for(i = 0; i < 4; i++)
|
|
|
|
printf("%d-", (cpu->status & (1 << i)) != 0);
|
|
|
|
printf("\n\n");
|
2021-01-29 15:14:37 -05:00
|
|
|
}
|
|
|
|
|
2021-01-29 14:17:59 -05:00
|
|
|
int
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
{
|
2021-01-29 15:14:37 -05:00
|
|
|
FILE *f;
|
|
|
|
Computer cpu;
|
|
|
|
if(argc < 2)
|
|
|
|
return error("No input.");
|
|
|
|
if(!(f = fopen(argv[1], "rb")))
|
|
|
|
return error("Missing input.");
|
2021-01-30 00:56:19 -05:00
|
|
|
reset(&cpu);
|
|
|
|
load(&cpu, f);
|
|
|
|
run(&cpu);
|
2021-01-29 15:14:37 -05:00
|
|
|
/* print result */
|
2021-01-30 00:56:19 -05:00
|
|
|
echo(cpu.stack, 0x40, "stack");
|
|
|
|
echo(cpu.memory, 0x40, "memory");
|
2021-01-29 14:17:59 -05:00
|
|
|
return 0;
|
|
|
|
}
|