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