* m32c.opc (BRK, GDBBRK): Remove debug logic.
[deliverable/binutils-gdb.git] / sim / m32c / mem.c
1 /* mem.c --- memory for M32C simulator.
2
3 Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
4 Contributed by Red Hat, Inc.
5
6 This file is part of the GNU 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
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <sys/time.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 #include <sys/select.h>
30 #include <termios.h>
31
32 #include "mem.h"
33 #include "cpu.h"
34 #include "syscalls.h"
35 #include "misc.h"
36 #ifdef TIMER_A
37 #include "int.h"
38 #include "timer_a.h"
39 #endif
40
41 #define L1_BITS (10)
42 #define L2_BITS (10)
43 #define OFF_BITS (12)
44
45 #define L1_LEN (1 << L1_BITS)
46 #define L2_LEN (1 << L2_BITS)
47 #define OFF_LEN (1 << OFF_BITS)
48
49 static unsigned char **pt[L1_LEN];
50
51 int m32c_console_ifd = 0;
52 int m32c_console_ofd = 1;
53 int m32c_use_raw_console = 0;
54
55 #ifdef TIMER_A
56 Timer_A timer_a;
57 #endif
58
59 /* [ get=0/put=1 ][ byte size ] */
60 static unsigned int mem_counters[2][5];
61
62 #define COUNT(isput,bytes) \
63 if (verbose && enable_counting) mem_counters[isput][bytes]++
64
65 void
66 init_mem (void)
67 {
68 int i, j;
69
70 for (i = 0; i < L1_LEN; i++)
71 if (pt[i])
72 {
73 for (j = 0; j < L2_LEN; j++)
74 if (pt[i][j])
75 free (pt[i][j]);
76 free (pt[i]);
77 }
78 memset (pt, 0, sizeof (pt));
79 memset (mem_counters, 0, sizeof (mem_counters));
80 }
81
82 static unsigned char *
83 mem_ptr (address)
84 {
85 static int recursing = 0;
86 int pt1 = (address >> (L2_BITS + OFF_BITS)) & ((1 << L1_BITS) - 1);
87 int pt2 = (address >> OFF_BITS) & ((1 << L2_BITS) - 1);
88 int pto = address & ((1 << OFF_BITS) - 1);
89
90 if (address == 0 && !recursing)
91 {
92 recursing = 1;
93 put_reg (pc, m32c_opcode_pc);
94 printf ("NULL pointer dereference at pc=0x%x\n", get_reg (pc));
95 step_result = M32C_MAKE_HIT_BREAK ();
96 #if 0
97 /* This code can be re-enabled to help diagnose NULL pointer
98 bugs that aren't debuggable in GDB. */
99 m32c_dump_all_registers ();
100 exit (1);
101 #endif
102 }
103
104 if (pt[pt1] == 0)
105 pt[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **));
106 if (pt[pt1][pt2] == 0)
107 {
108 pt[pt1][pt2] = (unsigned char *) malloc (OFF_LEN);
109 memset (pt[pt1][pt2], 0, OFF_LEN);
110 }
111
112 return pt[pt1][pt2] + pto;
113 }
114
115 static void
116 used (int rstart, int i, int j)
117 {
118 int rend = i << (L2_BITS + OFF_BITS);
119 rend += j << OFF_BITS;
120 if (rstart == 0xe0000 && rend == 0xe1000)
121 return;
122 printf ("mem: %08x - %08x (%dk bytes)\n", rstart, rend - 1,
123 (rend - rstart) / 1024);
124 }
125
126 static char *
127 mcs (int isput, int bytes)
128 {
129 return comma (mem_counters[isput][bytes]);
130 }
131
132 void
133 mem_usage_stats ()
134 {
135 int i, j;
136 int rstart = 0;
137 int pending = 0;
138
139 for (i = 0; i < L1_LEN; i++)
140 if (pt[i])
141 {
142 for (j = 0; j < L2_LEN; j++)
143 if (pt[i][j])
144 {
145 if (!pending)
146 {
147 pending = 1;
148 rstart = (i << (L2_BITS + OFF_BITS)) + (j << OFF_BITS);
149 }
150 }
151 else if (pending)
152 {
153 pending = 0;
154 used (rstart, i, j);
155 }
156 }
157 else
158 {
159 if (pending)
160 {
161 pending = 0;
162 used (rstart, i, 0);
163 }
164 }
165 /* mem foo: 123456789012 123456789012 123456789012 123456789012
166 123456789012 */
167 printf (" byte short pointer long"
168 " fetch\n");
169 printf ("mem get: %12s %12s %12s %12s %12s\n", mcs (0, 1), mcs (0, 2),
170 mcs (0, 3), mcs (0, 4), mcs (0, 0));
171 printf ("mem put: %12s %12s %12s %12s\n", mcs (1, 1), mcs (1, 2),
172 mcs (1, 3), mcs (1, 4));
173 }
174
175 static int tpr = 0;
176 static void
177 s (int address, char *dir)
178 {
179 if (tpr == 0)
180 printf ("MEM[%0*x] %s", membus_mask == 0xfffff ? 5 : 6, address, dir);
181 tpr++;
182 }
183
184 #define S(d) if (trace) s(address, d)
185 static void
186 e ()
187 {
188 if (!trace)
189 return;
190 tpr--;
191 if (tpr == 0)
192 printf ("\n");
193 }
194
195 #define E() if (trace) e()
196
197 extern int m32c_disassemble;
198
199 void
200 mem_put_byte (int address, unsigned char value)
201 {
202 unsigned char *m;
203 address &= membus_mask;
204 m = mem_ptr (address);
205 if (trace)
206 printf (" %02x", value);
207 *m = value;
208 switch (address)
209 {
210 case 0x00e1:
211 {
212 static int old_led = -1;
213 static char *led_on[] =
214 { "\033[31m O ", "\033[32m O ", "\033[34m O " };
215 static char *led_off[] = { "\033[0m · ", "\033[0m · ", "\033[0m · " };
216 int i;
217 if (old_led != value)
218 {
219 fputs (" ", stdout);
220 for (i = 0; i < 3; i++)
221 if (value & (1 << i))
222 fputs (led_off[i], stdout);
223 else
224 fputs (led_on[i], stdout);
225 fputs ("\033[0m\r", stdout);
226 fflush (stdout);
227 old_led = value;
228 }
229 }
230 break;
231 #ifdef TIMER_A
232 /* M32C Timer A */
233 case 0x346: /* TA0low */
234 timer_a.count = (timer_a.count & 0xff00) | value;
235 timer_a.reload = timer_a.count;
236 break;
237 case 0x347: /* TA0high */
238 timer_a.count = (timer_a.count & 0x00ff) | (value << 8);
239 timer_a.reload = timer_a.count;
240 break;
241 case 0x340: /* TABSR */
242 timer_a.bsr = value;
243 break;
244 case 0x356: /* TA0MR */
245 timer_a.mode = value;
246 break;
247 case 0x35f: /* TCSPR */
248 timer_a.tcspr = value;
249 break;
250 case 0x006c: /* TA0IC */
251 timer_a.ic = value;
252 break;
253
254 /* R8C Timer RA */
255 case 0x100: /* TRACR */
256 timer_a.bsr = value;
257 break;
258 case 0x102: /* TRAMR */
259 timer_a.mode = value;
260 break;
261 case 0x104: /* TRA */
262 timer_a.count = value;
263 timer_a.reload = value;
264 break;
265 case 0x103: /* TRAPRE */
266 timer_a.tcspr = value;
267 break;
268 case 0x0056: /* TA0IC */
269 timer_a.ic = value;
270 break;
271 #endif
272
273 case 0x2ea: /* m32c uart1tx */
274 case 0x3aa: /* m16c uart1tx */
275 {
276 static int pending_exit = 0;
277 if (value == 0)
278 {
279 if (pending_exit)
280 {
281 step_result = M32C_MAKE_EXITED (value);
282 return;
283 }
284 pending_exit = 1;
285 }
286 else
287 {
288 write (m32c_console_ofd, &value, 1);
289 }
290 }
291 break;
292
293 case 0x400:
294 m32c_syscall (value);
295 break;
296
297 case 0x401:
298 putchar (value);
299 break;
300
301 case 0x402:
302 printf ("SimTrace: %06lx %02x\n", regs.r_pc, value);
303 break;
304
305 case 0x403:
306 printf ("SimTrap: %06lx %02x\n", regs.r_pc, value);
307 abort ();
308 }
309 }
310
311 void
312 mem_put_qi (int address, unsigned char value)
313 {
314 S ("<=");
315 mem_put_byte (address, value & 0xff);
316 E ();
317 COUNT (1, 1);
318 }
319
320 void
321 mem_put_hi (int address, unsigned short value)
322 {
323 if (address == 0x402)
324 {
325 printf ("SimTrace: %06lx %04x\n", regs.r_pc, value);
326 return;
327 }
328 S ("<=");
329 mem_put_byte (address, value & 0xff);
330 mem_put_byte (address + 1, value >> 8);
331 E ();
332 COUNT (1, 2);
333 }
334
335 void
336 mem_put_psi (int address, unsigned long value)
337 {
338 S ("<=");
339 mem_put_byte (address, value & 0xff);
340 mem_put_byte (address + 1, (value >> 8) & 0xff);
341 mem_put_byte (address + 2, value >> 16);
342 E ();
343 COUNT (1, 3);
344 }
345
346 void
347 mem_put_si (int address, unsigned long value)
348 {
349 S ("<=");
350 mem_put_byte (address, value & 0xff);
351 mem_put_byte (address + 1, (value >> 8) & 0xff);
352 mem_put_byte (address + 2, (value >> 16) & 0xff);
353 mem_put_byte (address + 3, (value >> 24) & 0xff);
354 E ();
355 COUNT (1, 4);
356 }
357
358 void
359 mem_put_blk (int address, void *bufptr, int nbytes)
360 {
361 S ("<=");
362 if (enable_counting)
363 mem_counters[1][1] += nbytes;
364 while (nbytes--)
365 mem_put_byte (address++, *(unsigned char *) bufptr++);
366 E ();
367 }
368
369 unsigned char
370 mem_get_pc ()
371 {
372 unsigned char *m = mem_ptr (regs.r_pc & membus_mask);
373 COUNT (0, 0);
374 return *m;
375 }
376
377 static int console_raw = 0;
378 static struct termios oattr;
379
380 static int
381 stdin_ready ()
382 {
383 fd_set ifd;
384 int n;
385 struct timeval t;
386
387 t.tv_sec = 0;
388 t.tv_usec = 0;
389 FD_ZERO (&ifd);
390 FD_SET (m32c_console_ifd, &ifd);
391 n = select (1, &ifd, 0, 0, &t);
392 return n > 0;
393 }
394
395 void
396 m32c_sim_restore_console ()
397 {
398 if (console_raw)
399 tcsetattr (m32c_console_ifd, TCSANOW, &oattr);
400 console_raw = 0;
401 }
402
403 static unsigned char
404 mem_get_byte (int address)
405 {
406 unsigned char *m;
407 address &= membus_mask;
408 m = mem_ptr (address);
409 switch (address)
410 {
411 case 0x2ed: /* m32c uart1c1 */
412 case 0x3ad: /* m16c uart1c1 */
413
414 if (!console_raw && m32c_use_raw_console)
415 {
416 struct termios attr;
417 tcgetattr (m32c_console_ifd, &attr);
418 tcgetattr (m32c_console_ifd, &oattr);
419 /* We want each key to be sent as the user presses them. */
420 attr.c_lflag &= ~(ICANON | ECHO | ECHOE);
421 tcsetattr (m32c_console_ifd, TCSANOW, &attr);
422 console_raw = 1;
423 atexit (m32c_sim_restore_console);
424 }
425
426 if (stdin_ready ())
427 return 0x02; /* tx empty and rx full */
428 else
429 return 0x0a; /* transmitter empty */
430
431 case 0x2ee: /* m32c uart1 rx */
432 {
433 char c;
434 read (m32c_console_ifd, &c, 1);
435 if (m32c_console_ifd == 0 && c == 3) /* Ctrl-C */
436 {
437 printf ("Ctrl-C!\n");
438 exit (0);
439 }
440
441 if (m32c_console_ifd != 1)
442 {
443 if (isgraph (c))
444 printf ("\033[31m%c\033[0m", c);
445 else
446 printf ("\033[31m%02x\033[0m", c);
447 }
448 return c;
449 }
450
451 #ifdef TIMER_A
452 case 0x346: /* TA0low */
453 return timer_a.count & 0xff;
454 case 0x347: /* TA0high */
455 return (timer_a.count >> 8) & 0xff;
456 case 0x104: /* TRA */
457 return timer_a.count;
458 #endif
459
460 }
461
462 S ("=>");
463 if (trace)
464 printf (" %02x", *m);
465 E ();
466 return *m;
467 }
468
469 unsigned char
470 mem_get_qi (int address)
471 {
472 unsigned char rv;
473 S ("=>");
474 rv = mem_get_byte (address);
475 COUNT (0, 1);
476 E ();
477 return rv;
478 }
479
480 unsigned short
481 mem_get_hi (int address)
482 {
483 unsigned short rv;
484 S ("=>");
485 rv = mem_get_byte (address);
486 rv |= mem_get_byte (address + 1) * 256;
487 COUNT (0, 2);
488 E ();
489 return rv;
490 }
491
492 unsigned long
493 mem_get_psi (int address)
494 {
495 unsigned long rv;
496 S ("=>");
497 rv = mem_get_byte (address);
498 rv |= mem_get_byte (address + 1) * 256;
499 rv |= mem_get_byte (address + 2) * 65536;
500 COUNT (0, 3);
501 E ();
502 return rv;
503 }
504
505 unsigned long
506 mem_get_si (int address)
507 {
508 unsigned long rv;
509 S ("=>");
510 rv = mem_get_byte (address);
511 rv |= mem_get_byte (address + 1) << 8;
512 rv |= mem_get_byte (address + 2) << 16;
513 rv |= mem_get_byte (address + 3) << 24;
514 COUNT (0, 4);
515 E ();
516 return rv;
517 }
518
519 void
520 mem_get_blk (int address, void *bufptr, int nbytes)
521 {
522 S ("=>");
523 if (enable_counting)
524 mem_counters[0][1] += nbytes;
525 while (nbytes--)
526 *(char *) bufptr++ = mem_get_byte (address++);
527 E ();
528 }
529
530 int
531 sign_ext (int v, int bits)
532 {
533 if (bits < 32)
534 {
535 v &= (1 << bits) - 1;
536 if (v & (1 << (bits - 1)))
537 v -= (1 << bits);
538 }
539 return v;
540 }
541
542 #if TIMER_A
543 void
544 update_timer_a ()
545 {
546 if (timer_a.bsr & 1)
547 {
548 timer_a.prescale--;
549 if (timer_a.prescale < 0)
550 {
551 if (A24)
552 {
553 switch (timer_a.mode & 0xc0)
554 {
555 case 0x00:
556 timer_a.prescale = 0;
557 break;
558 case 0x40:
559 timer_a.prescale = 8;
560 break;
561 case 0x80:
562 timer_a.prescale = timer_a.tcspr & 0x0f;
563 break;
564 case 0xc0:
565 timer_a.prescale = 32;
566 break;
567 }
568 }
569 else
570 {
571 timer_a.prescale = timer_a.tcspr;
572 }
573 timer_a.count--;
574 if (timer_a.count < 0)
575 {
576 timer_a.count = timer_a.reload;
577 if (timer_a.ic & 7)
578 {
579 if (A24)
580 mem_put_qi (0x6c, timer_a.ic | 0x08);
581 else
582 mem_put_qi (0x56, timer_a.ic | 0x08);
583 }
584 }
585 }
586 }
587
588 if (regs.r_flags & FLAGBIT_I /* interrupts enabled */
589 && timer_a.ic & 0x08 /* timer A interrupt triggered */
590 && (timer_a.ic & 0x07) > ((regs.r_flags >> 12) & 0x07))
591 {
592 if (A24)
593 trigger_peripheral_interrupt (12, 0x06c);
594 else
595 trigger_peripheral_interrupt (22, 0x056);
596 }
597 }
598 #endif
This page took 0.040801 seconds and 5 git commands to generate.