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