Home | History | Annotate | Line # | Download | only in or1k
      1      1.1  christos /* OpenRISC simulator support code
      2  1.1.1.5  christos    Copyright (C) 2017-2025 Free Software Foundation, Inc.
      3      1.1  christos 
      4      1.1  christos    This file is part of GDB, the GNU debugger.
      5      1.1  christos 
      6      1.1  christos    This program is free software; you can redistribute it and/or modify
      7      1.1  christos    it under the terms of the GNU General Public License as published by
      8      1.1  christos    the Free Software Foundation; either version 3 of the License, or
      9      1.1  christos    (at your option) any later version.
     10      1.1  christos 
     11      1.1  christos    This program is distributed in the hope that it will be useful,
     12      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14      1.1  christos    GNU General Public License for more details.
     15      1.1  christos 
     16      1.1  christos    You should have received a copy of the GNU General Public License
     17      1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     18      1.1  christos 
     19  1.1.1.3  christos /* This must come before any other includes.  */
     20  1.1.1.3  christos #include "defs.h"
     21  1.1.1.3  christos 
     22      1.1  christos #define WANT_CPU_OR1K32BF
     23      1.1  christos #define WANT_CPU
     24      1.1  christos 
     25      1.1  christos #include "sim-main.h"
     26      1.1  christos #include "symcat.h"
     27      1.1  christos #include "cgen-ops.h"
     28      1.1  christos #include "cgen-mem.h"
     29      1.1  christos #include "cpuall.h"
     30      1.1  christos 
     31      1.1  christos #include <string.h>
     32      1.1  christos 
     33      1.1  christos int
     34  1.1.1.3  christos or1k32bf_fetch_register (sim_cpu *current_cpu, int rn, void *buf, int len)
     35      1.1  christos {
     36      1.1  christos   if (rn < 32)
     37      1.1  christos     SETTWI (buf, GET_H_GPR (rn));
     38      1.1  christos   else
     39      1.1  christos     switch (rn)
     40      1.1  christos       {
     41      1.1  christos       case PPC_REGNUM:
     42      1.1  christos 	SETTWI (buf, GET_H_SYS_PPC ());
     43      1.1  christos 	break;
     44      1.1  christos       case PC_REGNUM:
     45      1.1  christos 	SETTWI (buf, GET_H_PC ());
     46      1.1  christos 	break;
     47      1.1  christos       case SR_REGNUM:
     48      1.1  christos 	SETTWI (buf, GET_H_SYS_SR ());
     49      1.1  christos 	break;
     50      1.1  christos       default:
     51      1.1  christos 	return 0;
     52      1.1  christos       }
     53      1.1  christos   return sizeof (WI);		/* WI from arch.h */
     54      1.1  christos }
     55      1.1  christos 
     56      1.1  christos int
     57  1.1.1.3  christos or1k32bf_store_register (sim_cpu *current_cpu, int rn, const void *buf, int len)
     58      1.1  christos {
     59      1.1  christos   if (rn < 32)
     60      1.1  christos     SET_H_GPR (rn, GETTWI (buf));
     61      1.1  christos   else
     62      1.1  christos     switch (rn)
     63      1.1  christos       {
     64      1.1  christos       case PPC_REGNUM:
     65      1.1  christos 	SET_H_SYS_PPC (GETTWI (buf));
     66      1.1  christos 	break;
     67      1.1  christos       case PC_REGNUM:
     68      1.1  christos 	SET_H_PC (GETTWI (buf));
     69      1.1  christos 	break;
     70      1.1  christos       case SR_REGNUM:
     71      1.1  christos 	SET_H_SYS_SR (GETTWI (buf));
     72      1.1  christos 	break;
     73      1.1  christos       default:
     74      1.1  christos 	return 0;
     75      1.1  christos       }
     76      1.1  christos   return sizeof (WI);		/* WI from arch.h */
     77      1.1  christos }
     78      1.1  christos 
     79      1.1  christos int
     80      1.1  christos or1k32bf_model_or1200_u_exec (sim_cpu *current_cpu, const IDESC *idesc,
     81      1.1  christos 			      int unit_num, int referenced)
     82      1.1  christos {
     83      1.1  christos   return -1;
     84      1.1  christos }
     85      1.1  christos 
     86      1.1  christos int
     87      1.1  christos or1k32bf_model_or1200nd_u_exec (sim_cpu *current_cpu, const IDESC *idesc,
     88      1.1  christos 				int unit_num, int referenced)
     89      1.1  christos {
     90      1.1  christos   return -1;
     91      1.1  christos }
     92      1.1  christos 
     93      1.1  christos void
     94      1.1  christos or1k32bf_model_insn_before (sim_cpu *current_cpu, int first_p)
     95      1.1  christos {
     96      1.1  christos }
     97      1.1  christos 
     98      1.1  christos void
     99      1.1  christos or1k32bf_model_insn_after (sim_cpu *current_cpu, int last_p, int cycles)
    100      1.1  christos {
    101      1.1  christos }
    102      1.1  christos 
    103      1.1  christos USI
    104      1.1  christos or1k32bf_h_spr_get_raw (sim_cpu *current_cpu, USI addr)
    105      1.1  christos {
    106      1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
    107  1.1.1.4  christos   struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu);
    108  1.1.1.4  christos 
    109      1.1  christos   SIM_ASSERT (addr < NUM_SPR);
    110  1.1.1.4  christos   return or1k_cpu->spr[addr];
    111      1.1  christos }
    112      1.1  christos 
    113      1.1  christos void
    114      1.1  christos or1k32bf_h_spr_set_raw (sim_cpu *current_cpu, USI addr, USI val)
    115      1.1  christos {
    116      1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
    117  1.1.1.4  christos   struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu);
    118  1.1.1.4  christos 
    119      1.1  christos   SIM_ASSERT (addr < NUM_SPR);
    120  1.1.1.4  christos   or1k_cpu->spr[addr] = val;
    121      1.1  christos }
    122      1.1  christos 
    123      1.1  christos USI
    124      1.1  christos or1k32bf_h_spr_field_get_raw (sim_cpu *current_cpu, USI addr, int msb, int lsb)
    125      1.1  christos {
    126      1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
    127  1.1.1.4  christos   struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu);
    128  1.1.1.4  christos 
    129      1.1  christos   SIM_ASSERT (addr < NUM_SPR);
    130  1.1.1.4  christos   return LSEXTRACTED (or1k_cpu->spr[addr], msb, lsb);
    131      1.1  christos }
    132      1.1  christos 
    133      1.1  christos void
    134      1.1  christos or1k32bf_h_spr_field_set_raw (sim_cpu *current_cpu, USI addr, int msb, int lsb,
    135      1.1  christos 			      USI val)
    136      1.1  christos {
    137  1.1.1.4  christos   struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu);
    138  1.1.1.4  christos 
    139  1.1.1.4  christos   or1k_cpu->spr[addr] &= ~LSMASK32 (msb, lsb);
    140  1.1.1.4  christos   or1k_cpu->spr[addr] |= LSINSERTED (val, msb, lsb);
    141      1.1  christos }
    142      1.1  christos 
    143      1.1  christos /* Initialize a sim cpu object.  */
    144      1.1  christos void
    145      1.1  christos or1k_cpu_init (SIM_DESC sd, sim_cpu *current_cpu, const USI or1k_vr,
    146      1.1  christos 	       const USI or1k_upr, const USI or1k_cpucfgr)
    147      1.1  christos {
    148  1.1.1.4  christos   struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu);
    149  1.1.1.4  christos 
    150      1.1  christos   /* Set the configuration registers passed from the user.  */
    151      1.1  christos   SET_H_SYS_VR (or1k_vr);
    152      1.1  christos   SET_H_SYS_UPR (or1k_upr);
    153      1.1  christos   SET_H_SYS_CPUCFGR (or1k_cpucfgr);
    154      1.1  christos 
    155      1.1  christos #define CHECK_SPR_FIELD(GROUP, INDEX, FIELD, test) \
    156      1.1  christos   do \
    157      1.1  christos     { \
    158      1.1  christos       USI field = GET_H_##SYS##_##INDEX##_##FIELD (); \
    159      1.1  christos       if (!(test)) \
    160      1.1  christos 	sim_io_eprintf \
    161      1.1  christos 	  (sd, "WARNING: unsupported %s field in %s register: 0x%x\n", \
    162      1.1  christos 	   #FIELD, #INDEX, field); \
    163      1.1  christos     } while (0)
    164      1.1  christos 
    165      1.1  christos   /* Set flags indicating if we are in a delay slot or not.  */
    166  1.1.1.4  christos   or1k_cpu->next_delay_slot = 0;
    167  1.1.1.4  christos   or1k_cpu->delay_slot = 0;
    168      1.1  christos 
    169      1.1  christos   /* Verify any user passed fields and warn on configurations we don't
    170      1.1  christos      support.  */
    171      1.1  christos   CHECK_SPR_FIELD (SYS, UPR, UP, field == 1);
    172      1.1  christos   CHECK_SPR_FIELD (SYS, UPR, DCP, field == 0);
    173      1.1  christos   CHECK_SPR_FIELD (SYS, UPR, ICP, field == 0);
    174      1.1  christos   CHECK_SPR_FIELD (SYS, UPR, DMP, field == 0);
    175      1.1  christos   CHECK_SPR_FIELD (SYS, UPR, MP, field == 0);
    176      1.1  christos   CHECK_SPR_FIELD (SYS, UPR, IMP, field == 0);
    177      1.1  christos   CHECK_SPR_FIELD (SYS, UPR, DUP, field == 0);
    178      1.1  christos   CHECK_SPR_FIELD (SYS, UPR, PCUP, field == 0);
    179      1.1  christos   CHECK_SPR_FIELD (SYS, UPR, PICP, field == 0);
    180      1.1  christos   CHECK_SPR_FIELD (SYS, UPR, PMP, field == 0);
    181      1.1  christos   CHECK_SPR_FIELD (SYS, UPR, TTP, field == 0);
    182      1.1  christos   CHECK_SPR_FIELD (SYS, UPR, CUP, field == 0);
    183      1.1  christos 
    184      1.1  christos   CHECK_SPR_FIELD (SYS, CPUCFGR, NSGR, field == 0);
    185      1.1  christos   CHECK_SPR_FIELD (SYS, CPUCFGR, CGF, field == 0);
    186      1.1  christos   CHECK_SPR_FIELD (SYS, CPUCFGR, OB32S, field == 1);
    187      1.1  christos   CHECK_SPR_FIELD (SYS, CPUCFGR, OF32S, field == 1);
    188      1.1  christos   CHECK_SPR_FIELD (SYS, CPUCFGR, OB64S, field == 0);
    189      1.1  christos   CHECK_SPR_FIELD (SYS, CPUCFGR, OF64S, field == 0);
    190      1.1  christos   CHECK_SPR_FIELD (SYS, CPUCFGR, OV64S, field == 0);
    191      1.1  christos 
    192      1.1  christos #undef CHECK_SPR_FIELD
    193      1.1  christos 
    194      1.1  christos   /* Configure the fpu operations and mark fpu available.  */
    195      1.1  christos   cgen_init_accurate_fpu (current_cpu, CGEN_CPU_FPU (current_cpu),
    196      1.1  christos 			  or1k32bf_fpu_error);
    197      1.1  christos   SET_H_SYS_CPUCFGR_OF32S (1);
    198      1.1  christos 
    199      1.1  christos   /* Set the UPR[UP] flag, even if the user tried to unset it, as we always
    200      1.1  christos      support the Unit Present Register.  */
    201      1.1  christos   SET_H_SYS_UPR_UP (1);
    202      1.1  christos 
    203      1.1  christos   /* Set the supervisor register to indicate we are in supervisor mode and
    204      1.1  christos      set the Fixed-One bit which must always be set.  */
    205      1.1  christos   SET_H_SYS_SR (SPR_FIELD_MASK_SYS_SR_SM | SPR_FIELD_MASK_SYS_SR_FO);
    206      1.1  christos 
    207      1.1  christos   /* Clear the floating point control status register.  */
    208      1.1  christos   SET_H_SYS_FPCSR (0);
    209  1.1.1.5  christos 
    210  1.1.1.5  christos   /* Set this as the one and only core.  */
    211  1.1.1.5  christos   SET_H_SYS_NUMCORES (1);
    212  1.1.1.5  christos   SET_H_SYS_COREID (0);
    213      1.1  christos }
    214      1.1  christos 
    215      1.1  christos void
    216      1.1  christos or1k32bf_insn_before (sim_cpu *current_cpu, SEM_PC vpc, const IDESC *idesc)
    217      1.1  christos {
    218      1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
    219  1.1.1.4  christos   struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu);
    220      1.1  christos 
    221  1.1.1.4  christos   or1k_cpu->delay_slot = or1k_cpu->next_delay_slot;
    222  1.1.1.4  christos   or1k_cpu->next_delay_slot = 0;
    223      1.1  christos 
    224  1.1.1.4  christos   if (or1k_cpu->delay_slot &&
    225      1.1  christos       CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) &
    226      1.1  christos       CGEN_ATTR_MASK (CGEN_INSN_NOT_IN_DELAY_SLOT))
    227      1.1  christos     {
    228      1.1  christos       USI pc;
    229      1.1  christos #ifdef WITH_SCACHE
    230      1.1  christos       pc = vpc->argbuf.addr;
    231      1.1  christos #else
    232      1.1  christos       pc = vpc;
    233      1.1  christos #endif
    234      1.1  christos       sim_io_error (sd, "invalid instruction in a delay slot at PC 0x%08x",
    235      1.1  christos 		    pc);
    236      1.1  christos     }
    237      1.1  christos 
    238      1.1  christos }
    239      1.1  christos 
    240      1.1  christos void
    241      1.1  christos or1k32bf_insn_after (sim_cpu *current_cpu, SEM_PC vpc, const IDESC *idesc)
    242      1.1  christos {
    243      1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
    244  1.1.1.4  christos   struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu);
    245      1.1  christos   USI ppc;
    246      1.1  christos 
    247      1.1  christos #ifdef WITH_SCACHE
    248      1.1  christos   ppc = vpc->argbuf.addr;
    249      1.1  christos #else
    250      1.1  christos   ppc = vpc;
    251      1.1  christos #endif
    252      1.1  christos 
    253      1.1  christos   SET_H_SYS_PPC (ppc);
    254      1.1  christos 
    255      1.1  christos   if (!GET_H_SYS_CPUCFGR_ND () &&
    256      1.1  christos       CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) &
    257      1.1  christos       CGEN_ATTR_MASK (CGEN_INSN_DELAYED_CTI))
    258      1.1  christos     {
    259  1.1.1.4  christos       SIM_ASSERT (!or1k_cpu->delay_slot);
    260  1.1.1.4  christos       or1k_cpu->next_delay_slot = 1;
    261      1.1  christos     }
    262      1.1  christos }
    263      1.1  christos 
    264      1.1  christos void
    265      1.1  christos or1k32bf_nop (sim_cpu *current_cpu, USI uimm16)
    266      1.1  christos {
    267      1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
    268      1.1  christos 
    269      1.1  christos   switch (uimm16)
    270      1.1  christos     {
    271      1.1  christos 
    272      1.1  christos     case NOP_NOP:
    273      1.1  christos       break;
    274      1.1  christos 
    275      1.1  christos     case NOP_EXIT:
    276      1.1  christos       sim_io_printf (CPU_STATE (current_cpu), "exit(%d)\n", GET_H_GPR (3));
    277  1.1.1.4  christos       ATTRIBUTE_FALLTHROUGH;
    278      1.1  christos     case NOP_EXIT_SILENT:
    279      1.1  christos       sim_engine_halt (sd, current_cpu, NULL, CPU_PC_GET (current_cpu),
    280      1.1  christos 		       sim_exited, GET_H_GPR (3));
    281      1.1  christos       break;
    282      1.1  christos 
    283      1.1  christos     case NOP_REPORT:
    284      1.1  christos       sim_io_printf (CPU_STATE (current_cpu), "report(0x%08x);\n",
    285      1.1  christos 		     GET_H_GPR (3));
    286      1.1  christos       break;
    287      1.1  christos 
    288      1.1  christos     case NOP_PUTC:
    289      1.1  christos       sim_io_printf (CPU_STATE (current_cpu), "%c",
    290      1.1  christos 		     (char) (GET_H_GPR (3) & 0xff));
    291      1.1  christos       break;
    292      1.1  christos 
    293      1.1  christos     default:
    294      1.1  christos       sim_io_eprintf (sd, "WARNING: l.nop with unsupported code 0x%08x\n",
    295      1.1  christos 		      uimm16);
    296      1.1  christos       break;
    297      1.1  christos     }
    298      1.1  christos 
    299      1.1  christos }
    300      1.1  christos 
    301      1.1  christos /* Build an address value used for load and store instructions.  For example,
    302      1.1  christos    the instruction 'l.lws rD, I(rA)' will require to load data from the 4 byte
    303      1.1  christos    address represented by rA + I.  Here the argument base is rA, offset is I
    304      1.1  christos    and the size is the read size in bytes.  Note, OpenRISC requires that word
    305      1.1  christos    and half-word access be word and half-word aligned respectively, the check
    306      1.1  christos    for alignment is not needed here.  */
    307      1.1  christos 
    308      1.1  christos USI
    309      1.1  christos or1k32bf_make_load_store_addr (sim_cpu *current_cpu, USI base, SI offset,
    310      1.1  christos 			       int size)
    311      1.1  christos {
    312      1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
    313      1.1  christos 
    314      1.1  christos   USI addr = base + offset;
    315      1.1  christos 
    316      1.1  christos   /* If little endian load/store is enabled we adjust the byte and half-word
    317      1.1  christos      addresses to the little endian equivalent.  */
    318      1.1  christos   if (GET_H_SYS_SR_LEE ())
    319      1.1  christos     {
    320      1.1  christos       switch (size)
    321      1.1  christos 	{
    322      1.1  christos 
    323      1.1  christos 	case 4: /* We are retrieving the entire word no adjustment.  */
    324      1.1  christos 	  break;
    325      1.1  christos 
    326      1.1  christos 	case 2: /* Perform half-word adjustment 0 -> 2, 2 -> 0.  */
    327      1.1  christos 	  addr ^= 0x2;
    328      1.1  christos 	  break;
    329      1.1  christos 
    330      1.1  christos 	case 1: /* Perform byte adjustment, 0 -> 3, 2 -> 3, etc.  */
    331      1.1  christos 	  addr ^= 0x3;
    332      1.1  christos 	  break;
    333      1.1  christos 
    334      1.1  christos 	default:
    335      1.1  christos 	  SIM_ASSERT (0);
    336      1.1  christos 	  return 0;
    337      1.1  christos 	}
    338      1.1  christos     }
    339      1.1  christos 
    340      1.1  christos   return addr;
    341      1.1  christos }
    342      1.1  christos 
    343      1.1  christos /* The find first 1 instruction returns the location of the first set bit
    344      1.1  christos    in the argument register.  */
    345      1.1  christos 
    346      1.1  christos USI
    347      1.1  christos or1k32bf_ff1 (sim_cpu *current_cpu, USI val)
    348      1.1  christos {
    349      1.1  christos   USI bit;
    350      1.1  christos   USI ret;
    351      1.1  christos   for (bit = 1, ret = 1; bit; bit <<= 1, ret++)
    352      1.1  christos     {
    353      1.1  christos       if (val & bit)
    354      1.1  christos 	return ret;
    355      1.1  christos     }
    356      1.1  christos   return 0;
    357      1.1  christos }
    358      1.1  christos 
    359      1.1  christos /* The find last 1 instruction returns the location of the last set bit in
    360      1.1  christos    the argument register.  */
    361      1.1  christos 
    362      1.1  christos USI
    363      1.1  christos or1k32bf_fl1 (sim_cpu *current_cpu, USI val)
    364      1.1  christos {
    365      1.1  christos   USI bit;
    366      1.1  christos   USI ret;
    367      1.1  christos   for (bit = 1 << 31, ret = 32; bit; bit >>= 1, ret--)
    368      1.1  christos     {
    369      1.1  christos       if (val & bit)
    370      1.1  christos 	return ret;
    371      1.1  christos     }
    372      1.1  christos   return 0;
    373      1.1  christos }
    374