xref: /netbsd-src/external/gpl3/gdb/dist/sim/m32c/reg.c (revision 71f621822dbfd5073a314948bec169b7bb05f7be)
1 /* reg.c --- register set model for M32C 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 
30 int verbose = 0;
31 int trace = 0;
32 int enable_counting = 0;
33 int in_gdb = 1;
34 
35 regs_type regs;
36 int addr_mask = 0xffff;
37 int membus_mask = 0xfffff;
38 int m32c_cpu = 0;
39 int step_result;
40 unsigned int heapbottom = 0;
41 unsigned int heaptop = 0;
42 
43 char *reg_names[] = {
44   "mem",
45   "r0", "r0h", "r0l",
46   "r1", "r1h", "r1l",
47   "r2", "r2r0",
48   "r3", "r3r1",
49   "r3r1r2r0",
50   "r3r2r1r0",
51   "a0",
52   "a1", "a1a0",
53   "sb", "fb",
54   "intb", "intbl", "intbh",
55   "sp", "usp", "isp", "pc", "flags"
56 };
57 
58 int reg_bytes[] = {
59   0,
60   2, 1, 1,
61   2, 1, 1,
62   2, 4,
63   2, 4,
64   8,
65   8,
66   2,
67   2, 4,
68   2, 2,
69   2, 1, 3,
70   2, 2, 2, 3, 2
71 };
72 
73 
74 unsigned int b2mask[] = { 0, 0xff, 0xffff, 0xffffff, 0xffffffff };
75 unsigned int b2signbit[] = { 0, (1 << 7), (1 << 15), (1 << 24), (1 << 31) };
76 int b2maxsigned[] = { 0, 0x7f, 0x7fff, 0x7fffff, 0x7fffffff };
77 int b2minsigned[] = { 0, -128, -32768, -8388608, -2147483647 - 1 };
78 
79 static regs_type oldregs;
80 
81 int m32c_opcode_pc;
82 
83 void
84 init_regs (void)
85 {
86   memset (&regs, 0, sizeof (regs));
87   memset (&oldregs, 0, sizeof (oldregs));
88 }
89 
90 void
91 set_pointer_width (int bytes)
92 {
93   if (bytes == 2)
94     {
95       addr_mask = 0xffff;
96       membus_mask = 0x000fffff;
97       reg_bytes[a0] = reg_bytes[a1] = reg_bytes[sb] = reg_bytes[fb] =
98 	reg_bytes[sp] = reg_bytes[usp] = reg_bytes[isp] = 2;
99     }
100   else
101     {
102       addr_mask = 0xffffff;
103       membus_mask = 0x00ffffff;
104       reg_bytes[a0] = reg_bytes[a1] = reg_bytes[sb] = reg_bytes[fb] =
105 	reg_bytes[sp] = reg_bytes[usp] = reg_bytes[isp] = 3;
106     }
107 }
108 
109 void
110 m32c_set_cpu (int cpu)
111 {
112   switch (cpu)
113     {
114     case CPU_R8C:
115     case CPU_M16C:
116       set_pointer_width (2);
117       decode_opcode = decode_r8c;
118       break;
119     case CPU_M32CM:
120     case CPU_M32C:
121       set_pointer_width (3);
122       decode_opcode = decode_m32c;
123       break;
124     default:
125       abort ();
126     }
127   m32c_cpu = cpu;
128 }
129 
130 static unsigned int
131 get_reg_i (reg_id id)
132 {
133   reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0);
134 
135   switch (id)
136     {
137     case r0:
138       return b->r_r0;
139     case r0h:
140       return b->r_r0 >> 8;
141     case r0l:
142       return b->r_r0 & 0xff;
143     case r1:
144       return b->r_r1;
145     case r1h:
146       return b->r_r1 >> 8;
147     case r1l:
148       return b->r_r1 & 0xff;
149     case r2:
150       return b->r_r2;
151     case r2r0:
152       return b->r_r2 * 65536 + b->r_r0;
153     case r3:
154       return b->r_r3;
155     case r3r1:
156       return b->r_r3 * 65536 + b->r_r1;
157 
158     case a0:
159       return b->r_a0 & addr_mask;
160     case a1:
161       return b->r_a1 & addr_mask;
162     case a1a0:
163       return (b->r_a1 & 0xffff) * 65536 | (b->r_a0 & 0xffff);
164 
165     case sb:
166       return b->r_sb & addr_mask;
167     case fb:
168       return b->r_fb & addr_mask;
169 
170     case intb:
171       return regs.r_intbh * 65536 + regs.r_intbl;
172     case intbl:
173       return regs.r_intbl;
174     case intbh:
175       return regs.r_intbh;
176 
177     case sp:
178       return ((regs.r_flags & FLAGBIT_U) ? regs.r_usp : regs.
179 	      r_isp) & addr_mask;
180     case usp:
181       return regs.r_usp & addr_mask;
182     case isp:
183       return regs.r_isp & addr_mask;
184 
185     case pc:
186       return regs.r_pc & membus_mask;
187     case flags:
188       return regs.r_flags;
189     default:
190       abort ();
191     }
192 }
193 
194 unsigned int
195 get_reg (reg_id id)
196 {
197   unsigned int rv = get_reg_i (id);
198   if (trace > ((id != pc && id != fb && id != sp) ? 0 : 1))
199     printf ("get_reg (%s) = %0*x\n", reg_names[id], reg_bytes[id] * 2, rv);
200   return rv;
201 }
202 
203 DI
204 get_reg_ll (reg_id id)
205 {
206   reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0);
207 
208   switch (id)
209     {
210     case r3r1r2r0:
211       return ((DI) b->r_r3 << 48
212 	      | (DI) b->r_r1 << 32 | (DI) b->r_r2 << 16 | (DI) b->r_r0);
213     case r3r2r1r0:
214       return ((DI) b->r_r3 << 48
215 	      | (DI) b->r_r2 << 32 | (DI) b->r_r1 << 16 | (DI) b->r_r0);
216     default:
217       return get_reg (id);
218     }
219 }
220 
221 static int highest_sp = 0, lowest_sp = 0xffffff;
222 
223 void
224 stack_heap_stats (void)
225 {
226   printf ("heap:  %08x - %08x (%d bytes)\n", heapbottom, heaptop,
227 	  heaptop - heapbottom);
228   printf ("stack: %08x - %08x (%d bytes)\n", lowest_sp, highest_sp,
229 	  highest_sp - lowest_sp);
230 }
231 
232 void
233 put_reg (reg_id id, unsigned int v)
234 {
235   reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0);
236 
237   if (trace > ((id != pc) ? 0 : 1))
238     printf ("put_reg (%s) = %0*x\n", reg_names[id], reg_bytes[id] * 2, v);
239 
240   switch (id)
241     {
242     case r0:
243       b->r_r0 = v;
244       break;
245     case r0h:
246       b->r_r0 = (b->r_r0 & 0xff) | (v << 8);
247       break;
248     case r0l:
249       b->r_r0 = (b->r_r0 & 0xff00) | (v & 0xff);
250       break;
251     case r1:
252       b->r_r1 = v;
253       break;
254     case r1h:
255       b->r_r1 = (b->r_r1 & 0xff) | (v << 8);
256       break;
257     case r1l:
258       b->r_r1 = (b->r_r1 & 0xff00) | (v & 0xff);
259       break;
260     case r2:
261       b->r_r2 = v;
262       break;
263     case r2r0:
264       b->r_r0 = v & 0xffff;
265       b->r_r2 = v >> 16;
266       break;
267     case r3:
268       b->r_r3 = v;
269       break;
270     case r3r1:
271       b->r_r1 = v & 0xffff;
272       b->r_r3 = v >> 16;
273       break;
274 
275     case a0:
276       b->r_a0 = v & addr_mask;
277       break;
278     case a1:
279       b->r_a1 = v & addr_mask;
280       break;
281     case a1a0:
282       b->r_a0 = v & 0xffff;
283       b->r_a1 = v >> 16;
284       break;
285 
286     case sb:
287       b->r_sb = v & addr_mask;
288       break;
289     case fb:
290       b->r_fb = v & addr_mask;
291       break;
292 
293     case intb:
294       regs.r_intbl = v & 0xffff;
295       regs.r_intbh = v >> 16;
296       break;
297     case intbl:
298       regs.r_intbl = v & 0xffff;
299       break;
300     case intbh:
301       regs.r_intbh = v & 0xff;
302       break;
303 
304     case sp:
305       {
306 	SI *spp;
307 	if (regs.r_flags & FLAGBIT_U)
308 	  spp = &regs.r_usp;
309 	else
310 	  spp = &regs.r_isp;
311 	*spp = v & addr_mask;
312 	if (*spp < heaptop)
313 	  {
314 	    printf ("collision: pc %08lx heap %08x stack %08lx\n", regs.r_pc,
315 		    heaptop, *spp);
316 	    exit (1);
317 	  }
318 	if (*spp < lowest_sp)
319 	  lowest_sp = *spp;
320 	if (*spp > highest_sp)
321 	  highest_sp = *spp;
322 	break;
323       }
324     case usp:
325       regs.r_usp = v & addr_mask;
326       break;
327     case isp:
328       regs.r_isp = v & addr_mask;
329       break;
330 
331     case pc:
332       regs.r_pc = v & membus_mask;
333       break;
334     case flags:
335       regs.r_flags = v;
336       break;
337     default:
338       abort ();
339     }
340 }
341 
342 int
343 condition_true (int cond_id)
344 {
345   int f;
346   if (A16)
347     {
348       static const char *cond_name[] = {
349 	"C", "C&!Z", "Z", "S",
350 	"!C", "!(C&!Z)", "!Z", "!S",
351 	"(S^O)|Z", "O", "!(S^O)", "unk",
352 	"!((S^O)|Z)", "!O", "S^O", "unk"
353       };
354       switch (cond_id & 15)
355 	{
356 	case 0:
357 	  f = FLAG_C;
358 	  break;		/* GEU/C */
359 	case 1:
360 	  f = FLAG_C & !FLAG_Z;
361 	  break;		/* GTU */
362 	case 2:
363 	  f = FLAG_Z;
364 	  break;		/* EQ/Z */
365 	case 3:
366 	  f = FLAG_S;
367 	  break;		/* N */
368 	case 4:
369 	  f = !FLAG_C;
370 	  break;		/* LTU/NC */
371 	case 5:
372 	  f = !(FLAG_C & !FLAG_Z);
373 	  break;		/* LEU */
374 	case 6:
375 	  f = !FLAG_Z;
376 	  break;		/* NE/NZ */
377 	case 7:
378 	  f = !FLAG_S;
379 	  break;		/* PZ */
380 
381 	case 8:
382 	  f = (FLAG_S ^ FLAG_O) | FLAG_Z;
383 	  break;		/* LE */
384 	case 9:
385 	  f = FLAG_O;
386 	  break;		/* O */
387 	case 10:
388 	  f = !(FLAG_S ^ FLAG_O);
389 	  break;		/* GE */
390 	case 12:
391 	  f = !((FLAG_S ^ FLAG_O) | FLAG_Z);
392 	  break;		/* GT */
393 	case 13:
394 	  f = !FLAG_O;
395 	  break;		/* NO */
396 	case 14:
397 	  f = FLAG_S ^ FLAG_O;
398 	  break;		/* LT */
399 
400 	default:
401 	  f = 0;
402 	  break;
403 	}
404       if (trace)
405 	printf ("cond[%d] %s = %s\n", cond_id, cond_name[cond_id & 15],
406 		f ? "true" : "false");
407     }
408   else
409     {
410       static const char *cond_name[] = {
411 	"!C", "LEU", "!Z", "PZ",
412 	"!O", "GT", "GE", "?",
413 	"C", "GTU", "Z", "N",
414 	"O", "LE", "LT", "!?"
415       };
416       switch (cond_id & 15)
417 	{
418 	case 0:
419 	  f = !FLAG_C;
420 	  break;		/* LTU/NC */
421 	case 1:
422 	  f = !(FLAG_C & !FLAG_Z);
423 	  break;		/* LEU */
424 	case 2:
425 	  f = !FLAG_Z;
426 	  break;		/* NE/NZ */
427 	case 3:
428 	  f = !FLAG_S;
429 	  break;		/* PZ */
430 
431 	case 4:
432 	  f = !FLAG_O;
433 	  break;		/* NO */
434 	case 5:
435 	  f = !((FLAG_S ^ FLAG_O) | FLAG_Z);
436 	  break;		/* GT */
437 	case 6:
438 	  f = !(FLAG_S ^ FLAG_O);
439 	  break;		/* GE */
440 
441 	case 8:
442 	  f = FLAG_C;
443 	  break;		/* GEU/C */
444 	case 9:
445 	  f = FLAG_C & !FLAG_Z;
446 	  break;		/* GTU */
447 	case 10:
448 	  f = FLAG_Z;
449 	  break;		/* EQ/Z */
450 	case 11:
451 	  f = FLAG_S;
452 	  break;		/* N */
453 
454 	case 12:
455 	  f = FLAG_O;
456 	  break;		/* O */
457 	case 13:
458 	  f = (FLAG_S ^ FLAG_O) | FLAG_Z;
459 	  break;		/* LE */
460 	case 14:
461 	  f = FLAG_S ^ FLAG_O;
462 	  break;		/* LT */
463 
464 	default:
465 	  f = 0;
466 	  break;
467 	}
468       if (trace)
469 	printf ("cond[%d] %s = %s\n", cond_id, cond_name[cond_id & 15],
470 		f ? "true" : "false");
471     }
472   return f;
473 }
474 
475 void
476 set_flags (int mask, int newbits)
477 {
478   int i;
479   regs.r_flags &= ~mask;
480   regs.r_flags |= newbits & mask;
481   if (trace)
482     {
483       printf ("flags now \033[32m %d", (regs.r_flags >> (A16 ? 8 : 12)) & 7);
484       for (i = 7; i >= 0; i--)
485 	if (regs.r_flags & (1 << i))
486 	  putchar ("CDZSBOIU"[i]);
487 	else
488 	  putchar ('-');
489       printf ("\033[0m\n");
490     }
491 }
492 
493 void
494 set_oszc (int value, int b, int c)
495 {
496   int mask = b2mask[b];
497   int f = 0;
498 
499   if (c)
500     f |= FLAGBIT_C;
501   if ((value & mask) == 0)
502     f |= FLAGBIT_Z;
503   if (value & b2signbit[b])
504     f |= FLAGBIT_S;
505   if ((value > b2maxsigned[b]) || (value < b2minsigned[b]))
506     f |= FLAGBIT_O;
507   set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O | FLAGBIT_C, f);
508 }
509 
510 void
511 set_szc (int value, int b, int c)
512 {
513   int mask = b2mask[b];
514   int f = 0;
515 
516   if (c)
517     f |= FLAGBIT_C;
518   if ((value & mask) == 0)
519     f |= FLAGBIT_Z;
520   if (value & b2signbit[b])
521     f |= FLAGBIT_S;
522   set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_C, f);
523 }
524 
525 void
526 set_osz (int value, int b)
527 {
528   int mask = b2mask[b];
529   int f = 0;
530 
531   if ((value & mask) == 0)
532     f |= FLAGBIT_Z;
533   if (value & b2signbit[b])
534     f |= FLAGBIT_S;
535   if (value & ~mask && (value & ~mask) != ~mask)
536     f |= FLAGBIT_O;
537   set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, f);
538 }
539 
540 void
541 set_sz (int value, int b)
542 {
543   int mask = b2mask[b];
544   int f = 0;
545 
546   if ((value & mask) == 0)
547     f |= FLAGBIT_Z;
548   if (value & b2signbit[b])
549     f |= FLAGBIT_S;
550   set_flags (FLAGBIT_Z | FLAGBIT_S, f);
551 }
552 
553 void
554 set_zc (int z, int c)
555 {
556   set_flags (FLAGBIT_C | FLAGBIT_Z,
557 	     (c ? FLAGBIT_C : 0) | (z ? FLAGBIT_Z : 0));
558 }
559 
560 void
561 set_c (int c)
562 {
563   set_flags (FLAGBIT_C, c ? FLAGBIT_C : 0);
564 }
565 
566 void
567 put_reg_ll (reg_id id, DI v)
568 {
569   reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0);
570 
571   switch (id)
572     {
573     case r3r1r2r0:
574       b->r_r3 = v >> 48;
575       b->r_r1 = v >> 32;
576       b->r_r2 = v >> 16;
577       b->r_r0 = v;
578       break;
579     case r3r2r1r0:
580       b->r_r3 = v >> 48;
581       b->r_r2 = v >> 32;
582       b->r_r1 = v >> 16;
583       b->r_r0 = v;
584       break;
585     default:
586       put_reg (id, v);
587     }
588 }
589 
590 static void
591 print_flags (int f)
592 {
593   int i;
594   static char fn[] = "CDZSBOIU";
595   printf ("%d.", (f >> 12) & 7);
596   for (i = 7; i >= 0; i--)
597     if (f & (1 << i))
598       putchar (fn[i]);
599 }
600 
601 #define TRC(f,n, id) \
602   if (oldregs.f != regs.f) \
603     { \
604       printf("  %s %0*x:%0*x", n, \
605 	     reg_bytes[id]*2, (unsigned int)oldregs.f, \
606 	     reg_bytes[id]*2, (unsigned int)regs.f); \
607       oldregs.f = regs.f; \
608     }
609 
610 void
611 trace_register_changes (void)
612 {
613   if (!trace)
614     return;
615   printf ("\033[36mREGS:");
616   TRC (r[0].r_r0, "r0", r0);
617   TRC (r[0].r_r1, "r1", r1);
618   TRC (r[0].r_r2, "r2", r2);
619   TRC (r[0].r_r3, "r3", r3);
620   TRC (r[0].r_a0, "a0", a0);
621   TRC (r[0].r_a1, "a1", a1);
622   TRC (r[0].r_sb, "sb", sb);
623   TRC (r[0].r_fb, "fb", fb);
624   TRC (r[1].r_r0, "r0'", r0);
625   TRC (r[1].r_r1, "r1'", r1);
626   TRC (r[1].r_r2, "r2'", r2);
627   TRC (r[1].r_r3, "r3'", r3);
628   TRC (r[1].r_a0, "a0'", a0);
629   TRC (r[1].r_a1, "a1'", a1);
630   TRC (r[1].r_sb, "sb'", sb);
631   TRC (r[1].r_fb, "fb'", fb);
632   TRC (r_intbh, "intbh", intbh);
633   TRC (r_intbl, "intbl", intbl);
634   TRC (r_usp, "usp", usp);
635   TRC (r_isp, "isp", isp);
636   TRC (r_pc, "pc", pc);
637   if (oldregs.r_flags != regs.r_flags)
638     {
639       printf ("  flags ");
640       print_flags (oldregs.r_flags);
641       printf (":");
642       print_flags (regs.r_flags);
643     }
644   printf ("\033[0m\n");
645 }
646 
647 #define DRC(f, n, id) \
648   printf("  %-3s %0*x", n,			       \
649 	 reg_bytes[id]*2, (unsigned int)regs.f);       \
650 
651 void
652 m32c_dump_all_registers (void)
653 {
654   printf ("\033[36mREGS:");
655   DRC (r[0].r_r0, "r0", r0);
656   DRC (r[0].r_r1, "r1", r1);
657   DRC (r[0].r_r2, "r2", r2);
658   DRC (r[0].r_r3, "r3", r3);
659   DRC (r[0].r_a0, "a0", a0);
660   DRC (r[0].r_a1, "a1", a1);
661   DRC (r[0].r_sb, "sb", sb);
662   DRC (r[0].r_fb, "fb", fb);
663   printf ("\n     ");
664   DRC (r[1].r_r0, "r0'", r0);
665   DRC (r[1].r_r1, "r1'", r1);
666   DRC (r[1].r_r2, "r2'", r2);
667   DRC (r[1].r_r3, "r3'", r3);
668   DRC (r[1].r_a0, "a0'", a0);
669   DRC (r[1].r_a1, "a1'", a1);
670   DRC (r[1].r_sb, "sb'", sb);
671   DRC (r[1].r_fb, "fb'", fb);
672   printf ("     \n");
673   DRC (r_intbh, "intbh", intbh);
674   DRC (r_intbl, "intbl", intbl);
675   DRC (r_usp, "usp", usp);
676   DRC (r_isp, "isp", isp);
677   DRC (r_pc, "pc", pc);
678   printf ("  flags ");
679   print_flags (regs.r_flags);
680   printf ("\033[0m\n");
681   /*sim_disasm_one (); */
682 }
683