1 |
24 |
jeremybenn |
/* Memory ops header for CGEN-based simulators.
|
2 |
|
|
Copyright (C) 1996, 1997, 1998, 1999, 2007, 2008
|
3 |
|
|
Free Software Foundation, Inc.
|
4 |
|
|
Contributed by Cygnus Solutions.
|
5 |
|
|
|
6 |
|
|
This file is part of the GNU Simulators.
|
7 |
|
|
|
8 |
|
|
This program is free software; you can redistribute it and/or modify
|
9 |
|
|
it under the terms of the GNU General Public License as published by
|
10 |
|
|
the Free Software Foundation; either version 3 of the License, or
|
11 |
|
|
(at your option) any later version.
|
12 |
|
|
|
13 |
|
|
This program is distributed in the hope that it will be useful,
|
14 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16 |
|
|
GNU General Public License for more details.
|
17 |
|
|
|
18 |
|
|
You should have received a copy of the GNU General Public License
|
19 |
|
|
along 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) \
|
38 |
|
|
MEMOPS_INLINE mode \
|
39 |
|
|
XCONCAT2 (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) \
|
47 |
|
|
extern mode XCONCAT2 (GETMEM,mode) (SIM_CPU *, IADDR, ADDR);
|
48 |
|
|
#endif
|
49 |
|
|
|
50 |
|
|
DECLARE_GETMEM (QI, 1) /* TAGS: GETMEMQI */
|
51 |
|
|
DECLARE_GETMEM (UQI, 1) /* TAGS: GETMEMUQI */
|
52 |
|
|
DECLARE_GETMEM (HI, 2) /* TAGS: GETMEMHI */
|
53 |
|
|
DECLARE_GETMEM (UHI, 2) /* TAGS: GETMEMUHI */
|
54 |
|
|
DECLARE_GETMEM (SI, 4) /* TAGS: GETMEMSI */
|
55 |
|
|
DECLARE_GETMEM (USI, 4) /* TAGS: GETMEMUSI */
|
56 |
|
|
DECLARE_GETMEM (DI, 8) /* TAGS: GETMEMDI */
|
57 |
|
|
DECLARE_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) \
|
65 |
|
|
MEMOPS_INLINE void \
|
66 |
|
|
XCONCAT2 (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) \
|
74 |
|
|
extern void XCONCAT2 (SETMEM,mode) (SIM_CPU *, IADDR, ADDR, mode);
|
75 |
|
|
#endif
|
76 |
|
|
|
77 |
|
|
DECLARE_SETMEM (QI, 1) /* TAGS: SETMEMQI */
|
78 |
|
|
DECLARE_SETMEM (UQI, 1) /* TAGS: SETMEMUQI */
|
79 |
|
|
DECLARE_SETMEM (HI, 2) /* TAGS: SETMEMHI */
|
80 |
|
|
DECLARE_SETMEM (UHI, 2) /* TAGS: SETMEMUHI */
|
81 |
|
|
DECLARE_SETMEM (SI, 4) /* TAGS: SETMEMSI */
|
82 |
|
|
DECLARE_SETMEM (USI, 4) /* TAGS: SETMEMUSI */
|
83 |
|
|
DECLARE_SETMEM (DI, 8) /* TAGS: SETMEMDI */
|
84 |
|
|
DECLARE_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) \
|
92 |
|
|
MEMOPS_INLINE mode \
|
93 |
|
|
XCONCAT2 (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) \
|
101 |
|
|
extern mode XCONCAT2 (GETIMEM,mode) (SIM_CPU *, ADDR);
|
102 |
|
|
#endif
|
103 |
|
|
|
104 |
|
|
DECLARE_GETIMEM (UQI, 1) /* TAGS: GETIMEMUQI */
|
105 |
|
|
DECLARE_GETIMEM (UHI, 2) /* TAGS: GETIMEMUHI */
|
106 |
|
|
DECLARE_GETIMEM (USI, 4) /* TAGS: GETIMEMUSI */
|
107 |
|
|
DECLARE_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) \
|
123 |
|
|
MEMOPS_INLINE mode \
|
124 |
|
|
XCONCAT2 (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) \
|
132 |
|
|
extern mode XCONCAT2 (GETMEM,mode) (SIM_CPU *, IADDR, ADDR);
|
133 |
|
|
#endif
|
134 |
|
|
|
135 |
|
|
DECLARE_GETMEM (SF, 4) /* TAGS: GETMEMSF */
|
136 |
|
|
DECLARE_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) \
|
142 |
|
|
MEMOPS_INLINE void \
|
143 |
|
|
XCONCAT2 (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) \
|
151 |
|
|
extern void XCONCAT2 (SETMEM,mode) (SIM_CPU *, IADDR, ADDR, mode);
|
152 |
|
|
#endif
|
153 |
|
|
|
154 |
|
|
DECLARE_SETMEM (SF, 4) /* TAGS: SETMEMSF */
|
155 |
|
|
DECLARE_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 (__GNUC__) || defined (MEMOPS_DEFINE_INLINE)
|
164 |
|
|
#define DECLARE_GETT(mode, size) \
|
165 |
|
|
MEMOPS_INLINE mode \
|
166 |
|
|
XCONCAT2 (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) \
|
174 |
|
|
extern mode XCONCAT2 (GETT,mode) (unsigned char *);
|
175 |
|
|
#endif
|
176 |
|
|
|
177 |
|
|
DECLARE_GETT (QI, 1) /* TAGS: GETTQI */
|
178 |
|
|
DECLARE_GETT (UQI, 1) /* TAGS: GETTUQI */
|
179 |
|
|
DECLARE_GETT (HI, 2) /* TAGS: GETTHI */
|
180 |
|
|
DECLARE_GETT (UHI, 2) /* TAGS: GETTUHI */
|
181 |
|
|
DECLARE_GETT (SI, 4) /* TAGS: GETTSI */
|
182 |
|
|
DECLARE_GETT (USI, 4) /* TAGS: GETTUSI */
|
183 |
|
|
DECLARE_GETT (DI, 8) /* TAGS: GETTDI */
|
184 |
|
|
DECLARE_GETT (UDI, 8) /* TAGS: GETTUDI */
|
185 |
|
|
|
186 |
|
|
#if 0 /* ??? defered until necessary */
|
187 |
|
|
DECLARE_GETT (SF, 4) /* TAGS: GETTSF */
|
188 |
|
|
DECLARE_GETT (DF, 8) /* TAGS: GETTDF */
|
189 |
|
|
DECLARE_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 (__GNUC__) || defined (MEMOPS_DEFINE_INLINE)
|
199 |
|
|
#define DECLARE_SETT(mode, size) \
|
200 |
|
|
MEMOPS_INLINE void \
|
201 |
|
|
XCONCAT2 (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) \
|
209 |
|
|
extern mode XCONCAT2 (GETT,mode) (unsigned char *, mode);
|
210 |
|
|
#endif
|
211 |
|
|
|
212 |
|
|
DECLARE_SETT (QI, 1) /* TAGS: SETTQI */
|
213 |
|
|
DECLARE_SETT (UQI, 1) /* TAGS: SETTUQI */
|
214 |
|
|
DECLARE_SETT (HI, 2) /* TAGS: SETTHI */
|
215 |
|
|
DECLARE_SETT (UHI, 2) /* TAGS: SETTUHI */
|
216 |
|
|
DECLARE_SETT (SI, 4) /* TAGS: SETTSI */
|
217 |
|
|
DECLARE_SETT (USI, 4) /* TAGS: SETTUSI */
|
218 |
|
|
DECLARE_SETT (DI, 8) /* TAGS: SETTDI */
|
219 |
|
|
DECLARE_SETT (UDI, 8) /* TAGS: SETTUDI */
|
220 |
|
|
|
221 |
|
|
#if 0 /* ??? defered until necessary */
|
222 |
|
|
DECLARE_SETT (SF, 4) /* TAGS: SETTSF */
|
223 |
|
|
DECLARE_SETT (DF, 8) /* TAGS: SETTDF */
|
224 |
|
|
DECLARE_SETT (TF, 16) /* TAGS: SETTTF */
|
225 |
|
|
#endif
|
226 |
|
|
|
227 |
|
|
#undef DECLARE_SETT
|
228 |
|
|
|
229 |
|
|
#endif /* CGEN_MEM_H */
|