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