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