1c5dff60aSchristos /* Support code for various pieces of CGEN simulators.
2*1424dfb3Schristos    Copyright (C) 1996-2020 Free Software Foundation, Inc.
3c5dff60aSchristos    Contributed by Cygnus Support.
4c5dff60aSchristos 
5c5dff60aSchristos This file is part of GDB, the GNU debugger.
6c5dff60aSchristos 
7c5dff60aSchristos This program is free software; you can redistribute it and/or modify
8c5dff60aSchristos it under the terms of the GNU General Public License as published by
9c5dff60aSchristos the Free Software Foundation; either version 3 of the License, or
10c5dff60aSchristos (at your option) any later version.
11c5dff60aSchristos 
12c5dff60aSchristos This program is distributed in the hope that it will be useful,
13c5dff60aSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of
14c5dff60aSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15c5dff60aSchristos GNU General Public License for more details.
16c5dff60aSchristos 
17c5dff60aSchristos You should have received a copy of the GNU General Public License
18c5dff60aSchristos along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19c5dff60aSchristos 
2048596154Schristos #include "config.h"
21c5dff60aSchristos #include "bfd.h"
22c5dff60aSchristos #include "sim-main.h"
23c5dff60aSchristos #include "dis-asm.h"
24c5dff60aSchristos 
25c5dff60aSchristos #define MEMOPS_DEFINE_INLINE
26c5dff60aSchristos #include "cgen-mem.h"
27c5dff60aSchristos 
28c5dff60aSchristos #define SEMOPS_DEFINE_INLINE
29c5dff60aSchristos #include "cgen-ops.h"
30c5dff60aSchristos 
311c468f90Schristos const char * const mode_names[] = {
32c5dff60aSchristos   "VOID",
33c5dff60aSchristos   "BI",
34c5dff60aSchristos   "QI",
35c5dff60aSchristos   "HI",
36c5dff60aSchristos   "SI",
37c5dff60aSchristos   "DI",
38c5dff60aSchristos   "UQI",
39c5dff60aSchristos   "UHI",
40c5dff60aSchristos   "USI",
41c5dff60aSchristos   "UDI",
42c5dff60aSchristos   "SF",
43c5dff60aSchristos   "DF",
44c5dff60aSchristos   "XF",
45c5dff60aSchristos   "TF",
46c5dff60aSchristos   0, /* MODE_TARGET_MAX */
47c5dff60aSchristos   "INT",
48c5dff60aSchristos   "UINT",
49c5dff60aSchristos   "PTR"
50c5dff60aSchristos };
51c5dff60aSchristos 
52c5dff60aSchristos /* Opcode table for virtual insns used by the simulator.  */
53c5dff60aSchristos 
54c5dff60aSchristos #define V CGEN_ATTR_MASK (CGEN_INSN_VIRTUAL)
55c5dff60aSchristos 
56c5dff60aSchristos static const CGEN_IBASE virtual_insn_entries[] =
57c5dff60aSchristos {
58c5dff60aSchristos   {
59c5dff60aSchristos     VIRTUAL_INSN_X_INVALID, "--invalid--", NULL, 0, { V, { 0 } }
60c5dff60aSchristos   },
61c5dff60aSchristos   {
62c5dff60aSchristos     VIRTUAL_INSN_X_BEFORE, "--before--", NULL, 0, { V, { 0 } }
63c5dff60aSchristos   },
64c5dff60aSchristos   {
65c5dff60aSchristos     VIRTUAL_INSN_X_AFTER, "--after--", NULL, 0, { V, { 0 } }
66c5dff60aSchristos   },
67c5dff60aSchristos   {
68c5dff60aSchristos     VIRTUAL_INSN_X_BEGIN, "--begin--", NULL, 0, { V, { 0 } }
69c5dff60aSchristos   },
70c5dff60aSchristos   {
71c5dff60aSchristos     VIRTUAL_INSN_X_CHAIN, "--chain--", NULL, 0, { V, { 0 } }
72c5dff60aSchristos   },
73c5dff60aSchristos   {
74c5dff60aSchristos     VIRTUAL_INSN_X_CTI_CHAIN, "--cti-chain--", NULL, 0, { V, { 0 } }
75c5dff60aSchristos   }
76c5dff60aSchristos };
77c5dff60aSchristos 
78c5dff60aSchristos #undef V
79c5dff60aSchristos 
80c5dff60aSchristos const CGEN_INSN cgen_virtual_insn_table[] =
81c5dff60aSchristos {
82c5dff60aSchristos   { & virtual_insn_entries[0] },
83c5dff60aSchristos   { & virtual_insn_entries[1] },
84c5dff60aSchristos   { & virtual_insn_entries[2] },
85c5dff60aSchristos   { & virtual_insn_entries[3] },
86c5dff60aSchristos   { & virtual_insn_entries[4] },
87c5dff60aSchristos   { & virtual_insn_entries[5] }
88c5dff60aSchristos };
89c5dff60aSchristos 
90c5dff60aSchristos /* Initialize cgen things.
91c5dff60aSchristos    This is called after sim_post_argv_init.  */
92c5dff60aSchristos 
93c5dff60aSchristos void
cgen_init(SIM_DESC sd)94c5dff60aSchristos cgen_init (SIM_DESC sd)
95c5dff60aSchristos {
96c5dff60aSchristos   int i, c;
97c5dff60aSchristos 
98c5dff60aSchristos   /* If no profiling or tracing has been enabled, run in fast mode.  */
99c5dff60aSchristos   {
100c5dff60aSchristos     int run_fast_p = 1;
101c5dff60aSchristos 
102c5dff60aSchristos     for (c = 0; c < MAX_NR_PROCESSORS; ++c)
103c5dff60aSchristos       {
104c5dff60aSchristos 	SIM_CPU *cpu = STATE_CPU (sd, c);
105c5dff60aSchristos 
106c5dff60aSchristos 	for (i = 0; i < MAX_PROFILE_VALUES; ++i)
107c5dff60aSchristos 	  if (CPU_PROFILE_FLAGS (cpu) [i])
108c5dff60aSchristos 	    {
109c5dff60aSchristos 	      run_fast_p = 0;
110c5dff60aSchristos 	      break;
111c5dff60aSchristos 	    }
112c5dff60aSchristos 	for (i = 0; i < MAX_TRACE_VALUES; ++i)
113c5dff60aSchristos 	  if (CPU_TRACE_FLAGS (cpu) [i])
114c5dff60aSchristos 	    {
115c5dff60aSchristos 	      run_fast_p = 0;
116c5dff60aSchristos 	      break;
117c5dff60aSchristos 	    }
118c5dff60aSchristos 	if (! run_fast_p)
119c5dff60aSchristos 	  break;
120c5dff60aSchristos       }
121c5dff60aSchristos     STATE_RUN_FAST_P (sd) = run_fast_p;
122c5dff60aSchristos   }
123c5dff60aSchristos }
124c5dff60aSchristos 
125c5dff60aSchristos /* Return the name of insn number I.  */
126c5dff60aSchristos 
127c5dff60aSchristos const char *
cgen_insn_name(SIM_CPU * cpu,int i)128c5dff60aSchristos cgen_insn_name (SIM_CPU *cpu, int i)
129c5dff60aSchristos {
130c5dff60aSchristos   return CGEN_INSN_NAME ((* CPU_GET_IDATA (cpu)) ((cpu), (i)));
131c5dff60aSchristos }
132c5dff60aSchristos 
133c5dff60aSchristos /* Return the maximum number of extra bytes required for a SIM_CPU struct.  */
134c5dff60aSchristos 
135c5dff60aSchristos int
cgen_cpu_max_extra_bytes(void)136c5dff60aSchristos cgen_cpu_max_extra_bytes (void)
137c5dff60aSchristos {
138c5dff60aSchristos   int i;
139c5dff60aSchristos   int extra = 0;
140c5dff60aSchristos 
141c5dff60aSchristos   for (i = 0; sim_machs[i] != 0; ++i)
142c5dff60aSchristos     {
143c5dff60aSchristos       int size = IMP_PROPS_SIM_CPU_SIZE (MACH_IMP_PROPS (sim_machs[i]));
144c5dff60aSchristos       if (size > extra)
145c5dff60aSchristos 	extra = size;
146c5dff60aSchristos     }
147c5dff60aSchristos   return extra;
148c5dff60aSchristos }
149c5dff60aSchristos 
150c5dff60aSchristos #ifdef DI_FN_SUPPORT
151c5dff60aSchristos 
152c5dff60aSchristos DI
make_struct_di(hi,lo)153c5dff60aSchristos make_struct_di (hi, lo)
154c5dff60aSchristos      SI hi, lo;
155c5dff60aSchristos {
156c5dff60aSchristos   DI result;
157c5dff60aSchristos 
158c5dff60aSchristos   result.hi = hi;
159c5dff60aSchristos   result.lo = lo;
160c5dff60aSchristos   return result;
161c5dff60aSchristos }
162c5dff60aSchristos 
163c5dff60aSchristos DI
ANDDI(a,b)164c5dff60aSchristos ANDDI (a, b)
165c5dff60aSchristos      DI a, b;
166c5dff60aSchristos {
167c5dff60aSchristos   SI ahi = GETHIDI (a);
168c5dff60aSchristos   SI alo = GETLODI (a);
169c5dff60aSchristos   SI bhi = GETHIDI (b);
170c5dff60aSchristos   SI blo = GETLODI (b);
171c5dff60aSchristos   return MAKEDI (ahi & bhi, alo & blo);
172c5dff60aSchristos }
173c5dff60aSchristos 
174c5dff60aSchristos DI
ORDI(a,b)175c5dff60aSchristos ORDI (a, b)
176c5dff60aSchristos      DI a, b;
177c5dff60aSchristos {
178c5dff60aSchristos   SI ahi = GETHIDI (a);
179c5dff60aSchristos   SI alo = GETLODI (a);
180c5dff60aSchristos   SI bhi = GETHIDI (b);
181c5dff60aSchristos   SI blo = GETLODI (b);
182c5dff60aSchristos   return MAKEDI (ahi | bhi, alo | blo);
183c5dff60aSchristos }
184c5dff60aSchristos 
185c5dff60aSchristos DI
ADDDI(a,b)186c5dff60aSchristos ADDDI (a, b)
187c5dff60aSchristos      DI a, b;
188c5dff60aSchristos {
189c5dff60aSchristos   USI ahi = GETHIDI (a);
190c5dff60aSchristos   USI alo = GETLODI (a);
191c5dff60aSchristos   USI bhi = GETHIDI (b);
192c5dff60aSchristos   USI blo = GETLODI (b);
193c5dff60aSchristos   USI x = alo + blo;
194c5dff60aSchristos   return MAKEDI (ahi + bhi + (x < alo), x);
195c5dff60aSchristos }
196c5dff60aSchristos 
197c5dff60aSchristos DI
MULDI(a,b)198c5dff60aSchristos MULDI (a, b)
199c5dff60aSchristos      DI a, b;
200c5dff60aSchristos {
201c5dff60aSchristos   USI ahi = GETHIDI (a);
202c5dff60aSchristos   USI alo = GETLODI (a);
203c5dff60aSchristos   USI bhi = GETHIDI (b);
204c5dff60aSchristos   USI blo = GETLODI (b);
205c5dff60aSchristos   USI rhi,rlo;
206c5dff60aSchristos   USI x0, x1, x2, x3;
207c5dff60aSchristos 
208c5dff60aSchristos   x0 = alo * blo;
209c5dff60aSchristos   x1 = alo * bhi;
210c5dff60aSchristos   x2 = ahi * blo;
211c5dff60aSchristos   x3 = ahi * bhi;
212c5dff60aSchristos 
213c5dff60aSchristos #define SI_TYPE_SIZE 32
214c5dff60aSchristos #define BITS4 (SI_TYPE_SIZE / 4)
215c5dff60aSchristos #define ll_B (1L << (SI_TYPE_SIZE / 2))
216c5dff60aSchristos #define ll_lowpart(t) ((USI) (t) % ll_B)
217c5dff60aSchristos #define ll_highpart(t) ((USI) (t) / ll_B)
218c5dff60aSchristos   x1 += ll_highpart (x0);	/* this can't give carry */
219c5dff60aSchristos   x1 += x2;			/* but this indeed can */
220c5dff60aSchristos   if (x1 < x2)			/* did we get it? */
221c5dff60aSchristos     x3 += ll_B;			/* yes, add it in the proper pos. */
222c5dff60aSchristos 
223c5dff60aSchristos   rhi = x3 + ll_highpart (x1);
224c5dff60aSchristos   rlo = ll_lowpart (x1) * ll_B + ll_lowpart (x0);
225c5dff60aSchristos   return MAKEDI (rhi + (alo * bhi) + (ahi * blo), rlo);
226c5dff60aSchristos }
227c5dff60aSchristos 
228c5dff60aSchristos DI
SHLDI(val,shift)229c5dff60aSchristos SHLDI (val, shift)
230c5dff60aSchristos      DI val;
231c5dff60aSchristos      SI shift;
232c5dff60aSchristos {
233c5dff60aSchristos   USI hi = GETHIDI (val);
234c5dff60aSchristos   USI lo = GETLODI (val);
235c5dff60aSchristos   /* FIXME: Need to worry about shift < 0 || shift >= 32.  */
236c5dff60aSchristos   return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift);
237c5dff60aSchristos }
238c5dff60aSchristos 
239c5dff60aSchristos DI
SLADI(val,shift)240c5dff60aSchristos SLADI (val, shift)
241c5dff60aSchristos      DI val;
242c5dff60aSchristos      SI shift;
243c5dff60aSchristos {
244c5dff60aSchristos   SI hi = GETHIDI (val);
245c5dff60aSchristos   USI lo = GETLODI (val);
246c5dff60aSchristos   /* FIXME: Need to worry about shift < 0 || shift >= 32.  */
247c5dff60aSchristos   return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift);
248c5dff60aSchristos }
249c5dff60aSchristos 
250c5dff60aSchristos DI
SRADI(val,shift)251c5dff60aSchristos SRADI (val, shift)
252c5dff60aSchristos      DI val;
253c5dff60aSchristos      SI shift;
254c5dff60aSchristos {
255c5dff60aSchristos   SI hi = GETHIDI (val);
256c5dff60aSchristos   USI lo = GETLODI (val);
257c5dff60aSchristos   /* We use SRASI because the result is implementation defined if hi < 0.  */
258c5dff60aSchristos   /* FIXME: Need to worry about shift < 0 || shift >= 32.  */
259c5dff60aSchristos   return MAKEDI (SRASI (hi, shift), (hi << (32 - shift)) | (lo >> shift));
260c5dff60aSchristos }
261c5dff60aSchristos 
262c5dff60aSchristos int
GEDI(a,b)263c5dff60aSchristos GEDI (a, b)
264c5dff60aSchristos      DI a, b;
265c5dff60aSchristos {
266c5dff60aSchristos   SI ahi = GETHIDI (a);
267c5dff60aSchristos   USI alo = GETLODI (a);
268c5dff60aSchristos   SI bhi = GETHIDI (b);
269c5dff60aSchristos   USI blo = GETLODI (b);
270c5dff60aSchristos   if (ahi > bhi)
271c5dff60aSchristos     return 1;
272c5dff60aSchristos   if (ahi == bhi)
273c5dff60aSchristos     return alo >= blo;
274c5dff60aSchristos   return 0;
275c5dff60aSchristos }
276c5dff60aSchristos 
277c5dff60aSchristos int
LEDI(a,b)278c5dff60aSchristos LEDI (a, b)
279c5dff60aSchristos      DI a, b;
280c5dff60aSchristos {
281c5dff60aSchristos   SI ahi = GETHIDI (a);
282c5dff60aSchristos   USI alo = GETLODI (a);
283c5dff60aSchristos   SI bhi = GETHIDI (b);
284c5dff60aSchristos   USI blo = GETLODI (b);
285c5dff60aSchristos   if (ahi < bhi)
286c5dff60aSchristos     return 1;
287c5dff60aSchristos   if (ahi == bhi)
288c5dff60aSchristos     return alo <= blo;
289c5dff60aSchristos   return 0;
290c5dff60aSchristos }
291c5dff60aSchristos 
292c5dff60aSchristos DI
CONVHIDI(val)293c5dff60aSchristos CONVHIDI (val)
294c5dff60aSchristos      HI val;
295c5dff60aSchristos {
296c5dff60aSchristos   if (val < 0)
297c5dff60aSchristos     return MAKEDI (-1, val);
298c5dff60aSchristos   else
299c5dff60aSchristos     return MAKEDI (0, val);
300c5dff60aSchristos }
301c5dff60aSchristos 
302c5dff60aSchristos DI
CONVSIDI(val)303c5dff60aSchristos CONVSIDI (val)
304c5dff60aSchristos      SI val;
305c5dff60aSchristos {
306c5dff60aSchristos   if (val < 0)
307c5dff60aSchristos     return MAKEDI (-1, val);
308c5dff60aSchristos   else
309c5dff60aSchristos     return MAKEDI (0, val);
310c5dff60aSchristos }
311c5dff60aSchristos 
312c5dff60aSchristos SI
CONVDISI(val)313c5dff60aSchristos CONVDISI (val)
314c5dff60aSchristos      DI val;
315c5dff60aSchristos {
316c5dff60aSchristos   return GETLODI (val);
317c5dff60aSchristos }
318c5dff60aSchristos 
319c5dff60aSchristos #endif /* DI_FN_SUPPORT */
320c5dff60aSchristos 
321c5dff60aSchristos QI
RORQI(val,shift)322c5dff60aSchristos RORQI (val, shift)
323c5dff60aSchristos      QI  val;
324c5dff60aSchristos      int shift;
325c5dff60aSchristos {
326c5dff60aSchristos   if (shift != 0)
327c5dff60aSchristos     {
328c5dff60aSchristos       int remain = 8 - shift;
329c5dff60aSchristos       int mask = (1 << shift) - 1;
330c5dff60aSchristos       QI result = (val & mask) << remain;
331c5dff60aSchristos       mask = (1 << remain) - 1;
332c5dff60aSchristos       result |= (val >> shift) & mask;
333c5dff60aSchristos       return result;
334c5dff60aSchristos     }
335c5dff60aSchristos   return val;
336c5dff60aSchristos }
337c5dff60aSchristos 
338c5dff60aSchristos QI
ROLQI(val,shift)339c5dff60aSchristos ROLQI (val, shift)
340c5dff60aSchristos      QI  val;
341c5dff60aSchristos      int shift;
342c5dff60aSchristos {
343c5dff60aSchristos   if (shift != 0)
344c5dff60aSchristos     {
345c5dff60aSchristos       int remain = 8 - shift;
346c5dff60aSchristos       int mask = (1 << remain) - 1;
347c5dff60aSchristos       QI result = (val & mask) << shift;
348c5dff60aSchristos       mask = (1 << shift) - 1;
349c5dff60aSchristos       result |= (val >> remain) & mask;
350c5dff60aSchristos       return result;
351c5dff60aSchristos     }
352c5dff60aSchristos   return val;
353c5dff60aSchristos }
354c5dff60aSchristos 
355c5dff60aSchristos HI
RORHI(val,shift)356c5dff60aSchristos RORHI (val, shift)
357c5dff60aSchristos      HI  val;
358c5dff60aSchristos      int shift;
359c5dff60aSchristos {
360c5dff60aSchristos   if (shift != 0)
361c5dff60aSchristos     {
362c5dff60aSchristos       int remain = 16 - shift;
363c5dff60aSchristos       int mask = (1 << shift) - 1;
364c5dff60aSchristos       HI result = (val & mask) << remain;
365c5dff60aSchristos       mask = (1 << remain) - 1;
366c5dff60aSchristos       result |= (val >> shift) & mask;
367c5dff60aSchristos       return result;
368c5dff60aSchristos     }
369c5dff60aSchristos   return val;
370c5dff60aSchristos }
371c5dff60aSchristos 
372c5dff60aSchristos HI
ROLHI(val,shift)373c5dff60aSchristos ROLHI (val, shift)
374c5dff60aSchristos      HI  val;
375c5dff60aSchristos      int shift;
376c5dff60aSchristos {
377c5dff60aSchristos   if (shift != 0)
378c5dff60aSchristos     {
379c5dff60aSchristos       int remain = 16 - shift;
380c5dff60aSchristos       int mask = (1 << remain) - 1;
381c5dff60aSchristos       HI result = (val & mask) << shift;
382c5dff60aSchristos       mask = (1 << shift) - 1;
383c5dff60aSchristos       result |= (val >> remain) & mask;
384c5dff60aSchristos       return result;
385c5dff60aSchristos     }
386c5dff60aSchristos   return val;
387c5dff60aSchristos }
388c5dff60aSchristos 
389c5dff60aSchristos SI
RORSI(val,shift)390c5dff60aSchristos RORSI (val, shift)
391c5dff60aSchristos      SI  val;
392c5dff60aSchristos      int shift;
393c5dff60aSchristos {
394c5dff60aSchristos   if (shift != 0)
395c5dff60aSchristos     {
396c5dff60aSchristos       int remain = 32 - shift;
397c5dff60aSchristos       int mask = (1 << shift) - 1;
398c5dff60aSchristos       SI result = (val & mask) << remain;
399c5dff60aSchristos       mask = (1 << remain) - 1;
400c5dff60aSchristos       result |= (val >> shift) & mask;
401c5dff60aSchristos       return result;
402c5dff60aSchristos     }
403c5dff60aSchristos   return val;
404c5dff60aSchristos }
405c5dff60aSchristos 
406c5dff60aSchristos SI
ROLSI(val,shift)407c5dff60aSchristos ROLSI (val, shift)
408c5dff60aSchristos      SI  val;
409c5dff60aSchristos      int shift;
410c5dff60aSchristos {
411c5dff60aSchristos   if (shift != 0)
412c5dff60aSchristos     {
413c5dff60aSchristos       int remain = 32 - shift;
414c5dff60aSchristos       int mask = (1 << remain) - 1;
415c5dff60aSchristos       SI result = (val & mask) << shift;
416c5dff60aSchristos       mask = (1 << shift) - 1;
417c5dff60aSchristos       result |= (val >> remain) & mask;
418c5dff60aSchristos       return result;
419c5dff60aSchristos     }
420c5dff60aSchristos 
421c5dff60aSchristos   return val;
422c5dff60aSchristos }
423c5dff60aSchristos 
424c5dff60aSchristos /* Emit an error message from CGEN RTL.  */
425c5dff60aSchristos 
426c5dff60aSchristos void
cgen_rtx_error(SIM_CPU * cpu,const char * msg)427c5dff60aSchristos cgen_rtx_error (SIM_CPU *cpu, const char * msg)
428c5dff60aSchristos {
429c5dff60aSchristos   SIM_DESC sd = CPU_STATE (cpu);
430c5dff60aSchristos 
431c5dff60aSchristos   sim_io_printf (sd, msg);
432c5dff60aSchristos   sim_io_printf (sd, "\n");
433c5dff60aSchristos 
434ed6a76a9Schristos   sim_engine_halt (sd, cpu, NULL, CPU_PC_GET (cpu), sim_stopped, SIM_SIGTRAP);
435c5dff60aSchristos }
436