1 /*
2 * Copyright (C) 2005-2018 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * COMMENT: Various test machines
29 *
30 * Generally, the machines are as follows:
31 *
32 * bareXYZ: A bare machine using an XYZ processor.
33 *
34 * testXYZ: A machine with an XYZ processor, and some experimental
35 * devices connected to it.
36 *
37 * The experimental devices in the test machines are:
38 *
39 * cons A serial I/O console device.
40 * disk A device for reading/writing (emulated) disk sectors.
41 * ether An ethernet device, for sending/receiving ethernet
42 * frames on an emulated network.
43 * fb Framebuffer (24-bit RGB per pixel).
44 * irqc A generic interrupt controller.
45 * mp A multiprocessor controller.
46 * rtc A real-time clock device.
47 */
48
49 #include <stdio.h>
50 #include <string.h>
51
52 #include "cpu.h"
53 #include "device.h"
54 #include "devices.h"
55 #include "machine.h"
56 #include "memory.h"
57 #include "misc.h"
58
59 #include "thirdparty/sh4_exception.h"
60
61 #include "testmachine/dev_cons.h"
62 #include "testmachine/dev_disk.h"
63 #include "testmachine/dev_ether.h"
64 #include "testmachine/dev_fb.h"
65 #include "testmachine/dev_irqc.h"
66 #include "testmachine/dev_mp.h"
67 #include "testmachine/dev_rtc.h"
68
69
70 /*
71 * default_test():
72 *
73 * Initializes devices for most test machines. (Note: MIPS is different,
74 * because of legacy reasons.)
75 */
default_test(struct machine * machine,struct cpu * cpu)76 static void default_test(struct machine *machine, struct cpu *cpu)
77 {
78 char tmpstr[2000];
79 char base_irq[1000];
80 char end_of_base_irq[50];
81
82 /*
83 * First add the interrupt controller. Most processor architectures
84 * in GXemul have only 1 interrupt pin on the CPU, and it is simply
85 * called "machine[y].cpu[z]".
86 *
87 * MIPS is an exception, dealt with in a separate setup function.
88 * ARM and SH are dealt with here.
89 */
90
91 switch (machine->arch) {
92
93 case ARCH_ARM:
94 snprintf(end_of_base_irq, sizeof(end_of_base_irq), ".irq");
95 break;
96
97 case ARCH_SH:
98 snprintf(end_of_base_irq, sizeof(end_of_base_irq),
99 ".irq[0x%x]", SH4_INTEVT_IRQ15);
100 break;
101
102 default:
103 end_of_base_irq[0] = '\0';
104 }
105
106 snprintf(base_irq, sizeof(base_irq), "%s.cpu[%i]%s",
107 machine->path, machine->bootstrap_cpu, end_of_base_irq);
108
109 snprintf(tmpstr, sizeof(tmpstr), "irqc addr=0x%" PRIx64" irq=%s",
110 (uint64_t) DEV_IRQC_ADDRESS, base_irq);
111 device_add(machine, tmpstr);
112
113
114 /* Now, add the other devices: */
115
116 snprintf(tmpstr, sizeof(tmpstr), "cons addr=0x%" PRIx64
117 " irq=%s.irqc.2 in_use=%i",
118 (uint64_t) DEV_CONS_ADDRESS, base_irq, machine->arch != ARCH_SH);
119 machine->main_console_handle = (size_t)device_add(machine, tmpstr);
120
121 snprintf(tmpstr, sizeof(tmpstr), "mp addr=0x%" PRIx64" irq=%s%sirqc.6",
122 (uint64_t) DEV_MP_ADDRESS,
123 end_of_base_irq[0]? end_of_base_irq + 1 : "",
124 end_of_base_irq[0]? "." : "");
125 device_add(machine, tmpstr);
126
127 snprintf(tmpstr, sizeof(tmpstr), "fbctrl addr=0x%" PRIx64,
128 (uint64_t) DEV_FBCTRL_ADDRESS);
129 device_add(machine, tmpstr);
130
131 snprintf(tmpstr, sizeof(tmpstr), "disk addr=0x%" PRIx64,
132 (uint64_t) DEV_DISK_ADDRESS);
133 device_add(machine, tmpstr);
134
135 snprintf(tmpstr, sizeof(tmpstr), "ether addr=0x%" PRIx64" irq=%s.irqc.3",
136 (uint64_t) DEV_ETHER_ADDRESS, base_irq);
137 device_add(machine, tmpstr);
138
139 snprintf(tmpstr, sizeof(tmpstr), "rtc addr=0x%" PRIx64" irq=%s.irqc.4",
140 (uint64_t) DEV_RTC_ADDRESS, base_irq);
141 device_add(machine, tmpstr);
142 }
143
144
MACHINE_SETUP(barearm)145 MACHINE_SETUP(barearm)
146 {
147 machine->machine_name = strdup("Generic \"bare\" ARM machine");
148
149 #if 1
150 // An experiment with running a particular firmware image on a device;
151 // move some other place when/if it works?
152 cpu->byte_order = EMUL_BIG_ENDIAN;
153
154 dev_ram_init(machine, 0xa0000000, 128 * 1048576, DEV_RAM_MIRROR
155 | DEV_RAM_MIGHT_POINT_TO_DEVICES, 0x00000000, "ram_mirror");
156 #endif
157 }
158
159
MACHINE_SETUP(testarm)160 MACHINE_SETUP(testarm)
161 {
162 machine->machine_name = strdup("ARM test machine");
163
164 default_test(machine, cpu);
165
166 /*
167 * Place a tiny stub at end of memory, and set the link register to
168 * point to it. This stub halts the machine (making it easy to try
169 * out simple stand-alone C functions).
170 */
171 cpu->cd.arm.r[ARM_SP] = machine->physical_ram_in_mb * 1048576 - 4096;
172 cpu->cd.arm.r[ARM_LR] = cpu->cd.arm.r[ARM_SP] + 32;
173 store_32bit_word(cpu, cpu->cd.arm.r[ARM_LR] + 0, 0xe3a00201);
174 store_32bit_word(cpu, cpu->cd.arm.r[ARM_LR] + 4, 0xe5c00010);
175 store_32bit_word(cpu, cpu->cd.arm.r[ARM_LR] + 8, 0xeafffffe);
176 }
177
178
MACHINE_DEFAULT_CPU(barearm)179 MACHINE_DEFAULT_CPU(barearm)
180 {
181 machine->cpu_name = strdup("SA1110");
182 }
183
184
MACHINE_DEFAULT_CPU(testarm)185 MACHINE_DEFAULT_CPU(testarm)
186 {
187 machine->cpu_name = strdup("SA1110");
188 }
189
190
MACHINE_REGISTER(barearm)191 MACHINE_REGISTER(barearm)
192 {
193 MR_DEFAULT(barearm, "Generic \"bare\" ARM machine",
194 ARCH_ARM, MACHINE_BAREARM);
195
196 machine_entry_add_alias(me, "barearm");
197 }
198
199
MACHINE_REGISTER(testarm)200 MACHINE_REGISTER(testarm)
201 {
202 MR_DEFAULT(testarm, "Test-machine for ARM", ARCH_ARM, MACHINE_TESTARM);
203
204 machine_entry_add_alias(me, "testarm");
205 }
206
207
208
MACHINE_SETUP(barem88k)209 MACHINE_SETUP(barem88k)
210 {
211 machine->machine_name = strdup("Generic \"bare\" M88K machine");
212 }
213
214
MACHINE_SETUP(oldtestm88k)215 MACHINE_SETUP(oldtestm88k)
216 {
217 machine->machine_name = strdup("M88K test machine");
218
219 default_test(machine, cpu);
220 }
221
222
MACHINE_DEFAULT_CPU(barem88k)223 MACHINE_DEFAULT_CPU(barem88k)
224 {
225 machine->cpu_name = strdup("88110");
226 }
227
228
MACHINE_DEFAULT_CPU(oldtestm88k)229 MACHINE_DEFAULT_CPU(oldtestm88k)
230 {
231 machine->cpu_name = strdup("88110");
232 }
233
234
MACHINE_REGISTER(barem88k)235 MACHINE_REGISTER(barem88k)
236 {
237 MR_DEFAULT(barem88k, "Generic \"bare\" M88K machine",
238 ARCH_M88K, MACHINE_BAREM88K);
239
240 machine_entry_add_alias(me, "barem88k");
241 }
242
243
MACHINE_REGISTER(oldtestm88k)244 MACHINE_REGISTER(oldtestm88k)
245 {
246 MR_DEFAULT(oldtestm88k, "Test-machine for M88K",
247 ARCH_M88K, MACHINE_TESTM88K);
248
249 machine_entry_add_alias(me, "oldtestm88k");
250 }
251
252
MACHINE_SETUP(baremips)253 MACHINE_SETUP(baremips)
254 {
255 machine->machine_name = strdup("Generic \"bare\" MIPS machine");
256 cpu->byte_order = EMUL_BIG_ENDIAN;
257 }
258
259
MACHINE_SETUP(testmips)260 MACHINE_SETUP(testmips)
261 {
262 /*
263 * A MIPS test machine. Originally, this was created as a way for
264 * me to test my master's thesis code; since then it has both
265 * evolved to support new things, and suffered bit rot so that it
266 * no longer can run my thesis code. Well, well...
267 *
268 * IRQ map:
269 * 7 CPU counter
270 * 6 SMP IPIs
271 * 5 not used yet
272 * 4 rtc
273 * 3 ethernet
274 * 2 serial console
275 */
276
277 char tmpstr[300];
278
279 machine->machine_name = strdup("MIPS test machine");
280 cpu->byte_order = EMUL_BIG_ENDIAN;
281
282 snprintf(tmpstr, sizeof(tmpstr), "cons addr=0x%" PRIx64" irq=%s."
283 "cpu[%i].2", (uint64_t) DEV_CONS_ADDRESS, machine->path,
284 machine->bootstrap_cpu);
285 machine->main_console_handle = (size_t)device_add(machine, tmpstr);
286
287 snprintf(tmpstr, sizeof(tmpstr), "mp addr=0x%" PRIx64" irq=6",
288 (uint64_t) DEV_MP_ADDRESS);
289 device_add(machine, tmpstr);
290
291 snprintf(tmpstr, sizeof(tmpstr), "fbctrl addr=0x%" PRIx64,
292 (uint64_t) DEV_FBCTRL_ADDRESS);
293 device_add(machine, tmpstr);
294
295 snprintf(tmpstr, sizeof(tmpstr), "disk addr=0x%" PRIx64,
296 (uint64_t) DEV_DISK_ADDRESS);
297 device_add(machine, tmpstr);
298
299 snprintf(tmpstr, sizeof(tmpstr), "ether addr=0x%" PRIx64" irq=%s."
300 "cpu[%i].3", (uint64_t) DEV_ETHER_ADDRESS, machine->path,
301 machine->bootstrap_cpu);
302 device_add(machine, tmpstr);
303
304 snprintf(tmpstr, sizeof(tmpstr), "rtc addr=0x%" PRIx64" irq=%s."
305 "cpu[%i].4", (uint64_t) DEV_RTC_ADDRESS, machine->path,
306 machine->bootstrap_cpu);
307 device_add(machine, tmpstr);
308 }
309
310
MACHINE_DEFAULT_CPU(baremips)311 MACHINE_DEFAULT_CPU(baremips)
312 {
313 machine->cpu_name = strdup("5KE");
314 }
315
316
MACHINE_DEFAULT_CPU(testmips)317 MACHINE_DEFAULT_CPU(testmips)
318 {
319 machine->cpu_name = strdup("5KE");
320 }
321
322
MACHINE_REGISTER(baremips)323 MACHINE_REGISTER(baremips)
324 {
325 MR_DEFAULT(baremips, "Generic \"bare\" MIPS machine",
326 ARCH_MIPS, MACHINE_BAREMIPS);
327
328 machine_entry_add_alias(me, "baremips");
329 }
330
331
MACHINE_REGISTER(testmips)332 MACHINE_REGISTER(testmips)
333 {
334 MR_DEFAULT(testmips, "Test-machine for MIPS",
335 ARCH_MIPS, MACHINE_TESTMIPS);
336
337 machine_entry_add_alias(me, "testmips");
338 }
339
340
MACHINE_SETUP(bareppc)341 MACHINE_SETUP(bareppc)
342 {
343 machine->machine_name = strdup("Generic \"bare\" PPC machine");
344 }
345
346
MACHINE_SETUP(testppc)347 MACHINE_SETUP(testppc)
348 {
349 machine->machine_name = strdup("PPC test machine");
350
351 default_test(machine, cpu);
352 }
353
354
MACHINE_DEFAULT_CPU(bareppc)355 MACHINE_DEFAULT_CPU(bareppc)
356 {
357 machine->cpu_name = strdup("PPC970");
358 }
359
360
MACHINE_DEFAULT_CPU(testppc)361 MACHINE_DEFAULT_CPU(testppc)
362 {
363 machine->cpu_name = strdup("PPC970");
364 }
365
366
MACHINE_REGISTER(bareppc)367 MACHINE_REGISTER(bareppc)
368 {
369 MR_DEFAULT(bareppc, "Generic \"bare\" PPC machine",
370 ARCH_PPC, MACHINE_BAREPPC);
371
372 machine_entry_add_alias(me, "bareppc");
373 }
374
375
MACHINE_REGISTER(testppc)376 MACHINE_REGISTER(testppc)
377 {
378 MR_DEFAULT(testppc, "Test-machine for PPC", ARCH_PPC, MACHINE_TESTPPC);
379
380 machine_entry_add_alias(me, "testppc");
381 }
382
383
MACHINE_SETUP(baresh)384 MACHINE_SETUP(baresh)
385 {
386 machine->machine_name = strdup("Generic \"bare\" SH machine");
387 }
388
389
MACHINE_SETUP(testsh)390 MACHINE_SETUP(testsh)
391 {
392 machine->machine_name = strdup("SH test machine");
393
394 default_test(machine, cpu);
395 }
396
397
MACHINE_DEFAULT_CPU(baresh)398 MACHINE_DEFAULT_CPU(baresh)
399 {
400 machine->cpu_name = strdup("SH7750");
401 }
402
403
MACHINE_DEFAULT_CPU(testsh)404 MACHINE_DEFAULT_CPU(testsh)
405 {
406 machine->cpu_name = strdup("SH7750");
407 }
408
409
MACHINE_REGISTER(baresh)410 MACHINE_REGISTER(baresh)
411 {
412 MR_DEFAULT(baresh, "Generic \"bare\" SH machine",
413 ARCH_SH, MACHINE_BARESH);
414
415 machine_entry_add_alias(me, "baresh");
416 }
417
418
MACHINE_REGISTER(testsh)419 MACHINE_REGISTER(testsh)
420 {
421 MR_DEFAULT(testsh, "Test-machine for SH", ARCH_SH, MACHINE_TESTSH);
422
423 machine_entry_add_alias(me, "testsh");
424 }
425
426
427
428