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