xref: /netbsd-src/external/gpl3/gdb/dist/sim/example-synacor/sim-main.c (revision f8cf1a9151c7af1cb0bd8b09c13c66bca599c027)
1 /* Example synacor simulator.
2 
3    Copyright (C) 2005-2024 Free Software Foundation, Inc.
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 
24 /* This must come before any other includes.  */
25 #include "defs.h"
26 
27 #include "sim-main.h"
28 #include "sim-signal.h"
29 
30 #include "example-synacor-sim.h"
31 
32 /* Get the register number from the number.  */
33 static uint16_t
34 register_num (SIM_CPU *cpu, uint16_t num)
35 {
36   SIM_DESC sd = CPU_STATE (cpu);
37 
38   if (num < 0x8000 || num >= 0x8008)
39     sim_engine_halt (sd, cpu, NULL, sim_pc_get (cpu), sim_signalled, SIM_SIGILL);
40 
41   return num & 0xf;
42 }
43 
44 /* Helper to process immediates according to the ISA.  */
45 static uint16_t
46 interp_num (SIM_CPU *cpu, uint16_t num)
47 {
48   SIM_DESC sd = CPU_STATE (cpu);
49   struct example_sim_cpu *example_cpu = EXAMPLE_SIM_CPU (cpu);
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);
61       return example_cpu->regs[num & 0xf];
62     }
63   else
64     {
65       /* Numbers 32776..65535 are invalid.  */
66       TRACE_DECODE (cpu, "%#x is an invalid number", num);
67       sim_engine_halt (sd, cpu, NULL, example_cpu->pc, sim_signalled, SIM_SIGILL);
68     }
69 }
70 
71 /* Decode & execute a single instruction.  */
72 void step_once (SIM_CPU *cpu)
73 {
74   SIM_DESC sd = CPU_STATE (cpu);
75   struct example_sim_cpu *example_cpu = EXAMPLE_SIM_CPU (cpu);
76   uint16_t iw1, num1;
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>.  */
93       uint16_t iw2, iw3, num2, num3;
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);
103       example_cpu->regs[num2] = num3;
104 
105       pc += 6;
106     }
107   else if (num1 == 2)
108     {
109       /* push: 2 a: Push <a> onto the stack.  */
110       uint16_t iw2, num2;
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 
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);
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.  */
127       uint16_t iw2, num2, result;
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);
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);
136 
137       TRACE_REGISTER (cpu, "R%i = %#x", num2, result);
138       example_cpu->regs[num2] = result;
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.  */
146       uint16_t iw2, iw3, iw4, num2, num3, num4, result;
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);
160       example_cpu->regs[num2] = result;
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.  */
168       uint16_t iw2, iw3, iw4, num2, num3, num4, result;
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);
182       example_cpu->regs[num2] = result;
183 
184       pc += 8;
185     }
186   else if (num1 == 6)
187     {
188       /* jmp: 6 a: Jump to <a>.  */
189       uint16_t iw2, num2;
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>.  */
204       uint16_t iw2, iw3, num2, num3;
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>.  */
227       uint16_t iw2, iw3, num2, num3;
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).  */
250       uint16_t iw2, iw3, iw4, num2, num3, num4, result;
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);
265       example_cpu->regs[num2] = result;
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).  */
273       uint16_t iw2, iw3, iw4, num2, num3, num4, result;
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);
288       example_cpu->regs[num2] = result;
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>.  */
295       uint16_t iw2, iw3, iw4, num2, num3, num4, result;
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);
309       example_cpu->regs[num2] = result;
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>.  */
316       uint16_t iw2, iw3, iw4, num2, num3, num4, result;
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);
330       example_cpu->regs[num2] = result;
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>.  */
337       uint16_t iw2, iw3, iw4, num2, num3, num4, result;
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);
351       example_cpu->regs[num2] = result;
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>.  */
358       uint16_t iw2, iw3, num2, num3, result;
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);
370       example_cpu->regs[num2] = result;
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>.  */
377       uint16_t iw2, iw3, num2, num3, result;
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);
392       example_cpu->regs[num2] = result;
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>.  */
399       uint16_t iw2, iw3, num2, num3;
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>.  */
419       uint16_t iw2, num2;
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);
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);
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.  */
440       uint16_t result;
441 
442       TRACE_INSN (cpu, "RET");
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);
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.  */
454       uint16_t iw2, num2;
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.  */
472       uint16_t iw2, num2;
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);
492       example_cpu->regs[iw2 & 0xf] = c;
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 
510 /* Return the program counter for this cpu. */
511 static sim_cia
512 pc_get (sim_cpu *cpu)
513 {
514   struct example_sim_cpu *example_cpu = EXAMPLE_SIM_CPU (cpu);
515 
516   return example_cpu->pc;
517 }
518 
519 /* Set the program counter for this cpu to the new pc value. */
520 static void
521 pc_set (sim_cpu *cpu, sim_cia pc)
522 {
523   struct example_sim_cpu *example_cpu = EXAMPLE_SIM_CPU (cpu);
524 
525   example_cpu->pc = pc;
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.  */
531 void initialize_cpu (SIM_DESC sd, SIM_CPU *cpu)
532 {
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;
537   /* Make sure it's initialized outside of the 16-bit address space.  */
538   example_cpu->sp = 0x80000;
539 
540   CPU_PC_FETCH (cpu) = pc_get;
541   CPU_PC_STORE (cpu) = pc_set;
542 }
543