qemu/target/avr/cpu.h
<<
>>
Prefs
   1/*
   2 * QEMU AVR CPU
   3 *
   4 * Copyright (c) 2016-2020 Michael Rolnik
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2.1 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see
  18 * <http://www.gnu.org/licenses/lgpl-2.1.html>
  19 */
  20
  21#ifndef QEMU_AVR_CPU_H
  22#define QEMU_AVR_CPU_H
  23
  24#include "cpu-qom.h"
  25#include "exec/cpu-defs.h"
  26
  27#ifdef CONFIG_USER_ONLY
  28#error "AVR 8-bit does not support user mode"
  29#endif
  30
  31#define AVR_CPU_TYPE_SUFFIX "-" TYPE_AVR_CPU
  32#define AVR_CPU_TYPE_NAME(name) (name AVR_CPU_TYPE_SUFFIX)
  33#define CPU_RESOLVING_TYPE TYPE_AVR_CPU
  34
  35#define TCG_GUEST_DEFAULT_MO 0
  36
  37/*
  38 * AVR has two memory spaces, data & code.
  39 * e.g. both have 0 address
  40 * ST/LD instructions access data space
  41 * LPM/SPM and instruction fetching access code memory space
  42 */
  43#define MMU_CODE_IDX 0
  44#define MMU_DATA_IDX 1
  45
  46#define EXCP_RESET 1
  47#define EXCP_INT(n) (EXCP_RESET + (n) + 1)
  48
  49/* Number of CPU registers */
  50#define NUMBER_OF_CPU_REGISTERS 32
  51/* Number of IO registers accessible by ld/st/in/out */
  52#define NUMBER_OF_IO_REGISTERS 64
  53
  54/*
  55 * Offsets of AVR memory regions in host memory space.
  56 *
  57 * This is needed because the AVR has separate code and data address
  58 * spaces that both have start from zero but have to go somewhere in
  59 * host memory.
  60 *
  61 * It's also useful to know where some things are, like the IO registers.
  62 */
  63/* Flash program memory */
  64#define OFFSET_CODE 0x00000000
  65/* CPU registers, IO registers, and SRAM */
  66#define OFFSET_DATA 0x00800000
  67/* CPU registers specifically, these are mapped at the start of data */
  68#define OFFSET_CPU_REGISTERS OFFSET_DATA
  69/*
  70 * IO registers, including status register, stack pointer, and memory
  71 * mapped peripherals, mapped just after CPU registers
  72 */
  73#define OFFSET_IO_REGISTERS (OFFSET_DATA + NUMBER_OF_CPU_REGISTERS)
  74
  75typedef enum AVRFeature {
  76    AVR_FEATURE_SRAM,
  77
  78    AVR_FEATURE_1_BYTE_PC,
  79    AVR_FEATURE_2_BYTE_PC,
  80    AVR_FEATURE_3_BYTE_PC,
  81
  82    AVR_FEATURE_1_BYTE_SP,
  83    AVR_FEATURE_2_BYTE_SP,
  84
  85    AVR_FEATURE_BREAK,
  86    AVR_FEATURE_DES,
  87    AVR_FEATURE_RMW, /* Read Modify Write - XCH LAC LAS LAT */
  88
  89    AVR_FEATURE_EIJMP_EICALL,
  90    AVR_FEATURE_IJMP_ICALL,
  91    AVR_FEATURE_JMP_CALL,
  92
  93    AVR_FEATURE_ADIW_SBIW,
  94
  95    AVR_FEATURE_SPM,
  96    AVR_FEATURE_SPMX,
  97
  98    AVR_FEATURE_ELPMX,
  99    AVR_FEATURE_ELPM,
 100    AVR_FEATURE_LPMX,
 101    AVR_FEATURE_LPM,
 102
 103    AVR_FEATURE_MOVW,
 104    AVR_FEATURE_MUL,
 105    AVR_FEATURE_RAMPD,
 106    AVR_FEATURE_RAMPX,
 107    AVR_FEATURE_RAMPY,
 108    AVR_FEATURE_RAMPZ,
 109} AVRFeature;
 110
 111typedef struct CPUAVRState CPUAVRState;
 112
 113struct CPUAVRState {
 114    uint32_t pc_w; /* 0x003fffff up to 22 bits */
 115
 116    uint32_t sregC; /* 0x00000001 1 bit */
 117    uint32_t sregZ; /* 0x00000001 1 bit */
 118    uint32_t sregN; /* 0x00000001 1 bit */
 119    uint32_t sregV; /* 0x00000001 1 bit */
 120    uint32_t sregS; /* 0x00000001 1 bit */
 121    uint32_t sregH; /* 0x00000001 1 bit */
 122    uint32_t sregT; /* 0x00000001 1 bit */
 123    uint32_t sregI; /* 0x00000001 1 bit */
 124
 125    uint32_t rampD; /* 0x00ff0000 8 bits */
 126    uint32_t rampX; /* 0x00ff0000 8 bits */
 127    uint32_t rampY; /* 0x00ff0000 8 bits */
 128    uint32_t rampZ; /* 0x00ff0000 8 bits */
 129    uint32_t eind; /* 0x00ff0000 8 bits */
 130
 131    uint32_t r[NUMBER_OF_CPU_REGISTERS]; /* 8 bits each */
 132    uint32_t sp; /* 16 bits */
 133
 134    uint32_t skip; /* if set skip instruction */
 135
 136    uint64_t intsrc; /* interrupt sources */
 137    bool fullacc; /* CPU/MEM if true MEM only otherwise */
 138
 139    uint64_t features;
 140};
 141
 142/**
 143 *  AVRCPU:
 144 *  @env: #CPUAVRState
 145 *
 146 *  A AVR CPU.
 147 */
 148typedef struct AVRCPU {
 149    /*< private >*/
 150    CPUState parent_obj;
 151    /*< public >*/
 152
 153    CPUNegativeOffsetState neg;
 154    CPUAVRState env;
 155} AVRCPU;
 156
 157extern const struct VMStateDescription vms_avr_cpu;
 158
 159void avr_cpu_do_interrupt(CPUState *cpu);
 160bool avr_cpu_exec_interrupt(CPUState *cpu, int int_req);
 161hwaddr avr_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 162int avr_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
 163int avr_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 164int avr_print_insn(bfd_vma addr, disassemble_info *info);
 165vaddr avr_cpu_gdb_adjust_breakpoint(CPUState *cpu, vaddr addr);
 166
 167static inline int avr_feature(CPUAVRState *env, AVRFeature feature)
 168{
 169    return (env->features & (1U << feature)) != 0;
 170}
 171
 172static inline void set_avr_feature(CPUAVRState *env, int feature)
 173{
 174    env->features |= (1U << feature);
 175}
 176
 177#define cpu_list avr_cpu_list
 178#define cpu_mmu_index avr_cpu_mmu_index
 179
 180static inline int avr_cpu_mmu_index(CPUAVRState *env, bool ifetch)
 181{
 182    return ifetch ? MMU_CODE_IDX : MMU_DATA_IDX;
 183}
 184
 185void avr_cpu_tcg_init(void);
 186
 187void avr_cpu_list(void);
 188int cpu_avr_exec(CPUState *cpu);
 189int avr_cpu_memory_rw_debug(CPUState *cs, vaddr address, uint8_t *buf,
 190                            int len, bool is_write);
 191
 192enum {
 193    TB_FLAGS_FULL_ACCESS = 1,
 194    TB_FLAGS_SKIP = 2,
 195};
 196
 197static inline void cpu_get_tb_cpu_state(CPUAVRState *env, target_ulong *pc,
 198                                        target_ulong *cs_base, uint32_t *pflags)
 199{
 200    uint32_t flags = 0;
 201
 202    *pc = env->pc_w * 2;
 203    *cs_base = 0;
 204
 205    if (env->fullacc) {
 206        flags |= TB_FLAGS_FULL_ACCESS;
 207    }
 208    if (env->skip) {
 209        flags |= TB_FLAGS_SKIP;
 210    }
 211
 212    *pflags = flags;
 213}
 214
 215static inline int cpu_interrupts_enabled(CPUAVRState *env)
 216{
 217    return env->sregI != 0;
 218}
 219
 220static inline uint8_t cpu_get_sreg(CPUAVRState *env)
 221{
 222    uint8_t sreg;
 223    sreg = (env->sregC) << 0
 224         | (env->sregZ) << 1
 225         | (env->sregN) << 2
 226         | (env->sregV) << 3
 227         | (env->sregS) << 4
 228         | (env->sregH) << 5
 229         | (env->sregT) << 6
 230         | (env->sregI) << 7;
 231    return sreg;
 232}
 233
 234static inline void cpu_set_sreg(CPUAVRState *env, uint8_t sreg)
 235{
 236    env->sregC = (sreg >> 0) & 0x01;
 237    env->sregZ = (sreg >> 1) & 0x01;
 238    env->sregN = (sreg >> 2) & 0x01;
 239    env->sregV = (sreg >> 3) & 0x01;
 240    env->sregS = (sreg >> 4) & 0x01;
 241    env->sregH = (sreg >> 5) & 0x01;
 242    env->sregT = (sreg >> 6) & 0x01;
 243    env->sregI = (sreg >> 7) & 0x01;
 244}
 245
 246bool avr_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
 247                      MMUAccessType access_type, int mmu_idx,
 248                      bool probe, uintptr_t retaddr);
 249
 250typedef CPUAVRState CPUArchState;
 251typedef AVRCPU ArchCPU;
 252
 253#include "exec/cpu-all.h"
 254
 255#endif /* !defined (QEMU_AVR_CPU_H) */
 256