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