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