Upload Tizen:Base source
[external/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 }