]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/example-synacor/sim-main.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / sim / example-synacor / sim-main.c
CommitLineData
26da232c
MF
1/* Example synacor simulator.
2
1d506c26 3 Copyright (C) 2005-2024 Free Software Foundation, Inc.
26da232c
MF
4 Contributed by Mike Frysinger.
5
6 This file is part of simulators.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21/* This file contains the main simulator decoding logic. i.e. everything that
22 is architecture specific. */
23
6df01ab8
MF
24/* This must come before any other includes. */
25#include "defs.h"
26da232c
MF
26
27#include "sim-main.h"
1fef66b0 28#include "sim-signal.h"
ca6fd350
MF
29
30#include "example-synacor-sim.h"
26da232c
MF
31\f
32/* Get the register number from the number. */
c50b7c1b
MF
33static uint16_t
34register_num (SIM_CPU *cpu, uint16_t num)
26da232c
MF
35{
36 SIM_DESC sd = CPU_STATE (cpu);
37
38 if (num < 0x8000 || num >= 0x8008)
86ecb89b 39 sim_engine_halt (sd, cpu, NULL, sim_pc_get (cpu), sim_signalled, SIM_SIGILL);
26da232c
MF
40
41 return num & 0xf;
42}
43
44/* Helper to process immediates according to the ISA. */
c50b7c1b
MF
45static uint16_t
46interp_num (SIM_CPU *cpu, uint16_t num)
26da232c
MF
47{
48 SIM_DESC sd = CPU_STATE (cpu);
86ecb89b 49 struct example_sim_cpu *example_cpu = EXAMPLE_SIM_CPU (cpu);
26da232c
MF
50
51 if (num < 0x8000)
52 {
53 /* Numbers 0..32767 mean a literal value. */
54 TRACE_DECODE (cpu, "%#x is a literal", num);
55 return num;
56 }
57 else if (num < 0x8008)
58 {
59 /* Numbers 32768..32775 instead mean registers 0..7. */
60 TRACE_DECODE (cpu, "%#x is register R%i", num, num & 0xf);
86ecb89b 61 return example_cpu->regs[num & 0xf];
26da232c
MF
62 }
63 else
64 {
65 /* Numbers 32776..65535 are invalid. */
66 TRACE_DECODE (cpu, "%#x is an invalid number", num);
86ecb89b 67 sim_engine_halt (sd, cpu, NULL, example_cpu->pc, sim_signalled, SIM_SIGILL);
26da232c
MF
68 }
69}
70\f
71/* Decode & execute a single instruction. */
72void step_once (SIM_CPU *cpu)
73{
74 SIM_DESC sd = CPU_STATE (cpu);
86ecb89b 75 struct example_sim_cpu *example_cpu = EXAMPLE_SIM_CPU (cpu);
c50b7c1b 76 uint16_t iw1, num1;
26da232c
MF
77 sim_cia pc = sim_pc_get (cpu);
78
79 iw1 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc);
80 TRACE_EXTRACT (cpu, "%04x: iw1: %#x", pc, iw1);
81 /* This never happens, but technically is possible in the ISA. */
82 num1 = interp_num (cpu, iw1);
83
84 if (num1 == 0)
85 {
86 /* halt: 0: Stop execution and terminate the program. */
87 TRACE_INSN (cpu, "HALT");
88 sim_engine_halt (sd, cpu, NULL, pc, sim_exited, 0);
89 }
90 else if (num1 == 1)
91 {
92 /* set: 1 a b: Set register <a> to the value of <b>. */
c50b7c1b 93 uint16_t iw2, iw3, num2, num3;
26da232c
MF
94
95 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
96 num2 = register_num (cpu, iw2);
97 iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
98 num3 = interp_num (cpu, iw3);
99 TRACE_EXTRACT (cpu, "SET %#x %#x", iw2, iw3);
100 TRACE_INSN (cpu, "SET R%i %#x", num2, num3);
101
102 TRACE_REGISTER (cpu, "R%i = %#x", num2, num3);
86ecb89b 103 example_cpu->regs[num2] = num3;
26da232c
MF
104
105 pc += 6;
106 }
107 else if (num1 == 2)
108 {
109 /* push: 2 a: Push <a> onto the stack. */
c50b7c1b 110 uint16_t iw2, num2;
26da232c
MF
111
112 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
113 num2 = interp_num (cpu, iw2);
114 TRACE_EXTRACT (cpu, "PUSH %#x", iw2);
115 TRACE_INSN (cpu, "PUSH %#x", num2);
116
86ecb89b
MF
117 sim_core_write_aligned_2 (cpu, pc, write_map, example_cpu->sp, num2);
118 example_cpu->sp -= 2;
119 TRACE_REGISTER (cpu, "SP = %#x", example_cpu->sp);
26da232c
MF
120
121 pc += 4;
122 }
123 else if (num1 == 3)
124 {
125 /* pop: 3 a: Remove the top element from the stack and write it into <a>.
126 Empty stack = error. */
c50b7c1b 127 uint16_t iw2, num2, result;
26da232c
MF
128
129 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
130 num2 = register_num (cpu, iw2);
131 TRACE_EXTRACT (cpu, "POP %#x", iw2);
132 TRACE_INSN (cpu, "POP R%i", num2);
86ecb89b
MF
133 example_cpu->sp += 2;
134 TRACE_REGISTER (cpu, "SP = %#x", example_cpu->sp);
135 result = sim_core_read_aligned_2 (cpu, pc, read_map, example_cpu->sp);
26da232c
MF
136
137 TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
86ecb89b 138 example_cpu->regs[num2] = result;
26da232c
MF
139
140 pc += 4;
141 }
142 else if (num1 == 4)
143 {
144 /* eq: 4 a b c: Set <a> to 1 if <b> is equal to <c>; set it to 0
145 otherwise. */
c50b7c1b 146 uint16_t iw2, iw3, iw4, num2, num3, num4, result;
26da232c
MF
147
148 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
149 num2 = register_num (cpu, iw2);
150 iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
151 num3 = interp_num (cpu, iw3);
152 iw4 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 6);
153 num4 = interp_num (cpu, iw4);
154 result = (num3 == num4);
155 TRACE_EXTRACT (cpu, "EQ %#x %#x %#x", iw2, iw3, iw4);
156 TRACE_INSN (cpu, "EQ R%i %#x %#x", num2, num3, num4);
157 TRACE_DECODE (cpu, "R%i = (%#x == %#x) = %i", num2, num3, num4, result);
158
159 TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
86ecb89b 160 example_cpu->regs[num2] = result;
26da232c
MF
161
162 pc += 8;
163 }
164 else if (num1 == 5)
165 {
166 /* gt: 5 a b c: Set <a> to 1 if <b> is greater than <c>; set it to 0
167 otherwise. */
c50b7c1b 168 uint16_t iw2, iw3, iw4, num2, num3, num4, result;
26da232c
MF
169
170 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
171 num2 = register_num (cpu, iw2);
172 iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
173 num3 = interp_num (cpu, iw3);
174 iw4 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 6);
175 num4 = interp_num (cpu, iw4);
176 result = (num3 > num4);
177 TRACE_EXTRACT (cpu, "GT %#x %#x %#x", iw2, iw3, iw4);
178 TRACE_INSN (cpu, "GT R%i %#x %#x", num2, num3, num4);
179 TRACE_DECODE (cpu, "R%i = (%#x > %#x) = %i", num2, num3, num4, result);
180
181 TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
86ecb89b 182 example_cpu->regs[num2] = result;
26da232c
MF
183
184 pc += 8;
185 }
186 else if (num1 == 6)
187 {
188 /* jmp: 6 a: Jump to <a>. */
c50b7c1b 189 uint16_t iw2, num2;
26da232c
MF
190
191 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
192 num2 = interp_num (cpu, iw2);
193 /* Addresses are 16-bit aligned. */
194 num2 <<= 1;
195 TRACE_EXTRACT (cpu, "JMP %#x", iw2);
196 TRACE_INSN (cpu, "JMP %#x", num2);
197
198 pc = num2;
199 TRACE_BRANCH (cpu, "JMP %#x", pc);
200 }
201 else if (num1 == 7)
202 {
203 /* jt: 7 a b: If <a> is nonzero, jump to <b>. */
c50b7c1b 204 uint16_t iw2, iw3, num2, num3;
26da232c
MF
205
206 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
207 num2 = interp_num (cpu, iw2);
208 iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
209 num3 = interp_num (cpu, iw3);
210 /* Addresses are 16-bit aligned. */
211 num3 <<= 1;
212 TRACE_EXTRACT (cpu, "JT %#x %#x", iw2, iw3);
213 TRACE_INSN (cpu, "JT %#x %#x", num2, num3);
214 TRACE_DECODE (cpu, "JT %#x != 0 -> %s", num2, num2 ? "taken" : "nop");
215
216 if (num2)
217 {
218 pc = num3;
219 TRACE_BRANCH (cpu, "JT %#x", pc);
220 }
221 else
222 pc += 6;
223 }
224 else if (num1 == 8)
225 {
226 /* jf: 8 a b: If <a> is zero, jump to <b>. */
c50b7c1b 227 uint16_t iw2, iw3, num2, num3;
26da232c
MF
228
229 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
230 num2 = interp_num (cpu, iw2);
231 iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
232 num3 = interp_num (cpu, iw3);
233 /* Addresses are 16-bit aligned. */
234 num3 <<= 1;
235 TRACE_EXTRACT (cpu, "JF %#x %#x", iw2, iw3);
236 TRACE_INSN (cpu, "JF %#x %#x", num2, num3);
237 TRACE_DECODE (cpu, "JF %#x == 0 -> %s", num2, num2 ? "nop" : "taken");
238
239 if (!num2)
240 {
241 pc = num3;
242 TRACE_BRANCH (cpu, "JF %#x", pc);
243 }
244 else
245 pc += 6;
246 }
247 else if (num1 == 9)
248 {
249 /* add: 9 a b c: Assign <a> the sum of <b> and <c> (modulo 32768). */
c50b7c1b 250 uint16_t iw2, iw3, iw4, num2, num3, num4, result;
26da232c
MF
251
252 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
253 num2 = register_num (cpu, iw2);
254 iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
255 num3 = interp_num (cpu, iw3);
256 iw4 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 6);
257 num4 = interp_num (cpu, iw4);
258 result = (num3 + num4) % 32768;
259 TRACE_EXTRACT (cpu, "ADD %#x %#x %#x", iw2, iw3, iw4);
260 TRACE_INSN (cpu, "ADD R%i %#x %#x", num2, num3, num4);
261 TRACE_DECODE (cpu, "R%i = (%#x + %#x) %% %i = %#x", num2, num3, num4,
262 32768, result);
263
264 TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
86ecb89b 265 example_cpu->regs[num2] = result;
26da232c
MF
266
267 pc += 8;
268 }
269 else if (num1 == 10)
270 {
271 /* mult: 10 a b c: Store into <a> the product of <b> and <c> (modulo
272 32768). */
c50b7c1b 273 uint16_t iw2, iw3, iw4, num2, num3, num4, result;
26da232c
MF
274
275 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
276 num2 = register_num (cpu, iw2);
277 iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
278 num3 = interp_num (cpu, iw3);
279 iw4 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 6);
280 num4 = interp_num (cpu, iw4);
281 result = (num3 * num4) % 32768;
282 TRACE_EXTRACT (cpu, "MULT %#x %#x %#x", iw2, iw3, iw4);
283 TRACE_INSN (cpu, "MULT R%i %#x %#x", num2, num3, num4);
284 TRACE_DECODE (cpu, "R%i = (%#x * %#x) %% %i = %#x", num2, num3, num4,
285 32768, result);
286
287 TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
86ecb89b 288 example_cpu->regs[num2] = result;
26da232c
MF
289
290 pc += 8;
291 }
292 else if (num1 == 11)
293 {
294 /* mod: 11 a b c: Store into <a> the remainder of <b> divided by <c>. */
c50b7c1b 295 uint16_t iw2, iw3, iw4, num2, num3, num4, result;
26da232c
MF
296
297 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
298 num2 = register_num (cpu, iw2);
299 iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
300 num3 = interp_num (cpu, iw3);
301 iw4 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 6);
302 num4 = interp_num (cpu, iw4);
303 result = num3 % num4;
304 TRACE_EXTRACT (cpu, "MOD %#x %#x %#x", iw2, iw3, iw4);
305 TRACE_INSN (cpu, "MOD R%i %#x %#x", num2, num3, num4);
306 TRACE_DECODE (cpu, "R%i = %#x %% %#x = %#x", num2, num3, num4, result);
307
308 TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
86ecb89b 309 example_cpu->regs[num2] = result;
26da232c
MF
310
311 pc += 8;
312 }
313 else if (num1 == 12)
314 {
315 /* and: 12 a b c: Stores into <a> the bitwise and of <b> and <c>. */
c50b7c1b 316 uint16_t iw2, iw3, iw4, num2, num3, num4, result;
26da232c
MF
317
318 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
319 num2 = register_num (cpu, iw2);
320 iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
321 num3 = interp_num (cpu, iw3);
322 iw4 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 6);
323 num4 = interp_num (cpu, iw4);
324 result = (num3 & num4);
325 TRACE_EXTRACT (cpu, "AND %#x %#x %#x", iw2, iw3, iw4);
326 TRACE_INSN (cpu, "AND R%i %#x %#x", num2, num3, num4);
327 TRACE_DECODE (cpu, "R%i = %#x & %#x = %#x", num2, num3, num4, result);
328
329 TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
86ecb89b 330 example_cpu->regs[num2] = result;
26da232c
MF
331
332 pc += 8;
333 }
334 else if (num1 == 13)
335 {
336 /* or: 13 a b c: Stores into <a> the bitwise or of <b> and <c>. */
c50b7c1b 337 uint16_t iw2, iw3, iw4, num2, num3, num4, result;
26da232c
MF
338
339 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
340 num2 = register_num (cpu, iw2);
341 iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
342 num3 = interp_num (cpu, iw3);
343 iw4 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 6);
344 num4 = interp_num (cpu, iw4);
345 result = (num3 | num4);
346 TRACE_EXTRACT (cpu, "OR %#x %#x %#x", iw2, iw3, iw4);
347 TRACE_INSN (cpu, "OR R%i %#x %#x", num2, num3, num4);
348 TRACE_DECODE (cpu, "R%i = %#x | %#x = %#x", num2, num3, num4, result);
349
350 TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
86ecb89b 351 example_cpu->regs[num2] = result;
26da232c
MF
352
353 pc += 8;
354 }
355 else if (num1 == 14)
356 {
357 /* not: 14 a b: Stores 15-bit bitwise inverse of <b> in <a>. */
c50b7c1b 358 uint16_t iw2, iw3, num2, num3, result;
26da232c
MF
359
360 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
361 num2 = register_num (cpu, iw2);
362 iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
363 num3 = interp_num (cpu, iw3);
364 result = (~num3) & 0x7fff;
365 TRACE_EXTRACT (cpu, "NOT %#x %#x", iw2, iw3);
366 TRACE_INSN (cpu, "NOT R%i %#x", num2, num3);
367 TRACE_DECODE (cpu, "R%i = (~%#x) & 0x7fff = %#x", num2, num3, result);
368
369 TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
86ecb89b 370 example_cpu->regs[num2] = result;
26da232c
MF
371
372 pc += 6;
373 }
374 else if (num1 == 15)
375 {
376 /* rmem: 15 a b: Read memory at address <b> and write it to <a>. */
c50b7c1b 377 uint16_t iw2, iw3, num2, num3, result;
26da232c
MF
378
379 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
380 num2 = register_num (cpu, iw2);
381 iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
382 num3 = interp_num (cpu, iw3);
383 /* Addresses are 16-bit aligned. */
384 num3 <<= 1;
385 TRACE_EXTRACT (cpu, "RMEM %#x %#x", iw2, iw3);
386 TRACE_INSN (cpu, "RMEM R%i %#x", num2, num3);
387
388 TRACE_MEMORY (cpu, "reading %#x", num3);
389 result = sim_core_read_aligned_2 (cpu, pc, read_map, num3);
390
391 TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
86ecb89b 392 example_cpu->regs[num2] = result;
26da232c
MF
393
394 pc += 6;
395 }
396 else if (num1 == 16)
397 {
398 /* wmem: 16 a b: Write the value from <b> into memory at address <a>. */
c50b7c1b 399 uint16_t iw2, iw3, num2, num3;
26da232c
MF
400
401 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
402 num2 = interp_num (cpu, iw2);
403 iw3 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 4);
404 num3 = interp_num (cpu, iw3);
405 /* Addresses are 16-bit aligned. */
406 num2 <<= 1;
407 TRACE_EXTRACT (cpu, "WMEM %#x %#x", iw2, iw3);
408 TRACE_INSN (cpu, "WMEM %#x %#x", num2, num3);
409
410 TRACE_MEMORY (cpu, "writing %#x to %#x", num3, num2);
411 sim_core_write_aligned_2 (cpu, pc, write_map, num2, num3);
412
413 pc += 6;
414 }
415 else if (num1 == 17)
416 {
417 /* call: 17 a: Write the address of the next instruction to the stack and
418 jump to <a>. */
c50b7c1b 419 uint16_t iw2, num2;
26da232c
MF
420
421 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
422 num2 = interp_num (cpu, iw2);
423 /* Addresses are 16-bit aligned. */
424 num2 <<= 1;
425 TRACE_EXTRACT (cpu, "CALL %#x", iw2);
426 TRACE_INSN (cpu, "CALL %#x", num2);
427
428 TRACE_MEMORY (cpu, "pushing %#x onto stack", (pc + 4) >> 1);
86ecb89b
MF
429 sim_core_write_aligned_2 (cpu, pc, write_map, example_cpu->sp, (pc + 4) >> 1);
430 example_cpu->sp -= 2;
431 TRACE_REGISTER (cpu, "SP = %#x", example_cpu->sp);
26da232c
MF
432
433 pc = num2;
434 TRACE_BRANCH (cpu, "CALL %#x", pc);
435 }
436 else if (num1 == 18)
437 {
438 /* ret: 18: Remove the top element from the stack and jump to it; empty
439 stack = halt. */
c50b7c1b 440 uint16_t result;
26da232c
MF
441
442 TRACE_INSN (cpu, "RET");
86ecb89b
MF
443 example_cpu->sp += 2;
444 TRACE_REGISTER (cpu, "SP = %#x", example_cpu->sp);
445 result = sim_core_read_aligned_2 (cpu, pc, read_map, example_cpu->sp);
26da232c
MF
446 TRACE_MEMORY (cpu, "popping %#x off of stack", result << 1);
447
448 pc = result << 1;
449 TRACE_BRANCH (cpu, "RET -> %#x", pc);
450 }
451 else if (num1 == 19)
452 {
453 /* out: 19 a: Write the character <a> to the terminal. */
c50b7c1b 454 uint16_t iw2, num2;
26da232c
MF
455
456 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
457 num2 = interp_num (cpu, iw2);
458 TRACE_EXTRACT (cpu, "OUT %#x", iw2);
459 TRACE_INSN (cpu, "OUT %#x", num2);
460 TRACE_EVENTS (cpu, "write to stdout: %#x (%c)", num2, num2);
461
462 sim_io_printf (sd, "%c", num2);
463
464 pc += 4;
465 }
466 else if (num1 == 20)
467 {
468 /* in: 20 a: read a character from the terminal and write its ascii code
469 to <a>. It can be assumed that once input starts, it will continue
470 until a newline is encountered. This means that you can safely read
471 lines from the keyboard and trust that they will be fully read. */
c50b7c1b 472 uint16_t iw2, num2;
26da232c
MF
473 char c;
474
475 iw2 = sim_core_read_aligned_2 (cpu, pc, exec_map, pc + 2);
476 num2 = register_num (cpu, iw2);
477 TRACE_EXTRACT (cpu, "IN %#x", iw2);
478 TRACE_INSN (cpu, "IN %#x", num2);
479 sim_io_read_stdin (sd, &c, 1);
480 TRACE_EVENTS (cpu, "read from stdin: %#x (%c)", c, c);
481
482 /* The challenge uses lowercase for all inputs, so insert some low level
483 helpers of our own to make it a bit nicer. */
484 switch (c)
485 {
486 case 'Q':
487 sim_engine_halt (sd, cpu, NULL, pc, sim_exited, 0);
488 break;
489 }
490
491 TRACE_REGISTER (cpu, "R%i = %#x", iw2 & 0xf, c);
86ecb89b 492 example_cpu->regs[iw2 & 0xf] = c;
26da232c
MF
493
494 pc += 4;
495 }
496 else if (num1 == 21)
497 {
498 /* noop: 21: no operation */
499 TRACE_INSN (cpu, "NOOP");
500
501 pc += 2;
502 }
503 else
504 sim_engine_halt (sd, cpu, NULL, pc, sim_signalled, SIM_SIGILL);
505
506 TRACE_REGISTER (cpu, "PC = %#x", pc);
507 sim_pc_set (cpu, pc);
508}
509\f
510/* Return the program counter for this cpu. */
511static sim_cia
512pc_get (sim_cpu *cpu)
513{
86ecb89b
MF
514 struct example_sim_cpu *example_cpu = EXAMPLE_SIM_CPU (cpu);
515
516 return example_cpu->pc;
26da232c
MF
517}
518
519/* Set the program counter for this cpu to the new pc value. */
520static void
521pc_set (sim_cpu *cpu, sim_cia pc)
522{
86ecb89b
MF
523 struct example_sim_cpu *example_cpu = EXAMPLE_SIM_CPU (cpu);
524
525 example_cpu->pc = pc;
26da232c
MF
526}
527
528/* Initialize the state for a single cpu. Usuaully this involves clearing all
529 registers back to their reset state. Should also hook up the fetch/store
530 helper functions too. */
531void initialize_cpu (SIM_DESC sd, SIM_CPU *cpu)
532{
86ecb89b
MF
533 struct example_sim_cpu *example_cpu = EXAMPLE_SIM_CPU (cpu);
534
535 memset (example_cpu->regs, 0, sizeof (example_cpu->regs));
536 example_cpu->pc = 0;
26da232c 537 /* Make sure it's initialized outside of the 16-bit address space. */
86ecb89b 538 example_cpu->sp = 0x80000;
26da232c
MF
539
540 CPU_PC_FETCH (cpu) = pc_get;
541 CPU_PC_STORE (cpu) = pc_set;
542}