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