xref: /netbsd-src/external/gpl3/gdb/dist/sim/rx/mem.c (revision 1f4e7eb9e5e045e008f1894823a8e4e6c9f46890)
1 /* mem.c --- memory for RX simulator.
2 
3 Copyright (C) 2005-2024 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 	break;
328       }
329 #endif
330 
331     case 0x00088263: /* SCI4.TDR */
332       {
333 	static int pending_exit = 0;
334 	if (pending_exit == 2)
335 	  {
336 	    step_result = RX_MAKE_EXITED(value);
337 	    longjmp (decode_jmp_buf, 1);
338 	  }
339 	else if (value == 3)
340 	  pending_exit ++;
341 	else
342 	  pending_exit = 0;
343 
344 	putchar(value);
345       }
346       break;
347 
348     default:
349       if (is_reserved_address (address))
350 	generate_access_exception ();
351     }
352 }
353 
354 void
355 mem_put_qi (int address, unsigned char value)
356 {
357   S ("<=");
358   mem_put_byte (address, value & 0xff);
359   E ();
360   COUNT (1, 1);
361 }
362 
363 #ifdef CYCLE_ACCURATE
364 static int tpu_base;
365 #endif
366 
367 void
368 mem_put_hi (int address, unsigned short value)
369 {
370   S ("<=");
371   switch (address)
372     {
373 #ifdef CYCLE_ACCURATE
374     case 0x00088126: /* TPU1.TCNT */
375       tpu_base = regs.cycle_count;
376       break;
377     case 0x00088136: /* TPU2.TCNT */
378       tpu_base = regs.cycle_count;
379       break;
380 #endif
381     default:
382       if (rx_big_endian)
383 	{
384 	  mem_put_byte (address, value >> 8);
385 	  mem_put_byte (address + 1, value & 0xff);
386 	}
387       else
388 	{
389 	  mem_put_byte (address, value & 0xff);
390 	  mem_put_byte (address + 1, value >> 8);
391 	}
392     }
393   E ();
394   COUNT (1, 2);
395 }
396 
397 void
398 mem_put_psi (int address, unsigned long value)
399 {
400   S ("<=");
401   if (rx_big_endian)
402     {
403       mem_put_byte (address, value >> 16);
404       mem_put_byte (address + 1, (value >> 8) & 0xff);
405       mem_put_byte (address + 2, value & 0xff);
406     }
407   else
408     {
409       mem_put_byte (address, value & 0xff);
410       mem_put_byte (address + 1, (value >> 8) & 0xff);
411       mem_put_byte (address + 2, value >> 16);
412     }
413   E ();
414   COUNT (1, 3);
415 }
416 
417 void
418 mem_put_si (int address, unsigned long value)
419 {
420   S ("<=");
421   if (rx_big_endian)
422     {
423       mem_put_byte (address + 0, (value >> 24) & 0xff);
424       mem_put_byte (address + 1, (value >> 16) & 0xff);
425       mem_put_byte (address + 2, (value >> 8) & 0xff);
426       mem_put_byte (address + 3, value & 0xff);
427     }
428   else
429     {
430       mem_put_byte (address + 0, value & 0xff);
431       mem_put_byte (address + 1, (value >> 8) & 0xff);
432       mem_put_byte (address + 2, (value >> 16) & 0xff);
433       mem_put_byte (address + 3, (value >> 24) & 0xff);
434     }
435   E ();
436   COUNT (1, 4);
437 }
438 
439 void
440 mem_put_blk (int address, void *bufptr_void, int nbytes)
441 {
442   unsigned char *bufptr = (unsigned char *) bufptr_void;
443 
444   S ("<=");
445   if (enable_counting)
446     mem_counters[1][1] += nbytes;
447   while (nbytes--)
448     mem_put_byte (address++, *bufptr++);
449   E ();
450 }
451 
452 unsigned char
453 mem_get_pc (int address)
454 {
455   unsigned char *m = rx_mem_ptr (address, MPA_READING);
456   COUNT (0, 0);
457   return *m;
458 }
459 
460 static unsigned char
461 mem_get_byte (unsigned int address)
462 {
463   unsigned char *m;
464 
465   S ("=>");
466   m = rx_mem_ptr (address, MPA_READING);
467   switch (address)
468     {
469     case 0x00088264: /* SCI4.SSR */
470       E();
471       return 0x04; /* transmitter empty */
472       break;
473     default:
474       if (trace)
475 	printf (" %02x%c", *m, mtypec (address));
476       if (is_reserved_address (address))
477 	generate_access_exception ();
478       break;
479     }
480   E ();
481   return *m;
482 }
483 
484 unsigned char
485 mem_get_qi (int address)
486 {
487   unsigned char rv;
488   S ("=>");
489   rv = mem_get_byte (address);
490   COUNT (0, 1);
491   E ();
492   return rv;
493 }
494 
495 unsigned short
496 mem_get_hi (int address)
497 {
498   unsigned short rv;
499   S ("=>");
500   switch (address)
501     {
502 #ifdef CYCLE_ACCURATE
503     case 0x00088126: /* TPU1.TCNT */
504       rv = (regs.cycle_count - tpu_base) >> 16;
505       break;
506     case 0x00088136: /* TPU2.TCNT */
507       rv = (regs.cycle_count - tpu_base) >> 0;
508       break;
509 #endif
510 
511     default:
512       if (rx_big_endian)
513 	{
514 	  rv = mem_get_byte (address) << 8;
515 	  rv |= mem_get_byte (address + 1);
516 	}
517       else
518 	{
519 	  rv = mem_get_byte (address);
520 	  rv |= mem_get_byte (address + 1) << 8;
521 	}
522     }
523   COUNT (0, 2);
524   E ();
525   return rv;
526 }
527 
528 unsigned long
529 mem_get_psi (int address)
530 {
531   unsigned long rv;
532   S ("=>");
533   if (rx_big_endian)
534     {
535       rv = mem_get_byte (address + 2);
536       rv |= mem_get_byte (address + 1) << 8;
537       rv |= mem_get_byte (address) << 16;
538     }
539   else
540     {
541       rv = mem_get_byte (address);
542       rv |= mem_get_byte (address + 1) << 8;
543       rv |= mem_get_byte (address + 2) << 16;
544     }
545   COUNT (0, 3);
546   E ();
547   return rv;
548 }
549 
550 unsigned long
551 mem_get_si (int address)
552 {
553   unsigned long rv;
554   S ("=>");
555   if (rx_big_endian)
556     {
557       rv = mem_get_byte (address + 3);
558       rv |= mem_get_byte (address + 2) << 8;
559       rv |= mem_get_byte (address + 1) << 16;
560       rv |= mem_get_byte (address) << 24;
561     }
562   else
563     {
564       rv = mem_get_byte (address);
565       rv |= mem_get_byte (address + 1) << 8;
566       rv |= mem_get_byte (address + 2) << 16;
567       rv |= mem_get_byte (address + 3) << 24;
568     }
569   COUNT (0, 4);
570   E ();
571   return rv;
572 }
573 
574 void
575 mem_get_blk (int address, void *bufptr_void, int nbytes)
576 {
577   char *bufptr = (char *) bufptr_void;
578 
579   S ("=>");
580   if (enable_counting)
581     mem_counters[0][1] += nbytes;
582   while (nbytes--)
583     *bufptr++ = mem_get_byte (address++);
584   E ();
585 }
586 
587 int
588 sign_ext (int v, int bits)
589 {
590   if (bits < 32)
591     {
592       v &= (1 << bits) - 1;
593       if (v & (1 << (bits - 1)))
594 	v -= (1 << bits);
595     }
596   return v;
597 }
598 
599 void
600 mem_set_content_type (int address, enum mem_content_type type)
601 {
602   unsigned char *mt = rx_mem_ptr (address, MPA_CONTENT_TYPE);
603   *mt = type;
604 }
605 
606 void
607 mem_set_content_range (int start_address, int end_address, enum mem_content_type type)
608 {
609   while (start_address < end_address)
610     {
611       int sz, ofs;
612       unsigned char *mt;
613 
614       sz = end_address - start_address;
615       ofs = start_address % L1_LEN;
616       if (sz + ofs > L1_LEN)
617 	sz = L1_LEN - ofs;
618 
619       mt = rx_mem_ptr (start_address, MPA_CONTENT_TYPE);
620       memset (mt, type, sz);
621 
622       start_address += sz;
623     }
624 }
625 
626 enum mem_content_type
627 mem_get_content_type (int address)
628 {
629   unsigned char *mt = rx_mem_ptr (address, MPA_CONTENT_TYPE);
630   return *mt;
631 }
632