msp430/gas: correct BFD_RELOC_32 handling
[binutils-gdb.git] / sim / common / cgen-utils.c
blob40d3e69601cbd024dce6ad6c72ff282a45526b95
1 /* Support code for various pieces of CGEN simulators.
2 Copyright (C) 1996-2024 Free Software Foundation, Inc.
3 Contributed by Cygnus Support.
5 This file is part of GDB, the GNU debugger.
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.
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.
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/>. */
20 /* This must come before any other includes. */
21 #include "defs.h"
23 #include "bfd.h"
24 #include "dis-asm.h"
26 #include "sim-main.h"
27 #include "sim-signal.h"
29 #define MEMOPS_DEFINE_INLINE
30 #include "cgen-mem.h"
32 #define SEMOPS_DEFINE_INLINE
33 #include "cgen-ops.h"
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"
56 /* Opcode table for virtual insns used by the simulator. */
58 #define V CGEN_ATTR_MASK (CGEN_INSN_VIRTUAL)
60 static const CGEN_IBASE virtual_insn_entries[] =
63 VIRTUAL_INSN_X_INVALID, "--invalid--", NULL, 0, { V, {} }
66 VIRTUAL_INSN_X_BEFORE, "--before--", NULL, 0, { V, {} }
69 VIRTUAL_INSN_X_AFTER, "--after--", NULL, 0, { V, {} }
72 VIRTUAL_INSN_X_BEGIN, "--begin--", NULL, 0, { V, {} }
75 VIRTUAL_INSN_X_CHAIN, "--chain--", NULL, 0, { V, {} }
78 VIRTUAL_INSN_X_CTI_CHAIN, "--cti-chain--", NULL, 0, { V, {} }
82 #undef V
84 const CGEN_INSN cgen_virtual_insn_table[] =
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] }
94 /* Return the name of insn number I. */
96 const char *
97 cgen_insn_name (SIM_CPU *cpu, int i)
99 return CGEN_INSN_NAME ((* CPU_GET_IDATA (cpu)) ((cpu), (i)));
102 /* Return the maximum number of extra bytes required for a SIM_CPU struct. */
105 cgen_cpu_max_extra_bytes (SIM_DESC sd)
107 const SIM_MACH * const *machp;
108 int extra = 0;
110 SIM_ASSERT (STATE_MACHS (sd) != NULL);
112 for (machp = STATE_MACHS (sd); *machp != NULL; ++machp)
114 int size = IMP_PROPS_SIM_CPU_SIZE (MACH_IMP_PROPS (*machp));
115 if (size > extra)
116 extra = size;
118 return extra;
121 #ifdef DI_FN_SUPPORT
124 ANDDI (a, b)
125 DI a, b;
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);
135 ORDI (a, b)
136 DI a, b;
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);
146 ADDDI (a, b)
147 DI a, b;
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);
158 MULDI (a, b)
159 DI a, b;
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;
168 x0 = alo * blo;
169 x1 = alo * bhi;
170 x2 = ahi * blo;
171 x3 = ahi * bhi;
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. */
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);
189 SHLDI (val, shift)
190 DI val;
191 SI shift;
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);
200 SLADI (val, shift)
201 DI val;
202 SI shift;
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);
211 SRADI (val, shift)
212 DI val;
213 SI shift;
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));
223 GEDI (a, b)
224 DI a, b;
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;
238 LEDI (a, b)
239 DI a, b;
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;
253 CONVHIDI (val)
254 HI val;
256 if (val < 0)
257 return MAKEDI (-1, val);
258 else
259 return MAKEDI (0, val);
263 CONVSIDI (val)
264 SI val;
266 if (val < 0)
267 return MAKEDI (-1, val);
268 else
269 return MAKEDI (0, val);
273 CONVDISI (val)
274 DI val;
276 return GETLODI (val);
279 #endif /* DI_FN_SUPPORT */
282 RORQI (QI val, int shift)
284 if (shift != 0)
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;
293 return val;
297 ROLQI (QI val, int shift)
299 if (shift != 0)
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;
308 return val;
312 RORHI (HI val, int shift)
314 if (shift != 0)
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;
323 return val;
327 ROLHI (HI val, int shift)
329 if (shift != 0)
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;
338 return val;
342 RORSI (SI val, int shift)
344 if (shift != 0)
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;
353 return val;
357 ROLSI (SI val, int shift)
359 if (shift != 0)
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;
369 return val;
372 /* Emit an error message from CGEN RTL. */
374 void
375 cgen_rtx_error (SIM_CPU *cpu, const char * msg)
377 SIM_DESC sd = CPU_STATE (cpu);
379 sim_io_printf (sd, "%s", msg);
380 sim_io_printf (sd, "\n");
382 sim_engine_halt (sd, cpu, NULL, CPU_PC_GET (cpu), sim_stopped, SIM_SIGTRAP);