Fix thinko with previous delta to RL78 sim, by adding code to define the G10 and...
[external/binutils.git] / sim / rl78 / cpu.c
1 /* cpu.c --- CPU for RL78 simulator.
2
3    Copyright (C) 2011-2015 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 #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
31 int verbose = 0;
32 int trace = 0;
33 int rl78_in_gdb = 1;
34 int timer_enabled = 2;
35 int rl78_g10_mode = 0;
36 int g13_multiply = 0;
37
38 #define REGISTER_ADDRESS 0xffee0
39
40 typedef 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
51 static void trace_register_init ();
52
53 /* This maps PSW to a pointer into memory[] */
54 static RegBank *regbase_table[256];
55
56 #define regbase regbase_table[memory[RL78_SFR_PSW]]
57
58 #define REG(r) ((regbase)->r)
59
60 void
61 init_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
87 SI
88 get_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
119 extern unsigned char initted[];
120
121 SI
122 set_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
179 int
180 condition_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
209 const char * const
210 reg_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
232 static char *
233 psw_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
257 static unsigned char old_regs[32];
258 static int old_psw;
259 static int old_sp;
260
261 int trace_register_words;
262
263 void
264 trace_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
329 static void
330 trace_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 }