PowerPC relocations for prefix insns
[external/binutils.git] / sim / rl78 / cpu.c
1 /* cpu.c --- CPU for RL78 simulator.
2
3    Copyright (C) 2011-2019 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 <string.h>
25 #include <stdlib.h>
26
27 #include "opcode/rl78.h"
28 #include "mem.h"
29 #include "cpu.h"
30
31 int verbose = 0;
32 int trace = 0;
33 int rl78_in_gdb = 1;
34 int timer_enabled = 2;
35 int rl78_g10_mode = 0;
36 int g13_multiply = 0;
37 int g14_multiply = 0;
38
39 #define REGISTER_ADDRESS 0xffee0
40
41 typedef struct {
42   unsigned char x;
43   unsigned char a;
44   unsigned char c;
45   unsigned char b;
46   unsigned char e;
47   unsigned char d;
48   unsigned char l;
49   unsigned char h;
50 } RegBank;
51
52 static void trace_register_init ();
53
54 /* This maps PSW to a pointer into memory[] */
55 static RegBank *regbase_table[256];
56
57 #define regbase regbase_table[memory[RL78_SFR_PSW]]
58
59 #define REG(r) ((regbase)->r)
60
61 void
62 init_cpu (void)
63 {
64   int i;
65
66   init_mem ();
67
68   memset (memory+REGISTER_ADDRESS, 0x11, 8 * 4);
69   memory[RL78_SFR_PSW] = 0x06;
70   memory[RL78_SFR_ES] = 0x0f;
71   memory[RL78_SFR_CS] = 0x00;
72   memory[RL78_SFR_PMC] = 0x00;
73
74   for (i = 0; i < 256; i ++)
75     {
76       int rb0 = (i & RL78_PSW_RBS0) ? 1 : 0;
77       int rb1 = (i & RL78_PSW_RBS1) ? 2 : 0;
78       int rb = rb1 | rb0;
79       regbase_table[i] = (RegBank *)(memory + (3 - rb) * 8 + REGISTER_ADDRESS);
80     }
81
82   trace_register_init ();
83
84   /* This means "by default" */
85   timer_enabled = 2;
86 }
87
88 SI
89 get_reg (RL78_Register regno)
90 {
91   switch (regno)
92     {
93     case RL78_Reg_None:
94       /* Conditionals do this.  */
95       return 0;
96
97     default:
98       abort ();
99     case RL78_Reg_X:    return REG (x);
100     case RL78_Reg_A:    return REG (a);
101     case RL78_Reg_C:    return REG (c);
102     case RL78_Reg_B:    return REG (b);
103     case RL78_Reg_E:    return REG (e);
104     case RL78_Reg_D:    return REG (d);
105     case RL78_Reg_L:    return REG (l);
106     case RL78_Reg_H:    return REG (h);
107     case RL78_Reg_AX:   return REG (a) * 256 + REG (x);
108     case RL78_Reg_BC:   return REG (b) * 256 + REG (c);
109     case RL78_Reg_DE:   return REG (d) * 256 + REG (e);
110     case RL78_Reg_HL:   return REG (h) * 256 + REG (l);
111     case RL78_Reg_SP:   return memory[RL78_SFR_SP] + 256 * memory[RL78_SFR_SP+1];
112     case RL78_Reg_PSW:  return memory[RL78_SFR_PSW];
113     case RL78_Reg_CS:   return memory[RL78_SFR_CS];
114     case RL78_Reg_ES:   return memory[RL78_SFR_ES];
115     case RL78_Reg_PMC:  return memory[RL78_SFR_PMC];
116     case RL78_Reg_MEM:  return memory[RL78_SFR_MEM];
117     }
118 }
119
120 extern unsigned char initted[];
121
122 SI
123 set_reg (RL78_Register regno, SI val)
124 {
125   switch (regno)
126     {
127     case RL78_Reg_None:
128       abort ();
129     case RL78_Reg_X:    REG (x) = val; break;
130     case RL78_Reg_A:    REG (a) = val; break;
131     case RL78_Reg_C:    REG (c) = val; break;
132     case RL78_Reg_B:    REG (b) = val; break;
133     case RL78_Reg_E:    REG (e) = val; break;
134     case RL78_Reg_D:    REG (d) = val; break;
135     case RL78_Reg_L:    REG (l) = val; break;
136     case RL78_Reg_H:    REG (h) = val; break;
137     case RL78_Reg_AX:
138       REG (a) = val >> 8;
139       REG (x) = val & 0xff;
140       break;
141     case RL78_Reg_BC:
142       REG (b) = val >> 8;
143       REG (c) = val & 0xff;
144       break;
145     case RL78_Reg_DE:
146       REG (d) = val >> 8;
147       REG (e) = val & 0xff;
148       break;
149     case RL78_Reg_HL:
150       REG (h) = val >> 8;
151       REG (l) = val & 0xff;
152       break;
153     case RL78_Reg_SP:
154       if (val & 1)
155         {
156           printf ("Warning: SP value 0x%04x truncated at pc=0x%05x\n", val, pc);
157           val &= ~1;
158         }
159       {
160         int old_sp = get_reg (RL78_Reg_SP);
161         if (val < old_sp)
162           {
163             int i;
164             for (i = val; i < old_sp; i ++)
165               initted[i + 0xf0000] = 0;
166           }
167       }
168       memory[RL78_SFR_SP] = val & 0xff;
169       memory[RL78_SFR_SP + 1] = val >> 8;
170       break;
171     case RL78_Reg_PSW:  memory[RL78_SFR_PSW] = val; break;
172     case RL78_Reg_CS:   memory[RL78_SFR_CS] = val; break;
173     case RL78_Reg_ES:   memory[RL78_SFR_ES] = val; break;
174     case RL78_Reg_PMC:  memory[RL78_SFR_PMC] = val; break;
175     case RL78_Reg_MEM:  memory[RL78_SFR_MEM] = val; break;
176     }
177   return val;
178 }
179
180 int
181 condition_true (RL78_Condition cond_id, int val)
182 {
183   int psw = get_reg (RL78_Reg_PSW);
184   int z = (psw & RL78_PSW_Z) ? 1 : 0;
185   int cy = (psw & RL78_PSW_CY) ? 1 : 0;
186
187   switch (cond_id)
188     {
189     case RL78_Condition_T:
190       return val != 0;
191     case RL78_Condition_F:
192       return val == 0;
193     case RL78_Condition_C:
194       return cy;
195     case RL78_Condition_NC:
196       return !cy;
197     case RL78_Condition_H:
198       return !(z | cy);
199     case RL78_Condition_NH:
200       return z | cy;
201     case RL78_Condition_Z:
202       return z;
203     case RL78_Condition_NZ:
204       return !z;
205     default:
206       abort ();
207     }
208 }
209
210 const char * const
211 reg_names[] = {
212   "none",
213   "x",
214   "a",
215   "c",
216   "b",
217   "e",
218   "d",
219   "l",
220   "h",
221   "ax",
222   "bc",
223   "de",
224   "hl",
225   "sp",
226   "psw",
227   "cs",
228   "es",
229   "pmc",
230   "mem"
231 };
232
233 static char *
234 psw_string (int psw)
235 {
236   static char buf[30];
237   const char *comma = "";
238
239   buf[0] = 0;
240   if (psw == 0)
241     strcpy (buf, "-");
242   else
243     {
244 #define PSW1(bit, name) if (psw & bit) { strcat (buf, comma); strcat (buf, name); comma = ","; }
245       PSW1 (RL78_PSW_IE, "ie");
246       PSW1 (RL78_PSW_Z, "z");
247       PSW1 (RL78_PSW_RBS1, "r1");
248       PSW1 (RL78_PSW_AC, "ac");
249       PSW1 (RL78_PSW_RBS0, "r0");
250       PSW1 (RL78_PSW_ISP1, "i1");
251       PSW1 (RL78_PSW_ISP0, "i0");
252       PSW1 (RL78_PSW_CY, "cy");
253     }
254   printf ("%s", buf);
255   return buf;
256 }
257
258 static unsigned char old_regs[32];
259 static int old_psw;
260 static int old_sp;
261
262 int trace_register_words;
263
264 void
265 trace_register_changes (void)
266 {
267   int i;
268   int any = 0;
269
270   if (!trace)
271     return;
272
273 #define TB(name,nv,ov) if (nv != ov) { printf ("%s: \033[31m%02x \033[32m%02x\033[0m ", name, ov, nv); ov = nv; any = 1; }
274 #define TW(name,nv,ov) if (nv != ov) { printf ("%s: \033[31m%04x \033[32m%04x\033[0m ", name, ov, nv); ov = nv; any = 1; }
275
276   if (trace_register_words)
277     {
278 #define TRW(name, idx) TW (name, memory[REGISTER_ADDRESS + (idx)], old_regs[idx])
279       for (i = 0; i < 32; i += 2)
280         {
281           char buf[10];
282           int o, n, a;
283           switch (i)
284             {
285             case 0: strcpy (buf, "AX"); break;
286             case 2: strcpy (buf, "BC"); break;
287             case 4: strcpy (buf, "DE"); break;
288             case 6: strcpy (buf, "HL"); break;
289             default: sprintf (buf, "r%d", i); break;
290             }
291           a = REGISTER_ADDRESS + (i ^ 0x18);
292           o = old_regs[i ^ 0x18] + old_regs[(i ^ 0x18) + 1] * 256;
293           n = memory[a] + memory[a + 1] * 256;
294           TW (buf, n, o);
295           old_regs[i ^ 0x18] = n;
296           old_regs[(i ^ 0x18) + 1] = n >> 8;
297         }
298     }
299   else
300     {
301       for (i = 0; i < 32; i ++)
302         {
303           char buf[10];
304           if (i < 8)
305             {
306               buf[0] = "XACBEDLH"[i];
307               buf[1] = 0;
308             }
309           else
310             sprintf (buf, "r%d", i);
311 #define TRB(name, idx) TB (name, memory[REGISTER_ADDRESS + (idx)], old_regs[idx])
312           TRB (buf, i ^ 0x18);
313         }
314     }
315   if (memory[RL78_SFR_PSW] != old_psw)
316     {
317       printf ("PSW: \033[31m");
318       psw_string (old_psw);
319       printf (" \033[32m");
320       psw_string (memory[RL78_SFR_PSW]);
321       printf ("\033[0m ");
322       old_psw = memory[RL78_SFR_PSW];
323       any = 1;
324     }
325   TW ("SP", mem_get_hi (RL78_SFR_SP), old_sp);
326   if (any)
327     printf ("\n");
328 }
329
330 static void
331 trace_register_init (void)
332 {
333   memcpy (old_regs, memory + REGISTER_ADDRESS, 8 * 4);
334   old_psw = memory[RL78_SFR_PSW];
335   old_sp = mem_get_hi (RL78_SFR_SP);
336 }