xref: /netbsd-src/external/gpl3/gdb/dist/sim/rx/reg.c (revision 1f4e7eb9e5e045e008f1894823a8e4e6c9f46890)
1 /* reg.c --- register set model 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 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "cpu.h"
29 #include "bfd.h"
30 #include "trace.h"
31 
32 int verbose = 0;
33 int trace = 0;
34 int enable_counting = 0;
35 
36 int rx_in_gdb = 1;
37 
38 int rx_flagmask;
39 int rx_flagand;
40 int rx_flagor;
41 
42 int rx_big_endian;
43 regs_type regs;
44 int step_result;
45 unsigned int heapbottom = 0;
46 unsigned int heaptop = 0;
47 
48 char *reg_names[] = {
49   /* general registers */
50   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
51   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
52   /* control register */
53   "psw", "pc", "usp", "fpsw", "RES", "RES", "RES", "RES",
54   "bpsw", "bpc", "isp", "fintv", "intb", "RES", "RES", "RES",
55   "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES",
56   "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES",
57   "temp", "acc", "acchi", "accmi", "acclo"
58 };
59 
60 unsigned int b2mask[] = { 0, 0xff, 0xffff, 0xffffff, 0xffffffff };
61 unsigned int b2signbit[] = { 0, (1 << 7), (1 << 15), (1 << 24), (1 << 31) };
62 int b2maxsigned[] = { 0, 0x7f, 0x7fff, 0x7fffff, 0x7fffffff };
63 int b2minsigned[] = { 0, -128, -32768, -8388608, -2147483647 - 1 };
64 
65 static regs_type oldregs;
66 
67 void
68 init_regs (void)
69 {
70   memset (&regs, 0, sizeof (regs));
71   memset (&oldregs, 0, sizeof (oldregs));
72 
73 #ifdef CYCLE_ACCURATE
74   regs.rt = -1;
75   oldregs.rt = -1;
76 #endif
77 }
78 
79 static unsigned int
80 get_reg_i (int id)
81 {
82   if (id == 0)
83     return regs.r_psw & FLAGBIT_U ? regs.r_usp : regs.r_isp;
84 
85   if (id >= 1 && id <= 15)
86     return regs.r[id];
87 
88   switch (id)
89     {
90     case psw:
91       return regs.r_psw;
92     case fpsw:
93       return regs.r_fpsw;
94     case isp:
95       return regs.r_isp;
96     case usp:
97       return regs.r_usp;
98     case bpc:
99       return regs.r_bpc;
100     case bpsw:
101       return regs.r_bpsw;
102     case fintv:
103       return regs.r_fintv;
104     case intb:
105       return regs.r_intb;
106     case pc:
107       return regs.r_pc;
108     case r_temp_idx:
109       return regs.r_temp;
110     case acchi:
111       return (SI)(regs.r_acc >> 32);
112     case accmi:
113       return (SI)(regs.r_acc >> 16);
114     case acclo:
115       return (SI)regs.r_acc;
116     }
117   abort();
118 }
119 
120 unsigned int
121 get_reg (int id)
122 {
123   unsigned int rv = get_reg_i (id);
124   if (trace > ((id != pc && id != sp) ? 0 : 1))
125     printf ("get_reg (%s) = %08x\n", reg_names[id], rv);
126   return rv;
127 }
128 
129 static unsigned long long
130 get_reg64_i (int id)
131 {
132   switch (id)
133     {
134     case acc64:
135       return regs.r_acc;
136     default:
137       abort ();
138     }
139 }
140 
141 unsigned long long
142 get_reg64 (int id)
143 {
144   unsigned long long rv = get_reg64_i (id);
145   if (trace > ((id != pc && id != sp) ? 0 : 1))
146     printf ("get_reg (%s) = %016llx\n", reg_names[id], rv);
147   return rv;
148 }
149 
150 static int highest_sp = 0, lowest_sp = 0xffffff;
151 
152 void
153 stack_heap_stats (void)
154 {
155   if (heapbottom < heaptop)
156     printf ("heap:  %08x - %08x (%d bytes)\n", heapbottom, heaptop,
157 	    heaptop - heapbottom);
158   if (lowest_sp < highest_sp)
159     printf ("stack: %08x - %08x (%d bytes)\n", lowest_sp, highest_sp,
160 	    highest_sp - lowest_sp);
161 }
162 
163 void
164 put_reg (int id, unsigned int v)
165 {
166   if (trace > ((id != pc) ? 0 : 1))
167     printf ("put_reg (%s) = %08x\n", reg_names[id], v);
168 
169 
170   switch (id)
171     {
172     case psw:
173       regs.r_psw = v;
174       break;
175     case fpsw:
176       {
177 	SI anded;
178 	/* This is an odd one - The Cx flags are AND'd, and the FS flag
179 	   is synthetic.  */
180 	anded = regs.r_fpsw & v;
181 	anded |= ~ FPSWBITS_CMASK;
182 	regs.r_fpsw = v & anded;
183 	if (regs.r_fpsw & FPSWBITS_FMASK)
184 	  regs.r_fpsw |= FPSWBITS_FSUM;
185 	else
186 	  regs.r_fpsw &= ~FPSWBITS_FSUM;
187       }
188       break;
189     case isp:
190       regs.r_isp = v;
191       break;
192     case usp:
193       regs.r_usp = v;
194       break;
195     case bpc:
196       regs.r_bpc = v;
197       break;
198     case bpsw:
199       regs.r_bpsw = v;
200       break;
201     case fintv:
202       regs.r_fintv = v;
203       break;
204     case intb:
205       regs.r_intb = v;
206       break;
207     case pc:
208       regs.r_pc = v;
209       break;
210 
211     case acchi:
212       regs.r_acc = (regs.r_acc & 0xffffffffULL) | ((DI)v << 32);
213       break;
214     case accmi:
215       regs.r_acc = (regs.r_acc & ~0xffffffff0000ULL) | ((DI)v << 16);
216       break;
217     case acclo:
218       regs.r_acc = (regs.r_acc & ~0xffffffffULL) | ((DI)v);
219       break;
220 
221     case 0: /* Stack pointer is "in" R0.  */
222       {
223 	if (v < heaptop)
224 	  {
225 	    unsigned int line;
226 	    const char * dummy;
227 	    const char * fname = NULL;
228 
229 	    sim_get_current_source_location (& dummy, & fname, &line);
230 
231 	    /* The setjmp and longjmp functions play tricks with the stack pointer.  */
232 	    if (fname == NULL
233 		|| (strcmp (fname, "_setjmp") != 0
234 		    && strcmp (fname, "_longjmp") != 0))
235 	      {
236 		printf ("collision in %s: pc %08x heap %08x stack %08x\n",
237 			fname, (unsigned int) regs.r_pc, heaptop, v);
238 		exit (1);
239 	      }
240 	  }
241 	else
242 	  {
243 	    if (v < lowest_sp)
244 	      lowest_sp = v;
245 	    if (v > highest_sp)
246 	      highest_sp = v;
247 	  }
248 
249 	if (regs.r_psw & FLAGBIT_U)
250 	  regs.r_usp = v;
251 	else
252 	  regs.r_isp = v;
253 	break;
254       }
255 
256     default:
257       if (id >= 1 && id <= 15)
258 	regs.r[id] = v;
259       else
260 	abort ();
261     }
262 }
263 
264 void
265 put_reg64 (int id, unsigned long long v)
266 {
267   if (trace > ((id != pc) ? 0 : 1))
268     printf ("put_reg (%s) = %016llx\n", reg_names[id], v);
269 
270   switch (id)
271     {
272     case acc64:
273       regs.r_acc = v;
274       break;
275     default:
276       abort ();
277     }
278 }
279 
280 int
281 condition_true (int cond_id)
282 {
283   int f;
284 
285   static const char *cond_name[] = {
286     "Z",
287     "!Z",
288     "C",
289     "!C",
290     "C&!Z",
291     "!(C&!Z)",
292     "!S",
293     "S",
294     "!(S^O)",
295     "S^O",
296     "!((S^O)|Z)",
297     "(S^O)|Z",
298     "O",
299     "!O",
300     "always",
301     "never"
302   };
303   switch (cond_id & 15)
304     {
305     case 0:
306       f = FLAG_Z;
307       break;		/* EQ/Z */
308     case 1:
309       f = !FLAG_Z;
310       break;		/* NE/NZ */
311     case 2:
312       f = FLAG_C;
313       break;		/* GEU/C */
314     case 3:
315       f = !FLAG_C;
316       break;		/* LTU/NC */
317     case 4:
318       f = FLAG_C & !FLAG_Z;
319       break;		/* GTU */
320     case 5:
321       f = !(FLAG_C & !FLAG_Z);
322       break;		/* LEU */
323     case 6:
324       f = !FLAG_S;
325       break;		/* PZ */
326     case 7:
327       f = FLAG_S;
328       break;		/* N */
329 
330     case 8:
331       f = !(FLAG_S ^ FLAG_O);
332       break;		/* GE */
333     case 9:
334       f = FLAG_S ^ FLAG_O;
335       break;		/* LT */
336     case 10:
337       f = !((FLAG_S ^ FLAG_O) | FLAG_Z);
338       break;		/* GT */
339     case 11:
340       f = (FLAG_S ^ FLAG_O) | FLAG_Z;
341       break;		/* LE */
342     case 12:
343       f = FLAG_O;
344       break;		/* O */
345     case 13:
346       f = !FLAG_O;
347       break;		/* NO */
348     case 14:
349       f = 1;		/* always */
350       break;
351     default:
352       f = 0;		/* never */
353       break;
354     }
355   if (trace && ((cond_id & 15) != 14))
356     printf ("cond[%d] %s = %s\n", cond_id, cond_name[cond_id & 15],
357 	    f ? "true" : "false");
358   return f;
359 }
360 
361 void
362 set_flags (int mask, int newbits)
363 {
364   regs.r_psw &= rx_flagand;
365   regs.r_psw |= rx_flagor;
366   regs.r_psw |= (newbits & mask & rx_flagmask);
367 
368   if (trace)
369     {
370       int i;
371       printf ("flags now \033[32m %d", (int)((regs.r_psw >> 24) & 7));
372       for (i = 17; i >= 0; i--)
373 	if (0x3000f & (1 << i))
374 	  {
375 	    if (regs.r_psw & (1 << i))
376 	      putchar ("CZSO------------IU"[i]);
377 	    else
378 	      putchar ('-');
379 	  }
380       printf ("\033[0m\n");
381     }
382 }
383 
384 void
385 set_oszc (long long value, int b, int c)
386 {
387   unsigned int mask = b2mask[b];
388   int f = 0;
389 
390   if (c)
391     f |= FLAGBIT_C;
392   if ((value & mask) == 0)
393     f |= FLAGBIT_Z;
394   if (value & b2signbit[b])
395     f |= FLAGBIT_S;
396   if ((value > b2maxsigned[b]) || (value < b2minsigned[b]))
397     f |= FLAGBIT_O;
398   set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O | FLAGBIT_C, f);
399 }
400 
401 void
402 set_szc (long long value, int b, int c)
403 {
404   unsigned int mask = b2mask[b];
405   int f = 0;
406 
407   if (c)
408     f |= FLAGBIT_C;
409   if ((value & mask) == 0)
410     f |= FLAGBIT_Z;
411   if (value & b2signbit[b])
412     f |= FLAGBIT_S;
413   set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_C, f);
414 }
415 
416 void
417 set_osz (long long value, int b)
418 {
419   unsigned int mask = b2mask[b];
420   int f = 0;
421 
422   if ((value & mask) == 0)
423     f |= FLAGBIT_Z;
424   if (value & b2signbit[b])
425     f |= FLAGBIT_S;
426   if ((value > b2maxsigned[b]) || (value < b2minsigned[b]))
427     f |= FLAGBIT_O;
428   set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, f);
429 }
430 
431 void
432 set_sz (long long value, int b)
433 {
434   unsigned int mask = b2mask[b];
435   int f = 0;
436 
437   if ((value & mask) == 0)
438     f |= FLAGBIT_Z;
439   if (value & b2signbit[b])
440     f |= FLAGBIT_S;
441   set_flags (FLAGBIT_Z | FLAGBIT_S, f);
442 }
443 
444 void
445 set_zc (int z, int c)
446 {
447   set_flags (FLAGBIT_C | FLAGBIT_Z,
448 	     (c ? FLAGBIT_C : 0) | (z ? FLAGBIT_Z : 0));
449 }
450 
451 void
452 set_c (int c)
453 {
454   set_flags (FLAGBIT_C, c ? FLAGBIT_C : 0);
455 }
456 
457 static char *
458 psw2str(int rpsw)
459 {
460   static char buf[10];
461   char *bp = buf;
462   int i, ipl;
463 
464   ipl = (rpsw & FLAGBITS_IPL) >> FLAGSHIFT_IPL;
465   if (ipl > 9)
466     {
467       *bp++ = (ipl / 10) + '0';
468       ipl %= 10;
469     }
470   *bp++ = ipl + '0';
471   for (i = 20; i >= 0; i--)
472     if (0x13000f & (1 << i))
473       {
474 	if (rpsw & (1 << i))
475 	  *bp++ = "CZSO------------IU--P"[i];
476 	else
477 	  *bp++ = '-';
478       }
479   *bp = 0;
480   return buf;
481 }
482 
483 static char *
484 fpsw2str(int rpsw)
485 {
486   static char buf[100];
487   char *bp = buf;
488   int i;	/*   ---+---+---+---+---+---+---+---+ */
489   const char s1[] = "FFFFFF-----------EEEEE-DCCCCCCRR";
490   const char s2[] = "SXUZOV-----------XUZOV-NEXUZOV01";
491   const char rm[4][3] = { "RC", "RZ", "RP", "RN" };
492 
493   for (i = 31; i >= 0; i--)
494     if (0xfc007dfc & (1 << i))
495       {
496 	if (rpsw & (1 << i))
497 	  {
498 	    if (bp > buf)
499 	      *bp++ = '.';
500 	    *bp++ = s1[31-i];
501 	    *bp++ = s2[31-i];
502 	  }
503       }
504   if (bp > buf)
505     *bp++ = '.';
506   strcpy (bp, rm[rpsw&3]);
507   return buf;
508 }
509 
510 #define TRC(f,n) \
511   if (oldregs.f != regs.f) \
512     { \
513       if (tag) { printf ("%s", tag); tag = 0; }  \
514       printf("  %s %08x:%08x", n, \
515 	     (unsigned int)oldregs.f, \
516 	     (unsigned int)regs.f); \
517       oldregs.f = regs.f; \
518     }
519 
520 void
521 trace_register_changes (void)
522 {
523   char *tag = "\033[36mREGS:";
524   int i;
525 
526   if (!trace)
527     return;
528   for (i=1; i<16; i++)
529     TRC (r[i], reg_names[i]);
530   TRC (r_intb, "intb");
531   TRC (r_usp, "usp");
532   TRC (r_isp, "isp");
533   if (oldregs.r_psw != regs.r_psw)
534     {
535       if (tag) { printf ("%s", tag); tag = 0; }
536       printf("  psw %s:", psw2str(oldregs.r_psw));
537       printf("%s", psw2str(regs.r_psw));
538       oldregs.r_psw = regs.r_psw;
539     }
540 
541   if (oldregs.r_fpsw != regs.r_fpsw)
542     {
543       if (tag) { printf ("%s", tag); tag = 0; }
544       printf("  fpsw %s:", fpsw2str(oldregs.r_fpsw));
545       printf("%s", fpsw2str(regs.r_fpsw));
546       oldregs.r_fpsw = regs.r_fpsw;
547     }
548 
549   if (oldregs.r_acc != regs.r_acc)
550     {
551       if (tag) { printf ("%s", tag); tag = 0; }
552       printf("  acc %016" PRIx64 ":", oldregs.r_acc);
553       printf("%016" PRIx64, regs.r_acc);
554       oldregs.r_acc = regs.r_acc;
555     }
556 
557   if (tag == 0)
558     printf ("\033[0m\n");
559 }
560