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 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 "sim-main.h"
22 #include "dis-asm.h"
23 #include "cpu-opc.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 const char *mode_names[] = {
32   "VM",
33   "BI",
34   "QI",
35   "HI",
36   "SI",
37   "DI",
38   "UBI",
39   "UQI",
40   "UHI",
41   "USI",
42   "UDI",
43   "SF",
44   "DF",
45   "XF",
46   "TF",
47 };
48
49 /* Initialize cgen things.
50    This is called after sim_post_argv_init.  */
51
52 void
53 cgen_init (SIM_DESC sd)
54 {
55   int i, c;
56   int run_fast_p = 1;
57
58   /* If no profiling or tracing has been enabled, run in fast mode.  */
59   for (c = 0; c < MAX_NR_PROCESSORS; ++c)
60     {
61       sim_cpu *cpu = STATE_CPU (sd, c);
62
63       for (i = 0; i < MAX_PROFILE_VALUES; ++i)
64         if (CPU_PROFILE_FLAGS (cpu) [i])
65           {
66             run_fast_p = 0;
67             break;
68           }
69       for (i = 0; i < MAX_TRACE_VALUES; ++i)
70         if (CPU_TRACE_FLAGS (cpu) [i])
71           {
72             run_fast_p = 0;
73             break;
74           }
75       if (! run_fast_p)
76         break;
77     }
78   STATE_RUN_FAST_P (sd) = run_fast_p;
79 }
80 \f
81 /* Disassembly support.
82    ??? While executing an instruction, the insn has been decoded and all its
83    fields have been extracted.  It is certainly possible to do the disassembly
84    with that data.  This seems simpler, but maybe in the future the already
85    extracted fields will be used.  */
86
87 /* Pseudo FILE object for strings.  */
88 typedef struct {
89   char *buffer;
90   char *current;
91 } SFILE;
92
93 /* sprintf to a "stream" */
94
95 static int
96 disasm_sprintf VPARAMS ((SFILE *f, const char *format, ...))
97 {
98 #ifndef __STDC__
99   SFILE *f;
100   const char *format;
101 #endif
102   int n;
103   va_list args;
104
105   VA_START (args, format);
106 #ifndef __STDC__
107   f = va_arg (args, SFILE *);
108   format = va_arg (args, char *);
109 #endif
110   vsprintf (f->current, format, args);
111   f->current += n = strlen (f->current);
112   va_end (args);
113   return n;
114 }
115
116 void
117 sim_disassemble_insn (SIM_CPU *cpu, const struct cgen_insn *insn,
118                       const struct argbuf *abuf, PCADDR pc, char *buf)
119 {
120   unsigned int length;
121   unsigned long insn_value;
122   struct disassemble_info disasm_info;
123   struct cgen_fields fields;
124   SFILE sfile;
125   union {
126     unsigned8 bytes[16];
127     unsigned16 shorts[8];
128     unsigned32 words[4];
129   } insn_buf;
130   SIM_DESC sd = CPU_STATE (cpu);
131
132   sfile.buffer = sfile.current = buf;
133   INIT_DISASSEMBLE_INFO (disasm_info, (FILE *) &sfile,
134                          (fprintf_ftype) disasm_sprintf);
135   disasm_info.endian =
136     (bfd_big_endian (STATE_PROG_BFD (sd)) ? BFD_ENDIAN_BIG
137      : bfd_little_endian (STATE_PROG_BFD (sd)) ? BFD_ENDIAN_LITTLE
138      : BFD_ENDIAN_UNKNOWN);
139
140   length = sim_core_read_buffer (sd, cpu, sim_core_read_map, &insn_buf, pc,
141                                  CGEN_INSN_BITSIZE (insn) / 8);
142
143   switch (length)
144     {
145     case 1 : insn_value = insn_buf.bytes[0]; break;
146     case 2 : insn_value = T2H_2 (insn_buf.shorts[0]); break;
147     case 4 : insn_value = T2H_4 (insn_buf.words[0]); break;
148     default: abort ();
149     }
150
151   length = (*CGEN_EXTRACT_FN (insn)) (insn, NULL, insn_value, &fields);
152   /* Result of extract fn is in bits.  */
153   /* ??? This assumes that each instruction has a fixed length (and thus
154      for insns with multiple versions of variable lengths they would each
155      have their own table entry).  */
156   if (length == CGEN_INSN_BITSIZE (insn))
157     {
158       (*CGEN_PRINT_FN (insn)) (&disasm_info, insn, &fields, pc, length);
159     }
160   else
161     {
162       /* This shouldn't happen, but aborting is too drastic.  */
163       strcpy (buf, "***unknown***");
164     }
165 }
166 \f
167 #ifdef DI_FN_SUPPORT
168
169 DI
170 make_struct_di (hi, lo)
171      SI hi, lo;
172 {
173   DI result;
174
175   result.hi = hi;
176   result.lo = lo;
177   return result;
178 }
179
180 DI
181 ANDDI (a, b)
182      DI a, b;
183 {
184   SI ahi = GETHIDI (a);
185   SI alo = GETLODI (a);
186   SI bhi = GETHIDI (b);
187   SI blo = GETLODI (b);
188   return MAKEDI (ahi & bhi, alo & blo);
189 }
190
191 DI
192 ORDI (a, b)
193      DI a, b;
194 {
195   SI ahi = GETHIDI (a);
196   SI alo = GETLODI (a);
197   SI bhi = GETHIDI (b);
198   SI blo = GETLODI (b);
199   return MAKEDI (ahi | bhi, alo | blo);
200 }
201
202 DI
203 ADDDI (a, b)
204      DI a, b;
205 {
206   USI ahi = GETHIDI (a);
207   USI alo = GETLODI (a);
208   USI bhi = GETHIDI (b);
209   USI blo = GETLODI (b);
210   USI x = alo + blo;
211   return MAKEDI (ahi + bhi + (x < alo), x);
212 }
213
214 DI
215 MULDI (a, b)
216      DI a, b;
217 {
218   USI ahi = GETHIDI (a);
219   USI alo = GETLODI (a);
220   USI bhi = GETHIDI (b);
221   USI blo = GETLODI (b);
222   USI rhi,rlo;
223   USI x0, x1, x2, x3;
224
225   x0 = alo * blo;
226   x1 = alo * bhi;
227   x2 = ahi * blo;
228   x3 = ahi * bhi;
229
230 #define SI_TYPE_SIZE 32
231 #define BITS4 (SI_TYPE_SIZE / 4)
232 #define ll_B (1L << (SI_TYPE_SIZE / 2))
233 #define ll_lowpart(t) ((USI) (t) % ll_B)
234 #define ll_highpart(t) ((USI) (t) / ll_B)
235   x1 += ll_highpart (x0);       /* this can't give carry */
236   x1 += x2;                     /* but this indeed can */
237   if (x1 < x2)                  /* did we get it? */
238     x3 += ll_B;                 /* yes, add it in the proper pos. */
239
240   rhi = x3 + ll_highpart (x1);
241   rlo = ll_lowpart (x1) * ll_B + ll_lowpart (x0);
242   return MAKEDI (rhi + (alo * bhi) + (ahi * blo), rlo);
243 }
244
245 DI
246 SHLDI (val, shift)
247      DI val;
248      SI shift;
249 {
250   USI hi = GETHIDI (val);
251   USI lo = GETLODI (val);
252   /* FIXME: Need to worry about shift < 0 || shift >= 32.  */
253   return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift);
254 }
255
256 DI
257 SLADI (val, shift)
258      DI val;
259      SI shift;
260 {
261   SI hi = GETHIDI (val);
262   USI lo = GETLODI (val);
263   /* FIXME: Need to worry about shift < 0 || shift >= 32.  */
264   return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift);
265 }
266
267 DI
268 SRADI (val, shift)
269      DI val;
270      SI shift;
271 {
272   SI hi = GETHIDI (val);
273   USI lo = GETLODI (val);
274   /* We use SRASI because the result is implementation defined if hi < 0.  */
275   /* FIXME: Need to worry about shift < 0 || shift >= 32.  */
276   return MAKEDI (SRASI (hi, shift), (hi << (32 - shift)) | (lo >> shift));
277 }
278
279 int
280 GEDI (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 int
295 LEDI (a, b)
296      DI a, b;
297 {
298   SI ahi = GETHIDI (a);
299   USI alo = GETLODI (a);
300   SI bhi = GETHIDI (b);
301   USI blo = GETLODI (b);
302   if (ahi < bhi)
303     return 1;
304   if (ahi == bhi)
305     return alo <= blo;
306   return 0;
307 }
308
309 DI
310 CONVHIDI (val)
311      HI val;
312 {
313   if (val < 0)
314     return MAKEDI (-1, val);
315   else
316     return MAKEDI (0, val);
317 }
318
319 DI
320 CONVSIDI (val)
321      SI val;
322 {
323   if (val < 0)
324     return MAKEDI (-1, val);
325   else
326     return MAKEDI (0, val);
327 }
328
329 SI
330 CONVDISI (val)
331      DI val;
332 {
333   return GETLODI (val);
334 }
335
336 #endif /* DI_FN_SUPPORT */