Thu Jul 2 13:57:36 1998 Klaus Kaempf <kkaempf@rmi.de>
[deliverable/binutils-gdb.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 */
This page took 0.043268 seconds and 4 git commands to generate.