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