cpu.c revision 1.9
1285242Sachim/* cpu.c --- CPU for RL78 simulator. 2285242Sachim 3285242Sachim Copyright (C) 2011-2020 Free Software Foundation, Inc. 4285242Sachim Contributed by Red Hat, Inc. 5285242Sachim 6285242Sachim This file is part of the GNU simulators. 7285242Sachim 8285242Sachim This program is free software; you can redistribute it and/or modify 9285242Sachim it under the terms of the GNU General Public License as published by 10285242Sachim the Free Software Foundation; either version 3 of the License, or 11285242Sachim (at your option) any later version. 12285242Sachim 13285242Sachim This program is distributed in the hope that it will be useful, 14285242Sachim but WITHOUT ANY WARRANTY; without even the implied warranty of 15285242Sachim MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16285242Sachim GNU General Public License for more details. 17285242Sachim 18285242Sachim You should have received a copy of the GNU General Public License 19285242Sachim along with this program. If not, see <http://www.gnu.org/licenses/>. 20285242Sachim*/ 21285242Sachim 22285242Sachim#include "config.h" 23285242Sachim#include <stdio.h> 24285242Sachim#include <string.h> 25285242Sachim#include <stdlib.h> 26285242Sachim 27285242Sachim#include "opcode/rl78.h" 28285242Sachim#include "mem.h" 29285242Sachim#include "cpu.h" 30285242Sachim 31285242Sachimint verbose = 0; 32285242Sachimint trace = 0; 33285242Sachimint rl78_in_gdb = 1; 34285242Sachimint timer_enabled = 2; 35285242Sachimint rl78_g10_mode = 0; 36285242Sachimint g13_multiply = 0; 37285242Sachimint g14_multiply = 0; 38285242Sachim 39285242Sachim#define REGISTER_ADDRESS 0xffee0 40285242Sachim 41285242Sachimtypedef struct { 42285242Sachim unsigned char x; 43285242Sachim unsigned char a; 44285242Sachim unsigned char c; 45285242Sachim unsigned char b; 46285242Sachim unsigned char e; 47285242Sachim unsigned char d; 48285242Sachim unsigned char l; 49285242Sachim unsigned char h; 50285242Sachim} RegBank; 51285242Sachim 52285242Sachimstatic void trace_register_init (); 53285242Sachim 54285242Sachim/* This maps PSW to a pointer into memory[] */ 55285242Sachimstatic RegBank *regbase_table[256]; 56285242Sachim 57285242Sachim#define regbase regbase_table[memory[RL78_SFR_PSW]] 58285242Sachim 59285242Sachim#define REG(r) ((regbase)->r) 60285242Sachim 61285242Sachimvoid 62285242Sachiminit_cpu (void) 63285242Sachim{ 64285242Sachim int i; 65285242Sachim 66285242Sachim init_mem (); 67285242Sachim 68285242Sachim memset (memory+REGISTER_ADDRESS, 0x11, 8 * 4); 69285242Sachim memory[RL78_SFR_PSW] = 0x06; 70285242Sachim memory[RL78_SFR_ES] = 0x0f; 71285242Sachim memory[RL78_SFR_CS] = 0x00; 72285242Sachim memory[RL78_SFR_PMC] = 0x00; 73285242Sachim 74285242Sachim for (i = 0; i < 256; i ++) 75285242Sachim { 76285242Sachim int rb0 = (i & RL78_PSW_RBS0) ? 1 : 0; 77285242Sachim int rb1 = (i & RL78_PSW_RBS1) ? 2 : 0; 78285242Sachim int rb = rb1 | rb0; 79285242Sachim regbase_table[i] = (RegBank *)(memory + (3 - rb) * 8 + REGISTER_ADDRESS); 80285242Sachim } 81285242Sachim 82285242Sachim trace_register_init (); 83285242Sachim 84285242Sachim /* This means "by default" */ 85285242Sachim timer_enabled = 2; 86285242Sachim} 87285242Sachim 88285242SachimSI 89285242Sachimget_reg (RL78_Register regno) 90285242Sachim{ 91285242Sachim switch (regno) 92285242Sachim { 93285242Sachim case RL78_Reg_None: 94285242Sachim /* Conditionals do this. */ 95285242Sachim return 0; 96285242Sachim 97285242Sachim default: 98285242Sachim abort (); 99285242Sachim case RL78_Reg_X: return REG (x); 100285242Sachim case RL78_Reg_A: return REG (a); 101285242Sachim case RL78_Reg_C: return REG (c); 102285242Sachim case RL78_Reg_B: return REG (b); 103285242Sachim case RL78_Reg_E: return REG (e); 104285242Sachim case RL78_Reg_D: return REG (d); 105285242Sachim case RL78_Reg_L: return REG (l); 106285242Sachim case RL78_Reg_H: return REG (h); 107285242Sachim case RL78_Reg_AX: return REG (a) * 256 + REG (x); 108285242Sachim case RL78_Reg_BC: return REG (b) * 256 + REG (c); 109285242Sachim case RL78_Reg_DE: return REG (d) * 256 + REG (e); 110285242Sachim case RL78_Reg_HL: return REG (h) * 256 + REG (l); 111285242Sachim case RL78_Reg_SP: return memory[RL78_SFR_SP] + 256 * memory[RL78_SFR_SP+1]; 112285242Sachim case RL78_Reg_PSW: return memory[RL78_SFR_PSW]; 113285242Sachim case RL78_Reg_CS: return memory[RL78_SFR_CS]; 114285242Sachim case RL78_Reg_ES: return memory[RL78_SFR_ES]; 115285242Sachim case RL78_Reg_PMC: return memory[RL78_SFR_PMC]; 116285242Sachim case RL78_Reg_MEM: return memory[RL78_SFR_MEM]; 117285242Sachim } 118285242Sachim} 119285242Sachim 120285242Sachimextern unsigned char initted[]; 121285242Sachim 122285242SachimSI 123285242Sachimset_reg (RL78_Register regno, SI val) 124285242Sachim{ 125285242Sachim switch (regno) 126285242Sachim { 127285242Sachim case RL78_Reg_None: 128285242Sachim abort (); 129285242Sachim case RL78_Reg_X: REG (x) = val; break; 130285242Sachim case RL78_Reg_A: REG (a) = val; break; 131285242Sachim case RL78_Reg_C: REG (c) = val; break; 132285242Sachim case RL78_Reg_B: REG (b) = val; break; 133285242Sachim case RL78_Reg_E: REG (e) = val; break; 134285242Sachim case RL78_Reg_D: REG (d) = val; break; 135285242Sachim case RL78_Reg_L: REG (l) = val; break; 136285242Sachim case RL78_Reg_H: REG (h) = val; break; 137285242Sachim case RL78_Reg_AX: 138285242Sachim REG (a) = val >> 8; 139285242Sachim REG (x) = val & 0xff; 140285242Sachim break; 141285242Sachim case RL78_Reg_BC: 142285242Sachim REG (b) = val >> 8; 143285242Sachim REG (c) = val & 0xff; 144285242Sachim break; 145285242Sachim case RL78_Reg_DE: 146285242Sachim REG (d) = val >> 8; 147285242Sachim REG (e) = val & 0xff; 148285242Sachim break; 149285242Sachim case RL78_Reg_HL: 150285242Sachim REG (h) = val >> 8; 151285242Sachim REG (l) = val & 0xff; 152285242Sachim break; 153285242Sachim case RL78_Reg_SP: 154285242Sachim if (val & 1) 155285242Sachim { 156285242Sachim printf ("Warning: SP value 0x%04x truncated at pc=0x%05x\n", val, pc); 157285242Sachim val &= ~1; 158285242Sachim } 159285242Sachim { 160285242Sachim int old_sp = get_reg (RL78_Reg_SP); 161285242Sachim if (val < old_sp) 162285242Sachim { 163285242Sachim int i; 164285242Sachim for (i = val; i < old_sp; i ++) 165285242Sachim initted[i + 0xf0000] = 0; 166285242Sachim } 167285242Sachim } 168285242Sachim memory[RL78_SFR_SP] = val & 0xff; 169285242Sachim memory[RL78_SFR_SP + 1] = val >> 8; 170285242Sachim break; 171285242Sachim case RL78_Reg_PSW: memory[RL78_SFR_PSW] = val; break; 172285242Sachim case RL78_Reg_CS: memory[RL78_SFR_CS] = val; break; 173285242Sachim case RL78_Reg_ES: memory[RL78_SFR_ES] = val; break; 174285242Sachim case RL78_Reg_PMC: memory[RL78_SFR_PMC] = val; break; 175285242Sachim case RL78_Reg_MEM: memory[RL78_SFR_MEM] = val; break; 176285242Sachim } 177285242Sachim return val; 178285242Sachim} 179285242Sachim 180285242Sachimint 181285242Sachimcondition_true (RL78_Condition cond_id, int val) 182285242Sachim{ 183285242Sachim int psw = get_reg (RL78_Reg_PSW); 184285242Sachim int z = (psw & RL78_PSW_Z) ? 1 : 0; 185285242Sachim int cy = (psw & RL78_PSW_CY) ? 1 : 0; 186285242Sachim 187285242Sachim switch (cond_id) 188285242Sachim { 189285242Sachim case RL78_Condition_T: 190285242Sachim return val != 0; 191285242Sachim case RL78_Condition_F: 192285242Sachim return val == 0; 193285242Sachim case RL78_Condition_C: 194285242Sachim return cy; 195285242Sachim case RL78_Condition_NC: 196285242Sachim return !cy; 197285242Sachim case RL78_Condition_H: 198285242Sachim return !(z | cy); 199285242Sachim case RL78_Condition_NH: 200285242Sachim return z | cy; 201285242Sachim case RL78_Condition_Z: 202285242Sachim return z; 203285242Sachim case RL78_Condition_NZ: 204285242Sachim return !z; 205285242Sachim default: 206285242Sachim abort (); 207285242Sachim } 208285242Sachim} 209285242Sachim 210285242Sachimconst char * const 211285242Sachimreg_names[] = { 212285242Sachim "none", 213285242Sachim "x", 214285242Sachim "a", 215285242Sachim "c", 216285242Sachim "b", 217285242Sachim "e", 218285242Sachim "d", 219285242Sachim "l", 220285242Sachim "h", 221285242Sachim "ax", 222285242Sachim "bc", 223285242Sachim "de", 224285242Sachim "hl", 225285242Sachim "sp", 226285242Sachim "psw", 227285242Sachim "cs", 228285242Sachim "es", 229285242Sachim "pmc", 230285242Sachim "mem" 231285242Sachim}; 232285242Sachim 233285242Sachimstatic char * 234285242Sachimpsw_string (int psw) 235285242Sachim{ 236285242Sachim static char buf[30]; 237285242Sachim const char *comma = ""; 238285242Sachim 239285242Sachim buf[0] = 0; 240285242Sachim if (psw == 0) 241285242Sachim strcpy (buf, "-"); 242285242Sachim else 243285242Sachim { 244285242Sachim#define PSW1(bit, name) if (psw & bit) { strcat (buf, comma); strcat (buf, name); comma = ","; } 245285242Sachim PSW1 (RL78_PSW_IE, "ie"); 246285242Sachim PSW1 (RL78_PSW_Z, "z"); 247285242Sachim PSW1 (RL78_PSW_RBS1, "r1"); 248285242Sachim PSW1 (RL78_PSW_AC, "ac"); 249285242Sachim PSW1 (RL78_PSW_RBS0, "r0"); 250285242Sachim PSW1 (RL78_PSW_ISP1, "i1"); 251285242Sachim PSW1 (RL78_PSW_ISP0, "i0"); 252285242Sachim PSW1 (RL78_PSW_CY, "cy"); 253285242Sachim } 254285242Sachim printf ("%s", buf); 255285242Sachim return buf; 256285242Sachim} 257285242Sachim 258285242Sachimstatic unsigned char old_regs[32]; 259285242Sachimstatic int old_psw; 260285242Sachimstatic int old_sp; 261285242Sachim 262285242Sachimint trace_register_words; 263285242Sachim 264285242Sachimvoid 265285242Sachimtrace_register_changes (void) 266285242Sachim{ 267285242Sachim int i; 268285242Sachim int any = 0; 269285242Sachim 270285242Sachim if (!trace) 271285242Sachim return; 272285242Sachim 273285242Sachim#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; } 274285242Sachim#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; } 275285242Sachim 276285242Sachim if (trace_register_words) 277285242Sachim { 278285242Sachim#define TRW(name, idx) TW (name, memory[REGISTER_ADDRESS + (idx)], old_regs[idx]) 279285242Sachim for (i = 0; i < 32; i += 2) 280285242Sachim { 281285242Sachim char buf[10]; 282285242Sachim int o, n, a; 283285242Sachim switch (i) 284285242Sachim { 285285242Sachim case 0: strcpy (buf, "AX"); break; 286285242Sachim case 2: strcpy (buf, "BC"); break; 287285242Sachim case 4: strcpy (buf, "DE"); break; 288285242Sachim case 6: strcpy (buf, "HL"); break; 289285242Sachim default: sprintf (buf, "r%d", i); break; 290285242Sachim } 291285242Sachim a = REGISTER_ADDRESS + (i ^ 0x18); 292285242Sachim o = old_regs[i ^ 0x18] + old_regs[(i ^ 0x18) + 1] * 256; 293285242Sachim n = memory[a] + memory[a + 1] * 256; 294285242Sachim TW (buf, n, o); 295285242Sachim old_regs[i ^ 0x18] = n; 296285242Sachim old_regs[(i ^ 0x18) + 1] = n >> 8; 297285242Sachim } 298285242Sachim } 299285242Sachim else 300285242Sachim { 301285242Sachim for (i = 0; i < 32; i ++) 302285242Sachim { 303285242Sachim char buf[10]; 304285242Sachim if (i < 8) 305285242Sachim { 306285242Sachim buf[0] = "XACBEDLH"[i]; 307285242Sachim buf[1] = 0; 308285242Sachim } 309285242Sachim else 310285242Sachim sprintf (buf, "r%d", i); 311285242Sachim#define TRB(name, idx) TB (name, memory[REGISTER_ADDRESS + (idx)], old_regs[idx]) 312285242Sachim TRB (buf, i ^ 0x18); 313285242Sachim } 314285242Sachim } 315285242Sachim if (memory[RL78_SFR_PSW] != old_psw) 316285242Sachim { 317285242Sachim printf ("PSW: \033[31m"); 318285242Sachim psw_string (old_psw); 319285242Sachim printf (" \033[32m"); 320285242Sachim psw_string (memory[RL78_SFR_PSW]); 321285242Sachim printf ("\033[0m "); 322285242Sachim old_psw = memory[RL78_SFR_PSW]; 323285242Sachim any = 1; 324285242Sachim } 325285242Sachim TW ("SP", mem_get_hi (RL78_SFR_SP), old_sp); 326285242Sachim if (any) 327285242Sachim printf ("\n"); 328285242Sachim} 329285242Sachim 330285242Sachimstatic void 331285242Sachimtrace_register_init (void) 332285242Sachim{ 333285242Sachim memcpy (old_regs, memory + REGISTER_ADDRESS, 8 * 4); 334285242Sachim old_psw = memory[RL78_SFR_PSW]; 335285242Sachim old_sp = mem_get_hi (RL78_SFR_SP); 336285242Sachim} 337285242Sachim