#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <signal.h>
#include <assert.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <readline/readline.h>
#include "asm.h"
#include "cpu.h"
#include "log.h"
#include "mem.h"
#include "opc.h"
bool is_debug = false;
uint64_t reg_size = 0;
static
void usage(int rc)
{
fprintf(stderr, "Usage: risci [-dhi] <program>\n");
exit(rc);
}
static
void dump_registers(void)
{
fprintf(stderr, "REGISTER DUMP:\n");
for (size_t i = 0; i < reg_size; i++)
fprintf(stderr, "\tr%zu = %"PRIu32"\n", i, GPR[i]);
}
static
void read_program(const char *program)
{
struct stat sb;
if (lstat(program, &sb) == -1)
pdie("cannot stat program");
if (sb.st_size % sizeof(inst_t))
die("program does not align to instruction size of %zu bytes", sizeof(inst_t));
int pfd;
if ((pfd = open(program, O_RDONLY)) == -1)
pdie("could not open program");
/* initialize register file */
assert(read(pfd, ®_size, sizeof(inst_t)) == sizeof(inst_t));
reg_size += 4;
GPR = calloc(reg_size, sizeof(uint32_t));
/* initialize pseudo registers */
BP = reg_size - 3;
SP = reg_size - 2;
RV = reg_size - 1;
GPR[BP] = GPR[SP] = mem_size;
GPR[RV] = 0;
assert(read(pfd, MEM, sb.st_size - sizeof(inst_t)) == (ssize_t)(sb.st_size - sizeof(inst_t)));
memset(MEM + sb.st_size, 0xFF, sizeof(inst_t));
}
static
inst_t next_instruction(void)
{
inst_t tmp;
memcpy(&tmp, &MEM[IP], sizeof(inst_t));
return tmp;
}
int main(int argc, char *argv[])
{
int ch;
while ((ch = getopt(argc, argv, "dhm")) != -1) {
switch (ch) {
case 'd':
is_debug = true;
break;
case 'h':
usage(EXIT_SUCCESS);
case 'm':
mem_size = atoi(optarg) * sizeof(uint32_t);
break;
case '?':
default:
usage(EXIT_FAILURE);
}
}
argc -= optind;
argv += optind;
/* reserve memory */
MEM = calloc(mem_size, sizeof(uint8_t));
/* load program from file */
if (argc < 1)
usage(EXIT_FAILURE);
read_program(argv[0]);
/* push arguments onto stack */
while (--argc) {
//dump_registers();
push(atoi(argv[argc]));
}
/* reset program counter to first instruction */
IP = 0;
/* start instruction loop */
while (1) {
//dump_registers();
execute(next_instruction());
}
/* not reached, program is terminated by signal traps from the cpu */
}