]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/rx/reg.c
6effe4b621f9a7c413fcc8383d9cd67262ee5bae
[thirdparty/binutils-gdb.git] / sim / rx / reg.c
1 /* reg.c --- register set model for RX simulator.
2
3 Copyright (C) 2005-2015 Free Software Foundation, Inc.
4 Contributed by Red Hat, Inc.
5
6 This file is part of the GNU simulators.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21
22 #include "config.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "cpu.h"
28 #include "bfd.h"
29 #include "trace.h"
30
31 int verbose = 0;
32 int trace = 0;
33 int enable_counting = 0;
34
35 int rx_in_gdb = 1;
36
37 int rx_flagmask;
38 int rx_flagand;
39 int rx_flagor;
40
41 int rx_big_endian;
42 regs_type regs;
43 int step_result;
44 unsigned int heapbottom = 0;
45 unsigned int heaptop = 0;
46
47 char *reg_names[] = {
48 /* general registers */
49 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
50 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
51 /* control register */
52 "psw", "pc", "usp", "fpsw", "RES", "RES", "RES", "RES",
53 "bpsw", "bpc", "isp", "fintv", "intb", "RES", "RES", "RES",
54 "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES",
55 "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES",
56 "temp", "acc", "acchi", "accmi", "acclo"
57 };
58
59 unsigned int b2mask[] = { 0, 0xff, 0xffff, 0xffffff, 0xffffffff };
60 unsigned int b2signbit[] = { 0, (1 << 7), (1 << 15), (1 << 24), (1 << 31) };
61 int b2maxsigned[] = { 0, 0x7f, 0x7fff, 0x7fffff, 0x7fffffff };
62 int b2minsigned[] = { 0, -128, -32768, -8388608, -2147483647 - 1 };
63
64 static regs_type oldregs;
65
66 void
67 init_regs (void)
68 {
69 memset (&regs, 0, sizeof (regs));
70 memset (&oldregs, 0, sizeof (oldregs));
71
72 #ifdef CYCLE_ACCURATE
73 regs.rt = -1;
74 oldregs.rt = -1;
75 #endif
76 }
77
78 static unsigned int
79 get_reg_i (int id)
80 {
81 if (id == 0)
82 return regs.r_psw & FLAGBIT_U ? regs.r_usp : regs.r_isp;
83
84 if (id >= 1 && id <= 15)
85 return regs.r[id];
86
87 switch (id)
88 {
89 case psw:
90 return regs.r_psw;
91 case fpsw:
92 return regs.r_fpsw;
93 case isp:
94 return regs.r_isp;
95 case usp:
96 return regs.r_usp;
97 case bpc:
98 return regs.r_bpc;
99 case bpsw:
100 return regs.r_bpsw;
101 case fintv:
102 return regs.r_fintv;
103 case intb:
104 return regs.r_intb;
105 case pc:
106 return regs.r_pc;
107 case r_temp_idx:
108 return regs.r_temp;
109 case acchi:
110 return (SI)(regs.r_acc >> 32);
111 case accmi:
112 return (SI)(regs.r_acc >> 16);
113 case acclo:
114 return (SI)regs.r_acc;
115 }
116 abort();
117 }
118
119 unsigned int
120 get_reg (int id)
121 {
122 unsigned int rv = get_reg_i (id);
123 if (trace > ((id != pc && id != sp) ? 0 : 1))
124 printf ("get_reg (%s) = %08x\n", reg_names[id], rv);
125 return rv;
126 }
127
128 static unsigned long long
129 get_reg64_i (int id)
130 {
131 switch (id)
132 {
133 case acc64:
134 return regs.r_acc;
135 default:
136 abort ();
137 }
138 }
139
140 unsigned long long
141 get_reg64 (int id)
142 {
143 unsigned long long rv = get_reg64_i (id);
144 if (trace > ((id != pc && id != sp) ? 0 : 1))
145 printf ("get_reg (%s) = %016llx\n", reg_names[id], rv);
146 return rv;
147 }
148
149 static int highest_sp = 0, lowest_sp = 0xffffff;
150
151 void
152 stack_heap_stats ()
153 {
154 if (heapbottom < heaptop)
155 printf ("heap: %08x - %08x (%d bytes)\n", heapbottom, heaptop,
156 heaptop - heapbottom);
157 if (lowest_sp < highest_sp)
158 printf ("stack: %08x - %08x (%d bytes)\n", lowest_sp, highest_sp,
159 highest_sp - lowest_sp);
160 }
161
162 void
163 put_reg (int id, unsigned int v)
164 {
165 if (trace > ((id != pc) ? 0 : 1))
166 printf ("put_reg (%s) = %08x\n", reg_names[id], v);
167
168
169 switch (id)
170 {
171 case psw:
172 regs.r_psw = v;
173 break;
174 case fpsw:
175 {
176 SI anded;
177 /* This is an odd one - The Cx flags are AND'd, and the FS flag
178 is synthetic. */
179 anded = regs.r_fpsw & v;
180 anded |= ~ FPSWBITS_CMASK;
181 regs.r_fpsw = v & anded;
182 if (regs.r_fpsw & FPSWBITS_FMASK)
183 regs.r_fpsw |= FPSWBITS_FSUM;
184 else
185 regs.r_fpsw &= ~FPSWBITS_FSUM;
186 }
187 break;
188 case isp:
189 regs.r_isp = v;
190 break;
191 case usp:
192 regs.r_usp = v;
193 break;
194 case bpc:
195 regs.r_bpc = v;
196 break;
197 case bpsw:
198 regs.r_bpsw = v;
199 break;
200 case fintv:
201 regs.r_fintv = v;
202 break;
203 case intb:
204 regs.r_intb = v;
205 break;
206 case pc:
207 regs.r_pc = v;
208 break;
209
210 case acchi:
211 regs.r_acc = (regs.r_acc & 0xffffffffULL) | ((DI)v << 32);
212 break;
213 case accmi:
214 regs.r_acc = (regs.r_acc & ~0xffffffff0000ULL) | ((DI)v << 16);
215 break;
216 case acclo:
217 regs.r_acc = (regs.r_acc & ~0xffffffffULL) | ((DI)v);
218 break;
219
220 case 0: /* Stack pointer is "in" R0. */
221 {
222 if (v < heaptop)
223 {
224 unsigned int line;
225 const char * dummy;
226 const char * fname = NULL;
227
228 sim_get_current_source_location (& dummy, & fname, &line);
229
230 /* The setjmp and longjmp functions play tricks with the stack pointer. */
231 if (fname == NULL
232 || (strcmp (fname, "_setjmp") != 0
233 && strcmp (fname, "_longjmp") != 0))
234 {
235 printf ("collision in %s: pc %08x heap %08x stack %08x\n",
236 fname, (unsigned int) regs.r_pc, heaptop, v);
237 exit (1);
238 }
239 }
240 else
241 {
242 if (v < lowest_sp)
243 lowest_sp = v;
244 if (v > highest_sp)
245 highest_sp = v;
246 }
247
248 if (regs.r_psw & FLAGBIT_U)
249 regs.r_usp = v;
250 else
251 regs.r_isp = v;
252 break;
253 }
254
255 default:
256 if (id >= 1 && id <= 15)
257 regs.r[id] = v;
258 else
259 abort ();
260 }
261 }
262
263 void
264 put_reg64 (int id, unsigned long long v)
265 {
266 if (trace > ((id != pc) ? 0 : 1))
267 printf ("put_reg (%s) = %016llx\n", reg_names[id], v);
268
269 switch (id)
270 {
271 case acc64:
272 regs.r_acc = v;
273 break;
274 default:
275 abort ();
276 }
277 }
278
279 int
280 condition_true (int cond_id)
281 {
282 int f;
283
284 static const char *cond_name[] = {
285 "Z",
286 "!Z",
287 "C",
288 "!C",
289 "C&!Z",
290 "!(C&!Z)",
291 "!S",
292 "S",
293 "!(S^O)",
294 "S^O",
295 "!((S^O)|Z)",
296 "(S^O)|Z",
297 "O",
298 "!O",
299 "always",
300 "never"
301 };
302 switch (cond_id & 15)
303 {
304 case 0:
305 f = FLAG_Z;
306 break; /* EQ/Z */
307 case 1:
308 f = !FLAG_Z;
309 break; /* NE/NZ */
310 case 2:
311 f = FLAG_C;
312 break; /* GEU/C */
313 case 3:
314 f = !FLAG_C;
315 break; /* LTU/NC */
316 case 4:
317 f = FLAG_C & !FLAG_Z;
318 break; /* GTU */
319 case 5:
320 f = !(FLAG_C & !FLAG_Z);
321 break; /* LEU */
322 case 6:
323 f = !FLAG_S;
324 break; /* PZ */
325 case 7:
326 f = FLAG_S;
327 break; /* N */
328
329 case 8:
330 f = !(FLAG_S ^ FLAG_O);
331 break; /* GE */
332 case 9:
333 f = FLAG_S ^ FLAG_O;
334 break; /* LT */
335 case 10:
336 f = !((FLAG_S ^ FLAG_O) | FLAG_Z);
337 break; /* GT */
338 case 11:
339 f = (FLAG_S ^ FLAG_O) | FLAG_Z;
340 break; /* LE */
341 case 12:
342 f = FLAG_O;
343 break; /* O */
344 case 13:
345 f = !FLAG_O;
346 break; /* NO */
347 case 14:
348 f = 1; /* always */
349 break;
350 default:
351 f = 0; /* never */
352 break;
353 }
354 if (trace && ((cond_id & 15) != 14))
355 printf ("cond[%d] %s = %s\n", cond_id, cond_name[cond_id & 15],
356 f ? "true" : "false");
357 return f;
358 }
359
360 void
361 set_flags (int mask, int newbits)
362 {
363 regs.r_psw &= rx_flagand;
364 regs.r_psw |= rx_flagor;
365 regs.r_psw |= (newbits & mask & rx_flagmask);
366
367 if (trace)
368 {
369 int i;
370 printf ("flags now \033[32m %d", (int)((regs.r_psw >> 24) & 7));
371 for (i = 17; i >= 0; i--)
372 if (0x3000f & (1 << i))
373 {
374 if (regs.r_psw & (1 << i))
375 putchar ("CZSO------------IU"[i]);
376 else
377 putchar ('-');
378 }
379 printf ("\033[0m\n");
380 }
381 }
382
383 void
384 set_oszc (long long value, int b, int c)
385 {
386 unsigned int mask = b2mask[b];
387 int f = 0;
388
389 if (c)
390 f |= FLAGBIT_C;
391 if ((value & mask) == 0)
392 f |= FLAGBIT_Z;
393 if (value & b2signbit[b])
394 f |= FLAGBIT_S;
395 if ((value > b2maxsigned[b]) || (value < b2minsigned[b]))
396 f |= FLAGBIT_O;
397 set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O | FLAGBIT_C, f);
398 }
399
400 void
401 set_szc (long long value, int b, int c)
402 {
403 unsigned int mask = b2mask[b];
404 int f = 0;
405
406 if (c)
407 f |= FLAGBIT_C;
408 if ((value & mask) == 0)
409 f |= FLAGBIT_Z;
410 if (value & b2signbit[b])
411 f |= FLAGBIT_S;
412 set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_C, f);
413 }
414
415 void
416 set_osz (long long value, int b)
417 {
418 unsigned int mask = b2mask[b];
419 int f = 0;
420
421 if ((value & mask) == 0)
422 f |= FLAGBIT_Z;
423 if (value & b2signbit[b])
424 f |= FLAGBIT_S;
425 if ((value > b2maxsigned[b]) || (value < b2minsigned[b]))
426 f |= FLAGBIT_O;
427 set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, f);
428 }
429
430 void
431 set_sz (long long value, int b)
432 {
433 unsigned int mask = b2mask[b];
434 int f = 0;
435
436 if ((value & mask) == 0)
437 f |= FLAGBIT_Z;
438 if (value & b2signbit[b])
439 f |= FLAGBIT_S;
440 set_flags (FLAGBIT_Z | FLAGBIT_S, f);
441 }
442
443 void
444 set_zc (int z, int c)
445 {
446 set_flags (FLAGBIT_C | FLAGBIT_Z,
447 (c ? FLAGBIT_C : 0) | (z ? FLAGBIT_Z : 0));
448 }
449
450 void
451 set_c (int c)
452 {
453 set_flags (FLAGBIT_C, c ? FLAGBIT_C : 0);
454 }
455
456 static char *
457 psw2str(int rpsw)
458 {
459 static char buf[10];
460 char *bp = buf;
461 int i, ipl;
462
463 ipl = (rpsw & FLAGBITS_IPL) >> FLAGSHIFT_IPL;
464 if (ipl > 9)
465 {
466 *bp++ = (ipl / 10) + '0';
467 ipl %= 10;
468 }
469 *bp++ = ipl + '0';
470 for (i = 20; i >= 0; i--)
471 if (0x13000f & (1 << i))
472 {
473 if (rpsw & (1 << i))
474 *bp++ = "CZSO------------IU--P"[i];
475 else
476 *bp++ = '-';
477 }
478 *bp = 0;
479 return buf;
480 }
481
482 static char *
483 fpsw2str(int rpsw)
484 {
485 static char buf[100];
486 char *bp = buf;
487 int i; /* ---+---+---+---+---+---+---+---+ */
488 const char s1[] = "FFFFFF-----------EEEEE-DCCCCCCRR";
489 const char s2[] = "SXUZOV-----------XUZOV-NEXUZOV01";
490 const char rm[4][3] = { "RC", "RZ", "RP", "RN" };
491
492 for (i = 31; i >= 0; i--)
493 if (0xfc007dfc & (1 << i))
494 {
495 if (rpsw & (1 << i))
496 {
497 if (bp > buf)
498 *bp++ = '.';
499 *bp++ = s1[31-i];
500 *bp++ = s2[31-i];
501 }
502 }
503 if (bp > buf)
504 *bp++ = '.';
505 strcpy (bp, rm[rpsw&3]);
506 return buf;
507 }
508
509 #define TRC(f,n) \
510 if (oldregs.f != regs.f) \
511 { \
512 if (tag) { printf (tag); tag = 0; } \
513 printf(" %s %08x:%08x", n, \
514 (unsigned int)oldregs.f, \
515 (unsigned int)regs.f); \
516 oldregs.f = regs.f; \
517 }
518
519 void
520 trace_register_changes (void)
521 {
522 char *tag = "\033[36mREGS:";
523 int i;
524
525 if (!trace)
526 return;
527 for (i=1; i<16; i++)
528 TRC (r[i], reg_names[i]);
529 TRC (r_intb, "intb");
530 TRC (r_usp, "usp");
531 TRC (r_isp, "isp");
532 if (oldregs.r_psw != regs.r_psw)
533 {
534 if (tag) { printf (tag); tag = 0; }
535 printf(" psw %s:", psw2str(oldregs.r_psw));
536 printf("%s", psw2str(regs.r_psw));
537 oldregs.r_psw = regs.r_psw;
538 }
539
540 if (oldregs.r_fpsw != regs.r_fpsw)
541 {
542 if (tag) { printf (tag); tag = 0; }
543 printf(" fpsw %s:", fpsw2str(oldregs.r_fpsw));
544 printf("%s", fpsw2str(regs.r_fpsw));
545 oldregs.r_fpsw = regs.r_fpsw;
546 }
547
548 if (oldregs.r_acc != regs.r_acc)
549 {
550 if (tag) { printf (tag); tag = 0; }
551 printf(" acc %016llx:", oldregs.r_acc);
552 printf("%016llx", regs.r_acc);
553 oldregs.r_acc = regs.r_acc;
554 }
555
556 if (tag == 0)
557 printf ("\033[0m\n");
558 }