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