Home | History | Annotate | Line # | Download | only in frv
      1       1.1  christos /* frv memory model.
      2  1.1.1.10  christos    Copyright (C) 1999-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 frvbf
     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 "bfd.h"
     29   1.1.1.9  christos #include <stdlib.h>
     30       1.1  christos 
     31       1.1  christos /* Check for alignment and access restrictions.  Return the corrected address.
     32       1.1  christos  */
     33       1.1  christos static SI
     34       1.1  christos fr400_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
     35       1.1  christos {
     36       1.1  christos   /* Check access restrictions for double word loads only.  */
     37       1.1  christos   if (align_mask == 7)
     38       1.1  christos     {
     39       1.1  christos       if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
     40       1.1  christos 	frv_queue_data_access_error_interrupt (current_cpu, address);
     41       1.1  christos     }
     42       1.1  christos   return address;
     43       1.1  christos }
     44       1.1  christos 
     45       1.1  christos static SI
     46       1.1  christos fr500_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
     47       1.1  christos {
     48       1.1  christos   if (address & align_mask)
     49       1.1  christos     {
     50       1.1  christos       frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
     51       1.1  christos       address &= ~align_mask;
     52       1.1  christos     }
     53       1.1  christos 
     54   1.1.1.9  christos   if (((USI)address >= 0xfeff0600 && (USI)address <= 0xfeff7fff)
     55   1.1.1.9  christos       || ((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff))
     56       1.1  christos     frv_queue_data_access_error_interrupt (current_cpu, address);
     57       1.1  christos 
     58       1.1  christos   return address;
     59       1.1  christos }
     60       1.1  christos 
     61       1.1  christos static SI
     62       1.1  christos fr550_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
     63       1.1  christos {
     64   1.1.1.9  christos   if (((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff)
     65       1.1  christos       || (align_mask > 0x3
     66       1.1  christos 	  && ((USI)address >= 0xfeff0000 && (USI)address <= 0xfeffffff)))
     67       1.1  christos     frv_queue_data_access_error_interrupt (current_cpu, address);
     68       1.1  christos 
     69       1.1  christos   return address;
     70       1.1  christos }
     71       1.1  christos 
     72       1.1  christos static SI
     73       1.1  christos check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
     74       1.1  christos {
     75       1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
     76       1.1  christos   switch (STATE_ARCHITECTURE (sd)->mach)
     77       1.1  christos     {
     78       1.1  christos     case bfd_mach_fr400:
     79       1.1  christos     case bfd_mach_fr450:
     80       1.1  christos       address = fr400_check_data_read_address (current_cpu, address,
     81       1.1  christos 					       align_mask);
     82       1.1  christos       break;
     83       1.1  christos     case bfd_mach_frvtomcat:
     84       1.1  christos     case bfd_mach_fr500:
     85       1.1  christos     case bfd_mach_frv:
     86       1.1  christos       address = fr500_check_data_read_address (current_cpu, address,
     87       1.1  christos 					       align_mask);
     88       1.1  christos       break;
     89       1.1  christos     case bfd_mach_fr550:
     90       1.1  christos       address = fr550_check_data_read_address (current_cpu, address,
     91       1.1  christos 					       align_mask);
     92       1.1  christos       break;
     93       1.1  christos     default:
     94       1.1  christos       break;
     95       1.1  christos     }
     96       1.1  christos 
     97       1.1  christos   return address;
     98       1.1  christos }
     99       1.1  christos 
    100       1.1  christos static SI
    101       1.1  christos fr400_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
    102       1.1  christos {
    103       1.1  christos   if (address & align_mask)
    104       1.1  christos     {
    105       1.1  christos       /* Make sure that this exception is not masked.  */
    106       1.1  christos       USI isr = GET_ISR ();
    107       1.1  christos       if (! GET_ISR_EMAM (isr))
    108       1.1  christos 	{
    109       1.1  christos 	  /* Bad alignment causes a data_access_error on fr400.  */
    110       1.1  christos 	  frv_queue_data_access_error_interrupt (current_cpu, address);
    111       1.1  christos 	}
    112       1.1  christos       address &= ~align_mask;
    113       1.1  christos     }
    114       1.1  christos   /* Nothing to check.  */
    115       1.1  christos   return address;
    116       1.1  christos }
    117       1.1  christos 
    118       1.1  christos static SI
    119       1.1  christos fr500_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
    120       1.1  christos {
    121   1.1.1.9  christos   if (((USI)address >= 0xfe000000 && (USI)address <= 0xfe003fff)
    122   1.1.1.9  christos       || ((USI)address >= 0xfe004000 && (USI)address <= 0xfe3fffff)
    123   1.1.1.9  christos       || ((USI)address >= 0xfe400000 && (USI)address <= 0xfe403fff)
    124   1.1.1.9  christos       || ((USI)address >= 0xfe404000 && (USI)address <= 0xfe7fffff))
    125       1.1  christos     frv_queue_data_access_exception_interrupt (current_cpu);
    126       1.1  christos 
    127       1.1  christos   return address;
    128       1.1  christos }
    129       1.1  christos 
    130       1.1  christos static SI
    131       1.1  christos fr550_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
    132       1.1  christos {
    133       1.1  christos   /* No alignment restrictions on fr550 */
    134       1.1  christos 
    135   1.1.1.9  christos   if (((USI)address >= 0xfe000000 && (USI)address <= 0xfe3fffff)
    136   1.1.1.9  christos       || ((USI)address >= 0xfe408000 && (USI)address <= 0xfe7fffff))
    137       1.1  christos     frv_queue_data_access_exception_interrupt (current_cpu);
    138       1.1  christos   else
    139       1.1  christos     {
    140       1.1  christos       USI hsr0 = GET_HSR0 ();
    141       1.1  christos       if (! GET_HSR0_RME (hsr0)
    142   1.1.1.9  christos 	  && ((USI)address >= 0xfe400000 && (USI)address <= 0xfe407fff))
    143       1.1  christos 	frv_queue_data_access_exception_interrupt (current_cpu);
    144       1.1  christos     }
    145       1.1  christos 
    146       1.1  christos   return address;
    147       1.1  christos }
    148       1.1  christos 
    149       1.1  christos static SI
    150       1.1  christos check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
    151       1.1  christos {
    152       1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
    153       1.1  christos   switch (STATE_ARCHITECTURE (sd)->mach)
    154       1.1  christos     {
    155       1.1  christos     case bfd_mach_fr400:
    156       1.1  christos     case bfd_mach_fr450:
    157       1.1  christos       address = fr400_check_readwrite_address (current_cpu, address,
    158       1.1  christos 						    align_mask);
    159       1.1  christos       break;
    160       1.1  christos     case bfd_mach_frvtomcat:
    161       1.1  christos     case bfd_mach_fr500:
    162       1.1  christos     case bfd_mach_frv:
    163       1.1  christos       address = fr500_check_readwrite_address (current_cpu, address,
    164       1.1  christos 						    align_mask);
    165       1.1  christos       break;
    166       1.1  christos     case bfd_mach_fr550:
    167       1.1  christos       address = fr550_check_readwrite_address (current_cpu, address,
    168       1.1  christos 					       align_mask);
    169       1.1  christos       break;
    170       1.1  christos     default:
    171       1.1  christos       break;
    172       1.1  christos     }
    173       1.1  christos 
    174       1.1  christos   return address;
    175       1.1  christos }
    176       1.1  christos 
    177       1.1  christos static PCADDR
    178       1.1  christos fr400_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
    179       1.1  christos 			       int align_mask)
    180       1.1  christos {
    181       1.1  christos   if (address & align_mask)
    182       1.1  christos     {
    183       1.1  christos       frv_queue_instruction_access_error_interrupt (current_cpu);
    184       1.1  christos       address &= ~align_mask;
    185       1.1  christos     }
    186       1.1  christos   else if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
    187       1.1  christos     frv_queue_instruction_access_error_interrupt (current_cpu);
    188       1.1  christos 
    189       1.1  christos   return address;
    190       1.1  christos }
    191       1.1  christos 
    192       1.1  christos static PCADDR
    193       1.1  christos fr500_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
    194       1.1  christos 			       int align_mask)
    195       1.1  christos {
    196       1.1  christos   if (address & align_mask)
    197       1.1  christos     {
    198       1.1  christos       frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
    199       1.1  christos       address &= ~align_mask;
    200       1.1  christos     }
    201       1.1  christos 
    202   1.1.1.9  christos   if (((USI)address >= 0xfeff0600 && (USI)address <= 0xfeff7fff)
    203   1.1.1.9  christos       || ((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff))
    204       1.1  christos     frv_queue_instruction_access_error_interrupt (current_cpu);
    205   1.1.1.9  christos   else if (((USI)address >= 0xfe004000 && (USI)address <= 0xfe3fffff)
    206   1.1.1.9  christos 	   || ((USI)address >= 0xfe400000 && (USI)address <= 0xfe403fff)
    207   1.1.1.9  christos 	   || ((USI)address >= 0xfe404000 && (USI)address <= 0xfe7fffff))
    208       1.1  christos     frv_queue_instruction_access_exception_interrupt (current_cpu);
    209       1.1  christos   else
    210       1.1  christos     {
    211       1.1  christos       USI hsr0 = GET_HSR0 ();
    212       1.1  christos       if (! GET_HSR0_RME (hsr0)
    213   1.1.1.9  christos 	  && ((USI)address >= 0xfe000000 && (USI)address <= 0xfe003fff))
    214       1.1  christos 	frv_queue_instruction_access_exception_interrupt (current_cpu);
    215       1.1  christos     }
    216       1.1  christos 
    217       1.1  christos   return address;
    218       1.1  christos }
    219       1.1  christos 
    220       1.1  christos static PCADDR
    221       1.1  christos fr550_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
    222       1.1  christos 			       int align_mask)
    223       1.1  christos {
    224       1.1  christos   address &= ~align_mask;
    225       1.1  christos 
    226       1.1  christos   if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
    227       1.1  christos     frv_queue_instruction_access_error_interrupt (current_cpu);
    228       1.1  christos   else if ((USI)address >= 0xfe008000 && (USI)address <= 0xfe7fffff)
    229       1.1  christos     frv_queue_instruction_access_exception_interrupt (current_cpu);
    230       1.1  christos   else
    231       1.1  christos     {
    232       1.1  christos       USI hsr0 = GET_HSR0 ();
    233       1.1  christos       if (! GET_HSR0_RME (hsr0)
    234       1.1  christos 	  && (USI)address >= 0xfe000000 && (USI)address <= 0xfe007fff)
    235       1.1  christos 	frv_queue_instruction_access_exception_interrupt (current_cpu);
    236       1.1  christos     }
    237       1.1  christos 
    238       1.1  christos   return address;
    239       1.1  christos }
    240       1.1  christos 
    241       1.1  christos static PCADDR
    242       1.1  christos check_insn_read_address (SIM_CPU *current_cpu, PCADDR address, int align_mask)
    243       1.1  christos {
    244       1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
    245       1.1  christos   switch (STATE_ARCHITECTURE (sd)->mach)
    246       1.1  christos     {
    247       1.1  christos     case bfd_mach_fr400:
    248       1.1  christos     case bfd_mach_fr450:
    249       1.1  christos       address = fr400_check_insn_read_address (current_cpu, address,
    250       1.1  christos 					       align_mask);
    251       1.1  christos       break;
    252       1.1  christos     case bfd_mach_frvtomcat:
    253       1.1  christos     case bfd_mach_fr500:
    254       1.1  christos     case bfd_mach_frv:
    255       1.1  christos       address = fr500_check_insn_read_address (current_cpu, address,
    256       1.1  christos 					       align_mask);
    257       1.1  christos       break;
    258       1.1  christos     case bfd_mach_fr550:
    259       1.1  christos       address = fr550_check_insn_read_address (current_cpu, address,
    260       1.1  christos 					       align_mask);
    261       1.1  christos       break;
    262       1.1  christos     default:
    263       1.1  christos       break;
    264       1.1  christos     }
    265       1.1  christos 
    266       1.1  christos   return address;
    267       1.1  christos }
    268       1.1  christos 
    269       1.1  christos /* Memory reads.  */
    270       1.1  christos QI
    271       1.1  christos frvbf_read_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address)
    272       1.1  christos {
    273       1.1  christos   USI hsr0 = GET_HSR0 ();
    274       1.1  christos   FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
    275       1.1  christos 
    276       1.1  christos   /* Check for access exceptions.  */
    277       1.1  christos   address = check_data_read_address (current_cpu, address, 0);
    278       1.1  christos   address = check_readwrite_address (current_cpu, address, 0);
    279       1.1  christos 
    280       1.1  christos   /* If we need to count cycles, then the cache operation will be
    281       1.1  christos      initiated from the model profiling functions.
    282       1.1  christos      See frvbf_model_....  */
    283       1.1  christos   if (model_insn)
    284       1.1  christos     {
    285       1.1  christos       CPU_LOAD_ADDRESS (current_cpu) = address;
    286       1.1  christos       CPU_LOAD_LENGTH (current_cpu) = 1;
    287       1.1  christos       CPU_LOAD_SIGNED (current_cpu) = 1;
    288       1.1  christos       return 0xb7; /* any random value */
    289       1.1  christos     }
    290       1.1  christos 
    291       1.1  christos   if (GET_HSR0_DCE (hsr0))
    292       1.1  christos     {
    293       1.1  christos       int cycles;
    294       1.1  christos       cycles = frv_cache_read (cache, 0, address);
    295       1.1  christos       if (cycles != 0)
    296       1.1  christos 	return CACHE_RETURN_DATA (cache, 0, address, QI, 1);
    297       1.1  christos     }
    298       1.1  christos 
    299       1.1  christos   return GETMEMQI (current_cpu, pc, address);
    300       1.1  christos }
    301       1.1  christos 
    302       1.1  christos UQI
    303       1.1  christos frvbf_read_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address)
    304       1.1  christos {
    305       1.1  christos   USI hsr0 = GET_HSR0 ();
    306       1.1  christos   FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
    307       1.1  christos 
    308       1.1  christos   /* Check for access exceptions.  */
    309       1.1  christos   address = check_data_read_address (current_cpu, address, 0);
    310       1.1  christos   address = check_readwrite_address (current_cpu, address, 0);
    311       1.1  christos 
    312       1.1  christos   /* If we need to count cycles, then the cache operation will be
    313       1.1  christos      initiated from the model profiling functions.
    314       1.1  christos      See frvbf_model_....  */
    315       1.1  christos   if (model_insn)
    316       1.1  christos     {
    317       1.1  christos       CPU_LOAD_ADDRESS (current_cpu) = address;
    318       1.1  christos       CPU_LOAD_LENGTH (current_cpu) = 1;
    319       1.1  christos       CPU_LOAD_SIGNED (current_cpu) = 0;
    320       1.1  christos       return 0xb7; /* any random value */
    321       1.1  christos     }
    322       1.1  christos 
    323       1.1  christos   if (GET_HSR0_DCE (hsr0))
    324       1.1  christos     {
    325       1.1  christos       int cycles;
    326       1.1  christos       cycles = frv_cache_read (cache, 0, address);
    327       1.1  christos       if (cycles != 0)
    328       1.1  christos 	return CACHE_RETURN_DATA (cache, 0, address, UQI, 1);
    329       1.1  christos     }
    330       1.1  christos 
    331       1.1  christos   return GETMEMUQI (current_cpu, pc, address);
    332       1.1  christos }
    333       1.1  christos 
    334       1.1  christos /* Read a HI which spans two cache lines */
    335       1.1  christos static HI
    336       1.1  christos read_mem_unaligned_HI (SIM_CPU *current_cpu, IADDR pc, SI address)
    337       1.1  christos {
    338       1.1  christos   HI value = frvbf_read_mem_QI (current_cpu, pc, address);
    339       1.1  christos   value <<= 8;
    340       1.1  christos   value |= frvbf_read_mem_UQI (current_cpu, pc, address + 1);
    341       1.1  christos   return T2H_2 (value);
    342       1.1  christos }
    343       1.1  christos 
    344       1.1  christos HI
    345       1.1  christos frvbf_read_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address)
    346       1.1  christos {
    347       1.1  christos   USI hsr0;
    348       1.1  christos   FRV_CACHE *cache;
    349       1.1  christos 
    350       1.1  christos   /* Check for access exceptions.  */
    351       1.1  christos   address = check_data_read_address (current_cpu, address, 1);
    352       1.1  christos   address = check_readwrite_address (current_cpu, address, 1);
    353       1.1  christos 
    354       1.1  christos   /* If we need to count cycles, then the cache operation will be
    355       1.1  christos      initiated from the model profiling functions.
    356       1.1  christos      See frvbf_model_....  */
    357       1.1  christos   hsr0 = GET_HSR0 ();
    358       1.1  christos   cache = CPU_DATA_CACHE (current_cpu);
    359       1.1  christos   if (model_insn)
    360       1.1  christos     {
    361       1.1  christos       CPU_LOAD_ADDRESS (current_cpu) = address;
    362       1.1  christos       CPU_LOAD_LENGTH (current_cpu) = 2;
    363       1.1  christos       CPU_LOAD_SIGNED (current_cpu) = 1;
    364       1.1  christos       return 0xb711; /* any random value */
    365       1.1  christos     }
    366       1.1  christos 
    367       1.1  christos   if (GET_HSR0_DCE (hsr0))
    368       1.1  christos     {
    369       1.1  christos       int cycles;
    370       1.1  christos       /* Handle access which crosses cache line boundary */
    371       1.1  christos       SIM_DESC sd = CPU_STATE (current_cpu);
    372       1.1  christos       if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
    373       1.1  christos 	{
    374       1.1  christos 	  if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
    375       1.1  christos 	    return read_mem_unaligned_HI (current_cpu, pc, address);
    376       1.1  christos 	}
    377       1.1  christos       cycles = frv_cache_read (cache, 0, address);
    378       1.1  christos       if (cycles != 0)
    379       1.1  christos 	return CACHE_RETURN_DATA (cache, 0, address, HI, 2);
    380       1.1  christos     }
    381       1.1  christos 
    382       1.1  christos   return GETMEMHI (current_cpu, pc, address);
    383       1.1  christos }
    384       1.1  christos 
    385       1.1  christos UHI
    386       1.1  christos frvbf_read_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address)
    387       1.1  christos {
    388       1.1  christos   USI hsr0;
    389       1.1  christos   FRV_CACHE *cache;
    390       1.1  christos 
    391       1.1  christos   /* Check for access exceptions.  */
    392       1.1  christos   address = check_data_read_address (current_cpu, address, 1);
    393       1.1  christos   address = check_readwrite_address (current_cpu, address, 1);
    394       1.1  christos 
    395       1.1  christos   /* If we need to count cycles, then the cache operation will be
    396       1.1  christos      initiated from the model profiling functions.
    397       1.1  christos      See frvbf_model_....  */
    398       1.1  christos   hsr0 = GET_HSR0 ();
    399       1.1  christos   cache = CPU_DATA_CACHE (current_cpu);
    400       1.1  christos   if (model_insn)
    401       1.1  christos     {
    402       1.1  christos       CPU_LOAD_ADDRESS (current_cpu) = address;
    403       1.1  christos       CPU_LOAD_LENGTH (current_cpu) = 2;
    404       1.1  christos       CPU_LOAD_SIGNED (current_cpu) = 0;
    405       1.1  christos       return 0xb711; /* any random value */
    406       1.1  christos     }
    407       1.1  christos 
    408       1.1  christos   if (GET_HSR0_DCE (hsr0))
    409       1.1  christos     {
    410       1.1  christos       int cycles;
    411       1.1  christos       /* Handle access which crosses cache line boundary */
    412       1.1  christos       SIM_DESC sd = CPU_STATE (current_cpu);
    413       1.1  christos       if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
    414       1.1  christos 	{
    415       1.1  christos 	  if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
    416       1.1  christos 	    return read_mem_unaligned_HI (current_cpu, pc, address);
    417       1.1  christos 	}
    418       1.1  christos       cycles = frv_cache_read (cache, 0, address);
    419       1.1  christos       if (cycles != 0)
    420       1.1  christos 	return CACHE_RETURN_DATA (cache, 0, address, UHI, 2);
    421       1.1  christos     }
    422       1.1  christos 
    423       1.1  christos   return GETMEMUHI (current_cpu, pc, address);
    424       1.1  christos }
    425       1.1  christos 
    426       1.1  christos /* Read a SI which spans two cache lines */
    427       1.1  christos static SI
    428       1.1  christos read_mem_unaligned_SI (SIM_CPU *current_cpu, IADDR pc, SI address)
    429       1.1  christos {
    430       1.1  christos   FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
    431       1.1  christos   unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
    432       1.1  christos   char valarray[4];
    433       1.1  christos   SI SIvalue;
    434       1.1  christos   HI HIvalue;
    435       1.1  christos 
    436       1.1  christos   switch (hi_len)
    437       1.1  christos     {
    438       1.1  christos     case 1:
    439       1.1  christos       valarray[0] = frvbf_read_mem_QI (current_cpu, pc, address);
    440       1.1  christos       SIvalue = frvbf_read_mem_SI (current_cpu, pc, address + 1);
    441       1.1  christos       SIvalue = H2T_4 (SIvalue);
    442       1.1  christos       memcpy (valarray + 1, (char*)&SIvalue, 3);
    443       1.1  christos       break;
    444       1.1  christos     case 2:
    445       1.1  christos       HIvalue = frvbf_read_mem_HI (current_cpu, pc, address);
    446       1.1  christos       HIvalue = H2T_2 (HIvalue);
    447       1.1  christos       memcpy (valarray, (char*)&HIvalue, 2);
    448       1.1  christos       HIvalue = frvbf_read_mem_HI (current_cpu, pc, address + 2);
    449       1.1  christos       HIvalue = H2T_2 (HIvalue);
    450       1.1  christos       memcpy (valarray + 2, (char*)&HIvalue, 2);
    451       1.1  christos       break;
    452       1.1  christos     case 3:
    453       1.1  christos       SIvalue = frvbf_read_mem_SI (current_cpu, pc, address - 1);
    454       1.1  christos       SIvalue = H2T_4 (SIvalue);
    455       1.1  christos       memcpy (valarray, (char*)&SIvalue, 3);
    456       1.1  christos       valarray[3] = frvbf_read_mem_QI (current_cpu, pc, address + 3);
    457       1.1  christos       break;
    458       1.1  christos     default:
    459       1.1  christos       abort (); /* can't happen */
    460       1.1  christos     }
    461       1.1  christos   return T2H_4 (*(SI*)valarray);
    462       1.1  christos }
    463       1.1  christos 
    464       1.1  christos SI
    465       1.1  christos frvbf_read_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address)
    466       1.1  christos {
    467       1.1  christos   FRV_CACHE *cache;
    468       1.1  christos   USI hsr0;
    469       1.1  christos 
    470       1.1  christos   /* Check for access exceptions.  */
    471       1.1  christos   address = check_data_read_address (current_cpu, address, 3);
    472       1.1  christos   address = check_readwrite_address (current_cpu, address, 3);
    473       1.1  christos 
    474       1.1  christos   hsr0 = GET_HSR0 ();
    475       1.1  christos   cache = CPU_DATA_CACHE (current_cpu);
    476       1.1  christos   /* If we need to count cycles, then the cache operation will be
    477       1.1  christos      initiated from the model profiling functions.
    478       1.1  christos      See frvbf_model_....  */
    479       1.1  christos   if (model_insn)
    480       1.1  christos     {
    481       1.1  christos       CPU_LOAD_ADDRESS (current_cpu) = address;
    482       1.1  christos       CPU_LOAD_LENGTH (current_cpu) = 4;
    483       1.1  christos       return 0x37111319; /* any random value */
    484       1.1  christos     }
    485       1.1  christos 
    486       1.1  christos   if (GET_HSR0_DCE (hsr0))
    487       1.1  christos     {
    488       1.1  christos       int cycles;
    489       1.1  christos       /* Handle access which crosses cache line boundary */
    490       1.1  christos       SIM_DESC sd = CPU_STATE (current_cpu);
    491       1.1  christos       if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
    492       1.1  christos 	{
    493       1.1  christos 	  if (DATA_CROSSES_CACHE_LINE (cache, address, 4))
    494       1.1  christos 	    return read_mem_unaligned_SI (current_cpu, pc, address);
    495       1.1  christos 	}
    496       1.1  christos       cycles = frv_cache_read (cache, 0, address);
    497       1.1  christos       if (cycles != 0)
    498       1.1  christos 	return CACHE_RETURN_DATA (cache, 0, address, SI, 4);
    499       1.1  christos     }
    500       1.1  christos 
    501       1.1  christos   return GETMEMSI (current_cpu, pc, address);
    502       1.1  christos }
    503       1.1  christos 
    504       1.1  christos SI
    505       1.1  christos frvbf_read_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address)
    506       1.1  christos {
    507       1.1  christos   return frvbf_read_mem_SI (current_cpu, pc, address);
    508       1.1  christos }
    509       1.1  christos 
    510       1.1  christos /* Read a SI which spans two cache lines */
    511       1.1  christos static DI
    512       1.1  christos read_mem_unaligned_DI (SIM_CPU *current_cpu, IADDR pc, SI address)
    513       1.1  christos {
    514       1.1  christos   FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
    515       1.1  christos   unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
    516       1.1  christos   DI value, value1;
    517       1.1  christos 
    518       1.1  christos   switch (hi_len)
    519       1.1  christos     {
    520       1.1  christos     case 1:
    521       1.1  christos       value = frvbf_read_mem_QI (current_cpu, pc, address);
    522       1.1  christos       value <<= 56;
    523       1.1  christos       value1 = frvbf_read_mem_DI (current_cpu, pc, address + 1);
    524       1.1  christos       value1 = H2T_8 (value1);
    525       1.1  christos       value |= value1 & ((DI)0x00ffffff << 32);
    526       1.1  christos       value |= value1 & 0xffffffffu;
    527       1.1  christos       break;
    528       1.1  christos     case 2:
    529       1.1  christos       value = frvbf_read_mem_HI (current_cpu, pc, address);
    530       1.1  christos       value = H2T_2 (value);
    531       1.1  christos       value <<= 48;
    532       1.1  christos       value1 = frvbf_read_mem_DI (current_cpu, pc, address + 2);
    533       1.1  christos       value1 = H2T_8 (value1);
    534       1.1  christos       value |= value1 & ((DI)0x0000ffff << 32);
    535       1.1  christos       value |= value1 & 0xffffffffu;
    536       1.1  christos       break;
    537       1.1  christos     case 3:
    538       1.1  christos       value = frvbf_read_mem_SI (current_cpu, pc, address - 1);
    539       1.1  christos       value = H2T_4 (value);
    540       1.1  christos       value <<= 40;
    541       1.1  christos       value1 = frvbf_read_mem_DI (current_cpu, pc, address + 3);
    542       1.1  christos       value1 = H2T_8 (value1);
    543       1.1  christos       value |= value1 & ((DI)0x000000ff << 32);
    544       1.1  christos       value |= value1 & 0xffffffffu;
    545       1.1  christos       break;
    546       1.1  christos     case 4:
    547       1.1  christos       value = frvbf_read_mem_SI (current_cpu, pc, address);
    548       1.1  christos       value = H2T_4 (value);
    549       1.1  christos       value <<= 32;
    550       1.1  christos       value1 = frvbf_read_mem_SI (current_cpu, pc, address + 4);
    551       1.1  christos       value1 = H2T_4 (value1);
    552       1.1  christos       value |= value1 & 0xffffffffu;
    553       1.1  christos       break;
    554       1.1  christos     case 5:
    555       1.1  christos       value = frvbf_read_mem_DI (current_cpu, pc, address - 3);
    556       1.1  christos       value = H2T_8 (value);
    557       1.1  christos       value <<= 24;
    558       1.1  christos       value1 = frvbf_read_mem_SI (current_cpu, pc, address + 5);
    559       1.1  christos       value1 = H2T_4 (value1);
    560       1.1  christos       value |= value1 & 0x00ffffff;
    561       1.1  christos       break;
    562       1.1  christos     case 6:
    563       1.1  christos       value = frvbf_read_mem_DI (current_cpu, pc, address - 2);
    564       1.1  christos       value = H2T_8 (value);
    565       1.1  christos       value <<= 16;
    566       1.1  christos       value1 = frvbf_read_mem_HI (current_cpu, pc, address + 6);
    567       1.1  christos       value1 = H2T_2 (value1);
    568       1.1  christos       value |= value1 & 0x0000ffff;
    569       1.1  christos       break;
    570       1.1  christos     case 7:
    571       1.1  christos       value = frvbf_read_mem_DI (current_cpu, pc, address - 1);
    572       1.1  christos       value = H2T_8 (value);
    573       1.1  christos       value <<= 8;
    574       1.1  christos       value1 = frvbf_read_mem_QI (current_cpu, pc, address + 7);
    575       1.1  christos       value |= value1 & 0x000000ff;
    576       1.1  christos       break;
    577       1.1  christos     default:
    578       1.1  christos       abort (); /* can't happen */
    579       1.1  christos     }
    580       1.1  christos   return T2H_8 (value);
    581       1.1  christos }
    582       1.1  christos 
    583       1.1  christos DI
    584       1.1  christos frvbf_read_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address)
    585       1.1  christos {
    586       1.1  christos   USI hsr0;
    587       1.1  christos   FRV_CACHE *cache;
    588       1.1  christos 
    589       1.1  christos   /* Check for access exceptions.  */
    590       1.1  christos   address = check_data_read_address (current_cpu, address, 7);
    591       1.1  christos   address = check_readwrite_address (current_cpu, address, 7);
    592       1.1  christos 
    593       1.1  christos   /* If we need to count cycles, then the cache operation will be
    594       1.1  christos      initiated from the model profiling functions.
    595       1.1  christos      See frvbf_model_....  */
    596       1.1  christos   hsr0 = GET_HSR0 ();
    597       1.1  christos   cache = CPU_DATA_CACHE (current_cpu);
    598       1.1  christos   if (model_insn)
    599       1.1  christos     {
    600       1.1  christos       CPU_LOAD_ADDRESS (current_cpu) = address;
    601       1.1  christos       CPU_LOAD_LENGTH (current_cpu) = 8;
    602       1.1  christos       return 0x37111319; /* any random value */
    603       1.1  christos     }
    604       1.1  christos 
    605       1.1  christos   if (GET_HSR0_DCE (hsr0))
    606       1.1  christos     {
    607       1.1  christos       int cycles;
    608       1.1  christos       /* Handle access which crosses cache line boundary */
    609       1.1  christos       SIM_DESC sd = CPU_STATE (current_cpu);
    610       1.1  christos       if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
    611       1.1  christos 	{
    612       1.1  christos 	  if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
    613       1.1  christos 	    return read_mem_unaligned_DI (current_cpu, pc, address);
    614       1.1  christos 	}
    615       1.1  christos       cycles = frv_cache_read (cache, 0, address);
    616       1.1  christos       if (cycles != 0)
    617       1.1  christos 	return CACHE_RETURN_DATA (cache, 0, address, DI, 8);
    618       1.1  christos     }
    619       1.1  christos 
    620       1.1  christos   return GETMEMDI (current_cpu, pc, address);
    621       1.1  christos }
    622       1.1  christos 
    623       1.1  christos DF
    624       1.1  christos frvbf_read_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address)
    625       1.1  christos {
    626       1.1  christos   USI hsr0;
    627       1.1  christos   FRV_CACHE *cache;
    628       1.1  christos 
    629       1.1  christos   /* Check for access exceptions.  */
    630       1.1  christos   address = check_data_read_address (current_cpu, address, 7);
    631       1.1  christos   address = check_readwrite_address (current_cpu, address, 7);
    632       1.1  christos 
    633       1.1  christos   /* If we need to count cycles, then the cache operation will be
    634       1.1  christos      initiated from the model profiling functions.
    635       1.1  christos      See frvbf_model_....  */
    636       1.1  christos   hsr0 = GET_HSR0 ();
    637       1.1  christos   cache = CPU_DATA_CACHE (current_cpu);
    638       1.1  christos   if (model_insn)
    639       1.1  christos     {
    640       1.1  christos       CPU_LOAD_ADDRESS (current_cpu) = address;
    641       1.1  christos       CPU_LOAD_LENGTH (current_cpu) = 8;
    642       1.1  christos       return 0x37111319; /* any random value */
    643       1.1  christos     }
    644       1.1  christos 
    645       1.1  christos   if (GET_HSR0_DCE (hsr0))
    646       1.1  christos     {
    647       1.1  christos       int cycles;
    648       1.1  christos       /* Handle access which crosses cache line boundary */
    649       1.1  christos       SIM_DESC sd = CPU_STATE (current_cpu);
    650       1.1  christos       if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
    651       1.1  christos 	{
    652       1.1  christos 	  if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
    653       1.1  christos 	    return read_mem_unaligned_DI (current_cpu, pc, address);
    654       1.1  christos 	}
    655       1.1  christos       cycles = frv_cache_read (cache, 0, address);
    656       1.1  christos       if (cycles != 0)
    657       1.1  christos 	return CACHE_RETURN_DATA (cache, 0, address, DF, 8);
    658       1.1  christos     }
    659       1.1  christos 
    660       1.1  christos   return GETMEMDF (current_cpu, pc, address);
    661       1.1  christos }
    662       1.1  christos 
    663       1.1  christos USI
    664       1.1  christos frvbf_read_imem_USI (SIM_CPU *current_cpu, PCADDR vpc)
    665       1.1  christos {
    666       1.1  christos   USI hsr0;
    667       1.1  christos   vpc = check_insn_read_address (current_cpu, vpc, 3);
    668       1.1  christos 
    669       1.1  christos   hsr0 = GET_HSR0 ();
    670       1.1  christos   if (GET_HSR0_ICE (hsr0))
    671       1.1  christos     {
    672       1.1  christos       FRV_CACHE *cache;
    673  1.1.1.10  christos       SI value;
    674       1.1  christos 
    675       1.1  christos       /* We don't want this to show up in the cache statistics.  That read
    676       1.1  christos 	 is done in frvbf_simulate_insn_prefetch.  So read the cache or memory
    677       1.1  christos 	 passively here.  */
    678       1.1  christos       cache = CPU_INSN_CACHE (current_cpu);
    679       1.1  christos       if (frv_cache_read_passive_SI (cache, vpc, &value))
    680       1.1  christos 	return value;
    681       1.1  christos     }
    682       1.1  christos   return sim_core_read_unaligned_4 (current_cpu, vpc, read_map, vpc);
    683       1.1  christos }
    684       1.1  christos 
    685       1.1  christos static SI
    686       1.1  christos fr400_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
    687       1.1  christos {
    688       1.1  christos   if (align_mask == 7
    689       1.1  christos       && address >= 0xfe800000 && address <= 0xfeffffff)
    690       1.1  christos     frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
    691       1.1  christos 
    692       1.1  christos   return address;
    693       1.1  christos }
    694       1.1  christos 
    695       1.1  christos static SI
    696       1.1  christos fr500_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
    697       1.1  christos {
    698       1.1  christos   if (address & align_mask)
    699       1.1  christos     {
    700       1.1  christos       struct frv_interrupt_queue_element *item =
    701       1.1  christos 	frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
    702       1.1  christos       /* Record the correct vliw slot with the interrupt.  */
    703       1.1  christos       if (item != NULL)
    704       1.1  christos 	item->slot = frv_interrupt_state.slot;
    705       1.1  christos       address &= ~align_mask;
    706       1.1  christos     }
    707   1.1.1.9  christos   if ((address >= 0xfeff0600 && address <= 0xfeff7fff)
    708   1.1.1.9  christos       || (address >= 0xfe800000 && address <= 0xfefeffff))
    709       1.1  christos     frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
    710       1.1  christos 
    711       1.1  christos   return address;
    712       1.1  christos }
    713       1.1  christos 
    714       1.1  christos static SI
    715       1.1  christos fr550_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
    716       1.1  christos {
    717   1.1.1.9  christos   if (((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff)
    718       1.1  christos       || (align_mask > 0x3
    719       1.1  christos 	  && ((USI)address >= 0xfeff0000 && (USI)address <= 0xfeffffff)))
    720       1.1  christos     frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
    721       1.1  christos 
    722       1.1  christos   return address;
    723       1.1  christos }
    724       1.1  christos 
    725       1.1  christos static SI
    726       1.1  christos check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
    727       1.1  christos {
    728       1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
    729       1.1  christos   switch (STATE_ARCHITECTURE (sd)->mach)
    730       1.1  christos     {
    731       1.1  christos     case bfd_mach_fr400:
    732       1.1  christos     case bfd_mach_fr450:
    733       1.1  christos       address = fr400_check_write_address (current_cpu, address, align_mask);
    734       1.1  christos       break;
    735       1.1  christos     case bfd_mach_frvtomcat:
    736       1.1  christos     case bfd_mach_fr500:
    737       1.1  christos     case bfd_mach_frv:
    738       1.1  christos       address = fr500_check_write_address (current_cpu, address, align_mask);
    739       1.1  christos       break;
    740       1.1  christos     case bfd_mach_fr550:
    741       1.1  christos       address = fr550_check_write_address (current_cpu, address, align_mask);
    742       1.1  christos       break;
    743       1.1  christos     default:
    744       1.1  christos       break;
    745       1.1  christos     }
    746       1.1  christos   return address;
    747       1.1  christos }
    748       1.1  christos 
    749       1.1  christos void
    750       1.1  christos frvbf_write_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value)
    751       1.1  christos {
    752       1.1  christos   USI hsr0;
    753       1.1  christos   hsr0 = GET_HSR0 ();
    754       1.1  christos   if (GET_HSR0_DCE (hsr0))
    755       1.1  christos     sim_queue_fn_mem_qi_write (current_cpu, frvbf_mem_set_QI, address, value);
    756       1.1  christos   else
    757       1.1  christos     sim_queue_mem_qi_write (current_cpu, address, value);
    758       1.1  christos   frv_set_write_queue_slot (current_cpu);
    759       1.1  christos }
    760       1.1  christos 
    761       1.1  christos void
    762       1.1  christos frvbf_write_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address, UQI value)
    763       1.1  christos {
    764       1.1  christos   frvbf_write_mem_QI (current_cpu, pc, address, value);
    765       1.1  christos }
    766       1.1  christos 
    767       1.1  christos void
    768       1.1  christos frvbf_write_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
    769       1.1  christos {
    770       1.1  christos   USI hsr0;
    771       1.1  christos   hsr0 = GET_HSR0 ();
    772       1.1  christos   if (GET_HSR0_DCE (hsr0))
    773       1.1  christos     sim_queue_fn_mem_hi_write (current_cpu, frvbf_mem_set_HI, address, value);
    774       1.1  christos   else
    775       1.1  christos     sim_queue_mem_hi_write (current_cpu, address, value);
    776       1.1  christos   frv_set_write_queue_slot (current_cpu);
    777       1.1  christos }
    778       1.1  christos 
    779       1.1  christos void
    780       1.1  christos frvbf_write_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address, UHI value)
    781       1.1  christos {
    782       1.1  christos   frvbf_write_mem_HI (current_cpu, pc, address, value);
    783       1.1  christos }
    784       1.1  christos 
    785       1.1  christos void
    786       1.1  christos frvbf_write_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
    787       1.1  christos {
    788       1.1  christos   USI hsr0;
    789       1.1  christos   hsr0 = GET_HSR0 ();
    790       1.1  christos   if (GET_HSR0_DCE (hsr0))
    791       1.1  christos     sim_queue_fn_mem_si_write (current_cpu, frvbf_mem_set_SI, address, value);
    792       1.1  christos   else
    793       1.1  christos     sim_queue_mem_si_write (current_cpu, address, value);
    794       1.1  christos   frv_set_write_queue_slot (current_cpu);
    795       1.1  christos }
    796       1.1  christos 
    797       1.1  christos void
    798       1.1  christos frvbf_write_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
    799       1.1  christos {
    800       1.1  christos   frvbf_write_mem_SI (current_cpu, pc, address, value);
    801       1.1  christos }
    802       1.1  christos 
    803       1.1  christos void
    804       1.1  christos frvbf_write_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
    805       1.1  christos {
    806       1.1  christos   USI hsr0;
    807       1.1  christos   hsr0 = GET_HSR0 ();
    808       1.1  christos   if (GET_HSR0_DCE (hsr0))
    809       1.1  christos     sim_queue_fn_mem_di_write (current_cpu, frvbf_mem_set_DI, address, value);
    810       1.1  christos   else
    811       1.1  christos     sim_queue_mem_di_write (current_cpu, address, value);
    812       1.1  christos   frv_set_write_queue_slot (current_cpu);
    813       1.1  christos }
    814       1.1  christos 
    815       1.1  christos void
    816       1.1  christos frvbf_write_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value)
    817       1.1  christos {
    818       1.1  christos   USI hsr0;
    819       1.1  christos   hsr0 = GET_HSR0 ();
    820       1.1  christos   if (GET_HSR0_DCE (hsr0))
    821       1.1  christos     sim_queue_fn_mem_df_write (current_cpu, frvbf_mem_set_DF, address, value);
    822       1.1  christos   else
    823       1.1  christos     sim_queue_mem_df_write (current_cpu, address, value);
    824       1.1  christos   frv_set_write_queue_slot (current_cpu);
    825       1.1  christos }
    826       1.1  christos 
    827       1.1  christos /* Memory writes.  These do the actual writing through the cache.  */
    828       1.1  christos void
    829       1.1  christos frvbf_mem_set_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value)
    830       1.1  christos {
    831       1.1  christos   FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
    832       1.1  christos 
    833       1.1  christos   /* Check for access errors.  */
    834       1.1  christos   address = check_write_address (current_cpu, address, 0);
    835       1.1  christos   address = check_readwrite_address (current_cpu, address, 0);
    836       1.1  christos 
    837       1.1  christos   /* If we need to count cycles, then submit the write request to the cache
    838       1.1  christos      and let it prioritize the request.  Otherwise perform the write now.  */
    839       1.1  christos   if (model_insn)
    840       1.1  christos     {
    841       1.1  christos       int slot = UNIT_I0;
    842       1.1  christos       frv_cache_request_store (cache, address, slot, (char *)&value,
    843       1.1  christos 			       sizeof (value));
    844       1.1  christos     }
    845       1.1  christos   else
    846       1.1  christos     frv_cache_write (cache, address, (char *)&value, sizeof (value));
    847       1.1  christos }
    848       1.1  christos 
    849       1.1  christos /* Write a HI which spans two cache lines */
    850       1.1  christos static void
    851       1.1  christos mem_set_unaligned_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
    852       1.1  christos {
    853       1.1  christos   FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
    854       1.1  christos   /* value is already in target byte order */
    855       1.1  christos   frv_cache_write (cache, address, (char *)&value, 1);
    856       1.1  christos   frv_cache_write (cache, address + 1, ((char *)&value + 1), 1);
    857       1.1  christos }
    858       1.1  christos 
    859       1.1  christos void
    860       1.1  christos frvbf_mem_set_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
    861       1.1  christos {
    862       1.1  christos   FRV_CACHE *cache;
    863       1.1  christos 
    864       1.1  christos   /* Check for access errors.  */
    865       1.1  christos   address = check_write_address (current_cpu, address, 1);
    866       1.1  christos   address = check_readwrite_address (current_cpu, address, 1);
    867       1.1  christos 
    868       1.1  christos   /* If we need to count cycles, then submit the write request to the cache
    869       1.1  christos      and let it prioritize the request.  Otherwise perform the write now.  */
    870       1.1  christos   value = H2T_2 (value);
    871       1.1  christos   cache = CPU_DATA_CACHE (current_cpu);
    872       1.1  christos   if (model_insn)
    873       1.1  christos     {
    874       1.1  christos       int slot = UNIT_I0;
    875       1.1  christos       frv_cache_request_store (cache, address, slot,
    876       1.1  christos 			       (char *)&value, sizeof (value));
    877       1.1  christos     }
    878       1.1  christos   else
    879       1.1  christos     {
    880       1.1  christos       /* Handle access which crosses cache line boundary */
    881       1.1  christos       SIM_DESC sd = CPU_STATE (current_cpu);
    882       1.1  christos       if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
    883       1.1  christos 	{
    884       1.1  christos 	  if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
    885       1.1  christos 	    {
    886       1.1  christos 	      mem_set_unaligned_HI (current_cpu, pc, address, value);
    887       1.1  christos 	      return;
    888       1.1  christos 	    }
    889       1.1  christos 	}
    890       1.1  christos       frv_cache_write (cache, address, (char *)&value, sizeof (value));
    891       1.1  christos     }
    892       1.1  christos }
    893       1.1  christos 
    894       1.1  christos /* Write a SI which spans two cache lines */
    895       1.1  christos static void
    896       1.1  christos mem_set_unaligned_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
    897       1.1  christos {
    898       1.1  christos   FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
    899       1.1  christos   unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
    900       1.1  christos   /* value is already in target byte order */
    901       1.1  christos   frv_cache_write (cache, address, (char *)&value, hi_len);
    902       1.1  christos   frv_cache_write (cache, address + hi_len, (char *)&value + hi_len, 4 - hi_len);
    903       1.1  christos }
    904       1.1  christos 
    905       1.1  christos void
    906       1.1  christos frvbf_mem_set_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
    907       1.1  christos {
    908       1.1  christos   FRV_CACHE *cache;
    909       1.1  christos 
    910       1.1  christos   /* Check for access errors.  */
    911       1.1  christos   address = check_write_address (current_cpu, address, 3);
    912       1.1  christos   address = check_readwrite_address (current_cpu, address, 3);
    913       1.1  christos 
    914       1.1  christos   /* If we need to count cycles, then submit the write request to the cache
    915       1.1  christos      and let it prioritize the request.  Otherwise perform the write now.  */
    916       1.1  christos   cache = CPU_DATA_CACHE (current_cpu);
    917       1.1  christos   value = H2T_4 (value);
    918       1.1  christos   if (model_insn)
    919       1.1  christos     {
    920       1.1  christos       int slot = UNIT_I0;
    921       1.1  christos       frv_cache_request_store (cache, address, slot,
    922       1.1  christos 			       (char *)&value, sizeof (value));
    923       1.1  christos     }
    924       1.1  christos   else
    925       1.1  christos     {
    926       1.1  christos       /* Handle access which crosses cache line boundary */
    927       1.1  christos       SIM_DESC sd = CPU_STATE (current_cpu);
    928       1.1  christos       if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
    929       1.1  christos 	{
    930       1.1  christos 	  if (DATA_CROSSES_CACHE_LINE (cache, address, 4))
    931       1.1  christos 	    {
    932       1.1  christos 	      mem_set_unaligned_SI (current_cpu, pc, address, value);
    933       1.1  christos 	      return;
    934       1.1  christos 	    }
    935       1.1  christos 	}
    936       1.1  christos       frv_cache_write (cache, address, (char *)&value, sizeof (value));
    937       1.1  christos     }
    938       1.1  christos }
    939       1.1  christos 
    940       1.1  christos /* Write a DI which spans two cache lines */
    941       1.1  christos static void
    942       1.1  christos mem_set_unaligned_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
    943       1.1  christos {
    944       1.1  christos   FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
    945       1.1  christos   unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
    946       1.1  christos   /* value is already in target byte order */
    947       1.1  christos   frv_cache_write (cache, address, (char *)&value, hi_len);
    948       1.1  christos   frv_cache_write (cache, address + hi_len, (char *)&value + hi_len, 8 - hi_len);
    949       1.1  christos }
    950       1.1  christos 
    951       1.1  christos void
    952       1.1  christos frvbf_mem_set_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
    953       1.1  christos {
    954       1.1  christos   FRV_CACHE *cache;
    955       1.1  christos 
    956       1.1  christos   /* Check for access errors.  */
    957       1.1  christos   address = check_write_address (current_cpu, address, 7);
    958       1.1  christos   address = check_readwrite_address (current_cpu, address, 7);
    959       1.1  christos 
    960       1.1  christos   /* If we need to count cycles, then submit the write request to the cache
    961       1.1  christos      and let it prioritize the request.  Otherwise perform the write now.  */
    962       1.1  christos   value = H2T_8 (value);
    963       1.1  christos   cache = CPU_DATA_CACHE (current_cpu);
    964       1.1  christos   if (model_insn)
    965       1.1  christos     {
    966       1.1  christos       int slot = UNIT_I0;
    967       1.1  christos       frv_cache_request_store (cache, address, slot,
    968       1.1  christos 			       (char *)&value, sizeof (value));
    969       1.1  christos     }
    970       1.1  christos   else
    971       1.1  christos     {
    972       1.1  christos       /* Handle access which crosses cache line boundary */
    973       1.1  christos       SIM_DESC sd = CPU_STATE (current_cpu);
    974       1.1  christos       if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
    975       1.1  christos 	{
    976       1.1  christos 	  if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
    977       1.1  christos 	    {
    978       1.1  christos 	      mem_set_unaligned_DI (current_cpu, pc, address, value);
    979       1.1  christos 	      return;
    980       1.1  christos 	    }
    981       1.1  christos 	}
    982       1.1  christos       frv_cache_write (cache, address, (char *)&value, sizeof (value));
    983       1.1  christos     }
    984       1.1  christos }
    985       1.1  christos 
    986       1.1  christos void
    987       1.1  christos frvbf_mem_set_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value)
    988       1.1  christos {
    989       1.1  christos   FRV_CACHE *cache;
    990       1.1  christos 
    991       1.1  christos   /* Check for access errors.  */
    992       1.1  christos   address = check_write_address (current_cpu, address, 7);
    993       1.1  christos   address = check_readwrite_address (current_cpu, address, 7);
    994       1.1  christos 
    995       1.1  christos   /* If we need to count cycles, then submit the write request to the cache
    996       1.1  christos      and let it prioritize the request.  Otherwise perform the write now.  */
    997       1.1  christos   value = H2T_8 (value);
    998       1.1  christos   cache = CPU_DATA_CACHE (current_cpu);
    999       1.1  christos   if (model_insn)
   1000       1.1  christos     {
   1001       1.1  christos       int slot = UNIT_I0;
   1002       1.1  christos       frv_cache_request_store (cache, address, slot,
   1003       1.1  christos 			       (char *)&value, sizeof (value));
   1004       1.1  christos     }
   1005       1.1  christos   else
   1006       1.1  christos     {
   1007       1.1  christos       /* Handle access which crosses cache line boundary */
   1008       1.1  christos       SIM_DESC sd = CPU_STATE (current_cpu);
   1009       1.1  christos       if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
   1010       1.1  christos 	{
   1011       1.1  christos 	  if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
   1012       1.1  christos 	    {
   1013       1.1  christos 	      mem_set_unaligned_DI (current_cpu, pc, address, value);
   1014       1.1  christos 	      return;
   1015       1.1  christos 	    }
   1016       1.1  christos 	}
   1017       1.1  christos       frv_cache_write (cache, address, (char *)&value, sizeof (value));
   1018       1.1  christos     }
   1019       1.1  christos }
   1020       1.1  christos 
   1021       1.1  christos void
   1022       1.1  christos frvbf_mem_set_XI (SIM_CPU *current_cpu, IADDR pc, SI address, SI *value)
   1023       1.1  christos {
   1024       1.1  christos   int i;
   1025       1.1  christos   FRV_CACHE *cache;
   1026       1.1  christos 
   1027       1.1  christos   /* Check for access errors.  */
   1028       1.1  christos   address = check_write_address (current_cpu, address, 0xf);
   1029       1.1  christos   address = check_readwrite_address (current_cpu, address, 0xf);
   1030       1.1  christos 
   1031       1.1  christos   /* TODO -- reverse word order as well?  */
   1032       1.1  christos   for (i = 0; i < 4; ++i)
   1033       1.1  christos     value[i] = H2T_4 (value[i]);
   1034       1.1  christos 
   1035       1.1  christos   /* If we need to count cycles, then submit the write request to the cache
   1036       1.1  christos      and let it prioritize the request.  Otherwise perform the write now.  */
   1037       1.1  christos   cache = CPU_DATA_CACHE (current_cpu);
   1038       1.1  christos   if (model_insn)
   1039       1.1  christos     {
   1040       1.1  christos       int slot = UNIT_I0;
   1041       1.1  christos       frv_cache_request_store (cache, address, slot, (char*)value, 16);
   1042       1.1  christos     }
   1043       1.1  christos   else
   1044       1.1  christos     frv_cache_write (cache, address, (char*)value, 16);
   1045       1.1  christos }
   1046       1.1  christos 
   1047       1.1  christos /* Record the current VLIW slot on the element at the top of the write queue.
   1048       1.1  christos */
   1049       1.1  christos void
   1050       1.1  christos frv_set_write_queue_slot (SIM_CPU *current_cpu)
   1051       1.1  christos {
   1052       1.1  christos   FRV_VLIW *vliw = CPU_VLIW (current_cpu);
   1053       1.1  christos   int slot = vliw->next_slot - 1;
   1054       1.1  christos   CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (current_cpu);
   1055       1.1  christos   int ix = CGEN_WRITE_QUEUE_INDEX (q) - 1;
   1056       1.1  christos   CGEN_WRITE_QUEUE_ELEMENT *item = CGEN_WRITE_QUEUE_ELEMENT (q, ix);
   1057       1.1  christos   CGEN_WRITE_QUEUE_ELEMENT_PIPE (item) = (*vliw->current_vliw)[slot];
   1058       1.1  christos }
   1059