1 /* $Id: main.c,v 1.30 2008/12/11 12:18:17 ecd Exp $
2 */
3
4 #include <unistd.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <stdarg.h>
8 #include <string.h>
9 #include <fcntl.h>
10 #include <signal.h>
11 #include <sys/time.h>
12 #include <time.h>
13 #include <errno.h>
14
15 #include <gtk/gtk.h>
16 #include <glib.h>
17
18 #include <x49gp.h>
19 #include <x49gp_ui.h>
20 #include <memory.h>
21 #include <s3c2410.h>
22 #include <s3c2410_power.h>
23 #include <s3c2410_timer.h>
24 #include <x49gp_timer.h>
25
26 #include "gdbstub.h"
27
oom_check(void * ptr)28 static void *oom_check(void *ptr)
29 {
30 if (ptr == NULL) {
31 abort();
32 }
33 return ptr;
34 }
35
36 static x49gp_t *x49gp;
37
38 #ifdef QEMU_OLD // LD TEMPO HACK
39 extern
40 #endif
41 CPUState *__GLOBAL_env;
42
43 int semihosting_enabled = 1;
44
45 /* LD TEMPO HACK */
46 #ifndef QEMU_OLD
47 uint8_t *phys_ram_base;
48 int phys_ram_size;
49 ram_addr_t ram_size = 0x80000; // LD ???
50
51 /* vl.c */
52 int singlestep;
53
qemu_memalign(size_t alignment,size_t size)54 void *qemu_memalign(size_t alignment, size_t size)
55 {
56 #if defined(__APPLE__) || defined(_POSIX_C_SOURCE) && !defined(__sun__)
57 int ret;
58 void *ptr;
59 ret = posix_memalign(&ptr, alignment, size);
60 if (ret != 0)
61 abort();
62 return ptr;
63 #elif defined(CONFIG_BSD)
64 return oom_check(valloc(size));
65 #else
66 return oom_check(memalign(alignment, size));
67 #endif
68 }
69
70
qemu_init_vcpu(void * _env)71 void qemu_init_vcpu(void *_env)
72 {
73 CPUState *env = _env;
74
75 env->nr_cores = 1;
76 env->nr_threads = 1;
77 }
78
qemu_cpu_self(void * env)79 int qemu_cpu_self(void *env)
80 {
81 return 1;
82 }
83
qemu_cpu_kick(void * env)84 void qemu_cpu_kick(void *env)
85 {
86 }
87
armv7m_nvic_set_pending(void * opaque,int irq)88 void armv7m_nvic_set_pending(void *opaque, int irq)
89 {
90 abort();
91 }
armv7m_nvic_acknowledge_irq(void * opaque)92 int armv7m_nvic_acknowledge_irq(void *opaque)
93 {
94 abort();
95 }
armv7m_nvic_complete_irq(void * opaque,int irq)96 void armv7m_nvic_complete_irq(void *opaque, int irq)
97 {
98 abort();
99 }
100
gdb_register_coprocessor(CPUState * env,void * get_reg,void * set_reg,int num_regs,const char * xml,int g_pos)101 void gdb_register_coprocessor(CPUState * env,
102 void * get_reg, void * set_reg,
103 int num_regs, const char *xml, int g_pos)
104 {
105 fprintf(stderr, "TODO: %s\n", __FUNCTION__);
106 }
107
108 #endif /* !QEMU_OLD */
109
110 void *
qemu_malloc(size_t size)111 qemu_malloc(size_t size)
112 {
113 return malloc(size);
114 }
115
116 void *
qemu_mallocz(size_t size)117 qemu_mallocz(size_t size)
118 {
119 void *ptr;
120
121 ptr = qemu_malloc(size);
122 if (NULL == ptr)
123 return NULL;
124 memset(ptr, 0, size);
125 return ptr;
126 }
127
128 void
qemu_free(void * ptr)129 qemu_free(void *ptr)
130 {
131 free(ptr);
132 }
133
134 void *
qemu_vmalloc(size_t size)135 qemu_vmalloc(size_t size)
136 {
137 #if defined(__linux__)
138 void *mem;
139 if (0 == posix_memalign(&mem, sysconf(_SC_PAGE_SIZE), size))
140 return mem;
141 return NULL;
142 #else
143 return valloc(size);
144 #endif
145 }
146
147 #ifdef QEMU_OLD
148 int
term_vprintf(const char * fmt,va_list ap)149 term_vprintf(const char *fmt, va_list ap)
150 {
151 return vprintf(fmt, ap);
152 }
153
154 int
term_printf(const char * fmt,...)155 term_printf(const char *fmt, ...)
156 {
157 va_list ap;
158 int n;
159
160 va_start(ap, fmt);
161 n = vprintf(fmt, ap);
162 va_end(ap);
163
164 return n;
165 }
166 #endif
167
168 #define SWI_Breakpoint 0x180000
169
170 #ifdef QEMU_OLD
171 int
do_arm_semihosting(CPUState * env,uint32_t number)172 do_arm_semihosting(CPUState *env, uint32_t number)
173 #else
174 uint32_t
175 do_arm_semihosting(CPUState *env)
176 #endif
177 {
178 #ifndef QEMU_OLD
179 uint32_t number;
180 if (env->thumb) {
181 number = lduw_code(env->regs[15] - 2) & 0xff;
182 } else {
183 number = ldl_code(env->regs[15] - 4) & 0xffffff;
184 }
185 #endif
186 switch (number) {
187 case SWI_Breakpoint:
188 break;
189
190 case 0:
191 #ifdef DEBUG_X49GP_SYSCALL
192 printf("%s: SWI LR %08x: syscall %u: args %08x %08x %08x %08x %08x %08x %08x\n",
193 __FUNCTION__, env->regs[14], env->regs[0],
194 env->regs[1], env->regs[2], env->regs[3],
195 env->regs[4], env->regs[5], env->regs[6],
196 env->regs[7]);
197 #endif
198
199 #if 1
200 switch (env->regs[0]) {
201 case 305: /* Beep */
202 printf("%s: BEEP: frequency %u, time %u, override %u\n",
203 __FUNCTION__, env->regs[1], env->regs[2], env->regs[3]);
204
205 gdk_beep();
206 env->regs[0] = 0;
207 return 1;
208
209 case 28: /* CheckBeepEnd */
210 env->regs[0] = 0;
211 return 1;
212
213 case 29: /* StopBeep */
214 env->regs[0] = 0;
215 return 1;
216
217 default:
218 break;
219 }
220 #endif
221 break;
222
223 default:
224 break;
225 }
226
227 return 0;
228 }
229
230 void
x49gp_set_idle(x49gp_t * x49gp,x49gp_arm_idle_t idle)231 x49gp_set_idle(x49gp_t *x49gp, x49gp_arm_idle_t idle)
232 {
233 #ifdef DEBUG_X49GP_ARM_IDLE
234 if (idle != x49gp->arm_idle) {
235 printf("%s: arm_idle %u, idle %u\n", __FUNCTION__, x49gp->arm_idle, idle);
236 }
237 #endif
238
239 x49gp->arm_idle = idle;
240
241 if (x49gp->arm_idle == X49GP_ARM_RUN) {
242 x49gp->env->halted = 0;
243 } else {
244 x49gp->env->halted = 1;
245 #ifdef QEMU_OLD
246 cpu_interrupt(x49gp->env, CPU_INTERRUPT_EXIT);
247 #else
248 cpu_exit(x49gp->env);
249 #endif
250 }
251 }
252
253 static void
arm_sighnd(int sig)254 arm_sighnd(int sig)
255 {
256 switch (sig) {
257 case SIGUSR1:
258 // stop_simulator = 1;
259 // x49gp->arm->CallDebug ^= 1;
260 break;
261 default:
262 fprintf(stderr, "%s: sig %u\n", __FUNCTION__, sig);
263 break;
264 }
265 }
266
267 void
x49gp_gtk_timer(void * data)268 x49gp_gtk_timer(void *data)
269 {
270 while (gtk_events_pending()) {
271 // printf("%s: gtk_main_iteration_do()\n", __FUNCTION__);
272 gtk_main_iteration_do(FALSE);
273 }
274
275 x49gp_mod_timer(x49gp->gtk_timer,
276 x49gp_get_clock() + X49GP_GTK_REFRESH_INTERVAL);
277 }
278
279 void
x49gp_lcd_timer(void * data)280 x49gp_lcd_timer(void *data)
281 {
282 x49gp_t *x49gp = data;
283 int64_t now, expires;
284
285 // printf("%s: lcd_update\n", __FUNCTION__);
286 x49gp_lcd_update(x49gp);
287 gdk_flush();
288
289 now = x49gp_get_clock();
290 expires = now + X49GP_LCD_REFRESH_INTERVAL;
291
292 // printf("%s: now: %lld, next update: %lld\n", __FUNCTION__, now, expires);
293 x49gp_mod_timer(x49gp->lcd_timer, expires);
294 }
295
296 static void
usage(const char * progname)297 usage(const char *progname)
298 {
299 fprintf(stderr, "usage: %s <config-file>\n",
300 progname);
301 exit(1);
302 }
303
304 void
ui_sighnd(int sig)305 ui_sighnd(int sig)
306 {
307 switch (sig) {
308 case SIGINT:
309 case SIGQUIT:
310 case SIGTERM:
311 x49gp->arm_exit = 1;
312 #ifdef QEMU_OLD
313 cpu_interrupt(x49gp->env, CPU_INTERRUPT_EXIT);
314 #else
315 cpu_exit(x49gp->env);
316 #endif
317 break;
318 }
319 }
320
321 int
main(int argc,char ** argv)322 main(int argc, char **argv)
323 {
324 char *progname;
325 int error;
326
327
328 progname = strrchr(argv[0], '/');
329 if (progname)
330 progname++;
331 else
332 progname = argv[0];
333
334
335 gtk_init(&argc, &argv);
336
337
338 if (argc < 2)
339 usage(progname);
340
341 x49gp = malloc(sizeof(x49gp_t));
342 if (NULL == x49gp) {
343 fprintf(stderr, "%s: %s:%u: Out of memory\n",
344 progname, __FUNCTION__, __LINE__);
345 exit(1);
346 }
347 memset(x49gp, 0, sizeof(x49gp_t));
348
349 fprintf(stderr, "_SC_PAGE_SIZE: %08lx\n", sysconf(_SC_PAGE_SIZE));
350
351 printf("%s:%u: x49gp: %p\n", __FUNCTION__, __LINE__, x49gp);
352
353 INIT_LIST_HEAD(&x49gp->modules);
354
355
356 x49gp->progname = progname;
357 x49gp->clk_tck = sysconf(_SC_CLK_TCK);
358
359 x49gp->emulator_fclk = 75000000;
360 x49gp->PCLK_ratio = 4;
361 x49gp->PCLK = 75000000 / 4;
362
363 #ifdef QEMU_OLD
364 x49gp->env = cpu_init();
365 #else
366 //cpu_set_log(0xffffffff);
367 cpu_exec_init_all(0);
368 x49gp->env = cpu_init("arm926");
369 #endif
370 __GLOBAL_env = x49gp->env;
371
372 // cpu_set_log(cpu_str_to_log_mask("all"));
373
374 x49gp_timer_init(x49gp);
375
376 x49gp->gtk_timer = x49gp_new_timer(X49GP_TIMER_REALTIME,
377 x49gp_gtk_timer, x49gp);
378 x49gp->lcd_timer = x49gp_new_timer(X49GP_TIMER_VIRTUAL,
379 x49gp_lcd_timer, x49gp);
380
381 x49gp_ui_init(x49gp);
382
383 x49gp_s3c2410_arm_init(x49gp);
384
385 x49gp_flash_init(x49gp);
386 x49gp_sram_init(x49gp);
387
388 x49gp_s3c2410_init(x49gp);
389
390 if (x49gp_modules_init(x49gp)) {
391 exit(1);
392 }
393
394 error = x49gp_modules_load(x49gp, argv[1]);
395 if (error) {
396 if (error != -EAGAIN) {
397 exit(1);
398 }
399 x49gp_modules_reset(x49gp, X49GP_RESET_POWER_ON);
400 }
401 // x49gp_modules_reset(x49gp, X49GP_RESET_POWER_ON);
402
403 signal(SIGINT, ui_sighnd);
404 signal(SIGTERM, ui_sighnd);
405 signal(SIGQUIT, ui_sighnd);
406
407 signal(SIGUSR1, arm_sighnd);
408
409
410 x49gp_set_idle(x49gp, 0);
411
412 // stl_phys(0x08000a1c, 0x55555555);
413
414
415 x49gp_mod_timer(x49gp->gtk_timer, x49gp_get_clock());
416 x49gp_mod_timer(x49gp->lcd_timer, x49gp_get_clock());
417
418
419 #if 0
420 gdbserver_start(1234);
421 gdb_handlesig(x49gp->env, 0);
422 #endif
423
424 x49gp_main_loop(x49gp);
425
426
427 x49gp_modules_save(x49gp, argv[1]);
428 x49gp_modules_exit(x49gp);
429
430
431 #if 0
432 printf("ClkTicks: %lu\n", ARMul_Time(x49gp->arm));
433 printf("D TLB: hit0 %lu, hit1 %lu, search %lu (%lu), walk %lu\n",
434 x49gp->mmu->dTLB.hit0, x49gp->mmu->dTLB.hit1,
435 x49gp->mmu->dTLB.search, x49gp->mmu->dTLB.nsearch,
436 x49gp->mmu->dTLB.walk);
437 printf("I TLB: hit0 %lu, hit1 %lu, search %lu (%lu), walk %lu\n",
438 x49gp->mmu->iTLB.hit0, x49gp->mmu->iTLB.hit1,
439 x49gp->mmu->iTLB.search, x49gp->mmu->iTLB.nsearch,
440 x49gp->mmu->iTLB.walk);
441 #endif
442 return 0;
443 }
444