1/* Memory ops header for CGEN-based simulators. 2 Copyright (C) 1996, 1997, 1998, 1999, 2007, 2008, 2009, 2010, 2011 3 Free Software Foundation, Inc. 4 Contributed by Cygnus Solutions. 5 6This file is part of the GNU Simulators. 7 8This program is free software; you can redistribute it and/or modify 9it under the terms of the GNU General Public License as published by 10the Free Software Foundation; either version 3 of the License, or 11(at your option) any later version. 12 13This program is distributed in the hope that it will be useful, 14but WITHOUT ANY WARRANTY; without even the implied warranty of 15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16GNU General Public License for more details. 17 18You should have received a copy of the GNU General Public License 19along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 21#ifndef CGEN_MEM_H 22#define CGEN_MEM_H 23 24#ifdef MEMOPS_DEFINE_INLINE 25#define MEMOPS_INLINE 26#else 27#define MEMOPS_INLINE extern inline 28#endif 29 30/* Integer memory read support. 31 32 There is no floating point support. In this context there are no 33 floating point modes, only floating point operations (whose arguments 34 and results are arrays of bits that we treat as integer modes). */ 35 36#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) 37#define DECLARE_GETMEM(mode, size) \ 38MEMOPS_INLINE mode \ 39XCONCAT2 (GETMEM,mode) (SIM_CPU *cpu, IADDR pc, ADDR a) \ 40{ \ 41 PROFILE_COUNT_READ (cpu, a, XCONCAT2 (MODE_,mode)); \ 42 /* Don't read anything into "unaligned" here. Bad name choice. */\ 43 return XCONCAT2 (sim_core_read_unaligned_,size) (cpu, pc, read_map, a); \ 44} 45#else 46#define DECLARE_GETMEM(mode, size) \ 47extern mode XCONCAT2 (GETMEM,mode) (SIM_CPU *, IADDR, ADDR); 48#endif 49 50DECLARE_GETMEM (QI, 1) /* TAGS: GETMEMQI */ 51DECLARE_GETMEM (UQI, 1) /* TAGS: GETMEMUQI */ 52DECLARE_GETMEM (HI, 2) /* TAGS: GETMEMHI */ 53DECLARE_GETMEM (UHI, 2) /* TAGS: GETMEMUHI */ 54DECLARE_GETMEM (SI, 4) /* TAGS: GETMEMSI */ 55DECLARE_GETMEM (USI, 4) /* TAGS: GETMEMUSI */ 56DECLARE_GETMEM (DI, 8) /* TAGS: GETMEMDI */ 57DECLARE_GETMEM (UDI, 8) /* TAGS: GETMEMUDI */ 58 59#undef DECLARE_GETMEM 60 61/* Integer memory write support. */ 62 63#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) 64#define DECLARE_SETMEM(mode, size) \ 65MEMOPS_INLINE void \ 66XCONCAT2 (SETMEM,mode) (SIM_CPU *cpu, IADDR pc, ADDR a, mode val) \ 67{ \ 68 PROFILE_COUNT_WRITE (cpu, a, XCONCAT2 (MODE_,mode)); \ 69 /* Don't read anything into "unaligned" here. Bad name choice. */ \ 70 XCONCAT2 (sim_core_write_unaligned_,size) (cpu, pc, write_map, a, val); \ 71} 72#else 73#define DECLARE_SETMEM(mode, size) \ 74extern void XCONCAT2 (SETMEM,mode) (SIM_CPU *, IADDR, ADDR, mode); 75#endif 76 77DECLARE_SETMEM (QI, 1) /* TAGS: SETMEMQI */ 78DECLARE_SETMEM (UQI, 1) /* TAGS: SETMEMUQI */ 79DECLARE_SETMEM (HI, 2) /* TAGS: SETMEMHI */ 80DECLARE_SETMEM (UHI, 2) /* TAGS: SETMEMUHI */ 81DECLARE_SETMEM (SI, 4) /* TAGS: SETMEMSI */ 82DECLARE_SETMEM (USI, 4) /* TAGS: SETMEMUSI */ 83DECLARE_SETMEM (DI, 8) /* TAGS: SETMEMDI */ 84DECLARE_SETMEM (UDI, 8) /* TAGS: SETMEMUDI */ 85 86#undef DECLARE_SETMEM 87 88/* Instruction read support. */ 89 90#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) 91#define DECLARE_GETIMEM(mode, size) \ 92MEMOPS_INLINE mode \ 93XCONCAT2 (GETIMEM,mode) (SIM_CPU *cpu, IADDR a) \ 94{ \ 95 /*PROFILE_COUNT_READ (cpu, a, XCONCAT2 (MODE_,mode));*/ \ 96 /* Don't read anything into "unaligned" here. Bad name choice. */\ 97 return XCONCAT2 (sim_core_read_unaligned_,size) (cpu, a, exec_map, a); \ 98} 99#else 100#define DECLARE_GETIMEM(mode, size) \ 101extern mode XCONCAT2 (GETIMEM,mode) (SIM_CPU *, ADDR); 102#endif 103 104DECLARE_GETIMEM (UQI, 1) /* TAGS: GETIMEMUQI */ 105DECLARE_GETIMEM (UHI, 2) /* TAGS: GETIMEMUHI */ 106DECLARE_GETIMEM (USI, 4) /* TAGS: GETIMEMUSI */ 107DECLARE_GETIMEM (UDI, 8) /* TAGS: GETIMEMUDI */ 108 109#undef DECLARE_GETIMEM 110 111/* Floating point support. 112 113 ??? One can specify that the integer memory ops should be used instead, 114 and treat fp values as just a series of bits. One might even bubble 115 that notion up into the description language. However, that departs from 116 gcc. One could cross over from gcc's notion and a "series of bits" notion 117 between there and here, and thus still not require these routines. However, 118 that's a complication of its own (not that having these fns isn't). 119 But for now, we do things this way. */ 120 121#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) 122#define DECLARE_GETMEM(mode, size) \ 123MEMOPS_INLINE mode \ 124XCONCAT2 (GETMEM,mode) (SIM_CPU *cpu, IADDR pc, ADDR a) \ 125{ \ 126 PROFILE_COUNT_READ (cpu, a, XCONCAT2 (MODE_,mode)); \ 127 /* Don't read anything into "unaligned" here. Bad name choice. */\ 128 return XCONCAT2 (sim_core_read_unaligned_,size) (cpu, pc, read_map, a); \ 129} 130#else 131#define DECLARE_GETMEM(mode, size) \ 132extern mode XCONCAT2 (GETMEM,mode) (SIM_CPU *, IADDR, ADDR); 133#endif 134 135DECLARE_GETMEM (SF, 4) /* TAGS: GETMEMSF */ 136DECLARE_GETMEM (DF, 8) /* TAGS: GETMEMDF */ 137 138#undef DECLARE_GETMEM 139 140#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) 141#define DECLARE_SETMEM(mode, size) \ 142MEMOPS_INLINE void \ 143XCONCAT2 (SETMEM,mode) (SIM_CPU *cpu, IADDR pc, ADDR a, mode val) \ 144{ \ 145 PROFILE_COUNT_WRITE (cpu, a, XCONCAT2 (MODE_,mode)); \ 146 /* Don't read anything into "unaligned" here. Bad name choice. */ \ 147 XCONCAT2 (sim_core_write_unaligned_,size) (cpu, pc, write_map, a, val); \ 148} 149#else 150#define DECLARE_SETMEM(mode, size) \ 151extern void XCONCAT2 (SETMEM,mode) (SIM_CPU *, IADDR, ADDR, mode); 152#endif 153 154DECLARE_SETMEM (SF, 4) /* TAGS: SETMEMSF */ 155DECLARE_SETMEM (DF, 8) /* TAGS: SETMEMDF */ 156 157#undef DECLARE_SETMEM 158 159/* GETT<mode>: translate target value at P to host value. 160 This needn't be very efficient (i.e. can call memcpy) as this is 161 only used when interfacing with the outside world (e.g. gdb). */ 162 163#if defined (MEMOPS_DEFINE_INLINE) 164#define DECLARE_GETT(mode, size) \ 165mode \ 166XCONCAT2 (GETT,mode) (unsigned char *p) \ 167{ \ 168 mode tmp; \ 169 memcpy (&tmp, p, sizeof (mode)); \ 170 return XCONCAT2 (T2H_,size) (tmp); \ 171} 172#else 173#define DECLARE_GETT(mode, size) \ 174extern mode XCONCAT2 (GETT,mode) (unsigned char *); 175#endif 176 177DECLARE_GETT (QI, 1) /* TAGS: GETTQI */ 178DECLARE_GETT (UQI, 1) /* TAGS: GETTUQI */ 179DECLARE_GETT (HI, 2) /* TAGS: GETTHI */ 180DECLARE_GETT (UHI, 2) /* TAGS: GETTUHI */ 181DECLARE_GETT (SI, 4) /* TAGS: GETTSI */ 182DECLARE_GETT (USI, 4) /* TAGS: GETTUSI */ 183DECLARE_GETT (DI, 8) /* TAGS: GETTDI */ 184DECLARE_GETT (UDI, 8) /* TAGS: GETTUDI */ 185 186#if 0 /* ??? defered until necessary */ 187DECLARE_GETT (SF, 4) /* TAGS: GETTSF */ 188DECLARE_GETT (DF, 8) /* TAGS: GETTDF */ 189DECLARE_GETT (TF, 16) /* TAGS: GETTTF */ 190#endif 191 192#undef DECLARE_GETT 193 194/* SETT<mode>: translate host value to target value and store at P. 195 This needn't be very efficient (i.e. can call memcpy) as this is 196 only used when interfacing with the outside world (e.g. gdb). */ 197 198#if defined (MEMOPS_DEFINE_INLINE) 199#define DECLARE_SETT(mode, size) \ 200void \ 201XCONCAT2 (SETT,mode) (unsigned char *buf, mode val) \ 202{ \ 203 mode tmp; \ 204 tmp = XCONCAT2 (H2T_,size) (val); \ 205 memcpy (buf, &tmp, sizeof (mode)); \ 206} 207#else 208#define DECLARE_SETT(mode, size) \ 209extern mode XCONCAT2 (SETT,mode) (unsigned char *, mode); 210#endif 211 212DECLARE_SETT (QI, 1) /* TAGS: SETTQI */ 213DECLARE_SETT (UQI, 1) /* TAGS: SETTUQI */ 214DECLARE_SETT (HI, 2) /* TAGS: SETTHI */ 215DECLARE_SETT (UHI, 2) /* TAGS: SETTUHI */ 216DECLARE_SETT (SI, 4) /* TAGS: SETTSI */ 217DECLARE_SETT (USI, 4) /* TAGS: SETTUSI */ 218DECLARE_SETT (DI, 8) /* TAGS: SETTDI */ 219DECLARE_SETT (UDI, 8) /* TAGS: SETTUDI */ 220 221#if 0 /* ??? defered until necessary */ 222DECLARE_SETT (SF, 4) /* TAGS: SETTSF */ 223DECLARE_SETT (DF, 8) /* TAGS: SETTDF */ 224DECLARE_SETT (TF, 16) /* TAGS: SETTTF */ 225#endif 226 227#undef DECLARE_SETT 228 229#endif /* CGEN_MEM_H */ 230