Home | History | Annotate | Line # | Download | only in m32c
reg.c revision 1.9.2.1
      1 /* reg.c --- register set model for M32C 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 #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