-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.c
148 lines (124 loc) · 3.27 KB
/
main.c
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
File: main.c
Author: Connor McLeod
Date: May 21, 2023
Description: Emulator for the XM-23 RISC processor.
*/
#include "header.h"
CPU cpu;
PSW psw;
Memory mem;
CEX cex;
unsigned short regfile[2][8] =
{
{ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, // Registers.
{ 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0xFFFF } // Constants.
};
volatile sig_atomic_t ctrl_c_fnd;
// Please note that the code is heavily commented for ease of marking.
int main(int argv, char* argc[])
{
// Open .xme program file.
// Fails if no file, wrong type, or inaccessible.
FILE* file;
if (open_xme_file(&file, argv, argc[1]) != 0)
{
close();
return -1; // Program file failed to open.
}
printf("File opened successfully: %s\n", argc[1]);
// Load contents of .xme program file into virtual memory.
// -> This function also returns the start address of the PC.
PC = load_srec(file);
// Instructions have been loaded into virtual memory.
// -> Initialize the CPU's internal registers.
initialize_cpu(&cpu);
cache_init(CACHE_SIZE);
i_vector_init();
#ifdef VERBOSE
i_vector_print();
#endif
// Initialize local variables for user input.
bool running = true;
int input = 0;
int input_mod1 = 0;
int input_mod2 = 0;
int breakpoint = 0;
ctrl_c_fnd = false;
signal(SIGINT, (_crt_signal_t)sigint_hdlr);
// Prints the emulator's controls.
print_controls();
// Setup is complete, the execution can begin.
while (running)
{
// Prompts the user for input and reads the value.
printf("Clock: %i\n", cpu.clock);
printf("Input: ");
(void)scanf("%i", &input);
flush_buffer();
ctrl_c_fnd = false; // Resets ctrl-c handler.
switch (input)
{
case 1: // Run program.
printf("Program execution in progress. Press ctrl+c to halt.\n");
while (PC != breakpoint && !ctrl_c_fnd)
{
fetch();
execute(cpu.ir, PC);
}
break;
case 2: // Step through program.
fetch();
execute(cpu.ir, PC);
break;
case 3: // Set breakpoint.
printf("Enter breakpoint:\n");
printf("Input: ");
(void)scanf("%4x", &input_mod1);
flush_buffer();
breakpoint = input_mod1;
break;
case 4: // Modify program counter.
printf("Enter new program counter:\n");
printf("Input: ");
(void)scanf("%4x", &input_mod1);
flush_buffer();
PC = input_mod1;
break;
case 5: // Print memory contents.
printf("Enter addresses to print: <start> <end>\n");
printf("Input: ");
(void)scanf("%4x %4x", &input_mod1, &input_mod2);
flush_buffer();
print_mem(input_mod1, input_mod2);
break;
case 6: // Print register values.
print_reg(regfile);
break;
case 7: // Print PSW.
print_psw();
break;
case 8: // Print cache.
cache_print(CACHE_SIZE);
break;
case 9:
printf("Enter new cache settings: <org> <pol>\n");
printf("Cache Organizations:\n");
printf("\t0: Direct mapping\n");
printf("\t1: Associative\n");
printf("Cache Policies:\n");
printf("\t0: Write-back\n");
printf("\t1: Write-through\n");
printf("Input: ");
(void)scanf("%i %i", &input_mod1, &input_mod2);
flush_buffer();
cache_config(input_mod1, input_mod2);
break;
default: // Exit emulator.
running = false;
break;
}
}
fclose(file);
return 0;
}