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