cgen-utils.c revision 1.1 1 /* Support code for various pieces of CGEN simulators.
2 Copyright (C) 1996-2014 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 3 of the License, or
10 (at your option) 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
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "config.h"
21 #include "bfd.h"
22 #include "sim-main.h"
23 #include "dis-asm.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 #undef min
32 #define min(a,b) ((a) < (b) ? (a) : (b))
33
34 const char *mode_names[] = {
35 "VOID",
36 "BI",
37 "QI",
38 "HI",
39 "SI",
40 "DI",
41 "UQI",
42 "UHI",
43 "USI",
44 "UDI",
45 "SF",
46 "DF",
47 "XF",
48 "TF",
49 0, /* MODE_TARGET_MAX */
50 "INT",
51 "UINT",
52 "PTR"
53 };
54
55 /* Opcode table for virtual insns used by the simulator. */
56
57 #define V CGEN_ATTR_MASK (CGEN_INSN_VIRTUAL)
58
59 static const CGEN_IBASE virtual_insn_entries[] =
60 {
61 {
62 VIRTUAL_INSN_X_INVALID, "--invalid--", NULL, 0, { V, { 0 } }
63 },
64 {
65 VIRTUAL_INSN_X_BEFORE, "--before--", NULL, 0, { V, { 0 } }
66 },
67 {
68 VIRTUAL_INSN_X_AFTER, "--after--", NULL, 0, { V, { 0 } }
69 },
70 {
71 VIRTUAL_INSN_X_BEGIN, "--begin--", NULL, 0, { V, { 0 } }
72 },
73 {
74 VIRTUAL_INSN_X_CHAIN, "--chain--", NULL, 0, { V, { 0 } }
75 },
76 {
77 VIRTUAL_INSN_X_CTI_CHAIN, "--cti-chain--", NULL, 0, { V, { 0 } }
78 }
79 };
80
81 #undef V
82
83 const CGEN_INSN cgen_virtual_insn_table[] =
84 {
85 { & virtual_insn_entries[0] },
86 { & virtual_insn_entries[1] },
87 { & virtual_insn_entries[2] },
88 { & virtual_insn_entries[3] },
89 { & virtual_insn_entries[4] },
90 { & virtual_insn_entries[5] }
91 };
92
93 /* Initialize cgen things.
94 This is called after sim_post_argv_init. */
95
96 void
97 cgen_init (SIM_DESC sd)
98 {
99 int i, c;
100
101 /* If no profiling or tracing has been enabled, run in fast mode. */
102 {
103 int run_fast_p = 1;
104
105 for (c = 0; c < MAX_NR_PROCESSORS; ++c)
106 {
107 SIM_CPU *cpu = STATE_CPU (sd, c);
108
109 for (i = 0; i < MAX_PROFILE_VALUES; ++i)
110 if (CPU_PROFILE_FLAGS (cpu) [i])
111 {
112 run_fast_p = 0;
113 break;
114 }
115 for (i = 0; i < MAX_TRACE_VALUES; ++i)
116 if (CPU_TRACE_FLAGS (cpu) [i])
117 {
118 run_fast_p = 0;
119 break;
120 }
121 if (! run_fast_p)
122 break;
123 }
124 STATE_RUN_FAST_P (sd) = run_fast_p;
125 }
126 }
127
128 /* Return the name of insn number I. */
129
130 const char *
131 cgen_insn_name (SIM_CPU *cpu, int i)
132 {
133 return CGEN_INSN_NAME ((* CPU_GET_IDATA (cpu)) ((cpu), (i)));
134 }
135
136 /* Return the maximum number of extra bytes required for a SIM_CPU struct. */
137
138 int
139 cgen_cpu_max_extra_bytes (void)
140 {
141 int i;
142 int extra = 0;
143
144 for (i = 0; sim_machs[i] != 0; ++i)
145 {
146 int size = IMP_PROPS_SIM_CPU_SIZE (MACH_IMP_PROPS (sim_machs[i]));
147 if (size > extra)
148 extra = size;
149 }
150 return extra;
151 }
152
153 #ifdef DI_FN_SUPPORT
155
156 DI
157 make_struct_di (hi, lo)
158 SI hi, lo;
159 {
160 DI result;
161
162 result.hi = hi;
163 result.lo = lo;
164 return result;
165 }
166
167 DI
168 ANDDI (a, b)
169 DI a, b;
170 {
171 SI ahi = GETHIDI (a);
172 SI alo = GETLODI (a);
173 SI bhi = GETHIDI (b);
174 SI blo = GETLODI (b);
175 return MAKEDI (ahi & bhi, alo & blo);
176 }
177
178 DI
179 ORDI (a, b)
180 DI a, b;
181 {
182 SI ahi = GETHIDI (a);
183 SI alo = GETLODI (a);
184 SI bhi = GETHIDI (b);
185 SI blo = GETLODI (b);
186 return MAKEDI (ahi | bhi, alo | blo);
187 }
188
189 DI
190 ADDDI (a, b)
191 DI a, b;
192 {
193 USI ahi = GETHIDI (a);
194 USI alo = GETLODI (a);
195 USI bhi = GETHIDI (b);
196 USI blo = GETLODI (b);
197 USI x = alo + blo;
198 return MAKEDI (ahi + bhi + (x < alo), x);
199 }
200
201 DI
202 MULDI (a, b)
203 DI a, b;
204 {
205 USI ahi = GETHIDI (a);
206 USI alo = GETLODI (a);
207 USI bhi = GETHIDI (b);
208 USI blo = GETLODI (b);
209 USI rhi,rlo;
210 USI x0, x1, x2, x3;
211
212 x0 = alo * blo;
213 x1 = alo * bhi;
214 x2 = ahi * blo;
215 x3 = ahi * bhi;
216
217 #define SI_TYPE_SIZE 32
218 #define BITS4 (SI_TYPE_SIZE / 4)
219 #define ll_B (1L << (SI_TYPE_SIZE / 2))
220 #define ll_lowpart(t) ((USI) (t) % ll_B)
221 #define ll_highpart(t) ((USI) (t) / ll_B)
222 x1 += ll_highpart (x0); /* this can't give carry */
223 x1 += x2; /* but this indeed can */
224 if (x1 < x2) /* did we get it? */
225 x3 += ll_B; /* yes, add it in the proper pos. */
226
227 rhi = x3 + ll_highpart (x1);
228 rlo = ll_lowpart (x1) * ll_B + ll_lowpart (x0);
229 return MAKEDI (rhi + (alo * bhi) + (ahi * blo), rlo);
230 }
231
232 DI
233 SHLDI (val, shift)
234 DI val;
235 SI shift;
236 {
237 USI hi = GETHIDI (val);
238 USI lo = GETLODI (val);
239 /* FIXME: Need to worry about shift < 0 || shift >= 32. */
240 return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift);
241 }
242
243 DI
244 SLADI (val, shift)
245 DI val;
246 SI shift;
247 {
248 SI hi = GETHIDI (val);
249 USI lo = GETLODI (val);
250 /* FIXME: Need to worry about shift < 0 || shift >= 32. */
251 return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift);
252 }
253
254 DI
255 SRADI (val, shift)
256 DI val;
257 SI shift;
258 {
259 SI hi = GETHIDI (val);
260 USI lo = GETLODI (val);
261 /* We use SRASI because the result is implementation defined if hi < 0. */
262 /* FIXME: Need to worry about shift < 0 || shift >= 32. */
263 return MAKEDI (SRASI (hi, shift), (hi << (32 - shift)) | (lo >> shift));
264 }
265
266 int
267 GEDI (a, b)
268 DI a, b;
269 {
270 SI ahi = GETHIDI (a);
271 USI alo = GETLODI (a);
272 SI bhi = GETHIDI (b);
273 USI blo = GETLODI (b);
274 if (ahi > bhi)
275 return 1;
276 if (ahi == bhi)
277 return alo >= blo;
278 return 0;
279 }
280
281 int
282 LEDI (a, b)
283 DI a, b;
284 {
285 SI ahi = GETHIDI (a);
286 USI alo = GETLODI (a);
287 SI bhi = GETHIDI (b);
288 USI blo = GETLODI (b);
289 if (ahi < bhi)
290 return 1;
291 if (ahi == bhi)
292 return alo <= blo;
293 return 0;
294 }
295
296 DI
297 CONVHIDI (val)
298 HI val;
299 {
300 if (val < 0)
301 return MAKEDI (-1, val);
302 else
303 return MAKEDI (0, val);
304 }
305
306 DI
307 CONVSIDI (val)
308 SI val;
309 {
310 if (val < 0)
311 return MAKEDI (-1, val);
312 else
313 return MAKEDI (0, val);
314 }
315
316 SI
317 CONVDISI (val)
318 DI val;
319 {
320 return GETLODI (val);
321 }
322
323 #endif /* DI_FN_SUPPORT */
324
325 QI
327 RORQI (val, shift)
328 QI val;
329 int shift;
330 {
331 if (shift != 0)
332 {
333 int remain = 8 - shift;
334 int mask = (1 << shift) - 1;
335 QI result = (val & mask) << remain;
336 mask = (1 << remain) - 1;
337 result |= (val >> shift) & mask;
338 return result;
339 }
340 return val;
341 }
342
343 QI
344 ROLQI (val, shift)
345 QI val;
346 int shift;
347 {
348 if (shift != 0)
349 {
350 int remain = 8 - shift;
351 int mask = (1 << remain) - 1;
352 QI result = (val & mask) << shift;
353 mask = (1 << shift) - 1;
354 result |= (val >> remain) & mask;
355 return result;
356 }
357 return val;
358 }
359
360 HI
361 RORHI (val, shift)
362 HI val;
363 int shift;
364 {
365 if (shift != 0)
366 {
367 int remain = 16 - shift;
368 int mask = (1 << shift) - 1;
369 HI result = (val & mask) << remain;
370 mask = (1 << remain) - 1;
371 result |= (val >> shift) & mask;
372 return result;
373 }
374 return val;
375 }
376
377 HI
378 ROLHI (val, shift)
379 HI val;
380 int shift;
381 {
382 if (shift != 0)
383 {
384 int remain = 16 - shift;
385 int mask = (1 << remain) - 1;
386 HI result = (val & mask) << shift;
387 mask = (1 << shift) - 1;
388 result |= (val >> remain) & mask;
389 return result;
390 }
391 return val;
392 }
393
394 SI
395 RORSI (val, shift)
396 SI val;
397 int shift;
398 {
399 if (shift != 0)
400 {
401 int remain = 32 - shift;
402 int mask = (1 << shift) - 1;
403 SI result = (val & mask) << remain;
404 mask = (1 << remain) - 1;
405 result |= (val >> shift) & mask;
406 return result;
407 }
408 return val;
409 }
410
411 SI
412 ROLSI (val, shift)
413 SI val;
414 int shift;
415 {
416 if (shift != 0)
417 {
418 int remain = 32 - shift;
419 int mask = (1 << remain) - 1;
420 SI result = (val & mask) << shift;
421 mask = (1 << shift) - 1;
422 result |= (val >> remain) & mask;
423 return result;
424 }
425
426 return val;
427 }
428
429 /* Emit an error message from CGEN RTL. */
430
431 void
432 cgen_rtx_error (SIM_CPU *cpu, const char * msg)
433 {
434 SIM_DESC sd = CPU_STATE (cpu);
435
436 sim_io_printf (sd, msg);
437 sim_io_printf (sd, "\n");
438
439 sim_engine_halt (sd, cpu, NULL, CIA_GET (cpu), sim_stopped, SIM_SIGTRAP);
440 }
441