Update devo version of m32r sim to build with recent sim/common changes.
[deliverable/binutils-gdb.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 */
This page took 0.038732 seconds and 5 git commands to generate.