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

Subversion Repositories openrisc

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

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 834 Rev 842
/* Simulator for Atmel's AVR core.
/* Simulator for Atmel's AVR core.
   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
   Written by Tristan Gingold, AdaCore.
   Written by Tristan Gingold, AdaCore.
 
 
   This file is part of GDB, the GNU debugger.
   This file is part of GDB, the GNU debugger.
 
 
   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 "config.h"
#include "config.h"
 
 
#ifdef HAVE_STRING_H
#ifdef HAVE_STRING_H
#include <string.h>
#include <string.h>
#endif
#endif
#include "bfd.h"
#include "bfd.h"
#include "gdb/callback.h"
#include "gdb/callback.h"
#include "gdb/signals.h"
#include "gdb/signals.h"
#include "libiberty.h"
#include "libiberty.h"
#include "gdb/remote-sim.h"
#include "gdb/remote-sim.h"
#include "dis-asm.h"
#include "dis-asm.h"
#include "sim-utils.h"
#include "sim-utils.h"
 
 
/* As AVR is a 8/16 bits processor, define handy types.  */
/* As AVR is a 8/16 bits processor, define handy types.  */
typedef unsigned short int word;
typedef unsigned short int word;
typedef signed short int sword;
typedef signed short int sword;
typedef unsigned char byte;
typedef unsigned char byte;
typedef signed char sbyte;
typedef signed char sbyte;
 
 
/* Debug flag to display instructions and registers.  */
/* Debug flag to display instructions and registers.  */
static int tracing = 0;
static int tracing = 0;
static int lock_step = 0;
static int lock_step = 0;
static int verbose;
static int verbose;
 
 
/* The only real register.  */
/* The only real register.  */
static unsigned int pc;
static unsigned int pc;
 
 
/* We update a cycle counter.  */
/* We update a cycle counter.  */
static unsigned int cycles = 0;
static unsigned int cycles = 0;
 
 
/* If true, the pc needs more than 2 bytes.  */
/* If true, the pc needs more than 2 bytes.  */
static int avr_pc22;
static int avr_pc22;
 
 
static struct bfd *cur_bfd;
static struct bfd *cur_bfd;
 
 
static enum sim_stop cpu_exception;
static enum sim_stop cpu_exception;
static int cpu_signal;
static int cpu_signal;
 
 
static SIM_OPEN_KIND sim_kind;
static SIM_OPEN_KIND sim_kind;
static char *myname;
static char *myname;
static host_callback *callback;
static host_callback *callback;
 
 
/* Max size of I space (which is always flash on avr).  */
/* Max size of I space (which is always flash on avr).  */
#define MAX_AVR_FLASH (128 * 1024)
#define MAX_AVR_FLASH (128 * 1024)
#define PC_MASK (MAX_AVR_FLASH - 1)
#define PC_MASK (MAX_AVR_FLASH - 1)
 
 
/* Mac size of D space.  */
/* Mac size of D space.  */
#define MAX_AVR_SRAM (64 * 1024)
#define MAX_AVR_SRAM (64 * 1024)
#define SRAM_MASK (MAX_AVR_SRAM - 1)
#define SRAM_MASK (MAX_AVR_SRAM - 1)
 
 
/* D space offset in ELF file.  */
/* D space offset in ELF file.  */
#define SRAM_VADDR 0x800000
#define SRAM_VADDR 0x800000
 
 
/* Simulator specific ports.  */
/* Simulator specific ports.  */
#define STDIO_PORT      0x52
#define STDIO_PORT      0x52
#define EXIT_PORT       0x4F
#define EXIT_PORT       0x4F
#define ABORT_PORT      0x49
#define ABORT_PORT      0x49
 
 
/* GDB defined register numbers.  */
/* GDB defined register numbers.  */
#define AVR_SREG_REGNUM  32
#define AVR_SREG_REGNUM  32
#define AVR_SP_REGNUM    33
#define AVR_SP_REGNUM    33
#define AVR_PC_REGNUM    34
#define AVR_PC_REGNUM    34
 
 
/* Memory mapped registers.  */
/* Memory mapped registers.  */
#define SREG    0x5F
#define SREG    0x5F
#define REG_SP  0x5D
#define REG_SP  0x5D
#define EIND    0x5C
#define EIND    0x5C
#define RAMPZ   0x5B
#define RAMPZ   0x5B
 
 
#define REGX 0x1a
#define REGX 0x1a
#define REGY 0x1c
#define REGY 0x1c
#define REGZ 0x1e
#define REGZ 0x1e
#define REGZ_LO 0x1e
#define REGZ_LO 0x1e
#define REGZ_HI 0x1f
#define REGZ_HI 0x1f
 
 
/* Sreg (status) bits.  */
/* Sreg (status) bits.  */
#define SREG_I 0x80
#define SREG_I 0x80
#define SREG_T 0x40
#define SREG_T 0x40
#define SREG_H 0x20
#define SREG_H 0x20
#define SREG_S 0x10
#define SREG_S 0x10
#define SREG_V 0x08
#define SREG_V 0x08
#define SREG_N 0x04
#define SREG_N 0x04
#define SREG_Z 0x02
#define SREG_Z 0x02
#define SREG_C 0x01
#define SREG_C 0x01
 
 
/* In order to speed up emulation we use a simple approach:
/* In order to speed up emulation we use a simple approach:
   a code is associated with each instruction.  The pre-decoding occurs
   a code is associated with each instruction.  The pre-decoding occurs
   usually once when the instruction is first seen.
   usually once when the instruction is first seen.
   This works well because I&D spaces are separated.
   This works well because I&D spaces are separated.
 
 
   Missing opcodes: sleep, spm, wdr (as they are mmcu dependent).
   Missing opcodes: sleep, spm, wdr (as they are mmcu dependent).
*/
*/
enum avr_opcode
enum avr_opcode
  {
  {
    /* Opcode not yet decoded.  */
    /* Opcode not yet decoded.  */
    OP_unknown,
    OP_unknown,
    OP_bad,
    OP_bad,
 
 
    OP_nop,
    OP_nop,
 
 
    OP_rjmp,
    OP_rjmp,
    OP_rcall,
    OP_rcall,
    OP_ret,
    OP_ret,
    OP_reti,
    OP_reti,
 
 
    OP_break,
    OP_break,
 
 
    OP_brbs,
    OP_brbs,
    OP_brbc,
    OP_brbc,
 
 
    OP_bset,
    OP_bset,
    OP_bclr,
    OP_bclr,
 
 
    OP_bld,
    OP_bld,
    OP_bst,
    OP_bst,
 
 
    OP_sbrc,
    OP_sbrc,
    OP_sbrs,
    OP_sbrs,
 
 
    OP_eor,
    OP_eor,
    OP_and,
    OP_and,
    OP_andi,
    OP_andi,
    OP_or,
    OP_or,
    OP_ori,
    OP_ori,
    OP_com,
    OP_com,
    OP_swap,
    OP_swap,
    OP_neg,
    OP_neg,
 
 
    OP_out,
    OP_out,
    OP_in,
    OP_in,
    OP_cbi,
    OP_cbi,
    OP_sbi,
    OP_sbi,
 
 
    OP_sbic,
    OP_sbic,
    OP_sbis,
    OP_sbis,
 
 
    OP_ldi,
    OP_ldi,
    OP_cpse,
    OP_cpse,
    OP_cp,
    OP_cp,
    OP_cpi,
    OP_cpi,
    OP_cpc,
    OP_cpc,
    OP_sub,
    OP_sub,
    OP_sbc,
    OP_sbc,
    OP_sbiw,
    OP_sbiw,
    OP_adiw,
    OP_adiw,
    OP_add,
    OP_add,
    OP_adc,
    OP_adc,
    OP_subi,
    OP_subi,
    OP_sbci,
    OP_sbci,
    OP_inc,
    OP_inc,
    OP_dec,
    OP_dec,
    OP_lsr,
    OP_lsr,
    OP_ror,
    OP_ror,
    OP_asr,
    OP_asr,
 
 
    OP_mul,
    OP_mul,
    OP_muls,
    OP_muls,
    OP_mulsu,
    OP_mulsu,
    OP_fmul,
    OP_fmul,
    OP_fmuls,
    OP_fmuls,
    OP_fmulsu,
    OP_fmulsu,
 
 
    OP_mov,
    OP_mov,
    OP_movw,
    OP_movw,
 
 
    OP_push,
    OP_push,
    OP_pop,
    OP_pop,
 
 
    OP_st_X,
    OP_st_X,
    OP_st_dec_X,
    OP_st_dec_X,
    OP_st_X_inc,
    OP_st_X_inc,
    OP_st_Y_inc,
    OP_st_Y_inc,
    OP_st_dec_Y,
    OP_st_dec_Y,
    OP_st_Z_inc,
    OP_st_Z_inc,
    OP_st_dec_Z,
    OP_st_dec_Z,
    OP_std_Y,
    OP_std_Y,
    OP_std_Z,
    OP_std_Z,
    OP_ldd_Y,
    OP_ldd_Y,
    OP_ldd_Z,
    OP_ldd_Z,
    OP_ld_Z_inc,
    OP_ld_Z_inc,
    OP_ld_dec_Z,
    OP_ld_dec_Z,
    OP_ld_Y_inc,
    OP_ld_Y_inc,
    OP_ld_dec_Y,
    OP_ld_dec_Y,
    OP_ld_X,
    OP_ld_X,
    OP_ld_X_inc,
    OP_ld_X_inc,
    OP_ld_dec_X,
    OP_ld_dec_X,
 
 
    OP_lpm,
    OP_lpm,
    OP_lpm_Z,
    OP_lpm_Z,
    OP_lpm_inc_Z,
    OP_lpm_inc_Z,
    OP_elpm,
    OP_elpm,
    OP_elpm_Z,
    OP_elpm_Z,
    OP_elpm_inc_Z,
    OP_elpm_inc_Z,
 
 
    OP_ijmp,
    OP_ijmp,
    OP_icall,
    OP_icall,
 
 
    OP_eijmp,
    OP_eijmp,
    OP_eicall,
    OP_eicall,
 
 
    /* 2 words opcodes.  */
    /* 2 words opcodes.  */
#define OP_2words OP_jmp
#define OP_2words OP_jmp
    OP_jmp,
    OP_jmp,
    OP_call,
    OP_call,
    OP_sts,
    OP_sts,
    OP_lds
    OP_lds
  };
  };
 
 
struct avr_insn_cell
struct avr_insn_cell
{
{
  /* The insn (16 bits).  */
  /* The insn (16 bits).  */
  word op;
  word op;
 
 
  /* Pre-decoding code.  */
  /* Pre-decoding code.  */
  enum avr_opcode code : 8;
  enum avr_opcode code : 8;
  /* One byte of additional information.  */
  /* One byte of additional information.  */
  byte r;
  byte r;
};
};
 
 
/* I&D memories.  */
/* I&D memories.  */
static struct avr_insn_cell flash[MAX_AVR_FLASH];
static struct avr_insn_cell flash[MAX_AVR_FLASH];
static byte sram[MAX_AVR_SRAM];
static byte sram[MAX_AVR_SRAM];
 
 
void
void
sim_size (int s)
sim_size (int s)
{
{
}
}
 
 
/* Sign extend a value.  */
/* Sign extend a value.  */
static int sign_ext (word val, int nb_bits)
static int sign_ext (word val, int nb_bits)
{
{
  if (val & (1 << (nb_bits - 1)))
  if (val & (1 << (nb_bits - 1)))
    return val | (-1 << nb_bits);
    return val | (-1 << nb_bits);
  return val;
  return val;
}
}
 
 
/* Insn field extractors.  */
/* Insn field extractors.  */
 
 
/* Extract xxxx_xxxRx_xxxx_RRRR.  */
/* Extract xxxx_xxxRx_xxxx_RRRR.  */
static inline byte get_r (word op)
static inline byte get_r (word op)
{
{
  return (op & 0xf) | ((op >> 5) & 0x10);
  return (op & 0xf) | ((op >> 5) & 0x10);
}
}
 
 
/* Extract xxxx_xxxxx_xxxx_RRRR.  */
/* Extract xxxx_xxxxx_xxxx_RRRR.  */
static inline byte get_r16 (word op)
static inline byte get_r16 (word op)
{
{
  return 16 + (op & 0xf);
  return 16 + (op & 0xf);
}
}
 
 
/* Extract xxxx_xxxxx_xxxx_xRRR.  */
/* Extract xxxx_xxxxx_xxxx_xRRR.  */
static inline byte get_r16_23 (word op)
static inline byte get_r16_23 (word op)
{
{
  return 16 + (op & 0x7);
  return 16 + (op & 0x7);
}
}
 
 
/* Extract xxxx_xxxD_DDDD_xxxx.  */
/* Extract xxxx_xxxD_DDDD_xxxx.  */
static inline byte get_d (word op)
static inline byte get_d (word op)
{
{
  return (op >> 4) & 0x1f;
  return (op >> 4) & 0x1f;
}
}
 
 
/* Extract xxxx_xxxx_DDDD_xxxx.  */
/* Extract xxxx_xxxx_DDDD_xxxx.  */
static inline byte get_d16 (word op)
static inline byte get_d16 (word op)
{
{
  return 16 + ((op >> 4) & 0x0f);
  return 16 + ((op >> 4) & 0x0f);
}
}
 
 
/* Extract xxxx_xxxx_xDDD_xxxx.  */
/* Extract xxxx_xxxx_xDDD_xxxx.  */
static inline byte get_d16_23 (word op)
static inline byte get_d16_23 (word op)
{
{
  return 16 + ((op >> 4) & 0x07);
  return 16 + ((op >> 4) & 0x07);
}
}
 
 
/* Extract xxxx_xAAx_xxxx_AAAA.  */
/* Extract xxxx_xAAx_xxxx_AAAA.  */
static inline byte get_A (word op)
static inline byte get_A (word op)
{
{
  return (op & 0x0f) | ((op & 0x600) >> 5);
  return (op & 0x0f) | ((op & 0x600) >> 5);
}
}
 
 
/* Extract xxxx_xxxx_AAAA_Axxx.  */
/* Extract xxxx_xxxx_AAAA_Axxx.  */
static inline byte get_biA (word op)
static inline byte get_biA (word op)
{
{
  return (op >> 3) & 0x1f;
  return (op >> 3) & 0x1f;
}
}
 
 
/* Extract xxxx_KKKK_xxxx_KKKK.  */
/* Extract xxxx_KKKK_xxxx_KKKK.  */
static inline byte get_K (word op)
static inline byte get_K (word op)
{
{
  return (op & 0xf) | ((op & 0xf00) >> 4);
  return (op & 0xf) | ((op & 0xf00) >> 4);
}
}
 
 
/* Extract xxxx_xxKK_KKKK_Kxxx.  */
/* Extract xxxx_xxKK_KKKK_Kxxx.  */
static inline int get_k (word op)
static inline int get_k (word op)
{
{
  return sign_ext ((op & 0x3f8) >> 3, 7);
  return sign_ext ((op & 0x3f8) >> 3, 7);
}
}
 
 
/* Extract xxxx_xxxx_xxDD_xxxx.  */
/* Extract xxxx_xxxx_xxDD_xxxx.  */
static inline byte get_d24 (word op)
static inline byte get_d24 (word op)
{
{
  return 24 + ((op >> 3) & 6);
  return 24 + ((op >> 3) & 6);
}
}
 
 
/* Extract xxxx_xxxx_KKxx_KKKK.  */
/* Extract xxxx_xxxx_KKxx_KKKK.  */
static inline byte get_k6 (word op)
static inline byte get_k6 (word op)
{
{
  return (op & 0xf) | ((op >> 2) & 0x30);
  return (op & 0xf) | ((op >> 2) & 0x30);
}
}
 
 
/* Extract xxQx_QQxx_xxxx_xQQQ.  */
/* Extract xxQx_QQxx_xxxx_xQQQ.  */
static inline byte get_q (word op)
static inline byte get_q (word op)
{
{
  return (op & 7) | ((op >> 7) & 0x18)| ((op >> 8) & 0x20);
  return (op & 7) | ((op >> 7) & 0x18)| ((op >> 8) & 0x20);
}
}
 
 
/* Extract xxxx_xxxx_xxxx_xBBB.  */
/* Extract xxxx_xxxx_xxxx_xBBB.  */
static inline byte get_b (word op)
static inline byte get_b (word op)
{
{
  return (op & 7);
  return (op & 7);
}
}
 
 
/* AVR is little endian.  */
/* AVR is little endian.  */
static inline word
static inline word
read_word (unsigned int addr)
read_word (unsigned int addr)
{
{
  return sram[addr] | (sram[addr + 1] << 8);
  return sram[addr] | (sram[addr + 1] << 8);
}
}
 
 
static inline void
static inline void
write_word (unsigned int addr, word w)
write_word (unsigned int addr, word w)
{
{
  sram[addr] = w;
  sram[addr] = w;
  sram[addr + 1] = w >> 8;
  sram[addr + 1] = w >> 8;
}
}
 
 
static inline word
static inline word
read_word_post_inc (unsigned int addr)
read_word_post_inc (unsigned int addr)
{
{
  word v = read_word (addr);
  word v = read_word (addr);
  write_word (addr, v + 1);
  write_word (addr, v + 1);
  return v;
  return v;
}
}
 
 
static inline word
static inline word
read_word_pre_dec (unsigned int addr)
read_word_pre_dec (unsigned int addr)
{
{
  word v = read_word (addr) - 1;
  word v = read_word (addr) - 1;
  write_word (addr, v);
  write_word (addr, v);
  return v;
  return v;
}
}
 
 
static void
static void
update_flags_logic (byte res)
update_flags_logic (byte res)
{
{
  sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z);
  sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z);
  if (res == 0)
  if (res == 0)
    sram[SREG] |= SREG_Z;
    sram[SREG] |= SREG_Z;
  if (res & 0x80)
  if (res & 0x80)
    sram[SREG] |= SREG_N | SREG_S;
    sram[SREG] |= SREG_N | SREG_S;
}
}
 
 
static void
static void
update_flags_add (byte r, byte a, byte b)
update_flags_add (byte r, byte a, byte b)
{
{
  byte carry;
  byte carry;
 
 
  sram[SREG] &= ~(SREG_H | SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
  sram[SREG] &= ~(SREG_H | SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
  if (r & 0x80)
  if (r & 0x80)
    sram[SREG] |= SREG_N;
    sram[SREG] |= SREG_N;
  carry = (a & b) | (a & ~r) | (b & ~r);
  carry = (a & b) | (a & ~r) | (b & ~r);
  if (carry & 0x08)
  if (carry & 0x08)
    sram[SREG] |= SREG_H;
    sram[SREG] |= SREG_H;
  if (carry & 0x80)
  if (carry & 0x80)
    sram[SREG] |= SREG_C;
    sram[SREG] |= SREG_C;
  if (((a & b & ~r) | (~a & ~b & r)) & 0x80)
  if (((a & b & ~r) | (~a & ~b & r)) & 0x80)
    sram[SREG] |= SREG_V;
    sram[SREG] |= SREG_V;
  if (!(sram[SREG] & SREG_N) ^ !(sram[SREG] & SREG_V))
  if (!(sram[SREG] & SREG_N) ^ !(sram[SREG] & SREG_V))
    sram[SREG] |= SREG_S;
    sram[SREG] |= SREG_S;
  if (r == 0)
  if (r == 0)
    sram[SREG] |= SREG_Z;
    sram[SREG] |= SREG_Z;
}
}
 
 
static void update_flags_sub (byte r, byte a, byte b)
static void update_flags_sub (byte r, byte a, byte b)
{
{
  byte carry;
  byte carry;
 
 
  sram[SREG] &= ~(SREG_H | SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
  sram[SREG] &= ~(SREG_H | SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
  if (r & 0x80)
  if (r & 0x80)
    sram[SREG] |= SREG_N;
    sram[SREG] |= SREG_N;
  carry = (~a & b) | (b & r) | (r & ~a);
  carry = (~a & b) | (b & r) | (r & ~a);
  if (carry & 0x08)
  if (carry & 0x08)
    sram[SREG] |= SREG_H;
    sram[SREG] |= SREG_H;
  if (carry & 0x80)
  if (carry & 0x80)
    sram[SREG] |= SREG_C;
    sram[SREG] |= SREG_C;
  if (((a & ~b & ~r) | (~a & b & r)) & 0x80)
  if (((a & ~b & ~r) | (~a & b & r)) & 0x80)
    sram[SREG] |= SREG_V;
    sram[SREG] |= SREG_V;
  if (!(sram[SREG] & SREG_N) ^ !(sram[SREG] & SREG_V))
  if (!(sram[SREG] & SREG_N) ^ !(sram[SREG] & SREG_V))
    sram[SREG] |= SREG_S;
    sram[SREG] |= SREG_S;
  /* Note: Z is not set.  */
  /* Note: Z is not set.  */
}
}
 
 
static enum avr_opcode
static enum avr_opcode
decode (unsigned int pc)
decode (unsigned int pc)
{
{
  word op1 = flash[pc].op;
  word op1 = flash[pc].op;
 
 
  switch ((op1 >> 12) & 0x0f)
  switch ((op1 >> 12) & 0x0f)
    {
    {
    case 0x0:
    case 0x0:
      switch ((op1 >> 10) & 0x3)
      switch ((op1 >> 10) & 0x3)
        {
        {
        case 0x0:
        case 0x0:
          switch ((op1 >> 8) & 0x3)
          switch ((op1 >> 8) & 0x3)
            {
            {
            case 0x0:
            case 0x0:
              if (op1 == 0)
              if (op1 == 0)
                return OP_nop;
                return OP_nop;
              break;
              break;
            case 0x1:
            case 0x1:
              return OP_movw;
              return OP_movw;
            case 0x2:
            case 0x2:
              return OP_muls;
              return OP_muls;
            case 0x3:
            case 0x3:
              if (op1 & 0x80)
              if (op1 & 0x80)
                {
                {
                  if (op1 & 0x08)
                  if (op1 & 0x08)
                    return OP_fmulsu;
                    return OP_fmulsu;
                  else
                  else
                    return OP_fmuls;
                    return OP_fmuls;
                }
                }
              else
              else
                {
                {
                  if (op1 & 0x08)
                  if (op1 & 0x08)
                    return OP_fmul;
                    return OP_fmul;
                  else
                  else
                    return OP_mulsu;
                    return OP_mulsu;
                }
                }
            }
            }
          break;
          break;
        case 0x1:
        case 0x1:
          return OP_cpc;
          return OP_cpc;
        case 0x2:
        case 0x2:
          flash[pc].r = SREG_C;
          flash[pc].r = SREG_C;
          return OP_sbc;
          return OP_sbc;
        case 0x3:
        case 0x3:
          flash[pc].r = 0;
          flash[pc].r = 0;
          return OP_add;
          return OP_add;
        }
        }
      break;
      break;
    case 0x1:
    case 0x1:
      switch ((op1 >> 10) & 0x3)
      switch ((op1 >> 10) & 0x3)
        {
        {
        case 0x0:
        case 0x0:
          return OP_cpse;
          return OP_cpse;
        case 0x1:
        case 0x1:
          return OP_cp;
          return OP_cp;
        case 0x2:
        case 0x2:
          flash[pc].r = 0;
          flash[pc].r = 0;
          return OP_sub;
          return OP_sub;
        case 0x3:
        case 0x3:
          flash[pc].r = SREG_C;
          flash[pc].r = SREG_C;
          return OP_adc;
          return OP_adc;
        }
        }
      break;
      break;
    case 0x2:
    case 0x2:
      switch ((op1 >> 10) & 0x3)
      switch ((op1 >> 10) & 0x3)
        {
        {
        case 0x0:
        case 0x0:
          return OP_and;
          return OP_and;
        case 0x1:
        case 0x1:
          return OP_eor;
          return OP_eor;
        case 0x2:
        case 0x2:
          return OP_or;
          return OP_or;
        case 0x3:
        case 0x3:
          return OP_mov;
          return OP_mov;
        }
        }
      break;
      break;
    case 0x3:
    case 0x3:
      return OP_cpi;
      return OP_cpi;
    case 0x4:
    case 0x4:
      return OP_sbci;
      return OP_sbci;
    case 0x5:
    case 0x5:
      return OP_subi;
      return OP_subi;
    case 0x6:
    case 0x6:
      return OP_ori;
      return OP_ori;
    case 0x7:
    case 0x7:
      return OP_andi;
      return OP_andi;
    case 0x8:
    case 0x8:
    case 0xa:
    case 0xa:
      if (op1 & 0x0200)
      if (op1 & 0x0200)
        {
        {
          if (op1 & 0x0008)
          if (op1 & 0x0008)
            {
            {
              flash[pc].r = get_q (op1);
              flash[pc].r = get_q (op1);
              return OP_std_Y;
              return OP_std_Y;
            }
            }
          else
          else
            {
            {
              flash[pc].r = get_q (op1);
              flash[pc].r = get_q (op1);
              return OP_std_Z;
              return OP_std_Z;
            }
            }
        }
        }
      else
      else
        {
        {
          if (op1 & 0x0008)
          if (op1 & 0x0008)
            {
            {
              flash[pc].r = get_q (op1);
              flash[pc].r = get_q (op1);
              return OP_ldd_Y;
              return OP_ldd_Y;
            }
            }
          else
          else
            {
            {
              flash[pc].r = get_q (op1);
              flash[pc].r = get_q (op1);
              return OP_ldd_Z;
              return OP_ldd_Z;
            }
            }
        }
        }
      break;
      break;
    case 0x9: /* 9xxx */
    case 0x9: /* 9xxx */
      switch ((op1 >> 8) & 0xf)
      switch ((op1 >> 8) & 0xf)
        {
        {
        case 0x0:
        case 0x0:
        case 0x1:
        case 0x1:
          switch ((op1 >> 0) & 0xf)
          switch ((op1 >> 0) & 0xf)
            {
            {
            case 0x0:
            case 0x0:
              return OP_lds;
              return OP_lds;
            case 0x1:
            case 0x1:
              return OP_ld_Z_inc;
              return OP_ld_Z_inc;
            case 0x2:
            case 0x2:
              return OP_ld_dec_Z;
              return OP_ld_dec_Z;
            case 0x4:
            case 0x4:
              return OP_lpm_Z;
              return OP_lpm_Z;
            case 0x5:
            case 0x5:
              return OP_lpm_inc_Z;
              return OP_lpm_inc_Z;
            case 0x6:
            case 0x6:
              return OP_elpm_Z;
              return OP_elpm_Z;
            case 0x7:
            case 0x7:
              return OP_elpm_inc_Z;
              return OP_elpm_inc_Z;
            case 0x9:
            case 0x9:
              return OP_ld_Y_inc;
              return OP_ld_Y_inc;
            case 0xa:
            case 0xa:
              return OP_ld_dec_Y;
              return OP_ld_dec_Y;
            case 0xc:
            case 0xc:
              return OP_ld_X;
              return OP_ld_X;
            case 0xd:
            case 0xd:
              return OP_ld_X_inc;
              return OP_ld_X_inc;
            case 0xe:
            case 0xe:
              return OP_ld_dec_X;
              return OP_ld_dec_X;
            case 0xf:
            case 0xf:
              return OP_pop;
              return OP_pop;
            }
            }
          break;
          break;
        case 0x2:
        case 0x2:
        case 0x3:
        case 0x3:
          switch ((op1 >> 0) & 0xf)
          switch ((op1 >> 0) & 0xf)
            {
            {
            case 0x0:
            case 0x0:
              return OP_sts;
              return OP_sts;
            case 0x1:
            case 0x1:
              return OP_st_Z_inc;
              return OP_st_Z_inc;
            case 0x2:
            case 0x2:
              return OP_st_dec_Z;
              return OP_st_dec_Z;
            case 0x9:
            case 0x9:
              return OP_st_Y_inc;
              return OP_st_Y_inc;
            case 0xa:
            case 0xa:
              return OP_st_dec_Y;
              return OP_st_dec_Y;
            case 0xc:
            case 0xc:
              return OP_st_X;
              return OP_st_X;
            case 0xd:
            case 0xd:
              return OP_st_X_inc;
              return OP_st_X_inc;
            case 0xe:
            case 0xe:
              return OP_st_dec_X;
              return OP_st_dec_X;
            case 0xf:
            case 0xf:
              return OP_push;
              return OP_push;
            }
            }
          break;
          break;
        case 0x4:
        case 0x4:
        case 0x5:
        case 0x5:
          switch (op1 & 0xf)
          switch (op1 & 0xf)
            {
            {
            case 0x0:
            case 0x0:
              return OP_com;
              return OP_com;
            case 0x1:
            case 0x1:
              return OP_neg;
              return OP_neg;
            case 0x2:
            case 0x2:
              return OP_swap;
              return OP_swap;
            case 0x3:
            case 0x3:
              return OP_inc;
              return OP_inc;
            case 0x5:
            case 0x5:
              flash[pc].r = 0x80;
              flash[pc].r = 0x80;
              return OP_asr;
              return OP_asr;
            case 0x6:
            case 0x6:
              flash[pc].r = 0;
              flash[pc].r = 0;
              return OP_lsr;
              return OP_lsr;
            case 0x7:
            case 0x7:
              return OP_ror;
              return OP_ror;
            case 0x8: /* 9[45]x8 */
            case 0x8: /* 9[45]x8 */
              switch ((op1 >> 4) & 0x1f)
              switch ((op1 >> 4) & 0x1f)
                {
                {
                case 0x00:
                case 0x00:
                case 0x01:
                case 0x01:
                case 0x02:
                case 0x02:
                case 0x03:
                case 0x03:
                case 0x04:
                case 0x04:
                case 0x05:
                case 0x05:
                case 0x06:
                case 0x06:
                case 0x07:
                case 0x07:
                  return OP_bset;
                  return OP_bset;
                case 0x08:
                case 0x08:
                case 0x09:
                case 0x09:
                case 0x0a:
                case 0x0a:
                case 0x0b:
                case 0x0b:
                case 0x0c:
                case 0x0c:
                case 0x0d:
                case 0x0d:
                case 0x0e:
                case 0x0e:
                case 0x0f:
                case 0x0f:
                  return OP_bclr;
                  return OP_bclr;
                case 0x10:
                case 0x10:
                  return OP_ret;
                  return OP_ret;
                case 0x11:
                case 0x11:
                  return OP_reti;
                  return OP_reti;
                case 0x19:
                case 0x19:
                  return OP_break;
                  return OP_break;
                case 0x1c:
                case 0x1c:
                  return OP_lpm;
                  return OP_lpm;
                case 0x1d:
                case 0x1d:
                  return OP_elpm;
                  return OP_elpm;
                default:
                default:
                  break;
                  break;
                }
                }
              break;
              break;
            case 0x9: /* 9[45]x9 */
            case 0x9: /* 9[45]x9 */
              switch ((op1 >> 4) & 0x1f)
              switch ((op1 >> 4) & 0x1f)
                {
                {
                case 0x00:
                case 0x00:
                  return OP_ijmp;
                  return OP_ijmp;
                case 0x01:
                case 0x01:
                  return OP_eijmp;
                  return OP_eijmp;
                case 0x10:
                case 0x10:
                  return OP_icall;
                  return OP_icall;
                case 0x11:
                case 0x11:
                  return OP_eicall;
                  return OP_eicall;
                default:
                default:
                  break;
                  break;
                }
                }
              break;
              break;
            case 0xa:
            case 0xa:
              return OP_dec;
              return OP_dec;
            case 0xc:
            case 0xc:
            case 0xd:
            case 0xd:
              flash[pc].r = ((op1 & 0x1f0) >> 3) | (op1 & 1);
              flash[pc].r = ((op1 & 0x1f0) >> 3) | (op1 & 1);
              return OP_jmp;
              return OP_jmp;
            case 0xe:
            case 0xe:
            case 0xf:
            case 0xf:
              flash[pc].r = ((op1 & 0x1f0) >> 3) | (op1 & 1);
              flash[pc].r = ((op1 & 0x1f0) >> 3) | (op1 & 1);
              return OP_call;
              return OP_call;
            }
            }
          break;
          break;
        case 0x6:
        case 0x6:
          return OP_adiw;
          return OP_adiw;
        case 0x7:
        case 0x7:
          return OP_sbiw;
          return OP_sbiw;
        case 0x8:
        case 0x8:
          return OP_cbi;
          return OP_cbi;
        case 0x9:
        case 0x9:
          return OP_sbic;
          return OP_sbic;
        case 0xa:
        case 0xa:
          return OP_sbi;
          return OP_sbi;
        case 0xb:
        case 0xb:
          return OP_sbis;
          return OP_sbis;
        case 0xc:
        case 0xc:
        case 0xd:
        case 0xd:
        case 0xe:
        case 0xe:
        case 0xf:
        case 0xf:
          return OP_mul;
          return OP_mul;
        }
        }
      break;
      break;
    case 0xb:
    case 0xb:
      flash[pc].r = get_A (op1);
      flash[pc].r = get_A (op1);
      if (((op1 >> 11) & 1) == 0)
      if (((op1 >> 11) & 1) == 0)
        return OP_in;
        return OP_in;
      else
      else
        return OP_out;
        return OP_out;
    case 0xc:
    case 0xc:
      return OP_rjmp;
      return OP_rjmp;
    case 0xd:
    case 0xd:
      return OP_rcall;
      return OP_rcall;
    case 0xe:
    case 0xe:
      return OP_ldi;
      return OP_ldi;
    case 0xf:
    case 0xf:
      switch ((op1 >> 9) & 7)
      switch ((op1 >> 9) & 7)
        {
        {
        case 0:
        case 0:
        case 1:
        case 1:
          flash[pc].r = 1 << (op1 & 7);
          flash[pc].r = 1 << (op1 & 7);
          return OP_brbs;
          return OP_brbs;
        case 2:
        case 2:
        case 3:
        case 3:
          flash[pc].r = 1 << (op1 & 7);
          flash[pc].r = 1 << (op1 & 7);
          return OP_brbc;
          return OP_brbc;
        case 4:
        case 4:
          if ((op1 & 8) == 0)
          if ((op1 & 8) == 0)
            {
            {
              flash[pc].r = 1 << (op1 & 7);
              flash[pc].r = 1 << (op1 & 7);
              return OP_bld;
              return OP_bld;
            }
            }
          break;
          break;
        case 5:
        case 5:
          if ((op1 & 8) == 0)
          if ((op1 & 8) == 0)
            {
            {
              flash[pc].r = 1 << (op1 & 7);
              flash[pc].r = 1 << (op1 & 7);
              return OP_bst;
              return OP_bst;
            }
            }
          break;
          break;
        case 6:
        case 6:
          if ((op1 & 8) == 0)
          if ((op1 & 8) == 0)
            {
            {
              flash[pc].r = 1 << (op1 & 7);
              flash[pc].r = 1 << (op1 & 7);
              return OP_sbrc;
              return OP_sbrc;
            }
            }
          break;
          break;
        case 7:
        case 7:
          if ((op1 & 8) == 0)
          if ((op1 & 8) == 0)
            {
            {
              flash[pc].r = 1 << (op1 & 7);
              flash[pc].r = 1 << (op1 & 7);
              return OP_sbrs;
              return OP_sbrs;
            }
            }
          break;
          break;
        }
        }
    }
    }
  sim_cb_eprintf (callback,
  sim_cb_eprintf (callback,
                  "Unhandled instruction at pc=0x%x, op=%04x\n", pc * 2, op1);
                  "Unhandled instruction at pc=0x%x, op=%04x\n", pc * 2, op1);
  return OP_bad;
  return OP_bad;
}
}
 
 
/* Disassemble an instruction.  */
/* Disassemble an instruction.  */
 
 
static int
static int
disasm_read_memory (bfd_vma memaddr, bfd_byte *myaddr, unsigned int length,
disasm_read_memory (bfd_vma memaddr, bfd_byte *myaddr, unsigned int length,
                        struct disassemble_info *info)
                        struct disassemble_info *info)
{
{
  int res;
  int res;
 
 
  res = sim_read (NULL, memaddr, myaddr, length);
  res = sim_read (NULL, memaddr, myaddr, length);
  if (res != length)
  if (res != length)
    return -1;
    return -1;
  return 0;
  return 0;
}
}
 
 
/* Memory error support for an opcodes disassembler.  */
/* Memory error support for an opcodes disassembler.  */
 
 
static void
static void
disasm_perror_memory (int status, bfd_vma memaddr,
disasm_perror_memory (int status, bfd_vma memaddr,
                          struct disassemble_info *info)
                          struct disassemble_info *info)
{
{
  if (status != -1)
  if (status != -1)
    /* Can't happen.  */
    /* Can't happen.  */
    info->fprintf_func (info->stream, "Unknown error %d.", status);
    info->fprintf_func (info->stream, "Unknown error %d.", status);
  else
  else
    /* Actually, address between memaddr and memaddr + len was
    /* Actually, address between memaddr and memaddr + len was
       out of bounds.  */
       out of bounds.  */
    info->fprintf_func (info->stream,
    info->fprintf_func (info->stream,
                        "Address 0x%x is out of bounds.",
                        "Address 0x%x is out of bounds.",
                        (int) memaddr);
                        (int) memaddr);
}
}
 
 
static void
static void
disassemble_insn (SIM_DESC sd, SIM_ADDR pc)
disassemble_insn (SIM_DESC sd, SIM_ADDR pc)
{
{
  struct disassemble_info disasm_info;
  struct disassemble_info disasm_info;
  int len;
  int len;
  int i;
  int i;
 
 
  INIT_DISASSEMBLE_INFO (disasm_info, callback, sim_cb_eprintf);
  INIT_DISASSEMBLE_INFO (disasm_info, callback, sim_cb_eprintf);
 
 
  disasm_info.arch = bfd_get_arch (cur_bfd);
  disasm_info.arch = bfd_get_arch (cur_bfd);
  disasm_info.mach = bfd_get_mach (cur_bfd);
  disasm_info.mach = bfd_get_mach (cur_bfd);
  disasm_info.endian = BFD_ENDIAN_LITTLE;
  disasm_info.endian = BFD_ENDIAN_LITTLE;
  disasm_info.read_memory_func = disasm_read_memory;
  disasm_info.read_memory_func = disasm_read_memory;
  disasm_info.memory_error_func = disasm_perror_memory;
  disasm_info.memory_error_func = disasm_perror_memory;
 
 
  len = print_insn_avr (pc << 1, &disasm_info);
  len = print_insn_avr (pc << 1, &disasm_info);
  len = len / 2;
  len = len / 2;
  for (i = 0; i < len; i++)
  for (i = 0; i < len; i++)
    sim_cb_eprintf (callback, " %04x", flash[pc + i].op);
    sim_cb_eprintf (callback, " %04x", flash[pc + i].op);
}
}
 
 
static void
static void
do_call (unsigned int npc)
do_call (unsigned int npc)
{
{
  unsigned int sp = read_word (REG_SP);
  unsigned int sp = read_word (REG_SP);
 
 
  /* Big endian!  */
  /* Big endian!  */
  sram[sp--] = pc;
  sram[sp--] = pc;
  sram[sp--] = pc >> 8;
  sram[sp--] = pc >> 8;
  if (avr_pc22)
  if (avr_pc22)
    {
    {
      sram[sp--] = pc >> 16;
      sram[sp--] = pc >> 16;
      cycles++;
      cycles++;
    }
    }
  write_word (REG_SP, sp);
  write_word (REG_SP, sp);
  pc = npc & PC_MASK;
  pc = npc & PC_MASK;
  cycles += 3;
  cycles += 3;
}
}
 
 
static int
static int
get_insn_length (unsigned int p)
get_insn_length (unsigned int p)
{
{
  if (flash[p].code == OP_unknown)
  if (flash[p].code == OP_unknown)
    flash[p].code = decode(p);
    flash[p].code = decode(p);
  if (flash[p].code >= OP_2words)
  if (flash[p].code >= OP_2words)
    return 2;
    return 2;
  else
  else
    return 1;
    return 1;
}
}
 
 
static unsigned int
static unsigned int
get_z (void)
get_z (void)
{
{
  return (sram[RAMPZ] << 16) | (sram[REGZ_HI] << 8) | sram[REGZ_LO];
  return (sram[RAMPZ] << 16) | (sram[REGZ_HI] << 8) | sram[REGZ_LO];
}
}
 
 
static unsigned char
static unsigned char
get_lpm (unsigned int addr)
get_lpm (unsigned int addr)
{
{
  word w;
  word w;
 
 
  w = flash[(addr >> 1) & PC_MASK].op;
  w = flash[(addr >> 1) & PC_MASK].op;
  if (addr & 1)
  if (addr & 1)
    w >>= 8;
    w >>= 8;
  return w;
  return w;
}
}
 
 
static void
static void
gen_mul (unsigned int res)
gen_mul (unsigned int res)
{
{
  write_word (0, res);
  write_word (0, res);
  sram[SREG] &= ~(SREG_Z | SREG_C);
  sram[SREG] &= ~(SREG_Z | SREG_C);
  if (res == 0)
  if (res == 0)
    sram[SREG] |= SREG_Z;
    sram[SREG] |= SREG_Z;
  if (res & 0x8000)
  if (res & 0x8000)
    sram[SREG] |= SREG_C;
    sram[SREG] |= SREG_C;
  cycles++;
  cycles++;
}
}
 
 
void
void
sim_resume (SIM_DESC sd, int step, int signal)
sim_resume (SIM_DESC sd, int step, int signal)
{
{
  unsigned int ipc;
  unsigned int ipc;
 
 
  if (step)
  if (step)
    {
    {
      cpu_exception = sim_stopped;
      cpu_exception = sim_stopped;
      cpu_signal = TARGET_SIGNAL_TRAP;
      cpu_signal = TARGET_SIGNAL_TRAP;
    }
    }
  else
  else
    cpu_exception = sim_running;
    cpu_exception = sim_running;
 
 
  do
  do
    {
    {
      int code;
      int code;
      word op;
      word op;
      byte res;
      byte res;
      byte r, d, vd;
      byte r, d, vd;
 
 
    again:
    again:
      code = flash[pc].code;
      code = flash[pc].code;
      op = flash[pc].op;
      op = flash[pc].op;
 
 
 
 
      if ((tracing || lock_step) && code != OP_unknown)
      if ((tracing || lock_step) && code != OP_unknown)
        {
        {
          if (verbose > 0) {
          if (verbose > 0) {
            int flags;
            int flags;
            int i;
            int i;
 
 
            sim_cb_eprintf (callback, "R00-07:");
            sim_cb_eprintf (callback, "R00-07:");
            for (i = 0; i < 8; i++)
            for (i = 0; i < 8; i++)
              sim_cb_eprintf (callback, " %02x", sram[i]);
              sim_cb_eprintf (callback, " %02x", sram[i]);
            sim_cb_eprintf (callback, " -");
            sim_cb_eprintf (callback, " -");
            for (i = 8; i < 16; i++)
            for (i = 8; i < 16; i++)
              sim_cb_eprintf (callback, " %02x", sram[i]);
              sim_cb_eprintf (callback, " %02x", sram[i]);
            sim_cb_eprintf (callback, "  SP: %02x %02x",
            sim_cb_eprintf (callback, "  SP: %02x %02x",
                            sram[REG_SP + 1], sram[REG_SP]);
                            sram[REG_SP + 1], sram[REG_SP]);
            sim_cb_eprintf (callback, "\n");
            sim_cb_eprintf (callback, "\n");
            sim_cb_eprintf (callback, "R16-31:");
            sim_cb_eprintf (callback, "R16-31:");
            for (i = 16; i < 24; i++)
            for (i = 16; i < 24; i++)
              sim_cb_eprintf (callback, " %02x", sram[i]);
              sim_cb_eprintf (callback, " %02x", sram[i]);
            sim_cb_eprintf (callback, " -");
            sim_cb_eprintf (callback, " -");
            for (i = 24; i < 32; i++)
            for (i = 24; i < 32; i++)
              sim_cb_eprintf (callback, " %02x", sram[i]);
              sim_cb_eprintf (callback, " %02x", sram[i]);
            sim_cb_eprintf (callback, "  ");
            sim_cb_eprintf (callback, "  ");
            flags = sram[SREG];
            flags = sram[SREG];
            for (i = 0; i < 8; i++)
            for (i = 0; i < 8; i++)
              sim_cb_eprintf (callback, "%c",
              sim_cb_eprintf (callback, "%c",
                              flags & (0x80 >> i) ? "ITHSVNZC"[i] : '-');
                              flags & (0x80 >> i) ? "ITHSVNZC"[i] : '-');
            sim_cb_eprintf (callback, "\n");
            sim_cb_eprintf (callback, "\n");
          }
          }
 
 
          if (lock_step && !tracing)
          if (lock_step && !tracing)
            sim_cb_eprintf (callback, "%06x: %04x\n", 2 * pc, flash[pc].op);
            sim_cb_eprintf (callback, "%06x: %04x\n", 2 * pc, flash[pc].op);
          else
          else
            {
            {
              sim_cb_eprintf (callback, "pc=0x%06x insn=0x%04x code=%d r=%d\n",
              sim_cb_eprintf (callback, "pc=0x%06x insn=0x%04x code=%d r=%d\n",
                              2 * pc, flash[pc].op, code, flash[pc].r);
                              2 * pc, flash[pc].op, code, flash[pc].r);
              disassemble_insn (sd, pc);
              disassemble_insn (sd, pc);
              sim_cb_eprintf (callback, "\n");
              sim_cb_eprintf (callback, "\n");
            }
            }
        }
        }
 
 
      ipc = pc;
      ipc = pc;
      pc = (pc + 1) & PC_MASK;
      pc = (pc + 1) & PC_MASK;
      cycles++;
      cycles++;
 
 
      switch (code)
      switch (code)
        {
        {
        case OP_unknown:
        case OP_unknown:
          flash[ipc].code = decode(ipc);
          flash[ipc].code = decode(ipc);
          pc = ipc;
          pc = ipc;
          cycles--;
          cycles--;
          goto again;
          goto again;
          break;
          break;
 
 
        case OP_nop:
        case OP_nop:
          break;
          break;
 
 
        case OP_jmp:
        case OP_jmp:
          /* 2 words instruction, but we don't care about the pc.  */
          /* 2 words instruction, but we don't care about the pc.  */
          pc = ((flash[ipc].r << 16) | flash[ipc + 1].op) & PC_MASK;
          pc = ((flash[ipc].r << 16) | flash[ipc + 1].op) & PC_MASK;
          cycles += 2;
          cycles += 2;
          break;
          break;
 
 
        case OP_eijmp:
        case OP_eijmp:
          pc = ((sram[EIND] << 16) | read_word (REGZ)) & PC_MASK;
          pc = ((sram[EIND] << 16) | read_word (REGZ)) & PC_MASK;
          cycles += 2;
          cycles += 2;
          break;
          break;
 
 
        case OP_ijmp:
        case OP_ijmp:
          pc = read_word (REGZ) & PC_MASK;
          pc = read_word (REGZ) & PC_MASK;
          cycles += 1;
          cycles += 1;
          break;
          break;
 
 
        case OP_call:
        case OP_call:
          /* 2 words instruction.  */
          /* 2 words instruction.  */
          pc++;
          pc++;
          do_call ((flash[ipc].r << 16) | flash[ipc + 1].op);
          do_call ((flash[ipc].r << 16) | flash[ipc + 1].op);
          break;
          break;
 
 
        case OP_eicall:
        case OP_eicall:
          do_call ((sram[EIND] << 16) | read_word (REGZ));
          do_call ((sram[EIND] << 16) | read_word (REGZ));
          break;
          break;
 
 
        case OP_icall:
        case OP_icall:
          do_call (read_word (REGZ));
          do_call (read_word (REGZ));
          break;
          break;
 
 
        case OP_rcall:
        case OP_rcall:
          do_call (pc + sign_ext (op & 0xfff, 12));
          do_call (pc + sign_ext (op & 0xfff, 12));
          break;
          break;
 
 
        case OP_reti:
        case OP_reti:
          sram[SREG] |= SREG_I;
          sram[SREG] |= SREG_I;
          /* Fall through */
          /* Fall through */
        case OP_ret:
        case OP_ret:
          {
          {
            unsigned int sp = read_word (REG_SP);
            unsigned int sp = read_word (REG_SP);
            if (avr_pc22)
            if (avr_pc22)
              {
              {
                pc = sram[++sp] << 16;
                pc = sram[++sp] << 16;
                cycles++;
                cycles++;
              }
              }
            else
            else
              pc = 0;
              pc = 0;
            pc |= sram[++sp] << 8;
            pc |= sram[++sp] << 8;
            pc |= sram[++sp];
            pc |= sram[++sp];
            write_word (REG_SP, sp);
            write_word (REG_SP, sp);
          }
          }
          cycles += 3;
          cycles += 3;
          break;
          break;
 
 
        case OP_break:
        case OP_break:
          /* Stop on this address.  */
          /* Stop on this address.  */
          cpu_exception = sim_stopped;
          cpu_exception = sim_stopped;
          cpu_signal = TARGET_SIGNAL_TRAP;
          cpu_signal = TARGET_SIGNAL_TRAP;
          pc = ipc;
          pc = ipc;
          break;
          break;
 
 
        case OP_bld:
        case OP_bld:
          d = get_d (op);
          d = get_d (op);
          r = flash[ipc].r;
          r = flash[ipc].r;
          if (sram[SREG] & SREG_T)
          if (sram[SREG] & SREG_T)
            sram[d] |= r;
            sram[d] |= r;
          else
          else
            sram[d] &= ~r;
            sram[d] &= ~r;
          break;
          break;
 
 
        case OP_bst:
        case OP_bst:
          if (sram[get_d (op)] & flash[ipc].r)
          if (sram[get_d (op)] & flash[ipc].r)
            sram[SREG] |= SREG_T;
            sram[SREG] |= SREG_T;
          else
          else
            sram[SREG] &= ~SREG_T;
            sram[SREG] &= ~SREG_T;
          break;
          break;
 
 
        case OP_sbrc:
        case OP_sbrc:
        case OP_sbrs:
        case OP_sbrs:
          if (((sram[get_d (op)] & flash[ipc].r) == 0) ^ ((op & 0x0200) != 0))
          if (((sram[get_d (op)] & flash[ipc].r) == 0) ^ ((op & 0x0200) != 0))
            {
            {
              int l = get_insn_length(pc);
              int l = get_insn_length(pc);
              pc += l;
              pc += l;
              cycles += l;
              cycles += l;
            }
            }
          break;
          break;
 
 
        case OP_push:
        case OP_push:
          {
          {
            unsigned int sp = read_word (REG_SP);
            unsigned int sp = read_word (REG_SP);
            sram[sp--] = sram[get_d (op)];
            sram[sp--] = sram[get_d (op)];
            write_word (REG_SP, sp);
            write_word (REG_SP, sp);
          }
          }
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_pop:
        case OP_pop:
          {
          {
            unsigned int sp = read_word (REG_SP);
            unsigned int sp = read_word (REG_SP);
            sram[get_d (op)] = sram[++sp];
            sram[get_d (op)] = sram[++sp];
            write_word (REG_SP, sp);
            write_word (REG_SP, sp);
          }
          }
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_bclr:
        case OP_bclr:
          sram[SREG] &= ~(1 << ((op >> 4) & 0x7));
          sram[SREG] &= ~(1 << ((op >> 4) & 0x7));
          break;
          break;
 
 
        case OP_bset:
        case OP_bset:
          sram[SREG] |= 1 << ((op >> 4) & 0x7);
          sram[SREG] |= 1 << ((op >> 4) & 0x7);
          break;
          break;
 
 
        case OP_rjmp:
        case OP_rjmp:
          pc = (pc + sign_ext (op & 0xfff, 12)) & PC_MASK;
          pc = (pc + sign_ext (op & 0xfff, 12)) & PC_MASK;
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_eor:
        case OP_eor:
          d = get_d (op);
          d = get_d (op);
          res = sram[d] ^ sram[get_r (op)];
          res = sram[d] ^ sram[get_r (op)];
          sram[d] = res;
          sram[d] = res;
          update_flags_logic (res);
          update_flags_logic (res);
          break;
          break;
 
 
        case OP_and:
        case OP_and:
          d = get_d (op);
          d = get_d (op);
          res = sram[d] & sram[get_r (op)];
          res = sram[d] & sram[get_r (op)];
          sram[d] = res;
          sram[d] = res;
          update_flags_logic (res);
          update_flags_logic (res);
          break;
          break;
 
 
        case OP_andi:
        case OP_andi:
          d = get_d16 (op);
          d = get_d16 (op);
          res = sram[d] & get_K (op);
          res = sram[d] & get_K (op);
          sram[d] = res;
          sram[d] = res;
          update_flags_logic (res);
          update_flags_logic (res);
          break;
          break;
 
 
        case OP_or:
        case OP_or:
          d = get_d (op);
          d = get_d (op);
          res = sram[d] | sram[get_r (op)];
          res = sram[d] | sram[get_r (op)];
          sram[d] = res;
          sram[d] = res;
          update_flags_logic (res);
          update_flags_logic (res);
          break;
          break;
 
 
        case OP_ori:
        case OP_ori:
          d = get_d16 (op);
          d = get_d16 (op);
          res = sram[d] | get_K (op);
          res = sram[d] | get_K (op);
          sram[d] = res;
          sram[d] = res;
          update_flags_logic (res);
          update_flags_logic (res);
          break;
          break;
 
 
        case OP_com:
        case OP_com:
          d = get_d (op);
          d = get_d (op);
          res = ~sram[d];
          res = ~sram[d];
          sram[d] = res;
          sram[d] = res;
          update_flags_logic (res);
          update_flags_logic (res);
          sram[SREG] |= SREG_C;
          sram[SREG] |= SREG_C;
          break;
          break;
 
 
        case OP_swap:
        case OP_swap:
          d = get_d (op);
          d = get_d (op);
          vd = sram[d];
          vd = sram[d];
          sram[d] = (vd >> 4) | (vd << 4);
          sram[d] = (vd >> 4) | (vd << 4);
          break;
          break;
 
 
        case OP_neg:
        case OP_neg:
          d = get_d (op);
          d = get_d (op);
          vd = sram[d];
          vd = sram[d];
          res = -vd;
          res = -vd;
          sram[d] = res;
          sram[d] = res;
          sram[SREG] &= ~(SREG_H | SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
          sram[SREG] &= ~(SREG_H | SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
          if (res == 0)
          if (res == 0)
            sram[SREG] |= SREG_Z;
            sram[SREG] |= SREG_Z;
          else
          else
            sram[SREG] |= SREG_C;
            sram[SREG] |= SREG_C;
          if (res == 0x80)
          if (res == 0x80)
            sram[SREG] |= SREG_V | SREG_N;
            sram[SREG] |= SREG_V | SREG_N;
          else if (res & 0x80)
          else if (res & 0x80)
            sram[SREG] |= SREG_N | SREG_S;
            sram[SREG] |= SREG_N | SREG_S;
          if ((res | vd) & 0x08)
          if ((res | vd) & 0x08)
            sram[SREG] |= SREG_H;
            sram[SREG] |= SREG_H;
          break;
          break;
 
 
        case OP_inc:
        case OP_inc:
          d = get_d (op);
          d = get_d (op);
          res = sram[d] + 1;
          res = sram[d] + 1;
          sram[d] = res;
          sram[d] = res;
          sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z);
          sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z);
          if (res == 0x80)
          if (res == 0x80)
            sram[SREG] |= SREG_V | SREG_N;
            sram[SREG] |= SREG_V | SREG_N;
          else if (res & 0x80)
          else if (res & 0x80)
            sram[SREG] |= SREG_N | SREG_S;
            sram[SREG] |= SREG_N | SREG_S;
          else if (res == 0)
          else if (res == 0)
            sram[SREG] |= SREG_Z;
            sram[SREG] |= SREG_Z;
          break;
          break;
 
 
        case OP_dec:
        case OP_dec:
          d = get_d (op);
          d = get_d (op);
          res = sram[d] - 1;
          res = sram[d] - 1;
          sram[d] = res;
          sram[d] = res;
          sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z);
          sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z);
          if (res == 0x7f)
          if (res == 0x7f)
            sram[SREG] |= SREG_V | SREG_S;
            sram[SREG] |= SREG_V | SREG_S;
          else if (res & 0x80)
          else if (res & 0x80)
            sram[SREG] |= SREG_N | SREG_S;
            sram[SREG] |= SREG_N | SREG_S;
          else if (res == 0)
          else if (res == 0)
            sram[SREG] |= SREG_Z;
            sram[SREG] |= SREG_Z;
          break;
          break;
 
 
        case OP_lsr:
        case OP_lsr:
        case OP_asr:
        case OP_asr:
          d = get_d (op);
          d = get_d (op);
          vd = sram[d];
          vd = sram[d];
          res = (vd >> 1) | (vd & flash[ipc].r);
          res = (vd >> 1) | (vd & flash[ipc].r);
          sram[d] = res;
          sram[d] = res;
          sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
          sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
          if (vd & 1)
          if (vd & 1)
            sram[SREG] |= SREG_C | SREG_S;
            sram[SREG] |= SREG_C | SREG_S;
          if (res & 0x80)
          if (res & 0x80)
            sram[SREG] |= SREG_N;
            sram[SREG] |= SREG_N;
          if (!(sram[SREG] & SREG_N) ^ !(sram[SREG] & SREG_C))
          if (!(sram[SREG] & SREG_N) ^ !(sram[SREG] & SREG_C))
            sram[SREG] |= SREG_V;
            sram[SREG] |= SREG_V;
          if (res == 0)
          if (res == 0)
            sram[SREG] |= SREG_Z;
            sram[SREG] |= SREG_Z;
          break;
          break;
 
 
        case OP_ror:
        case OP_ror:
          d = get_d (op);
          d = get_d (op);
          vd = sram[d];
          vd = sram[d];
          res = vd >> 1 | (sram[SREG] << 7);
          res = vd >> 1 | (sram[SREG] << 7);
          sram[d] = res;
          sram[d] = res;
          sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
          sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
          if (vd & 1)
          if (vd & 1)
            sram[SREG] |= SREG_C | SREG_S;
            sram[SREG] |= SREG_C | SREG_S;
          if (res & 0x80)
          if (res & 0x80)
            sram[SREG] |= SREG_N;
            sram[SREG] |= SREG_N;
          if (!(sram[SREG] & SREG_N) ^ !(sram[SREG] & SREG_C))
          if (!(sram[SREG] & SREG_N) ^ !(sram[SREG] & SREG_C))
            sram[SREG] |= SREG_V;
            sram[SREG] |= SREG_V;
          if (res == 0)
          if (res == 0)
            sram[SREG] |= SREG_Z;
            sram[SREG] |= SREG_Z;
          break;
          break;
 
 
        case OP_mul:
        case OP_mul:
          gen_mul ((word)sram[get_r (op)] * (word)sram[get_d (op)]);
          gen_mul ((word)sram[get_r (op)] * (word)sram[get_d (op)]);
          break;
          break;
 
 
        case OP_muls:
        case OP_muls:
          gen_mul((sword)(sbyte)sram[get_r16 (op)]
          gen_mul((sword)(sbyte)sram[get_r16 (op)]
                  * (sword)(sbyte)sram[get_d16 (op)]);
                  * (sword)(sbyte)sram[get_d16 (op)]);
          break;
          break;
 
 
        case OP_mulsu:
        case OP_mulsu:
          gen_mul ((sword)(word)sram[get_r16_23 (op)]
          gen_mul ((sword)(word)sram[get_r16_23 (op)]
                   * (sword)(sbyte)sram[get_d16_23 (op)]);
                   * (sword)(sbyte)sram[get_d16_23 (op)]);
          break;
          break;
 
 
        case OP_fmul:
        case OP_fmul:
          gen_mul(((word)sram[get_r16_23 (op)]
          gen_mul(((word)sram[get_r16_23 (op)]
                   * (word)sram[get_d16_23 (op)]) << 1);
                   * (word)sram[get_d16_23 (op)]) << 1);
          break;
          break;
 
 
        case OP_fmuls:
        case OP_fmuls:
          gen_mul(((sword)(sbyte)sram[get_r16_23 (op)]
          gen_mul(((sword)(sbyte)sram[get_r16_23 (op)]
                   * (sword)(sbyte)sram[get_d16_23 (op)]) << 1);
                   * (sword)(sbyte)sram[get_d16_23 (op)]) << 1);
          break;
          break;
 
 
        case OP_fmulsu:
        case OP_fmulsu:
          gen_mul(((sword)(word)sram[get_r16_23 (op)]
          gen_mul(((sword)(word)sram[get_r16_23 (op)]
                   * (sword)(sbyte)sram[get_d16_23 (op)]) << 1);
                   * (sword)(sbyte)sram[get_d16_23 (op)]) << 1);
          break;
          break;
 
 
        case OP_adc:
        case OP_adc:
        case OP_add:
        case OP_add:
          r = sram[get_r (op)];
          r = sram[get_r (op)];
          d = get_d (op);
          d = get_d (op);
          vd = sram[d];
          vd = sram[d];
          res = r + vd + (sram[SREG] & flash[ipc].r);
          res = r + vd + (sram[SREG] & flash[ipc].r);
          sram[d] = res;
          sram[d] = res;
          update_flags_add (res, vd, r);
          update_flags_add (res, vd, r);
          break;
          break;
 
 
        case OP_sub:
        case OP_sub:
          d = get_d (op);
          d = get_d (op);
          vd = sram[d];
          vd = sram[d];
          r = sram[get_r (op)];
          r = sram[get_r (op)];
          res = vd - r;
          res = vd - r;
          sram[d] = res;
          sram[d] = res;
          update_flags_sub (res, vd, r);
          update_flags_sub (res, vd, r);
          if (res == 0)
          if (res == 0)
            sram[SREG] |= SREG_Z;
            sram[SREG] |= SREG_Z;
          break;
          break;
 
 
        case OP_sbc:
        case OP_sbc:
          {
          {
            byte old = sram[SREG];
            byte old = sram[SREG];
            d = get_d (op);
            d = get_d (op);
            vd = sram[d];
            vd = sram[d];
            r = sram[get_r (op)];
            r = sram[get_r (op)];
            res = vd - r - (old & SREG_C);
            res = vd - r - (old & SREG_C);
            sram[d] = res;
            sram[d] = res;
            update_flags_sub (res, vd, r);
            update_flags_sub (res, vd, r);
            if (res == 0 && (old & SREG_Z))
            if (res == 0 && (old & SREG_Z))
              sram[SREG] |= SREG_Z;
              sram[SREG] |= SREG_Z;
          }
          }
          break;
          break;
 
 
        case OP_subi:
        case OP_subi:
          d = get_d16 (op);
          d = get_d16 (op);
          vd = sram[d];
          vd = sram[d];
          r = get_K (op);
          r = get_K (op);
          res = vd - r;
          res = vd - r;
          sram[d] = res;
          sram[d] = res;
          update_flags_sub (res, vd, r);
          update_flags_sub (res, vd, r);
          if (res == 0)
          if (res == 0)
            sram[SREG] |= SREG_Z;
            sram[SREG] |= SREG_Z;
          break;
          break;
 
 
        case OP_sbci:
        case OP_sbci:
          {
          {
            byte old = sram[SREG];
            byte old = sram[SREG];
 
 
            d = get_d16 (op);
            d = get_d16 (op);
            vd = sram[d];
            vd = sram[d];
            r = get_K (op);
            r = get_K (op);
            res = vd - r - (old & SREG_C);
            res = vd - r - (old & SREG_C);
            sram[d] = res;
            sram[d] = res;
            update_flags_sub (res, vd, r);
            update_flags_sub (res, vd, r);
            if (res == 0 && (old & SREG_Z))
            if (res == 0 && (old & SREG_Z))
              sram[SREG] |= SREG_Z;
              sram[SREG] |= SREG_Z;
          }
          }
          break;
          break;
 
 
        case OP_mov:
        case OP_mov:
          sram[get_d (op)] = sram[get_r (op)];
          sram[get_d (op)] = sram[get_r (op)];
          break;
          break;
 
 
        case OP_movw:
        case OP_movw:
          d = (op & 0xf0) >> 3;
          d = (op & 0xf0) >> 3;
          r = (op & 0x0f) << 1;
          r = (op & 0x0f) << 1;
          sram[d] = sram[r];
          sram[d] = sram[r];
          sram[d + 1] = sram[r + 1];
          sram[d + 1] = sram[r + 1];
          break;
          break;
 
 
        case OP_out:
        case OP_out:
          d = get_A (op) + 0x20;
          d = get_A (op) + 0x20;
          res = sram[get_d (op)];
          res = sram[get_d (op)];
          sram[d] = res;
          sram[d] = res;
          if (d == STDIO_PORT)
          if (d == STDIO_PORT)
            putchar (res);
            putchar (res);
          else if (d == EXIT_PORT)
          else if (d == EXIT_PORT)
            {
            {
              cpu_exception = sim_exited;
              cpu_exception = sim_exited;
              cpu_signal = 0;
              cpu_signal = 0;
              return;
              return;
            }
            }
          else if (d == ABORT_PORT)
          else if (d == ABORT_PORT)
            {
            {
              cpu_exception = sim_exited;
              cpu_exception = sim_exited;
              cpu_signal = 1;
              cpu_signal = 1;
              return;
              return;
            }
            }
          break;
          break;
 
 
        case OP_in:
        case OP_in:
          d = get_A (op) + 0x20;
          d = get_A (op) + 0x20;
          sram[get_d (op)] = sram[d];
          sram[get_d (op)] = sram[d];
          break;
          break;
 
 
        case OP_cbi:
        case OP_cbi:
          d = get_biA (op) + 0x20;
          d = get_biA (op) + 0x20;
          sram[d] &= ~(1 << get_b(op));
          sram[d] &= ~(1 << get_b(op));
          break;
          break;
 
 
        case OP_sbi:
        case OP_sbi:
          d = get_biA (op) + 0x20;
          d = get_biA (op) + 0x20;
          sram[d] |= 1 << get_b(op);
          sram[d] |= 1 << get_b(op);
          break;
          break;
 
 
        case OP_sbic:
        case OP_sbic:
          if (!(sram[get_biA (op) + 0x20] & 1 << get_b(op)))
          if (!(sram[get_biA (op) + 0x20] & 1 << get_b(op)))
            {
            {
              int l = get_insn_length(pc);
              int l = get_insn_length(pc);
              pc += l;
              pc += l;
              cycles += l;
              cycles += l;
            }
            }
          break;
          break;
 
 
        case OP_sbis:
        case OP_sbis:
          if (sram[get_biA (op) + 0x20] & 1 << get_b(op))
          if (sram[get_biA (op) + 0x20] & 1 << get_b(op))
            {
            {
              int l = get_insn_length(pc);
              int l = get_insn_length(pc);
              pc += l;
              pc += l;
              cycles += l;
              cycles += l;
            }
            }
          break;
          break;
 
 
        case OP_ldi:
        case OP_ldi:
          res = get_K (op);
          res = get_K (op);
          d = get_d16 (op);
          d = get_d16 (op);
          sram[d] = res;
          sram[d] = res;
          break;
          break;
 
 
        case OP_lds:
        case OP_lds:
          sram[get_d (op)] = sram[flash[pc].op];
          sram[get_d (op)] = sram[flash[pc].op];
          pc++;
          pc++;
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_sts:
        case OP_sts:
          sram[flash[pc].op] = sram[get_d (op)];
          sram[flash[pc].op] = sram[get_d (op)];
          pc++;
          pc++;
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_cpse:
        case OP_cpse:
          if (sram[get_r (op)] == sram[get_d (op)])
          if (sram[get_r (op)] == sram[get_d (op)])
            {
            {
              int l = get_insn_length(pc);
              int l = get_insn_length(pc);
              pc += l;
              pc += l;
              cycles += l;
              cycles += l;
            }
            }
          break;
          break;
 
 
        case OP_cp:
        case OP_cp:
          r = sram[get_r (op)];
          r = sram[get_r (op)];
          d = sram[get_d (op)];
          d = sram[get_d (op)];
          res = d - r;
          res = d - r;
          update_flags_sub (res, d, r);
          update_flags_sub (res, d, r);
          if (res == 0)
          if (res == 0)
            sram[SREG] |= SREG_Z;
            sram[SREG] |= SREG_Z;
          break;
          break;
 
 
        case OP_cpi:
        case OP_cpi:
          r = get_K (op);
          r = get_K (op);
          d = sram[get_d16 (op)];
          d = sram[get_d16 (op)];
          res = d - r;
          res = d - r;
          update_flags_sub (res, d, r);
          update_flags_sub (res, d, r);
          if (res == 0)
          if (res == 0)
            sram[SREG] |= SREG_Z;
            sram[SREG] |= SREG_Z;
          break;
          break;
 
 
        case OP_cpc:
        case OP_cpc:
          {
          {
            byte old = sram[SREG];
            byte old = sram[SREG];
            d = sram[get_d (op)];
            d = sram[get_d (op)];
            r = sram[get_r (op)];
            r = sram[get_r (op)];
            res = d - r - (old & SREG_C);
            res = d - r - (old & SREG_C);
            update_flags_sub (res, d, r);
            update_flags_sub (res, d, r);
            if (res == 0 && (old & SREG_Z))
            if (res == 0 && (old & SREG_Z))
              sram[SREG] |= SREG_Z;
              sram[SREG] |= SREG_Z;
          }
          }
          break;
          break;
 
 
        case OP_brbc:
        case OP_brbc:
          if (!(sram[SREG] & flash[ipc].r))
          if (!(sram[SREG] & flash[ipc].r))
            {
            {
              pc = (pc + get_k (op)) & PC_MASK;
              pc = (pc + get_k (op)) & PC_MASK;
              cycles++;
              cycles++;
            }
            }
          break;
          break;
 
 
        case OP_brbs:
        case OP_brbs:
          if (sram[SREG] & flash[ipc].r)
          if (sram[SREG] & flash[ipc].r)
            {
            {
              pc = (pc + get_k (op)) & PC_MASK;
              pc = (pc + get_k (op)) & PC_MASK;
              cycles++;
              cycles++;
            }
            }
          break;
          break;
 
 
        case OP_lpm:
        case OP_lpm:
          sram[0] = get_lpm (read_word (REGZ));
          sram[0] = get_lpm (read_word (REGZ));
          cycles += 2;
          cycles += 2;
          break;
          break;
 
 
        case OP_lpm_Z:
        case OP_lpm_Z:
          sram[get_d (op)] = get_lpm (read_word (REGZ));
          sram[get_d (op)] = get_lpm (read_word (REGZ));
          cycles += 2;
          cycles += 2;
          break;
          break;
 
 
        case OP_lpm_inc_Z:
        case OP_lpm_inc_Z:
          sram[get_d (op)] = get_lpm (read_word_post_inc (REGZ));
          sram[get_d (op)] = get_lpm (read_word_post_inc (REGZ));
          cycles += 2;
          cycles += 2;
          break;
          break;
 
 
        case OP_elpm:
        case OP_elpm:
          sram[0] = get_lpm (get_z ());
          sram[0] = get_lpm (get_z ());
          cycles += 2;
          cycles += 2;
          break;
          break;
 
 
        case OP_elpm_Z:
        case OP_elpm_Z:
          sram[get_d (op)] = get_lpm (get_z ());
          sram[get_d (op)] = get_lpm (get_z ());
          cycles += 2;
          cycles += 2;
          break;
          break;
 
 
        case OP_elpm_inc_Z:
        case OP_elpm_inc_Z:
          {
          {
            unsigned int z = get_z ();
            unsigned int z = get_z ();
 
 
            sram[get_d (op)] = get_lpm (z);
            sram[get_d (op)] = get_lpm (z);
            z++;
            z++;
            sram[REGZ_LO] = z;
            sram[REGZ_LO] = z;
            sram[REGZ_HI] = z >> 8;
            sram[REGZ_HI] = z >> 8;
            sram[RAMPZ] = z >> 16;
            sram[RAMPZ] = z >> 16;
          }
          }
          cycles += 2;
          cycles += 2;
          break;
          break;
 
 
        case OP_ld_Z_inc:
        case OP_ld_Z_inc:
          sram[get_d (op)] = sram[read_word_post_inc (REGZ) & SRAM_MASK];
          sram[get_d (op)] = sram[read_word_post_inc (REGZ) & SRAM_MASK];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_ld_dec_Z:
        case OP_ld_dec_Z:
          sram[get_d (op)] = sram[read_word_pre_dec (REGZ) & SRAM_MASK];
          sram[get_d (op)] = sram[read_word_pre_dec (REGZ) & SRAM_MASK];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_ld_X_inc:
        case OP_ld_X_inc:
          sram[get_d (op)] = sram[read_word_post_inc (REGX) & SRAM_MASK];
          sram[get_d (op)] = sram[read_word_post_inc (REGX) & SRAM_MASK];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_ld_dec_X:
        case OP_ld_dec_X:
          sram[get_d (op)] = sram[read_word_pre_dec (REGX) & SRAM_MASK];
          sram[get_d (op)] = sram[read_word_pre_dec (REGX) & SRAM_MASK];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_ld_Y_inc:
        case OP_ld_Y_inc:
          sram[get_d (op)] = sram[read_word_post_inc (REGY) & SRAM_MASK];
          sram[get_d (op)] = sram[read_word_post_inc (REGY) & SRAM_MASK];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_ld_dec_Y:
        case OP_ld_dec_Y:
          sram[get_d (op)] = sram[read_word_pre_dec (REGY) & SRAM_MASK];
          sram[get_d (op)] = sram[read_word_pre_dec (REGY) & SRAM_MASK];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_st_X:
        case OP_st_X:
          sram[read_word (REGX) & SRAM_MASK] = sram[get_d (op)];
          sram[read_word (REGX) & SRAM_MASK] = sram[get_d (op)];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_st_X_inc:
        case OP_st_X_inc:
          sram[read_word_post_inc (REGX) & SRAM_MASK] = sram[get_d (op)];
          sram[read_word_post_inc (REGX) & SRAM_MASK] = sram[get_d (op)];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_st_dec_X:
        case OP_st_dec_X:
          sram[read_word_pre_dec (REGX) & SRAM_MASK] = sram[get_d (op)];
          sram[read_word_pre_dec (REGX) & SRAM_MASK] = sram[get_d (op)];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_st_Z_inc:
        case OP_st_Z_inc:
          sram[read_word_post_inc (REGZ) & SRAM_MASK] = sram[get_d (op)];
          sram[read_word_post_inc (REGZ) & SRAM_MASK] = sram[get_d (op)];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_st_dec_Z:
        case OP_st_dec_Z:
          sram[read_word_pre_dec (REGZ) & SRAM_MASK] = sram[get_d (op)];
          sram[read_word_pre_dec (REGZ) & SRAM_MASK] = sram[get_d (op)];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_st_Y_inc:
        case OP_st_Y_inc:
          sram[read_word_post_inc (REGY) & SRAM_MASK] = sram[get_d (op)];
          sram[read_word_post_inc (REGY) & SRAM_MASK] = sram[get_d (op)];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_st_dec_Y:
        case OP_st_dec_Y:
          sram[read_word_pre_dec (REGY) & SRAM_MASK] = sram[get_d (op)];
          sram[read_word_pre_dec (REGY) & SRAM_MASK] = sram[get_d (op)];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_std_Y:
        case OP_std_Y:
          sram[read_word (REGY) + flash[ipc].r] = sram[get_d (op)];
          sram[read_word (REGY) + flash[ipc].r] = sram[get_d (op)];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_std_Z:
        case OP_std_Z:
          sram[read_word (REGZ) + flash[ipc].r] = sram[get_d (op)];
          sram[read_word (REGZ) + flash[ipc].r] = sram[get_d (op)];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_ldd_Z:
        case OP_ldd_Z:
          sram[get_d (op)] = sram[read_word (REGZ) + flash[ipc].r];
          sram[get_d (op)] = sram[read_word (REGZ) + flash[ipc].r];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_ldd_Y:
        case OP_ldd_Y:
          sram[get_d (op)] = sram[read_word (REGY) + flash[ipc].r];
          sram[get_d (op)] = sram[read_word (REGY) + flash[ipc].r];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_ld_X:
        case OP_ld_X:
          sram[get_d (op)] = sram[read_word (REGX) & SRAM_MASK];
          sram[get_d (op)] = sram[read_word (REGX) & SRAM_MASK];
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_sbiw:
        case OP_sbiw:
          {
          {
            word wk = get_k6 (op);
            word wk = get_k6 (op);
            word wres;
            word wres;
            word wr;
            word wr;
 
 
            d = get_d24 (op);
            d = get_d24 (op);
            wr = read_word (d);
            wr = read_word (d);
            wres = wr - wk;
            wres = wr - wk;
 
 
            sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
            sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
            if (wres == 0)
            if (wres == 0)
              sram[SREG] |= SREG_Z;
              sram[SREG] |= SREG_Z;
            if (wres & 0x8000)
            if (wres & 0x8000)
              sram[SREG] |= SREG_N;
              sram[SREG] |= SREG_N;
            if (wres & ~wr & 0x8000)
            if (wres & ~wr & 0x8000)
              sram[SREG] |= SREG_C;
              sram[SREG] |= SREG_C;
            if (~wres & wr & 0x8000)
            if (~wres & wr & 0x8000)
              sram[SREG] |= SREG_V;
              sram[SREG] |= SREG_V;
            if (((~wres & wr) ^ wres) & 0x8000)
            if (((~wres & wr) ^ wres) & 0x8000)
              sram[SREG] |= SREG_S;
              sram[SREG] |= SREG_S;
            write_word (d, wres);
            write_word (d, wres);
          }
          }
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_adiw:
        case OP_adiw:
          {
          {
            word wk = get_k6 (op);
            word wk = get_k6 (op);
            word wres;
            word wres;
            word wr;
            word wr;
 
 
            d = get_d24 (op);
            d = get_d24 (op);
            wr = read_word (d);
            wr = read_word (d);
            wres = wr + wk;
            wres = wr + wk;
 
 
            sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
            sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
            if (wres == 0)
            if (wres == 0)
              sram[SREG] |= SREG_Z;
              sram[SREG] |= SREG_Z;
            if (wres & 0x8000)
            if (wres & 0x8000)
              sram[SREG] |= SREG_N;
              sram[SREG] |= SREG_N;
            if (~wres & wr & 0x8000)
            if (~wres & wr & 0x8000)
              sram[SREG] |= SREG_C;
              sram[SREG] |= SREG_C;
            if (wres & ~wr & 0x8000)
            if (wres & ~wr & 0x8000)
              sram[SREG] |= SREG_V;
              sram[SREG] |= SREG_V;
            if (((wres & ~wr) ^ wres) & 0x8000)
            if (((wres & ~wr) ^ wres) & 0x8000)
              sram[SREG] |= SREG_S;
              sram[SREG] |= SREG_S;
            write_word (d, wres);
            write_word (d, wres);
          }
          }
          cycles++;
          cycles++;
          break;
          break;
 
 
        case OP_bad:
        case OP_bad:
          sim_cb_eprintf (callback, "Bad instruction at pc=0x%x\n", ipc * 2);
          sim_cb_eprintf (callback, "Bad instruction at pc=0x%x\n", ipc * 2);
          return;
          return;
 
 
        default:
        default:
          sim_cb_eprintf (callback,
          sim_cb_eprintf (callback,
                          "Unhandled instruction at pc=0x%x, code=%d\n",
                          "Unhandled instruction at pc=0x%x, code=%d\n",
                          2 * ipc, code);
                          2 * ipc, code);
          return;
          return;
        }
        }
    }
    }
  while (cpu_exception == sim_running);
  while (cpu_exception == sim_running);
}
}
 
 
 
 
int
int
sim_trace (SIM_DESC sd)
sim_trace (SIM_DESC sd)
{
{
  tracing = 1;
  tracing = 1;
 
 
  sim_resume (sd, 0, 0);
  sim_resume (sd, 0, 0);
 
 
  tracing = 0;
  tracing = 0;
 
 
  return 1;
  return 1;
}
}
 
 
int
int
sim_write (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
sim_write (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
{
{
  int osize = size;
  int osize = size;
 
 
  if (addr >= 0 && addr < SRAM_VADDR)
  if (addr >= 0 && addr < SRAM_VADDR)
    {
    {
      while (size > 0 && addr < (MAX_AVR_FLASH << 1))
      while (size > 0 && addr < (MAX_AVR_FLASH << 1))
        {
        {
          word val = flash[addr >> 1].op;
          word val = flash[addr >> 1].op;
 
 
          if (addr & 1)
          if (addr & 1)
            val = (val & 0xff) | (buffer[0] << 8);
            val = (val & 0xff) | (buffer[0] << 8);
          else
          else
            val = (val & 0xff00) | buffer[0];
            val = (val & 0xff00) | buffer[0];
 
 
          flash[addr >> 1].op = val;
          flash[addr >> 1].op = val;
          flash[addr >> 1].code = OP_unknown;
          flash[addr >> 1].code = OP_unknown;
          addr++;
          addr++;
          buffer++;
          buffer++;
          size--;
          size--;
        }
        }
      return osize - size;
      return osize - size;
    }
    }
  else if (addr >= SRAM_VADDR && addr < SRAM_VADDR + MAX_AVR_SRAM)
  else if (addr >= SRAM_VADDR && addr < SRAM_VADDR + MAX_AVR_SRAM)
    {
    {
      addr -= SRAM_VADDR;
      addr -= SRAM_VADDR;
      if (addr + size > MAX_AVR_SRAM)
      if (addr + size > MAX_AVR_SRAM)
        size = MAX_AVR_SRAM - addr;
        size = MAX_AVR_SRAM - addr;
      memcpy (sram + addr, buffer, size);
      memcpy (sram + addr, buffer, size);
      return size;
      return size;
    }
    }
  else
  else
    return 0;
    return 0;
}
}
 
 
int
int
sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
{
{
  int osize = size;
  int osize = size;
 
 
  if (addr >= 0 && addr < SRAM_VADDR)
  if (addr >= 0 && addr < SRAM_VADDR)
    {
    {
      while (size > 0 && addr < (MAX_AVR_FLASH << 1))
      while (size > 0 && addr < (MAX_AVR_FLASH << 1))
        {
        {
          word val = flash[addr >> 1].op;
          word val = flash[addr >> 1].op;
 
 
          if (addr & 1)
          if (addr & 1)
            val >>= 8;
            val >>= 8;
 
 
          *buffer++ = val;
          *buffer++ = val;
          addr++;
          addr++;
          size--;
          size--;
        }
        }
      return osize - size;
      return osize - size;
    }
    }
  else if (addr >= SRAM_VADDR && addr < SRAM_VADDR + MAX_AVR_SRAM)
  else if (addr >= SRAM_VADDR && addr < SRAM_VADDR + MAX_AVR_SRAM)
    {
    {
      addr -= SRAM_VADDR;
      addr -= SRAM_VADDR;
      if (addr + size > MAX_AVR_SRAM)
      if (addr + size > MAX_AVR_SRAM)
        size = MAX_AVR_SRAM - addr;
        size = MAX_AVR_SRAM - addr;
      memcpy (buffer, sram + addr, size);
      memcpy (buffer, sram + addr, size);
      return size;
      return size;
    }
    }
  else
  else
    {
    {
      /* Avoid errors.  */
      /* Avoid errors.  */
      memset (buffer, 0, size);
      memset (buffer, 0, size);
      return size;
      return size;
    }
    }
}
}
 
 
int
int
sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
{
{
  if (rn < 32 && length == 1)
  if (rn < 32 && length == 1)
    {
    {
      sram[rn] = *memory;
      sram[rn] = *memory;
      return 1;
      return 1;
    }
    }
  if (rn == AVR_SREG_REGNUM && length == 1)
  if (rn == AVR_SREG_REGNUM && length == 1)
    {
    {
      sram[SREG] = *memory;
      sram[SREG] = *memory;
      return 1;
      return 1;
    }
    }
  if (rn == AVR_SP_REGNUM && length == 2)
  if (rn == AVR_SP_REGNUM && length == 2)
    {
    {
      sram[REG_SP] = memory[0];
      sram[REG_SP] = memory[0];
      sram[REG_SP + 1] = memory[1];
      sram[REG_SP + 1] = memory[1];
      return 2;
      return 2;
    }
    }
  if (rn == AVR_PC_REGNUM && length == 4)
  if (rn == AVR_PC_REGNUM && length == 4)
    {
    {
      pc = (memory[0] >> 1) | (memory[1] << 7)
      pc = (memory[0] >> 1) | (memory[1] << 7)
        | (memory[2] << 15) | (memory[3] << 23);
        | (memory[2] << 15) | (memory[3] << 23);
      pc &= PC_MASK;
      pc &= PC_MASK;
      return 4;
      return 4;
    }
    }
  return 0;
  return 0;
}
}
 
 
int
int
sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
{
{
  if (rn < 32 && length == 1)
  if (rn < 32 && length == 1)
    {
    {
      *memory = sram[rn];
      *memory = sram[rn];
      return 1;
      return 1;
    }
    }
  if (rn == AVR_SREG_REGNUM && length == 1)
  if (rn == AVR_SREG_REGNUM && length == 1)
    {
    {
      *memory = sram[SREG];
      *memory = sram[SREG];
      return 1;
      return 1;
    }
    }
  if (rn == AVR_SP_REGNUM && length == 2)
  if (rn == AVR_SP_REGNUM && length == 2)
    {
    {
      memory[0] = sram[REG_SP];
      memory[0] = sram[REG_SP];
      memory[1] = sram[REG_SP + 1];
      memory[1] = sram[REG_SP + 1];
      return 2;
      return 2;
    }
    }
  if (rn == AVR_PC_REGNUM && length == 4)
  if (rn == AVR_PC_REGNUM && length == 4)
    {
    {
      memory[0] = pc << 1;
      memory[0] = pc << 1;
      memory[1] = pc >> 7;
      memory[1] = pc >> 7;
      memory[2] = pc >> 15;
      memory[2] = pc >> 15;
      memory[3] = pc >> 23;
      memory[3] = pc >> 23;
      return 4;
      return 4;
    }
    }
  return 0;
  return 0;
}
}
 
 
void
void
sim_stop_reason (SIM_DESC sd, enum sim_stop * reason,  int *sigrc)
sim_stop_reason (SIM_DESC sd, enum sim_stop * reason,  int *sigrc)
{
{
  *reason = cpu_exception;
  *reason = cpu_exception;
  *sigrc = cpu_signal;
  *sigrc = cpu_signal;
}
}
 
 
int
int
sim_stop (SIM_DESC sd)
sim_stop (SIM_DESC sd)
{
{
  cpu_exception = sim_stopped;
  cpu_exception = sim_stopped;
  cpu_signal = TARGET_SIGNAL_INT;
  cpu_signal = TARGET_SIGNAL_INT;
  return 1;
  return 1;
}
}
 
 
void
void
sim_info (SIM_DESC sd, int verbose)
sim_info (SIM_DESC sd, int verbose)
{
{
  callback->printf_filtered
  callback->printf_filtered
    (callback, "\n\n# cycles  %10u\n", cycles);
    (callback, "\n\n# cycles  %10u\n", cycles);
}
}
 
 
SIM_DESC
SIM_DESC
sim_open (SIM_OPEN_KIND kind, host_callback *cb, struct bfd *abfd, char **argv)
sim_open (SIM_OPEN_KIND kind, host_callback *cb, struct bfd *abfd, char **argv)
{
{
  myname = argv[0];
  myname = argv[0];
  callback = cb;
  callback = cb;
 
 
  cur_bfd = abfd;
  cur_bfd = abfd;
 
 
  /* Fudge our descriptor for now.  */
  /* Fudge our descriptor for now.  */
  return (SIM_DESC) 1;
  return (SIM_DESC) 1;
}
}
 
 
void
void
sim_close (SIM_DESC sd, int quitting)
sim_close (SIM_DESC sd, int quitting)
{
{
  /* nothing to do */
  /* nothing to do */
}
}
 
 
SIM_RC
SIM_RC
sim_load (SIM_DESC sd, char *prog, bfd *abfd, int from_tty)
sim_load (SIM_DESC sd, char *prog, bfd *abfd, int from_tty)
{
{
  bfd *prog_bfd;
  bfd *prog_bfd;
 
 
  /* Clear all the memory.  */
  /* Clear all the memory.  */
  memset (sram, 0, sizeof (sram));
  memset (sram, 0, sizeof (sram));
  memset (flash, 0, sizeof (flash));
  memset (flash, 0, sizeof (flash));
 
 
  prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
  prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
                            sim_kind == SIM_OPEN_DEBUG,
                            sim_kind == SIM_OPEN_DEBUG,
                            0, sim_write);
                            0, sim_write);
  if (prog_bfd == NULL)
  if (prog_bfd == NULL)
    return SIM_RC_FAIL;
    return SIM_RC_FAIL;
 
 
  avr_pc22 = (bfd_get_mach (prog_bfd) >= bfd_mach_avr6);
  avr_pc22 = (bfd_get_mach (prog_bfd) >= bfd_mach_avr6);
 
 
  if (abfd != NULL)
  if (abfd != NULL)
    cur_bfd = abfd;
    cur_bfd = abfd;
 
 
  return SIM_RC_OK;
  return SIM_RC_OK;
}
}
 
 
SIM_RC
SIM_RC
sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, char **argv, char **env)
sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, char **argv, char **env)
{
{
  /* Set the initial register set.  */
  /* Set the initial register set.  */
  pc = 0;
  pc = 0;
 
 
  return SIM_RC_OK;
  return SIM_RC_OK;
}
}
 
 
void
void
sim_kill (SIM_DESC sd)
sim_kill (SIM_DESC sd)
{
{
  /* nothing to do */
  /* nothing to do */
}
}
 
 
void
void
sim_do_command (SIM_DESC sd, char *cmd)
sim_do_command (SIM_DESC sd, char *cmd)
{
{
  /* Nothing there yet; it's all an error.  */
  /* Nothing there yet; it's all an error.  */
 
 
  if (cmd == NULL)
  if (cmd == NULL)
    return;
    return;
 
 
  if (strcmp (cmd, "verbose") == 0)
  if (strcmp (cmd, "verbose") == 0)
    verbose = 2;
    verbose = 2;
  else if (strcmp (cmd, "trace") == 0)
  else if (strcmp (cmd, "trace") == 0)
    tracing = 1;
    tracing = 1;
  else
  else
    sim_cb_eprintf (callback,
    sim_cb_eprintf (callback,
                    "Error: \"%s\" is not a valid avr simulator command.\n",
                    "Error: \"%s\" is not a valid avr simulator command.\n",
                    cmd);
                    cmd);
}
}
 
 
void
void
sim_set_callbacks (host_callback *ptr)
sim_set_callbacks (host_callback *ptr)
{
{
  callback = ptr;
  callback = ptr;
}
}
 
 

powered by: WebSVN 2.1.0

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