This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / sim / common / cgen-utils.c
1 /* Support code for various pieces of CGEN simulators.
2    Copyright (C) 1996, 1997, 1998, 1999 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 2, or (at your option)
10 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 along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #include "bfd.h"
22 #include "sim-main.h"
23 #include "dis-asm.h"
24
25 #define MEMOPS_DEFINE_INLINE
26 #include "cgen-mem.h"
27
28 #define SEMOPS_DEFINE_INLINE
29 #include "cgen-ops.h"
30
31 #undef min
32 #define min(a,b) ((a) < (b) ? (a) : (b))
33
34 const char *mode_names[] = {
35   "VM",
36   "BI",
37   "QI",
38   "HI",
39   "SI",
40   "DI",
41   "UQI",
42   "UHI",
43   "USI",
44   "UDI",
45   "SF",
46   "DF",
47   "XF",
48   "TF",
49   0, /* MODE_TARGET_MAX */
50   "INT",
51   "UINT",
52   "PTR"
53 };
54
55 /* Opcode table for virtual insns used by the simulator.  */
56
57 #define V CGEN_ATTR_MASK (CGEN_INSN_VIRTUAL)
58
59 static const CGEN_IBASE virtual_insn_entries[] =
60 {
61   {
62     VIRTUAL_INSN_X_INVALID, "--invalid--", NULL, 0, { V, { 0 } }
63   },
64   {
65     VIRTUAL_INSN_X_BEFORE, "--before--", NULL, 0, { V, { 0 } }
66   },
67   {
68     VIRTUAL_INSN_X_AFTER, "--after--", NULL, 0, { V, { 0 } }
69   },
70   {
71     VIRTUAL_INSN_X_BEGIN, "--begin--", NULL, 0, { V, { 0 } }
72   },
73   {
74     VIRTUAL_INSN_X_CHAIN, "--chain--", NULL, 0, { V, { 0 } }
75   },
76   {
77     VIRTUAL_INSN_X_CTI_CHAIN, "--cti-chain--", NULL, 0, { V, { 0 } }
78   }
79 };
80
81 #undef V
82
83 const CGEN_INSN cgen_virtual_insn_table[] =
84 {
85   { & virtual_insn_entries[0] },
86   { & virtual_insn_entries[1] },
87   { & virtual_insn_entries[2] },
88   { & virtual_insn_entries[3] },
89   { & virtual_insn_entries[4] },
90   { & virtual_insn_entries[5] }
91 };
92
93 /* Initialize cgen things.
94    This is called after sim_post_argv_init.  */
95
96 void
97 cgen_init (SIM_DESC sd)
98 {
99   int i, c;
100
101   /* If no profiling or tracing has been enabled, run in fast mode.  */
102   {
103     int run_fast_p = 1;
104
105     for (c = 0; c < MAX_NR_PROCESSORS; ++c)
106       {
107         SIM_CPU *cpu = STATE_CPU (sd, c);
108
109         for (i = 0; i < MAX_PROFILE_VALUES; ++i)
110           if (CPU_PROFILE_FLAGS (cpu) [i])
111             {
112               run_fast_p = 0;
113               break;
114             }
115         for (i = 0; i < MAX_TRACE_VALUES; ++i)
116           if (CPU_TRACE_FLAGS (cpu) [i])
117             {
118               run_fast_p = 0;
119               break;
120             }
121         if (! run_fast_p)
122           break;
123       }
124     STATE_RUN_FAST_P (sd) = run_fast_p;
125   }
126 }
127
128 /* Return the name of insn number I.  */
129
130 const char *
131 cgen_insn_name (SIM_CPU *cpu, int i)
132 {
133   return CGEN_INSN_NAME ((* CPU_GET_IDATA (cpu)) ((cpu), (i)));
134 }
135
136 /* Return the maximum number of extra bytes required for a SIM_CPU struct.  */
137
138 int
139 cgen_cpu_max_extra_bytes (void)
140 {
141   int i;
142   int extra = 0;
143
144   for (i = 0; sim_machs[i] != 0; ++i)
145     {
146       int size = IMP_PROPS_SIM_CPU_SIZE (MACH_IMP_PROPS (sim_machs[i]));
147       if (size > extra)
148         extra = size;
149     }
150   return extra;
151 }
152 \f
153 #ifdef DI_FN_SUPPORT
154
155 DI
156 make_struct_di (hi, lo)
157      SI hi, lo;
158 {
159   DI result;
160
161   result.hi = hi;
162   result.lo = lo;
163   return result;
164 }
165
166 DI
167 ANDDI (a, b)
168      DI a, b;
169 {
170   SI ahi = GETHIDI (a);
171   SI alo = GETLODI (a);
172   SI bhi = GETHIDI (b);
173   SI blo = GETLODI (b);
174   return MAKEDI (ahi & bhi, alo & blo);
175 }
176
177 DI
178 ORDI (a, b)
179      DI a, b;
180 {
181   SI ahi = GETHIDI (a);
182   SI alo = GETLODI (a);
183   SI bhi = GETHIDI (b);
184   SI blo = GETLODI (b);
185   return MAKEDI (ahi | bhi, alo | blo);
186 }
187
188 DI
189 ADDDI (a, b)
190      DI a, b;
191 {
192   USI ahi = GETHIDI (a);
193   USI alo = GETLODI (a);
194   USI bhi = GETHIDI (b);
195   USI blo = GETLODI (b);
196   USI x = alo + blo;
197   return MAKEDI (ahi + bhi + (x < alo), x);
198 }
199
200 DI
201 MULDI (a, b)
202      DI a, b;
203 {
204   USI ahi = GETHIDI (a);
205   USI alo = GETLODI (a);
206   USI bhi = GETHIDI (b);
207   USI blo = GETLODI (b);
208   USI rhi,rlo;
209   USI x0, x1, x2, x3;
210
211   x0 = alo * blo;
212   x1 = alo * bhi;
213   x2 = ahi * blo;
214   x3 = ahi * bhi;
215
216 #define SI_TYPE_SIZE 32
217 #define BITS4 (SI_TYPE_SIZE / 4)
218 #define ll_B (1L << (SI_TYPE_SIZE / 2))
219 #define ll_lowpart(t) ((USI) (t) % ll_B)
220 #define ll_highpart(t) ((USI) (t) / ll_B)
221   x1 += ll_highpart (x0);       /* this can't give carry */
222   x1 += x2;                     /* but this indeed can */
223   if (x1 < x2)                  /* did we get it? */
224     x3 += ll_B;                 /* yes, add it in the proper pos. */
225
226   rhi = x3 + ll_highpart (x1);
227   rlo = ll_lowpart (x1) * ll_B + ll_lowpart (x0);
228   return MAKEDI (rhi + (alo * bhi) + (ahi * blo), rlo);
229 }
230
231 DI
232 SHLDI (val, shift)
233      DI val;
234      SI shift;
235 {
236   USI hi = GETHIDI (val);
237   USI lo = GETLODI (val);
238   /* FIXME: Need to worry about shift < 0 || shift >= 32.  */
239   return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift);
240 }
241
242 DI
243 SLADI (val, shift)
244      DI val;
245      SI shift;
246 {
247   SI hi = GETHIDI (val);
248   USI lo = GETLODI (val);
249   /* FIXME: Need to worry about shift < 0 || shift >= 32.  */
250   return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift);
251 }
252
253 DI
254 SRADI (val, shift)
255      DI val;
256      SI shift;
257 {
258   SI hi = GETHIDI (val);
259   USI lo = GETLODI (val);
260   /* We use SRASI because the result is implementation defined if hi < 0.  */
261   /* FIXME: Need to worry about shift < 0 || shift >= 32.  */
262   return MAKEDI (SRASI (hi, shift), (hi << (32 - shift)) | (lo >> shift));
263 }
264
265 int
266 GEDI (a, b)
267      DI a, b;
268 {
269   SI ahi = GETHIDI (a);
270   USI alo = GETLODI (a);
271   SI bhi = GETHIDI (b);
272   USI blo = GETLODI (b);
273   if (ahi > bhi)
274     return 1;
275   if (ahi == bhi)
276     return alo >= blo;
277   return 0;
278 }
279
280 int
281 LEDI (a, b)
282      DI a, b;
283 {
284   SI ahi = GETHIDI (a);
285   USI alo = GETLODI (a);
286   SI bhi = GETHIDI (b);
287   USI blo = GETLODI (b);
288   if (ahi < bhi)
289     return 1;
290   if (ahi == bhi)
291     return alo <= blo;
292   return 0;
293 }
294
295 DI
296 CONVHIDI (val)
297      HI val;
298 {
299   if (val < 0)
300     return MAKEDI (-1, val);
301   else
302     return MAKEDI (0, val);
303 }
304
305 DI
306 CONVSIDI (val)
307      SI val;
308 {
309   if (val < 0)
310     return MAKEDI (-1, val);
311   else
312     return MAKEDI (0, val);
313 }
314
315 SI
316 CONVDISI (val)
317      DI val;
318 {
319   return GETLODI (val);
320 }
321
322 #endif /* DI_FN_SUPPORT */