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,
63     { CGEN_INSN_NBOOL_ATTRS, V, { 0 } }
64   },
65   {
66     VIRTUAL_INSN_X_BEFORE, "--before--", NULL, 0,
67     { CGEN_INSN_NBOOL_ATTRS, V, { 0 } }
68   },
69   {
70     VIRTUAL_INSN_X_AFTER, "--after--", NULL, 0,
71     { CGEN_INSN_NBOOL_ATTRS, V, { 0 } }
72   },
73   {
74     VIRTUAL_INSN_X_BEGIN, "--begin--", NULL, 0,
75     { CGEN_INSN_NBOOL_ATTRS, V, { 0 } }
76   },
77   {
78     VIRTUAL_INSN_X_CHAIN, "--chain--", NULL, 0,
79     { CGEN_INSN_NBOOL_ATTRS, V, { 0 } }
80   },
81   {
82     VIRTUAL_INSN_X_CTI_CHAIN, "--cti-chain--", NULL, 0,
83     { CGEN_INSN_NBOOL_ATTRS, V, { 0 } }
84   }
85 };
86
87 #undef V
88
89 const CGEN_INSN cgen_virtual_insn_table[] =
90 {
91   { & virtual_insn_entries[0] },
92   { & virtual_insn_entries[1] },
93   { & virtual_insn_entries[2] },
94   { & virtual_insn_entries[3] },
95   { & virtual_insn_entries[4] },
96   { & virtual_insn_entries[5] }
97 };
98
99 /* Initialize cgen things.
100    This is called after sim_post_argv_init.  */
101
102 void
103 cgen_init (SIM_DESC sd)
104 {
105   int i, c;
106
107   /* If no profiling or tracing has been enabled, run in fast mode.  */
108   {
109     int run_fast_p = 1;
110
111     for (c = 0; c < MAX_NR_PROCESSORS; ++c)
112       {
113         SIM_CPU *cpu = STATE_CPU (sd, c);
114
115         for (i = 0; i < MAX_PROFILE_VALUES; ++i)
116           if (CPU_PROFILE_FLAGS (cpu) [i])
117             {
118               run_fast_p = 0;
119               break;
120             }
121         for (i = 0; i < MAX_TRACE_VALUES; ++i)
122           if (CPU_TRACE_FLAGS (cpu) [i])
123             {
124               run_fast_p = 0;
125               break;
126             }
127         if (! run_fast_p)
128           break;
129       }
130     STATE_RUN_FAST_P (sd) = run_fast_p;
131   }
132 }
133
134 /* Return the name of insn number I.  */
135
136 const char *
137 cgen_insn_name (SIM_CPU *cpu, int i)
138 {
139   return CGEN_INSN_NAME ((* CPU_GET_IDATA (cpu)) ((cpu), (i)));
140 }
141
142 /* Return the maximum number of extra bytes required for a SIM_CPU struct.  */
143
144 int
145 cgen_cpu_max_extra_bytes (void)
146 {
147   int i;
148   int extra = 0;
149
150   for (i = 0; sim_machs[i] != 0; ++i)
151     {
152       int size = IMP_PROPS_SIM_CPU_SIZE (MACH_IMP_PROPS (sim_machs[i]));
153       if (size > extra)
154         extra = size;
155     }
156   return extra;
157 }
158 \f
159 #ifdef DI_FN_SUPPORT
160
161 DI
162 make_struct_di (hi, lo)
163      SI hi, lo;
164 {
165   DI result;
166
167   result.hi = hi;
168   result.lo = lo;
169   return result;
170 }
171
172 DI
173 ANDDI (a, b)
174      DI a, b;
175 {
176   SI ahi = GETHIDI (a);
177   SI alo = GETLODI (a);
178   SI bhi = GETHIDI (b);
179   SI blo = GETLODI (b);
180   return MAKEDI (ahi & bhi, alo & blo);
181 }
182
183 DI
184 ORDI (a, b)
185      DI a, b;
186 {
187   SI ahi = GETHIDI (a);
188   SI alo = GETLODI (a);
189   SI bhi = GETHIDI (b);
190   SI blo = GETLODI (b);
191   return MAKEDI (ahi | bhi, alo | blo);
192 }
193
194 DI
195 ADDDI (a, b)
196      DI a, b;
197 {
198   USI ahi = GETHIDI (a);
199   USI alo = GETLODI (a);
200   USI bhi = GETHIDI (b);
201   USI blo = GETLODI (b);
202   USI x = alo + blo;
203   return MAKEDI (ahi + bhi + (x < alo), x);
204 }
205
206 DI
207 MULDI (a, b)
208      DI a, b;
209 {
210   USI ahi = GETHIDI (a);
211   USI alo = GETLODI (a);
212   USI bhi = GETHIDI (b);
213   USI blo = GETLODI (b);
214   USI rhi,rlo;
215   USI x0, x1, x2, x3;
216
217   x0 = alo * blo;
218   x1 = alo * bhi;
219   x2 = ahi * blo;
220   x3 = ahi * bhi;
221
222 #define SI_TYPE_SIZE 32
223 #define BITS4 (SI_TYPE_SIZE / 4)
224 #define ll_B (1L << (SI_TYPE_SIZE / 2))
225 #define ll_lowpart(t) ((USI) (t) % ll_B)
226 #define ll_highpart(t) ((USI) (t) / ll_B)
227   x1 += ll_highpart (x0);       /* this can't give carry */
228   x1 += x2;                     /* but this indeed can */
229   if (x1 < x2)                  /* did we get it? */
230     x3 += ll_B;                 /* yes, add it in the proper pos. */
231
232   rhi = x3 + ll_highpart (x1);
233   rlo = ll_lowpart (x1) * ll_B + ll_lowpart (x0);
234   return MAKEDI (rhi + (alo * bhi) + (ahi * blo), rlo);
235 }
236
237 DI
238 SHLDI (val, shift)
239      DI val;
240      SI shift;
241 {
242   USI hi = GETHIDI (val);
243   USI lo = GETLODI (val);
244   /* FIXME: Need to worry about shift < 0 || shift >= 32.  */
245   return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift);
246 }
247
248 DI
249 SLADI (val, shift)
250      DI val;
251      SI shift;
252 {
253   SI hi = GETHIDI (val);
254   USI lo = GETLODI (val);
255   /* FIXME: Need to worry about shift < 0 || shift >= 32.  */
256   return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift);
257 }
258
259 DI
260 SRADI (val, shift)
261      DI val;
262      SI shift;
263 {
264   SI hi = GETHIDI (val);
265   USI lo = GETLODI (val);
266   /* We use SRASI because the result is implementation defined if hi < 0.  */
267   /* FIXME: Need to worry about shift < 0 || shift >= 32.  */
268   return MAKEDI (SRASI (hi, shift), (hi << (32 - shift)) | (lo >> shift));
269 }
270
271 int
272 GEDI (a, b)
273      DI a, b;
274 {
275   SI ahi = GETHIDI (a);
276   USI alo = GETLODI (a);
277   SI bhi = GETHIDI (b);
278   USI blo = GETLODI (b);
279   if (ahi > bhi)
280     return 1;
281   if (ahi == bhi)
282     return alo >= blo;
283   return 0;
284 }
285
286 int
287 LEDI (a, b)
288      DI a, b;
289 {
290   SI ahi = GETHIDI (a);
291   USI alo = GETLODI (a);
292   SI bhi = GETHIDI (b);
293   USI blo = GETLODI (b);
294   if (ahi < bhi)
295     return 1;
296   if (ahi == bhi)
297     return alo <= blo;
298   return 0;
299 }
300
301 DI
302 CONVHIDI (val)
303      HI val;
304 {
305   if (val < 0)
306     return MAKEDI (-1, val);
307   else
308     return MAKEDI (0, val);
309 }
310
311 DI
312 CONVSIDI (val)
313      SI val;
314 {
315   if (val < 0)
316     return MAKEDI (-1, val);
317   else
318     return MAKEDI (0, val);
319 }
320
321 SI
322 CONVDISI (val)
323      DI val;
324 {
325   return GETLODI (val);
326 }
327
328 #endif /* DI_FN_SUPPORT */