Commit | Line | Data |
---|---|---|
c906108c | 1 | /* Support code for various pieces of CGEN simulators. |
ecd75fc8 | 2 | Copyright (C) 1996-2014 Free Software Foundation, Inc. |
c906108c SS |
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 | |
4744ac1b JB |
9 | the Free Software Foundation; either version 3 of the License, or |
10 | (at your option) any later version. | |
c906108c SS |
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 | ||
4744ac1b JB |
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/>. */ | |
c906108c | 19 | |
a6ff997c | 20 | #include "config.h" |
c906108c SS |
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[] = { | |
104c1213 | 35 | "VOID", |
c906108c SS |
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 | { | |
7a292a7a | 62 | VIRTUAL_INSN_X_INVALID, "--invalid--", NULL, 0, { V, { 0 } } |
c906108c SS |
63 | }, |
64 | { | |
7a292a7a | 65 | VIRTUAL_INSN_X_BEFORE, "--before--", NULL, 0, { V, { 0 } } |
c906108c SS |
66 | }, |
67 | { | |
7a292a7a | 68 | VIRTUAL_INSN_X_AFTER, "--after--", NULL, 0, { V, { 0 } } |
c906108c SS |
69 | }, |
70 | { | |
7a292a7a | 71 | VIRTUAL_INSN_X_BEGIN, "--begin--", NULL, 0, { V, { 0 } } |
c906108c SS |
72 | }, |
73 | { | |
7a292a7a | 74 | VIRTUAL_INSN_X_CHAIN, "--chain--", NULL, 0, { V, { 0 } } |
c906108c SS |
75 | }, |
76 | { | |
7a292a7a | 77 | VIRTUAL_INSN_X_CTI_CHAIN, "--cti-chain--", NULL, 0, { V, { 0 } } |
c906108c SS |
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 */ | |
adf40b2e | 323 | \f |
6d4c43bf DB |
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 | ||
adf40b2e JM |
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 | } | |
a8d894af BE |
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 | } |