summaryrefslogtreecommitdiffstats
path: root/src/emu/risci.c
blob: 1711089658a4ab989be8d991329a8201554c041f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#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 mem_size = 64 * 1024 * 1024;
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, &reg_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]);

	/* 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 */
}