]> Git Repo - binutils.git/blob - sim/rl78/cpu.c
Automatic date update in version.in
[binutils.git] / sim / rl78 / cpu.c
1 /* cpu.c --- CPU for RL78 simulator.
2
3    Copyright (C) 2011-2022 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 }
This page took 0.04233 seconds and 4 git commands to generate.