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