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