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