cgen-utils.c revision 1.11 1 /* Support code for various pieces of CGEN simulators.
2 Copyright (C) 1996-2024 Free Software Foundation, Inc.
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
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 /* This must come before any other includes. */
21 #include "defs.h"
22
23 #include "bfd.h"
24 #include "dis-asm.h"
25
26 #include "sim-main.h"
27 #include "sim-signal.h"
28
29 #define MEMOPS_DEFINE_INLINE
30 #include "cgen-mem.h"
31
32 #define SEMOPS_DEFINE_INLINE
33 #include "cgen-ops.h"
34
35 const char * const cgen_mode_names[] = {
36 "VOID",
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 {
63 VIRTUAL_INSN_X_INVALID, "--invalid--", NULL, 0, { V, {} }
64 },
65 {
66 VIRTUAL_INSN_X_BEFORE, "--before--", NULL, 0, { V, {} }
67 },
68 {
69 VIRTUAL_INSN_X_AFTER, "--after--", NULL, 0, { V, {} }
70 },
71 {
72 VIRTUAL_INSN_X_BEGIN, "--begin--", NULL, 0, { V, {} }
73 },
74 {
75 VIRTUAL_INSN_X_CHAIN, "--chain--", NULL, 0, { V, {} }
76 },
77 {
78 VIRTUAL_INSN_X_CTI_CHAIN, "--cti-chain--", NULL, 0, { V, {} }
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
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
105 cgen_cpu_max_extra_bytes (SIM_DESC sd)
106 {
107 const SIM_MACH * const *machp;
108 int extra = 0;
109
110 SIM_ASSERT (STATE_MACHS (sd) != NULL);
111
112 for (machp = STATE_MACHS (sd); *machp != NULL; ++machp)
113 {
114 int size = IMP_PROPS_SIM_CPU_SIZE (MACH_IMP_PROPS (*machp));
115 if (size > extra)
116 extra = size;
117 }
118 return extra;
119 }
120
121 #ifdef DI_FN_SUPPORT
123
124 DI
125 ANDDI (a, b)
126 DI a, b;
127 {
128 SI ahi = GETHIDI (a);
129 SI alo = GETLODI (a);
130 SI bhi = GETHIDI (b);
131 SI blo = GETLODI (b);
132 return MAKEDI (ahi & bhi, alo & blo);
133 }
134
135 DI
136 ORDI (a, b)
137 DI a, b;
138 {
139 SI ahi = GETHIDI (a);
140 SI alo = GETLODI (a);
141 SI bhi = GETHIDI (b);
142 SI blo = GETLODI (b);
143 return MAKEDI (ahi | bhi, alo | blo);
144 }
145
146 DI
147 ADDDI (a, b)
148 DI a, b;
149 {
150 USI ahi = GETHIDI (a);
151 USI alo = GETLODI (a);
152 USI bhi = GETHIDI (b);
153 USI blo = GETLODI (b);
154 USI x = alo + blo;
155 return MAKEDI (ahi + bhi + (x < alo), x);
156 }
157
158 DI
159 MULDI (a, b)
160 DI a, b;
161 {
162 USI ahi = GETHIDI (a);
163 USI alo = GETLODI (a);
164 USI bhi = GETHIDI (b);
165 USI blo = GETLODI (b);
166 USI rhi,rlo;
167 USI x0, x1, x2, x3;
168
169 x0 = alo * blo;
170 x1 = alo * bhi;
171 x2 = ahi * blo;
172 x3 = ahi * bhi;
173
174 #define SI_TYPE_SIZE 32
175 #define BITS4 (SI_TYPE_SIZE / 4)
176 #define ll_B (1L << (SI_TYPE_SIZE / 2))
177 #define ll_lowpart(t) ((USI) (t) % ll_B)
178 #define ll_highpart(t) ((USI) (t) / ll_B)
179 x1 += ll_highpart (x0); /* this can't give carry */
180 x1 += x2; /* but this indeed can */
181 if (x1 < x2) /* did we get it? */
182 x3 += ll_B; /* yes, add it in the proper pos. */
183
184 rhi = x3 + ll_highpart (x1);
185 rlo = ll_lowpart (x1) * ll_B + ll_lowpart (x0);
186 return MAKEDI (rhi + (alo * bhi) + (ahi * blo), rlo);
187 }
188
189 DI
190 SHLDI (val, shift)
191 DI val;
192 SI shift;
193 {
194 USI hi = GETHIDI (val);
195 USI lo = GETLODI (val);
196 /* FIXME: Need to worry about shift < 0 || shift >= 32. */
197 return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift);
198 }
199
200 DI
201 SLADI (val, shift)
202 DI val;
203 SI shift;
204 {
205 SI hi = GETHIDI (val);
206 USI lo = GETLODI (val);
207 /* FIXME: Need to worry about shift < 0 || shift >= 32. */
208 return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift);
209 }
210
211 DI
212 SRADI (val, shift)
213 DI val;
214 SI shift;
215 {
216 SI hi = GETHIDI (val);
217 USI lo = GETLODI (val);
218 /* We use SRASI because the result is implementation defined if hi < 0. */
219 /* FIXME: Need to worry about shift < 0 || shift >= 32. */
220 return MAKEDI (SRASI (hi, shift), (hi << (32 - shift)) | (lo >> shift));
221 }
222
223 int
224 GEDI (a, b)
225 DI a, b;
226 {
227 SI ahi = GETHIDI (a);
228 USI alo = GETLODI (a);
229 SI bhi = GETHIDI (b);
230 USI blo = GETLODI (b);
231 if (ahi > bhi)
232 return 1;
233 if (ahi == bhi)
234 return alo >= blo;
235 return 0;
236 }
237
238 int
239 LEDI (a, b)
240 DI a, b;
241 {
242 SI ahi = GETHIDI (a);
243 USI alo = GETLODI (a);
244 SI bhi = GETHIDI (b);
245 USI blo = GETLODI (b);
246 if (ahi < bhi)
247 return 1;
248 if (ahi == bhi)
249 return alo <= blo;
250 return 0;
251 }
252
253 DI
254 CONVHIDI (val)
255 HI val;
256 {
257 if (val < 0)
258 return MAKEDI (-1, val);
259 else
260 return MAKEDI (0, val);
261 }
262
263 DI
264 CONVSIDI (val)
265 SI val;
266 {
267 if (val < 0)
268 return MAKEDI (-1, val);
269 else
270 return MAKEDI (0, val);
271 }
272
273 SI
274 CONVDISI (val)
275 DI val;
276 {
277 return GETLODI (val);
278 }
279
280 #endif /* DI_FN_SUPPORT */
281
282 QI
284 RORQI (QI val, int shift)
285 {
286 if (shift != 0)
287 {
288 int remain = 8 - shift;
289 int mask = (1 << shift) - 1;
290 QI result = (val & mask) << remain;
291 mask = (1 << remain) - 1;
292 result |= (val >> shift) & mask;
293 return result;
294 }
295 return val;
296 }
297
298 QI
299 ROLQI (QI val, int shift)
300 {
301 if (shift != 0)
302 {
303 int remain = 8 - shift;
304 int mask = (1 << remain) - 1;
305 QI result = (val & mask) << shift;
306 mask = (1 << shift) - 1;
307 result |= (val >> remain) & mask;
308 return result;
309 }
310 return val;
311 }
312
313 HI
314 RORHI (HI val, int shift)
315 {
316 if (shift != 0)
317 {
318 int remain = 16 - shift;
319 int mask = (1 << shift) - 1;
320 HI result = (val & mask) << remain;
321 mask = (1 << remain) - 1;
322 result |= (val >> shift) & mask;
323 return result;
324 }
325 return val;
326 }
327
328 HI
329 ROLHI (HI val, int shift)
330 {
331 if (shift != 0)
332 {
333 int remain = 16 - shift;
334 int mask = (1 << remain) - 1;
335 HI result = (val & mask) << shift;
336 mask = (1 << shift) - 1;
337 result |= (val >> remain) & mask;
338 return result;
339 }
340 return val;
341 }
342
343 SI
344 RORSI (SI val, int shift)
345 {
346 if (shift != 0)
347 {
348 int remain = 32 - shift;
349 int mask = (1 << shift) - 1;
350 SI result = (val & mask) << remain;
351 mask = (1 << remain) - 1;
352 result |= (val >> shift) & mask;
353 return result;
354 }
355 return val;
356 }
357
358 SI
359 ROLSI (SI val, int shift)
360 {
361 if (shift != 0)
362 {
363 int remain = 32 - shift;
364 int mask = (1 << remain) - 1;
365 SI result = (val & mask) << shift;
366 mask = (1 << shift) - 1;
367 result |= (val >> remain) & mask;
368 return result;
369 }
370
371 return val;
372 }
373
374 /* Emit an error message from CGEN RTL. */
375
376 void
377 cgen_rtx_error (SIM_CPU *cpu, const char * msg)
378 {
379 SIM_DESC sd = CPU_STATE (cpu);
380
381 sim_io_printf (sd, "%s", msg);
382 sim_io_printf (sd, "\n");
383
384 sim_engine_halt (sd, cpu, NULL, CPU_PC_GET (cpu), sim_stopped, SIM_SIGTRAP);
385 }
386