jsos
college code for operating system fundamentals in js
git clone https://9o.is/git/jsos.git
cpu.js
(4553B)
1 /* ------------
2 CPU.js
3
4 Requires global.js.
5
6 Routines for the host CPU simulation, NOT for the OS itself.
7 In this manner, it's A LITTLE BIT like a hypervisor,
8 in that the Document envorinment inside a browser is the "bare metal" (so to speak) for which we write code
9 that hosts our client OS. But that analogy only goes so far, and the lines are blurred, because we are using
10 JavaScript in both the host and client environments.
11
12 This code references page numbers in the text book:
13 Operating System Concepts 8th editiion by Silberschatz, Galvin, and Gagne. ISBN 978-0-470-12872-5
14 ------------ */
15
16 /*
17 * The cpu that contains the program counter (PC),
18 * accumulator (ACC), X register (X),
19 * Y register (Y), Z-ero flag (Z).
20 */
21 function cpu() {
22 this.PC = 0;
23 this.ACC = 0;
24 this.X = 0;
25 this.Y = 0;
26 this.Z = 0;
27
28 this.init = function() {
29 this.output();
30 }
31
32 /* Executes a CPU cycle. */
33 this.cycle = function() {
34 krnTrace("CPU cycle");
35 this.execute();
36 this.output();
37
38 _KernelCPUScheduler.running.bursts += 1;
39 }
40
41 /*
42 * Executes the byte in location PC.
43 */
44 this.execute = function() {
45 var operator = _Memory.getByte(this.PC++);
46 switch(operator) {
47 // LDA: Load the accumulator with a constant
48 case 0xA9:
49 this.ACC = this.immediateOperand();
50 break;
51
52 // LDA: Load the accumulator from memory
53 case 0xAD:
54 this.ACC = this.directOperand();
55 break;
56
57 // STA: Store the accumulator in memory
58 case 0x8D:
59 _Memory.setByte(this.ACC, this.immediateOperand() + this.base());
60 this.PC += 1;
61 break;
62
63 // ADC: Add with carry
64 case 0x6D:
65 this.ACC += this.directOperand();
66 break;
67
68 // LDX: Load the X register with a constant
69 case 0xA2:
70 this.X = this.immediateOperand();
71 break;
72
73 // LDX: Load the X register from memory
74 case 0xAE:
75 this.X = this.directOperand();
76 break;
77
78 // LDY: Load the Y register with a constant
79 case 0xA0:
80 this.Y = this.immediateOperand();
81 break;
82
83 // LDY: Load the Y register from memory
84 case 0xAC:
85 this.Y = this.directOperand();
86 break;
87
88 // NOP: No operation
89 case 0xEA:
90 break;
91
92 // BRK: Break (Terminate)
93 case 0x00:
94 krnInterrupt(SYSCALL_IRQ, 0x00);
95 break;
96
97 // CPX: Compare a byte in memory to the X reg
98 // Sets the Z (zero) flag if equal
99 case 0xEC:
100 this.Z = this.directOperand() == this.X ? 1 : 0;
101 break;
102
103 // BNE: Branch X bytes if Z flag = 0
104 case 0xD0:
105 if(this.Z == 0) {
106 this.PC += this.immediateOperand()+1;
107 if(this.PC > this.limit()) {
108 this.PC -= this.limit()+1;
109 this.PC += this.base();
110 }
111 }
112 else
113 this.PC += 1;
114 break;
115
116 // INC: Increment the value of a byte
117 case 0xEE:
118 var location = _Memory.getByte(this.PC) + this.base();
119 _Memory.setByte(this.directOperand() + 1, location);
120 break;
121
122 // SYS: System Call
123 case 0xFF:
124 krnInterrupt(SYSCALL_IRQ, 0xFF);
125 break;
126
127 }
128 }
129
130 /*
131 * Gets operand from memory in location PC.
132 */
133 this.directOperand = function() {
134 var location = _Memory.getByte(this.PC) + this.base();
135 var value = _Memory.getByte(location);
136 this.PC += 2;
137 return value;
138 }
139
140 /*
141 * Gets operand as a constant in location PC
142 */
143 this.immediateOperand = function() {
144 var value = _Memory.getByte(this.PC);
145 this.PC += 1;
146 return value;
147 }
148
149 /* Base is the lowest value PC can be. */
150 this.base = function() {
151 return _KernelCPUScheduler.running.base;
152 }
153
154 /* Limit is the highest value PC can be. */
155 this.limit = function() {
156 return _KernelCPUScheduler.running.limit;
157 }
158
159 /*
160 * Displays register values in interface.
161 */
162 this.output = function() {
163 document.getElementById("pc_register").innerHTML =
164 pad(this.PC.toString(16),4).toUpperCase();
165
166 document.getElementById("acc_register").innerHTML =
167 pad(this.ACC.toString(16),2).toUpperCase();
168
169 document.getElementById("x_register").innerHTML =
170 pad(this.X.toString(16),2).toUpperCase();
171
172 document.getElementById("y_register").innerHTML =
173 pad(this.Y.toString(16),2).toUpperCase();
174
175 document.getElementById("z_register").innerHTML =
176 this.Z.toString(16);
177 }
178 }