Home | History | Annotate | Line # | Download | only in frv
      1       1.1  christos /* frv simulator support code
      2  1.1.1.10  christos    Copyright (C) 1998-2024 Free Software Foundation, Inc.
      3       1.1  christos    Contributed by Red Hat.
      4       1.1  christos 
      5       1.1  christos This file is part of the GNU simulators.
      6       1.1  christos 
      7       1.1  christos This program is free software; you can redistribute it and/or modify
      8       1.1  christos it under the terms of the GNU General Public License as published by
      9       1.1  christos the Free Software Foundation; either version 3 of the License, or
     10       1.1  christos (at your option) any later version.
     11       1.1  christos 
     12       1.1  christos This program is distributed in the hope that it will be useful,
     13       1.1  christos but WITHOUT ANY WARRANTY; without even the implied warranty of
     14       1.1  christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15       1.1  christos GNU General Public License for more details.
     16       1.1  christos 
     17       1.1  christos You should have received a copy of the GNU General Public License
     18       1.1  christos along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19       1.1  christos 
     20   1.1.1.9  christos /* This must come before any other includes.  */
     21   1.1.1.9  christos #include "defs.h"
     22   1.1.1.9  christos 
     23       1.1  christos #define WANT_CPU
     24       1.1  christos #define WANT_CPU_FRVBF
     25       1.1  christos 
     26       1.1  christos #include "sim-main.h"
     27       1.1  christos #include "cgen-mem.h"
     28       1.1  christos #include "cgen-ops.h"
     29       1.1  christos #include "cgen-engine.h"
     30       1.1  christos #include "cgen-par.h"
     31       1.1  christos #include "bfd.h"
     32  1.1.1.10  christos #include "sim/sim-frv.h"
     33       1.1  christos #include <math.h>
     34   1.1.1.9  christos #include <stdlib.h>
     35       1.1  christos 
     36       1.1  christos /* Maintain a flag in order to know when to write the address of the next
     37       1.1  christos    VLIW instruction into the LR register.  Used by JMPL. JMPIL, and CALL
     38       1.1  christos    insns.  */
     39       1.1  christos int frvbf_write_next_vliw_addr_to_LR;
     40       1.1  christos 
     41       1.1  christos /* The contents of BUF are in target byte order.  */
     42       1.1  christos int
     43   1.1.1.9  christos frvbf_fetch_register (SIM_CPU *current_cpu, int rn, void *buf, int len)
     44       1.1  christos {
     45       1.1  christos   if (SIM_FRV_GR0_REGNUM <= rn && rn <= SIM_FRV_GR63_REGNUM)
     46       1.1  christos     {
     47       1.1  christos       int hi_available, lo_available;
     48       1.1  christos       int grn = rn - SIM_FRV_GR0_REGNUM;
     49       1.1  christos 
     50       1.1  christos       frv_gr_registers_available (current_cpu, &hi_available, &lo_available);
     51       1.1  christos 
     52       1.1  christos       if ((grn < 32 && !lo_available) || (grn >= 32 && !hi_available))
     53       1.1  christos 	return 0;
     54       1.1  christos       else
     55       1.1  christos 	SETTSI (buf, GET_H_GR (grn));
     56       1.1  christos     }
     57       1.1  christos   else if (SIM_FRV_FR0_REGNUM <= rn && rn <= SIM_FRV_FR63_REGNUM)
     58       1.1  christos     {
     59       1.1  christos       int hi_available, lo_available;
     60       1.1  christos       int frn = rn - SIM_FRV_FR0_REGNUM;
     61       1.1  christos 
     62       1.1  christos       frv_fr_registers_available (current_cpu, &hi_available, &lo_available);
     63       1.1  christos 
     64       1.1  christos       if ((frn < 32 && !lo_available) || (frn >= 32 && !hi_available))
     65       1.1  christos 	return 0;
     66       1.1  christos       else
     67       1.1  christos 	SETTSI (buf, GET_H_FR (frn));
     68       1.1  christos     }
     69       1.1  christos   else if (rn == SIM_FRV_PC_REGNUM)
     70       1.1  christos     SETTSI (buf, GET_H_PC ());
     71       1.1  christos   else if (SIM_FRV_SPR0_REGNUM <= rn && rn <= SIM_FRV_SPR4095_REGNUM)
     72       1.1  christos     {
     73       1.1  christos       /* Make sure the register is implemented.  */
     74       1.1  christos       FRV_REGISTER_CONTROL *control = CPU_REGISTER_CONTROL (current_cpu);
     75       1.1  christos       int spr = rn - SIM_FRV_SPR0_REGNUM;
     76       1.1  christos       if (! control->spr[spr].implemented)
     77       1.1  christos 	return 0;
     78       1.1  christos       SETTSI (buf, GET_H_SPR (spr));
     79       1.1  christos     }
     80       1.1  christos   else
     81       1.1  christos     {
     82       1.1  christos       SETTSI (buf, 0xdeadbeef);
     83       1.1  christos       return 0;
     84       1.1  christos     }
     85       1.1  christos 
     86       1.1  christos   return len;
     87       1.1  christos }
     88       1.1  christos 
     89       1.1  christos /* The contents of BUF are in target byte order.  */
     90       1.1  christos 
     91       1.1  christos int
     92   1.1.1.9  christos frvbf_store_register (SIM_CPU *current_cpu, int rn, const void *buf, int len)
     93       1.1  christos {
     94       1.1  christos   if (SIM_FRV_GR0_REGNUM <= rn && rn <= SIM_FRV_GR63_REGNUM)
     95       1.1  christos     {
     96       1.1  christos       int hi_available, lo_available;
     97       1.1  christos       int grn = rn - SIM_FRV_GR0_REGNUM;
     98       1.1  christos 
     99       1.1  christos       frv_gr_registers_available (current_cpu, &hi_available, &lo_available);
    100       1.1  christos 
    101       1.1  christos       if ((grn < 32 && !lo_available) || (grn >= 32 && !hi_available))
    102       1.1  christos 	return 0;
    103       1.1  christos       else
    104       1.1  christos 	SET_H_GR (grn, GETTSI (buf));
    105       1.1  christos     }
    106       1.1  christos   else if (SIM_FRV_FR0_REGNUM <= rn && rn <= SIM_FRV_FR63_REGNUM)
    107       1.1  christos     {
    108       1.1  christos       int hi_available, lo_available;
    109       1.1  christos       int frn = rn - SIM_FRV_FR0_REGNUM;
    110       1.1  christos 
    111       1.1  christos       frv_fr_registers_available (current_cpu, &hi_available, &lo_available);
    112       1.1  christos 
    113       1.1  christos       if ((frn < 32 && !lo_available) || (frn >= 32 && !hi_available))
    114       1.1  christos 	return 0;
    115       1.1  christos       else
    116       1.1  christos 	SET_H_FR (frn, GETTSI (buf));
    117       1.1  christos     }
    118       1.1  christos   else if (rn == SIM_FRV_PC_REGNUM)
    119       1.1  christos     SET_H_PC (GETTSI (buf));
    120       1.1  christos   else if (SIM_FRV_SPR0_REGNUM <= rn && rn <= SIM_FRV_SPR4095_REGNUM)
    121       1.1  christos     {
    122       1.1  christos       /* Make sure the register is implemented.  */
    123       1.1  christos       FRV_REGISTER_CONTROL *control = CPU_REGISTER_CONTROL (current_cpu);
    124       1.1  christos       int spr = rn - SIM_FRV_SPR0_REGNUM;
    125       1.1  christos       if (! control->spr[spr].implemented)
    126       1.1  christos 	return 0;
    127       1.1  christos       SET_H_SPR (spr, GETTSI (buf));
    128       1.1  christos     }
    129       1.1  christos   else
    130       1.1  christos     return 0;
    131       1.1  christos 
    132       1.1  christos   return len;
    133       1.1  christos }
    134       1.1  christos 
    135       1.1  christos /* Cover fns to access the general registers.  */
    137       1.1  christos USI
    138       1.1  christos frvbf_h_gr_get_handler (SIM_CPU *current_cpu, UINT gr)
    139       1.1  christos {
    140       1.1  christos   frv_check_gr_access (current_cpu, gr);
    141       1.1  christos   return CPU (h_gr[gr]);
    142       1.1  christos }
    143       1.1  christos 
    144       1.1  christos void
    145       1.1  christos frvbf_h_gr_set_handler (SIM_CPU *current_cpu, UINT gr, USI newval)
    146       1.1  christos {
    147       1.1  christos   frv_check_gr_access (current_cpu, gr);
    148       1.1  christos 
    149       1.1  christos   if (gr == 0)
    150       1.1  christos     return; /* Storing into gr0 has no effect.  */
    151       1.1  christos 
    152       1.1  christos   CPU (h_gr[gr]) = newval;
    153       1.1  christos }
    154       1.1  christos 
    155       1.1  christos /* Cover fns to access the floating point registers.  */
    157       1.1  christos SF
    158       1.1  christos frvbf_h_fr_get_handler (SIM_CPU *current_cpu, UINT fr)
    159       1.1  christos {
    160       1.1  christos   frv_check_fr_access (current_cpu, fr);
    161       1.1  christos   return CPU (h_fr[fr]);
    162       1.1  christos }
    163       1.1  christos 
    164       1.1  christos void
    165       1.1  christos frvbf_h_fr_set_handler (SIM_CPU *current_cpu, UINT fr, SF newval)
    166       1.1  christos {
    167       1.1  christos   frv_check_fr_access (current_cpu, fr);
    168       1.1  christos   CPU (h_fr[fr]) = newval;
    169       1.1  christos }
    170       1.1  christos 
    171       1.1  christos /* Cover fns to access the general registers as double words.  */
    173       1.1  christos static UINT
    174       1.1  christos check_register_alignment (SIM_CPU *current_cpu, UINT reg, int align_mask)
    175       1.1  christos {
    176       1.1  christos   if (reg & align_mask)
    177       1.1  christos     {
    178       1.1  christos       SIM_DESC sd = CPU_STATE (current_cpu);
    179       1.1  christos       switch (STATE_ARCHITECTURE (sd)->mach)
    180       1.1  christos 	{
    181       1.1  christos 	  /* Note: there is a discrepancy between V2.2 of the FR400
    182       1.1  christos 	     instruction manual and the various FR4xx LSI specs.
    183       1.1  christos 	     The former claims that unaligned registers cause a
    184       1.1  christos 	     register_exception while the latter say it's an
    185       1.1  christos 	     illegal_instruction.  The LSI specs appear to be
    186       1.1  christos 	     correct; in fact, the FR4xx series is not documented
    187       1.1  christos 	     as having a register_exception.  */
    188       1.1  christos 	case bfd_mach_fr400:
    189       1.1  christos 	case bfd_mach_fr450:
    190       1.1  christos 	case bfd_mach_fr550:
    191       1.1  christos 	  frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
    192       1.1  christos 	  break;
    193       1.1  christos 	case bfd_mach_frvtomcat:
    194       1.1  christos 	case bfd_mach_fr500:
    195       1.1  christos 	case bfd_mach_frv:
    196       1.1  christos 	  frv_queue_register_exception_interrupt (current_cpu,
    197       1.1  christos 						  FRV_REC_UNALIGNED);
    198       1.1  christos 	  break;
    199       1.1  christos 	default:
    200       1.1  christos 	  break;
    201       1.1  christos 	}
    202       1.1  christos 
    203       1.1  christos       reg &= ~align_mask;
    204       1.1  christos     }
    205       1.1  christos 
    206       1.1  christos   return reg;
    207       1.1  christos }
    208       1.1  christos 
    209       1.1  christos static UINT
    210       1.1  christos check_fr_register_alignment (SIM_CPU *current_cpu, UINT reg, int align_mask)
    211       1.1  christos {
    212       1.1  christos   if (reg & align_mask)
    213       1.1  christos     {
    214       1.1  christos       SIM_DESC sd = CPU_STATE (current_cpu);
    215       1.1  christos       switch (STATE_ARCHITECTURE (sd)->mach)
    216       1.1  christos 	{
    217       1.1  christos 	  /* See comment in check_register_alignment().  */
    218       1.1  christos 	case bfd_mach_fr400:
    219       1.1  christos 	case bfd_mach_fr450:
    220       1.1  christos 	case bfd_mach_fr550:
    221       1.1  christos 	  frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
    222       1.1  christos 	  break;
    223       1.1  christos 	case bfd_mach_frvtomcat:
    224       1.1  christos 	case bfd_mach_fr500:
    225       1.1  christos 	case bfd_mach_frv:
    226       1.1  christos 	  {
    227       1.1  christos 	    struct frv_fp_exception_info fp_info = {
    228       1.1  christos 	      FSR_NO_EXCEPTION, FTT_INVALID_FR
    229       1.1  christos 	    };
    230       1.1  christos 	    frv_queue_fp_exception_interrupt (current_cpu, & fp_info);
    231       1.1  christos 	  }
    232       1.1  christos 	  break;
    233       1.1  christos 	default:
    234       1.1  christos 	  break;
    235       1.1  christos 	}
    236       1.1  christos 
    237       1.1  christos       reg &= ~align_mask;
    238       1.1  christos     }
    239       1.1  christos 
    240       1.1  christos   return reg;
    241       1.1  christos }
    242       1.1  christos 
    243       1.1  christos static UINT
    244       1.1  christos check_memory_alignment (SIM_CPU *current_cpu, SI address, int align_mask)
    245       1.1  christos {
    246       1.1  christos   if (address & align_mask)
    247       1.1  christos     {
    248       1.1  christos       SIM_DESC sd = CPU_STATE (current_cpu);
    249       1.1  christos       switch (STATE_ARCHITECTURE (sd)->mach)
    250       1.1  christos 	{
    251       1.1  christos 	  /* See comment in check_register_alignment().  */
    252       1.1  christos 	case bfd_mach_fr400:
    253       1.1  christos 	case bfd_mach_fr450:
    254       1.1  christos 	  frv_queue_data_access_error_interrupt (current_cpu, address);
    255       1.1  christos 	  break;
    256       1.1  christos 	case bfd_mach_frvtomcat:
    257       1.1  christos 	case bfd_mach_fr500:
    258       1.1  christos 	case bfd_mach_frv:
    259       1.1  christos 	  frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
    260       1.1  christos 	  break;
    261       1.1  christos 	default:
    262       1.1  christos 	  break;
    263       1.1  christos 	}
    264       1.1  christos 
    265       1.1  christos       address &= ~align_mask;
    266       1.1  christos     }
    267       1.1  christos 
    268       1.1  christos   return address;
    269       1.1  christos }
    270       1.1  christos 
    271       1.1  christos DI
    272       1.1  christos frvbf_h_gr_double_get_handler (SIM_CPU *current_cpu, UINT gr)
    273       1.1  christos {
    274       1.1  christos   DI value;
    275       1.1  christos 
    276       1.1  christos   if (gr == 0)
    277       1.1  christos     return 0; /* gr0 is always 0.  */
    278       1.1  christos 
    279       1.1  christos   /* Check the register alignment.  */
    280       1.1  christos   gr = check_register_alignment (current_cpu, gr, 1);
    281       1.1  christos 
    282       1.1  christos   value = GET_H_GR (gr);
    283       1.1  christos   value <<= 32;
    284       1.1  christos   value |=  (USI) GET_H_GR (gr + 1);
    285       1.1  christos   return value;
    286       1.1  christos }
    287       1.1  christos 
    288       1.1  christos void
    289       1.1  christos frvbf_h_gr_double_set_handler (SIM_CPU *current_cpu, UINT gr, DI newval)
    290       1.1  christos {
    291       1.1  christos   if (gr == 0)
    292       1.1  christos     return; /* Storing into gr0 has no effect.  */
    293       1.1  christos 
    294       1.1  christos   /* Check the register alignment.  */
    295       1.1  christos   gr = check_register_alignment (current_cpu, gr, 1);
    296       1.1  christos 
    297       1.1  christos   SET_H_GR (gr    , (newval >> 32) & 0xffffffff);
    298       1.1  christos   SET_H_GR (gr + 1, (newval      ) & 0xffffffff);
    299       1.1  christos }
    300       1.1  christos 
    301       1.1  christos /* Cover fns to access the floating point register as double words.  */
    303       1.1  christos DF
    304       1.1  christos frvbf_h_fr_double_get_handler (SIM_CPU *current_cpu, UINT fr)
    305       1.1  christos {
    306       1.1  christos   union {
    307       1.1  christos     SF as_sf[2];
    308       1.1  christos     DF as_df;
    309       1.1  christos   } value;
    310   1.1.1.5  christos 
    311       1.1  christos   /* Check the register alignment.  */
    312       1.1  christos   fr = check_fr_register_alignment (current_cpu, fr, 1);
    313       1.1  christos 
    314       1.1  christos   if (HOST_BYTE_ORDER == BFD_ENDIAN_LITTLE)
    315       1.1  christos     {
    316       1.1  christos       value.as_sf[1] = GET_H_FR (fr);
    317       1.1  christos       value.as_sf[0] = GET_H_FR (fr + 1);
    318       1.1  christos     }
    319       1.1  christos   else
    320       1.1  christos     {
    321       1.1  christos       value.as_sf[0] = GET_H_FR (fr);
    322       1.1  christos       value.as_sf[1] = GET_H_FR (fr + 1);
    323       1.1  christos     }
    324       1.1  christos 
    325       1.1  christos   return value.as_df;
    326       1.1  christos }
    327       1.1  christos 
    328       1.1  christos void
    329       1.1  christos frvbf_h_fr_double_set_handler (SIM_CPU *current_cpu, UINT fr, DF newval)
    330       1.1  christos {
    331       1.1  christos   union {
    332       1.1  christos     SF as_sf[2];
    333       1.1  christos     DF as_df;
    334       1.1  christos   } value;
    335       1.1  christos 
    336   1.1.1.5  christos   /* Check the register alignment.  */
    337       1.1  christos   fr = check_fr_register_alignment (current_cpu, fr, 1);
    338       1.1  christos 
    339       1.1  christos   value.as_df = newval;
    340       1.1  christos   if (HOST_BYTE_ORDER == BFD_ENDIAN_LITTLE)
    341       1.1  christos     {
    342       1.1  christos       SET_H_FR (fr    , value.as_sf[1]);
    343       1.1  christos       SET_H_FR (fr + 1, value.as_sf[0]);
    344       1.1  christos     }
    345       1.1  christos   else
    346       1.1  christos     {
    347       1.1  christos       SET_H_FR (fr    , value.as_sf[0]);
    348       1.1  christos       SET_H_FR (fr + 1, value.as_sf[1]);
    349       1.1  christos     }
    350       1.1  christos }
    351       1.1  christos 
    352       1.1  christos /* Cover fns to access the floating point register as integer words.  */
    354       1.1  christos USI
    355       1.1  christos frvbf_h_fr_int_get_handler (SIM_CPU *current_cpu, UINT fr)
    356       1.1  christos {
    357       1.1  christos   union {
    358       1.1  christos     SF  as_sf;
    359       1.1  christos     USI as_usi;
    360       1.1  christos   } value;
    361       1.1  christos 
    362       1.1  christos   value.as_sf = GET_H_FR (fr);
    363       1.1  christos   return value.as_usi;
    364       1.1  christos }
    365       1.1  christos 
    366       1.1  christos void
    367       1.1  christos frvbf_h_fr_int_set_handler (SIM_CPU *current_cpu, UINT fr, USI newval)
    368       1.1  christos {
    369       1.1  christos   union {
    370       1.1  christos     SF  as_sf;
    371       1.1  christos     USI as_usi;
    372       1.1  christos   } value;
    373       1.1  christos 
    374       1.1  christos   value.as_usi = newval;
    375       1.1  christos   SET_H_FR (fr, value.as_sf);
    376       1.1  christos }
    377       1.1  christos 
    378       1.1  christos /* Cover fns to access the coprocessor registers as double words.  */
    380       1.1  christos DI
    381       1.1  christos frvbf_h_cpr_double_get_handler (SIM_CPU *current_cpu, UINT cpr)
    382       1.1  christos {
    383       1.1  christos   DI value;
    384       1.1  christos 
    385       1.1  christos   /* Check the register alignment.  */
    386       1.1  christos   cpr = check_register_alignment (current_cpu, cpr, 1);
    387       1.1  christos 
    388       1.1  christos   value = GET_H_CPR (cpr);
    389       1.1  christos   value <<= 32;
    390       1.1  christos   value |=  (USI) GET_H_CPR (cpr + 1);
    391       1.1  christos   return value;
    392       1.1  christos }
    393       1.1  christos 
    394       1.1  christos void
    395       1.1  christos frvbf_h_cpr_double_set_handler (SIM_CPU *current_cpu, UINT cpr, DI newval)
    396       1.1  christos {
    397       1.1  christos   /* Check the register alignment.  */
    398       1.1  christos   cpr = check_register_alignment (current_cpu, cpr, 1);
    399       1.1  christos 
    400       1.1  christos   SET_H_CPR (cpr    , (newval >> 32) & 0xffffffff);
    401       1.1  christos   SET_H_CPR (cpr + 1, (newval      ) & 0xffffffff);
    402       1.1  christos }
    403       1.1  christos 
    404       1.1  christos /* Cover fns to write registers as quad words.  */
    406       1.1  christos void
    407       1.1  christos frvbf_h_gr_quad_set_handler (SIM_CPU *current_cpu, UINT gr, SI *newval)
    408       1.1  christos {
    409       1.1  christos   if (gr == 0)
    410       1.1  christos     return; /* Storing into gr0 has no effect.  */
    411       1.1  christos 
    412       1.1  christos   /* Check the register alignment.  */
    413       1.1  christos   gr = check_register_alignment (current_cpu, gr, 3);
    414       1.1  christos 
    415       1.1  christos   SET_H_GR (gr    , newval[0]);
    416       1.1  christos   SET_H_GR (gr + 1, newval[1]);
    417       1.1  christos   SET_H_GR (gr + 2, newval[2]);
    418       1.1  christos   SET_H_GR (gr + 3, newval[3]);
    419       1.1  christos }
    420       1.1  christos 
    421       1.1  christos void
    422       1.1  christos frvbf_h_fr_quad_set_handler (SIM_CPU *current_cpu, UINT fr, SI *newval)
    423       1.1  christos {
    424       1.1  christos   /* Check the register alignment.  */
    425       1.1  christos   fr = check_fr_register_alignment (current_cpu, fr, 3);
    426       1.1  christos 
    427       1.1  christos   SET_H_FR (fr    , newval[0]);
    428       1.1  christos   SET_H_FR (fr + 1, newval[1]);
    429       1.1  christos   SET_H_FR (fr + 2, newval[2]);
    430       1.1  christos   SET_H_FR (fr + 3, newval[3]);
    431       1.1  christos }
    432       1.1  christos 
    433       1.1  christos void
    434       1.1  christos frvbf_h_cpr_quad_set_handler (SIM_CPU *current_cpu, UINT cpr, SI *newval)
    435       1.1  christos {
    436       1.1  christos   /* Check the register alignment.  */
    437       1.1  christos   cpr = check_register_alignment (current_cpu, cpr, 3);
    438       1.1  christos 
    439       1.1  christos   SET_H_CPR (cpr    , newval[0]);
    440       1.1  christos   SET_H_CPR (cpr + 1, newval[1]);
    441       1.1  christos   SET_H_CPR (cpr + 2, newval[2]);
    442       1.1  christos   SET_H_CPR (cpr + 3, newval[3]);
    443       1.1  christos }
    444       1.1  christos 
    445       1.1  christos /* Cover fns to access the special purpose registers.  */
    447       1.1  christos USI
    448       1.1  christos frvbf_h_spr_get_handler (SIM_CPU *current_cpu, UINT spr)
    449       1.1  christos {
    450       1.1  christos   /* Check access restrictions.  */
    451       1.1  christos   frv_check_spr_read_access (current_cpu, spr);
    452       1.1  christos 
    453       1.1  christos   switch (spr)
    454       1.1  christos     {
    455       1.1  christos     case H_SPR_PSR:
    456       1.1  christos       return spr_psr_get_handler (current_cpu);
    457       1.1  christos     case H_SPR_TBR:
    458       1.1  christos       return spr_tbr_get_handler (current_cpu);
    459       1.1  christos     case H_SPR_BPSR:
    460       1.1  christos       return spr_bpsr_get_handler (current_cpu);
    461       1.1  christos     case H_SPR_CCR:
    462       1.1  christos       return spr_ccr_get_handler (current_cpu);
    463       1.1  christos     case H_SPR_CCCR:
    464       1.1  christos       return spr_cccr_get_handler (current_cpu);
    465       1.1  christos     case H_SPR_SR0:
    466       1.1  christos     case H_SPR_SR1:
    467       1.1  christos     case H_SPR_SR2:
    468       1.1  christos     case H_SPR_SR3:
    469       1.1  christos       return spr_sr_get_handler (current_cpu, spr);
    470       1.1  christos       break;
    471       1.1  christos     default:
    472       1.1  christos       return CPU (h_spr[spr]);
    473       1.1  christos     }
    474       1.1  christos   return 0;
    475       1.1  christos }
    476       1.1  christos 
    477       1.1  christos void
    478       1.1  christos frvbf_h_spr_set_handler (SIM_CPU *current_cpu, UINT spr, USI newval)
    479       1.1  christos {
    480       1.1  christos   FRV_REGISTER_CONTROL *control;
    481       1.1  christos   USI mask;
    482       1.1  christos   USI oldval;
    483       1.1  christos 
    484       1.1  christos   /* Check access restrictions.  */
    485       1.1  christos   frv_check_spr_write_access (current_cpu, spr);
    486       1.1  christos 
    487       1.1  christos   /* Only set those fields which are writeable.  */
    488       1.1  christos   control = CPU_REGISTER_CONTROL (current_cpu);
    489       1.1  christos   mask = control->spr[spr].read_only_mask;
    490       1.1  christos   oldval = GET_H_SPR (spr);
    491       1.1  christos 
    492       1.1  christos   newval = (newval & ~mask) | (oldval & mask);
    493       1.1  christos 
    494       1.1  christos   /* Some registers are represented by individual components which are
    495       1.1  christos      referenced more often than the register itself.  */
    496       1.1  christos   switch (spr)
    497       1.1  christos     {
    498       1.1  christos     case H_SPR_PSR:
    499       1.1  christos       spr_psr_set_handler (current_cpu, newval);
    500       1.1  christos       break;
    501       1.1  christos     case H_SPR_TBR:
    502       1.1  christos       spr_tbr_set_handler (current_cpu, newval);
    503       1.1  christos       break;
    504       1.1  christos     case H_SPR_BPSR:
    505       1.1  christos       spr_bpsr_set_handler (current_cpu, newval);
    506       1.1  christos       break;
    507       1.1  christos     case H_SPR_CCR:
    508       1.1  christos       spr_ccr_set_handler (current_cpu, newval);
    509       1.1  christos       break;
    510       1.1  christos     case H_SPR_CCCR:
    511       1.1  christos       spr_cccr_set_handler (current_cpu, newval);
    512       1.1  christos       break;
    513       1.1  christos     case H_SPR_SR0:
    514       1.1  christos     case H_SPR_SR1:
    515       1.1  christos     case H_SPR_SR2:
    516       1.1  christos     case H_SPR_SR3:
    517       1.1  christos       spr_sr_set_handler (current_cpu, spr, newval);
    518       1.1  christos       break;
    519       1.1  christos     case H_SPR_IHSR8:
    520       1.1  christos       frv_cache_reconfigure (current_cpu, CPU_INSN_CACHE (current_cpu));
    521       1.1  christos       break;
    522       1.1  christos     default:
    523       1.1  christos       CPU (h_spr[spr]) = newval;
    524       1.1  christos       break;
    525       1.1  christos     }
    526       1.1  christos }
    527       1.1  christos 
    528       1.1  christos /* Cover fns to access the gr_hi and gr_lo registers.  */
    530       1.1  christos UHI
    531       1.1  christos frvbf_h_gr_hi_get_handler (SIM_CPU *current_cpu, UINT gr)
    532       1.1  christos {
    533       1.1  christos   return (GET_H_GR(gr) >> 16) & 0xffff;
    534       1.1  christos }
    535       1.1  christos 
    536       1.1  christos void
    537       1.1  christos frvbf_h_gr_hi_set_handler (SIM_CPU *current_cpu, UINT gr, UHI newval)
    538       1.1  christos {
    539       1.1  christos   USI value = (GET_H_GR (gr) & 0xffff) | (newval << 16);
    540       1.1  christos   SET_H_GR (gr, value);
    541       1.1  christos }
    542       1.1  christos 
    543       1.1  christos UHI
    544       1.1  christos frvbf_h_gr_lo_get_handler (SIM_CPU *current_cpu, UINT gr)
    545       1.1  christos {
    546       1.1  christos   return GET_H_GR(gr) & 0xffff;
    547       1.1  christos }
    548       1.1  christos 
    549       1.1  christos void
    550       1.1  christos frvbf_h_gr_lo_set_handler (SIM_CPU *current_cpu, UINT gr, UHI newval)
    551       1.1  christos {
    552       1.1  christos   USI value = (GET_H_GR (gr) & 0xffff0000) | (newval & 0xffff);
    553       1.1  christos   SET_H_GR (gr, value);
    554       1.1  christos }
    555       1.1  christos 
    556       1.1  christos /* Cover fns to access the tbr bits.  */
    558       1.1  christos USI
    559       1.1  christos spr_tbr_get_handler (SIM_CPU *current_cpu)
    560       1.1  christos {
    561       1.1  christos   int tbr = ((GET_H_TBR_TBA () & 0xfffff) << 12) |
    562       1.1  christos             ((GET_H_TBR_TT  () &  0xff) <<  4);
    563       1.1  christos 
    564       1.1  christos   return tbr;
    565       1.1  christos }
    566       1.1  christos 
    567       1.1  christos void
    568       1.1  christos spr_tbr_set_handler (SIM_CPU *current_cpu, USI newval)
    569       1.1  christos {
    570       1.1  christos   int tbr = newval;
    571       1.1  christos 
    572       1.1  christos   SET_H_TBR_TBA ((tbr >> 12) & 0xfffff) ;
    573       1.1  christos   SET_H_TBR_TT  ((tbr >>  4) & 0xff) ;
    574       1.1  christos }
    575       1.1  christos 
    576       1.1  christos /* Cover fns to access the bpsr bits.  */
    578       1.1  christos USI
    579       1.1  christos spr_bpsr_get_handler (SIM_CPU *current_cpu)
    580       1.1  christos {
    581       1.1  christos   int bpsr = ((GET_H_BPSR_BS  () & 0x1) << 12) |
    582       1.1  christos              ((GET_H_BPSR_BET () & 0x1)      );
    583       1.1  christos 
    584       1.1  christos   return bpsr;
    585       1.1  christos }
    586       1.1  christos 
    587       1.1  christos void
    588       1.1  christos spr_bpsr_set_handler (SIM_CPU *current_cpu, USI newval)
    589       1.1  christos {
    590       1.1  christos   int bpsr = newval;
    591       1.1  christos 
    592       1.1  christos   SET_H_BPSR_BS  ((bpsr >> 12) & 1);
    593       1.1  christos   SET_H_BPSR_BET ((bpsr      ) & 1);
    594       1.1  christos }
    595       1.1  christos 
    596       1.1  christos /* Cover fns to access the psr bits.  */
    598       1.1  christos USI
    599       1.1  christos spr_psr_get_handler (SIM_CPU *current_cpu)
    600       1.1  christos {
    601       1.1  christos   int psr = ((GET_H_PSR_IMPLE () & 0xf) << 28) |
    602       1.1  christos             ((GET_H_PSR_VER   () & 0xf) << 24) |
    603       1.1  christos             ((GET_H_PSR_ICE   () & 0x1) << 16) |
    604       1.1  christos             ((GET_H_PSR_NEM   () & 0x1) << 14) |
    605       1.1  christos             ((GET_H_PSR_CM    () & 0x1) << 13) |
    606       1.1  christos             ((GET_H_PSR_BE    () & 0x1) << 12) |
    607       1.1  christos             ((GET_H_PSR_ESR   () & 0x1) << 11) |
    608       1.1  christos             ((GET_H_PSR_EF    () & 0x1) <<  8) |
    609       1.1  christos             ((GET_H_PSR_EM    () & 0x1) <<  7) |
    610       1.1  christos             ((GET_H_PSR_PIL   () & 0xf) <<  3) |
    611       1.1  christos             ((GET_H_PSR_S     () & 0x1) <<  2) |
    612       1.1  christos             ((GET_H_PSR_PS    () & 0x1) <<  1) |
    613       1.1  christos             ((GET_H_PSR_ET    () & 0x1)      );
    614       1.1  christos 
    615       1.1  christos   return psr;
    616       1.1  christos }
    617       1.1  christos 
    618       1.1  christos void
    619       1.1  christos spr_psr_set_handler (SIM_CPU *current_cpu, USI newval)
    620       1.1  christos {
    621       1.1  christos   /* The handler for PSR.S references the value of PSR.ESR, so set PSR.S
    622       1.1  christos      first.  */
    623       1.1  christos   SET_H_PSR_S ((newval >>  2) & 1);
    624       1.1  christos 
    625       1.1  christos   SET_H_PSR_IMPLE ((newval >> 28) & 0xf);
    626       1.1  christos   SET_H_PSR_VER   ((newval >> 24) & 0xf);
    627       1.1  christos   SET_H_PSR_ICE   ((newval >> 16) & 1);
    628       1.1  christos   SET_H_PSR_NEM   ((newval >> 14) & 1);
    629       1.1  christos   SET_H_PSR_CM    ((newval >> 13) & 1);
    630       1.1  christos   SET_H_PSR_BE    ((newval >> 12) & 1);
    631       1.1  christos   SET_H_PSR_ESR   ((newval >> 11) & 1);
    632       1.1  christos   SET_H_PSR_EF    ((newval >>  8) & 1);
    633       1.1  christos   SET_H_PSR_EM    ((newval >>  7) & 1);
    634       1.1  christos   SET_H_PSR_PIL   ((newval >>  3) & 0xf);
    635       1.1  christos   SET_H_PSR_PS    ((newval >>  1) & 1);
    636       1.1  christos   SET_H_PSR_ET    ((newval      ) & 1);
    637       1.1  christos }
    638       1.1  christos 
    639       1.1  christos void
    640       1.1  christos frvbf_h_psr_s_set_handler (SIM_CPU *current_cpu, BI newval)
    641       1.1  christos {
    642       1.1  christos   /* If switching from user to supervisor mode, or vice-versa, then switch
    643       1.1  christos      the supervisor/user context.  */
    644       1.1  christos   int psr_s = GET_H_PSR_S ();
    645       1.1  christos   if (psr_s != (newval & 1))
    646       1.1  christos     {
    647       1.1  christos       frvbf_switch_supervisor_user_context (current_cpu);
    648       1.1  christos       CPU (h_psr_s) = newval & 1;
    649       1.1  christos     }
    650       1.1  christos }
    651       1.1  christos 
    652       1.1  christos /* Cover fns to access the ccr bits.  */
    654       1.1  christos USI
    655       1.1  christos spr_ccr_get_handler (SIM_CPU *current_cpu)
    656       1.1  christos {
    657       1.1  christos   int ccr = ((GET_H_ICCR (H_ICCR_ICC3) & 0xf) << 28) |
    658       1.1  christos             ((GET_H_ICCR (H_ICCR_ICC2) & 0xf) << 24) |
    659       1.1  christos             ((GET_H_ICCR (H_ICCR_ICC1) & 0xf) << 20) |
    660       1.1  christos             ((GET_H_ICCR (H_ICCR_ICC0) & 0xf) << 16) |
    661       1.1  christos             ((GET_H_FCCR (H_FCCR_FCC3) & 0xf) << 12) |
    662       1.1  christos             ((GET_H_FCCR (H_FCCR_FCC2) & 0xf) <<  8) |
    663       1.1  christos             ((GET_H_FCCR (H_FCCR_FCC1) & 0xf) <<  4) |
    664       1.1  christos             ((GET_H_FCCR (H_FCCR_FCC0) & 0xf)      );
    665       1.1  christos 
    666       1.1  christos   return ccr;
    667       1.1  christos }
    668       1.1  christos 
    669       1.1  christos void
    670       1.1  christos spr_ccr_set_handler (SIM_CPU *current_cpu, USI newval)
    671       1.1  christos {
    672       1.1  christos   SET_H_ICCR (H_ICCR_ICC3, (newval >> 28) & 0xf);
    673       1.1  christos   SET_H_ICCR (H_ICCR_ICC2, (newval >> 24) & 0xf);
    674       1.1  christos   SET_H_ICCR (H_ICCR_ICC1, (newval >> 20) & 0xf);
    675       1.1  christos   SET_H_ICCR (H_ICCR_ICC0, (newval >> 16) & 0xf);
    676       1.1  christos   SET_H_FCCR (H_FCCR_FCC3, (newval >> 12) & 0xf);
    677       1.1  christos   SET_H_FCCR (H_FCCR_FCC2, (newval >>  8) & 0xf);
    678       1.1  christos   SET_H_FCCR (H_FCCR_FCC1, (newval >>  4) & 0xf);
    679       1.1  christos   SET_H_FCCR (H_FCCR_FCC0, (newval      ) & 0xf);
    680       1.1  christos }
    681       1.1  christos 
    682       1.1  christos QI
    684       1.1  christos frvbf_set_icc_for_shift_right (
    685       1.1  christos   SIM_CPU *current_cpu, SI value, SI shift, QI icc
    686       1.1  christos )
    687       1.1  christos {
    688       1.1  christos   /* Set the C flag of the given icc to the logical OR of the bits shifted
    689       1.1  christos      out.  */
    690       1.1  christos   int mask = (1 << shift) - 1;
    691       1.1  christos   if ((value & mask) != 0)
    692       1.1  christos     return icc | 0x1;
    693       1.1  christos 
    694       1.1  christos   return icc & 0xe;
    695       1.1  christos }
    696       1.1  christos 
    697       1.1  christos QI
    698       1.1  christos frvbf_set_icc_for_shift_left (
    699       1.1  christos   SIM_CPU *current_cpu, SI value, SI shift, QI icc
    700       1.1  christos )
    701       1.1  christos {
    702       1.1  christos   /* Set the V flag of the given icc to the logical OR of the bits shifted
    703       1.1  christos      out.  */
    704       1.1  christos   int mask = ((1 << shift) - 1) << (32 - shift);
    705       1.1  christos   if ((value & mask) != 0)
    706       1.1  christos     return icc | 0x2;
    707       1.1  christos 
    708       1.1  christos   return icc & 0xd;
    709       1.1  christos }
    710       1.1  christos 
    711       1.1  christos /* Cover fns to access the cccr bits.  */
    713       1.1  christos USI
    714       1.1  christos spr_cccr_get_handler (SIM_CPU *current_cpu)
    715       1.1  christos {
    716       1.1  christos   int cccr = ((GET_H_CCCR (H_CCCR_CC7) & 0x3) << 14) |
    717       1.1  christos              ((GET_H_CCCR (H_CCCR_CC6) & 0x3) << 12) |
    718       1.1  christos              ((GET_H_CCCR (H_CCCR_CC5) & 0x3) << 10) |
    719       1.1  christos              ((GET_H_CCCR (H_CCCR_CC4) & 0x3) <<  8) |
    720       1.1  christos              ((GET_H_CCCR (H_CCCR_CC3) & 0x3) <<  6) |
    721       1.1  christos              ((GET_H_CCCR (H_CCCR_CC2) & 0x3) <<  4) |
    722       1.1  christos              ((GET_H_CCCR (H_CCCR_CC1) & 0x3) <<  2) |
    723       1.1  christos              ((GET_H_CCCR (H_CCCR_CC0) & 0x3)      );
    724       1.1  christos 
    725       1.1  christos   return cccr;
    726       1.1  christos }
    727       1.1  christos 
    728       1.1  christos void
    729       1.1  christos spr_cccr_set_handler (SIM_CPU *current_cpu, USI newval)
    730       1.1  christos {
    731       1.1  christos   SET_H_CCCR (H_CCCR_CC7, (newval >> 14) & 0x3);
    732       1.1  christos   SET_H_CCCR (H_CCCR_CC6, (newval >> 12) & 0x3);
    733       1.1  christos   SET_H_CCCR (H_CCCR_CC5, (newval >> 10) & 0x3);
    734       1.1  christos   SET_H_CCCR (H_CCCR_CC4, (newval >>  8) & 0x3);
    735       1.1  christos   SET_H_CCCR (H_CCCR_CC3, (newval >>  6) & 0x3);
    736       1.1  christos   SET_H_CCCR (H_CCCR_CC2, (newval >>  4) & 0x3);
    737       1.1  christos   SET_H_CCCR (H_CCCR_CC1, (newval >>  2) & 0x3);
    738       1.1  christos   SET_H_CCCR (H_CCCR_CC0, (newval      ) & 0x3);
    739       1.1  christos }
    740       1.1  christos 
    741       1.1  christos /* Cover fns to access the sr bits.  */
    743       1.1  christos USI
    744       1.1  christos spr_sr_get_handler (SIM_CPU *current_cpu, UINT spr)
    745       1.1  christos {
    746       1.1  christos   /* If PSR.ESR is not set, then SR0-3 map onto SGR4-7 which will be GR4-7,
    747       1.1  christos      otherwise the correct mapping of USG4-7 or SGR4-7 will be in SR0-3.  */
    748       1.1  christos   int psr_esr = GET_H_PSR_ESR ();
    749       1.1  christos   if (! psr_esr)
    750       1.1  christos     return GET_H_GR (4 + (spr - H_SPR_SR0));
    751       1.1  christos 
    752       1.1  christos   return CPU (h_spr[spr]);
    753       1.1  christos }
    754       1.1  christos 
    755       1.1  christos void
    756       1.1  christos spr_sr_set_handler (SIM_CPU *current_cpu, UINT spr, USI newval)
    757       1.1  christos {
    758       1.1  christos   /* If PSR.ESR is not set, then SR0-3 map onto SGR4-7 which will be GR4-7,
    759       1.1  christos      otherwise the correct mapping of USG4-7 or SGR4-7 will be in SR0-3.  */
    760       1.1  christos   int psr_esr = GET_H_PSR_ESR ();
    761       1.1  christos   if (! psr_esr)
    762       1.1  christos     SET_H_GR (4 + (spr - H_SPR_SR0), newval);
    763       1.1  christos   else
    764       1.1  christos     CPU (h_spr[spr]) = newval;
    765       1.1  christos }
    766       1.1  christos 
    767       1.1  christos /* Switch SR0-SR4 with GR4-GR7 if PSR.ESR is set.  */
    769       1.1  christos void
    770       1.1  christos frvbf_switch_supervisor_user_context (SIM_CPU *current_cpu)
    771       1.1  christos {
    772       1.1  christos   if (GET_H_PSR_ESR ())
    773       1.1  christos     {
    774       1.1  christos       /* We need to be in supervisor mode to swap the registers. Access the
    775       1.1  christos 	 PSR.S directly in order to avoid recursive context switches.  */
    776       1.1  christos       int i;
    777       1.1  christos       int save_psr_s = CPU (h_psr_s);
    778       1.1  christos       CPU (h_psr_s) = 1;
    779       1.1  christos       for (i = 0; i < 4; ++i)
    780       1.1  christos 	{
    781       1.1  christos 	  int gr = i + 4;
    782       1.1  christos 	  int spr = i + H_SPR_SR0;
    783       1.1  christos 	  SI tmp = GET_H_SPR (spr);
    784       1.1  christos 	  SET_H_SPR (spr, GET_H_GR (gr));
    785       1.1  christos 	  SET_H_GR (gr, tmp);
    786       1.1  christos 	}
    787       1.1  christos       CPU (h_psr_s) = save_psr_s;
    788       1.1  christos     }
    789       1.1  christos }
    790       1.1  christos 
    791       1.1  christos /* Handle load/store of quad registers.  */
    793       1.1  christos void
    794       1.1  christos frvbf_load_quad_GR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI targ_ix)
    795       1.1  christos {
    796       1.1  christos   int i;
    797       1.1  christos   SI value[4];
    798       1.1  christos 
    799       1.1  christos   /* Check memory alignment */
    800       1.1  christos   address = check_memory_alignment (current_cpu, address, 0xf);
    801       1.1  christos 
    802       1.1  christos   /* If we need to count cycles, then the cache operation will be
    803       1.1  christos      initiated from the model profiling functions.
    804       1.1  christos      See frvbf_model_....  */
    805       1.1  christos   if (model_insn)
    806       1.1  christos     {
    807       1.1  christos       CPU_LOAD_ADDRESS (current_cpu) = address;
    808       1.1  christos       CPU_LOAD_LENGTH (current_cpu) = 16;
    809       1.1  christos     }
    810       1.1  christos   else
    811       1.1  christos     {
    812       1.1  christos       for (i = 0; i < 4; ++i)
    813       1.1  christos 	{
    814       1.1  christos 	  value[i] = frvbf_read_mem_SI (current_cpu, pc, address);
    815       1.1  christos 	  address += 4;
    816       1.1  christos 	}
    817       1.1  christos       sim_queue_fn_xi_write (current_cpu, frvbf_h_gr_quad_set_handler, targ_ix,
    818       1.1  christos 			     value);
    819       1.1  christos     }
    820       1.1  christos }
    821       1.1  christos 
    822       1.1  christos void
    823       1.1  christos frvbf_store_quad_GR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI src_ix)
    824       1.1  christos {
    825       1.1  christos   int i;
    826       1.1  christos   SI value[4];
    827       1.1  christos   USI hsr0;
    828       1.1  christos 
    829       1.1  christos   /* Check register and memory alignment.  */
    830       1.1  christos   src_ix = check_register_alignment (current_cpu, src_ix, 3);
    831       1.1  christos   address = check_memory_alignment (current_cpu, address, 0xf);
    832       1.1  christos 
    833       1.1  christos   for (i = 0; i < 4; ++i)
    834       1.1  christos     {
    835       1.1  christos       /* GR0 is always 0.  */
    836       1.1  christos       if (src_ix == 0)
    837       1.1  christos 	value[i] = 0;
    838       1.1  christos       else
    839       1.1  christos 	value[i] = GET_H_GR (src_ix + i);
    840       1.1  christos     }
    841       1.1  christos   hsr0 = GET_HSR0 ();
    842       1.1  christos   if (GET_HSR0_DCE (hsr0))
    843       1.1  christos     sim_queue_fn_mem_xi_write (current_cpu, frvbf_mem_set_XI, address, value);
    844       1.1  christos   else
    845       1.1  christos     sim_queue_mem_xi_write (current_cpu, address, value);
    846       1.1  christos }
    847       1.1  christos 
    848       1.1  christos void
    849       1.1  christos frvbf_load_quad_FRint (SIM_CPU *current_cpu, PCADDR pc, SI address, SI targ_ix)
    850       1.1  christos {
    851       1.1  christos   int i;
    852       1.1  christos   SI value[4];
    853       1.1  christos 
    854       1.1  christos   /* Check memory alignment */
    855       1.1  christos   address = check_memory_alignment (current_cpu, address, 0xf);
    856       1.1  christos 
    857       1.1  christos   /* If we need to count cycles, then the cache operation will be
    858       1.1  christos      initiated from the model profiling functions.
    859       1.1  christos      See frvbf_model_....  */
    860       1.1  christos   if (model_insn)
    861       1.1  christos     {
    862       1.1  christos       CPU_LOAD_ADDRESS (current_cpu) = address;
    863       1.1  christos       CPU_LOAD_LENGTH (current_cpu) = 16;
    864       1.1  christos     }
    865       1.1  christos   else
    866       1.1  christos     {
    867       1.1  christos       for (i = 0; i < 4; ++i)
    868       1.1  christos 	{
    869       1.1  christos 	  value[i] = frvbf_read_mem_SI (current_cpu, pc, address);
    870       1.1  christos 	  address += 4;
    871       1.1  christos 	}
    872       1.1  christos       sim_queue_fn_xi_write (current_cpu, frvbf_h_fr_quad_set_handler, targ_ix,
    873       1.1  christos 			     value);
    874       1.1  christos     }
    875       1.1  christos }
    876       1.1  christos 
    877       1.1  christos void
    878       1.1  christos frvbf_store_quad_FRint (SIM_CPU *current_cpu, PCADDR pc, SI address, SI src_ix)
    879       1.1  christos {
    880       1.1  christos   int i;
    881       1.1  christos   SI value[4];
    882       1.1  christos   USI hsr0;
    883       1.1  christos 
    884       1.1  christos   /* Check register and memory alignment.  */
    885       1.1  christos   src_ix = check_fr_register_alignment (current_cpu, src_ix, 3);
    886       1.1  christos   address = check_memory_alignment (current_cpu, address, 0xf);
    887       1.1  christos 
    888       1.1  christos   for (i = 0; i < 4; ++i)
    889       1.1  christos     value[i] = GET_H_FR (src_ix + i);
    890       1.1  christos 
    891       1.1  christos   hsr0 = GET_HSR0 ();
    892       1.1  christos   if (GET_HSR0_DCE (hsr0))
    893       1.1  christos     sim_queue_fn_mem_xi_write (current_cpu, frvbf_mem_set_XI, address, value);
    894       1.1  christos   else
    895       1.1  christos     sim_queue_mem_xi_write (current_cpu, address, value);
    896       1.1  christos }
    897       1.1  christos 
    898       1.1  christos void
    899       1.1  christos frvbf_load_quad_CPR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI targ_ix)
    900       1.1  christos {
    901       1.1  christos   int i;
    902       1.1  christos   SI value[4];
    903       1.1  christos 
    904       1.1  christos   /* Check memory alignment */
    905       1.1  christos   address = check_memory_alignment (current_cpu, address, 0xf);
    906       1.1  christos 
    907       1.1  christos   /* If we need to count cycles, then the cache operation will be
    908       1.1  christos      initiated from the model profiling functions.
    909       1.1  christos      See frvbf_model_....  */
    910       1.1  christos   if (model_insn)
    911       1.1  christos     {
    912       1.1  christos       CPU_LOAD_ADDRESS (current_cpu) = address;
    913       1.1  christos       CPU_LOAD_LENGTH (current_cpu) = 16;
    914       1.1  christos     }
    915       1.1  christos   else
    916       1.1  christos     {
    917       1.1  christos       for (i = 0; i < 4; ++i)
    918       1.1  christos 	{
    919       1.1  christos 	  value[i] = frvbf_read_mem_SI (current_cpu, pc, address);
    920       1.1  christos 	  address += 4;
    921       1.1  christos 	}
    922       1.1  christos       sim_queue_fn_xi_write (current_cpu, frvbf_h_cpr_quad_set_handler, targ_ix,
    923       1.1  christos 			     value);
    924       1.1  christos     }
    925       1.1  christos }
    926       1.1  christos 
    927       1.1  christos void
    928       1.1  christos frvbf_store_quad_CPR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI src_ix)
    929       1.1  christos {
    930       1.1  christos   int i;
    931       1.1  christos   SI value[4];
    932       1.1  christos   USI hsr0;
    933       1.1  christos 
    934       1.1  christos   /* Check register and memory alignment.  */
    935       1.1  christos   src_ix = check_register_alignment (current_cpu, src_ix, 3);
    936       1.1  christos   address = check_memory_alignment (current_cpu, address, 0xf);
    937       1.1  christos 
    938       1.1  christos   for (i = 0; i < 4; ++i)
    939       1.1  christos     value[i] = GET_H_CPR (src_ix + i);
    940       1.1  christos 
    941       1.1  christos   hsr0 = GET_HSR0 ();
    942       1.1  christos   if (GET_HSR0_DCE (hsr0))
    943       1.1  christos     sim_queue_fn_mem_xi_write (current_cpu, frvbf_mem_set_XI, address, value);
    944       1.1  christos   else
    945       1.1  christos     sim_queue_mem_xi_write (current_cpu, address, value);
    946       1.1  christos }
    947       1.1  christos 
    948       1.1  christos void
    950       1.1  christos frvbf_signed_integer_divide (
    951       1.1  christos   SIM_CPU *current_cpu, SI arg1, SI arg2, int target_index, int non_excepting
    952       1.1  christos )
    953       1.1  christos {
    954       1.1  christos   enum frv_dtt dtt = FRV_DTT_NO_EXCEPTION;
    955       1.1  christos   if (arg1 == 0x80000000 && arg2 == -1)
    956       1.1  christos     {
    957       1.1  christos       /* 0x80000000/(-1) must result in 0x7fffffff when ISR.EDE is set
    958       1.1  christos 	 otherwise it may result in 0x7fffffff (sparc compatibility) or
    959       1.1  christos 	 0x80000000 (C language compatibility). */
    960       1.1  christos       USI isr;
    961       1.1  christos       dtt = FRV_DTT_OVERFLOW;
    962       1.1  christos 
    963       1.1  christos       isr = GET_ISR ();
    964       1.1  christos       if (GET_ISR_EDE (isr))
    965       1.1  christos 	sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index,
    966       1.1  christos 			       0x7fffffff);
    967       1.1  christos       else
    968       1.1  christos 	sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index,
    969       1.1  christos 			       0x80000000);
    970       1.1  christos       frvbf_force_update (current_cpu); /* Force update of target register.  */
    971       1.1  christos     }
    972       1.1  christos   else if (arg2 == 0)
    973       1.1  christos     dtt = FRV_DTT_DIVISION_BY_ZERO;
    974       1.1  christos   else
    975       1.1  christos     sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index,
    976       1.1  christos 			   arg1 / arg2);
    977       1.1  christos 
    978       1.1  christos   /* Check for exceptions.  */
    979       1.1  christos   if (dtt != FRV_DTT_NO_EXCEPTION)
    980       1.1  christos     dtt = frvbf_division_exception (current_cpu, dtt, target_index,
    981       1.1  christos 				    non_excepting);
    982       1.1  christos   if (non_excepting && dtt == FRV_DTT_NO_EXCEPTION)
    983       1.1  christos     {
    984       1.1  christos       /* Non excepting instruction. Clear the NE flag for the target
    985       1.1  christos 	 register.  */
    986       1.1  christos       SI NE_flags[2];
    987       1.1  christos       GET_NE_FLAGS (NE_flags, H_SPR_GNER0);
    988       1.1  christos       CLEAR_NE_FLAG (NE_flags, target_index);
    989       1.1  christos       SET_NE_FLAGS (H_SPR_GNER0, NE_flags);
    990       1.1  christos     }
    991       1.1  christos }
    992       1.1  christos 
    993       1.1  christos void
    994       1.1  christos frvbf_unsigned_integer_divide (
    995       1.1  christos   SIM_CPU *current_cpu, USI arg1, USI arg2, int target_index, int non_excepting
    996       1.1  christos )
    997       1.1  christos {
    998       1.1  christos   if (arg2 == 0)
    999       1.1  christos     frvbf_division_exception (current_cpu, FRV_DTT_DIVISION_BY_ZERO,
   1000       1.1  christos 			      target_index, non_excepting);
   1001       1.1  christos   else
   1002       1.1  christos     {
   1003       1.1  christos       sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index,
   1004       1.1  christos 			     arg1 / arg2);
   1005       1.1  christos       if (non_excepting)
   1006       1.1  christos 	{
   1007       1.1  christos 	  /* Non excepting instruction. Clear the NE flag for the target
   1008       1.1  christos 	     register.  */
   1009       1.1  christos 	  SI NE_flags[2];
   1010       1.1  christos 	  GET_NE_FLAGS (NE_flags, H_SPR_GNER0);
   1011       1.1  christos 	  CLEAR_NE_FLAG (NE_flags, target_index);
   1012       1.1  christos 	  SET_NE_FLAGS (H_SPR_GNER0, NE_flags);
   1013       1.1  christos 	}
   1014       1.1  christos     }
   1015       1.1  christos }
   1016       1.1  christos 
   1017       1.1  christos /* Clear accumulators.  */
   1019       1.1  christos void
   1020       1.1  christos frvbf_clear_accumulators (SIM_CPU *current_cpu, SI acc_ix, int A)
   1021       1.1  christos {
   1022       1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
   1023       1.1  christos   int acc_mask =
   1024       1.1  christos     (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr500) ? 7 :
   1025       1.1  christos     (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) ? 7 :
   1026       1.1  christos     (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450) ? 11 :
   1027       1.1  christos     (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400) ? 3 :
   1028       1.1  christos     63;
   1029       1.1  christos   FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu);
   1030       1.1  christos 
   1031       1.1  christos   ps->mclracc_acc = acc_ix;
   1032       1.1  christos   ps->mclracc_A   = A;
   1033       1.1  christos   if (A == 0 || acc_ix != 0) /* Clear 1 accumuator?  */
   1034       1.1  christos     {
   1035       1.1  christos       /* This instruction is a nop if the referenced accumulator is not
   1036       1.1  christos 	 implemented. */
   1037       1.1  christos       if ((acc_ix & acc_mask) == acc_ix)
   1038       1.1  christos 	sim_queue_fn_di_write (current_cpu, frvbf_h_acc40S_set, acc_ix, 0);
   1039       1.1  christos     }
   1040       1.1  christos   else
   1041       1.1  christos     {
   1042       1.1  christos       /* Clear all implemented accumulators.  */
   1043       1.1  christos       int i;
   1044       1.1  christos       for (i = 0; i <= acc_mask; ++i)
   1045       1.1  christos 	if ((i & acc_mask) == i)
   1046       1.1  christos 	  sim_queue_fn_di_write (current_cpu, frvbf_h_acc40S_set, i, 0);
   1047       1.1  christos     }
   1048       1.1  christos }
   1049       1.1  christos 
   1050       1.1  christos /* Functions to aid insn semantics.  */
   1052       1.1  christos 
   1053       1.1  christos /* Compute the result of the SCAN and SCANI insns after the shift and xor.  */
   1054       1.1  christos SI
   1055       1.1  christos frvbf_scan_result (SIM_CPU *current_cpu, SI value)
   1056       1.1  christos {
   1057       1.1  christos   SI i;
   1058       1.1  christos   SI mask;
   1059       1.1  christos 
   1060       1.1  christos   if (value == 0)
   1061       1.1  christos     return 63;
   1062       1.1  christos 
   1063       1.1  christos   /* Find the position of the first non-zero bit.
   1064       1.1  christos      The loop will terminate since there is guaranteed to be at least one
   1065       1.1  christos      non-zero bit.  */
   1066       1.1  christos   mask = 1 << (sizeof (mask) * 8 - 1);
   1067       1.1  christos   for (i = 0; (value & mask) == 0; ++i)
   1068       1.1  christos     value <<= 1;
   1069       1.1  christos 
   1070       1.1  christos   return i;
   1071       1.1  christos }
   1072       1.1  christos 
   1073       1.1  christos /* Compute the result of the cut insns.  */
   1074       1.1  christos SI
   1075       1.1  christos frvbf_cut (SIM_CPU *current_cpu, SI reg1, SI reg2, SI cut_point)
   1076       1.1  christos {
   1077       1.1  christos   SI result;
   1078       1.1  christos   cut_point &= 0x3f;
   1079       1.1  christos   if (cut_point < 32)
   1080       1.1  christos     {
   1081       1.1  christos       result = reg1 << cut_point;
   1082       1.1  christos       result |= (reg2 >> (32 - cut_point)) & ((1 << cut_point) - 1);
   1083       1.1  christos     }
   1084       1.1  christos   else
   1085       1.1  christos     result = reg2 << (cut_point - 32);
   1086       1.1  christos 
   1087       1.1  christos   return result;
   1088       1.1  christos }
   1089       1.1  christos 
   1090       1.1  christos /* Compute the result of the cut insns.  */
   1091       1.1  christos SI
   1092       1.1  christos frvbf_media_cut (SIM_CPU *current_cpu, DI acc, SI cut_point)
   1093       1.1  christos {
   1094       1.1  christos   /* The cut point is the lower 6 bits (signed) of what we are passed.  */
   1095       1.1  christos   cut_point = cut_point << 26 >> 26;
   1096       1.1  christos 
   1097       1.1  christos   /* The cut_point is relative to bit 40 of 64 bits.  */
   1098       1.1  christos   if (cut_point >= 0)
   1099       1.1  christos     return (acc << (cut_point + 24)) >> 32;
   1100       1.1  christos 
   1101       1.1  christos   /* Extend the sign bit (bit 40) for negative cuts.  */
   1102       1.1  christos   if (cut_point == -32)
   1103       1.1  christos     return (acc << 24) >> 63; /* Special case for full shiftout.  */
   1104       1.1  christos 
   1105       1.1  christos   return (acc << 24) >> (32 + -cut_point);
   1106       1.1  christos }
   1107       1.1  christos 
   1108       1.1  christos /* Compute the result of the cut insns.  */
   1109       1.1  christos SI
   1110       1.1  christos frvbf_media_cut_ss (SIM_CPU *current_cpu, DI acc, SI cut_point)
   1111       1.1  christos {
   1112       1.1  christos   /* The cut point is the lower 6 bits (signed) of what we are passed.  */
   1113       1.1  christos   cut_point = cut_point << 26 >> 26;
   1114       1.1  christos 
   1115       1.1  christos   if (cut_point >= 0)
   1116       1.1  christos     {
   1117       1.1  christos       /* The cut_point is relative to bit 40 of 64 bits.  */
   1118       1.1  christos       DI shifted = acc << (cut_point + 24);
   1119       1.1  christos       DI unshifted = shifted >> (cut_point + 24);
   1120       1.1  christos 
   1121       1.1  christos       /* The result will be saturated if significant bits are shifted out.  */
   1122       1.1  christos       if (unshifted != acc)
   1123       1.1  christos 	{
   1124       1.1  christos 	  if (acc < 0)
   1125       1.1  christos 	    return 0x80000000;
   1126       1.1  christos 	  return 0x7fffffff;
   1127       1.1  christos 	}
   1128       1.1  christos     }
   1129       1.1  christos 
   1130       1.1  christos   /* The result will not be saturated, so use the code for the normal cut.  */
   1131       1.1  christos   return frvbf_media_cut (current_cpu, acc, cut_point);
   1132       1.1  christos }
   1133       1.1  christos 
   1134       1.1  christos /* Compute the result of int accumulator cut (SCUTSS).  */
   1135       1.1  christos SI
   1136       1.1  christos frvbf_iacc_cut (SIM_CPU *current_cpu, DI acc, SI cut_point)
   1137       1.1  christos {
   1138       1.1  christos   DI lower, upper;
   1139       1.1  christos 
   1140       1.1  christos   /* The cut point is the lower 7 bits (signed) of what we are passed.  */
   1141       1.1  christos   cut_point = cut_point << 25 >> 25;
   1142       1.1  christos 
   1143       1.1  christos   /* Conceptually, the operation is on a 128-bit sign-extension of ACC.
   1144       1.1  christos      The top bit of the return value corresponds to bit (63 - CUT_POINT)
   1145       1.1  christos      of this 128-bit value.
   1146       1.1  christos 
   1147       1.1  christos      Since we can't deal with 128-bit values very easily, convert the
   1148       1.1  christos      operation into an equivalent 64-bit one.  */
   1149       1.1  christos   if (cut_point < 0)
   1150       1.1  christos     {
   1151       1.1  christos       /* Avoid an undefined shift operation.  */
   1152       1.1  christos       if (cut_point == -64)
   1153       1.1  christos 	acc >>= 63;
   1154       1.1  christos       else
   1155       1.1  christos 	acc >>= -cut_point;
   1156       1.1  christos       cut_point = 0;
   1157       1.1  christos     }
   1158       1.1  christos 
   1159       1.1  christos   /* Get the shifted but unsaturated result.  Set LOWER to the lowest
   1160       1.1  christos      32 bits of the result and UPPER to the result >> 31.  */
   1161       1.1  christos   if (cut_point < 32)
   1162       1.1  christos     {
   1163       1.1  christos       /* The cut loses the (32 - CUT_POINT) least significant bits.
   1164       1.1  christos 	 Round the result up if the most significant of these lost bits
   1165       1.1  christos 	 is 1.  */
   1166       1.1  christos       lower = acc >> (32 - cut_point);
   1167       1.1  christos       if (lower < 0x7fffffff)
   1168       1.1  christos 	if (acc & LSBIT64 (32 - cut_point - 1))
   1169       1.1  christos 	  lower++;
   1170       1.1  christos       upper = lower >> 31;
   1171       1.1  christos     }
   1172       1.1  christos   else
   1173       1.1  christos     {
   1174       1.1  christos       lower = acc << (cut_point - 32);
   1175       1.1  christos       upper = acc >> (63 - cut_point);
   1176       1.1  christos     }
   1177       1.1  christos 
   1178       1.1  christos   /* Saturate the result.  */
   1179       1.1  christos   if (upper < -1)
   1180       1.1  christos     return ~0x7fffffff;
   1181   1.1.1.9  christos   else if (upper > 0)
   1182   1.1.1.9  christos     return 0x7fffffff;
   1183   1.1.1.9  christos   else
   1184   1.1.1.9  christos     return lower;
   1185   1.1.1.9  christos }
   1186   1.1.1.9  christos 
   1187       1.1  christos /* Compute the result of shift-left-arithmetic-with-saturation (SLASS).  */
   1188       1.1  christos SI
   1189       1.1  christos frvbf_shift_left_arith_saturate (SIM_CPU *current_cpu, SI arg1, SI arg2)
   1190       1.1  christos {
   1191       1.1  christos   int neg_arg1;
   1192       1.1  christos 
   1193       1.1  christos   /* FIXME: what to do with negative shift amt?  */
   1194       1.1  christos   if (arg2 <= 0)
   1195       1.1  christos     return arg1;
   1196       1.1  christos 
   1197       1.1  christos   if (arg1 == 0)
   1198       1.1  christos     return 0;
   1199       1.1  christos 
   1200       1.1  christos   /* Signed shift by 31 or greater saturates by definition.  */
   1201       1.1  christos   if (arg2 >= 31)
   1202       1.1  christos     {
   1203       1.1  christos       if (arg1 > 0)
   1204       1.1  christos 	return (SI) 0x7fffffff;
   1205       1.1  christos       else
   1206       1.1  christos 	return (SI) 0x80000000;
   1207       1.1  christos     }
   1208       1.1  christos 
   1209       1.1  christos   /* OK, arg2 is between 1 and 31.  */
   1210       1.1  christos   neg_arg1 = (arg1 < 0);
   1211       1.1  christos   do {
   1212       1.1  christos     arg1 <<= 1;
   1213       1.1  christos     /* Check for sign bit change (saturation).  */
   1214       1.1  christos     if (neg_arg1 && (arg1 >= 0))
   1215       1.1  christos       return (SI) 0x80000000;
   1216       1.1  christos     else if (!neg_arg1 && (arg1 < 0))
   1217       1.1  christos       return (SI) 0x7fffffff;
   1218       1.1  christos   } while (--arg2 > 0);
   1219       1.1  christos 
   1220       1.1  christos   return arg1;
   1221       1.1  christos }
   1222       1.1  christos 
   1223       1.1  christos /* Simulate the media custom insns.  */
   1224       1.1  christos void
   1225       1.1  christos frvbf_media_cop (SIM_CPU *current_cpu, int cop_num)
   1226       1.1  christos {
   1227       1.1  christos   /* The semantics of the insn are a nop, since it is implementation defined.
   1228       1.1  christos      We do need to check whether it's implemented and set up for MTRAP
   1229       1.1  christos      if it's not.  */
   1230       1.1  christos   USI msr0 = GET_MSR (0);
   1231       1.1  christos   if (GET_MSR_EMCI (msr0) == 0)
   1232       1.1  christos     {
   1233       1.1  christos       /* no interrupt queued at this time.  */
   1234       1.1  christos       frv_set_mp_exception_registers (current_cpu, MTT_UNIMPLEMENTED_MPOP, 0);
   1235       1.1  christos     }
   1236       1.1  christos }
   1237       1.1  christos 
   1238       1.1  christos /* Simulate the media average (MAVEH) insn.  */
   1239       1.1  christos static HI
   1240       1.1  christos do_media_average (SIM_CPU *current_cpu, HI arg1, HI arg2)
   1241       1.1  christos {
   1242       1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
   1243       1.1  christos   SI sum = (arg1 + arg2);
   1244       1.1  christos   HI result = sum >> 1;
   1245       1.1  christos   int rounding_value;
   1246       1.1  christos 
   1247       1.1  christos   /* On fr4xx and fr550, check the rounding mode.  On other machines
   1248       1.1  christos      rounding is always toward negative infinity and the result is
   1249       1.1  christos      already correctly rounded.  */
   1250       1.1  christos   switch (STATE_ARCHITECTURE (sd)->mach)
   1251       1.1  christos     {
   1252       1.1  christos       /* Need to check rounding mode. */
   1253       1.1  christos     case bfd_mach_fr400:
   1254       1.1  christos     case bfd_mach_fr450:
   1255       1.1  christos     case bfd_mach_fr550:
   1256       1.1  christos       /* Check whether rounding will be required.  Rounding will be required
   1257       1.1  christos 	 if the sum is an odd number.  */
   1258       1.1  christos       rounding_value = sum & 1;
   1259       1.1  christos       if (rounding_value)
   1260       1.1  christos 	{
   1261       1.1  christos 	  USI msr0 = GET_MSR (0);
   1262       1.1  christos 	  /* Check MSR0.SRDAV to determine which bits control the rounding.  */
   1263       1.1  christos 	  if (GET_MSR_SRDAV (msr0))
   1264       1.1  christos 	    {
   1265       1.1  christos 	      /* MSR0.RD controls rounding.  */
   1266       1.1  christos 	      switch (GET_MSR_RD (msr0))
   1267       1.1  christos 		{
   1268       1.1  christos 		case 0:
   1269       1.1  christos 		  /* Round to nearest.  */
   1270       1.1  christos 		  if (result >= 0)
   1271       1.1  christos 		    ++result;
   1272       1.1  christos 		  break;
   1273       1.1  christos 		case 1:
   1274       1.1  christos 		  /* Round toward 0. */
   1275       1.1  christos 		  if (result < 0)
   1276       1.1  christos 		    ++result;
   1277       1.1  christos 		  break;
   1278       1.1  christos 		case 2:
   1279       1.1  christos 		  /* Round toward positive infinity.  */
   1280       1.1  christos 		  ++result;
   1281       1.1  christos 		  break;
   1282       1.1  christos 		case 3:
   1283       1.1  christos 		  /* Round toward negative infinity.  The result is already
   1284       1.1  christos 		     correctly rounded.  */
   1285       1.1  christos 		  break;
   1286       1.1  christos 		default:
   1287       1.1  christos 		  abort ();
   1288       1.1  christos 		  break;
   1289       1.1  christos 		}
   1290       1.1  christos 	    }
   1291       1.1  christos 	  else
   1292       1.1  christos 	    {
   1293       1.1  christos 	      /* MSR0.RDAV controls rounding.  If set, round toward positive
   1294       1.1  christos 		 infinity.  Otherwise the result is already rounded correctly
   1295       1.1  christos 		 toward negative infinity.  */
   1296       1.1  christos 	      if (GET_MSR_RDAV (msr0))
   1297       1.1  christos 		++result;
   1298       1.1  christos 	    }
   1299       1.1  christos 	}
   1300       1.1  christos       break;
   1301       1.1  christos     default:
   1302       1.1  christos       break;
   1303       1.1  christos     }
   1304       1.1  christos 
   1305       1.1  christos   return result;
   1306       1.1  christos }
   1307       1.1  christos 
   1308       1.1  christos SI
   1309       1.1  christos frvbf_media_average (SIM_CPU *current_cpu, SI reg1, SI reg2)
   1310       1.1  christos {
   1311       1.1  christos   SI result;
   1312       1.1  christos   result  = do_media_average (current_cpu, reg1 & 0xffff, reg2 & 0xffff);
   1313       1.1  christos   result &= 0xffff;
   1314       1.1  christos   result |= do_media_average (current_cpu, (reg1 >> 16) & 0xffff,
   1315       1.1  christos 			      (reg2 >> 16) & 0xffff) << 16;
   1316       1.1  christos   return result;
   1317       1.1  christos }
   1318       1.1  christos 
   1319       1.1  christos /* Maintain a flag in order to know when to write the address of the next
   1320       1.1  christos    VLIW instruction into the LR register.  Used by JMPL. JMPIL, and CALL.  */
   1321       1.1  christos void
   1322       1.1  christos frvbf_set_write_next_vliw_addr_to_LR (SIM_CPU *current_cpu, int value)
   1323       1.1  christos {
   1324       1.1  christos   frvbf_write_next_vliw_addr_to_LR = value;
   1325       1.1  christos }
   1326       1.1  christos 
   1327       1.1  christos void
   1328       1.1  christos frvbf_set_ne_index (SIM_CPU *current_cpu, int index)
   1329       1.1  christos {
   1330       1.1  christos   USI NE_flags[2];
   1331       1.1  christos 
   1332       1.1  christos   /* Save the target register so interrupt processing can set its NE flag
   1333       1.1  christos      in the event of an exception.  */
   1334       1.1  christos   frv_interrupt_state.ne_index = index;
   1335       1.1  christos 
   1336       1.1  christos   /* Clear the NE flag of the target register. It will be reset if necessary
   1337       1.1  christos      in the event of an exception.  */
   1338       1.1  christos   GET_NE_FLAGS (NE_flags, H_SPR_FNER0);
   1339       1.1  christos   CLEAR_NE_FLAG (NE_flags, index);
   1340       1.1  christos   SET_NE_FLAGS (H_SPR_FNER0, NE_flags);
   1341       1.1  christos }
   1342       1.1  christos 
   1343       1.1  christos void
   1344       1.1  christos frvbf_force_update (SIM_CPU *current_cpu)
   1345       1.1  christos {
   1346       1.1  christos   CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (current_cpu);
   1347       1.1  christos   int ix = CGEN_WRITE_QUEUE_INDEX (q);
   1348       1.1  christos   if (ix > 0)
   1349       1.1  christos     {
   1350       1.1  christos       CGEN_WRITE_QUEUE_ELEMENT *item = CGEN_WRITE_QUEUE_ELEMENT (q, ix - 1);
   1351       1.1  christos       item->flags |= FRV_WRITE_QUEUE_FORCE_WRITE;
   1352       1.1  christos     }
   1353       1.1  christos }
   1354       1.1  christos 
   1355       1.1  christos /* Condition code logic.  */
   1357       1.1  christos enum cr_ops {
   1358       1.1  christos   andcr, orcr, xorcr, nandcr, norcr, andncr, orncr, nandncr, norncr,
   1359       1.1  christos   num_cr_ops
   1360       1.1  christos };
   1361       1.1  christos 
   1362       1.1  christos enum cr_result {cr_undefined, cr_undefined1, cr_false, cr_true};
   1363       1.1  christos 
   1364       1.1  christos static enum cr_result
   1365       1.1  christos cr_logic[num_cr_ops][4][4] = {
   1366       1.1  christos   /* andcr */
   1367       1.1  christos   {
   1368       1.1  christos     /*                undefined     undefined       false         true */
   1369       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
   1370       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
   1371       1.1  christos     /* false     */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
   1372       1.1  christos     /* true      */ {cr_undefined, cr_undefined, cr_false,     cr_true     }
   1373       1.1  christos   },
   1374       1.1  christos   /* orcr */
   1375       1.1  christos   {
   1376       1.1  christos     /*                undefined     undefined       false         true */
   1377       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_false,     cr_true     },
   1378       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_false,     cr_true     },
   1379       1.1  christos     /* false     */ {cr_false,     cr_false,     cr_false,     cr_true     },
   1380       1.1  christos     /* true      */ {cr_true,      cr_true,      cr_true,      cr_true     }
   1381       1.1  christos   },
   1382       1.1  christos   /* xorcr */
   1383       1.1  christos   {
   1384       1.1  christos     /*                undefined     undefined       false         true */
   1385       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
   1386       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
   1387       1.1  christos     /* false     */ {cr_undefined, cr_undefined, cr_false,     cr_true     },
   1388       1.1  christos     /* true      */ {cr_true,      cr_true,      cr_true,      cr_false    }
   1389       1.1  christos   },
   1390       1.1  christos   /* nandcr */
   1391       1.1  christos   {
   1392       1.1  christos     /*                undefined     undefined       false         true */
   1393       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
   1394       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
   1395       1.1  christos     /* false     */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
   1396       1.1  christos     /* true      */ {cr_undefined, cr_undefined, cr_true,      cr_false    }
   1397       1.1  christos   },
   1398       1.1  christos   /* norcr */
   1399       1.1  christos   {
   1400       1.1  christos     /*                undefined     undefined       false         true */
   1401       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_true,      cr_false    },
   1402       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_true,      cr_false    },
   1403       1.1  christos     /* false     */ {cr_true,      cr_true,      cr_true,      cr_false    },
   1404       1.1  christos     /* true      */ {cr_false,     cr_false,     cr_false,     cr_false    }
   1405       1.1  christos   },
   1406       1.1  christos   /* andncr */
   1407       1.1  christos   {
   1408       1.1  christos     /*                undefined     undefined       false         true */
   1409       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
   1410       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
   1411       1.1  christos     /* false     */ {cr_undefined, cr_undefined, cr_false,     cr_true     },
   1412       1.1  christos     /* true      */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}
   1413       1.1  christos   },
   1414       1.1  christos   /* orncr */
   1415       1.1  christos   {
   1416       1.1  christos     /*                undefined     undefined       false         true */
   1417       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_false,     cr_true     },
   1418       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_false,     cr_true     },
   1419       1.1  christos     /* false     */ {cr_true,      cr_true,      cr_true,      cr_true     },
   1420       1.1  christos     /* true      */ {cr_false,     cr_false,     cr_false,     cr_true     }
   1421       1.1  christos   },
   1422       1.1  christos   /* nandncr */
   1423       1.1  christos   {
   1424       1.1  christos     /*                undefined     undefined       false         true */
   1425       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
   1426       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
   1427       1.1  christos     /* false     */ {cr_undefined, cr_undefined, cr_true,      cr_false    },
   1428       1.1  christos     /* true      */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}
   1429       1.1  christos   },
   1430       1.1  christos   /* norncr */
   1431       1.1  christos   {
   1432       1.1  christos     /*                undefined     undefined       false         true */
   1433       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_true,      cr_false    },
   1434       1.1  christos     /* undefined */ {cr_undefined, cr_undefined, cr_true,      cr_false    },
   1435       1.1  christos     /* false     */ {cr_false,     cr_false,     cr_false,     cr_false    },
   1436       1.1  christos     /* true      */ {cr_true,      cr_true,      cr_true,      cr_false    }
   1437       1.1  christos   }
   1438       1.1  christos };
   1439       1.1  christos 
   1440       1.1  christos UQI
   1441       1.1  christos frvbf_cr_logic (SIM_CPU *current_cpu, SI operation, UQI arg1, UQI arg2)
   1442       1.1  christos {
   1443       1.1  christos   return cr_logic[operation][arg1][arg2];
   1444       1.1  christos }
   1445       1.1  christos 
   1446       1.1  christos /* Cache Manipulation.  */
   1448       1.1  christos void
   1449       1.1  christos frvbf_insn_cache_preload (SIM_CPU *current_cpu, SI address, USI length, int lock)
   1450       1.1  christos {
   1451       1.1  christos   /* If we need to count cycles, then the cache operation will be
   1452       1.1  christos      initiated from the model profiling functions.
   1453       1.1  christos      See frvbf_model_....  */
   1454       1.1  christos   int hsr0 = GET_HSR0 ();
   1455       1.1  christos   if (GET_HSR0_ICE (hsr0))
   1456       1.1  christos     {
   1457       1.1  christos       if (model_insn)
   1458       1.1  christos 	{
   1459       1.1  christos 	  CPU_LOAD_ADDRESS (current_cpu) = address;
   1460       1.1  christos 	  CPU_LOAD_LENGTH (current_cpu) = length;
   1461       1.1  christos 	  CPU_LOAD_LOCK (current_cpu) = lock;
   1462       1.1  christos 	}
   1463       1.1  christos       else
   1464       1.1  christos 	{
   1465       1.1  christos 	  FRV_CACHE *cache = CPU_INSN_CACHE (current_cpu);
   1466       1.1  christos 	  frv_cache_preload (cache, address, length, lock);
   1467       1.1  christos 	}
   1468       1.1  christos     }
   1469       1.1  christos }
   1470       1.1  christos 
   1471       1.1  christos void
   1472       1.1  christos frvbf_data_cache_preload (SIM_CPU *current_cpu, SI address, USI length, int lock)
   1473       1.1  christos {
   1474       1.1  christos   /* If we need to count cycles, then the cache operation will be
   1475       1.1  christos      initiated from the model profiling functions.
   1476       1.1  christos      See frvbf_model_....  */
   1477       1.1  christos   int hsr0 = GET_HSR0 ();
   1478       1.1  christos   if (GET_HSR0_DCE (hsr0))
   1479       1.1  christos     {
   1480       1.1  christos       if (model_insn)
   1481       1.1  christos 	{
   1482       1.1  christos 	  CPU_LOAD_ADDRESS (current_cpu) = address;
   1483       1.1  christos 	  CPU_LOAD_LENGTH (current_cpu) = length;
   1484       1.1  christos 	  CPU_LOAD_LOCK (current_cpu) = lock;
   1485       1.1  christos 	}
   1486       1.1  christos       else
   1487       1.1  christos 	{
   1488       1.1  christos 	  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
   1489       1.1  christos 	  frv_cache_preload (cache, address, length, lock);
   1490       1.1  christos 	}
   1491       1.1  christos     }
   1492       1.1  christos }
   1493       1.1  christos 
   1494       1.1  christos void
   1495       1.1  christos frvbf_insn_cache_unlock (SIM_CPU *current_cpu, SI address)
   1496       1.1  christos {
   1497       1.1  christos   /* If we need to count cycles, then the cache operation will be
   1498       1.1  christos      initiated from the model profiling functions.
   1499       1.1  christos      See frvbf_model_....  */
   1500       1.1  christos   int hsr0 = GET_HSR0 ();
   1501       1.1  christos   if (GET_HSR0_ICE (hsr0))
   1502       1.1  christos     {
   1503       1.1  christos       if (model_insn)
   1504       1.1  christos 	CPU_LOAD_ADDRESS (current_cpu) = address;
   1505       1.1  christos       else
   1506       1.1  christos 	{
   1507       1.1  christos 	  FRV_CACHE *cache = CPU_INSN_CACHE (current_cpu);
   1508       1.1  christos 	  frv_cache_unlock (cache, address);
   1509       1.1  christos 	}
   1510       1.1  christos     }
   1511       1.1  christos }
   1512       1.1  christos 
   1513       1.1  christos void
   1514       1.1  christos frvbf_data_cache_unlock (SIM_CPU *current_cpu, SI address)
   1515       1.1  christos {
   1516       1.1  christos   /* If we need to count cycles, then the cache operation will be
   1517       1.1  christos      initiated from the model profiling functions.
   1518       1.1  christos      See frvbf_model_....  */
   1519       1.1  christos   int hsr0 = GET_HSR0 ();
   1520       1.1  christos   if (GET_HSR0_DCE (hsr0))
   1521       1.1  christos     {
   1522       1.1  christos       if (model_insn)
   1523       1.1  christos 	CPU_LOAD_ADDRESS (current_cpu) = address;
   1524       1.1  christos       else
   1525       1.1  christos 	{
   1526       1.1  christos 	  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
   1527       1.1  christos 	  frv_cache_unlock (cache, address);
   1528       1.1  christos 	}
   1529       1.1  christos     }
   1530       1.1  christos }
   1531       1.1  christos 
   1532       1.1  christos void
   1533       1.1  christos frvbf_insn_cache_invalidate (SIM_CPU *current_cpu, SI address, int all)
   1534       1.1  christos {
   1535       1.1  christos   /* Make sure the insn was specified properly.  -1 will be passed for ALL
   1536       1.1  christos      for a icei with A=0.  */
   1537       1.1  christos   if (all == -1)
   1538       1.1  christos     {
   1539       1.1  christos       frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
   1540       1.1  christos       return;
   1541       1.1  christos     }
   1542       1.1  christos 
   1543       1.1  christos   /* If we need to count cycles, then the cache operation will be
   1544       1.1  christos      initiated from the model profiling functions.
   1545       1.1  christos      See frvbf_model_....  */
   1546       1.1  christos   if (model_insn)
   1547       1.1  christos     {
   1548       1.1  christos       /* Record the all-entries flag for use in profiling.  */
   1549       1.1  christos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu);
   1550       1.1  christos       ps->all_cache_entries = all;
   1551       1.1  christos       CPU_LOAD_ADDRESS (current_cpu) = address;
   1552       1.1  christos     }
   1553       1.1  christos   else
   1554       1.1  christos     {
   1555       1.1  christos       FRV_CACHE *cache = CPU_INSN_CACHE (current_cpu);
   1556       1.1  christos       if (all)
   1557       1.1  christos 	frv_cache_invalidate_all (cache, 0/* flush? */);
   1558       1.1  christos       else
   1559       1.1  christos 	frv_cache_invalidate (cache, address, 0/* flush? */);
   1560       1.1  christos     }
   1561       1.1  christos }
   1562       1.1  christos 
   1563       1.1  christos void
   1564       1.1  christos frvbf_data_cache_invalidate (SIM_CPU *current_cpu, SI address, int all)
   1565       1.1  christos {
   1566       1.1  christos   /* Make sure the insn was specified properly.  -1 will be passed for ALL
   1567       1.1  christos      for a dcei with A=0.  */
   1568       1.1  christos   if (all == -1)
   1569       1.1  christos     {
   1570       1.1  christos       frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
   1571       1.1  christos       return;
   1572       1.1  christos     }
   1573       1.1  christos 
   1574       1.1  christos   /* If we need to count cycles, then the cache operation will be
   1575       1.1  christos      initiated from the model profiling functions.
   1576       1.1  christos      See frvbf_model_....  */
   1577       1.1  christos   if (model_insn)
   1578       1.1  christos     {
   1579       1.1  christos       /* Record the all-entries flag for use in profiling.  */
   1580       1.1  christos       FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu);
   1581       1.1  christos       ps->all_cache_entries = all;
   1582       1.1  christos       CPU_LOAD_ADDRESS (current_cpu) = address;
   1583       1.1  christos     }
   1584       1.1  christos   else
   1585       1.1  christos     {
   1586       1.1  christos       FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
   1587       1.1  christos       if (all)
   1588       1.1  christos 	frv_cache_invalidate_all (cache, 0/* flush? */);
   1589       1.1  christos       else
   1590       1.1  christos 	frv_cache_invalidate (cache, address, 0/* flush? */);
   1591       1.1  christos     }
   1592       1.1  christos }
   1593       1.1  christos 
   1594       1.1  christos void
   1595       1.1  christos frvbf_data_cache_flush (SIM_CPU *current_cpu, SI address, int all)
   1596       1.1  christos {
   1597       1.1  christos   /* Make sure the insn was specified properly.  -1 will be passed for ALL
   1598       1.1  christos      for a dcef with A=0.  */
   1599       1.1  christos   if (all == -1)
   1600       1.1  christos     {
   1601                           frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
   1602                           return;
   1603                         }
   1604                     
   1605                       /* If we need to count cycles, then the cache operation will be
   1606                          initiated from the model profiling functions.
   1607                          See frvbf_model_....  */
   1608                       if (model_insn)
   1609                         {
   1610                           /* Record the all-entries flag for use in profiling.  */
   1611                           FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu);
   1612                           ps->all_cache_entries = all;
   1613                           CPU_LOAD_ADDRESS (current_cpu) = address;
   1614                         }
   1615                       else
   1616                         {
   1617                           FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
   1618                           if (all)
   1619                     	frv_cache_invalidate_all (cache, 1/* flush? */);
   1620                           else
   1621                     	frv_cache_invalidate (cache, address, 1/* flush? */);
   1622                         }
   1623                     }
   1624