OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [sim/] [m68hc11/] [m68hc11_sim.c] - Diff between revs 834 and 842

Only display areas with differences | Details | Blame | View Log

Rev 834 Rev 842
/* m6811_cpu.c -- 68HC11&68HC12 CPU Emulation
/* m6811_cpu.c -- 68HC11&68HC12 CPU Emulation
   Copyright 1999, 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010
   Copyright 1999, 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
   Written by Stephane Carrez (stcarrez@nerim.fr)
   Written by Stephane Carrez (stcarrez@nerim.fr)
 
 
This file is part of GDB, GAS, and the GNU binutils.
This file is part of GDB, GAS, and the GNU binutils.
 
 
This program is free software; you can redistribute it and/or modify
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
(at your option) any later version.
 
 
This program is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
GNU General Public License for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
#include "sim-main.h"
#include "sim-main.h"
#include "sim-assert.h"
#include "sim-assert.h"
#include "sim-module.h"
#include "sim-module.h"
#include "sim-options.h"
#include "sim-options.h"
 
 
enum {
enum {
  OPTION_CPU_RESET = OPTION_START,
  OPTION_CPU_RESET = OPTION_START,
  OPTION_EMUL_OS,
  OPTION_EMUL_OS,
  OPTION_CPU_CONFIG,
  OPTION_CPU_CONFIG,
  OPTION_CPU_BOOTSTRAP,
  OPTION_CPU_BOOTSTRAP,
  OPTION_CPU_MODE
  OPTION_CPU_MODE
};
};
 
 
static DECLARE_OPTION_HANDLER (cpu_option_handler);
static DECLARE_OPTION_HANDLER (cpu_option_handler);
 
 
static const OPTION cpu_options[] =
static const OPTION cpu_options[] =
{
{
  { {"cpu-reset", no_argument, NULL, OPTION_CPU_RESET },
  { {"cpu-reset", no_argument, NULL, OPTION_CPU_RESET },
      '\0', NULL, "Reset the CPU",
      '\0', NULL, "Reset the CPU",
      cpu_option_handler },
      cpu_option_handler },
 
 
  { {"emulos",    no_argument, NULL, OPTION_EMUL_OS },
  { {"emulos",    no_argument, NULL, OPTION_EMUL_OS },
      '\0', NULL, "Emulate some OS system calls (read, write, ...)",
      '\0', NULL, "Emulate some OS system calls (read, write, ...)",
      cpu_option_handler },
      cpu_option_handler },
 
 
  { {"cpu-config", required_argument, NULL, OPTION_CPU_CONFIG },
  { {"cpu-config", required_argument, NULL, OPTION_CPU_CONFIG },
      '\0', NULL, "Specify the initial CPU configuration register",
      '\0', NULL, "Specify the initial CPU configuration register",
      cpu_option_handler },
      cpu_option_handler },
 
 
  { {"bootstrap", no_argument, NULL, OPTION_CPU_BOOTSTRAP },
  { {"bootstrap", no_argument, NULL, OPTION_CPU_BOOTSTRAP },
      '\0', NULL, "Start the processing in bootstrap mode",
      '\0', NULL, "Start the processing in bootstrap mode",
      cpu_option_handler },
      cpu_option_handler },
 
 
  { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
  { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
};
};
 
 
 
 
static SIM_RC
static SIM_RC
cpu_option_handler (SIM_DESC sd, sim_cpu *cpu,
cpu_option_handler (SIM_DESC sd, sim_cpu *cpu,
                    int opt, char *arg, int is_command)
                    int opt, char *arg, int is_command)
{
{
  int val;
  int val;
 
 
  cpu = STATE_CPU (sd, 0);
  cpu = STATE_CPU (sd, 0);
  switch (opt)
  switch (opt)
    {
    {
    case OPTION_CPU_RESET:
    case OPTION_CPU_RESET:
      sim_board_reset (sd);
      sim_board_reset (sd);
      break;
      break;
 
 
    case OPTION_EMUL_OS:
    case OPTION_EMUL_OS:
      cpu->cpu_emul_syscall = 1;
      cpu->cpu_emul_syscall = 1;
      break;
      break;
 
 
    case OPTION_CPU_CONFIG:
    case OPTION_CPU_CONFIG:
      if (sscanf(arg, "0x%x", &val) == 1
      if (sscanf(arg, "0x%x", &val) == 1
          || sscanf(arg, "%d", &val) == 1)
          || sscanf(arg, "%d", &val) == 1)
        {
        {
          cpu->cpu_config = val;
          cpu->cpu_config = val;
          cpu->cpu_use_local_config = 1;
          cpu->cpu_use_local_config = 1;
        }
        }
      else
      else
        cpu->cpu_use_local_config = 0;
        cpu->cpu_use_local_config = 0;
      break;
      break;
 
 
    case OPTION_CPU_BOOTSTRAP:
    case OPTION_CPU_BOOTSTRAP:
       cpu->cpu_start_mode = "bootstrap";
       cpu->cpu_start_mode = "bootstrap";
       break;
       break;
 
 
    case OPTION_CPU_MODE:
    case OPTION_CPU_MODE:
      break;
      break;
    }
    }
 
 
  return SIM_RC_OK;
  return SIM_RC_OK;
}
}
 
 
 
 
void
void
cpu_call (sim_cpu *cpu, uint16 addr)
cpu_call (sim_cpu *cpu, uint16 addr)
{
{
 
 
  cpu_set_pc (cpu, addr);
  cpu_set_pc (cpu, addr);
}
}
 
 
void
void
cpu_return (sim_cpu *cpu)
cpu_return (sim_cpu *cpu)
{
{
}
}
 
 
/* Set the stack pointer and re-compute the current frame.  */
/* Set the stack pointer and re-compute the current frame.  */
void
void
cpu_set_sp (sim_cpu *cpu, uint16 val)
cpu_set_sp (sim_cpu *cpu, uint16 val)
{
{
  cpu->cpu_regs.sp = val;
  cpu->cpu_regs.sp = val;
}
}
 
 
uint16
uint16
cpu_get_reg (sim_cpu* cpu, uint8 reg)
cpu_get_reg (sim_cpu* cpu, uint8 reg)
{
{
  switch (reg)
  switch (reg)
    {
    {
    case 0:
    case 0:
      return cpu_get_x (cpu);
      return cpu_get_x (cpu);
 
 
    case 1:
    case 1:
      return cpu_get_y (cpu);
      return cpu_get_y (cpu);
 
 
    case 2:
    case 2:
      return cpu_get_sp (cpu);
      return cpu_get_sp (cpu);
 
 
    case 3:
    case 3:
      return cpu_get_pc (cpu);
      return cpu_get_pc (cpu);
 
 
    default:
    default:
      return 0;
      return 0;
    }
    }
}
}
 
 
uint16
uint16
cpu_get_src_reg (sim_cpu* cpu, uint8 reg)
cpu_get_src_reg (sim_cpu* cpu, uint8 reg)
{
{
  switch (reg)
  switch (reg)
    {
    {
    case 0:
    case 0:
      return cpu_get_a (cpu);
      return cpu_get_a (cpu);
 
 
    case 1:
    case 1:
      return cpu_get_b (cpu);
      return cpu_get_b (cpu);
 
 
    case 2:
    case 2:
      return cpu_get_ccr (cpu);
      return cpu_get_ccr (cpu);
 
 
    case 3:
    case 3:
      return cpu_get_tmp3 (cpu);
      return cpu_get_tmp3 (cpu);
 
 
    case 4:
    case 4:
      return cpu_get_d (cpu);
      return cpu_get_d (cpu);
 
 
    case 5:
    case 5:
      return cpu_get_x (cpu);
      return cpu_get_x (cpu);
 
 
    case 6:
    case 6:
      return cpu_get_y (cpu);
      return cpu_get_y (cpu);
 
 
    case 7:
    case 7:
      return cpu_get_sp (cpu);
      return cpu_get_sp (cpu);
 
 
    default:
    default:
      return 0;
      return 0;
    }
    }
}
}
 
 
void
void
cpu_set_dst_reg (sim_cpu* cpu, uint8 reg, uint16 val)
cpu_set_dst_reg (sim_cpu* cpu, uint8 reg, uint16 val)
{
{
  switch (reg)
  switch (reg)
    {
    {
    case 0:
    case 0:
      cpu_set_a (cpu, val);
      cpu_set_a (cpu, val);
      break;
      break;
 
 
    case 1:
    case 1:
      cpu_set_b (cpu, val);
      cpu_set_b (cpu, val);
      break;
      break;
 
 
    case 2:
    case 2:
      cpu_set_ccr (cpu, val);
      cpu_set_ccr (cpu, val);
      break;
      break;
 
 
    case 3:
    case 3:
      cpu_set_tmp2 (cpu, val);
      cpu_set_tmp2 (cpu, val);
      break;
      break;
 
 
    case 4:
    case 4:
      cpu_set_d (cpu, val);
      cpu_set_d (cpu, val);
      break;
      break;
 
 
    case 5:
    case 5:
      cpu_set_x (cpu, val);
      cpu_set_x (cpu, val);
      break;
      break;
 
 
    case 6:
    case 6:
      cpu_set_y (cpu, val);
      cpu_set_y (cpu, val);
      break;
      break;
 
 
    case 7:
    case 7:
      cpu_set_sp (cpu, val);
      cpu_set_sp (cpu, val);
      break;
      break;
 
 
    default:
    default:
      break;
      break;
    }
    }
}
}
 
 
void
void
cpu_set_reg (sim_cpu* cpu, uint8 reg, uint16 val)
cpu_set_reg (sim_cpu* cpu, uint8 reg, uint16 val)
{
{
  switch (reg)
  switch (reg)
    {
    {
    case 0:
    case 0:
      cpu_set_x (cpu, val);
      cpu_set_x (cpu, val);
      break;
      break;
 
 
    case 1:
    case 1:
      cpu_set_y (cpu, val);
      cpu_set_y (cpu, val);
      break;
      break;
 
 
    case 2:
    case 2:
      cpu_set_sp (cpu, val);
      cpu_set_sp (cpu, val);
      break;
      break;
 
 
    case 3:
    case 3:
      cpu_set_pc (cpu, val);
      cpu_set_pc (cpu, val);
      break;
      break;
 
 
    default:
    default:
      break;
      break;
    }
    }
}
}
 
 
/* Returns the address of a 68HC12 indexed operand.
/* Returns the address of a 68HC12 indexed operand.
   Pre and post modifications are handled on the source register.  */
   Pre and post modifications are handled on the source register.  */
uint16
uint16
cpu_get_indexed_operand_addr (sim_cpu* cpu, int restrict)
cpu_get_indexed_operand_addr (sim_cpu* cpu, int restrict)
{
{
  uint8 reg;
  uint8 reg;
  uint16 sval;
  uint16 sval;
  uint16 addr;
  uint16 addr;
  uint8 code;
  uint8 code;
 
 
  code = cpu_fetch8 (cpu);
  code = cpu_fetch8 (cpu);
 
 
  /* n,r with 5-bit signed constant.  */
  /* n,r with 5-bit signed constant.  */
  if ((code & 0x20) == 0)
  if ((code & 0x20) == 0)
    {
    {
      reg = (code >> 6) & 3;
      reg = (code >> 6) & 3;
      sval = (code & 0x1f);
      sval = (code & 0x1f);
      if (code & 0x10)
      if (code & 0x10)
        sval |= 0xfff0;
        sval |= 0xfff0;
 
 
      addr = cpu_get_reg (cpu, reg);
      addr = cpu_get_reg (cpu, reg);
      addr += sval;
      addr += sval;
    }
    }
 
 
  /* Auto pre/post increment/decrement.  */
  /* Auto pre/post increment/decrement.  */
  else if ((code & 0xc0) != 0xc0)
  else if ((code & 0xc0) != 0xc0)
    {
    {
      reg = (code >> 6) & 3;
      reg = (code >> 6) & 3;
      sval = (code & 0x0f);
      sval = (code & 0x0f);
      if (sval & 0x8)
      if (sval & 0x8)
        {
        {
          sval |= 0xfff0;
          sval |= 0xfff0;
        }
        }
      else
      else
        {
        {
          sval = sval + 1;
          sval = sval + 1;
        }
        }
      addr = cpu_get_reg (cpu, reg);
      addr = cpu_get_reg (cpu, reg);
      cpu_set_reg (cpu, reg, addr + sval);
      cpu_set_reg (cpu, reg, addr + sval);
      if ((code & 0x10) == 0)
      if ((code & 0x10) == 0)
        {
        {
          addr += sval;
          addr += sval;
        }
        }
    }
    }
 
 
  /* [n,r] 16-bits offset indexed indirect.  */
  /* [n,r] 16-bits offset indexed indirect.  */
  else if ((code & 0x07) == 3)
  else if ((code & 0x07) == 3)
    {
    {
      if (restrict)
      if (restrict)
        {
        {
          return 0;
          return 0;
        }
        }
      reg = (code >> 3) & 0x03;
      reg = (code >> 3) & 0x03;
      addr = cpu_get_reg (cpu, reg);
      addr = cpu_get_reg (cpu, reg);
      addr += cpu_fetch16 (cpu);
      addr += cpu_fetch16 (cpu);
      addr = memory_read16 (cpu, addr);
      addr = memory_read16 (cpu, addr);
      cpu_add_cycles (cpu, 1);
      cpu_add_cycles (cpu, 1);
    }
    }
  else if ((code & 0x4) == 0)
  else if ((code & 0x4) == 0)
    {
    {
      if (restrict)
      if (restrict)
        {
        {
          return 0;
          return 0;
        }
        }
      reg = (code >> 3) & 0x03;
      reg = (code >> 3) & 0x03;
      addr = cpu_get_reg (cpu, reg);
      addr = cpu_get_reg (cpu, reg);
      if (code & 0x2)
      if (code & 0x2)
        {
        {
          sval = cpu_fetch16 (cpu);
          sval = cpu_fetch16 (cpu);
          cpu_add_cycles (cpu, 1);
          cpu_add_cycles (cpu, 1);
        }
        }
      else
      else
        {
        {
          sval = cpu_fetch8 (cpu);
          sval = cpu_fetch8 (cpu);
          if (code & 0x1)
          if (code & 0x1)
            sval |= 0xff00;
            sval |= 0xff00;
          cpu_add_cycles (cpu, 1);
          cpu_add_cycles (cpu, 1);
        }
        }
      addr += sval;
      addr += sval;
    }
    }
  else
  else
    {
    {
      reg = (code >> 3) & 0x03;
      reg = (code >> 3) & 0x03;
      addr = cpu_get_reg (cpu, reg);
      addr = cpu_get_reg (cpu, reg);
      switch (code & 3)
      switch (code & 3)
        {
        {
        case 0:
        case 0:
          addr += cpu_get_a (cpu);
          addr += cpu_get_a (cpu);
          break;
          break;
        case 1:
        case 1:
          addr += cpu_get_b (cpu);
          addr += cpu_get_b (cpu);
          break;
          break;
        case 2:
        case 2:
          addr += cpu_get_d (cpu);
          addr += cpu_get_d (cpu);
          break;
          break;
        case 3:
        case 3:
        default:
        default:
          addr += cpu_get_d (cpu);
          addr += cpu_get_d (cpu);
          addr = memory_read16 (cpu, addr);
          addr = memory_read16 (cpu, addr);
          cpu_add_cycles (cpu, 1);
          cpu_add_cycles (cpu, 1);
          break;
          break;
        }
        }
    }
    }
 
 
  return addr;
  return addr;
}
}
 
 
uint8
uint8
cpu_get_indexed_operand8 (sim_cpu* cpu, int restrict)
cpu_get_indexed_operand8 (sim_cpu* cpu, int restrict)
{
{
  uint16 addr;
  uint16 addr;
 
 
  addr = cpu_get_indexed_operand_addr (cpu, restrict);
  addr = cpu_get_indexed_operand_addr (cpu, restrict);
  return memory_read8 (cpu, addr);
  return memory_read8 (cpu, addr);
}
}
 
 
uint16
uint16
cpu_get_indexed_operand16 (sim_cpu* cpu, int restrict)
cpu_get_indexed_operand16 (sim_cpu* cpu, int restrict)
{
{
  uint16 addr;
  uint16 addr;
 
 
  addr = cpu_get_indexed_operand_addr (cpu, restrict);
  addr = cpu_get_indexed_operand_addr (cpu, restrict);
  return memory_read16 (cpu, addr);
  return memory_read16 (cpu, addr);
}
}
 
 
void
void
cpu_move8 (sim_cpu *cpu, uint8 code)
cpu_move8 (sim_cpu *cpu, uint8 code)
{
{
  uint8 src;
  uint8 src;
  uint16 addr;
  uint16 addr;
 
 
  switch (code)
  switch (code)
    {
    {
    case 0x0b:
    case 0x0b:
      src = cpu_fetch8 (cpu);
      src = cpu_fetch8 (cpu);
      addr = cpu_fetch16 (cpu);
      addr = cpu_fetch16 (cpu);
      break;
      break;
 
 
    case 0x08:
    case 0x08:
      addr = cpu_get_indexed_operand_addr (cpu, 1);
      addr = cpu_get_indexed_operand_addr (cpu, 1);
      src = cpu_fetch8 (cpu);
      src = cpu_fetch8 (cpu);
      break;
      break;
 
 
    case 0x0c:
    case 0x0c:
      addr = cpu_fetch16 (cpu);
      addr = cpu_fetch16 (cpu);
      src = memory_read8 (cpu, addr);
      src = memory_read8 (cpu, addr);
      addr = cpu_fetch16 (cpu);
      addr = cpu_fetch16 (cpu);
      break;
      break;
 
 
    case 0x09:
    case 0x09:
      addr = cpu_get_indexed_operand_addr (cpu, 1);
      addr = cpu_get_indexed_operand_addr (cpu, 1);
      src = memory_read8 (cpu, cpu_fetch16 (cpu));
      src = memory_read8 (cpu, cpu_fetch16 (cpu));
      break;
      break;
 
 
    case 0x0d:
    case 0x0d:
      src = cpu_get_indexed_operand8 (cpu, 1);
      src = cpu_get_indexed_operand8 (cpu, 1);
      addr = cpu_fetch16 (cpu);
      addr = cpu_fetch16 (cpu);
      break;
      break;
 
 
    case 0x0a:
    case 0x0a:
      src = cpu_get_indexed_operand8 (cpu, 1);
      src = cpu_get_indexed_operand8 (cpu, 1);
      addr = cpu_get_indexed_operand_addr (cpu, 1);
      addr = cpu_get_indexed_operand_addr (cpu, 1);
      break;
      break;
 
 
    default:
    default:
      sim_engine_abort (CPU_STATE (cpu), cpu, 0,
      sim_engine_abort (CPU_STATE (cpu), cpu, 0,
                        "Invalid code 0x%0x -- internal error?", code);
                        "Invalid code 0x%0x -- internal error?", code);
      return;
      return;
    }
    }
  memory_write8 (cpu, addr, src);
  memory_write8 (cpu, addr, src);
}
}
 
 
void
void
cpu_move16 (sim_cpu *cpu, uint8 code)
cpu_move16 (sim_cpu *cpu, uint8 code)
{
{
  uint16 src;
  uint16 src;
  uint16 addr;
  uint16 addr;
 
 
  switch (code)
  switch (code)
    {
    {
    case 0x03:
    case 0x03:
      src = cpu_fetch16 (cpu);
      src = cpu_fetch16 (cpu);
      addr = cpu_fetch16 (cpu);
      addr = cpu_fetch16 (cpu);
      break;
      break;
 
 
    case 0x00:
    case 0x00:
      addr = cpu_get_indexed_operand_addr (cpu, 1);
      addr = cpu_get_indexed_operand_addr (cpu, 1);
      src = cpu_fetch16 (cpu);
      src = cpu_fetch16 (cpu);
      break;
      break;
 
 
    case 0x04:
    case 0x04:
      addr = cpu_fetch16 (cpu);
      addr = cpu_fetch16 (cpu);
      src = memory_read16 (cpu, addr);
      src = memory_read16 (cpu, addr);
      addr = cpu_fetch16 (cpu);
      addr = cpu_fetch16 (cpu);
      break;
      break;
 
 
    case 0x01:
    case 0x01:
      addr = cpu_get_indexed_operand_addr (cpu, 1);
      addr = cpu_get_indexed_operand_addr (cpu, 1);
      src = memory_read16 (cpu, cpu_fetch16 (cpu));
      src = memory_read16 (cpu, cpu_fetch16 (cpu));
      break;
      break;
 
 
    case 0x05:
    case 0x05:
      src = cpu_get_indexed_operand16 (cpu, 1);
      src = cpu_get_indexed_operand16 (cpu, 1);
      addr = cpu_fetch16 (cpu);
      addr = cpu_fetch16 (cpu);
      break;
      break;
 
 
    case 0x02:
    case 0x02:
      src = cpu_get_indexed_operand16 (cpu, 1);
      src = cpu_get_indexed_operand16 (cpu, 1);
      addr = cpu_get_indexed_operand_addr (cpu, 1);
      addr = cpu_get_indexed_operand_addr (cpu, 1);
      break;
      break;
 
 
    default:
    default:
      sim_engine_abort (CPU_STATE (cpu), cpu, 0,
      sim_engine_abort (CPU_STATE (cpu), cpu, 0,
                        "Invalid code 0x%0x -- internal error?", code);
                        "Invalid code 0x%0x -- internal error?", code);
      return;
      return;
    }
    }
  memory_write16 (cpu, addr, src);
  memory_write16 (cpu, addr, src);
}
}
 
 
int
int
cpu_initialize (SIM_DESC sd, sim_cpu *cpu)
cpu_initialize (SIM_DESC sd, sim_cpu *cpu)
{
{
  sim_add_option_table (sd, 0, cpu_options);
  sim_add_option_table (sd, 0, cpu_options);
 
 
  memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
  memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
 
 
  cpu->cpu_absolute_cycle = 0;
  cpu->cpu_absolute_cycle = 0;
  cpu->cpu_current_cycle  = 0;
  cpu->cpu_current_cycle  = 0;
  cpu->cpu_emul_syscall   = 1;
  cpu->cpu_emul_syscall   = 1;
  cpu->cpu_running        = 1;
  cpu->cpu_running        = 1;
  cpu->cpu_stop_on_interrupt = 0;
  cpu->cpu_stop_on_interrupt = 0;
  cpu->cpu_frequency = 8 * 1000 * 1000;
  cpu->cpu_frequency = 8 * 1000 * 1000;
  cpu->cpu_use_elf_start = 0;
  cpu->cpu_use_elf_start = 0;
  cpu->cpu_elf_start     = 0;
  cpu->cpu_elf_start     = 0;
  cpu->cpu_use_local_config = 0;
  cpu->cpu_use_local_config = 0;
  cpu->bank_start = 0;
  cpu->bank_start = 0;
  cpu->bank_end   = 0;
  cpu->bank_end   = 0;
  cpu->bank_shift = 0;
  cpu->bank_shift = 0;
  cpu->cpu_config        = M6811_NOSEC | M6811_NOCOP | M6811_ROMON |
  cpu->cpu_config        = M6811_NOSEC | M6811_NOCOP | M6811_ROMON |
    M6811_EEON;
    M6811_EEON;
  interrupts_initialize (sd, cpu);
  interrupts_initialize (sd, cpu);
 
 
  cpu->cpu_is_initialized = 1;
  cpu->cpu_is_initialized = 1;
  return 0;
  return 0;
}
}
 
 
 
 
/* Reinitialize the processor after a reset.  */
/* Reinitialize the processor after a reset.  */
int
int
cpu_reset (sim_cpu *cpu)
cpu_reset (sim_cpu *cpu)
{
{
  /* Initialize the config register.
  /* Initialize the config register.
     It is only initialized at reset time.  */
     It is only initialized at reset time.  */
  memset (cpu->ios, 0, sizeof (cpu->ios));
  memset (cpu->ios, 0, sizeof (cpu->ios));
  if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
  if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
    cpu->ios[M6811_INIT] = 0x1;
    cpu->ios[M6811_INIT] = 0x1;
  else
  else
    cpu->ios[M6811_INIT] = 0;
    cpu->ios[M6811_INIT] = 0;
 
 
  /* Output compare registers set to 0xFFFF.  */
  /* Output compare registers set to 0xFFFF.  */
  cpu->ios[M6811_TOC1_H] = 0xFF;
  cpu->ios[M6811_TOC1_H] = 0xFF;
  cpu->ios[M6811_TOC1_L] = 0xFF;
  cpu->ios[M6811_TOC1_L] = 0xFF;
  cpu->ios[M6811_TOC2_H] = 0xFF;
  cpu->ios[M6811_TOC2_H] = 0xFF;
  cpu->ios[M6811_TOC2_L] = 0xFF;
  cpu->ios[M6811_TOC2_L] = 0xFF;
  cpu->ios[M6811_TOC3_H] = 0xFF;
  cpu->ios[M6811_TOC3_H] = 0xFF;
  cpu->ios[M6811_TOC4_L] = 0xFF;
  cpu->ios[M6811_TOC4_L] = 0xFF;
  cpu->ios[M6811_TOC5_H] = 0xFF;
  cpu->ios[M6811_TOC5_H] = 0xFF;
  cpu->ios[M6811_TOC5_L] = 0xFF;
  cpu->ios[M6811_TOC5_L] = 0xFF;
 
 
  /* Setup the processor registers.  */
  /* Setup the processor registers.  */
  memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
  memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
  cpu->cpu_absolute_cycle = 0;
  cpu->cpu_absolute_cycle = 0;
  cpu->cpu_current_cycle  = 0;
  cpu->cpu_current_cycle  = 0;
  cpu->cpu_is_initialized = 0;
  cpu->cpu_is_initialized = 0;
 
 
  /* Reset interrupts.  */
  /* Reset interrupts.  */
  interrupts_reset (&cpu->cpu_interrupts);
  interrupts_reset (&cpu->cpu_interrupts);
 
 
  /* Reinitialize the CPU operating mode.  */
  /* Reinitialize the CPU operating mode.  */
  cpu->ios[M6811_HPRIO] = cpu->cpu_mode;
  cpu->ios[M6811_HPRIO] = cpu->cpu_mode;
  return 0;
  return 0;
}
}
 
 
/* Reinitialize the processor after a reset.  */
/* Reinitialize the processor after a reset.  */
int
int
cpu_restart (sim_cpu *cpu)
cpu_restart (sim_cpu *cpu)
{
{
  uint16 addr;
  uint16 addr;
 
 
  /* Get CPU starting address depending on the CPU mode.  */
  /* Get CPU starting address depending on the CPU mode.  */
  if (cpu->cpu_use_elf_start == 0)
  if (cpu->cpu_use_elf_start == 0)
    {
    {
      switch ((cpu->ios[M6811_HPRIO]) & (M6811_SMOD | M6811_MDA))
      switch ((cpu->ios[M6811_HPRIO]) & (M6811_SMOD | M6811_MDA))
        {
        {
          /* Single Chip  */
          /* Single Chip  */
        default:
        default:
        case 0 :
        case 0 :
          addr = memory_read16 (cpu, 0xFFFE);
          addr = memory_read16 (cpu, 0xFFFE);
          break;
          break;
 
 
          /* Expanded Multiplexed  */
          /* Expanded Multiplexed  */
        case M6811_MDA:
        case M6811_MDA:
          addr = memory_read16 (cpu, 0xFFFE);
          addr = memory_read16 (cpu, 0xFFFE);
          break;
          break;
 
 
          /* Special Bootstrap  */
          /* Special Bootstrap  */
        case M6811_SMOD:
        case M6811_SMOD:
          addr = 0;
          addr = 0;
          break;
          break;
 
 
          /* Factory Test  */
          /* Factory Test  */
        case M6811_MDA | M6811_SMOD:
        case M6811_MDA | M6811_SMOD:
          addr = memory_read16 (cpu, 0xFFFE);
          addr = memory_read16 (cpu, 0xFFFE);
          break;
          break;
        }
        }
    }
    }
  else
  else
    {
    {
      addr = cpu->cpu_elf_start;
      addr = cpu->cpu_elf_start;
    }
    }
 
 
  /* Setup the processor registers.  */
  /* Setup the processor registers.  */
  cpu->cpu_insn_pc  = addr;
  cpu->cpu_insn_pc  = addr;
  cpu->cpu_regs.pc  = addr;
  cpu->cpu_regs.pc  = addr;
  cpu->cpu_regs.ccr = M6811_X_BIT | M6811_I_BIT | M6811_S_BIT;
  cpu->cpu_regs.ccr = M6811_X_BIT | M6811_I_BIT | M6811_S_BIT;
  cpu->cpu_absolute_cycle = 0;
  cpu->cpu_absolute_cycle = 0;
  cpu->cpu_is_initialized = 1;
  cpu->cpu_is_initialized = 1;
  cpu->cpu_current_cycle  = 0;
  cpu->cpu_current_cycle  = 0;
 
 
  cpu_call (cpu, addr);
  cpu_call (cpu, addr);
 
 
  return 0;
  return 0;
}
}
 
 
void
void
print_io_reg_desc (SIM_DESC sd, io_reg_desc *desc, int val, int mode)
print_io_reg_desc (SIM_DESC sd, io_reg_desc *desc, int val, int mode)
{
{
  while (desc->mask)
  while (desc->mask)
    {
    {
      if (val & desc->mask)
      if (val & desc->mask)
        sim_io_printf (sd, "%s",
        sim_io_printf (sd, "%s",
                       mode == 0 ? desc->short_name : desc->long_name);
                       mode == 0 ? desc->short_name : desc->long_name);
      desc++;
      desc++;
    }
    }
}
}
 
 
void
void
print_io_byte (SIM_DESC sd, const char *name, io_reg_desc *desc,
print_io_byte (SIM_DESC sd, const char *name, io_reg_desc *desc,
               uint8 val, uint16 addr)
               uint8 val, uint16 addr)
{
{
  sim_io_printf (sd, "  %-9.9s @ 0x%04x 0x%02x ", name, addr, val);
  sim_io_printf (sd, "  %-9.9s @ 0x%04x 0x%02x ", name, addr, val);
  if (desc)
  if (desc)
    print_io_reg_desc (sd, desc, val, 0);
    print_io_reg_desc (sd, desc, val, 0);
}
}
 
 
void
void
print_io_word (SIM_DESC sd, const char *name, io_reg_desc *desc,
print_io_word (SIM_DESC sd, const char *name, io_reg_desc *desc,
               uint16 val, uint16 addr)
               uint16 val, uint16 addr)
{
{
  sim_io_printf (sd, "  %-9.9s @ 0x%04x 0x%04x ", name, addr, val);
  sim_io_printf (sd, "  %-9.9s @ 0x%04x 0x%04x ", name, addr, val);
  if (desc)
  if (desc)
    print_io_reg_desc (sd, desc, val, 0);
    print_io_reg_desc (sd, desc, val, 0);
}
}
 
 
void
void
cpu_ccr_update_tst8 (sim_cpu *proc, uint8 val)
cpu_ccr_update_tst8 (sim_cpu *proc, uint8 val)
{
{
  cpu_set_ccr_V (proc, 0);
  cpu_set_ccr_V (proc, 0);
  cpu_set_ccr_N (proc, val & 0x80 ? 1 : 0);
  cpu_set_ccr_N (proc, val & 0x80 ? 1 : 0);
  cpu_set_ccr_Z (proc, val == 0 ? 1 : 0);
  cpu_set_ccr_Z (proc, val == 0 ? 1 : 0);
}
}
 
 
 
 
uint16
uint16
cpu_fetch_relbranch (sim_cpu *cpu)
cpu_fetch_relbranch (sim_cpu *cpu)
{
{
  uint16 addr = (uint16) cpu_fetch8 (cpu);
  uint16 addr = (uint16) cpu_fetch8 (cpu);
 
 
  if (addr & 0x0080)
  if (addr & 0x0080)
    {
    {
      addr |= 0xFF00;
      addr |= 0xFF00;
    }
    }
  addr += cpu->cpu_regs.pc;
  addr += cpu->cpu_regs.pc;
  return addr;
  return addr;
}
}
 
 
uint16
uint16
cpu_fetch_relbranch16 (sim_cpu *cpu)
cpu_fetch_relbranch16 (sim_cpu *cpu)
{
{
  uint16 addr = cpu_fetch16 (cpu);
  uint16 addr = cpu_fetch16 (cpu);
 
 
  addr += cpu->cpu_regs.pc;
  addr += cpu->cpu_regs.pc;
  return addr;
  return addr;
}
}
 
 
/* Push all the CPU registers (when an interruption occurs).  */
/* Push all the CPU registers (when an interruption occurs).  */
void
void
cpu_push_all (sim_cpu *cpu)
cpu_push_all (sim_cpu *cpu)
{
{
  if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
  if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
    {
    {
      cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.pc);
      cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.pc);
      cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.iy);
      cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.iy);
      cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.ix);
      cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.ix);
      cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.d);
      cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.d);
      cpu_m68hc11_push_uint8 (cpu, cpu->cpu_regs.ccr);
      cpu_m68hc11_push_uint8 (cpu, cpu->cpu_regs.ccr);
    }
    }
  else
  else
    {
    {
      cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.pc);
      cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.pc);
      cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.iy);
      cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.iy);
      cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.ix);
      cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.ix);
      cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.d);
      cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.d);
      cpu_m68hc12_push_uint8 (cpu, cpu->cpu_regs.ccr);
      cpu_m68hc12_push_uint8 (cpu, cpu->cpu_regs.ccr);
    }
    }
}
}
 
 
/* Simulation of the dbcc/ibcc/tbcc 68HC12 conditional branch operations.  */
/* Simulation of the dbcc/ibcc/tbcc 68HC12 conditional branch operations.  */
void
void
cpu_dbcc (sim_cpu* cpu)
cpu_dbcc (sim_cpu* cpu)
{
{
  uint8 code;
  uint8 code;
  uint16 addr;
  uint16 addr;
  uint16 inc;
  uint16 inc;
  uint16 reg;
  uint16 reg;
 
 
  code = cpu_fetch8 (cpu);
  code = cpu_fetch8 (cpu);
  switch (code & 0xc0)
  switch (code & 0xc0)
    {
    {
    case 0x80: /* ibcc */
    case 0x80: /* ibcc */
      inc = 1;
      inc = 1;
      break;
      break;
    case 0x40: /* tbcc */
    case 0x40: /* tbcc */
      inc = 0;
      inc = 0;
      break;
      break;
    case 0:    /* dbcc */
    case 0:    /* dbcc */
      inc = -1;
      inc = -1;
      break;
      break;
    default:
    default:
      abort ();
      abort ();
      break;
      break;
    }
    }
 
 
  addr = cpu_fetch8 (cpu);
  addr = cpu_fetch8 (cpu);
  if (code & 0x10)
  if (code & 0x10)
    addr |= 0xff00;
    addr |= 0xff00;
 
 
  addr += cpu_get_pc (cpu);
  addr += cpu_get_pc (cpu);
  reg = cpu_get_src_reg (cpu, code & 0x07);
  reg = cpu_get_src_reg (cpu, code & 0x07);
  reg += inc;
  reg += inc;
 
 
  /* Branch according to register value.  */
  /* Branch according to register value.  */
  if ((reg != 0 && (code & 0x20)) || (reg == 0 && !(code & 0x20)))
  if ((reg != 0 && (code & 0x20)) || (reg == 0 && !(code & 0x20)))
    {
    {
      cpu_set_pc (cpu, addr);
      cpu_set_pc (cpu, addr);
    }
    }
  cpu_set_dst_reg (cpu, code & 0x07, reg);
  cpu_set_dst_reg (cpu, code & 0x07, reg);
}
}
 
 
void
void
cpu_exg (sim_cpu* cpu, uint8 code)
cpu_exg (sim_cpu* cpu, uint8 code)
{
{
  uint8 r1, r2;
  uint8 r1, r2;
  uint16 src1;
  uint16 src1;
  uint16 src2;
  uint16 src2;
 
 
  r1 = (code >> 4) & 0x07;
  r1 = (code >> 4) & 0x07;
  r2 = code & 0x07;
  r2 = code & 0x07;
  if (code & 0x80)
  if (code & 0x80)
    {
    {
      src1 = cpu_get_src_reg (cpu, r1);
      src1 = cpu_get_src_reg (cpu, r1);
      src2 = cpu_get_src_reg (cpu, r2);
      src2 = cpu_get_src_reg (cpu, r2);
      if (r2 == 1 || r2 == 2)
      if (r2 == 1 || r2 == 2)
        src2 |= 0xff00;
        src2 |= 0xff00;
 
 
      cpu_set_dst_reg (cpu, r2, src1);
      cpu_set_dst_reg (cpu, r2, src1);
      cpu_set_dst_reg (cpu, r1, src2);
      cpu_set_dst_reg (cpu, r1, src2);
    }
    }
  else
  else
    {
    {
      src1 = cpu_get_src_reg (cpu, r1);
      src1 = cpu_get_src_reg (cpu, r1);
 
 
      /* Sign extend the 8-bit registers (A, B, CCR).  */
      /* Sign extend the 8-bit registers (A, B, CCR).  */
      if ((r1 == 0 || r1 == 1 || r1 == 2) && (src1 & 0x80))
      if ((r1 == 0 || r1 == 1 || r1 == 2) && (src1 & 0x80))
        src1 |= 0xff00;
        src1 |= 0xff00;
 
 
      cpu_set_dst_reg (cpu, r2, src1);
      cpu_set_dst_reg (cpu, r2, src1);
    }
    }
}
}
 
 
/* Handle special instructions.  */
/* Handle special instructions.  */
void
void
cpu_special (sim_cpu *cpu, enum M6811_Special special)
cpu_special (sim_cpu *cpu, enum M6811_Special special)
{
{
  switch (special)
  switch (special)
    {
    {
    case M6811_RTI:
    case M6811_RTI:
      {
      {
        uint8 ccr;
        uint8 ccr;
 
 
        ccr = cpu_m68hc11_pop_uint8 (cpu);
        ccr = cpu_m68hc11_pop_uint8 (cpu);
        cpu_set_ccr (cpu, ccr);
        cpu_set_ccr (cpu, ccr);
        cpu_set_d (cpu, cpu_m68hc11_pop_uint16 (cpu));
        cpu_set_d (cpu, cpu_m68hc11_pop_uint16 (cpu));
        cpu_set_x (cpu, cpu_m68hc11_pop_uint16 (cpu));
        cpu_set_x (cpu, cpu_m68hc11_pop_uint16 (cpu));
        cpu_set_y (cpu, cpu_m68hc11_pop_uint16 (cpu));
        cpu_set_y (cpu, cpu_m68hc11_pop_uint16 (cpu));
        cpu_set_pc (cpu, cpu_m68hc11_pop_uint16 (cpu));
        cpu_set_pc (cpu, cpu_m68hc11_pop_uint16 (cpu));
        cpu_return (cpu);
        cpu_return (cpu);
        break;
        break;
      }
      }
 
 
    case M6812_RTI:
    case M6812_RTI:
      {
      {
        uint8 ccr;
        uint8 ccr;
 
 
        ccr = cpu_m68hc12_pop_uint8 (cpu);
        ccr = cpu_m68hc12_pop_uint8 (cpu);
        cpu_set_ccr (cpu, ccr);
        cpu_set_ccr (cpu, ccr);
        cpu_set_d (cpu, cpu_m68hc12_pop_uint16 (cpu));
        cpu_set_d (cpu, cpu_m68hc12_pop_uint16 (cpu));
        cpu_set_x (cpu, cpu_m68hc12_pop_uint16 (cpu));
        cpu_set_x (cpu, cpu_m68hc12_pop_uint16 (cpu));
        cpu_set_y (cpu, cpu_m68hc12_pop_uint16 (cpu));
        cpu_set_y (cpu, cpu_m68hc12_pop_uint16 (cpu));
        cpu_set_pc (cpu, cpu_m68hc12_pop_uint16 (cpu));
        cpu_set_pc (cpu, cpu_m68hc12_pop_uint16 (cpu));
        cpu_return (cpu);
        cpu_return (cpu);
        break;
        break;
      }
      }
 
 
    case M6811_WAI:
    case M6811_WAI:
      /* In the ELF-start mode, we are in a special mode where
      /* In the ELF-start mode, we are in a special mode where
         the WAI corresponds to an exit.  */
         the WAI corresponds to an exit.  */
      if (cpu->cpu_use_elf_start)
      if (cpu->cpu_use_elf_start)
        {
        {
          cpu_set_pc (cpu, cpu->cpu_insn_pc);
          cpu_set_pc (cpu, cpu->cpu_insn_pc);
          sim_engine_halt (CPU_STATE (cpu), cpu,
          sim_engine_halt (CPU_STATE (cpu), cpu,
                           NULL, NULL_CIA, sim_exited,
                           NULL, NULL_CIA, sim_exited,
                           cpu_get_d (cpu));
                           cpu_get_d (cpu));
          return;
          return;
        }
        }
      /* SCz: not correct... */
      /* SCz: not correct... */
      cpu_push_all (cpu);
      cpu_push_all (cpu);
      break;
      break;
 
 
    case M6811_SWI:
    case M6811_SWI:
      interrupts_raise (&cpu->cpu_interrupts, M6811_INT_SWI);
      interrupts_raise (&cpu->cpu_interrupts, M6811_INT_SWI);
      interrupts_process (&cpu->cpu_interrupts);
      interrupts_process (&cpu->cpu_interrupts);
      break;
      break;
 
 
    case M6811_EMUL_SYSCALL:
    case M6811_EMUL_SYSCALL:
    case M6811_ILLEGAL:
    case M6811_ILLEGAL:
      if (cpu->cpu_emul_syscall)
      if (cpu->cpu_emul_syscall)
        {
        {
          uint8 op = memory_read8 (cpu,
          uint8 op = memory_read8 (cpu,
                                   cpu_get_pc (cpu) - 1);
                                   cpu_get_pc (cpu) - 1);
          if (op == 0x41)
          if (op == 0x41)
            {
            {
              cpu_set_pc (cpu, cpu->cpu_insn_pc);
              cpu_set_pc (cpu, cpu->cpu_insn_pc);
              sim_engine_halt (CPU_STATE (cpu), cpu,
              sim_engine_halt (CPU_STATE (cpu), cpu,
                               NULL, NULL_CIA, sim_exited,
                               NULL, NULL_CIA, sim_exited,
                               cpu_get_d (cpu));
                               cpu_get_d (cpu));
              return;
              return;
            }
            }
          else
          else
            {
            {
              emul_os (op, cpu);
              emul_os (op, cpu);
            }
            }
          return;
          return;
        }
        }
 
 
      interrupts_raise (&cpu->cpu_interrupts, M6811_INT_ILLEGAL);
      interrupts_raise (&cpu->cpu_interrupts, M6811_INT_ILLEGAL);
      interrupts_process (&cpu->cpu_interrupts);
      interrupts_process (&cpu->cpu_interrupts);
      break;
      break;
 
 
    case M6811_TEST:
    case M6811_TEST:
    case M6812_BGND:
    case M6812_BGND:
      {
      {
        SIM_DESC sd;
        SIM_DESC sd;
 
 
        sd = CPU_STATE (cpu);
        sd = CPU_STATE (cpu);
 
 
        /* Breakpoint instruction if we are under gdb.  */
        /* Breakpoint instruction if we are under gdb.  */
        if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
        if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
          {
          {
            cpu->cpu_regs.pc --;
            cpu->cpu_regs.pc --;
            sim_engine_halt (CPU_STATE (cpu), cpu,
            sim_engine_halt (CPU_STATE (cpu), cpu,
                             0, cpu_get_pc (cpu), sim_stopped,
                             0, cpu_get_pc (cpu), sim_stopped,
                             SIM_SIGTRAP);
                             SIM_SIGTRAP);
          }
          }
        /* else this is a nop but not in test factory mode.  */
        /* else this is a nop but not in test factory mode.  */
        break;
        break;
      }
      }
 
 
    case M6812_IDIVS:
    case M6812_IDIVS:
      {
      {
        int32 src1 = (int16) cpu_get_d (cpu);
        int32 src1 = (int16) cpu_get_d (cpu);
        int32 src2 = (int16) cpu_get_x (cpu);
        int32 src2 = (int16) cpu_get_x (cpu);
 
 
        if (src2 == 0)
        if (src2 == 0)
          {
          {
            cpu_set_ccr_C (cpu, 1);
            cpu_set_ccr_C (cpu, 1);
          }
          }
        else
        else
          {
          {
            cpu_set_d (cpu, src1 % src2);
            cpu_set_d (cpu, src1 % src2);
            src1 = src1 / src2;
            src1 = src1 / src2;
            cpu_set_x (cpu, src1);
            cpu_set_x (cpu, src1);
            cpu_set_ccr_C (cpu, 0);
            cpu_set_ccr_C (cpu, 0);
            cpu_set_ccr_Z (cpu, src1 == 0);
            cpu_set_ccr_Z (cpu, src1 == 0);
            cpu_set_ccr_N (cpu, src1 & 0x8000);
            cpu_set_ccr_N (cpu, src1 & 0x8000);
            cpu_set_ccr_V (cpu, src1 >= 32768 || src1 < -32768);
            cpu_set_ccr_V (cpu, src1 >= 32768 || src1 < -32768);
          }
          }
      }
      }
      break;
      break;
 
 
    case M6812_EDIV:
    case M6812_EDIV:
      {
      {
        uint32 src1 = (uint32) cpu_get_x (cpu);
        uint32 src1 = (uint32) cpu_get_x (cpu);
        uint32 src2 = (uint32) (cpu_get_y (cpu) << 16)
        uint32 src2 = (uint32) (cpu_get_y (cpu) << 16)
          | (uint32) (cpu_get_d (cpu));
          | (uint32) (cpu_get_d (cpu));
 
 
        if (src1 == 0)
        if (src1 == 0)
          {
          {
            cpu_set_ccr_C (cpu, 1);
            cpu_set_ccr_C (cpu, 1);
          }
          }
        else
        else
          {
          {
            cpu_set_ccr_C (cpu, 0);
            cpu_set_ccr_C (cpu, 0);
            cpu_set_d (cpu, src2 % src1);
            cpu_set_d (cpu, src2 % src1);
            src2 = src2 / src1;
            src2 = src2 / src1;
            cpu_set_y (cpu, src2);
            cpu_set_y (cpu, src2);
            cpu_set_ccr_Z (cpu, src2 == 0);
            cpu_set_ccr_Z (cpu, src2 == 0);
            cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
            cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
            cpu_set_ccr_V (cpu, (src2 & 0xffff0000) != 0);
            cpu_set_ccr_V (cpu, (src2 & 0xffff0000) != 0);
          }
          }
      }
      }
      break;
      break;
 
 
    case M6812_EDIVS:
    case M6812_EDIVS:
      {
      {
        int32 src1 = (int16) cpu_get_x (cpu);
        int32 src1 = (int16) cpu_get_x (cpu);
        int32 src2 = (uint32) (cpu_get_y (cpu) << 16)
        int32 src2 = (uint32) (cpu_get_y (cpu) << 16)
          | (uint32) (cpu_get_d (cpu));
          | (uint32) (cpu_get_d (cpu));
 
 
        if (src1 == 0)
        if (src1 == 0)
          {
          {
            cpu_set_ccr_C (cpu, 1);
            cpu_set_ccr_C (cpu, 1);
          }
          }
        else
        else
          {
          {
            cpu_set_ccr_C (cpu, 0);
            cpu_set_ccr_C (cpu, 0);
            cpu_set_d (cpu, src2 % src1);
            cpu_set_d (cpu, src2 % src1);
            src2 = src2 / src1;
            src2 = src2 / src1;
            cpu_set_y (cpu, src2);
            cpu_set_y (cpu, src2);
            cpu_set_ccr_Z (cpu, src2 == 0);
            cpu_set_ccr_Z (cpu, src2 == 0);
            cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
            cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
            cpu_set_ccr_V (cpu, src2 > 32767 || src2 < -32768);
            cpu_set_ccr_V (cpu, src2 > 32767 || src2 < -32768);
          }
          }
      }
      }
      break;
      break;
 
 
    case M6812_EMULS:
    case M6812_EMULS:
      {
      {
        int32 src1, src2;
        int32 src1, src2;
 
 
        src1 = (int16) cpu_get_d (cpu);
        src1 = (int16) cpu_get_d (cpu);
        src2 = (int16) cpu_get_y (cpu);
        src2 = (int16) cpu_get_y (cpu);
        src1 = src1 * src2;
        src1 = src1 * src2;
        cpu_set_d (cpu, src1 & 0x0ffff);
        cpu_set_d (cpu, src1 & 0x0ffff);
        cpu_set_y (cpu, src1 >> 16);
        cpu_set_y (cpu, src1 >> 16);
        cpu_set_ccr_Z (cpu, src1 == 0);
        cpu_set_ccr_Z (cpu, src1 == 0);
        cpu_set_ccr_N (cpu, (src1 & 0x80000000) != 0);
        cpu_set_ccr_N (cpu, (src1 & 0x80000000) != 0);
        cpu_set_ccr_C (cpu, (src1 & 0x00008000) != 0);
        cpu_set_ccr_C (cpu, (src1 & 0x00008000) != 0);
      }
      }
      break;
      break;
 
 
    case M6812_EMACS:
    case M6812_EMACS:
      {
      {
        int32 src1, src2;
        int32 src1, src2;
        uint16 addr;
        uint16 addr;
 
 
        addr = cpu_fetch16 (cpu);
        addr = cpu_fetch16 (cpu);
        src1 = (int16) memory_read16 (cpu, cpu_get_x (cpu));
        src1 = (int16) memory_read16 (cpu, cpu_get_x (cpu));
        src2 = (int16) memory_read16 (cpu, cpu_get_y (cpu));
        src2 = (int16) memory_read16 (cpu, cpu_get_y (cpu));
        src1 = src1 * src2;
        src1 = src1 * src2;
        src2 = (((uint32) memory_read16 (cpu, addr)) << 16)
        src2 = (((uint32) memory_read16 (cpu, addr)) << 16)
          | (uint32) memory_read16 (cpu, addr + 2);
          | (uint32) memory_read16 (cpu, addr + 2);
 
 
        memory_write16 (cpu, addr, (src1 + src2) >> 16);
        memory_write16 (cpu, addr, (src1 + src2) >> 16);
        memory_write16 (cpu, addr + 2, (src1 + src2));
        memory_write16 (cpu, addr + 2, (src1 + src2));
 
 
 
 
      }
      }
      break;
      break;
 
 
    case M6812_CALL:
    case M6812_CALL:
      {
      {
        uint8 page;
        uint8 page;
        uint16 addr;
        uint16 addr;
 
 
        addr = cpu_fetch16 (cpu);
        addr = cpu_fetch16 (cpu);
        page = cpu_fetch8 (cpu);
        page = cpu_fetch8 (cpu);
 
 
        cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
        cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
        cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
        cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
 
 
        cpu_set_page (cpu, page);
        cpu_set_page (cpu, page);
        cpu_set_pc (cpu, addr);
        cpu_set_pc (cpu, addr);
      }
      }
      break;
      break;
 
 
    case M6812_CALL_INDIRECT:
    case M6812_CALL_INDIRECT:
      {
      {
        uint8 code;
        uint8 code;
        uint16 addr;
        uint16 addr;
        uint8 page;
        uint8 page;
 
 
        code = memory_read8 (cpu, cpu_get_pc (cpu));
        code = memory_read8 (cpu, cpu_get_pc (cpu));
        /* Indirect addressing call has the page specified in the
        /* Indirect addressing call has the page specified in the
           memory location pointed to by the address.  */
           memory location pointed to by the address.  */
        if ((code & 0xE3) == 0xE3)
        if ((code & 0xE3) == 0xE3)
          {
          {
            addr = cpu_get_indexed_operand_addr (cpu, 0);
            addr = cpu_get_indexed_operand_addr (cpu, 0);
            page = memory_read8 (cpu, addr + 2);
            page = memory_read8 (cpu, addr + 2);
            addr = memory_read16 (cpu, addr);
            addr = memory_read16 (cpu, addr);
          }
          }
        else
        else
          {
          {
            /* Otherwise, page is in the opcode.  */
            /* Otherwise, page is in the opcode.  */
            addr = cpu_get_indexed_operand16 (cpu, 0);
            addr = cpu_get_indexed_operand16 (cpu, 0);
            page = cpu_fetch8 (cpu);
            page = cpu_fetch8 (cpu);
          }
          }
        cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
        cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
        cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
        cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
        cpu_set_page (cpu, page);
        cpu_set_page (cpu, page);
        cpu_set_pc (cpu, addr);
        cpu_set_pc (cpu, addr);
      }
      }
      break;
      break;
 
 
    case M6812_RTC:
    case M6812_RTC:
      {
      {
        uint8 page = cpu_m68hc12_pop_uint8 (cpu);
        uint8 page = cpu_m68hc12_pop_uint8 (cpu);
        uint16 addr = cpu_m68hc12_pop_uint16 (cpu);
        uint16 addr = cpu_m68hc12_pop_uint16 (cpu);
 
 
        cpu_set_page (cpu, page);
        cpu_set_page (cpu, page);
        cpu_set_pc (cpu, addr);
        cpu_set_pc (cpu, addr);
      }
      }
      break;
      break;
 
 
    case M6812_ETBL:
    case M6812_ETBL:
    default:
    default:
      sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
      sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
                       cpu_get_pc (cpu), sim_stopped,
                       cpu_get_pc (cpu), sim_stopped,
                       SIM_SIGILL);
                       SIM_SIGILL);
      break;
      break;
    }
    }
}
}
 
 
 
 
void
void
cpu_single_step (sim_cpu *cpu)
cpu_single_step (sim_cpu *cpu)
{
{
  cpu->cpu_current_cycle = 0;
  cpu->cpu_current_cycle = 0;
  cpu->cpu_insn_pc = cpu_get_pc (cpu);
  cpu->cpu_insn_pc = cpu_get_pc (cpu);
 
 
  /* Handle the pending interrupts.  If an interrupt is handled,
  /* Handle the pending interrupts.  If an interrupt is handled,
     treat this as an single step.  */
     treat this as an single step.  */
  if (interrupts_process (&cpu->cpu_interrupts))
  if (interrupts_process (&cpu->cpu_interrupts))
    {
    {
      cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
      cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
      return;
      return;
    }
    }
 
 
  /*  printf("PC = 0x%04x\n", cpu_get_pc (cpu));*/
  /*  printf("PC = 0x%04x\n", cpu_get_pc (cpu));*/
  cpu->cpu_interpretor (cpu);
  cpu->cpu_interpretor (cpu);
  cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
  cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
}
}
 
 
/* VARARGS */
/* VARARGS */
void
void
sim_memory_error (sim_cpu *cpu, SIM_SIGNAL excep,
sim_memory_error (sim_cpu *cpu, SIM_SIGNAL excep,
                  uint16 addr, const char *message, ...)
                  uint16 addr, const char *message, ...)
{
{
  char buf[1024];
  char buf[1024];
  va_list args;
  va_list args;
 
 
  va_start (args, message);
  va_start (args, message);
  vsprintf (buf, message, args);
  vsprintf (buf, message, args);
  va_end (args);
  va_end (args);
 
 
  sim_io_printf (CPU_STATE (cpu), "%s\n", buf);
  sim_io_printf (CPU_STATE (cpu), "%s\n", buf);
  cpu_memory_exception (cpu, excep, addr, buf);
  cpu_memory_exception (cpu, excep, addr, buf);
}
}
 
 
 
 
void
void
cpu_memory_exception (sim_cpu *cpu, SIM_SIGNAL excep,
cpu_memory_exception (sim_cpu *cpu, SIM_SIGNAL excep,
                      uint16 addr, const char *message)
                      uint16 addr, const char *message)
{
{
  if (cpu->cpu_running == 0)
  if (cpu->cpu_running == 0)
    return;
    return;
 
 
  cpu_set_pc (cpu, cpu->cpu_insn_pc);
  cpu_set_pc (cpu, cpu->cpu_insn_pc);
  sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
  sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
                   cpu_get_pc (cpu), sim_stopped, excep);
                   cpu_get_pc (cpu), sim_stopped, excep);
 
 
#if 0
#if 0
  cpu->mem_exception = excep;
  cpu->mem_exception = excep;
  cpu->fault_addr    = addr;
  cpu->fault_addr    = addr;
  cpu->fault_msg     = strdup (message);
  cpu->fault_msg     = strdup (message);
 
 
  if (cpu->cpu_use_handler)
  if (cpu->cpu_use_handler)
    {
    {
      longjmp (&cpu->cpu_exception_handler, 1);
      longjmp (&cpu->cpu_exception_handler, 1);
    }
    }
  (* cpu->callback->printf_filtered)
  (* cpu->callback->printf_filtered)
    (cpu->callback, "Fault at 0x%04x: %s\n", addr, message);
    (cpu->callback, "Fault at 0x%04x: %s\n", addr, message);
#endif
#endif
}
}
 
 
void
void
cpu_info (SIM_DESC sd, sim_cpu *cpu)
cpu_info (SIM_DESC sd, sim_cpu *cpu)
{
{
  sim_io_printf (sd, "CPU info:\n");
  sim_io_printf (sd, "CPU info:\n");
  sim_io_printf (sd, "  Absolute cycle: %s\n",
  sim_io_printf (sd, "  Absolute cycle: %s\n",
                 cycle_to_string (cpu, cpu->cpu_absolute_cycle,
                 cycle_to_string (cpu, cpu->cpu_absolute_cycle,
                                  PRINT_TIME | PRINT_CYCLE));
                                  PRINT_TIME | PRINT_CYCLE));
 
 
  sim_io_printf (sd, "  Syscall emulation: %s\n",
  sim_io_printf (sd, "  Syscall emulation: %s\n",
                 cpu->cpu_emul_syscall ? "yes, via 0xcd <n>" : "no");
                 cpu->cpu_emul_syscall ? "yes, via 0xcd <n>" : "no");
  sim_io_printf (sd, "  Memory errors detection: %s\n",
  sim_io_printf (sd, "  Memory errors detection: %s\n",
                 cpu->cpu_check_memory ? "yes" : "no");
                 cpu->cpu_check_memory ? "yes" : "no");
  sim_io_printf (sd, "  Stop on interrupt: %s\n",
  sim_io_printf (sd, "  Stop on interrupt: %s\n",
                 cpu->cpu_stop_on_interrupt ? "yes" : "no");
                 cpu->cpu_stop_on_interrupt ? "yes" : "no");
}
}
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.