]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/common/cgen-utils.c
e1138aff4d35d44c6f91076c7d232296f9a83505
[thirdparty/binutils-gdb.git] / sim / common / cgen-utils.c
1 /* Support code for various pieces of CGEN simulators.
2 Copyright (C) 1996-2015 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 \f
153 #ifdef DI_FN_SUPPORT
154
155 DI
156 make_struct_di (hi, lo)
157 SI hi, lo;
158 {
159 DI result;
160
161 result.hi = hi;
162 result.lo = lo;
163 return result;
164 }
165
166 DI
167 ANDDI (a, b)
168 DI a, b;
169 {
170 SI ahi = GETHIDI (a);
171 SI alo = GETLODI (a);
172 SI bhi = GETHIDI (b);
173 SI blo = GETLODI (b);
174 return MAKEDI (ahi & bhi, alo & blo);
175 }
176
177 DI
178 ORDI (a, b)
179 DI a, b;
180 {
181 SI ahi = GETHIDI (a);
182 SI alo = GETLODI (a);
183 SI bhi = GETHIDI (b);
184 SI blo = GETLODI (b);
185 return MAKEDI (ahi | bhi, alo | blo);
186 }
187
188 DI
189 ADDDI (a, b)
190 DI a, b;
191 {
192 USI ahi = GETHIDI (a);
193 USI alo = GETLODI (a);
194 USI bhi = GETHIDI (b);
195 USI blo = GETLODI (b);
196 USI x = alo + blo;
197 return MAKEDI (ahi + bhi + (x < alo), x);
198 }
199
200 DI
201 MULDI (a, b)
202 DI a, b;
203 {
204 USI ahi = GETHIDI (a);
205 USI alo = GETLODI (a);
206 USI bhi = GETHIDI (b);
207 USI blo = GETLODI (b);
208 USI rhi,rlo;
209 USI x0, x1, x2, x3;
210
211 x0 = alo * blo;
212 x1 = alo * bhi;
213 x2 = ahi * blo;
214 x3 = ahi * bhi;
215
216 #define SI_TYPE_SIZE 32
217 #define BITS4 (SI_TYPE_SIZE / 4)
218 #define ll_B (1L << (SI_TYPE_SIZE / 2))
219 #define ll_lowpart(t) ((USI) (t) % ll_B)
220 #define ll_highpart(t) ((USI) (t) / ll_B)
221 x1 += ll_highpart (x0); /* this can't give carry */
222 x1 += x2; /* but this indeed can */
223 if (x1 < x2) /* did we get it? */
224 x3 += ll_B; /* yes, add it in the proper pos. */
225
226 rhi = x3 + ll_highpart (x1);
227 rlo = ll_lowpart (x1) * ll_B + ll_lowpart (x0);
228 return MAKEDI (rhi + (alo * bhi) + (ahi * blo), rlo);
229 }
230
231 DI
232 SHLDI (val, shift)
233 DI val;
234 SI shift;
235 {
236 USI hi = GETHIDI (val);
237 USI lo = GETLODI (val);
238 /* FIXME: Need to worry about shift < 0 || shift >= 32. */
239 return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift);
240 }
241
242 DI
243 SLADI (val, shift)
244 DI val;
245 SI shift;
246 {
247 SI hi = GETHIDI (val);
248 USI lo = GETLODI (val);
249 /* FIXME: Need to worry about shift < 0 || shift >= 32. */
250 return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift);
251 }
252
253 DI
254 SRADI (val, shift)
255 DI val;
256 SI shift;
257 {
258 SI hi = GETHIDI (val);
259 USI lo = GETLODI (val);
260 /* We use SRASI because the result is implementation defined if hi < 0. */
261 /* FIXME: Need to worry about shift < 0 || shift >= 32. */
262 return MAKEDI (SRASI (hi, shift), (hi << (32 - shift)) | (lo >> shift));
263 }
264
265 int
266 GEDI (a, b)
267 DI a, b;
268 {
269 SI ahi = GETHIDI (a);
270 USI alo = GETLODI (a);
271 SI bhi = GETHIDI (b);
272 USI blo = GETLODI (b);
273 if (ahi > bhi)
274 return 1;
275 if (ahi == bhi)
276 return alo >= blo;
277 return 0;
278 }
279
280 int
281 LEDI (a, b)
282 DI a, b;
283 {
284 SI ahi = GETHIDI (a);
285 USI alo = GETLODI (a);
286 SI bhi = GETHIDI (b);
287 USI blo = GETLODI (b);
288 if (ahi < bhi)
289 return 1;
290 if (ahi == bhi)
291 return alo <= blo;
292 return 0;
293 }
294
295 DI
296 CONVHIDI (val)
297 HI val;
298 {
299 if (val < 0)
300 return MAKEDI (-1, val);
301 else
302 return MAKEDI (0, val);
303 }
304
305 DI
306 CONVSIDI (val)
307 SI val;
308 {
309 if (val < 0)
310 return MAKEDI (-1, val);
311 else
312 return MAKEDI (0, val);
313 }
314
315 SI
316 CONVDISI (val)
317 DI val;
318 {
319 return GETLODI (val);
320 }
321
322 #endif /* DI_FN_SUPPORT */
323 \f
324 QI
325 RORQI (val, shift)
326 QI val;
327 int shift;
328 {
329 if (shift != 0)
330 {
331 int remain = 8 - shift;
332 int mask = (1 << shift) - 1;
333 QI result = (val & mask) << remain;
334 mask = (1 << remain) - 1;
335 result |= (val >> shift) & mask;
336 return result;
337 }
338 return val;
339 }
340
341 QI
342 ROLQI (val, shift)
343 QI val;
344 int shift;
345 {
346 if (shift != 0)
347 {
348 int remain = 8 - shift;
349 int mask = (1 << remain) - 1;
350 QI result = (val & mask) << shift;
351 mask = (1 << shift) - 1;
352 result |= (val >> remain) & mask;
353 return result;
354 }
355 return val;
356 }
357
358 HI
359 RORHI (val, shift)
360 HI val;
361 int shift;
362 {
363 if (shift != 0)
364 {
365 int remain = 16 - shift;
366 int mask = (1 << shift) - 1;
367 HI result = (val & mask) << remain;
368 mask = (1 << remain) - 1;
369 result |= (val >> shift) & mask;
370 return result;
371 }
372 return val;
373 }
374
375 HI
376 ROLHI (val, shift)
377 HI val;
378 int shift;
379 {
380 if (shift != 0)
381 {
382 int remain = 16 - shift;
383 int mask = (1 << remain) - 1;
384 HI result = (val & mask) << shift;
385 mask = (1 << shift) - 1;
386 result |= (val >> remain) & mask;
387 return result;
388 }
389 return val;
390 }
391
392 SI
393 RORSI (val, shift)
394 SI val;
395 int shift;
396 {
397 if (shift != 0)
398 {
399 int remain = 32 - shift;
400 int mask = (1 << shift) - 1;
401 SI result = (val & mask) << remain;
402 mask = (1 << remain) - 1;
403 result |= (val >> shift) & mask;
404 return result;
405 }
406 return val;
407 }
408
409 SI
410 ROLSI (val, shift)
411 SI val;
412 int shift;
413 {
414 if (shift != 0)
415 {
416 int remain = 32 - shift;
417 int mask = (1 << remain) - 1;
418 SI result = (val & mask) << shift;
419 mask = (1 << shift) - 1;
420 result |= (val >> remain) & mask;
421 return result;
422 }
423
424 return val;
425 }
426
427 /* Emit an error message from CGEN RTL. */
428
429 void
430 cgen_rtx_error (SIM_CPU *cpu, const char * msg)
431 {
432 SIM_DESC sd = CPU_STATE (cpu);
433
434 sim_io_printf (sd, msg);
435 sim_io_printf (sd, "\n");
436
437 sim_engine_halt (sd, cpu, NULL, CIA_GET (cpu), sim_stopped, SIM_SIGTRAP);
438 }