xref: /netbsd-src/external/gpl3/gdb.old/dist/sim/rx/mem.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* mem.c --- memory for RX simulator.
2 
3 Copyright (C) 2005-2023 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 /* This must come before any other includes.  */
22 #include "defs.h"
23 
24 /* This slows down the simulator and we get some false negatives from
25    gcc, like when it uses a long-sized hole to hold a byte-sized
26    variable, knowing that it doesn't care about the other bits.  But,
27    if you need to track down a read-from-unitialized bug, set this to
28    1.  */
29 #define RDCHECK 0
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include "opcode/rx.h"
36 #include "mem.h"
37 #include "cpu.h"
38 #include "syscalls.h"
39 #include "misc.h"
40 #include "err.h"
41 
42 #define L1_BITS  (10)
43 #define L2_BITS  (10)
44 #define OFF_BITS PAGE_BITS
45 
46 #define L1_LEN  (1 << L1_BITS)
47 #define L2_LEN  (1 << L2_BITS)
48 #define OFF_LEN (1 << OFF_BITS)
49 
50 static unsigned char **pt[L1_LEN];
51 static unsigned char **ptr[L1_LEN];
52 static RX_Opcode_Decoded ***ptdc[L1_LEN];
53 
54 /* [ get=0/put=1 ][ byte size ] */
55 static unsigned int mem_counters[2][5];
56 
57 #define COUNT(isput,bytes)                                      \
58   if (verbose && enable_counting) mem_counters[isput][bytes]++
59 
60 void
61 init_mem (void)
62 {
63   int i, j;
64 
65   for (i = 0; i < L1_LEN; i++)
66     if (pt[i])
67       {
68 	for (j = 0; j < L2_LEN; j++)
69 	  if (pt[i][j])
70 	    free (pt[i][j]);
71 	free (pt[i]);
72       }
73   memset (pt, 0, sizeof (pt));
74   memset (ptr, 0, sizeof (ptr));
75   memset (mem_counters, 0, sizeof (mem_counters));
76 }
77 
78 unsigned char *
79 rx_mem_ptr (unsigned long address, enum mem_ptr_action action)
80 {
81   int pt1 = (address >> (L2_BITS + OFF_BITS)) & ((1 << L1_BITS) - 1);
82   int pt2 = (address >> OFF_BITS) & ((1 << L2_BITS) - 1);
83   int pto = address & ((1 << OFF_BITS) - 1);
84 
85   if (address == 0)
86     execution_error (SIM_ERR_NULL_POINTER_DEREFERENCE, 0);
87 
88   if (pt[pt1] == 0)
89     {
90       pt[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **));
91       ptr[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **));
92       ptdc[pt1] = (RX_Opcode_Decoded ***) calloc (L2_LEN, sizeof (RX_Opcode_Decoded ***));
93     }
94   if (pt[pt1][pt2] == 0)
95     {
96       if (action == MPA_READING)
97 	execution_error (SIM_ERR_READ_UNWRITTEN_PAGES, address);
98 
99       pt[pt1][pt2] = (unsigned char *) calloc (OFF_LEN, 1);
100       ptr[pt1][pt2] = (unsigned char *) calloc (OFF_LEN, 1);
101       ptdc[pt1][pt2] = (RX_Opcode_Decoded **) calloc (OFF_LEN, sizeof(RX_Opcode_Decoded *));
102     }
103   else if (action == MPA_READING
104 	   && ptr[pt1][pt2][pto] == MC_UNINIT)
105     execution_error (SIM_ERR_READ_UNWRITTEN_BYTES, address);
106 
107   if (action == MPA_WRITING)
108     {
109       int pto_dc;
110       if (ptr[pt1][pt2][pto] == MC_PUSHED_PC)
111 	execution_error (SIM_ERR_CORRUPT_STACK, address);
112       ptr[pt1][pt2][pto] = MC_DATA;
113 
114       /* The instruction decoder doesn't store it's decoded instructions
115          at word swapped addresses.  Therefore, when clearing the decode
116 	 cache, we have to account for that here.  */
117       pto_dc = pto ^ (rx_big_endian ? 3 : 0);
118       if (ptdc[pt1][pt2][pto_dc])
119 	{
120 	  free (ptdc[pt1][pt2][pto_dc]);
121 	  ptdc[pt1][pt2][pto_dc] = NULL;
122 	}
123     }
124 
125   if (action == MPA_CONTENT_TYPE)
126     return (unsigned char *) (ptr[pt1][pt2] + pto);
127 
128   if (action == MPA_DECODE_CACHE)
129     return (unsigned char *) (ptdc[pt1][pt2] + pto);
130 
131   return pt[pt1][pt2] + pto;
132 }
133 
134 RX_Opcode_Decoded **
135 rx_mem_decode_cache (unsigned long address)
136 {
137   return (RX_Opcode_Decoded **) rx_mem_ptr (address, MPA_DECODE_CACHE);
138 }
139 
140 static inline int
141 is_reserved_address (unsigned int address)
142 {
143   return (address >= 0x00020000 && address < 0x00080000)
144     ||   (address >= 0x00100000 && address < 0x01000000)
145     ||   (address >= 0x08000000 && address < 0xff000000);
146 }
147 
148 static void
149 used (int rstart, int i, int j)
150 {
151   int rend = i << (L2_BITS + OFF_BITS);
152   rend += j << OFF_BITS;
153   if (rstart == 0xe0000 && rend == 0xe1000)
154     return;
155   printf ("mem:   %08x - %08x (%dk bytes)\n", rstart, rend - 1,
156 	  (rend - rstart) / 1024);
157 }
158 
159 static char *
160 mcs (int isput, int bytes)
161 {
162   return comma (mem_counters[isput][bytes]);
163 }
164 
165 void
166 mem_usage_stats (void)
167 {
168   int i, j;
169   int rstart = 0;
170   int pending = 0;
171 
172   for (i = 0; i < L1_LEN; i++)
173     if (pt[i])
174       {
175 	for (j = 0; j < L2_LEN; j++)
176 	  if (pt[i][j])
177 	    {
178 	      if (!pending)
179 		{
180 		  pending = 1;
181 		  rstart = (i << (L2_BITS + OFF_BITS)) + (j << OFF_BITS);
182 		}
183 	    }
184 	  else if (pending)
185 	    {
186 	      pending = 0;
187 	      used (rstart, i, j);
188 	    }
189       }
190     else
191       {
192 	if (pending)
193 	  {
194 	    pending = 0;
195 	    used (rstart, i, 0);
196 	  }
197       }
198   /*       mem foo: 123456789012 123456789012 123456789012 123456789012
199             123456789012 */
200   printf ("                 byte        short        3byte         long"
201           "       opcode\n");
202   if (verbose > 1)
203     {
204       /* Only use comma separated numbers when being very verbose.
205 	 Comma separated numbers are hard to parse in awk scripts.  */
206       printf ("mem get: %12s %12s %12s %12s %12s\n", mcs (0, 1), mcs (0, 2),
207 	      mcs (0, 3), mcs (0, 4), mcs (0, 0));
208       printf ("mem put: %12s %12s %12s %12s\n", mcs (1, 1), mcs (1, 2),
209 	      mcs (1, 3), mcs (1, 4));
210     }
211   else
212     {
213       printf ("mem get: %12u %12u %12u %12u %12u\n",
214 	      mem_counters[0][1], mem_counters[0][2],
215 	      mem_counters[0][3], mem_counters[0][4],
216 	      mem_counters[0][0]);
217       printf ("mem put: %12u %12u %12u %12u\n",
218 	      mem_counters [1][1], mem_counters [1][2],
219 	      mem_counters [1][3], mem_counters [1][4]);
220     }
221 }
222 
223 unsigned long
224 mem_usage_cycles (void)
225 {
226   unsigned long rv = mem_counters[0][0];
227   rv += mem_counters[0][1] * 1;
228   rv += mem_counters[0][2] * 2;
229   rv += mem_counters[0][3] * 3;
230   rv += mem_counters[0][4] * 4;
231   rv += mem_counters[1][1] * 1;
232   rv += mem_counters[1][2] * 2;
233   rv += mem_counters[1][3] * 3;
234   rv += mem_counters[1][4] * 4;
235   return rv;
236 }
237 
238 static int tpr = 0;
239 static void
240 s (int address, char *dir)
241 {
242   if (tpr == 0)
243     printf ("MEM[%08x] %s", address, dir);
244   tpr++;
245 }
246 
247 #define S(d) if (trace) s(address, d)
248 static void
249 e (void)
250 {
251   if (!trace)
252     return;
253   tpr--;
254   if (tpr == 0)
255     printf ("\n");
256 }
257 
258 static char
259 mtypec (int address)
260 {
261   unsigned char *cp = rx_mem_ptr (address, MPA_CONTENT_TYPE);
262   return "udp"[*cp];
263 }
264 
265 #define E() if (trace) e()
266 
267 static void
268 mem_put_byte (unsigned int address, unsigned char value)
269 {
270   unsigned char *m;
271   char tc = ' ';
272 
273   if (trace)
274     tc = mtypec (address);
275   m = rx_mem_ptr (address, MPA_WRITING);
276   if (trace)
277     printf (" %02x%c", value, tc);
278   *m = value;
279   switch (address)
280     {
281     case 0x0008c02a: /* PA.DR */
282      {
283 	static int old_led = -1;
284 	int red_on = 0;
285 	int i;
286 
287 	if (old_led != value)
288 	  {
289 	    fputs (" ", stdout);
290 	    for (i = 0; i < 8; i++)
291 	      if (value & (1 << i))
292 		{
293 		  if (! red_on)
294 		    {
295 		      fputs ("\033[31m", stdout);
296 		      red_on = 1;
297 		    }
298 		  fputs (" @", stdout);
299 		}
300 	      else
301 		{
302 		  if (red_on)
303 		    {
304 		      fputs ("\033[0m", stdout);
305 		      red_on = 0;
306 		    }
307 		  fputs (" *", stdout);
308 		}
309 
310 	    if (red_on)
311 	      fputs ("\033[0m", stdout);
312 
313 	    fputs ("\r", stdout);
314 	    fflush (stdout);
315 	    old_led = value;
316 	  }
317       }
318       break;
319 
320 #ifdef WITH_PROFILE
321     case 0x0008c02b: /* PB.DR */
322       {
323 	if (value == 0)
324 	  halt_pipeline_stats ();
325 	else
326 	  reset_pipeline_stats ();
327       }
328 #endif
329 
330     case 0x00088263: /* SCI4.TDR */
331       {
332 	static int pending_exit = 0;
333 	if (pending_exit == 2)
334 	  {
335 	    step_result = RX_MAKE_EXITED(value);
336 	    longjmp (decode_jmp_buf, 1);
337 	  }
338 	else if (value == 3)
339 	  pending_exit ++;
340 	else
341 	  pending_exit = 0;
342 
343 	putchar(value);
344       }
345       break;
346 
347     default:
348       if (is_reserved_address (address))
349 	generate_access_exception ();
350     }
351 }
352 
353 void
354 mem_put_qi (int address, unsigned char value)
355 {
356   S ("<=");
357   mem_put_byte (address, value & 0xff);
358   E ();
359   COUNT (1, 1);
360 }
361 
362 #ifdef CYCLE_ACCURATE
363 static int tpu_base;
364 #endif
365 
366 void
367 mem_put_hi (int address, unsigned short value)
368 {
369   S ("<=");
370   switch (address)
371     {
372 #ifdef CYCLE_ACCURATE
373     case 0x00088126: /* TPU1.TCNT */
374       tpu_base = regs.cycle_count;
375       break;
376     case 0x00088136: /* TPU2.TCNT */
377       tpu_base = regs.cycle_count;
378       break;
379 #endif
380     default:
381       if (rx_big_endian)
382 	{
383 	  mem_put_byte (address, value >> 8);
384 	  mem_put_byte (address + 1, value & 0xff);
385 	}
386       else
387 	{
388 	  mem_put_byte (address, value & 0xff);
389 	  mem_put_byte (address + 1, value >> 8);
390 	}
391     }
392   E ();
393   COUNT (1, 2);
394 }
395 
396 void
397 mem_put_psi (int address, unsigned long value)
398 {
399   S ("<=");
400   if (rx_big_endian)
401     {
402       mem_put_byte (address, value >> 16);
403       mem_put_byte (address + 1, (value >> 8) & 0xff);
404       mem_put_byte (address + 2, value & 0xff);
405     }
406   else
407     {
408       mem_put_byte (address, value & 0xff);
409       mem_put_byte (address + 1, (value >> 8) & 0xff);
410       mem_put_byte (address + 2, value >> 16);
411     }
412   E ();
413   COUNT (1, 3);
414 }
415 
416 void
417 mem_put_si (int address, unsigned long value)
418 {
419   S ("<=");
420   if (rx_big_endian)
421     {
422       mem_put_byte (address + 0, (value >> 24) & 0xff);
423       mem_put_byte (address + 1, (value >> 16) & 0xff);
424       mem_put_byte (address + 2, (value >> 8) & 0xff);
425       mem_put_byte (address + 3, value & 0xff);
426     }
427   else
428     {
429       mem_put_byte (address + 0, value & 0xff);
430       mem_put_byte (address + 1, (value >> 8) & 0xff);
431       mem_put_byte (address + 2, (value >> 16) & 0xff);
432       mem_put_byte (address + 3, (value >> 24) & 0xff);
433     }
434   E ();
435   COUNT (1, 4);
436 }
437 
438 void
439 mem_put_blk (int address, void *bufptr_void, int nbytes)
440 {
441   unsigned char *bufptr = (unsigned char *) bufptr_void;
442 
443   S ("<=");
444   if (enable_counting)
445     mem_counters[1][1] += nbytes;
446   while (nbytes--)
447     mem_put_byte (address++, *bufptr++);
448   E ();
449 }
450 
451 unsigned char
452 mem_get_pc (int address)
453 {
454   unsigned char *m = rx_mem_ptr (address, MPA_READING);
455   COUNT (0, 0);
456   return *m;
457 }
458 
459 static unsigned char
460 mem_get_byte (unsigned int address)
461 {
462   unsigned char *m;
463 
464   S ("=>");
465   m = rx_mem_ptr (address, MPA_READING);
466   switch (address)
467     {
468     case 0x00088264: /* SCI4.SSR */
469       E();
470       return 0x04; /* transmitter empty */
471       break;
472     default:
473       if (trace)
474 	printf (" %02x%c", *m, mtypec (address));
475       if (is_reserved_address (address))
476 	generate_access_exception ();
477       break;
478     }
479   E ();
480   return *m;
481 }
482 
483 unsigned char
484 mem_get_qi (int address)
485 {
486   unsigned char rv;
487   S ("=>");
488   rv = mem_get_byte (address);
489   COUNT (0, 1);
490   E ();
491   return rv;
492 }
493 
494 unsigned short
495 mem_get_hi (int address)
496 {
497   unsigned short rv;
498   S ("=>");
499   switch (address)
500     {
501 #ifdef CYCLE_ACCURATE
502     case 0x00088126: /* TPU1.TCNT */
503       rv = (regs.cycle_count - tpu_base) >> 16;
504       break;
505     case 0x00088136: /* TPU2.TCNT */
506       rv = (regs.cycle_count - tpu_base) >> 0;
507       break;
508 #endif
509 
510     default:
511       if (rx_big_endian)
512 	{
513 	  rv = mem_get_byte (address) << 8;
514 	  rv |= mem_get_byte (address + 1);
515 	}
516       else
517 	{
518 	  rv = mem_get_byte (address);
519 	  rv |= mem_get_byte (address + 1) << 8;
520 	}
521     }
522   COUNT (0, 2);
523   E ();
524   return rv;
525 }
526 
527 unsigned long
528 mem_get_psi (int address)
529 {
530   unsigned long rv;
531   S ("=>");
532   if (rx_big_endian)
533     {
534       rv = mem_get_byte (address + 2);
535       rv |= mem_get_byte (address + 1) << 8;
536       rv |= mem_get_byte (address) << 16;
537     }
538   else
539     {
540       rv = mem_get_byte (address);
541       rv |= mem_get_byte (address + 1) << 8;
542       rv |= mem_get_byte (address + 2) << 16;
543     }
544   COUNT (0, 3);
545   E ();
546   return rv;
547 }
548 
549 unsigned long
550 mem_get_si (int address)
551 {
552   unsigned long rv;
553   S ("=>");
554   if (rx_big_endian)
555     {
556       rv = mem_get_byte (address + 3);
557       rv |= mem_get_byte (address + 2) << 8;
558       rv |= mem_get_byte (address + 1) << 16;
559       rv |= mem_get_byte (address) << 24;
560     }
561   else
562     {
563       rv = mem_get_byte (address);
564       rv |= mem_get_byte (address + 1) << 8;
565       rv |= mem_get_byte (address + 2) << 16;
566       rv |= mem_get_byte (address + 3) << 24;
567     }
568   COUNT (0, 4);
569   E ();
570   return rv;
571 }
572 
573 void
574 mem_get_blk (int address, void *bufptr_void, int nbytes)
575 {
576   char *bufptr = (char *) bufptr_void;
577 
578   S ("=>");
579   if (enable_counting)
580     mem_counters[0][1] += nbytes;
581   while (nbytes--)
582     *bufptr++ = mem_get_byte (address++);
583   E ();
584 }
585 
586 int
587 sign_ext (int v, int bits)
588 {
589   if (bits < 32)
590     {
591       v &= (1 << bits) - 1;
592       if (v & (1 << (bits - 1)))
593 	v -= (1 << bits);
594     }
595   return v;
596 }
597 
598 void
599 mem_set_content_type (int address, enum mem_content_type type)
600 {
601   unsigned char *mt = rx_mem_ptr (address, MPA_CONTENT_TYPE);
602   *mt = type;
603 }
604 
605 void
606 mem_set_content_range (int start_address, int end_address, enum mem_content_type type)
607 {
608   while (start_address < end_address)
609     {
610       int sz, ofs;
611       unsigned char *mt;
612 
613       sz = end_address - start_address;
614       ofs = start_address % L1_LEN;
615       if (sz + ofs > L1_LEN)
616 	sz = L1_LEN - ofs;
617 
618       mt = rx_mem_ptr (start_address, MPA_CONTENT_TYPE);
619       memset (mt, type, sz);
620 
621       start_address += sz;
622     }
623 }
624 
625 enum mem_content_type
626 mem_get_content_type (int address)
627 {
628   unsigned char *mt = rx_mem_ptr (address, MPA_CONTENT_TYPE);
629   return *mt;
630 }
631