Blame sim/rl78/cpu.c

Packit Service 706eca
/* cpu.c --- CPU for RL78 simulator.
Packit Service 706eca
Packit Service 706eca
   Copyright (C) 2011-2018 Free Software Foundation, Inc.
Packit Service 706eca
   Contributed by Red Hat, Inc.
Packit Service 706eca
Packit Service 706eca
   This file is part of the GNU simulators.
Packit Service 706eca
Packit Service 706eca
   This program is free software; you can redistribute it and/or modify
Packit Service 706eca
   it under the terms of the GNU General Public License as published by
Packit Service 706eca
   the Free Software Foundation; either version 3 of the License, or
Packit Service 706eca
   (at your option) any later version.
Packit Service 706eca
Packit Service 706eca
   This program is distributed in the hope that it will be useful,
Packit Service 706eca
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 706eca
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 706eca
   GNU General Public License for more details.
Packit Service 706eca
Packit Service 706eca
   You should have received a copy of the GNU General Public License
Packit Service 706eca
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit Service 706eca
*/
Packit Service 706eca
Packit Service 706eca
#include "config.h"
Packit Service 706eca
#include <stdio.h>
Packit Service 706eca
#include <string.h>
Packit Service 706eca
#include <stdlib.h>
Packit Service 706eca
Packit Service 706eca
#include "opcode/rl78.h"
Packit Service 706eca
#include "mem.h"
Packit Service 706eca
#include "cpu.h"
Packit Service 706eca
Packit Service 706eca
int verbose = 0;
Packit Service 706eca
int trace = 0;
Packit Service 706eca
int rl78_in_gdb = 1;
Packit Service 706eca
int timer_enabled = 2;
Packit Service 706eca
int rl78_g10_mode = 0;
Packit Service 706eca
int g13_multiply = 0;
Packit Service 706eca
int g14_multiply = 0;
Packit Service 706eca
Packit Service 706eca
#define REGISTER_ADDRESS 0xffee0
Packit Service 706eca
Packit Service 706eca
typedef struct {
Packit Service 706eca
  unsigned char x;
Packit Service 706eca
  unsigned char a;
Packit Service 706eca
  unsigned char c;
Packit Service 706eca
  unsigned char b;
Packit Service 706eca
  unsigned char e;
Packit Service 706eca
  unsigned char d;
Packit Service 706eca
  unsigned char l;
Packit Service 706eca
  unsigned char h;
Packit Service 706eca
} RegBank;
Packit Service 706eca
Packit Service 706eca
static void trace_register_init ();
Packit Service 706eca
Packit Service 706eca
/* This maps PSW to a pointer into memory[] */
Packit Service 706eca
static RegBank *regbase_table[256];
Packit Service 706eca
Packit Service 706eca
#define regbase regbase_table[memory[RL78_SFR_PSW]]
Packit Service 706eca
Packit Service 706eca
#define REG(r) ((regbase)->r)
Packit Service 706eca
Packit Service 706eca
void
Packit Service 706eca
init_cpu (void)
Packit Service 706eca
{
Packit Service 706eca
  int i;
Packit Service 706eca
Packit Service 706eca
  init_mem ();
Packit Service 706eca
Packit Service 706eca
  memset (memory+REGISTER_ADDRESS, 0x11, 8 * 4);
Packit Service 706eca
  memory[RL78_SFR_PSW] = 0x06;
Packit Service 706eca
  memory[RL78_SFR_ES] = 0x0f;
Packit Service 706eca
  memory[RL78_SFR_CS] = 0x00;
Packit Service 706eca
  memory[RL78_SFR_PMC] = 0x00;
Packit Service 706eca
Packit Service 706eca
  for (i = 0; i < 256; i ++)
Packit Service 706eca
    {
Packit Service 706eca
      int rb0 = (i & RL78_PSW_RBS0) ? 1 : 0;
Packit Service 706eca
      int rb1 = (i & RL78_PSW_RBS1) ? 2 : 0;
Packit Service 706eca
      int rb = rb1 | rb0;
Packit Service 706eca
      regbase_table[i] = (RegBank *)(memory + (3 - rb) * 8 + REGISTER_ADDRESS);
Packit Service 706eca
    }
Packit Service 706eca
Packit Service 706eca
  trace_register_init ();
Packit Service 706eca
Packit Service 706eca
  /* This means "by default" */
Packit Service 706eca
  timer_enabled = 2;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
SI
Packit Service 706eca
get_reg (RL78_Register regno)
Packit Service 706eca
{
Packit Service 706eca
  switch (regno)
Packit Service 706eca
    {
Packit Service 706eca
    case RL78_Reg_None:
Packit Service 706eca
      /* Conditionals do this.  */
Packit Service 706eca
      return 0;
Packit Service 706eca
Packit Service 706eca
    default:
Packit Service 706eca
      abort ();
Packit Service 706eca
    case RL78_Reg_X:	return REG (x);
Packit Service 706eca
    case RL78_Reg_A:	return REG (a);
Packit Service 706eca
    case RL78_Reg_C:	return REG (c);
Packit Service 706eca
    case RL78_Reg_B:	return REG (b);
Packit Service 706eca
    case RL78_Reg_E:	return REG (e);
Packit Service 706eca
    case RL78_Reg_D:	return REG (d);
Packit Service 706eca
    case RL78_Reg_L:	return REG (l);
Packit Service 706eca
    case RL78_Reg_H:	return REG (h);
Packit Service 706eca
    case RL78_Reg_AX:	return REG (a) * 256 + REG (x);
Packit Service 706eca
    case RL78_Reg_BC:	return REG (b) * 256 + REG (c);
Packit Service 706eca
    case RL78_Reg_DE:	return REG (d) * 256 + REG (e);
Packit Service 706eca
    case RL78_Reg_HL:	return REG (h) * 256 + REG (l);
Packit Service 706eca
    case RL78_Reg_SP:	return memory[RL78_SFR_SP] + 256 * memory[RL78_SFR_SP+1];
Packit Service 706eca
    case RL78_Reg_PSW:	return memory[RL78_SFR_PSW];
Packit Service 706eca
    case RL78_Reg_CS:	return memory[RL78_SFR_CS];
Packit Service 706eca
    case RL78_Reg_ES:	return memory[RL78_SFR_ES];
Packit Service 706eca
    case RL78_Reg_PMC:	return memory[RL78_SFR_PMC];
Packit Service 706eca
    case RL78_Reg_MEM:	return memory[RL78_SFR_MEM];
Packit Service 706eca
    }
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
extern unsigned char initted[];
Packit Service 706eca
Packit Service 706eca
SI
Packit Service 706eca
set_reg (RL78_Register regno, SI val)
Packit Service 706eca
{
Packit Service 706eca
  switch (regno)
Packit Service 706eca
    {
Packit Service 706eca
    case RL78_Reg_None:
Packit Service 706eca
      abort ();
Packit Service 706eca
    case RL78_Reg_X:	REG (x) = val; break;
Packit Service 706eca
    case RL78_Reg_A:	REG (a) = val; break;
Packit Service 706eca
    case RL78_Reg_C:	REG (c) = val; break;
Packit Service 706eca
    case RL78_Reg_B:	REG (b) = val; break;
Packit Service 706eca
    case RL78_Reg_E:	REG (e) = val; break;
Packit Service 706eca
    case RL78_Reg_D:	REG (d) = val; break;
Packit Service 706eca
    case RL78_Reg_L:	REG (l) = val; break;
Packit Service 706eca
    case RL78_Reg_H:	REG (h) = val; break;
Packit Service 706eca
    case RL78_Reg_AX:
Packit Service 706eca
      REG (a) = val >> 8;
Packit Service 706eca
      REG (x) = val & 0xff;
Packit Service 706eca
      break;
Packit Service 706eca
    case RL78_Reg_BC:
Packit Service 706eca
      REG (b) = val >> 8;
Packit Service 706eca
      REG (c) = val & 0xff;
Packit Service 706eca
      break;
Packit Service 706eca
    case RL78_Reg_DE:
Packit Service 706eca
      REG (d) = val >> 8;
Packit Service 706eca
      REG (e) = val & 0xff;
Packit Service 706eca
      break;
Packit Service 706eca
    case RL78_Reg_HL:
Packit Service 706eca
      REG (h) = val >> 8;
Packit Service 706eca
      REG (l) = val & 0xff;
Packit Service 706eca
      break;
Packit Service 706eca
    case RL78_Reg_SP:
Packit Service 706eca
      if (val & 1)
Packit Service 706eca
	{
Packit Service 706eca
	  printf ("Warning: SP value 0x%04x truncated at pc=0x%05x\n", val, pc);
Packit Service 706eca
	  val &= ~1;
Packit Service 706eca
	}
Packit Service 706eca
      {
Packit Service 706eca
	int old_sp = get_reg (RL78_Reg_SP);
Packit Service 706eca
	if (val < old_sp)
Packit Service 706eca
	  {
Packit Service 706eca
	    int i;
Packit Service 706eca
	    for (i = val; i < old_sp; i ++)
Packit Service 706eca
	      initted[i + 0xf0000] = 0;
Packit Service 706eca
	  }
Packit Service 706eca
      }
Packit Service 706eca
      memory[RL78_SFR_SP] = val & 0xff;
Packit Service 706eca
      memory[RL78_SFR_SP + 1] = val >> 8;
Packit Service 706eca
      break;
Packit Service 706eca
    case RL78_Reg_PSW:	memory[RL78_SFR_PSW] = val; break;
Packit Service 706eca
    case RL78_Reg_CS:	memory[RL78_SFR_CS] = val; break;
Packit Service 706eca
    case RL78_Reg_ES:	memory[RL78_SFR_ES] = val; break;
Packit Service 706eca
    case RL78_Reg_PMC:	memory[RL78_SFR_PMC] = val; break;
Packit Service 706eca
    case RL78_Reg_MEM:	memory[RL78_SFR_MEM] = val; break;
Packit Service 706eca
    }
Packit Service 706eca
  return val;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
int
Packit Service 706eca
condition_true (RL78_Condition cond_id, int val)
Packit Service 706eca
{
Packit Service 706eca
  int psw = get_reg (RL78_Reg_PSW);
Packit Service 706eca
  int z = (psw & RL78_PSW_Z) ? 1 : 0;
Packit Service 706eca
  int cy = (psw & RL78_PSW_CY) ? 1 : 0;
Packit Service 706eca
Packit Service 706eca
  switch (cond_id)
Packit Service 706eca
    {
Packit Service 706eca
    case RL78_Condition_T:
Packit Service 706eca
      return val != 0;
Packit Service 706eca
    case RL78_Condition_F:
Packit Service 706eca
      return val == 0;
Packit Service 706eca
    case RL78_Condition_C:
Packit Service 706eca
      return cy;
Packit Service 706eca
    case RL78_Condition_NC:
Packit Service 706eca
      return !cy;
Packit Service 706eca
    case RL78_Condition_H:
Packit Service 706eca
      return !(z | cy);
Packit Service 706eca
    case RL78_Condition_NH:
Packit Service 706eca
      return z | cy;
Packit Service 706eca
    case RL78_Condition_Z:
Packit Service 706eca
      return z;
Packit Service 706eca
    case RL78_Condition_NZ:
Packit Service 706eca
      return !z;
Packit Service 706eca
    default:
Packit Service 706eca
      abort ();
Packit Service 706eca
    }
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
const char * const
Packit Service 706eca
reg_names[] = {
Packit Service 706eca
  "none",
Packit Service 706eca
  "x",
Packit Service 706eca
  "a",
Packit Service 706eca
  "c",
Packit Service 706eca
  "b",
Packit Service 706eca
  "e",
Packit Service 706eca
  "d",
Packit Service 706eca
  "l",
Packit Service 706eca
  "h",
Packit Service 706eca
  "ax",
Packit Service 706eca
  "bc",
Packit Service 706eca
  "de",
Packit Service 706eca
  "hl",
Packit Service 706eca
  "sp",
Packit Service 706eca
  "psw",
Packit Service 706eca
  "cs",
Packit Service 706eca
  "es",
Packit Service 706eca
  "pmc",
Packit Service 706eca
  "mem"
Packit Service 706eca
};
Packit Service 706eca
Packit Service 706eca
static char *
Packit Service 706eca
psw_string (int psw)
Packit Service 706eca
{
Packit Service 706eca
  static char buf[30];
Packit Service 706eca
  const char *comma = "";
Packit Service 706eca
Packit Service 706eca
  buf[0] = 0;
Packit Service 706eca
  if (psw == 0)
Packit Service 706eca
    strcpy (buf, "-");
Packit Service 706eca
  else
Packit Service 706eca
    {
Packit Service 706eca
#define PSW1(bit, name) if (psw & bit) { strcat (buf, comma); strcat (buf, name); comma = ","; }
Packit Service 706eca
      PSW1 (RL78_PSW_IE, "ie");
Packit Service 706eca
      PSW1 (RL78_PSW_Z, "z");
Packit Service 706eca
      PSW1 (RL78_PSW_RBS1, "r1");
Packit Service 706eca
      PSW1 (RL78_PSW_AC, "ac");
Packit Service 706eca
      PSW1 (RL78_PSW_RBS0, "r0");
Packit Service 706eca
      PSW1 (RL78_PSW_ISP1, "i1");
Packit Service 706eca
      PSW1 (RL78_PSW_ISP0, "i0");
Packit Service 706eca
      PSW1 (RL78_PSW_CY, "cy");
Packit Service 706eca
    }
Packit Service 706eca
  printf ("%s", buf);
Packit Service 706eca
  return buf;
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static unsigned char old_regs[32];
Packit Service 706eca
static int old_psw;
Packit Service 706eca
static int old_sp;
Packit Service 706eca
Packit Service 706eca
int trace_register_words;
Packit Service 706eca
Packit Service 706eca
void
Packit Service 706eca
trace_register_changes (void)
Packit Service 706eca
{
Packit Service 706eca
  int i;
Packit Service 706eca
  int any = 0;
Packit Service 706eca
Packit Service 706eca
  if (!trace)
Packit Service 706eca
    return;
Packit Service 706eca
Packit Service 706eca
#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; }
Packit Service 706eca
#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; }
Packit Service 706eca
Packit Service 706eca
  if (trace_register_words)
Packit Service 706eca
    {
Packit Service 706eca
#define TRW(name, idx) TW (name, memory[REGISTER_ADDRESS + (idx)], old_regs[idx])
Packit Service 706eca
      for (i = 0; i < 32; i += 2)
Packit Service 706eca
	{
Packit Service 706eca
	  char buf[10];
Packit Service 706eca
	  int o, n, a;
Packit Service 706eca
	  switch (i)
Packit Service 706eca
	    {
Packit Service 706eca
	    case 0: strcpy (buf, "AX"); break;
Packit Service 706eca
	    case 2: strcpy (buf, "BC"); break;
Packit Service 706eca
	    case 4: strcpy (buf, "DE"); break;
Packit Service 706eca
	    case 6: strcpy (buf, "HL"); break;
Packit Service 706eca
	    default: sprintf (buf, "r%d", i); break;
Packit Service 706eca
	    }
Packit Service 706eca
	  a = REGISTER_ADDRESS + (i ^ 0x18);
Packit Service 706eca
	  o = old_regs[i ^ 0x18] + old_regs[(i ^ 0x18) + 1] * 256;
Packit Service 706eca
	  n = memory[a] + memory[a + 1] * 256;
Packit Service 706eca
	  TW (buf, n, o);
Packit Service 706eca
	  old_regs[i ^ 0x18] = n;
Packit Service 706eca
	  old_regs[(i ^ 0x18) + 1] = n >> 8;
Packit Service 706eca
	}
Packit Service 706eca
    }
Packit Service 706eca
  else
Packit Service 706eca
    {
Packit Service 706eca
      for (i = 0; i < 32; i ++)
Packit Service 706eca
	{
Packit Service 706eca
	  char buf[10];
Packit Service 706eca
	  if (i < 8)
Packit Service 706eca
	    {
Packit Service 706eca
	      buf[0] = "XACBEDLH"[i];
Packit Service 706eca
	      buf[1] = 0;
Packit Service 706eca
	    }
Packit Service 706eca
	  else
Packit Service 706eca
	    sprintf (buf, "r%d", i);
Packit Service 706eca
#define TRB(name, idx) TB (name, memory[REGISTER_ADDRESS + (idx)], old_regs[idx])
Packit Service 706eca
	  TRB (buf, i ^ 0x18);
Packit Service 706eca
	}
Packit Service 706eca
    }
Packit Service 706eca
  if (memory[RL78_SFR_PSW] != old_psw)
Packit Service 706eca
    {
Packit Service 706eca
      printf ("PSW: \033[31m");
Packit Service 706eca
      psw_string (old_psw);
Packit Service 706eca
      printf (" \033[32m");
Packit Service 706eca
      psw_string (memory[RL78_SFR_PSW]);
Packit Service 706eca
      printf ("\033[0m ");
Packit Service 706eca
      old_psw = memory[RL78_SFR_PSW];
Packit Service 706eca
      any = 1;
Packit Service 706eca
    }
Packit Service 706eca
  TW ("SP", mem_get_hi (RL78_SFR_SP), old_sp);
Packit Service 706eca
  if (any)
Packit Service 706eca
    printf ("\n");
Packit Service 706eca
}
Packit Service 706eca
Packit Service 706eca
static void
Packit Service 706eca
trace_register_init (void)
Packit Service 706eca
{
Packit Service 706eca
  memcpy (old_regs, memory + REGISTER_ADDRESS, 8 * 4);
Packit Service 706eca
  old_psw = memory[RL78_SFR_PSW];
Packit Service 706eca
  old_sp = mem_get_hi (RL78_SFR_SP);
Packit Service 706eca
}