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