xref: /netbsd-src/external/gpl3/gdb/dist/sim/avr/interp.c (revision 88241920d21b339bf319c0e979ffda80c49a2936)
198b9484cSchristos /* Simulator for Atmel's AVR core.
2*88241920Schristos    Copyright (C) 2009-2024 Free Software Foundation, Inc.
398b9484cSchristos    Written by Tristan Gingold, AdaCore.
498b9484cSchristos 
598b9484cSchristos    This file is part of GDB, the GNU debugger.
698b9484cSchristos 
798b9484cSchristos    This program is free software; you can redistribute it and/or modify
898b9484cSchristos    it under the terms of the GNU General Public License as published by
998b9484cSchristos    the Free Software Foundation; either version 3 of the License, or
1098b9484cSchristos    (at your option) any later version.
1198b9484cSchristos 
1298b9484cSchristos    This program is distributed in the hope that it will be useful,
1398b9484cSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1498b9484cSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1598b9484cSchristos    GNU General Public License for more details.
1698b9484cSchristos 
1798b9484cSchristos    You should have received a copy of the GNU General Public License
1898b9484cSchristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
1998b9484cSchristos 
204b169a6bSchristos /* This must come before any other includes.  */
214b169a6bSchristos #include "defs.h"
2298b9484cSchristos 
2398b9484cSchristos #include <string.h>
244b169a6bSchristos 
2598b9484cSchristos #include "bfd.h"
2698b9484cSchristos #include "libiberty.h"
274b169a6bSchristos #include "sim/sim.h"
28212397c6Schristos 
29212397c6Schristos #include "sim-main.h"
30212397c6Schristos #include "sim-base.h"
31212397c6Schristos #include "sim-options.h"
324b169a6bSchristos #include "sim-signal.h"
33*88241920Schristos #include "avr-sim.h"
3498b9484cSchristos 
3598b9484cSchristos /* As AVR is a 8/16 bits processor, define handy types.  */
3698b9484cSchristos typedef unsigned short int word;
3798b9484cSchristos typedef signed short int sword;
3898b9484cSchristos typedef unsigned char byte;
3998b9484cSchristos typedef signed char sbyte;
4098b9484cSchristos 
4198b9484cSchristos /* Max size of I space (which is always flash on avr).  */
4298b9484cSchristos #define MAX_AVR_FLASH (128 * 1024)
4398b9484cSchristos #define PC_MASK (MAX_AVR_FLASH - 1)
4498b9484cSchristos 
4598b9484cSchristos /* Mac size of D space.  */
4698b9484cSchristos #define MAX_AVR_SRAM (64 * 1024)
4798b9484cSchristos #define SRAM_MASK (MAX_AVR_SRAM - 1)
4898b9484cSchristos 
4998b9484cSchristos /* D space offset in ELF file.  */
5098b9484cSchristos #define SRAM_VADDR 0x800000
5198b9484cSchristos 
5298b9484cSchristos /* Simulator specific ports.  */
5398b9484cSchristos #define STDIO_PORT	0x52
5498b9484cSchristos #define EXIT_PORT	0x4F
5598b9484cSchristos #define ABORT_PORT	0x49
5698b9484cSchristos 
5798b9484cSchristos /* GDB defined register numbers.  */
5898b9484cSchristos #define AVR_SREG_REGNUM  32
5998b9484cSchristos #define AVR_SP_REGNUM    33
6098b9484cSchristos #define AVR_PC_REGNUM    34
6198b9484cSchristos 
6298b9484cSchristos /* Memory mapped registers.  */
6398b9484cSchristos #define SREG	0x5F
6498b9484cSchristos #define REG_SP	0x5D
6598b9484cSchristos #define EIND	0x5C
6698b9484cSchristos #define RAMPZ	0x5B
6798b9484cSchristos 
6898b9484cSchristos #define REGX 0x1a
6998b9484cSchristos #define REGY 0x1c
7098b9484cSchristos #define REGZ 0x1e
7198b9484cSchristos #define REGZ_LO 0x1e
7298b9484cSchristos #define REGZ_HI 0x1f
7398b9484cSchristos 
7498b9484cSchristos /* Sreg (status) bits.  */
7598b9484cSchristos #define SREG_I 0x80
7698b9484cSchristos #define SREG_T 0x40
7798b9484cSchristos #define SREG_H 0x20
7898b9484cSchristos #define SREG_S 0x10
7998b9484cSchristos #define SREG_V 0x08
8098b9484cSchristos #define SREG_N 0x04
8198b9484cSchristos #define SREG_Z 0x02
8298b9484cSchristos #define SREG_C 0x01
8398b9484cSchristos 
8498b9484cSchristos /* In order to speed up emulation we use a simple approach:
8598b9484cSchristos    a code is associated with each instruction.  The pre-decoding occurs
8698b9484cSchristos    usually once when the instruction is first seen.
8798b9484cSchristos    This works well because I&D spaces are separated.
8898b9484cSchristos 
8998b9484cSchristos    Missing opcodes: sleep, spm, wdr (as they are mmcu dependent).
9098b9484cSchristos */
9198b9484cSchristos enum avr_opcode
9298b9484cSchristos   {
9398b9484cSchristos     /* Opcode not yet decoded.  */
9498b9484cSchristos     OP_unknown,
9598b9484cSchristos     OP_bad,
9698b9484cSchristos 
9798b9484cSchristos     OP_nop,
9898b9484cSchristos 
9998b9484cSchristos     OP_rjmp,
10098b9484cSchristos     OP_rcall,
10198b9484cSchristos     OP_ret,
10298b9484cSchristos     OP_reti,
10398b9484cSchristos 
10498b9484cSchristos     OP_break,
10598b9484cSchristos 
10698b9484cSchristos     OP_brbs,
10798b9484cSchristos     OP_brbc,
10898b9484cSchristos 
10998b9484cSchristos     OP_bset,
11098b9484cSchristos     OP_bclr,
11198b9484cSchristos 
11298b9484cSchristos     OP_bld,
11398b9484cSchristos     OP_bst,
11498b9484cSchristos 
11598b9484cSchristos     OP_sbrc,
11698b9484cSchristos     OP_sbrs,
11798b9484cSchristos 
11898b9484cSchristos     OP_eor,
11998b9484cSchristos     OP_and,
12098b9484cSchristos     OP_andi,
12198b9484cSchristos     OP_or,
12298b9484cSchristos     OP_ori,
12398b9484cSchristos     OP_com,
12498b9484cSchristos     OP_swap,
12598b9484cSchristos     OP_neg,
12698b9484cSchristos 
12798b9484cSchristos     OP_out,
12898b9484cSchristos     OP_in,
12998b9484cSchristos     OP_cbi,
13098b9484cSchristos     OP_sbi,
13198b9484cSchristos 
13298b9484cSchristos     OP_sbic,
13398b9484cSchristos     OP_sbis,
13498b9484cSchristos 
13598b9484cSchristos     OP_ldi,
13698b9484cSchristos     OP_cpse,
13798b9484cSchristos     OP_cp,
13898b9484cSchristos     OP_cpi,
13998b9484cSchristos     OP_cpc,
14098b9484cSchristos     OP_sub,
14198b9484cSchristos     OP_sbc,
14298b9484cSchristos     OP_sbiw,
14398b9484cSchristos     OP_adiw,
14498b9484cSchristos     OP_add,
14598b9484cSchristos     OP_adc,
14698b9484cSchristos     OP_subi,
14798b9484cSchristos     OP_sbci,
14898b9484cSchristos     OP_inc,
14998b9484cSchristos     OP_dec,
15098b9484cSchristos     OP_lsr,
15198b9484cSchristos     OP_ror,
15298b9484cSchristos     OP_asr,
15398b9484cSchristos 
15498b9484cSchristos     OP_mul,
15598b9484cSchristos     OP_muls,
15698b9484cSchristos     OP_mulsu,
15798b9484cSchristos     OP_fmul,
15898b9484cSchristos     OP_fmuls,
15998b9484cSchristos     OP_fmulsu,
16098b9484cSchristos 
16198b9484cSchristos     OP_mov,
16298b9484cSchristos     OP_movw,
16398b9484cSchristos 
16498b9484cSchristos     OP_push,
16598b9484cSchristos     OP_pop,
16698b9484cSchristos 
16798b9484cSchristos     OP_st_X,
16898b9484cSchristos     OP_st_dec_X,
16998b9484cSchristos     OP_st_X_inc,
17098b9484cSchristos     OP_st_Y_inc,
17198b9484cSchristos     OP_st_dec_Y,
17298b9484cSchristos     OP_st_Z_inc,
17398b9484cSchristos     OP_st_dec_Z,
17498b9484cSchristos     OP_std_Y,
17598b9484cSchristos     OP_std_Z,
17698b9484cSchristos     OP_ldd_Y,
17798b9484cSchristos     OP_ldd_Z,
17898b9484cSchristos     OP_ld_Z_inc,
17998b9484cSchristos     OP_ld_dec_Z,
18098b9484cSchristos     OP_ld_Y_inc,
18198b9484cSchristos     OP_ld_dec_Y,
18298b9484cSchristos     OP_ld_X,
18398b9484cSchristos     OP_ld_X_inc,
18498b9484cSchristos     OP_ld_dec_X,
18598b9484cSchristos 
18698b9484cSchristos     OP_lpm,
18798b9484cSchristos     OP_lpm_Z,
18898b9484cSchristos     OP_lpm_inc_Z,
18998b9484cSchristos     OP_elpm,
19098b9484cSchristos     OP_elpm_Z,
19198b9484cSchristos     OP_elpm_inc_Z,
19298b9484cSchristos 
19398b9484cSchristos     OP_ijmp,
19498b9484cSchristos     OP_icall,
19598b9484cSchristos 
19698b9484cSchristos     OP_eijmp,
19798b9484cSchristos     OP_eicall,
19898b9484cSchristos 
19998b9484cSchristos     /* 2 words opcodes.  */
20098b9484cSchristos #define OP_2words OP_jmp
20198b9484cSchristos     OP_jmp,
20298b9484cSchristos     OP_call,
20398b9484cSchristos     OP_sts,
20498b9484cSchristos     OP_lds
20598b9484cSchristos   };
20698b9484cSchristos 
20798b9484cSchristos struct avr_insn_cell
20898b9484cSchristos {
20998b9484cSchristos   /* The insn (16 bits).  */
21098b9484cSchristos   word op;
21198b9484cSchristos 
21298b9484cSchristos   /* Pre-decoding code.  */
21398b9484cSchristos   enum avr_opcode code : 8;
21498b9484cSchristos   /* One byte of additional information.  */
21598b9484cSchristos   byte r;
21698b9484cSchristos };
21798b9484cSchristos 
21898b9484cSchristos /* I&D memories.  */
219212397c6Schristos /* TODO: Should be moved to SIM_CPU.  */
22098b9484cSchristos static struct avr_insn_cell flash[MAX_AVR_FLASH];
22198b9484cSchristos static byte sram[MAX_AVR_SRAM];
22298b9484cSchristos 
22398b9484cSchristos /* Sign extend a value.  */
22498b9484cSchristos static int sign_ext (word val, int nb_bits)
22598b9484cSchristos {
22698b9484cSchristos   if (val & (1 << (nb_bits - 1)))
227ba340e45Schristos     return val | -(1 << nb_bits);
22898b9484cSchristos   return val;
22998b9484cSchristos }
23098b9484cSchristos 
23198b9484cSchristos /* Insn field extractors.  */
23298b9484cSchristos 
23398b9484cSchristos /* Extract xxxx_xxxRx_xxxx_RRRR.  */
23498b9484cSchristos static inline byte get_r (word op)
23598b9484cSchristos {
23698b9484cSchristos   return (op & 0xf) | ((op >> 5) & 0x10);
23798b9484cSchristos }
23898b9484cSchristos 
23998b9484cSchristos /* Extract xxxx_xxxxx_xxxx_RRRR.  */
24098b9484cSchristos static inline byte get_r16 (word op)
24198b9484cSchristos {
24298b9484cSchristos   return 16 + (op & 0xf);
24398b9484cSchristos }
24498b9484cSchristos 
24598b9484cSchristos /* Extract xxxx_xxxxx_xxxx_xRRR.  */
24698b9484cSchristos static inline byte get_r16_23 (word op)
24798b9484cSchristos {
24898b9484cSchristos   return 16 + (op & 0x7);
24998b9484cSchristos }
25098b9484cSchristos 
25198b9484cSchristos /* Extract xxxx_xxxD_DDDD_xxxx.  */
25298b9484cSchristos static inline byte get_d (word op)
25398b9484cSchristos {
25498b9484cSchristos   return (op >> 4) & 0x1f;
25598b9484cSchristos }
25698b9484cSchristos 
25798b9484cSchristos /* Extract xxxx_xxxx_DDDD_xxxx.  */
25898b9484cSchristos static inline byte get_d16 (word op)
25998b9484cSchristos {
26098b9484cSchristos   return 16 + ((op >> 4) & 0x0f);
26198b9484cSchristos }
26298b9484cSchristos 
26398b9484cSchristos /* Extract xxxx_xxxx_xDDD_xxxx.  */
26498b9484cSchristos static inline byte get_d16_23 (word op)
26598b9484cSchristos {
26698b9484cSchristos   return 16 + ((op >> 4) & 0x07);
26798b9484cSchristos }
26898b9484cSchristos 
26998b9484cSchristos /* Extract xxxx_xAAx_xxxx_AAAA.  */
27098b9484cSchristos static inline byte get_A (word op)
27198b9484cSchristos {
27298b9484cSchristos   return (op & 0x0f) | ((op & 0x600) >> 5);
27398b9484cSchristos }
27498b9484cSchristos 
27598b9484cSchristos /* Extract xxxx_xxxx_AAAA_Axxx.  */
27698b9484cSchristos static inline byte get_biA (word op)
27798b9484cSchristos {
27898b9484cSchristos   return (op >> 3) & 0x1f;
27998b9484cSchristos }
28098b9484cSchristos 
28198b9484cSchristos /* Extract xxxx_KKKK_xxxx_KKKK.  */
28298b9484cSchristos static inline byte get_K (word op)
28398b9484cSchristos {
28498b9484cSchristos   return (op & 0xf) | ((op & 0xf00) >> 4);
28598b9484cSchristos }
28698b9484cSchristos 
28798b9484cSchristos /* Extract xxxx_xxKK_KKKK_Kxxx.  */
28898b9484cSchristos static inline int get_k (word op)
28998b9484cSchristos {
29098b9484cSchristos   return sign_ext ((op & 0x3f8) >> 3, 7);
29198b9484cSchristos }
29298b9484cSchristos 
29398b9484cSchristos /* Extract xxxx_xxxx_xxDD_xxxx.  */
29498b9484cSchristos static inline byte get_d24 (word op)
29598b9484cSchristos {
29698b9484cSchristos   return 24 + ((op >> 3) & 6);
29798b9484cSchristos }
29898b9484cSchristos 
29998b9484cSchristos /* Extract xxxx_xxxx_KKxx_KKKK.  */
30098b9484cSchristos static inline byte get_k6 (word op)
30198b9484cSchristos {
30298b9484cSchristos   return (op & 0xf) | ((op >> 2) & 0x30);
30398b9484cSchristos }
30498b9484cSchristos 
30598b9484cSchristos /* Extract xxQx_QQxx_xxxx_xQQQ.  */
30698b9484cSchristos static inline byte get_q (word op)
30798b9484cSchristos {
30898b9484cSchristos   return (op & 7) | ((op >> 7) & 0x18)| ((op >> 8) & 0x20);
30998b9484cSchristos }
31098b9484cSchristos 
31198b9484cSchristos /* Extract xxxx_xxxx_xxxx_xBBB.  */
31298b9484cSchristos static inline byte get_b (word op)
31398b9484cSchristos {
31498b9484cSchristos   return (op & 7);
31598b9484cSchristos }
31698b9484cSchristos 
31798b9484cSchristos /* AVR is little endian.  */
31898b9484cSchristos static inline word
31998b9484cSchristos read_word (unsigned int addr)
32098b9484cSchristos {
32198b9484cSchristos   return sram[addr] | (sram[addr + 1] << 8);
32298b9484cSchristos }
32398b9484cSchristos 
32498b9484cSchristos static inline void
32598b9484cSchristos write_word (unsigned int addr, word w)
32698b9484cSchristos {
32798b9484cSchristos   sram[addr] = w;
32898b9484cSchristos   sram[addr + 1] = w >> 8;
32998b9484cSchristos }
33098b9484cSchristos 
33198b9484cSchristos static inline word
33298b9484cSchristos read_word_post_inc (unsigned int addr)
33398b9484cSchristos {
33498b9484cSchristos   word v = read_word (addr);
33598b9484cSchristos   write_word (addr, v + 1);
33698b9484cSchristos   return v;
33798b9484cSchristos }
33898b9484cSchristos 
33998b9484cSchristos static inline word
34098b9484cSchristos read_word_pre_dec (unsigned int addr)
34198b9484cSchristos {
34298b9484cSchristos   word v = read_word (addr) - 1;
34398b9484cSchristos   write_word (addr, v);
34498b9484cSchristos   return v;
34598b9484cSchristos }
34698b9484cSchristos 
34798b9484cSchristos static void
34898b9484cSchristos update_flags_logic (byte res)
34998b9484cSchristos {
35098b9484cSchristos   sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z);
35198b9484cSchristos   if (res == 0)
35298b9484cSchristos     sram[SREG] |= SREG_Z;
35398b9484cSchristos   if (res & 0x80)
35498b9484cSchristos     sram[SREG] |= SREG_N | SREG_S;
35598b9484cSchristos }
35698b9484cSchristos 
35798b9484cSchristos static void
35898b9484cSchristos update_flags_add (byte r, byte a, byte b)
35998b9484cSchristos {
36098b9484cSchristos   byte carry;
36198b9484cSchristos 
36298b9484cSchristos   sram[SREG] &= ~(SREG_H | SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
36398b9484cSchristos   if (r & 0x80)
36498b9484cSchristos     sram[SREG] |= SREG_N;
36598b9484cSchristos   carry = (a & b) | (a & ~r) | (b & ~r);
36698b9484cSchristos   if (carry & 0x08)
36798b9484cSchristos     sram[SREG] |= SREG_H;
36898b9484cSchristos   if (carry & 0x80)
36998b9484cSchristos     sram[SREG] |= SREG_C;
37098b9484cSchristos   if (((a & b & ~r) | (~a & ~b & r)) & 0x80)
37198b9484cSchristos     sram[SREG] |= SREG_V;
37298b9484cSchristos   if (!(sram[SREG] & SREG_N) ^ !(sram[SREG] & SREG_V))
37398b9484cSchristos     sram[SREG] |= SREG_S;
37498b9484cSchristos   if (r == 0)
37598b9484cSchristos     sram[SREG] |= SREG_Z;
37698b9484cSchristos }
37798b9484cSchristos 
37898b9484cSchristos static void update_flags_sub (byte r, byte a, byte b)
37998b9484cSchristos {
38098b9484cSchristos   byte carry;
38198b9484cSchristos 
38298b9484cSchristos   sram[SREG] &= ~(SREG_H | SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
38398b9484cSchristos   if (r & 0x80)
38498b9484cSchristos     sram[SREG] |= SREG_N;
38598b9484cSchristos   carry = (~a & b) | (b & r) | (r & ~a);
38698b9484cSchristos   if (carry & 0x08)
38798b9484cSchristos     sram[SREG] |= SREG_H;
38898b9484cSchristos   if (carry & 0x80)
38998b9484cSchristos     sram[SREG] |= SREG_C;
39098b9484cSchristos   if (((a & ~b & ~r) | (~a & b & r)) & 0x80)
39198b9484cSchristos     sram[SREG] |= SREG_V;
39298b9484cSchristos   if (!(sram[SREG] & SREG_N) ^ !(sram[SREG] & SREG_V))
39398b9484cSchristos     sram[SREG] |= SREG_S;
39498b9484cSchristos   /* Note: Z is not set.  */
39598b9484cSchristos }
39698b9484cSchristos 
39798b9484cSchristos static enum avr_opcode
39898b9484cSchristos decode (unsigned int pc)
39998b9484cSchristos {
40098b9484cSchristos   word op1 = flash[pc].op;
40198b9484cSchristos 
40298b9484cSchristos   switch ((op1 >> 12) & 0x0f)
40398b9484cSchristos     {
40498b9484cSchristos     case 0x0:
40598b9484cSchristos       switch ((op1 >> 10) & 0x3)
40698b9484cSchristos         {
40798b9484cSchristos         case 0x0:
40898b9484cSchristos           switch ((op1 >> 8) & 0x3)
40998b9484cSchristos             {
41098b9484cSchristos             case 0x0:
41198b9484cSchristos               if (op1 == 0)
41298b9484cSchristos                 return OP_nop;
41398b9484cSchristos               break;
41498b9484cSchristos             case 0x1:
41598b9484cSchristos               return OP_movw;
41698b9484cSchristos             case 0x2:
41798b9484cSchristos               return OP_muls;
41898b9484cSchristos             case 0x3:
41998b9484cSchristos               if (op1 & 0x80)
42098b9484cSchristos                 {
42198b9484cSchristos                   if (op1 & 0x08)
42298b9484cSchristos                     return OP_fmulsu;
42398b9484cSchristos                   else
42498b9484cSchristos                     return OP_fmuls;
42598b9484cSchristos                 }
42698b9484cSchristos               else
42798b9484cSchristos                 {
42898b9484cSchristos                   if (op1 & 0x08)
42998b9484cSchristos                     return OP_fmul;
43098b9484cSchristos                   else
43198b9484cSchristos                     return OP_mulsu;
43298b9484cSchristos                 }
43398b9484cSchristos             }
43498b9484cSchristos           break;
43598b9484cSchristos         case 0x1:
43698b9484cSchristos           return OP_cpc;
43798b9484cSchristos         case 0x2:
43898b9484cSchristos           flash[pc].r = SREG_C;
43998b9484cSchristos           return OP_sbc;
44098b9484cSchristos         case 0x3:
44198b9484cSchristos           flash[pc].r = 0;
44298b9484cSchristos           return OP_add;
44398b9484cSchristos         }
44498b9484cSchristos       break;
44598b9484cSchristos     case 0x1:
44698b9484cSchristos       switch ((op1 >> 10) & 0x3)
44798b9484cSchristos         {
44898b9484cSchristos         case 0x0:
44998b9484cSchristos           return OP_cpse;
45098b9484cSchristos         case 0x1:
45198b9484cSchristos           return OP_cp;
45298b9484cSchristos         case 0x2:
45398b9484cSchristos           flash[pc].r = 0;
45498b9484cSchristos           return OP_sub;
45598b9484cSchristos         case 0x3:
45698b9484cSchristos           flash[pc].r = SREG_C;
45798b9484cSchristos           return OP_adc;
45898b9484cSchristos         }
45998b9484cSchristos       break;
46098b9484cSchristos     case 0x2:
46198b9484cSchristos       switch ((op1 >> 10) & 0x3)
46298b9484cSchristos         {
46398b9484cSchristos         case 0x0:
46498b9484cSchristos           return OP_and;
46598b9484cSchristos         case 0x1:
46698b9484cSchristos           return OP_eor;
46798b9484cSchristos         case 0x2:
46898b9484cSchristos           return OP_or;
46998b9484cSchristos         case 0x3:
47098b9484cSchristos           return OP_mov;
47198b9484cSchristos         }
47298b9484cSchristos       break;
47398b9484cSchristos     case 0x3:
47498b9484cSchristos       return OP_cpi;
47598b9484cSchristos     case 0x4:
47698b9484cSchristos       return OP_sbci;
47798b9484cSchristos     case 0x5:
47898b9484cSchristos       return OP_subi;
47998b9484cSchristos     case 0x6:
48098b9484cSchristos       return OP_ori;
48198b9484cSchristos     case 0x7:
48298b9484cSchristos       return OP_andi;
48398b9484cSchristos     case 0x8:
48498b9484cSchristos     case 0xa:
48598b9484cSchristos       if (op1 & 0x0200)
48698b9484cSchristos         {
48798b9484cSchristos           if (op1 & 0x0008)
48898b9484cSchristos             {
48998b9484cSchristos               flash[pc].r = get_q (op1);
49098b9484cSchristos               return OP_std_Y;
49198b9484cSchristos             }
49298b9484cSchristos           else
49398b9484cSchristos             {
49498b9484cSchristos               flash[pc].r = get_q (op1);
49598b9484cSchristos               return OP_std_Z;
49698b9484cSchristos             }
49798b9484cSchristos         }
49898b9484cSchristos       else
49998b9484cSchristos         {
50098b9484cSchristos           if (op1 & 0x0008)
50198b9484cSchristos             {
50298b9484cSchristos               flash[pc].r = get_q (op1);
50398b9484cSchristos               return OP_ldd_Y;
50498b9484cSchristos             }
50598b9484cSchristos           else
50698b9484cSchristos             {
50798b9484cSchristos               flash[pc].r = get_q (op1);
50898b9484cSchristos               return OP_ldd_Z;
50998b9484cSchristos             }
51098b9484cSchristos         }
51198b9484cSchristos       break;
51298b9484cSchristos     case 0x9: /* 9xxx */
51398b9484cSchristos       switch ((op1 >> 8) & 0xf)
51498b9484cSchristos         {
51598b9484cSchristos         case 0x0:
51698b9484cSchristos         case 0x1:
51798b9484cSchristos           switch ((op1 >> 0) & 0xf)
51898b9484cSchristos             {
51998b9484cSchristos             case 0x0:
52098b9484cSchristos               return OP_lds;
52198b9484cSchristos             case 0x1:
52298b9484cSchristos               return OP_ld_Z_inc;
52398b9484cSchristos             case 0x2:
52498b9484cSchristos               return OP_ld_dec_Z;
52598b9484cSchristos             case 0x4:
52698b9484cSchristos               return OP_lpm_Z;
52798b9484cSchristos             case 0x5:
52898b9484cSchristos               return OP_lpm_inc_Z;
52998b9484cSchristos             case 0x6:
53098b9484cSchristos               return OP_elpm_Z;
53198b9484cSchristos             case 0x7:
53298b9484cSchristos               return OP_elpm_inc_Z;
53398b9484cSchristos             case 0x9:
53498b9484cSchristos               return OP_ld_Y_inc;
53598b9484cSchristos             case 0xa:
53698b9484cSchristos               return OP_ld_dec_Y;
53798b9484cSchristos             case 0xc:
53898b9484cSchristos               return OP_ld_X;
53998b9484cSchristos             case 0xd:
54098b9484cSchristos               return OP_ld_X_inc;
54198b9484cSchristos             case 0xe:
54298b9484cSchristos               return OP_ld_dec_X;
54398b9484cSchristos             case 0xf:
54498b9484cSchristos               return OP_pop;
54598b9484cSchristos             }
54698b9484cSchristos           break;
54798b9484cSchristos         case 0x2:
54898b9484cSchristos         case 0x3:
54998b9484cSchristos           switch ((op1 >> 0) & 0xf)
55098b9484cSchristos             {
55198b9484cSchristos             case 0x0:
55298b9484cSchristos               return OP_sts;
55398b9484cSchristos             case 0x1:
55498b9484cSchristos               return OP_st_Z_inc;
55598b9484cSchristos             case 0x2:
55698b9484cSchristos               return OP_st_dec_Z;
55798b9484cSchristos             case 0x9:
55898b9484cSchristos               return OP_st_Y_inc;
55998b9484cSchristos             case 0xa:
56098b9484cSchristos               return OP_st_dec_Y;
56198b9484cSchristos             case 0xc:
56298b9484cSchristos               return OP_st_X;
56398b9484cSchristos             case 0xd:
56498b9484cSchristos               return OP_st_X_inc;
56598b9484cSchristos             case 0xe:
56698b9484cSchristos               return OP_st_dec_X;
56798b9484cSchristos             case 0xf:
56898b9484cSchristos               return OP_push;
56998b9484cSchristos             }
57098b9484cSchristos           break;
57198b9484cSchristos         case 0x4:
57298b9484cSchristos         case 0x5:
57398b9484cSchristos           switch (op1 & 0xf)
57498b9484cSchristos             {
57598b9484cSchristos             case 0x0:
57698b9484cSchristos               return OP_com;
57798b9484cSchristos             case 0x1:
57898b9484cSchristos               return OP_neg;
57998b9484cSchristos             case 0x2:
58098b9484cSchristos               return OP_swap;
58198b9484cSchristos             case 0x3:
58298b9484cSchristos               return OP_inc;
58398b9484cSchristos             case 0x5:
58498b9484cSchristos               flash[pc].r = 0x80;
58598b9484cSchristos               return OP_asr;
58698b9484cSchristos             case 0x6:
58798b9484cSchristos               flash[pc].r = 0;
58898b9484cSchristos               return OP_lsr;
58998b9484cSchristos             case 0x7:
59098b9484cSchristos               return OP_ror;
59198b9484cSchristos             case 0x8: /* 9[45]x8 */
59298b9484cSchristos               switch ((op1 >> 4) & 0x1f)
59398b9484cSchristos                 {
59498b9484cSchristos                 case 0x00:
59598b9484cSchristos                 case 0x01:
59698b9484cSchristos                 case 0x02:
59798b9484cSchristos                 case 0x03:
59898b9484cSchristos                 case 0x04:
59998b9484cSchristos                 case 0x05:
60098b9484cSchristos                 case 0x06:
60198b9484cSchristos                 case 0x07:
60298b9484cSchristos                   return OP_bset;
60398b9484cSchristos                 case 0x08:
60498b9484cSchristos                 case 0x09:
60598b9484cSchristos                 case 0x0a:
60698b9484cSchristos                 case 0x0b:
60798b9484cSchristos                 case 0x0c:
60898b9484cSchristos                 case 0x0d:
60998b9484cSchristos                 case 0x0e:
61098b9484cSchristos                 case 0x0f:
61198b9484cSchristos                   return OP_bclr;
61298b9484cSchristos                 case 0x10:
61398b9484cSchristos                   return OP_ret;
61498b9484cSchristos                 case 0x11:
61598b9484cSchristos                   return OP_reti;
61698b9484cSchristos                 case 0x19:
61798b9484cSchristos                   return OP_break;
61898b9484cSchristos                 case 0x1c:
61998b9484cSchristos                   return OP_lpm;
62098b9484cSchristos                 case 0x1d:
62198b9484cSchristos                   return OP_elpm;
62298b9484cSchristos                 default:
62398b9484cSchristos                   break;
62498b9484cSchristos                 }
62598b9484cSchristos               break;
62698b9484cSchristos             case 0x9: /* 9[45]x9 */
62798b9484cSchristos               switch ((op1 >> 4) & 0x1f)
62898b9484cSchristos                 {
62998b9484cSchristos                 case 0x00:
63098b9484cSchristos                   return OP_ijmp;
63198b9484cSchristos                 case 0x01:
63298b9484cSchristos                   return OP_eijmp;
63398b9484cSchristos                 case 0x10:
63498b9484cSchristos                   return OP_icall;
63598b9484cSchristos                 case 0x11:
63698b9484cSchristos                   return OP_eicall;
63798b9484cSchristos                 default:
63898b9484cSchristos                   break;
63998b9484cSchristos                 }
64098b9484cSchristos               break;
64198b9484cSchristos             case 0xa:
64298b9484cSchristos               return OP_dec;
64398b9484cSchristos             case 0xc:
64498b9484cSchristos             case 0xd:
64598b9484cSchristos               flash[pc].r = ((op1 & 0x1f0) >> 3) | (op1 & 1);
64698b9484cSchristos               return OP_jmp;
64798b9484cSchristos             case 0xe:
64898b9484cSchristos             case 0xf:
64998b9484cSchristos               flash[pc].r = ((op1 & 0x1f0) >> 3) | (op1 & 1);
65098b9484cSchristos               return OP_call;
65198b9484cSchristos             }
65298b9484cSchristos           break;
65398b9484cSchristos         case 0x6:
65498b9484cSchristos           return OP_adiw;
65598b9484cSchristos         case 0x7:
65698b9484cSchristos           return OP_sbiw;
65798b9484cSchristos         case 0x8:
65898b9484cSchristos           return OP_cbi;
65998b9484cSchristos         case 0x9:
66098b9484cSchristos           return OP_sbic;
66198b9484cSchristos         case 0xa:
66298b9484cSchristos           return OP_sbi;
66398b9484cSchristos         case 0xb:
66498b9484cSchristos           return OP_sbis;
66598b9484cSchristos         case 0xc:
66698b9484cSchristos         case 0xd:
66798b9484cSchristos         case 0xe:
66898b9484cSchristos         case 0xf:
66998b9484cSchristos           return OP_mul;
67098b9484cSchristos         }
67198b9484cSchristos       break;
67298b9484cSchristos     case 0xb:
67398b9484cSchristos       flash[pc].r = get_A (op1);
67498b9484cSchristos       if (((op1 >> 11) & 1) == 0)
67598b9484cSchristos         return OP_in;
67698b9484cSchristos       else
67798b9484cSchristos         return OP_out;
67898b9484cSchristos     case 0xc:
67998b9484cSchristos       return OP_rjmp;
68098b9484cSchristos     case 0xd:
68198b9484cSchristos       return OP_rcall;
68298b9484cSchristos     case 0xe:
68398b9484cSchristos       return OP_ldi;
68498b9484cSchristos     case 0xf:
68598b9484cSchristos       switch ((op1 >> 9) & 7)
68698b9484cSchristos         {
68798b9484cSchristos         case 0:
68898b9484cSchristos         case 1:
68998b9484cSchristos           flash[pc].r = 1 << (op1 & 7);
69098b9484cSchristos           return OP_brbs;
69198b9484cSchristos         case 2:
69298b9484cSchristos         case 3:
69398b9484cSchristos           flash[pc].r = 1 << (op1 & 7);
69498b9484cSchristos           return OP_brbc;
69598b9484cSchristos         case 4:
69698b9484cSchristos           if ((op1 & 8) == 0)
69798b9484cSchristos             {
69898b9484cSchristos               flash[pc].r = 1 << (op1 & 7);
69998b9484cSchristos               return OP_bld;
70098b9484cSchristos             }
70198b9484cSchristos           break;
70298b9484cSchristos         case 5:
70398b9484cSchristos           if ((op1 & 8) == 0)
70498b9484cSchristos             {
70598b9484cSchristos               flash[pc].r = 1 << (op1 & 7);
70698b9484cSchristos               return OP_bst;
70798b9484cSchristos             }
70898b9484cSchristos           break;
70998b9484cSchristos         case 6:
71098b9484cSchristos           if ((op1 & 8) == 0)
71198b9484cSchristos             {
71298b9484cSchristos               flash[pc].r = 1 << (op1 & 7);
71398b9484cSchristos               return OP_sbrc;
71498b9484cSchristos             }
71598b9484cSchristos           break;
71698b9484cSchristos         case 7:
71798b9484cSchristos           if ((op1 & 8) == 0)
71898b9484cSchristos             {
71998b9484cSchristos               flash[pc].r = 1 << (op1 & 7);
72098b9484cSchristos               return OP_sbrs;
72198b9484cSchristos             }
72298b9484cSchristos           break;
72398b9484cSchristos         }
72498b9484cSchristos     }
725212397c6Schristos 
72698b9484cSchristos   return OP_bad;
72798b9484cSchristos }
72898b9484cSchristos 
72998b9484cSchristos static void
730ba340e45Schristos do_call (SIM_CPU *cpu, unsigned int npc)
73198b9484cSchristos {
7324b169a6bSchristos   const struct avr_sim_state *state = AVR_SIM_STATE (CPU_STATE (cpu));
733*88241920Schristos   struct avr_sim_cpu *avr_cpu = AVR_SIM_CPU (cpu);
73498b9484cSchristos   unsigned int sp = read_word (REG_SP);
73598b9484cSchristos 
73698b9484cSchristos   /* Big endian!  */
737*88241920Schristos   sram[sp--] = avr_cpu->pc;
738*88241920Schristos   sram[sp--] = avr_cpu->pc >> 8;
7394b169a6bSchristos   if (state->avr_pc22)
74098b9484cSchristos     {
741*88241920Schristos       sram[sp--] = avr_cpu->pc >> 16;
742*88241920Schristos       avr_cpu->cycles++;
74398b9484cSchristos     }
74498b9484cSchristos   write_word (REG_SP, sp);
745*88241920Schristos   avr_cpu->pc = npc & PC_MASK;
746*88241920Schristos   avr_cpu->cycles += 3;
74798b9484cSchristos }
74898b9484cSchristos 
74998b9484cSchristos static int
75098b9484cSchristos get_insn_length (unsigned int p)
75198b9484cSchristos {
75298b9484cSchristos   if (flash[p].code == OP_unknown)
75398b9484cSchristos     flash[p].code = decode(p);
75498b9484cSchristos   if (flash[p].code >= OP_2words)
75598b9484cSchristos     return 2;
75698b9484cSchristos   else
75798b9484cSchristos     return 1;
75898b9484cSchristos }
75998b9484cSchristos 
76098b9484cSchristos static unsigned int
76198b9484cSchristos get_z (void)
76298b9484cSchristos {
76398b9484cSchristos   return (sram[RAMPZ] << 16) | (sram[REGZ_HI] << 8) | sram[REGZ_LO];
76498b9484cSchristos }
76598b9484cSchristos 
76698b9484cSchristos static unsigned char
76798b9484cSchristos get_lpm (unsigned int addr)
76898b9484cSchristos {
76998b9484cSchristos   word w;
77098b9484cSchristos 
77198b9484cSchristos   w = flash[(addr >> 1) & PC_MASK].op;
77298b9484cSchristos   if (addr & 1)
77398b9484cSchristos     w >>= 8;
77498b9484cSchristos   return w;
77598b9484cSchristos }
77698b9484cSchristos 
77798b9484cSchristos static void
778ba340e45Schristos gen_mul (SIM_CPU *cpu, unsigned int res)
77998b9484cSchristos {
780*88241920Schristos   struct avr_sim_cpu *avr_cpu = AVR_SIM_CPU (cpu);
781*88241920Schristos 
78298b9484cSchristos   write_word (0, res);
78398b9484cSchristos   sram[SREG] &= ~(SREG_Z | SREG_C);
78498b9484cSchristos   if (res == 0)
78598b9484cSchristos     sram[SREG] |= SREG_Z;
78698b9484cSchristos   if (res & 0x8000)
78798b9484cSchristos     sram[SREG] |= SREG_C;
788*88241920Schristos   avr_cpu->cycles++;
78998b9484cSchristos }
79098b9484cSchristos 
791212397c6Schristos static void
792212397c6Schristos step_once (SIM_CPU *cpu)
79398b9484cSchristos {
794*88241920Schristos   struct avr_sim_cpu *avr_cpu = AVR_SIM_CPU (cpu);
79598b9484cSchristos   unsigned int ipc;
79698b9484cSchristos 
79798b9484cSchristos   int code;
79898b9484cSchristos   word op;
79998b9484cSchristos   byte res;
80098b9484cSchristos   byte r, d, vd;
80198b9484cSchristos 
80298b9484cSchristos  again:
803*88241920Schristos   code = flash[avr_cpu->pc].code;
804*88241920Schristos   op = flash[avr_cpu->pc].op;
80598b9484cSchristos 
806212397c6Schristos #if 0
807212397c6Schristos       if (tracing && code != OP_unknown)
80898b9484cSchristos 	{
80998b9484cSchristos 	  if (verbose > 0) {
81098b9484cSchristos 	    int flags;
81198b9484cSchristos 	    int i;
81298b9484cSchristos 
81398b9484cSchristos 	    sim_cb_eprintf (callback, "R00-07:");
81498b9484cSchristos 	    for (i = 0; i < 8; i++)
81598b9484cSchristos 	      sim_cb_eprintf (callback, " %02x", sram[i]);
81698b9484cSchristos 	    sim_cb_eprintf (callback, " -");
81798b9484cSchristos 	    for (i = 8; i < 16; i++)
81898b9484cSchristos 	      sim_cb_eprintf (callback, " %02x", sram[i]);
81998b9484cSchristos 	    sim_cb_eprintf (callback, "  SP: %02x %02x",
82098b9484cSchristos                             sram[REG_SP + 1], sram[REG_SP]);
82198b9484cSchristos 	    sim_cb_eprintf (callback, "\n");
82298b9484cSchristos 	    sim_cb_eprintf (callback, "R16-31:");
82398b9484cSchristos 	    for (i = 16; i < 24; i++)
82498b9484cSchristos 	      sim_cb_eprintf (callback, " %02x", sram[i]);
82598b9484cSchristos 	    sim_cb_eprintf (callback, " -");
82698b9484cSchristos 	    for (i = 24; i < 32; i++)
82798b9484cSchristos 	      sim_cb_eprintf (callback, " %02x", sram[i]);
82898b9484cSchristos 	    sim_cb_eprintf (callback, "  ");
82998b9484cSchristos 	    flags = sram[SREG];
83098b9484cSchristos 	    for (i = 0; i < 8; i++)
83198b9484cSchristos 	      sim_cb_eprintf (callback, "%c",
83298b9484cSchristos                               flags & (0x80 >> i) ? "ITHSVNZC"[i] : '-');
83398b9484cSchristos 	    sim_cb_eprintf (callback, "\n");
83498b9484cSchristos 	  }
83598b9484cSchristos 
836212397c6Schristos 	  if (!tracing)
837*88241920Schristos 	    sim_cb_eprintf (callback, "%06x: %04x\n", 2 * avr_cpu->pc, flash[avr_cpu->pc].op);
83898b9484cSchristos 	  else
83998b9484cSchristos 	    {
84098b9484cSchristos 	      sim_cb_eprintf (callback, "pc=0x%06x insn=0x%04x code=%d r=%d\n",
841*88241920Schristos                               2 * avr_cpu->pc, flash[avr_cpu->pc].op, code, flash[avr_cpu->pc].r);
842*88241920Schristos 	      disassemble_insn (CPU_STATE (cpu), avr_cpu->pc);
84398b9484cSchristos 	      sim_cb_eprintf (callback, "\n");
84498b9484cSchristos 	    }
84598b9484cSchristos 	}
846212397c6Schristos #endif
84798b9484cSchristos 
848*88241920Schristos   ipc = avr_cpu->pc;
849*88241920Schristos   avr_cpu->pc = (avr_cpu->pc + 1) & PC_MASK;
850*88241920Schristos   avr_cpu->cycles++;
85198b9484cSchristos 
85298b9484cSchristos   switch (code)
85398b9484cSchristos     {
85498b9484cSchristos       case OP_unknown:
85598b9484cSchristos 	flash[ipc].code = decode(ipc);
856*88241920Schristos 	avr_cpu->pc = ipc;
857*88241920Schristos 	avr_cpu->cycles--;
85898b9484cSchristos 	goto again;
85998b9484cSchristos 
86098b9484cSchristos       case OP_nop:
86198b9484cSchristos 	break;
86298b9484cSchristos 
86398b9484cSchristos       case OP_jmp:
86498b9484cSchristos 	/* 2 words instruction, but we don't care about the pc.  */
865*88241920Schristos 	avr_cpu->pc = ((flash[ipc].r << 16) | flash[ipc + 1].op) & PC_MASK;
866*88241920Schristos 	avr_cpu->cycles += 2;
86798b9484cSchristos 	break;
86898b9484cSchristos 
86998b9484cSchristos       case OP_eijmp:
870*88241920Schristos 	avr_cpu->pc = ((sram[EIND] << 16) | read_word (REGZ)) & PC_MASK;
871*88241920Schristos 	avr_cpu->cycles += 2;
87298b9484cSchristos 	break;
87398b9484cSchristos 
87498b9484cSchristos       case OP_ijmp:
875*88241920Schristos 	avr_cpu->pc = read_word (REGZ) & PC_MASK;
876*88241920Schristos 	avr_cpu->cycles += 1;
87798b9484cSchristos 	break;
87898b9484cSchristos 
87998b9484cSchristos       case OP_call:
88098b9484cSchristos 	/* 2 words instruction.  */
881*88241920Schristos 	avr_cpu->pc++;
882ba340e45Schristos 	do_call (cpu, (flash[ipc].r << 16) | flash[ipc + 1].op);
88398b9484cSchristos 	break;
88498b9484cSchristos 
88598b9484cSchristos       case OP_eicall:
886ba340e45Schristos 	do_call (cpu, (sram[EIND] << 16) | read_word (REGZ));
88798b9484cSchristos 	break;
88898b9484cSchristos 
88998b9484cSchristos       case OP_icall:
890ba340e45Schristos 	do_call (cpu, read_word (REGZ));
89198b9484cSchristos 	break;
89298b9484cSchristos 
89398b9484cSchristos       case OP_rcall:
894*88241920Schristos 	do_call (cpu, avr_cpu->pc + sign_ext (op & 0xfff, 12));
89598b9484cSchristos 	break;
89698b9484cSchristos 
89798b9484cSchristos       case OP_reti:
89898b9484cSchristos 	sram[SREG] |= SREG_I;
899*88241920Schristos 	ATTRIBUTE_FALLTHROUGH;
90098b9484cSchristos       case OP_ret:
90198b9484cSchristos 	{
9024b169a6bSchristos 	  const struct avr_sim_state *state = AVR_SIM_STATE (CPU_STATE (cpu));
90398b9484cSchristos 	  unsigned int sp = read_word (REG_SP);
9044b169a6bSchristos 	  if (state->avr_pc22)
90598b9484cSchristos 	    {
906*88241920Schristos 	      avr_cpu->pc = sram[++sp] << 16;
907*88241920Schristos 	      avr_cpu->cycles++;
90898b9484cSchristos 	    }
90998b9484cSchristos 	  else
910*88241920Schristos 	    avr_cpu->pc = 0;
911*88241920Schristos 	  avr_cpu->pc |= sram[++sp] << 8;
912*88241920Schristos 	  avr_cpu->pc |= sram[++sp];
91398b9484cSchristos 	  write_word (REG_SP, sp);
91498b9484cSchristos 	}
915*88241920Schristos 	avr_cpu->cycles += 3;
91698b9484cSchristos 	break;
91798b9484cSchristos 
91898b9484cSchristos       case OP_break:
91998b9484cSchristos 	/* Stop on this address.  */
920ba340e45Schristos 	sim_engine_halt (CPU_STATE (cpu), cpu, NULL, ipc, sim_stopped, SIM_SIGTRAP);
92198b9484cSchristos 	break;
92298b9484cSchristos 
92398b9484cSchristos       case OP_bld:
92498b9484cSchristos 	d = get_d (op);
92598b9484cSchristos 	r = flash[ipc].r;
92698b9484cSchristos 	if (sram[SREG] & SREG_T)
92798b9484cSchristos 	  sram[d] |= r;
92898b9484cSchristos 	else
92998b9484cSchristos 	  sram[d] &= ~r;
93098b9484cSchristos 	break;
93198b9484cSchristos 
93298b9484cSchristos       case OP_bst:
93398b9484cSchristos 	if (sram[get_d (op)] & flash[ipc].r)
93498b9484cSchristos 	  sram[SREG] |= SREG_T;
93598b9484cSchristos 	else
93698b9484cSchristos 	  sram[SREG] &= ~SREG_T;
93798b9484cSchristos 	break;
93898b9484cSchristos 
93998b9484cSchristos       case OP_sbrc:
94098b9484cSchristos       case OP_sbrs:
94198b9484cSchristos 	if (((sram[get_d (op)] & flash[ipc].r) == 0) ^ ((op & 0x0200) != 0))
94298b9484cSchristos 	  {
943*88241920Schristos 	    int l = get_insn_length (avr_cpu->pc);
944*88241920Schristos 	    avr_cpu->pc += l;
945*88241920Schristos 	    avr_cpu->cycles += l;
94698b9484cSchristos 	  }
94798b9484cSchristos 	break;
94898b9484cSchristos 
94998b9484cSchristos       case OP_push:
95098b9484cSchristos 	{
95198b9484cSchristos 	  unsigned int sp = read_word (REG_SP);
95298b9484cSchristos 	  sram[sp--] = sram[get_d (op)];
95398b9484cSchristos 	  write_word (REG_SP, sp);
95498b9484cSchristos 	}
955*88241920Schristos 	avr_cpu->cycles++;
95698b9484cSchristos 	break;
95798b9484cSchristos 
95898b9484cSchristos       case OP_pop:
95998b9484cSchristos 	{
96098b9484cSchristos 	  unsigned int sp = read_word (REG_SP);
96198b9484cSchristos 	  sram[get_d (op)] = sram[++sp];
96298b9484cSchristos 	  write_word (REG_SP, sp);
96398b9484cSchristos 	}
964*88241920Schristos 	avr_cpu->cycles++;
96598b9484cSchristos 	break;
96698b9484cSchristos 
96798b9484cSchristos       case OP_bclr:
96898b9484cSchristos 	sram[SREG] &= ~(1 << ((op >> 4) & 0x7));
96998b9484cSchristos 	break;
97098b9484cSchristos 
97198b9484cSchristos       case OP_bset:
97298b9484cSchristos 	sram[SREG] |= 1 << ((op >> 4) & 0x7);
97398b9484cSchristos 	break;
97498b9484cSchristos 
97598b9484cSchristos       case OP_rjmp:
976*88241920Schristos 	avr_cpu->pc = (avr_cpu->pc + sign_ext (op & 0xfff, 12)) & PC_MASK;
977*88241920Schristos 	avr_cpu->cycles++;
97898b9484cSchristos 	break;
97998b9484cSchristos 
98098b9484cSchristos       case OP_eor:
98198b9484cSchristos 	d = get_d (op);
98298b9484cSchristos 	res = sram[d] ^ sram[get_r (op)];
98398b9484cSchristos 	sram[d] = res;
98498b9484cSchristos 	update_flags_logic (res);
98598b9484cSchristos 	break;
98698b9484cSchristos 
98798b9484cSchristos       case OP_and:
98898b9484cSchristos 	d = get_d (op);
98998b9484cSchristos 	res = sram[d] & sram[get_r (op)];
99098b9484cSchristos 	sram[d] = res;
99198b9484cSchristos 	update_flags_logic (res);
99298b9484cSchristos 	break;
99398b9484cSchristos 
99498b9484cSchristos       case OP_andi:
99598b9484cSchristos 	d = get_d16 (op);
99698b9484cSchristos 	res = sram[d] & get_K (op);
99798b9484cSchristos 	sram[d] = res;
99898b9484cSchristos 	update_flags_logic (res);
99998b9484cSchristos 	break;
100098b9484cSchristos 
100198b9484cSchristos       case OP_or:
100298b9484cSchristos 	d = get_d (op);
100398b9484cSchristos 	res = sram[d] | sram[get_r (op)];
100498b9484cSchristos 	sram[d] = res;
100598b9484cSchristos 	update_flags_logic (res);
100698b9484cSchristos 	break;
100798b9484cSchristos 
100898b9484cSchristos       case OP_ori:
100998b9484cSchristos 	d = get_d16 (op);
101098b9484cSchristos 	res = sram[d] | get_K (op);
101198b9484cSchristos 	sram[d] = res;
101298b9484cSchristos 	update_flags_logic (res);
101398b9484cSchristos 	break;
101498b9484cSchristos 
101598b9484cSchristos       case OP_com:
101698b9484cSchristos 	d = get_d (op);
101798b9484cSchristos 	res = ~sram[d];
101898b9484cSchristos 	sram[d] = res;
101998b9484cSchristos 	update_flags_logic (res);
102098b9484cSchristos 	sram[SREG] |= SREG_C;
102198b9484cSchristos 	break;
102298b9484cSchristos 
102398b9484cSchristos       case OP_swap:
102498b9484cSchristos 	d = get_d (op);
102598b9484cSchristos 	vd = sram[d];
102698b9484cSchristos 	sram[d] = (vd >> 4) | (vd << 4);
102798b9484cSchristos 	break;
102898b9484cSchristos 
102998b9484cSchristos       case OP_neg:
103098b9484cSchristos 	d = get_d (op);
103198b9484cSchristos 	vd = sram[d];
103298b9484cSchristos 	res = -vd;
103398b9484cSchristos 	sram[d] = res;
103498b9484cSchristos 	sram[SREG] &= ~(SREG_H | SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
103598b9484cSchristos 	if (res == 0)
103698b9484cSchristos 	  sram[SREG] |= SREG_Z;
103798b9484cSchristos 	else
103898b9484cSchristos 	  sram[SREG] |= SREG_C;
103998b9484cSchristos 	if (res == 0x80)
104098b9484cSchristos 	  sram[SREG] |= SREG_V | SREG_N;
104198b9484cSchristos 	else if (res & 0x80)
104298b9484cSchristos 	  sram[SREG] |= SREG_N | SREG_S;
104398b9484cSchristos 	if ((res | vd) & 0x08)
104498b9484cSchristos 	  sram[SREG] |= SREG_H;
104598b9484cSchristos 	break;
104698b9484cSchristos 
104798b9484cSchristos       case OP_inc:
104898b9484cSchristos 	d = get_d (op);
104998b9484cSchristos 	res = sram[d] + 1;
105098b9484cSchristos 	sram[d] = res;
105198b9484cSchristos 	sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z);
105298b9484cSchristos 	if (res == 0x80)
105398b9484cSchristos 	  sram[SREG] |= SREG_V | SREG_N;
105498b9484cSchristos 	else if (res & 0x80)
105598b9484cSchristos 	  sram[SREG] |= SREG_N | SREG_S;
105698b9484cSchristos 	else if (res == 0)
105798b9484cSchristos 	  sram[SREG] |= SREG_Z;
105898b9484cSchristos 	break;
105998b9484cSchristos 
106098b9484cSchristos       case OP_dec:
106198b9484cSchristos 	d = get_d (op);
106298b9484cSchristos 	res = sram[d] - 1;
106398b9484cSchristos 	sram[d] = res;
106498b9484cSchristos 	sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z);
106598b9484cSchristos 	if (res == 0x7f)
106698b9484cSchristos 	  sram[SREG] |= SREG_V | SREG_S;
106798b9484cSchristos 	else if (res & 0x80)
106898b9484cSchristos 	  sram[SREG] |= SREG_N | SREG_S;
106998b9484cSchristos 	else if (res == 0)
107098b9484cSchristos 	  sram[SREG] |= SREG_Z;
107198b9484cSchristos 	break;
107298b9484cSchristos 
107398b9484cSchristos       case OP_lsr:
107498b9484cSchristos       case OP_asr:
107598b9484cSchristos 	d = get_d (op);
107698b9484cSchristos 	vd = sram[d];
107798b9484cSchristos 	res = (vd >> 1) | (vd & flash[ipc].r);
107898b9484cSchristos 	sram[d] = res;
107998b9484cSchristos 	sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
108098b9484cSchristos 	if (vd & 1)
108198b9484cSchristos 	  sram[SREG] |= SREG_C | SREG_S;
108298b9484cSchristos 	if (res & 0x80)
108398b9484cSchristos 	  sram[SREG] |= SREG_N;
108498b9484cSchristos 	if (!(sram[SREG] & SREG_N) ^ !(sram[SREG] & SREG_C))
108598b9484cSchristos 	  sram[SREG] |= SREG_V;
108698b9484cSchristos 	if (res == 0)
108798b9484cSchristos 	  sram[SREG] |= SREG_Z;
108898b9484cSchristos 	break;
108998b9484cSchristos 
109098b9484cSchristos       case OP_ror:
109198b9484cSchristos 	d = get_d (op);
109298b9484cSchristos 	vd = sram[d];
109398b9484cSchristos 	res = vd >> 1 | (sram[SREG] << 7);
109498b9484cSchristos 	sram[d] = res;
109598b9484cSchristos 	sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
109698b9484cSchristos 	if (vd & 1)
109798b9484cSchristos 	  sram[SREG] |= SREG_C | SREG_S;
109898b9484cSchristos 	if (res & 0x80)
109998b9484cSchristos 	  sram[SREG] |= SREG_N;
110098b9484cSchristos 	if (!(sram[SREG] & SREG_N) ^ !(sram[SREG] & SREG_C))
110198b9484cSchristos 	  sram[SREG] |= SREG_V;
110298b9484cSchristos 	if (res == 0)
110398b9484cSchristos 	  sram[SREG] |= SREG_Z;
110498b9484cSchristos 	break;
110598b9484cSchristos 
110698b9484cSchristos       case OP_mul:
1107ba340e45Schristos 	gen_mul (cpu, (word)sram[get_r (op)] * (word)sram[get_d (op)]);
110898b9484cSchristos 	break;
110998b9484cSchristos 
111098b9484cSchristos       case OP_muls:
1111ba340e45Schristos 	gen_mul (cpu, (sword)(sbyte)sram[get_r16 (op)]
111298b9484cSchristos 		      * (sword)(sbyte)sram[get_d16 (op)]);
111398b9484cSchristos 	break;
111498b9484cSchristos 
111598b9484cSchristos       case OP_mulsu:
1116ba340e45Schristos 	gen_mul (cpu, (sword)(word)sram[get_r16_23 (op)]
111798b9484cSchristos 		      * (sword)(sbyte)sram[get_d16_23 (op)]);
111898b9484cSchristos 	break;
111998b9484cSchristos 
112098b9484cSchristos       case OP_fmul:
1121ba340e45Schristos 	gen_mul (cpu, ((word)sram[get_r16_23 (op)]
112298b9484cSchristos 		       * (word)sram[get_d16_23 (op)]) << 1);
112398b9484cSchristos 	break;
112498b9484cSchristos 
112598b9484cSchristos       case OP_fmuls:
1126ba340e45Schristos 	gen_mul (cpu, ((sword)(sbyte)sram[get_r16_23 (op)]
112798b9484cSchristos 		       * (sword)(sbyte)sram[get_d16_23 (op)]) << 1);
112898b9484cSchristos 	break;
112998b9484cSchristos 
113098b9484cSchristos       case OP_fmulsu:
1131ba340e45Schristos 	gen_mul (cpu, ((sword)(word)sram[get_r16_23 (op)]
113298b9484cSchristos 		       * (sword)(sbyte)sram[get_d16_23 (op)]) << 1);
113398b9484cSchristos 	break;
113498b9484cSchristos 
113598b9484cSchristos       case OP_adc:
113698b9484cSchristos       case OP_add:
113798b9484cSchristos 	r = sram[get_r (op)];
113898b9484cSchristos 	d = get_d (op);
113998b9484cSchristos 	vd = sram[d];
114098b9484cSchristos 	res = r + vd + (sram[SREG] & flash[ipc].r);
114198b9484cSchristos 	sram[d] = res;
114298b9484cSchristos 	update_flags_add (res, vd, r);
114398b9484cSchristos 	break;
114498b9484cSchristos 
114598b9484cSchristos       case OP_sub:
114698b9484cSchristos 	d = get_d (op);
114798b9484cSchristos 	vd = sram[d];
114898b9484cSchristos 	r = sram[get_r (op)];
114998b9484cSchristos 	res = vd - r;
115098b9484cSchristos 	sram[d] = res;
115198b9484cSchristos 	update_flags_sub (res, vd, r);
115298b9484cSchristos 	if (res == 0)
115398b9484cSchristos 	  sram[SREG] |= SREG_Z;
115498b9484cSchristos 	break;
115598b9484cSchristos 
115698b9484cSchristos       case OP_sbc:
115798b9484cSchristos 	{
115898b9484cSchristos 	  byte old = sram[SREG];
115998b9484cSchristos 	  d = get_d (op);
116098b9484cSchristos 	  vd = sram[d];
116198b9484cSchristos 	  r = sram[get_r (op)];
116298b9484cSchristos 	  res = vd - r - (old & SREG_C);
116398b9484cSchristos 	  sram[d] = res;
116498b9484cSchristos 	  update_flags_sub (res, vd, r);
116598b9484cSchristos 	  if (res == 0 && (old & SREG_Z))
116698b9484cSchristos 	    sram[SREG] |= SREG_Z;
116798b9484cSchristos 	}
116898b9484cSchristos 	break;
116998b9484cSchristos 
117098b9484cSchristos       case OP_subi:
117198b9484cSchristos 	d = get_d16 (op);
117298b9484cSchristos 	vd = sram[d];
117398b9484cSchristos 	r = get_K (op);
117498b9484cSchristos 	res = vd - r;
117598b9484cSchristos 	sram[d] = res;
117698b9484cSchristos 	update_flags_sub (res, vd, r);
117798b9484cSchristos 	if (res == 0)
117898b9484cSchristos 	  sram[SREG] |= SREG_Z;
117998b9484cSchristos 	break;
118098b9484cSchristos 
118198b9484cSchristos       case OP_sbci:
118298b9484cSchristos 	{
118398b9484cSchristos 	  byte old = sram[SREG];
118498b9484cSchristos 
118598b9484cSchristos 	  d = get_d16 (op);
118698b9484cSchristos 	  vd = sram[d];
118798b9484cSchristos 	  r = get_K (op);
118898b9484cSchristos 	  res = vd - r - (old & SREG_C);
118998b9484cSchristos 	  sram[d] = res;
119098b9484cSchristos 	  update_flags_sub (res, vd, r);
119198b9484cSchristos 	  if (res == 0 && (old & SREG_Z))
119298b9484cSchristos 	    sram[SREG] |= SREG_Z;
119398b9484cSchristos 	}
119498b9484cSchristos 	break;
119598b9484cSchristos 
119698b9484cSchristos       case OP_mov:
119798b9484cSchristos 	sram[get_d (op)] = sram[get_r (op)];
119898b9484cSchristos 	break;
119998b9484cSchristos 
120098b9484cSchristos       case OP_movw:
120198b9484cSchristos 	d = (op & 0xf0) >> 3;
120298b9484cSchristos 	r = (op & 0x0f) << 1;
120398b9484cSchristos 	sram[d] = sram[r];
120498b9484cSchristos 	sram[d + 1] = sram[r + 1];
120598b9484cSchristos 	break;
120698b9484cSchristos 
120798b9484cSchristos       case OP_out:
120898b9484cSchristos 	d = get_A (op) + 0x20;
120998b9484cSchristos 	res = sram[get_d (op)];
121098b9484cSchristos 	sram[d] = res;
121198b9484cSchristos 	if (d == STDIO_PORT)
121298b9484cSchristos 	  putchar (res);
121398b9484cSchristos 	else if (d == EXIT_PORT)
1214*88241920Schristos 	  sim_engine_halt (CPU_STATE (cpu), cpu, NULL, avr_cpu->pc, sim_exited, 0);
121598b9484cSchristos 	else if (d == ABORT_PORT)
1216*88241920Schristos 	  sim_engine_halt (CPU_STATE (cpu), cpu, NULL, avr_cpu->pc, sim_exited, 1);
121798b9484cSchristos 	break;
121898b9484cSchristos 
121998b9484cSchristos       case OP_in:
122098b9484cSchristos 	d = get_A (op) + 0x20;
122198b9484cSchristos 	sram[get_d (op)] = sram[d];
122298b9484cSchristos 	break;
122398b9484cSchristos 
122498b9484cSchristos       case OP_cbi:
122598b9484cSchristos 	d = get_biA (op) + 0x20;
122698b9484cSchristos 	sram[d] &= ~(1 << get_b(op));
122798b9484cSchristos 	break;
122898b9484cSchristos 
122998b9484cSchristos       case OP_sbi:
123098b9484cSchristos 	d = get_biA (op) + 0x20;
123198b9484cSchristos 	sram[d] |= 1 << get_b(op);
123298b9484cSchristos 	break;
123398b9484cSchristos 
123498b9484cSchristos       case OP_sbic:
123598b9484cSchristos 	if (!(sram[get_biA (op) + 0x20] & 1 << get_b(op)))
123698b9484cSchristos 	  {
1237*88241920Schristos 	    int l = get_insn_length (avr_cpu->pc);
1238*88241920Schristos 	    avr_cpu->pc += l;
1239*88241920Schristos 	    avr_cpu->cycles += l;
124098b9484cSchristos 	  }
124198b9484cSchristos 	break;
124298b9484cSchristos 
124398b9484cSchristos       case OP_sbis:
124498b9484cSchristos 	if (sram[get_biA (op) + 0x20] & 1 << get_b(op))
124598b9484cSchristos 	  {
1246*88241920Schristos 	    int l = get_insn_length (avr_cpu->pc);
1247*88241920Schristos 	    avr_cpu->pc += l;
1248*88241920Schristos 	    avr_cpu->cycles += l;
124998b9484cSchristos 	  }
125098b9484cSchristos 	break;
125198b9484cSchristos 
125298b9484cSchristos       case OP_ldi:
125398b9484cSchristos 	res = get_K (op);
125498b9484cSchristos 	d = get_d16 (op);
125598b9484cSchristos 	sram[d] = res;
125698b9484cSchristos 	break;
125798b9484cSchristos 
125898b9484cSchristos       case OP_lds:
1259*88241920Schristos 	sram[get_d (op)] = sram[flash[avr_cpu->pc].op];
1260*88241920Schristos 	avr_cpu->pc++;
1261*88241920Schristos 	avr_cpu->cycles++;
126298b9484cSchristos 	break;
126398b9484cSchristos 
126498b9484cSchristos       case OP_sts:
1265*88241920Schristos 	sram[flash[avr_cpu->pc].op] = sram[get_d (op)];
1266*88241920Schristos 	avr_cpu->pc++;
1267*88241920Schristos 	avr_cpu->cycles++;
126898b9484cSchristos 	break;
126998b9484cSchristos 
127098b9484cSchristos       case OP_cpse:
127198b9484cSchristos 	if (sram[get_r (op)] == sram[get_d (op)])
127298b9484cSchristos 	  {
1273*88241920Schristos 	    int l = get_insn_length (avr_cpu->pc);
1274*88241920Schristos 	    avr_cpu->pc += l;
1275*88241920Schristos 	    avr_cpu->cycles += l;
127698b9484cSchristos 	  }
127798b9484cSchristos 	break;
127898b9484cSchristos 
127998b9484cSchristos       case OP_cp:
128098b9484cSchristos 	r = sram[get_r (op)];
128198b9484cSchristos 	d = sram[get_d (op)];
128298b9484cSchristos 	res = d - r;
128398b9484cSchristos 	update_flags_sub (res, d, r);
128498b9484cSchristos 	if (res == 0)
128598b9484cSchristos 	  sram[SREG] |= SREG_Z;
128698b9484cSchristos 	break;
128798b9484cSchristos 
128898b9484cSchristos       case OP_cpi:
128998b9484cSchristos 	r = get_K (op);
129098b9484cSchristos 	d = sram[get_d16 (op)];
129198b9484cSchristos 	res = d - r;
129298b9484cSchristos 	update_flags_sub (res, d, r);
129398b9484cSchristos 	if (res == 0)
129498b9484cSchristos 	  sram[SREG] |= SREG_Z;
129598b9484cSchristos 	break;
129698b9484cSchristos 
129798b9484cSchristos       case OP_cpc:
129898b9484cSchristos 	{
129998b9484cSchristos 	  byte old = sram[SREG];
130098b9484cSchristos 	  d = sram[get_d (op)];
130198b9484cSchristos 	  r = sram[get_r (op)];
130298b9484cSchristos 	  res = d - r - (old & SREG_C);
130398b9484cSchristos 	  update_flags_sub (res, d, r);
130498b9484cSchristos 	  if (res == 0 && (old & SREG_Z))
130598b9484cSchristos 	    sram[SREG] |= SREG_Z;
130698b9484cSchristos 	}
130798b9484cSchristos 	break;
130898b9484cSchristos 
130998b9484cSchristos       case OP_brbc:
131098b9484cSchristos 	if (!(sram[SREG] & flash[ipc].r))
131198b9484cSchristos 	  {
1312*88241920Schristos 	    avr_cpu->pc = (avr_cpu->pc + get_k (op)) & PC_MASK;
1313*88241920Schristos 	    avr_cpu->cycles++;
131498b9484cSchristos 	  }
131598b9484cSchristos 	break;
131698b9484cSchristos 
131798b9484cSchristos       case OP_brbs:
131898b9484cSchristos 	if (sram[SREG] & flash[ipc].r)
131998b9484cSchristos 	  {
1320*88241920Schristos 	    avr_cpu->pc = (avr_cpu->pc + get_k (op)) & PC_MASK;
1321*88241920Schristos 	    avr_cpu->cycles++;
132298b9484cSchristos 	  }
132398b9484cSchristos 	break;
132498b9484cSchristos 
132598b9484cSchristos       case OP_lpm:
132698b9484cSchristos 	sram[0] = get_lpm (read_word (REGZ));
1327*88241920Schristos 	avr_cpu->cycles += 2;
132898b9484cSchristos 	break;
132998b9484cSchristos 
133098b9484cSchristos       case OP_lpm_Z:
133198b9484cSchristos 	sram[get_d (op)] = get_lpm (read_word (REGZ));
1332*88241920Schristos 	avr_cpu->cycles += 2;
133398b9484cSchristos 	break;
133498b9484cSchristos 
133598b9484cSchristos       case OP_lpm_inc_Z:
133698b9484cSchristos 	sram[get_d (op)] = get_lpm (read_word_post_inc (REGZ));
1337*88241920Schristos 	avr_cpu->cycles += 2;
133898b9484cSchristos 	break;
133998b9484cSchristos 
134098b9484cSchristos       case OP_elpm:
134198b9484cSchristos 	sram[0] = get_lpm (get_z ());
1342*88241920Schristos 	avr_cpu->cycles += 2;
134398b9484cSchristos 	break;
134498b9484cSchristos 
134598b9484cSchristos       case OP_elpm_Z:
134698b9484cSchristos 	sram[get_d (op)] = get_lpm (get_z ());
1347*88241920Schristos 	avr_cpu->cycles += 2;
134898b9484cSchristos 	break;
134998b9484cSchristos 
135098b9484cSchristos       case OP_elpm_inc_Z:
135198b9484cSchristos 	{
135298b9484cSchristos 	  unsigned int z = get_z ();
135398b9484cSchristos 
135498b9484cSchristos 	  sram[get_d (op)] = get_lpm (z);
135598b9484cSchristos 	  z++;
135698b9484cSchristos 	  sram[REGZ_LO] = z;
135798b9484cSchristos 	  sram[REGZ_HI] = z >> 8;
135898b9484cSchristos 	  sram[RAMPZ] = z >> 16;
135998b9484cSchristos 	}
1360*88241920Schristos 	avr_cpu->cycles += 2;
136198b9484cSchristos 	break;
136298b9484cSchristos 
136398b9484cSchristos       case OP_ld_Z_inc:
136498b9484cSchristos 	sram[get_d (op)] = sram[read_word_post_inc (REGZ) & SRAM_MASK];
1365*88241920Schristos 	avr_cpu->cycles++;
136698b9484cSchristos 	break;
136798b9484cSchristos 
136898b9484cSchristos       case OP_ld_dec_Z:
136998b9484cSchristos 	sram[get_d (op)] = sram[read_word_pre_dec (REGZ) & SRAM_MASK];
1370*88241920Schristos 	avr_cpu->cycles++;
137198b9484cSchristos 	break;
137298b9484cSchristos 
137398b9484cSchristos       case OP_ld_X_inc:
137498b9484cSchristos 	sram[get_d (op)] = sram[read_word_post_inc (REGX) & SRAM_MASK];
1375*88241920Schristos 	avr_cpu->cycles++;
137698b9484cSchristos 	break;
137798b9484cSchristos 
137898b9484cSchristos       case OP_ld_dec_X:
137998b9484cSchristos 	sram[get_d (op)] = sram[read_word_pre_dec (REGX) & SRAM_MASK];
1380*88241920Schristos 	avr_cpu->cycles++;
138198b9484cSchristos 	break;
138298b9484cSchristos 
138398b9484cSchristos       case OP_ld_Y_inc:
138498b9484cSchristos 	sram[get_d (op)] = sram[read_word_post_inc (REGY) & SRAM_MASK];
1385*88241920Schristos 	avr_cpu->cycles++;
138698b9484cSchristos 	break;
138798b9484cSchristos 
138898b9484cSchristos       case OP_ld_dec_Y:
138998b9484cSchristos 	sram[get_d (op)] = sram[read_word_pre_dec (REGY) & SRAM_MASK];
1390*88241920Schristos 	avr_cpu->cycles++;
139198b9484cSchristos 	break;
139298b9484cSchristos 
139398b9484cSchristos       case OP_st_X:
139498b9484cSchristos 	sram[read_word (REGX) & SRAM_MASK] = sram[get_d (op)];
1395*88241920Schristos 	avr_cpu->cycles++;
139698b9484cSchristos 	break;
139798b9484cSchristos 
139898b9484cSchristos       case OP_st_X_inc:
139998b9484cSchristos 	sram[read_word_post_inc (REGX) & SRAM_MASK] = sram[get_d (op)];
1400*88241920Schristos 	avr_cpu->cycles++;
140198b9484cSchristos 	break;
140298b9484cSchristos 
140398b9484cSchristos       case OP_st_dec_X:
140498b9484cSchristos 	sram[read_word_pre_dec (REGX) & SRAM_MASK] = sram[get_d (op)];
1405*88241920Schristos 	avr_cpu->cycles++;
140698b9484cSchristos 	break;
140798b9484cSchristos 
140898b9484cSchristos       case OP_st_Z_inc:
140998b9484cSchristos 	sram[read_word_post_inc (REGZ) & SRAM_MASK] = sram[get_d (op)];
1410*88241920Schristos 	avr_cpu->cycles++;
141198b9484cSchristos 	break;
141298b9484cSchristos 
141398b9484cSchristos       case OP_st_dec_Z:
141498b9484cSchristos 	sram[read_word_pre_dec (REGZ) & SRAM_MASK] = sram[get_d (op)];
1415*88241920Schristos 	avr_cpu->cycles++;
141698b9484cSchristos 	break;
141798b9484cSchristos 
141898b9484cSchristos       case OP_st_Y_inc:
141998b9484cSchristos 	sram[read_word_post_inc (REGY) & SRAM_MASK] = sram[get_d (op)];
1420*88241920Schristos 	avr_cpu->cycles++;
142198b9484cSchristos 	break;
142298b9484cSchristos 
142398b9484cSchristos       case OP_st_dec_Y:
142498b9484cSchristos 	sram[read_word_pre_dec (REGY) & SRAM_MASK] = sram[get_d (op)];
1425*88241920Schristos 	avr_cpu->cycles++;
142698b9484cSchristos 	break;
142798b9484cSchristos 
142898b9484cSchristos       case OP_std_Y:
142998b9484cSchristos 	sram[read_word (REGY) + flash[ipc].r] = sram[get_d (op)];
1430*88241920Schristos 	avr_cpu->cycles++;
143198b9484cSchristos 	break;
143298b9484cSchristos 
143398b9484cSchristos       case OP_std_Z:
143498b9484cSchristos 	sram[read_word (REGZ) + flash[ipc].r] = sram[get_d (op)];
1435*88241920Schristos 	avr_cpu->cycles++;
143698b9484cSchristos 	break;
143798b9484cSchristos 
143898b9484cSchristos       case OP_ldd_Z:
143998b9484cSchristos 	sram[get_d (op)] = sram[read_word (REGZ) + flash[ipc].r];
1440*88241920Schristos 	avr_cpu->cycles++;
144198b9484cSchristos 	break;
144298b9484cSchristos 
144398b9484cSchristos       case OP_ldd_Y:
144498b9484cSchristos 	sram[get_d (op)] = sram[read_word (REGY) + flash[ipc].r];
1445*88241920Schristos 	avr_cpu->cycles++;
144698b9484cSchristos 	break;
144798b9484cSchristos 
144898b9484cSchristos       case OP_ld_X:
144998b9484cSchristos 	sram[get_d (op)] = sram[read_word (REGX) & SRAM_MASK];
1450*88241920Schristos 	avr_cpu->cycles++;
145198b9484cSchristos 	break;
145298b9484cSchristos 
145398b9484cSchristos       case OP_sbiw:
145498b9484cSchristos 	{
145598b9484cSchristos 	  word wk = get_k6 (op);
145698b9484cSchristos 	  word wres;
145798b9484cSchristos 	  word wr;
145898b9484cSchristos 
145998b9484cSchristos 	  d = get_d24 (op);
146098b9484cSchristos 	  wr = read_word (d);
146198b9484cSchristos 	  wres = wr - wk;
146298b9484cSchristos 
146398b9484cSchristos 	  sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
146498b9484cSchristos 	  if (wres == 0)
146598b9484cSchristos 	    sram[SREG] |= SREG_Z;
146698b9484cSchristos 	  if (wres & 0x8000)
146798b9484cSchristos 	    sram[SREG] |= SREG_N;
146898b9484cSchristos 	  if (wres & ~wr & 0x8000)
146998b9484cSchristos 	    sram[SREG] |= SREG_C;
147098b9484cSchristos 	  if (~wres & wr & 0x8000)
147198b9484cSchristos 	    sram[SREG] |= SREG_V;
147298b9484cSchristos 	  if (((~wres & wr) ^ wres) & 0x8000)
147398b9484cSchristos 	    sram[SREG] |= SREG_S;
147498b9484cSchristos 	  write_word (d, wres);
147598b9484cSchristos 	}
1476*88241920Schristos 	avr_cpu->cycles++;
147798b9484cSchristos 	break;
147898b9484cSchristos 
147998b9484cSchristos       case OP_adiw:
148098b9484cSchristos 	{
148198b9484cSchristos 	  word wk = get_k6 (op);
148298b9484cSchristos 	  word wres;
148398b9484cSchristos 	  word wr;
148498b9484cSchristos 
148598b9484cSchristos 	  d = get_d24 (op);
148698b9484cSchristos 	  wr = read_word (d);
148798b9484cSchristos 	  wres = wr + wk;
148898b9484cSchristos 
148998b9484cSchristos 	  sram[SREG] &= ~(SREG_S | SREG_V | SREG_N | SREG_Z | SREG_C);
149098b9484cSchristos 	  if (wres == 0)
149198b9484cSchristos 	    sram[SREG] |= SREG_Z;
149298b9484cSchristos 	  if (wres & 0x8000)
149398b9484cSchristos 	    sram[SREG] |= SREG_N;
149498b9484cSchristos 	  if (~wres & wr & 0x8000)
149598b9484cSchristos 	    sram[SREG] |= SREG_C;
149698b9484cSchristos 	  if (wres & ~wr & 0x8000)
149798b9484cSchristos 	    sram[SREG] |= SREG_V;
149898b9484cSchristos 	  if (((wres & ~wr) ^ wres) & 0x8000)
149998b9484cSchristos 	    sram[SREG] |= SREG_S;
150098b9484cSchristos 	  write_word (d, wres);
150198b9484cSchristos 	}
1502*88241920Schristos 	avr_cpu->cycles++;
150398b9484cSchristos 	break;
150498b9484cSchristos 
150598b9484cSchristos       case OP_bad:
1506*88241920Schristos 	sim_engine_halt (CPU_STATE (cpu), cpu, NULL, avr_cpu->pc, sim_signalled, SIM_SIGILL);
150798b9484cSchristos 
150898b9484cSchristos       default:
1509*88241920Schristos 	sim_engine_halt (CPU_STATE (cpu), cpu, NULL, avr_cpu->pc, sim_signalled, SIM_SIGILL);
151098b9484cSchristos       }
151198b9484cSchristos }
151298b9484cSchristos 
1513212397c6Schristos void
1514212397c6Schristos sim_engine_run (SIM_DESC sd,
1515212397c6Schristos 		int next_cpu_nr, /* ignore  */
1516212397c6Schristos 		int nr_cpus, /* ignore  */
1517212397c6Schristos 		int siggnal) /* ignore  */
151898b9484cSchristos {
1519212397c6Schristos   SIM_CPU *cpu;
152098b9484cSchristos 
1521212397c6Schristos   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
152298b9484cSchristos 
1523212397c6Schristos   cpu = STATE_CPU (sd, 0);
152498b9484cSchristos 
1525212397c6Schristos   while (1)
1526212397c6Schristos     {
1527212397c6Schristos       step_once (cpu);
1528212397c6Schristos       if (sim_events_tick (sd))
1529212397c6Schristos 	sim_events_process (sd);
1530212397c6Schristos     }
153198b9484cSchristos }
153298b9484cSchristos 
1533*88241920Schristos uint64_t
1534*88241920Schristos sim_write (SIM_DESC sd, uint64_t addr, const void *buffer, uint64_t size)
153598b9484cSchristos {
153698b9484cSchristos   int osize = size;
153798b9484cSchristos 
153898b9484cSchristos   if (addr >= 0 && addr < SRAM_VADDR)
153998b9484cSchristos     {
15404b169a6bSchristos       const unsigned char *data = buffer;
154198b9484cSchristos       while (size > 0 && addr < (MAX_AVR_FLASH << 1))
154298b9484cSchristos 	{
154398b9484cSchristos           word val = flash[addr >> 1].op;
154498b9484cSchristos 
154598b9484cSchristos           if (addr & 1)
15464b169a6bSchristos             val = (val & 0xff) | (data[0] << 8);
154798b9484cSchristos           else
15484b169a6bSchristos             val = (val & 0xff00) | data[0];
154998b9484cSchristos 
155098b9484cSchristos 	  flash[addr >> 1].op = val;
155198b9484cSchristos 	  flash[addr >> 1].code = OP_unknown;
155298b9484cSchristos 	  addr++;
15534b169a6bSchristos 	  data++;
155498b9484cSchristos 	  size--;
155598b9484cSchristos 	}
155698b9484cSchristos       return osize - size;
155798b9484cSchristos     }
155898b9484cSchristos   else if (addr >= SRAM_VADDR && addr < SRAM_VADDR + MAX_AVR_SRAM)
155998b9484cSchristos     {
156098b9484cSchristos       addr -= SRAM_VADDR;
156198b9484cSchristos       if (addr + size > MAX_AVR_SRAM)
156298b9484cSchristos 	size = MAX_AVR_SRAM - addr;
156398b9484cSchristos       memcpy (sram + addr, buffer, size);
156498b9484cSchristos       return size;
156598b9484cSchristos     }
156698b9484cSchristos   else
156798b9484cSchristos     return 0;
156898b9484cSchristos }
156998b9484cSchristos 
1570*88241920Schristos uint64_t
1571*88241920Schristos sim_read (SIM_DESC sd, uint64_t addr, void *buffer, uint64_t size)
157298b9484cSchristos {
157398b9484cSchristos   int osize = size;
157498b9484cSchristos 
157598b9484cSchristos   if (addr >= 0 && addr < SRAM_VADDR)
157698b9484cSchristos     {
15774b169a6bSchristos       unsigned char *data = buffer;
157898b9484cSchristos       while (size > 0 && addr < (MAX_AVR_FLASH << 1))
157998b9484cSchristos 	{
158098b9484cSchristos           word val = flash[addr >> 1].op;
158198b9484cSchristos 
158298b9484cSchristos           if (addr & 1)
158398b9484cSchristos             val >>= 8;
158498b9484cSchristos 
15854b169a6bSchristos           *data++ = val;
158698b9484cSchristos 	  addr++;
158798b9484cSchristos 	  size--;
158898b9484cSchristos 	}
158998b9484cSchristos       return osize - size;
159098b9484cSchristos     }
159198b9484cSchristos   else if (addr >= SRAM_VADDR && addr < SRAM_VADDR + MAX_AVR_SRAM)
159298b9484cSchristos     {
159398b9484cSchristos       addr -= SRAM_VADDR;
159498b9484cSchristos       if (addr + size > MAX_AVR_SRAM)
159598b9484cSchristos 	size = MAX_AVR_SRAM - addr;
159698b9484cSchristos       memcpy (buffer, sram + addr, size);
159798b9484cSchristos       return size;
159898b9484cSchristos     }
159998b9484cSchristos   else
160098b9484cSchristos     {
160198b9484cSchristos       /* Avoid errors.  */
160298b9484cSchristos       memset (buffer, 0, size);
160398b9484cSchristos       return size;
160498b9484cSchristos     }
160598b9484cSchristos }
160698b9484cSchristos 
1607ba340e45Schristos static int
16084b169a6bSchristos avr_reg_store (SIM_CPU *cpu, int rn, const void *buf, int length)
160998b9484cSchristos {
1610*88241920Schristos   struct avr_sim_cpu *avr_cpu = AVR_SIM_CPU (cpu);
16114b169a6bSchristos   const unsigned char *memory = buf;
16124b169a6bSchristos 
161398b9484cSchristos   if (rn < 32 && length == 1)
161498b9484cSchristos     {
161598b9484cSchristos       sram[rn] = *memory;
161698b9484cSchristos       return 1;
161798b9484cSchristos     }
161898b9484cSchristos   if (rn == AVR_SREG_REGNUM && length == 1)
161998b9484cSchristos     {
162098b9484cSchristos       sram[SREG] = *memory;
162198b9484cSchristos       return 1;
162298b9484cSchristos     }
162398b9484cSchristos   if (rn == AVR_SP_REGNUM && length == 2)
162498b9484cSchristos     {
162598b9484cSchristos       sram[REG_SP] = memory[0];
162698b9484cSchristos       sram[REG_SP + 1] = memory[1];
162798b9484cSchristos       return 2;
162898b9484cSchristos     }
162998b9484cSchristos   if (rn == AVR_PC_REGNUM && length == 4)
163098b9484cSchristos     {
1631*88241920Schristos       avr_cpu->pc = (memory[0] >> 1) | (memory[1] << 7)
163298b9484cSchristos 		| (memory[2] << 15) | (memory[3] << 23);
1633*88241920Schristos       avr_cpu->pc &= PC_MASK;
163498b9484cSchristos       return 4;
163598b9484cSchristos     }
163698b9484cSchristos   return 0;
163798b9484cSchristos }
163898b9484cSchristos 
1639ba340e45Schristos static int
16404b169a6bSchristos avr_reg_fetch (SIM_CPU *cpu, int rn, void *buf, int length)
164198b9484cSchristos {
1642*88241920Schristos   struct avr_sim_cpu *avr_cpu = AVR_SIM_CPU (cpu);
16434b169a6bSchristos   unsigned char *memory = buf;
16444b169a6bSchristos 
164598b9484cSchristos   if (rn < 32 && length == 1)
164698b9484cSchristos     {
164798b9484cSchristos       *memory = sram[rn];
164898b9484cSchristos       return 1;
164998b9484cSchristos     }
165098b9484cSchristos   if (rn == AVR_SREG_REGNUM && length == 1)
165198b9484cSchristos     {
165298b9484cSchristos       *memory = sram[SREG];
165398b9484cSchristos       return 1;
165498b9484cSchristos     }
165598b9484cSchristos   if (rn == AVR_SP_REGNUM && length == 2)
165698b9484cSchristos     {
165798b9484cSchristos       memory[0] = sram[REG_SP];
165898b9484cSchristos       memory[1] = sram[REG_SP + 1];
165998b9484cSchristos       return 2;
166098b9484cSchristos     }
166198b9484cSchristos   if (rn == AVR_PC_REGNUM && length == 4)
166298b9484cSchristos     {
1663*88241920Schristos       memory[0] = avr_cpu->pc << 1;
1664*88241920Schristos       memory[1] = avr_cpu->pc >> 7;
1665*88241920Schristos       memory[2] = avr_cpu->pc >> 15;
1666*88241920Schristos       memory[3] = avr_cpu->pc >> 23;
166798b9484cSchristos       return 4;
166898b9484cSchristos     }
166998b9484cSchristos   return 0;
167098b9484cSchristos }
167198b9484cSchristos 
1672212397c6Schristos static sim_cia
1673212397c6Schristos avr_pc_get (sim_cpu *cpu)
167498b9484cSchristos {
1675*88241920Schristos   return AVR_SIM_CPU (cpu)->pc;
167698b9484cSchristos }
167798b9484cSchristos 
1678212397c6Schristos static void
1679ba340e45Schristos avr_pc_set (sim_cpu *cpu, sim_cia pc)
168098b9484cSchristos {
1681*88241920Schristos   AVR_SIM_CPU (cpu)->pc = pc;
168298b9484cSchristos }
168398b9484cSchristos 
1684212397c6Schristos static void
1685212397c6Schristos free_state (SIM_DESC sd)
168698b9484cSchristos {
1687212397c6Schristos   if (STATE_MODULES (sd) != NULL)
1688212397c6Schristos     sim_module_uninstall (sd);
1689212397c6Schristos   sim_cpu_free_all (sd);
1690212397c6Schristos   sim_state_free (sd);
169198b9484cSchristos }
169298b9484cSchristos 
169398b9484cSchristos SIM_DESC
1694ba340e45Schristos sim_open (SIM_OPEN_KIND kind, host_callback *cb,
1695ba340e45Schristos 	  struct bfd *abfd, char * const *argv)
169698b9484cSchristos {
1697212397c6Schristos   int i;
16984b169a6bSchristos   SIM_DESC sd = sim_state_alloc_extra (kind, cb, sizeof (struct avr_sim_state));
1699212397c6Schristos   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
170098b9484cSchristos 
17014b169a6bSchristos   /* Set default options before parsing user options.  */
17024b169a6bSchristos   current_alignment = STRICT_ALIGNMENT;
17034b169a6bSchristos   current_target_byte_order = BFD_ENDIAN_LITTLE;
17044b169a6bSchristos 
1705212397c6Schristos   /* The cpu data is kept in a separately allocated chunk of memory.  */
1706*88241920Schristos   if (sim_cpu_alloc_all_extra (sd, 0, sizeof (struct avr_sim_cpu))
1707*88241920Schristos       != SIM_RC_OK)
1708212397c6Schristos     {
1709212397c6Schristos       free_state (sd);
1710212397c6Schristos       return 0;
171198b9484cSchristos     }
171298b9484cSchristos 
1713212397c6Schristos   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
171498b9484cSchristos     {
1715212397c6Schristos       free_state (sd);
1716212397c6Schristos       return 0;
171798b9484cSchristos     }
171898b9484cSchristos 
1719ba340e45Schristos   /* The parser will print an error message for us, so we silently return.  */
1720212397c6Schristos   if (sim_parse_args (sd, argv) != SIM_RC_OK)
172198b9484cSchristos     {
1722212397c6Schristos       free_state (sd);
1723212397c6Schristos       return 0;
1724212397c6Schristos     }
1725212397c6Schristos 
1726212397c6Schristos   /* Check for/establish the a reference program image.  */
17274b169a6bSchristos   if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
1728212397c6Schristos     {
1729212397c6Schristos       free_state (sd);
1730212397c6Schristos       return 0;
1731212397c6Schristos     }
1732212397c6Schristos 
1733212397c6Schristos   /* Configure/verify the target byte order and other runtime
1734212397c6Schristos      configuration options.  */
1735212397c6Schristos   if (sim_config (sd) != SIM_RC_OK)
1736212397c6Schristos     {
1737212397c6Schristos       sim_module_uninstall (sd);
1738212397c6Schristos       return 0;
1739212397c6Schristos     }
1740212397c6Schristos 
1741212397c6Schristos   if (sim_post_argv_init (sd) != SIM_RC_OK)
1742212397c6Schristos     {
1743212397c6Schristos       /* Uninstall the modules to avoid memory leaks,
1744212397c6Schristos 	 file descriptor leaks, etc.  */
1745212397c6Schristos       sim_module_uninstall (sd);
1746212397c6Schristos       return 0;
1747212397c6Schristos     }
1748212397c6Schristos 
1749212397c6Schristos   /* CPU specific initialization.  */
1750212397c6Schristos   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
1751212397c6Schristos     {
1752212397c6Schristos       SIM_CPU *cpu = STATE_CPU (sd, i);
1753212397c6Schristos 
1754ba340e45Schristos       CPU_REG_FETCH (cpu) = avr_reg_fetch;
1755ba340e45Schristos       CPU_REG_STORE (cpu) = avr_reg_store;
1756212397c6Schristos       CPU_PC_FETCH (cpu) = avr_pc_get;
1757212397c6Schristos       CPU_PC_STORE (cpu) = avr_pc_set;
1758212397c6Schristos     }
175998b9484cSchristos 
176098b9484cSchristos   /* Clear all the memory.  */
176198b9484cSchristos   memset (sram, 0, sizeof (sram));
176298b9484cSchristos   memset (flash, 0, sizeof (flash));
176398b9484cSchristos 
1764212397c6Schristos   return sd;
1765212397c6Schristos }
176698b9484cSchristos 
176798b9484cSchristos SIM_RC
1768ba340e45Schristos sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
1769ba340e45Schristos 		     char * const *argv, char * const *env)
177098b9484cSchristos {
17714b169a6bSchristos   struct avr_sim_state *state = AVR_SIM_STATE (sd);
1772ba340e45Schristos   SIM_CPU *cpu = STATE_CPU (sd, 0);
1773*88241920Schristos   bfd_vma addr;
1774ba340e45Schristos 
1775212397c6Schristos   /* Set the PC.  */
1776212397c6Schristos   if (abfd != NULL)
1777ba340e45Schristos     addr = bfd_get_start_address (abfd);
1778212397c6Schristos   else
1779ba340e45Schristos     addr = 0;
1780ba340e45Schristos   sim_pc_set (cpu, addr);
178198b9484cSchristos 
1782212397c6Schristos   if (abfd != NULL)
17834b169a6bSchristos     state->avr_pc22 = (bfd_get_mach (abfd) >= bfd_mach_avr6);
1784212397c6Schristos 
178598b9484cSchristos   return SIM_RC_OK;
178698b9484cSchristos }
1787