]>
Commit | Line | Data |
---|---|---|
c906108c | 1 | /* Support code for various pieces of CGEN simulators. |
3666a048 | 2 | Copyright (C) 1996-2021 Free Software Foundation, Inc. |
c906108c SS |
3 | Contributed by Cygnus Support. |
4 | ||
5 | This file is part of GDB, the GNU debugger. | |
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 | |
4744ac1b JB |
9 | the Free Software Foundation; either version 3 of the License, or |
10 | (at your option) any later version. | |
c906108c SS |
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 | ||
4744ac1b JB |
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/>. */ | |
c906108c | 19 | |
6df01ab8 MF |
20 | /* This must come before any other includes. */ |
21 | #include "defs.h" | |
22 | ||
c906108c | 23 | #include "bfd.h" |
20a8e078 MF |
24 | #include "dis-asm.h" |
25 | ||
c906108c | 26 | #include "sim-main.h" |
1fef66b0 | 27 | #include "sim-signal.h" |
c906108c SS |
28 | |
29 | #define MEMOPS_DEFINE_INLINE | |
30 | #include "cgen-mem.h" | |
31 | ||
32 | #define SEMOPS_DEFINE_INLINE | |
33 | #include "cgen-ops.h" | |
34 | ||
12279229 | 35 | const char * const cgen_mode_names[] = { |
104c1213 | 36 | "VOID", |
c906108c SS |
37 | "BI", |
38 | "QI", | |
39 | "HI", | |
40 | "SI", | |
41 | "DI", | |
42 | "UQI", | |
43 | "UHI", | |
44 | "USI", | |
45 | "UDI", | |
46 | "SF", | |
47 | "DF", | |
48 | "XF", | |
49 | "TF", | |
50 | 0, /* MODE_TARGET_MAX */ | |
51 | "INT", | |
52 | "UINT", | |
53 | "PTR" | |
54 | }; | |
55 | ||
56 | /* Opcode table for virtual insns used by the simulator. */ | |
57 | ||
58 | #define V CGEN_ATTR_MASK (CGEN_INSN_VIRTUAL) | |
59 | ||
60 | static const CGEN_IBASE virtual_insn_entries[] = | |
61 | { | |
62 | { | |
aac7ce3c | 63 | VIRTUAL_INSN_X_INVALID, "--invalid--", NULL, 0, { V, {} } |
c906108c SS |
64 | }, |
65 | { | |
aac7ce3c | 66 | VIRTUAL_INSN_X_BEFORE, "--before--", NULL, 0, { V, {} } |
c906108c SS |
67 | }, |
68 | { | |
aac7ce3c | 69 | VIRTUAL_INSN_X_AFTER, "--after--", NULL, 0, { V, {} } |
c906108c SS |
70 | }, |
71 | { | |
aac7ce3c | 72 | VIRTUAL_INSN_X_BEGIN, "--begin--", NULL, 0, { V, {} } |
c906108c SS |
73 | }, |
74 | { | |
aac7ce3c | 75 | VIRTUAL_INSN_X_CHAIN, "--chain--", NULL, 0, { V, {} } |
c906108c SS |
76 | }, |
77 | { | |
aac7ce3c | 78 | VIRTUAL_INSN_X_CTI_CHAIN, "--cti-chain--", NULL, 0, { V, {} } |
c906108c SS |
79 | } |
80 | }; | |
81 | ||
82 | #undef V | |
83 | ||
84 | const CGEN_INSN cgen_virtual_insn_table[] = | |
85 | { | |
86 | { & virtual_insn_entries[0] }, | |
87 | { & virtual_insn_entries[1] }, | |
88 | { & virtual_insn_entries[2] }, | |
89 | { & virtual_insn_entries[3] }, | |
90 | { & virtual_insn_entries[4] }, | |
91 | { & virtual_insn_entries[5] } | |
92 | }; | |
93 | ||
c906108c SS |
94 | /* Return the name of insn number I. */ |
95 | ||
96 | const char * | |
97 | cgen_insn_name (SIM_CPU *cpu, int i) | |
98 | { | |
99 | return CGEN_INSN_NAME ((* CPU_GET_IDATA (cpu)) ((cpu), (i))); | |
100 | } | |
101 | ||
102 | /* Return the maximum number of extra bytes required for a SIM_CPU struct. */ | |
103 | ||
104 | int | |
1c636da0 | 105 | cgen_cpu_max_extra_bytes (SIM_DESC sd) |
c906108c | 106 | { |
1c636da0 | 107 | const SIM_MACH * const *machp; |
c906108c SS |
108 | int extra = 0; |
109 | ||
1c636da0 MF |
110 | SIM_ASSERT (STATE_MACHS (sd) != NULL); |
111 | ||
112 | for (machp = STATE_MACHS (sd); *machp != NULL; ++machp) | |
c906108c | 113 | { |
1c636da0 | 114 | int size = IMP_PROPS_SIM_CPU_SIZE (MACH_IMP_PROPS (*machp)); |
c906108c SS |
115 | if (size > extra) |
116 | extra = size; | |
117 | } | |
118 | return extra; | |
119 | } | |
120 | \f | |
121 | #ifdef DI_FN_SUPPORT | |
122 | ||
c906108c SS |
123 | DI |
124 | ANDDI (a, b) | |
125 | DI a, b; | |
126 | { | |
127 | SI ahi = GETHIDI (a); | |
128 | SI alo = GETLODI (a); | |
129 | SI bhi = GETHIDI (b); | |
130 | SI blo = GETLODI (b); | |
131 | return MAKEDI (ahi & bhi, alo & blo); | |
132 | } | |
133 | ||
134 | DI | |
135 | ORDI (a, b) | |
136 | DI a, b; | |
137 | { | |
138 | SI ahi = GETHIDI (a); | |
139 | SI alo = GETLODI (a); | |
140 | SI bhi = GETHIDI (b); | |
141 | SI blo = GETLODI (b); | |
142 | return MAKEDI (ahi | bhi, alo | blo); | |
143 | } | |
144 | ||
145 | DI | |
146 | ADDDI (a, b) | |
147 | DI a, b; | |
148 | { | |
149 | USI ahi = GETHIDI (a); | |
150 | USI alo = GETLODI (a); | |
151 | USI bhi = GETHIDI (b); | |
152 | USI blo = GETLODI (b); | |
153 | USI x = alo + blo; | |
154 | return MAKEDI (ahi + bhi + (x < alo), x); | |
155 | } | |
156 | ||
157 | DI | |
158 | MULDI (a, b) | |
159 | DI a, b; | |
160 | { | |
161 | USI ahi = GETHIDI (a); | |
162 | USI alo = GETLODI (a); | |
163 | USI bhi = GETHIDI (b); | |
164 | USI blo = GETLODI (b); | |
165 | USI rhi,rlo; | |
166 | USI x0, x1, x2, x3; | |
167 | ||
168 | x0 = alo * blo; | |
169 | x1 = alo * bhi; | |
170 | x2 = ahi * blo; | |
171 | x3 = ahi * bhi; | |
172 | ||
173 | #define SI_TYPE_SIZE 32 | |
174 | #define BITS4 (SI_TYPE_SIZE / 4) | |
175 | #define ll_B (1L << (SI_TYPE_SIZE / 2)) | |
176 | #define ll_lowpart(t) ((USI) (t) % ll_B) | |
177 | #define ll_highpart(t) ((USI) (t) / ll_B) | |
178 | x1 += ll_highpart (x0); /* this can't give carry */ | |
179 | x1 += x2; /* but this indeed can */ | |
180 | if (x1 < x2) /* did we get it? */ | |
181 | x3 += ll_B; /* yes, add it in the proper pos. */ | |
182 | ||
183 | rhi = x3 + ll_highpart (x1); | |
184 | rlo = ll_lowpart (x1) * ll_B + ll_lowpart (x0); | |
185 | return MAKEDI (rhi + (alo * bhi) + (ahi * blo), rlo); | |
186 | } | |
187 | ||
188 | DI | |
189 | SHLDI (val, shift) | |
190 | DI val; | |
191 | SI shift; | |
192 | { | |
193 | USI hi = GETHIDI (val); | |
194 | USI lo = GETLODI (val); | |
195 | /* FIXME: Need to worry about shift < 0 || shift >= 32. */ | |
196 | return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift); | |
197 | } | |
198 | ||
199 | DI | |
200 | SLADI (val, shift) | |
201 | DI val; | |
202 | SI shift; | |
203 | { | |
204 | SI hi = GETHIDI (val); | |
205 | USI lo = GETLODI (val); | |
206 | /* FIXME: Need to worry about shift < 0 || shift >= 32. */ | |
207 | return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift); | |
208 | } | |
209 | ||
210 | DI | |
211 | SRADI (val, shift) | |
212 | DI val; | |
213 | SI shift; | |
214 | { | |
215 | SI hi = GETHIDI (val); | |
216 | USI lo = GETLODI (val); | |
217 | /* We use SRASI because the result is implementation defined if hi < 0. */ | |
218 | /* FIXME: Need to worry about shift < 0 || shift >= 32. */ | |
219 | return MAKEDI (SRASI (hi, shift), (hi << (32 - shift)) | (lo >> shift)); | |
220 | } | |
221 | ||
222 | int | |
223 | GEDI (a, b) | |
224 | DI a, b; | |
225 | { | |
226 | SI ahi = GETHIDI (a); | |
227 | USI alo = GETLODI (a); | |
228 | SI bhi = GETHIDI (b); | |
229 | USI blo = GETLODI (b); | |
230 | if (ahi > bhi) | |
231 | return 1; | |
232 | if (ahi == bhi) | |
233 | return alo >= blo; | |
234 | return 0; | |
235 | } | |
236 | ||
237 | int | |
238 | LEDI (a, b) | |
239 | DI a, b; | |
240 | { | |
241 | SI ahi = GETHIDI (a); | |
242 | USI alo = GETLODI (a); | |
243 | SI bhi = GETHIDI (b); | |
244 | USI blo = GETLODI (b); | |
245 | if (ahi < bhi) | |
246 | return 1; | |
247 | if (ahi == bhi) | |
248 | return alo <= blo; | |
249 | return 0; | |
250 | } | |
251 | ||
252 | DI | |
253 | CONVHIDI (val) | |
254 | HI val; | |
255 | { | |
256 | if (val < 0) | |
257 | return MAKEDI (-1, val); | |
258 | else | |
259 | return MAKEDI (0, val); | |
260 | } | |
261 | ||
262 | DI | |
263 | CONVSIDI (val) | |
264 | SI val; | |
265 | { | |
266 | if (val < 0) | |
267 | return MAKEDI (-1, val); | |
268 | else | |
269 | return MAKEDI (0, val); | |
270 | } | |
271 | ||
272 | SI | |
273 | CONVDISI (val) | |
274 | DI val; | |
275 | { | |
276 | return GETLODI (val); | |
277 | } | |
278 | ||
279 | #endif /* DI_FN_SUPPORT */ | |
adf40b2e | 280 | \f |
6d4c43bf | 281 | QI |
81e6e8ae | 282 | RORQI (QI val, int shift) |
6d4c43bf DB |
283 | { |
284 | if (shift != 0) | |
285 | { | |
286 | int remain = 8 - shift; | |
287 | int mask = (1 << shift) - 1; | |
288 | QI result = (val & mask) << remain; | |
289 | mask = (1 << remain) - 1; | |
290 | result |= (val >> shift) & mask; | |
291 | return result; | |
292 | } | |
293 | return val; | |
294 | } | |
295 | ||
296 | QI | |
81e6e8ae | 297 | ROLQI (QI val, int shift) |
6d4c43bf DB |
298 | { |
299 | if (shift != 0) | |
300 | { | |
301 | int remain = 8 - shift; | |
302 | int mask = (1 << remain) - 1; | |
303 | QI result = (val & mask) << shift; | |
304 | mask = (1 << shift) - 1; | |
305 | result |= (val >> remain) & mask; | |
306 | return result; | |
307 | } | |
308 | return val; | |
309 | } | |
310 | ||
311 | HI | |
81e6e8ae | 312 | RORHI (HI val, int shift) |
6d4c43bf DB |
313 | { |
314 | if (shift != 0) | |
315 | { | |
316 | int remain = 16 - shift; | |
317 | int mask = (1 << shift) - 1; | |
318 | HI result = (val & mask) << remain; | |
319 | mask = (1 << remain) - 1; | |
320 | result |= (val >> shift) & mask; | |
321 | return result; | |
322 | } | |
323 | return val; | |
324 | } | |
325 | ||
326 | HI | |
81e6e8ae | 327 | ROLHI (HI val, int shift) |
6d4c43bf DB |
328 | { |
329 | if (shift != 0) | |
330 | { | |
331 | int remain = 16 - shift; | |
332 | int mask = (1 << remain) - 1; | |
333 | HI result = (val & mask) << shift; | |
334 | mask = (1 << shift) - 1; | |
335 | result |= (val >> remain) & mask; | |
336 | return result; | |
337 | } | |
338 | return val; | |
339 | } | |
340 | ||
adf40b2e | 341 | SI |
81e6e8ae | 342 | RORSI (SI val, int shift) |
adf40b2e JM |
343 | { |
344 | if (shift != 0) | |
345 | { | |
346 | int remain = 32 - shift; | |
347 | int mask = (1 << shift) - 1; | |
348 | SI result = (val & mask) << remain; | |
349 | mask = (1 << remain) - 1; | |
350 | result |= (val >> shift) & mask; | |
351 | return result; | |
352 | } | |
353 | return val; | |
354 | } | |
355 | ||
356 | SI | |
81e6e8ae | 357 | ROLSI (SI val, int shift) |
adf40b2e JM |
358 | { |
359 | if (shift != 0) | |
360 | { | |
361 | int remain = 32 - shift; | |
362 | int mask = (1 << remain) - 1; | |
363 | SI result = (val & mask) << shift; | |
364 | mask = (1 << shift) - 1; | |
365 | result |= (val >> remain) & mask; | |
366 | return result; | |
367 | } | |
368 | ||
369 | return val; | |
370 | } | |
a8d894af BE |
371 | |
372 | /* Emit an error message from CGEN RTL. */ | |
373 | ||
374 | void | |
375 | cgen_rtx_error (SIM_CPU *cpu, const char * msg) | |
376 | { | |
377 | SIM_DESC sd = CPU_STATE (cpu); | |
378 | ||
6ae9091a | 379 | sim_io_printf (sd, "%s", msg); |
a8d894af BE |
380 | sim_io_printf (sd, "\n"); |
381 | ||
034685f9 | 382 | sim_engine_halt (sd, cpu, NULL, CPU_PC_GET (cpu), sim_stopped, SIM_SIGTRAP); |
a8d894af | 383 | } |