xref: /openbmc/qemu/target/avr/cpu.h (revision 12b35405)
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 
75 typedef struct CPUAVRState CPUAVRState;
76 
77 struct CPUAVRState {
78     uint32_t pc_w; /* 0x003fffff up to 22 bits */
79 
80     uint32_t sregC; /* 0x00000001 1 bit */
81     uint32_t sregZ; /* 0x00000001 1 bit */
82     uint32_t sregN; /* 0x00000001 1 bit */
83     uint32_t sregV; /* 0x00000001 1 bit */
84     uint32_t sregS; /* 0x00000001 1 bit */
85     uint32_t sregH; /* 0x00000001 1 bit */
86     uint32_t sregT; /* 0x00000001 1 bit */
87     uint32_t sregI; /* 0x00000001 1 bit */
88 
89     uint32_t rampD; /* 0x00ff0000 8 bits */
90     uint32_t rampX; /* 0x00ff0000 8 bits */
91     uint32_t rampY; /* 0x00ff0000 8 bits */
92     uint32_t rampZ; /* 0x00ff0000 8 bits */
93     uint32_t eind; /* 0x00ff0000 8 bits */
94 
95     uint32_t r[NUMBER_OF_CPU_REGISTERS]; /* 8 bits each */
96     uint32_t sp; /* 16 bits */
97 
98     uint32_t skip; /* if set skip instruction */
99 
100     uint64_t intsrc; /* interrupt sources */
101     bool fullacc; /* CPU/MEM if true MEM only otherwise */
102 
103     uint64_t features;
104 };
105 
106 /**
107  *  AVRCPU:
108  *  @env: #CPUAVRState
109  *
110  *  A AVR CPU.
111  */
112 typedef struct AVRCPU {
113     /*< private >*/
114     CPUState parent_obj;
115     /*< public >*/
116 
117     CPUNegativeOffsetState neg;
118     CPUAVRState env;
119 } AVRCPU;
120 
121 extern const struct VMStateDescription vms_avr_cpu;
122 
123 void avr_cpu_do_interrupt(CPUState *cpu);
124 bool avr_cpu_exec_interrupt(CPUState *cpu, int int_req);
125 hwaddr avr_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
126 int avr_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
127 int avr_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
128 
129 #define cpu_list avr_cpu_list
130 #define cpu_signal_handler cpu_avr_signal_handler
131 #define cpu_mmu_index avr_cpu_mmu_index
132 
133 static inline int avr_cpu_mmu_index(CPUAVRState *env, bool ifetch)
134 {
135     return ifetch ? MMU_CODE_IDX : MMU_DATA_IDX;
136 }
137 
138 void avr_cpu_tcg_init(void);
139 
140 void avr_cpu_list(void);
141 int cpu_avr_exec(CPUState *cpu);
142 int cpu_avr_signal_handler(int host_signum, void *pinfo, void *puc);
143 int avr_cpu_memory_rw_debug(CPUState *cs, vaddr address, uint8_t *buf,
144                             int len, bool is_write);
145 
146 enum {
147     TB_FLAGS_FULL_ACCESS = 1,
148     TB_FLAGS_SKIP = 2,
149 };
150 
151 static inline void cpu_get_tb_cpu_state(CPUAVRState *env, target_ulong *pc,
152                                         target_ulong *cs_base, uint32_t *pflags)
153 {
154     uint32_t flags = 0;
155 
156     *pc = env->pc_w * 2;
157     *cs_base = 0;
158 
159     if (env->fullacc) {
160         flags |= TB_FLAGS_FULL_ACCESS;
161     }
162     if (env->skip) {
163         flags |= TB_FLAGS_SKIP;
164     }
165 
166     *pflags = flags;
167 }
168 
169 static inline int cpu_interrupts_enabled(CPUAVRState *env)
170 {
171     return env->sregI != 0;
172 }
173 
174 static inline uint8_t cpu_get_sreg(CPUAVRState *env)
175 {
176     uint8_t sreg;
177     sreg = (env->sregC) << 0
178          | (env->sregZ) << 1
179          | (env->sregN) << 2
180          | (env->sregV) << 3
181          | (env->sregS) << 4
182          | (env->sregH) << 5
183          | (env->sregT) << 6
184          | (env->sregI) << 7;
185     return sreg;
186 }
187 
188 static inline void cpu_set_sreg(CPUAVRState *env, uint8_t sreg)
189 {
190     env->sregC = (sreg >> 0) & 0x01;
191     env->sregZ = (sreg >> 1) & 0x01;
192     env->sregN = (sreg >> 2) & 0x01;
193     env->sregV = (sreg >> 3) & 0x01;
194     env->sregS = (sreg >> 4) & 0x01;
195     env->sregH = (sreg >> 5) & 0x01;
196     env->sregT = (sreg >> 6) & 0x01;
197     env->sregI = (sreg >> 7) & 0x01;
198 }
199 
200 bool avr_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
201                       MMUAccessType access_type, int mmu_idx,
202                       bool probe, uintptr_t retaddr);
203 
204 typedef CPUAVRState CPUArchState;
205 typedef AVRCPU ArchCPU;
206 
207 #include "exec/cpu-all.h"
208 
209 #endif /* !defined (QEMU_AVR_CPU_H) */
210