Home | History | Annotate | Line # | Download | only in or1k
      1      1.1  christos /* OpenRISC simulator support code
      2  1.1.1.4  christos    Copyright (C) 2017-2024 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  christos }
    210      1.1  christos 
    211      1.1  christos void
    212      1.1  christos or1k32bf_insn_before (sim_cpu *current_cpu, SEM_PC vpc, const IDESC *idesc)
    213      1.1  christos {
    214      1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
    215  1.1.1.4  christos   struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu);
    216      1.1  christos 
    217  1.1.1.4  christos   or1k_cpu->delay_slot = or1k_cpu->next_delay_slot;
    218  1.1.1.4  christos   or1k_cpu->next_delay_slot = 0;
    219      1.1  christos 
    220  1.1.1.4  christos   if (or1k_cpu->delay_slot &&
    221      1.1  christos       CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) &
    222      1.1  christos       CGEN_ATTR_MASK (CGEN_INSN_NOT_IN_DELAY_SLOT))
    223      1.1  christos     {
    224      1.1  christos       USI pc;
    225      1.1  christos #ifdef WITH_SCACHE
    226      1.1  christos       pc = vpc->argbuf.addr;
    227      1.1  christos #else
    228      1.1  christos       pc = vpc;
    229      1.1  christos #endif
    230      1.1  christos       sim_io_error (sd, "invalid instruction in a delay slot at PC 0x%08x",
    231      1.1  christos 		    pc);
    232      1.1  christos     }
    233      1.1  christos 
    234      1.1  christos }
    235      1.1  christos 
    236      1.1  christos void
    237      1.1  christos or1k32bf_insn_after (sim_cpu *current_cpu, SEM_PC vpc, const IDESC *idesc)
    238      1.1  christos {
    239      1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
    240  1.1.1.4  christos   struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu);
    241      1.1  christos   USI ppc;
    242      1.1  christos 
    243      1.1  christos #ifdef WITH_SCACHE
    244      1.1  christos   ppc = vpc->argbuf.addr;
    245      1.1  christos #else
    246      1.1  christos   ppc = vpc;
    247      1.1  christos #endif
    248      1.1  christos 
    249      1.1  christos   SET_H_SYS_PPC (ppc);
    250      1.1  christos 
    251      1.1  christos   if (!GET_H_SYS_CPUCFGR_ND () &&
    252      1.1  christos       CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) &
    253      1.1  christos       CGEN_ATTR_MASK (CGEN_INSN_DELAYED_CTI))
    254      1.1  christos     {
    255  1.1.1.4  christos       SIM_ASSERT (!or1k_cpu->delay_slot);
    256  1.1.1.4  christos       or1k_cpu->next_delay_slot = 1;
    257      1.1  christos     }
    258      1.1  christos }
    259      1.1  christos 
    260      1.1  christos void
    261      1.1  christos or1k32bf_nop (sim_cpu *current_cpu, USI uimm16)
    262      1.1  christos {
    263      1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
    264      1.1  christos 
    265      1.1  christos   switch (uimm16)
    266      1.1  christos     {
    267      1.1  christos 
    268      1.1  christos     case NOP_NOP:
    269      1.1  christos       break;
    270      1.1  christos 
    271      1.1  christos     case NOP_EXIT:
    272      1.1  christos       sim_io_printf (CPU_STATE (current_cpu), "exit(%d)\n", GET_H_GPR (3));
    273  1.1.1.4  christos       ATTRIBUTE_FALLTHROUGH;
    274      1.1  christos     case NOP_EXIT_SILENT:
    275      1.1  christos       sim_engine_halt (sd, current_cpu, NULL, CPU_PC_GET (current_cpu),
    276      1.1  christos 		       sim_exited, GET_H_GPR (3));
    277      1.1  christos       break;
    278      1.1  christos 
    279      1.1  christos     case NOP_REPORT:
    280      1.1  christos       sim_io_printf (CPU_STATE (current_cpu), "report(0x%08x);\n",
    281      1.1  christos 		     GET_H_GPR (3));
    282      1.1  christos       break;
    283      1.1  christos 
    284      1.1  christos     case NOP_PUTC:
    285      1.1  christos       sim_io_printf (CPU_STATE (current_cpu), "%c",
    286      1.1  christos 		     (char) (GET_H_GPR (3) & 0xff));
    287      1.1  christos       break;
    288      1.1  christos 
    289      1.1  christos     default:
    290      1.1  christos       sim_io_eprintf (sd, "WARNING: l.nop with unsupported code 0x%08x\n",
    291      1.1  christos 		      uimm16);
    292      1.1  christos       break;
    293      1.1  christos     }
    294      1.1  christos 
    295      1.1  christos }
    296      1.1  christos 
    297      1.1  christos /* Build an address value used for load and store instructions.  For example,
    298      1.1  christos    the instruction 'l.lws rD, I(rA)' will require to load data from the 4 byte
    299      1.1  christos    address represented by rA + I.  Here the argument base is rA, offset is I
    300      1.1  christos    and the size is the read size in bytes.  Note, OpenRISC requires that word
    301      1.1  christos    and half-word access be word and half-word aligned respectively, the check
    302      1.1  christos    for alignment is not needed here.  */
    303      1.1  christos 
    304      1.1  christos USI
    305      1.1  christos or1k32bf_make_load_store_addr (sim_cpu *current_cpu, USI base, SI offset,
    306      1.1  christos 			       int size)
    307      1.1  christos {
    308      1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
    309      1.1  christos 
    310      1.1  christos   USI addr = base + offset;
    311      1.1  christos 
    312      1.1  christos   /* If little endian load/store is enabled we adjust the byte and half-word
    313      1.1  christos      addresses to the little endian equivalent.  */
    314      1.1  christos   if (GET_H_SYS_SR_LEE ())
    315      1.1  christos     {
    316      1.1  christos       switch (size)
    317      1.1  christos 	{
    318      1.1  christos 
    319      1.1  christos 	case 4: /* We are retrieving the entire word no adjustment.  */
    320      1.1  christos 	  break;
    321      1.1  christos 
    322      1.1  christos 	case 2: /* Perform half-word adjustment 0 -> 2, 2 -> 0.  */
    323      1.1  christos 	  addr ^= 0x2;
    324      1.1  christos 	  break;
    325      1.1  christos 
    326      1.1  christos 	case 1: /* Perform byte adjustment, 0 -> 3, 2 -> 3, etc.  */
    327      1.1  christos 	  addr ^= 0x3;
    328      1.1  christos 	  break;
    329      1.1  christos 
    330      1.1  christos 	default:
    331      1.1  christos 	  SIM_ASSERT (0);
    332      1.1  christos 	  return 0;
    333      1.1  christos 	}
    334      1.1  christos     }
    335      1.1  christos 
    336      1.1  christos   return addr;
    337      1.1  christos }
    338      1.1  christos 
    339      1.1  christos /* The find first 1 instruction returns the location of the first set bit
    340      1.1  christos    in the argument register.  */
    341      1.1  christos 
    342      1.1  christos USI
    343      1.1  christos or1k32bf_ff1 (sim_cpu *current_cpu, USI val)
    344      1.1  christos {
    345      1.1  christos   USI bit;
    346      1.1  christos   USI ret;
    347      1.1  christos   for (bit = 1, ret = 1; bit; bit <<= 1, ret++)
    348      1.1  christos     {
    349      1.1  christos       if (val & bit)
    350      1.1  christos 	return ret;
    351      1.1  christos     }
    352      1.1  christos   return 0;
    353      1.1  christos }
    354      1.1  christos 
    355      1.1  christos /* The find last 1 instruction returns the location of the last set bit in
    356      1.1  christos    the argument register.  */
    357      1.1  christos 
    358      1.1  christos USI
    359      1.1  christos or1k32bf_fl1 (sim_cpu *current_cpu, USI val)
    360      1.1  christos {
    361      1.1  christos   USI bit;
    362      1.1  christos   USI ret;
    363      1.1  christos   for (bit = 1 << 31, ret = 32; bit; bit >>= 1, ret--)
    364      1.1  christos     {
    365      1.1  christos       if (val & bit)
    366      1.1  christos 	return ret;
    367      1.1  christos     }
    368      1.1  christos   return 0;
    369      1.1  christos }
    370