Update devo version of m32r sim to build with recent sim/common changes.
[external/binutils.git] / sim / common / cgen-utils.c
1 /* Support code for various pieces of CGEN simulators.
2    Copyright (C) 1996, 1997 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 <signal.h>
23 #include "dis-asm.h"
24 #include "cpu-opc.h"
25 #include "decode.h"
26
27 #define MEMOPS_DEFINE_INLINE
28 #include "mem-ops.h"
29
30 #define SEMOPS_DEFINE_INLINE
31 #include "sem-ops.h"
32
33 const char *mode_names[] = {
34   "VM",
35   "BI",
36   "QI",
37   "HI",
38   "SI",
39   "DI",
40   "UBI",
41   "UQI",
42   "UHI",
43   "USI",
44   "UDI",
45   "SF",
46   "DF",
47   "XF",
48   "TF",
49 };
50
51 /* Initialize cgen things.
52    This is called after sim_post_argv_init.  */
53
54 void
55 cgen_init (SIM_DESC sd)
56 {
57   int i, c;
58   int run_fast_p = 1;
59
60   /* If no profiling or tracing has been enabled, run in fast mode.  */
61   for (c = 0; c < MAX_NR_PROCESSORS; ++c)
62     {
63       sim_cpu *cpu = STATE_CPU (sd, c);
64
65       for (i = 0; i < MAX_PROFILE_VALUES; ++i)
66         if (CPU_PROFILE_FLAGS (cpu) [i])
67           {
68             run_fast_p = 0;
69             break;
70           }
71       for (i = 0; i < MAX_TRACE_VALUES; ++i)
72         if (CPU_TRACE_FLAGS (cpu) [i])
73           {
74             run_fast_p = 0;
75             break;
76           }
77       if (! run_fast_p)
78         break;
79     }
80   STATE_RUN_FAST_P (sd) = run_fast_p;
81 }
82 \f
83 void
84 engine_halt (cpu, reason, sigrc)
85      sim_cpu *cpu;
86      enum exec_state reason;
87      int sigrc;
88 {
89   CPU_EXEC_STATE (cpu) = reason;
90   CPU_HALT_SIGRC (cpu) = sigrc;
91
92   longjmp (STATE_HALT_JMP_BUF (CPU_STATE (cpu)), 1);
93 }
94
95 void
96 engine_signal (cpu, sig)
97      sim_cpu *cpu;
98      enum sim_signal_type sig;
99 {
100   engine_halt (cpu, EXEC_STATE_STOPPED, sig);
101 }
102
103 /* Convert SIM_SIGFOO to SIGFOO.  */
104
105 int
106 sim_signal_to_host (sig)
107      int sig;
108 {
109   switch (sig)
110     {
111     case SIM_SIGILL :
112 #ifdef SIGILL
113       return SIGILL;
114 #endif
115       break;
116
117     case SIM_SIGTRAP :
118 #ifdef SIGTRAP
119       return SIGTRAP;
120 #else
121 #ifdef _MSC_VER
122       /* Wingdb uses this value.  */
123       return 5;
124 #endif
125 #endif
126       break;
127
128     case SIM_SIGALIGN :
129     case SIM_SIGACCESS :
130 #ifdef SIGSEGV
131       return SIGSEGV;
132 #endif
133       break;
134
135     case SIM_SIGXCPU :
136 #ifdef SIGXCPU
137       return SIGXCPU;
138 #endif
139       break;
140     }
141   return 1;
142 }
143 \f
144 /* FIXME: Add "no return" attribute to illegal insn handlers.
145    They all call longjmp.  */
146 /* FIXME: May wish to call a target supplied routine which can then call
147    sim_halt if it wants: to allow target to gain control for moment.  */
148
149 void
150 ex_illegal (SIM_CPU *cpu, PCADDR pc, insn_t insn, ARGBUF *abuf)
151 {
152   abuf->length = CGEN_BASE_INSN_SIZE;
153   abuf->addr = pc;
154   /* Leave signalling to semantic fn.  */
155 }
156
157 void
158 exc_illegal (SIM_CPU *cpu, PCADDR pc, insn_t insn, ARGBUF *abuf)
159 {
160   abuf->length = CGEN_BASE_INSN_SIZE;
161   abuf->addr = pc;
162   /* Leave signalling to semantic fn.  */
163 }
164
165 PCADDR
166 sem_illegal (current_cpu, sem_arg)
167      SIM_CPU *current_cpu;
168      struct argbuf *sem_arg;
169 {
170   engine_halt (current_cpu, EXEC_STATE_SIGNALLED, SIM_SIGILL);
171   return 0;
172 }
173
174 PCADDR
175 semc_illegal (current_cpu, sem_arg)
176      SIM_CPU *current_cpu;
177      struct scache *sem_arg;
178 {
179   engine_halt (current_cpu, EXEC_STATE_SIGNALLED, SIM_SIGILL);
180   return 0;
181 }
182 \f
183 /* Disassembly support.
184    ??? While executing an instruction, the insn has been decoded and all its
185    fields have been extracted.  It is certainly possible to do the disassembly
186    with that data.  This seems simpler, but maybe in the future the already
187    extracted fields will be used.  */
188
189 /* Pseudo FILE object for strings.  */
190 typedef struct {
191   char *buffer;
192   char *current;
193 } SFILE;
194
195 /* sprintf to a "stream" */
196
197 static int
198 disasm_sprintf VPARAMS ((SFILE *f, const char *format, ...))
199 {
200 #ifndef __STDC__
201   SFILE *f;
202   const char *format;
203 #endif
204   int n;
205   va_list args;
206
207   VA_START (args, format);
208 #ifndef __STDC__
209   f = va_arg (args, SFILE *);
210   format = va_arg (args, char *);
211 #endif
212   vsprintf (f->current, format, args);
213   f->current += n = strlen (f->current);
214   va_end (args);
215   return n;
216 }
217
218 void
219 sim_disassemble_insn (SIM_CPU *cpu, const struct cgen_insn *insn,
220                       const struct argbuf *abuf, PCADDR pc, char *buf)
221 {
222   int length;
223   unsigned long insn_value;
224   struct disassemble_info disasm_info;
225   struct cgen_fields fields;
226   SFILE sfile;
227   char insn_buf[20];
228   SIM_DESC sd = CPU_STATE (cpu);
229
230   sfile.buffer = sfile.current = buf;
231   INIT_DISASSEMBLE_INFO (disasm_info, (FILE *) &sfile,
232                          (fprintf_ftype) disasm_sprintf);
233   disasm_info.endian =
234     (bfd_big_endian (STATE_PROG_BFD (sd)) ? BFD_ENDIAN_BIG
235      : bfd_little_endian (STATE_PROG_BFD (sd)) ? BFD_ENDIAN_LITTLE
236      : BFD_ENDIAN_UNKNOWN);
237
238   switch (abuf->length)
239     {
240     case 1 :
241       insn_value = sim_core_read_1 (CPU_STATE (cpu), sim_core_read_map, pc, NULL, NULL_CIA);
242       break;
243     case 2 :
244       insn_value = sim_core_read_2 (CPU_STATE (cpu), sim_core_read_map, pc, NULL, NULL_CIA);
245       break;
246     case 4 :
247       insn_value = sim_core_read_4 (CPU_STATE (cpu), sim_core_read_map, pc, NULL, NULL_CIA);
248       break;
249     default:
250       abort ();
251     }
252
253   length = (*CGEN_EXTRACT_FN (insn)) (insn, NULL, insn_value, &fields);
254   if (length != abuf->length)
255     {
256       (*CGEN_PRINT_FN (insn)) (&disasm_info, insn, &fields, pc, length);
257     }
258   else
259     {
260       /* This shouldn't happen, but aborting is too drastic.  */
261       strcpy (buf, "***unknown***");
262     }
263 }
264 \f
265 #ifdef DI_FN_SUPPORT
266
267 DI
268 make_struct_di (hi, lo)
269      SI hi, lo;
270 {
271   DI result;
272
273   result.hi = hi;
274   result.lo = lo;
275   return result;
276 }
277
278 DI
279 ANDDI (a, b)
280      DI a, b;
281 {
282   SI ahi = GETHIDI (a);
283   SI alo = GETLODI (a);
284   SI bhi = GETHIDI (b);
285   SI blo = GETLODI (b);
286   return MAKEDI (ahi & bhi, alo & blo);
287 }
288
289 DI
290 ORDI (a, b)
291      DI a, b;
292 {
293   SI ahi = GETHIDI (a);
294   SI alo = GETLODI (a);
295   SI bhi = GETHIDI (b);
296   SI blo = GETLODI (b);
297   return MAKEDI (ahi | bhi, alo | blo);
298 }
299
300 DI
301 ADDDI (a, b)
302      DI a, b;
303 {
304   USI ahi = GETHIDI (a);
305   USI alo = GETLODI (a);
306   USI bhi = GETHIDI (b);
307   USI blo = GETLODI (b);
308   USI x = alo + blo;
309   return MAKEDI (ahi + bhi + (x < alo), x);
310 }
311
312 DI
313 MULDI (a, b)
314      DI a, b;
315 {
316   USI ahi = GETHIDI (a);
317   USI alo = GETLODI (a);
318   USI bhi = GETHIDI (b);
319   USI blo = GETLODI (b);
320   USI rhi,rlo;
321   USI x0, x1, x2, x3;
322
323   x0 = alo * blo;
324   x1 = alo * bhi;
325   x2 = ahi * blo;
326   x3 = ahi * bhi;
327
328 #define SI_TYPE_SIZE 32
329 #define BITS4 (SI_TYPE_SIZE / 4)
330 #define ll_B (1L << (SI_TYPE_SIZE / 2))
331 #define ll_lowpart(t) ((USI) (t) % ll_B)
332 #define ll_highpart(t) ((USI) (t) / ll_B)
333   x1 += ll_highpart (x0);       /* this can't give carry */
334   x1 += x2;                     /* but this indeed can */
335   if (x1 < x2)                  /* did we get it? */
336     x3 += ll_B;                 /* yes, add it in the proper pos. */
337
338   rhi = x3 + ll_highpart (x1);
339   rlo = ll_lowpart (x1) * ll_B + ll_lowpart (x0);
340   return MAKEDI (rhi + (alo * bhi) + (ahi * blo), rlo);
341 }
342
343 DI
344 SHLDI (val, shift)
345      DI val;
346      SI shift;
347 {
348   USI hi = GETHIDI (val);
349   USI lo = GETLODI (val);
350   /* FIXME: Need to worry about shift < 0 || shift >= 32.  */
351   return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift);
352 }
353
354 DI
355 SLADI (val, shift)
356      DI val;
357      SI shift;
358 {
359   SI hi = GETHIDI (val);
360   USI lo = GETLODI (val);
361   /* FIXME: Need to worry about shift < 0 || shift >= 32.  */
362   return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift);
363 }
364
365 DI
366 SRADI (val, shift)
367      DI val;
368      SI shift;
369 {
370   SI hi = GETHIDI (val);
371   USI lo = GETLODI (val);
372   /* We use SRASI because the result is implementation defined if hi < 0.  */
373   /* FIXME: Need to worry about shift < 0 || shift >= 32.  */
374   return MAKEDI (SRASI (hi, shift), (hi << (32 - shift)) | (lo >> shift));
375 }
376
377 int
378 GEDI (a, b)
379      DI a, b;
380 {
381   SI ahi = GETHIDI (a);
382   USI alo = GETLODI (a);
383   SI bhi = GETHIDI (b);
384   USI blo = GETLODI (b);
385   if (ahi > bhi)
386     return 1;
387   if (ahi == bhi)
388     return alo >= blo;
389   return 0;
390 }
391
392 int
393 LEDI (a, b)
394      DI a, b;
395 {
396   SI ahi = GETHIDI (a);
397   USI alo = GETLODI (a);
398   SI bhi = GETHIDI (b);
399   USI blo = GETLODI (b);
400   if (ahi < bhi)
401     return 1;
402   if (ahi == bhi)
403     return alo <= blo;
404   return 0;
405 }
406
407 DI
408 CONVHIDI (val)
409      HI val;
410 {
411   if (val < 0)
412     return MAKEDI (-1, val);
413   else
414     return MAKEDI (0, val);
415 }
416
417 DI
418 CONVSIDI (val)
419      SI val;
420 {
421   if (val < 0)
422     return MAKEDI (-1, val);
423   else
424     return MAKEDI (0, val);
425 }
426
427 SI
428 CONVDISI (val)
429      DI val;
430 {
431   return GETLODI (val);
432 }
433
434 #endif /* DI_FN_SUPPORT */