#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;
size_t mem_size = 64 * 1024 * 1024;
size_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 % 4)
die("program does not align to op-code size of 4 bytes");
int pfd;
if ((pfd = open(program, O_RDONLY)) == -1)
pdie("could not open program");
/* initialize register file */
assert(read(pfd, ®_size, 4) == 4);
reg_size += 4;
GPR = calloc(reg_size, 4);
/* 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 - 4) == sb.st_size - 4);
memset(MEM + sb.st_size + 4, 0xFF, 4);
}
static
uint32_t next_instruction(void)
{
uint32_t tmp;
memcpy(&tmp, &MEM[IP], 4);
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) * 4;
break;
case '?':
default:
usage(EXIT_FAILURE);
}
}
argc -= optind;
argv += optind;
/* reserve memory */
MEM = calloc(mem_size, sizeof(char));
/* load program from file */
if (argc < 1)
usage(EXIT_FAILURE);
read_program(argv[0]);
/* 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 */
}