]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/rl78/cpu.c
update copyright year range in GDB files
[thirdparty/binutils-gdb.git] / sim / rl78 / cpu.c
CommitLineData
87326c78
DD
1/* cpu.c --- CPU for RL78 simulator.
2
61baf725 3 Copyright (C) 2011-2017 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
DD
38
39#define REGISTER_ADDRESS 0xffee0
40
41typedef 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
52static void trace_register_init ();
53
54/* This maps PSW to a pointer into memory[] */
55static RegBank *regbase_table[256];
56
57#define regbase regbase_table[memory[RL78_SFR_PSW]]
58
59#define REG(r) ((regbase)->r)
60
61void
62init_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
88SI
89get_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
120extern unsigned char initted[];
121
122SI
123set_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
180int
181condition_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
210const char * const
211reg_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
233static char *
234psw_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
258static unsigned char old_regs[32];
259static int old_psw;
260static int old_sp;
261
262int trace_register_words;
263
264void
265trace_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
330static void
331trace_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}