1/* Support code for various pieces of CGEN simulators.
2   Copyright (C) 1996-2023 Free Software Foundation, Inc.
3   Contributed by Cygnus Support.
4
5This file is part of GDB, the GNU debugger.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along 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
35const 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
60static 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
84const 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
96const char *
97cgen_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
104int
105cgen_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
122
123DI
124ANDDI (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
134DI
135ORDI (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
145DI
146ADDDI (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
157DI
158MULDI (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
188DI
189SHLDI (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
199DI
200SLADI (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
210DI
211SRADI (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
222int
223GEDI (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
237int
238LEDI (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
252DI
253CONVHIDI (val)
254     HI val;
255{
256  if (val < 0)
257    return MAKEDI (-1, val);
258  else
259    return MAKEDI (0, val);
260}
261
262DI
263CONVSIDI (val)
264     SI val;
265{
266  if (val < 0)
267    return MAKEDI (-1, val);
268  else
269    return MAKEDI (0, val);
270}
271
272SI
273CONVDISI (val)
274     DI val;
275{
276  return GETLODI (val);
277}
278
279#endif /* DI_FN_SUPPORT */
280
281QI
282RORQI (QI val, int shift)
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
296QI
297ROLQI (QI val, int shift)
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
311HI
312RORHI (HI val, int shift)
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
326HI
327ROLHI (HI val, int shift)
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
341SI
342RORSI (SI val, int shift)
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
356SI
357ROLSI (SI val, int shift)
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}
371
372/* Emit an error message from CGEN RTL.  */
373
374void
375cgen_rtx_error (SIM_CPU *cpu, const char * msg)
376{
377  SIM_DESC sd = CPU_STATE (cpu);
378
379  sim_io_printf (sd, "%s", msg);
380  sim_io_printf (sd, "\n");
381
382  sim_engine_halt (sd, cpu, NULL, CPU_PC_GET (cpu), sim_stopped, SIM_SIGTRAP);
383}
384