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