blob: dd9c230540337ceb76f70e225691939eb5bf9d68 [file] [log] [blame]
bellard5a9fdfe2003-06-15 20:02:25 +00001/*
2 * defines common to all virtual CPUs
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard5a9fdfe2003-06-15 20:02:25 +00004 * Copyright (c) 2003 Fabrice Bellard
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 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
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
bellard5a9fdfe2003-06-15 20:02:25 +000018 */
19#ifndef CPU_ALL_H
20#define CPU_ALL_H
21
blueswir17d99a002009-01-14 19:00:36 +000022#include "qemu-common.h"
Paul Brook1ad21342009-05-19 16:17:58 +010023#include "cpu-common.h"
bellard0ac4bd52004-01-04 15:44:17 +000024
ths5fafdf22007-09-16 21:08:06 +000025/* some important defines:
26 *
bellard0ac4bd52004-01-04 15:44:17 +000027 * WORDS_ALIGNED : if defined, the host cpu can only make word aligned
28 * memory accesses.
ths5fafdf22007-09-16 21:08:06 +000029 *
Juan Quintelae2542fe2009-07-27 16:13:06 +020030 * HOST_WORDS_BIGENDIAN : if defined, the host cpu is big endian and
bellard0ac4bd52004-01-04 15:44:17 +000031 * otherwise little endian.
ths5fafdf22007-09-16 21:08:06 +000032 *
bellard0ac4bd52004-01-04 15:44:17 +000033 * (TARGET_WORDS_ALIGNED : same for target cpu (not supported yet))
ths5fafdf22007-09-16 21:08:06 +000034 *
bellard0ac4bd52004-01-04 15:44:17 +000035 * TARGET_WORDS_BIGENDIAN : same for target cpu
36 */
37
aurel32939ef592008-05-09 18:45:47 +000038#include "softfloat.h"
bellardf193c792004-03-21 17:06:25 +000039
Juan Quintelae2542fe2009-07-27 16:13:06 +020040#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
bellardf193c792004-03-21 17:06:25 +000041#define BSWAP_NEEDED
42#endif
43
44#ifdef BSWAP_NEEDED
45
46static inline uint16_t tswap16(uint16_t s)
47{
48 return bswap16(s);
49}
50
51static inline uint32_t tswap32(uint32_t s)
52{
53 return bswap32(s);
54}
55
56static inline uint64_t tswap64(uint64_t s)
57{
58 return bswap64(s);
59}
60
61static inline void tswap16s(uint16_t *s)
62{
63 *s = bswap16(*s);
64}
65
66static inline void tswap32s(uint32_t *s)
67{
68 *s = bswap32(*s);
69}
70
71static inline void tswap64s(uint64_t *s)
72{
73 *s = bswap64(*s);
74}
75
76#else
77
78static inline uint16_t tswap16(uint16_t s)
79{
80 return s;
81}
82
83static inline uint32_t tswap32(uint32_t s)
84{
85 return s;
86}
87
88static inline uint64_t tswap64(uint64_t s)
89{
90 return s;
91}
92
93static inline void tswap16s(uint16_t *s)
94{
95}
96
97static inline void tswap32s(uint32_t *s)
98{
99}
100
101static inline void tswap64s(uint64_t *s)
102{
103}
104
105#endif
106
107#if TARGET_LONG_SIZE == 4
108#define tswapl(s) tswap32(s)
109#define tswapls(s) tswap32s((uint32_t *)(s))
bellard0a962c02005-02-10 22:00:27 +0000110#define bswaptls(s) bswap32s(s)
bellardf193c792004-03-21 17:06:25 +0000111#else
112#define tswapl(s) tswap64(s)
113#define tswapls(s) tswap64s((uint64_t *)(s))
bellard0a962c02005-02-10 22:00:27 +0000114#define bswaptls(s) bswap64s(s)
bellardf193c792004-03-21 17:06:25 +0000115#endif
116
aurel320ca9d382008-03-13 19:19:16 +0000117typedef union {
118 float32 f;
119 uint32_t l;
120} CPU_FloatU;
121
bellard832ed0f2005-02-07 12:35:16 +0000122/* NOTE: arm FPA is horrible as double 32 bit words are stored in big
123 endian ! */
bellard0ac4bd52004-01-04 15:44:17 +0000124typedef union {
bellard53cd6632005-03-13 18:50:23 +0000125 float64 d;
Juan Quintelae2542fe2009-07-27 16:13:06 +0200126#if defined(HOST_WORDS_BIGENDIAN) \
bellard9d60cac2005-04-07 19:55:52 +0000127 || (defined(__arm__) && !defined(__VFP_FP__) && !defined(CONFIG_SOFTFLOAT))
bellard0ac4bd52004-01-04 15:44:17 +0000128 struct {
bellard0ac4bd52004-01-04 15:44:17 +0000129 uint32_t upper;
bellard832ed0f2005-02-07 12:35:16 +0000130 uint32_t lower;
bellard0ac4bd52004-01-04 15:44:17 +0000131 } l;
132#else
133 struct {
bellard0ac4bd52004-01-04 15:44:17 +0000134 uint32_t lower;
bellard832ed0f2005-02-07 12:35:16 +0000135 uint32_t upper;
bellard0ac4bd52004-01-04 15:44:17 +0000136 } l;
137#endif
138 uint64_t ll;
139} CPU_DoubleU;
140
Aurelien Jarno602308f2011-04-14 00:49:29 +0200141#if defined(FLOATX80)
142typedef union {
143 floatx80 d;
144 struct {
145 uint64_t lower;
146 uint16_t upper;
147 } l;
148} CPU_LDoubleU;
149#endif
150
Peter Maydellc8f930c2011-04-04 12:09:22 +0100151#if defined(CONFIG_SOFTFLOAT)
blueswir11f587322007-11-25 18:40:20 +0000152typedef union {
153 float128 q;
Peter Maydellc8f930c2011-04-04 12:09:22 +0100154#if defined(HOST_WORDS_BIGENDIAN)
blueswir11f587322007-11-25 18:40:20 +0000155 struct {
156 uint32_t upmost;
157 uint32_t upper;
158 uint32_t lower;
159 uint32_t lowest;
160 } l;
161 struct {
162 uint64_t upper;
163 uint64_t lower;
164 } ll;
165#else
166 struct {
167 uint32_t lowest;
168 uint32_t lower;
169 uint32_t upper;
170 uint32_t upmost;
171 } l;
172 struct {
173 uint64_t lower;
174 uint64_t upper;
175 } ll;
176#endif
177} CPU_QuadU;
178#endif
179
bellard61382a52003-10-27 21:22:23 +0000180/* CPU memory access without any memory or io remapping */
181
bellard83d73962004-02-22 11:53:50 +0000182/*
183 * the generic syntax for the memory accesses is:
184 *
185 * load: ld{type}{sign}{size}{endian}_{access_type}(ptr)
186 *
187 * store: st{type}{size}{endian}_{access_type}(ptr, val)
188 *
189 * type is:
190 * (empty): integer access
191 * f : float access
ths5fafdf22007-09-16 21:08:06 +0000192 *
bellard83d73962004-02-22 11:53:50 +0000193 * sign is:
194 * (empty): for floats or 32 bit size
195 * u : unsigned
196 * s : signed
197 *
198 * size is:
199 * b: 8 bits
200 * w: 16 bits
201 * l: 32 bits
202 * q: 64 bits
ths5fafdf22007-09-16 21:08:06 +0000203 *
bellard83d73962004-02-22 11:53:50 +0000204 * endian is:
205 * (empty): target cpu endianness or 8 bit access
206 * r : reversed target cpu endianness (not implemented yet)
207 * be : big endian (not implemented yet)
208 * le : little endian (not implemented yet)
209 *
210 * access_type is:
211 * raw : host memory access
212 * user : user mode access using soft MMU
213 * kernel : kernel mode access using soft MMU
214 */
balrog8bba3ea2008-12-07 23:44:44 +0000215static inline int ldub_p(const void *ptr)
bellard5a9fdfe2003-06-15 20:02:25 +0000216{
217 return *(uint8_t *)ptr;
218}
219
balrog8bba3ea2008-12-07 23:44:44 +0000220static inline int ldsb_p(const void *ptr)
bellard5a9fdfe2003-06-15 20:02:25 +0000221{
222 return *(int8_t *)ptr;
223}
224
bellardc27004e2005-01-03 23:35:10 +0000225static inline void stb_p(void *ptr, int v)
bellard5a9fdfe2003-06-15 20:02:25 +0000226{
227 *(uint8_t *)ptr = v;
228}
229
230/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
231 kernel handles unaligned load/stores may give better results, but
232 it is a system wide setting : bad */
Juan Quintelae2542fe2009-07-27 16:13:06 +0200233#if defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
bellard5a9fdfe2003-06-15 20:02:25 +0000234
235/* conservative code for little endian unaligned accesses */
balrog8bba3ea2008-12-07 23:44:44 +0000236static inline int lduw_le_p(const void *ptr)
bellard5a9fdfe2003-06-15 20:02:25 +0000237{
malce58ffeb2009-01-14 18:39:49 +0000238#ifdef _ARCH_PPC
bellard5a9fdfe2003-06-15 20:02:25 +0000239 int val;
240 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
241 return val;
242#else
malce01fe6d2008-12-11 00:14:30 +0000243 const uint8_t *p = ptr;
bellard5a9fdfe2003-06-15 20:02:25 +0000244 return p[0] | (p[1] << 8);
245#endif
246}
247
balrog8bba3ea2008-12-07 23:44:44 +0000248static inline int ldsw_le_p(const void *ptr)
bellard5a9fdfe2003-06-15 20:02:25 +0000249{
malce58ffeb2009-01-14 18:39:49 +0000250#ifdef _ARCH_PPC
bellard5a9fdfe2003-06-15 20:02:25 +0000251 int val;
252 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
253 return (int16_t)val;
254#else
malce01fe6d2008-12-11 00:14:30 +0000255 const uint8_t *p = ptr;
bellard5a9fdfe2003-06-15 20:02:25 +0000256 return (int16_t)(p[0] | (p[1] << 8));
257#endif
258}
259
balrog8bba3ea2008-12-07 23:44:44 +0000260static inline int ldl_le_p(const void *ptr)
bellard5a9fdfe2003-06-15 20:02:25 +0000261{
malce58ffeb2009-01-14 18:39:49 +0000262#ifdef _ARCH_PPC
bellard5a9fdfe2003-06-15 20:02:25 +0000263 int val;
264 __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
265 return val;
266#else
malce01fe6d2008-12-11 00:14:30 +0000267 const uint8_t *p = ptr;
bellard5a9fdfe2003-06-15 20:02:25 +0000268 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
269#endif
270}
271
balrog8bba3ea2008-12-07 23:44:44 +0000272static inline uint64_t ldq_le_p(const void *ptr)
bellard5a9fdfe2003-06-15 20:02:25 +0000273{
malce01fe6d2008-12-11 00:14:30 +0000274 const uint8_t *p = ptr;
bellard5a9fdfe2003-06-15 20:02:25 +0000275 uint32_t v1, v2;
bellardf0aca822005-11-21 23:22:06 +0000276 v1 = ldl_le_p(p);
277 v2 = ldl_le_p(p + 4);
bellard5a9fdfe2003-06-15 20:02:25 +0000278 return v1 | ((uint64_t)v2 << 32);
279}
280
bellard2df3b952005-11-19 17:47:39 +0000281static inline void stw_le_p(void *ptr, int v)
bellard5a9fdfe2003-06-15 20:02:25 +0000282{
malce58ffeb2009-01-14 18:39:49 +0000283#ifdef _ARCH_PPC
bellard5a9fdfe2003-06-15 20:02:25 +0000284 __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
285#else
286 uint8_t *p = ptr;
287 p[0] = v;
288 p[1] = v >> 8;
289#endif
290}
291
bellard2df3b952005-11-19 17:47:39 +0000292static inline void stl_le_p(void *ptr, int v)
bellard5a9fdfe2003-06-15 20:02:25 +0000293{
malce58ffeb2009-01-14 18:39:49 +0000294#ifdef _ARCH_PPC
bellard5a9fdfe2003-06-15 20:02:25 +0000295 __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
296#else
297 uint8_t *p = ptr;
298 p[0] = v;
299 p[1] = v >> 8;
300 p[2] = v >> 16;
301 p[3] = v >> 24;
302#endif
303}
304
bellard2df3b952005-11-19 17:47:39 +0000305static inline void stq_le_p(void *ptr, uint64_t v)
bellard5a9fdfe2003-06-15 20:02:25 +0000306{
307 uint8_t *p = ptr;
bellardf0aca822005-11-21 23:22:06 +0000308 stl_le_p(p, (uint32_t)v);
309 stl_le_p(p + 4, v >> 32);
bellard5a9fdfe2003-06-15 20:02:25 +0000310}
311
312/* float access */
313
balrog8bba3ea2008-12-07 23:44:44 +0000314static inline float32 ldfl_le_p(const void *ptr)
bellard5a9fdfe2003-06-15 20:02:25 +0000315{
316 union {
bellard53cd6632005-03-13 18:50:23 +0000317 float32 f;
bellard5a9fdfe2003-06-15 20:02:25 +0000318 uint32_t i;
319 } u;
bellard2df3b952005-11-19 17:47:39 +0000320 u.i = ldl_le_p(ptr);
bellard5a9fdfe2003-06-15 20:02:25 +0000321 return u.f;
322}
323
bellard2df3b952005-11-19 17:47:39 +0000324static inline void stfl_le_p(void *ptr, float32 v)
bellard5a9fdfe2003-06-15 20:02:25 +0000325{
326 union {
bellard53cd6632005-03-13 18:50:23 +0000327 float32 f;
bellard5a9fdfe2003-06-15 20:02:25 +0000328 uint32_t i;
329 } u;
330 u.f = v;
bellard2df3b952005-11-19 17:47:39 +0000331 stl_le_p(ptr, u.i);
bellard5a9fdfe2003-06-15 20:02:25 +0000332}
333
balrog8bba3ea2008-12-07 23:44:44 +0000334static inline float64 ldfq_le_p(const void *ptr)
bellard5a9fdfe2003-06-15 20:02:25 +0000335{
bellard0ac4bd52004-01-04 15:44:17 +0000336 CPU_DoubleU u;
bellard2df3b952005-11-19 17:47:39 +0000337 u.l.lower = ldl_le_p(ptr);
338 u.l.upper = ldl_le_p(ptr + 4);
bellard5a9fdfe2003-06-15 20:02:25 +0000339 return u.d;
340}
341
bellard2df3b952005-11-19 17:47:39 +0000342static inline void stfq_le_p(void *ptr, float64 v)
bellard5a9fdfe2003-06-15 20:02:25 +0000343{
bellard0ac4bd52004-01-04 15:44:17 +0000344 CPU_DoubleU u;
bellard5a9fdfe2003-06-15 20:02:25 +0000345 u.d = v;
bellard2df3b952005-11-19 17:47:39 +0000346 stl_le_p(ptr, u.l.lower);
347 stl_le_p(ptr + 4, u.l.upper);
bellard5a9fdfe2003-06-15 20:02:25 +0000348}
349
bellard2df3b952005-11-19 17:47:39 +0000350#else
bellard93ac68b2003-09-30 20:57:29 +0000351
balrog8bba3ea2008-12-07 23:44:44 +0000352static inline int lduw_le_p(const void *ptr)
bellard2df3b952005-11-19 17:47:39 +0000353{
354 return *(uint16_t *)ptr;
355}
356
balrog8bba3ea2008-12-07 23:44:44 +0000357static inline int ldsw_le_p(const void *ptr)
bellard2df3b952005-11-19 17:47:39 +0000358{
359 return *(int16_t *)ptr;
360}
361
balrog8bba3ea2008-12-07 23:44:44 +0000362static inline int ldl_le_p(const void *ptr)
bellard2df3b952005-11-19 17:47:39 +0000363{
364 return *(uint32_t *)ptr;
365}
366
balrog8bba3ea2008-12-07 23:44:44 +0000367static inline uint64_t ldq_le_p(const void *ptr)
bellard2df3b952005-11-19 17:47:39 +0000368{
369 return *(uint64_t *)ptr;
370}
371
372static inline void stw_le_p(void *ptr, int v)
373{
374 *(uint16_t *)ptr = v;
375}
376
377static inline void stl_le_p(void *ptr, int v)
378{
379 *(uint32_t *)ptr = v;
380}
381
382static inline void stq_le_p(void *ptr, uint64_t v)
383{
384 *(uint64_t *)ptr = v;
385}
386
387/* float access */
388
balrog8bba3ea2008-12-07 23:44:44 +0000389static inline float32 ldfl_le_p(const void *ptr)
bellard2df3b952005-11-19 17:47:39 +0000390{
391 return *(float32 *)ptr;
392}
393
balrog8bba3ea2008-12-07 23:44:44 +0000394static inline float64 ldfq_le_p(const void *ptr)
bellard2df3b952005-11-19 17:47:39 +0000395{
396 return *(float64 *)ptr;
397}
398
399static inline void stfl_le_p(void *ptr, float32 v)
400{
401 *(float32 *)ptr = v;
402}
403
404static inline void stfq_le_p(void *ptr, float64 v)
405{
406 *(float64 *)ptr = v;
407}
408#endif
409
Juan Quintelae2542fe2009-07-27 16:13:06 +0200410#if !defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
bellard2df3b952005-11-19 17:47:39 +0000411
balrog8bba3ea2008-12-07 23:44:44 +0000412static inline int lduw_be_p(const void *ptr)
bellard93ac68b2003-09-30 20:57:29 +0000413{
bellard83d73962004-02-22 11:53:50 +0000414#if defined(__i386__)
415 int val;
416 asm volatile ("movzwl %1, %0\n"
417 "xchgb %b0, %h0\n"
418 : "=q" (val)
419 : "m" (*(uint16_t *)ptr));
420 return val;
421#else
malce01fe6d2008-12-11 00:14:30 +0000422 const uint8_t *b = ptr;
bellard83d73962004-02-22 11:53:50 +0000423 return ((b[0] << 8) | b[1]);
424#endif
bellard93ac68b2003-09-30 20:57:29 +0000425}
426
balrog8bba3ea2008-12-07 23:44:44 +0000427static inline int ldsw_be_p(const void *ptr)
bellard93ac68b2003-09-30 20:57:29 +0000428{
bellard83d73962004-02-22 11:53:50 +0000429#if defined(__i386__)
430 int val;
431 asm volatile ("movzwl %1, %0\n"
432 "xchgb %b0, %h0\n"
433 : "=q" (val)
434 : "m" (*(uint16_t *)ptr));
435 return (int16_t)val;
436#else
malce01fe6d2008-12-11 00:14:30 +0000437 const uint8_t *b = ptr;
bellard83d73962004-02-22 11:53:50 +0000438 return (int16_t)((b[0] << 8) | b[1]);
439#endif
bellard93ac68b2003-09-30 20:57:29 +0000440}
441
balrog8bba3ea2008-12-07 23:44:44 +0000442static inline int ldl_be_p(const void *ptr)
bellard93ac68b2003-09-30 20:57:29 +0000443{
bellard4f2ac232004-04-26 19:44:02 +0000444#if defined(__i386__) || defined(__x86_64__)
bellard83d73962004-02-22 11:53:50 +0000445 int val;
446 asm volatile ("movl %1, %0\n"
447 "bswap %0\n"
448 : "=r" (val)
449 : "m" (*(uint32_t *)ptr));
450 return val;
451#else
malce01fe6d2008-12-11 00:14:30 +0000452 const uint8_t *b = ptr;
bellard83d73962004-02-22 11:53:50 +0000453 return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
454#endif
bellard93ac68b2003-09-30 20:57:29 +0000455}
456
balrog8bba3ea2008-12-07 23:44:44 +0000457static inline uint64_t ldq_be_p(const void *ptr)
bellard93ac68b2003-09-30 20:57:29 +0000458{
459 uint32_t a,b;
bellard2df3b952005-11-19 17:47:39 +0000460 a = ldl_be_p(ptr);
blueswir14d7a0882008-05-10 10:14:22 +0000461 b = ldl_be_p((uint8_t *)ptr + 4);
bellard93ac68b2003-09-30 20:57:29 +0000462 return (((uint64_t)a<<32)|b);
463}
464
bellard2df3b952005-11-19 17:47:39 +0000465static inline void stw_be_p(void *ptr, int v)
bellard93ac68b2003-09-30 20:57:29 +0000466{
bellard83d73962004-02-22 11:53:50 +0000467#if defined(__i386__)
468 asm volatile ("xchgb %b0, %h0\n"
469 "movw %w0, %1\n"
470 : "=q" (v)
471 : "m" (*(uint16_t *)ptr), "0" (v));
472#else
bellard93ac68b2003-09-30 20:57:29 +0000473 uint8_t *d = (uint8_t *) ptr;
474 d[0] = v >> 8;
475 d[1] = v;
bellard83d73962004-02-22 11:53:50 +0000476#endif
bellard93ac68b2003-09-30 20:57:29 +0000477}
478
bellard2df3b952005-11-19 17:47:39 +0000479static inline void stl_be_p(void *ptr, int v)
bellard93ac68b2003-09-30 20:57:29 +0000480{
bellard4f2ac232004-04-26 19:44:02 +0000481#if defined(__i386__) || defined(__x86_64__)
bellard83d73962004-02-22 11:53:50 +0000482 asm volatile ("bswap %0\n"
483 "movl %0, %1\n"
484 : "=r" (v)
485 : "m" (*(uint32_t *)ptr), "0" (v));
486#else
bellard93ac68b2003-09-30 20:57:29 +0000487 uint8_t *d = (uint8_t *) ptr;
488 d[0] = v >> 24;
489 d[1] = v >> 16;
490 d[2] = v >> 8;
491 d[3] = v;
bellard83d73962004-02-22 11:53:50 +0000492#endif
bellard93ac68b2003-09-30 20:57:29 +0000493}
494
bellard2df3b952005-11-19 17:47:39 +0000495static inline void stq_be_p(void *ptr, uint64_t v)
bellard93ac68b2003-09-30 20:57:29 +0000496{
bellard2df3b952005-11-19 17:47:39 +0000497 stl_be_p(ptr, v >> 32);
blueswir14d7a0882008-05-10 10:14:22 +0000498 stl_be_p((uint8_t *)ptr + 4, v);
bellard0ac4bd52004-01-04 15:44:17 +0000499}
500
501/* float access */
502
balrog8bba3ea2008-12-07 23:44:44 +0000503static inline float32 ldfl_be_p(const void *ptr)
bellard0ac4bd52004-01-04 15:44:17 +0000504{
505 union {
bellard53cd6632005-03-13 18:50:23 +0000506 float32 f;
bellard0ac4bd52004-01-04 15:44:17 +0000507 uint32_t i;
508 } u;
bellard2df3b952005-11-19 17:47:39 +0000509 u.i = ldl_be_p(ptr);
bellard0ac4bd52004-01-04 15:44:17 +0000510 return u.f;
511}
512
bellard2df3b952005-11-19 17:47:39 +0000513static inline void stfl_be_p(void *ptr, float32 v)
bellard0ac4bd52004-01-04 15:44:17 +0000514{
515 union {
bellard53cd6632005-03-13 18:50:23 +0000516 float32 f;
bellard0ac4bd52004-01-04 15:44:17 +0000517 uint32_t i;
518 } u;
519 u.f = v;
bellard2df3b952005-11-19 17:47:39 +0000520 stl_be_p(ptr, u.i);
bellard0ac4bd52004-01-04 15:44:17 +0000521}
522
balrog8bba3ea2008-12-07 23:44:44 +0000523static inline float64 ldfq_be_p(const void *ptr)
bellard0ac4bd52004-01-04 15:44:17 +0000524{
525 CPU_DoubleU u;
bellard2df3b952005-11-19 17:47:39 +0000526 u.l.upper = ldl_be_p(ptr);
blueswir14d7a0882008-05-10 10:14:22 +0000527 u.l.lower = ldl_be_p((uint8_t *)ptr + 4);
bellard0ac4bd52004-01-04 15:44:17 +0000528 return u.d;
529}
530
bellard2df3b952005-11-19 17:47:39 +0000531static inline void stfq_be_p(void *ptr, float64 v)
bellard0ac4bd52004-01-04 15:44:17 +0000532{
533 CPU_DoubleU u;
534 u.d = v;
bellard2df3b952005-11-19 17:47:39 +0000535 stl_be_p(ptr, u.l.upper);
blueswir14d7a0882008-05-10 10:14:22 +0000536 stl_be_p((uint8_t *)ptr + 4, u.l.lower);
bellard93ac68b2003-09-30 20:57:29 +0000537}
538
bellard5a9fdfe2003-06-15 20:02:25 +0000539#else
540
balrog8bba3ea2008-12-07 23:44:44 +0000541static inline int lduw_be_p(const void *ptr)
bellard5a9fdfe2003-06-15 20:02:25 +0000542{
543 return *(uint16_t *)ptr;
544}
545
balrog8bba3ea2008-12-07 23:44:44 +0000546static inline int ldsw_be_p(const void *ptr)
bellard5a9fdfe2003-06-15 20:02:25 +0000547{
548 return *(int16_t *)ptr;
549}
550
balrog8bba3ea2008-12-07 23:44:44 +0000551static inline int ldl_be_p(const void *ptr)
bellard5a9fdfe2003-06-15 20:02:25 +0000552{
553 return *(uint32_t *)ptr;
554}
555
balrog8bba3ea2008-12-07 23:44:44 +0000556static inline uint64_t ldq_be_p(const void *ptr)
bellard5a9fdfe2003-06-15 20:02:25 +0000557{
558 return *(uint64_t *)ptr;
559}
560
bellard2df3b952005-11-19 17:47:39 +0000561static inline void stw_be_p(void *ptr, int v)
bellard5a9fdfe2003-06-15 20:02:25 +0000562{
563 *(uint16_t *)ptr = v;
564}
565
bellard2df3b952005-11-19 17:47:39 +0000566static inline void stl_be_p(void *ptr, int v)
bellard5a9fdfe2003-06-15 20:02:25 +0000567{
568 *(uint32_t *)ptr = v;
569}
570
bellard2df3b952005-11-19 17:47:39 +0000571static inline void stq_be_p(void *ptr, uint64_t v)
bellard5a9fdfe2003-06-15 20:02:25 +0000572{
573 *(uint64_t *)ptr = v;
574}
575
576/* float access */
577
balrog8bba3ea2008-12-07 23:44:44 +0000578static inline float32 ldfl_be_p(const void *ptr)
bellard5a9fdfe2003-06-15 20:02:25 +0000579{
bellard53cd6632005-03-13 18:50:23 +0000580 return *(float32 *)ptr;
bellard5a9fdfe2003-06-15 20:02:25 +0000581}
582
balrog8bba3ea2008-12-07 23:44:44 +0000583static inline float64 ldfq_be_p(const void *ptr)
bellard5a9fdfe2003-06-15 20:02:25 +0000584{
bellard53cd6632005-03-13 18:50:23 +0000585 return *(float64 *)ptr;
bellard5a9fdfe2003-06-15 20:02:25 +0000586}
587
bellard2df3b952005-11-19 17:47:39 +0000588static inline void stfl_be_p(void *ptr, float32 v)
bellard5a9fdfe2003-06-15 20:02:25 +0000589{
bellard53cd6632005-03-13 18:50:23 +0000590 *(float32 *)ptr = v;
bellard5a9fdfe2003-06-15 20:02:25 +0000591}
592
bellard2df3b952005-11-19 17:47:39 +0000593static inline void stfq_be_p(void *ptr, float64 v)
bellard5a9fdfe2003-06-15 20:02:25 +0000594{
bellard53cd6632005-03-13 18:50:23 +0000595 *(float64 *)ptr = v;
bellard5a9fdfe2003-06-15 20:02:25 +0000596}
bellard2df3b952005-11-19 17:47:39 +0000597
598#endif
599
600/* target CPU memory access functions */
601#if defined(TARGET_WORDS_BIGENDIAN)
602#define lduw_p(p) lduw_be_p(p)
603#define ldsw_p(p) ldsw_be_p(p)
604#define ldl_p(p) ldl_be_p(p)
605#define ldq_p(p) ldq_be_p(p)
606#define ldfl_p(p) ldfl_be_p(p)
607#define ldfq_p(p) ldfq_be_p(p)
608#define stw_p(p, v) stw_be_p(p, v)
609#define stl_p(p, v) stl_be_p(p, v)
610#define stq_p(p, v) stq_be_p(p, v)
611#define stfl_p(p, v) stfl_be_p(p, v)
612#define stfq_p(p, v) stfq_be_p(p, v)
613#else
614#define lduw_p(p) lduw_le_p(p)
615#define ldsw_p(p) ldsw_le_p(p)
616#define ldl_p(p) ldl_le_p(p)
617#define ldq_p(p) ldq_le_p(p)
618#define ldfl_p(p) ldfl_le_p(p)
619#define ldfq_p(p) ldfq_le_p(p)
620#define stw_p(p, v) stw_le_p(p, v)
621#define stl_p(p, v) stl_le_p(p, v)
622#define stq_p(p, v) stq_le_p(p, v)
623#define stfl_p(p, v) stfl_le_p(p, v)
624#define stfq_p(p, v) stfq_le_p(p, v)
bellard5a9fdfe2003-06-15 20:02:25 +0000625#endif
626
bellard61382a52003-10-27 21:22:23 +0000627/* MMU memory access macros */
628
pbrook53a59602006-03-25 19:31:22 +0000629#if defined(CONFIG_USER_ONLY)
aurel320e62fd72008-12-08 18:12:11 +0000630#include <assert.h>
631#include "qemu-types.h"
632
pbrook53a59602006-03-25 19:31:22 +0000633/* On some host systems the guest address space is reserved on the host.
634 * This allows the guest address space to be offset to a convenient location.
635 */
Paul Brook379f6692009-07-17 12:48:08 +0100636#if defined(CONFIG_USE_GUEST_BASE)
637extern unsigned long guest_base;
638extern int have_guest_base;
Paul Brook68a1c812010-05-29 02:27:35 +0100639extern unsigned long reserved_va;
Paul Brook379f6692009-07-17 12:48:08 +0100640#define GUEST_BASE guest_base
Aurelien Jarno18e9ea82010-07-30 21:09:10 +0200641#define RESERVED_VA reserved_va
Paul Brook379f6692009-07-17 12:48:08 +0100642#else
643#define GUEST_BASE 0ul
Aurelien Jarno18e9ea82010-07-30 21:09:10 +0200644#define RESERVED_VA 0ul
Paul Brook379f6692009-07-17 12:48:08 +0100645#endif
pbrook53a59602006-03-25 19:31:22 +0000646
647/* All direct uses of g2h and h2g need to go away for usermode softmmu. */
648#define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE))
Richard Hendersonb9f83122010-03-10 14:36:58 -0800649
650#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
651#define h2g_valid(x) 1
652#else
653#define h2g_valid(x) ({ \
654 unsigned long __guest = (unsigned long)(x) - GUEST_BASE; \
655 __guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS); \
656})
657#endif
658
aurel320e62fd72008-12-08 18:12:11 +0000659#define h2g(x) ({ \
660 unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \
661 /* Check if given address fits target address space */ \
Richard Hendersonb9f83122010-03-10 14:36:58 -0800662 assert(h2g_valid(x)); \
aurel320e62fd72008-12-08 18:12:11 +0000663 (abi_ulong)__ret; \
664})
pbrook53a59602006-03-25 19:31:22 +0000665
666#define saddr(x) g2h(x)
667#define laddr(x) g2h(x)
668
669#else /* !CONFIG_USER_ONLY */
bellardc27004e2005-01-03 23:35:10 +0000670/* NOTE: we use double casts if pointers and target_ulong have
671 different sizes */
pbrook53a59602006-03-25 19:31:22 +0000672#define saddr(x) (uint8_t *)(long)(x)
673#define laddr(x) (uint8_t *)(long)(x)
674#endif
675
676#define ldub_raw(p) ldub_p(laddr((p)))
677#define ldsb_raw(p) ldsb_p(laddr((p)))
678#define lduw_raw(p) lduw_p(laddr((p)))
679#define ldsw_raw(p) ldsw_p(laddr((p)))
680#define ldl_raw(p) ldl_p(laddr((p)))
681#define ldq_raw(p) ldq_p(laddr((p)))
682#define ldfl_raw(p) ldfl_p(laddr((p)))
683#define ldfq_raw(p) ldfq_p(laddr((p)))
684#define stb_raw(p, v) stb_p(saddr((p)), v)
685#define stw_raw(p, v) stw_p(saddr((p)), v)
686#define stl_raw(p, v) stl_p(saddr((p)), v)
687#define stq_raw(p, v) stq_p(saddr((p)), v)
688#define stfl_raw(p, v) stfl_p(saddr((p)), v)
689#define stfq_raw(p, v) stfq_p(saddr((p)), v)
bellardc27004e2005-01-03 23:35:10 +0000690
691
ths5fafdf22007-09-16 21:08:06 +0000692#if defined(CONFIG_USER_ONLY)
bellard61382a52003-10-27 21:22:23 +0000693
694/* if user mode, no other memory access functions */
695#define ldub(p) ldub_raw(p)
696#define ldsb(p) ldsb_raw(p)
697#define lduw(p) lduw_raw(p)
698#define ldsw(p) ldsw_raw(p)
699#define ldl(p) ldl_raw(p)
700#define ldq(p) ldq_raw(p)
701#define ldfl(p) ldfl_raw(p)
702#define ldfq(p) ldfq_raw(p)
703#define stb(p, v) stb_raw(p, v)
704#define stw(p, v) stw_raw(p, v)
705#define stl(p, v) stl_raw(p, v)
706#define stq(p, v) stq_raw(p, v)
707#define stfl(p, v) stfl_raw(p, v)
708#define stfq(p, v) stfq_raw(p, v)
709
710#define ldub_code(p) ldub_raw(p)
711#define ldsb_code(p) ldsb_raw(p)
712#define lduw_code(p) lduw_raw(p)
713#define ldsw_code(p) ldsw_raw(p)
714#define ldl_code(p) ldl_raw(p)
j_mayerbc98a7e2007-04-04 07:55:12 +0000715#define ldq_code(p) ldq_raw(p)
bellard61382a52003-10-27 21:22:23 +0000716
717#define ldub_kernel(p) ldub_raw(p)
718#define ldsb_kernel(p) ldsb_raw(p)
719#define lduw_kernel(p) lduw_raw(p)
720#define ldsw_kernel(p) ldsw_raw(p)
721#define ldl_kernel(p) ldl_raw(p)
j_mayerbc98a7e2007-04-04 07:55:12 +0000722#define ldq_kernel(p) ldq_raw(p)
bellard0ac4bd52004-01-04 15:44:17 +0000723#define ldfl_kernel(p) ldfl_raw(p)
724#define ldfq_kernel(p) ldfq_raw(p)
bellard61382a52003-10-27 21:22:23 +0000725#define stb_kernel(p, v) stb_raw(p, v)
726#define stw_kernel(p, v) stw_raw(p, v)
727#define stl_kernel(p, v) stl_raw(p, v)
728#define stq_kernel(p, v) stq_raw(p, v)
bellard0ac4bd52004-01-04 15:44:17 +0000729#define stfl_kernel(p, v) stfl_raw(p, v)
730#define stfq_kernel(p, vt) stfq_raw(p, v)
bellard61382a52003-10-27 21:22:23 +0000731
732#endif /* defined(CONFIG_USER_ONLY) */
733
bellard5a9fdfe2003-06-15 20:02:25 +0000734/* page related stuff */
735
aurel3203875442008-04-22 20:45:18 +0000736#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
bellard5a9fdfe2003-06-15 20:02:25 +0000737#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
738#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK)
739
pbrook53a59602006-03-25 19:31:22 +0000740/* ??? These should be the larger of unsigned long and target_ulong. */
bellard83fb7ad2004-07-05 21:25:26 +0000741extern unsigned long qemu_real_host_page_size;
742extern unsigned long qemu_host_page_bits;
743extern unsigned long qemu_host_page_size;
744extern unsigned long qemu_host_page_mask;
bellard5a9fdfe2003-06-15 20:02:25 +0000745
bellard83fb7ad2004-07-05 21:25:26 +0000746#define HOST_PAGE_ALIGN(addr) (((addr) + qemu_host_page_size - 1) & qemu_host_page_mask)
bellard5a9fdfe2003-06-15 20:02:25 +0000747
748/* same as PROT_xxx */
749#define PAGE_READ 0x0001
750#define PAGE_WRITE 0x0002
751#define PAGE_EXEC 0x0004
752#define PAGE_BITS (PAGE_READ | PAGE_WRITE | PAGE_EXEC)
753#define PAGE_VALID 0x0008
754/* original state of the write flag (used when tracking self-modifying
755 code */
ths5fafdf22007-09-16 21:08:06 +0000756#define PAGE_WRITE_ORG 0x0010
Paul Brook2e9a5712010-05-05 16:32:59 +0100757#if defined(CONFIG_BSD) && defined(CONFIG_USER_ONLY)
758/* FIXME: Code that sets/uses this is broken and needs to go away. */
balrog50a95692007-12-12 01:16:23 +0000759#define PAGE_RESERVED 0x0020
Paul Brook2e9a5712010-05-05 16:32:59 +0100760#endif
bellard5a9fdfe2003-06-15 20:02:25 +0000761
Paul Brookb480d9b2010-03-12 23:23:29 +0000762#if defined(CONFIG_USER_ONLY)
bellard5a9fdfe2003-06-15 20:02:25 +0000763void page_dump(FILE *f);
Richard Henderson5cd2c5b2010-03-10 15:53:37 -0800764
Paul Brookb480d9b2010-03-12 23:23:29 +0000765typedef int (*walk_memory_regions_fn)(void *, abi_ulong,
766 abi_ulong, unsigned long);
Richard Henderson5cd2c5b2010-03-10 15:53:37 -0800767int walk_memory_regions(void *, walk_memory_regions_fn);
768
pbrook53a59602006-03-25 19:31:22 +0000769int page_get_flags(target_ulong address);
770void page_set_flags(target_ulong start, target_ulong end, int flags);
ths3d97b402007-11-02 19:02:07 +0000771int page_check_range(target_ulong start, target_ulong len, int flags);
Paul Brookb480d9b2010-03-12 23:23:29 +0000772#endif
bellard5a9fdfe2003-06-15 20:02:25 +0000773
thsc5be9f02007-02-28 20:20:53 +0000774CPUState *cpu_copy(CPUState *env);
Glauber Costa950f1472009-06-09 12:15:18 -0400775CPUState *qemu_get_cpu(int cpu);
thsc5be9f02007-02-28 20:20:53 +0000776
Jan Kiszkaf5c848e2011-01-21 21:48:08 +0100777#define CPU_DUMP_CODE 0x00010000
778
Stefan Weil9a78eea2010-10-22 23:03:33 +0200779void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
bellard7fe48482004-10-09 18:08:01 +0000780 int flags);
Stefan Weil9a78eea2010-10-22 23:03:33 +0200781void cpu_dump_statistics(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
782 int flags);
bellard7fe48482004-10-09 18:08:01 +0000783
malca5e50b22009-02-01 22:19:27 +0000784void QEMU_NORETURN cpu_abort(CPUState *env, const char *fmt, ...)
Stefan Weil2c80e422010-10-13 20:54:27 +0200785 GCC_FMT_ATTR(2, 3);
bellardf0aca822005-11-21 23:22:06 +0000786extern CPUState *first_cpu;
bellarde2f22892003-06-25 16:09:48 +0000787extern CPUState *cpu_single_env;
Paolo Bonzinidb1a4972010-03-10 11:38:55 +0100788
Richard Henderson9c762192011-05-04 13:34:24 -0700789/* Flags for use in ENV->INTERRUPT_PENDING.
790
791 The numbers assigned here are non-sequential in order to preserve
792 binary compatibility with the vmstate dump. Bit 0 (0x0001) was
793 previously used for CPU_INTERRUPT_EXIT, and is cleared when loading
794 the vmstate dump. */
795
796/* External hardware interrupt pending. This is typically used for
797 interrupts from devices. */
798#define CPU_INTERRUPT_HARD 0x0002
799
800/* Exit the current TB. This is typically used when some system-level device
801 makes some change to the memory mapping. E.g. the a20 line change. */
802#define CPU_INTERRUPT_EXITTB 0x0004
803
804/* Halt the CPU. */
805#define CPU_INTERRUPT_HALT 0x0020
806
807/* Debug event pending. */
808#define CPU_INTERRUPT_DEBUG 0x0080
809
810/* Several target-specific external hardware interrupts. Each target/cpu.h
811 should define proper names based on these defines. */
812#define CPU_INTERRUPT_TGT_EXT_0 0x0008
813#define CPU_INTERRUPT_TGT_EXT_1 0x0010
814#define CPU_INTERRUPT_TGT_EXT_2 0x0040
815#define CPU_INTERRUPT_TGT_EXT_3 0x0200
816#define CPU_INTERRUPT_TGT_EXT_4 0x1000
817
818/* Several target-specific internal interrupts. These differ from the
819 preceeding target-specific interrupts in that they are intended to
820 originate from within the cpu itself, typically in response to some
821 instruction being executed. These, therefore, are not masked while
822 single-stepping within the debugger. */
823#define CPU_INTERRUPT_TGT_INT_0 0x0100
824#define CPU_INTERRUPT_TGT_INT_1 0x0400
825#define CPU_INTERRUPT_TGT_INT_2 0x0800
826
827/* First unused bit: 0x2000. */
828
829/* Temporary remapping from the generic names back to the previous
830 cpu-specific names. These will be moved to target-foo/cpu.h next. */
831#define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_EXT_0
832#define CPU_INTERRUPT_FIQ CPU_INTERRUPT_TGT_EXT_1
833#define CPU_INTERRUPT_SMI CPU_INTERRUPT_TGT_EXT_2
834#define CPU_INTERRUPT_VIRQ CPU_INTERRUPT_TGT_INT_0
835#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3
836#define CPU_INTERRUPT_INIT CPU_INTERRUPT_TGT_INT_1
837#define CPU_INTERRUPT_SIPI CPU_INTERRUPT_TGT_INT_2
838#define CPU_INTERRUPT_MCE CPU_INTERRUPT_TGT_EXT_4
839
bellard98699962005-11-26 10:29:22 +0000840
Jan Kiszkaec6959d2011-04-13 01:32:56 +0200841#ifndef CONFIG_USER_ONLY
842typedef void (*CPUInterruptHandler)(CPUState *, int);
843
844extern CPUInterruptHandler cpu_interrupt_handler;
845
846static inline void cpu_interrupt(CPUState *s, int mask)
847{
848 cpu_interrupt_handler(s, mask);
849}
850#else /* USER_ONLY */
851void cpu_interrupt(CPUState *env, int mask);
852#endif /* USER_ONLY */
853
bellardb54ad042004-05-20 13:42:52 +0000854void cpu_reset_interrupt(CPUState *env, int mask);
bellard68a79312003-06-30 13:12:32 +0000855
aurel323098dba2009-03-07 21:28:24 +0000856void cpu_exit(CPUState *s);
857
aliguori6a4955a2009-04-24 18:03:20 +0000858int qemu_cpu_has_work(CPUState *env);
859
aliguoria1d1bb32008-11-18 20:07:32 +0000860/* Breakpoint/watchpoint flags */
861#define BP_MEM_READ 0x01
862#define BP_MEM_WRITE 0x02
863#define BP_MEM_ACCESS (BP_MEM_READ | BP_MEM_WRITE)
aliguori06d55cc2008-11-18 20:24:06 +0000864#define BP_STOP_BEFORE_ACCESS 0x04
aliguori6e140f22008-11-18 20:37:55 +0000865#define BP_WATCHPOINT_HIT 0x08
aliguoria1d1bb32008-11-18 20:07:32 +0000866#define BP_GDB 0x10
aliguori2dc9f412008-11-18 20:56:59 +0000867#define BP_CPU 0x20
aliguoria1d1bb32008-11-18 20:07:32 +0000868
869int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
870 CPUBreakpoint **breakpoint);
871int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags);
872void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint);
873void cpu_breakpoint_remove_all(CPUState *env, int mask);
874int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
875 int flags, CPUWatchpoint **watchpoint);
876int cpu_watchpoint_remove(CPUState *env, target_ulong addr,
877 target_ulong len, int flags);
878void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint);
879void cpu_watchpoint_remove_all(CPUState *env, int mask);
edgar_igl60897d32008-05-09 08:25:14 +0000880
881#define SSTEP_ENABLE 0x1 /* Enable simulated HW single stepping */
882#define SSTEP_NOIRQ 0x2 /* Do not use IRQ while single stepping */
883#define SSTEP_NOTIMER 0x4 /* Do not Timers while single stepping */
884
bellardc33a3462003-07-29 20:50:33 +0000885void cpu_single_step(CPUState *env, int enabled);
bellardd95dc322004-06-20 12:35:26 +0000886void cpu_reset(CPUState *s);
Marcelo Tosatti3ae95012010-05-04 09:45:24 -0300887int cpu_is_stopped(CPUState *env);
Marcelo Tosattie82bcec2010-05-04 09:45:22 -0300888void run_on_cpu(CPUState *env, void (*func)(void *data), void *data);
bellard4c3a88a2003-07-26 12:06:08 +0000889
ths5fafdf22007-09-16 21:08:06 +0000890#define CPU_LOG_TB_OUT_ASM (1 << 0)
bellard9fddaa02004-05-21 12:59:32 +0000891#define CPU_LOG_TB_IN_ASM (1 << 1)
bellardf193c792004-03-21 17:06:25 +0000892#define CPU_LOG_TB_OP (1 << 2)
893#define CPU_LOG_TB_OP_OPT (1 << 3)
894#define CPU_LOG_INT (1 << 4)
895#define CPU_LOG_EXEC (1 << 5)
896#define CPU_LOG_PCALL (1 << 6)
bellardfd872592004-05-12 19:11:15 +0000897#define CPU_LOG_IOPORT (1 << 7)
bellard9fddaa02004-05-21 12:59:32 +0000898#define CPU_LOG_TB_CPU (1 << 8)
aliguorieca1bdf2009-01-26 19:54:31 +0000899#define CPU_LOG_RESET (1 << 9)
bellardf193c792004-03-21 17:06:25 +0000900
901/* define log items */
902typedef struct CPULogItem {
903 int mask;
904 const char *name;
905 const char *help;
906} CPULogItem;
907
blueswir1c7cd6a32008-10-02 18:27:46 +0000908extern const CPULogItem cpu_log_items[];
bellardf193c792004-03-21 17:06:25 +0000909
bellard34865132003-10-05 14:28:56 +0000910void cpu_set_log(int log_flags);
911void cpu_set_log_filename(const char *filename);
bellardf193c792004-03-21 17:06:25 +0000912int cpu_str_to_log_mask(const char *str);
bellard34865132003-10-05 14:28:56 +0000913
Paul Brookb3755a92010-03-12 16:54:58 +0000914#if !defined(CONFIG_USER_ONLY)
915
Paul Brook4fcc5622010-03-01 03:46:18 +0000916/* Return the physical page corresponding to a virtual one. Use it
917 only for debugging because no protection checks are done. Return -1
918 if no page found. */
919target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
920
bellard33417e72003-08-10 21:47:01 +0000921/* memory API */
922
bellardedf75d52004-01-04 17:43:30 +0000923extern int phys_ram_fd;
Anthony Liguoric227f092009-10-01 16:12:16 -0500924extern ram_addr_t ram_size;
Alex Williamsonf471a172010-06-11 11:11:42 -0600925
Huang Yingcd19cfa2011-03-02 08:56:19 +0100926/* RAM is pre-allocated and passed into qemu_ram_alloc_from_ptr */
927#define RAM_PREALLOC_MASK (1 << 0)
928
Alex Williamsonf471a172010-06-11 11:11:42 -0600929typedef struct RAMBlock {
930 uint8_t *host;
931 ram_addr_t offset;
932 ram_addr_t length;
Huang Yingcd19cfa2011-03-02 08:56:19 +0100933 uint32_t flags;
Alex Williamsoncc9e98c2010-06-25 11:09:43 -0600934 char idstr[256];
Alex Williamsonf471a172010-06-11 11:11:42 -0600935 QLIST_ENTRY(RAMBlock) next;
Alex Williamson04b16652010-07-02 11:13:17 -0600936#if defined(__linux__) && !defined(TARGET_S390X)
937 int fd;
938#endif
Alex Williamsonf471a172010-06-11 11:11:42 -0600939} RAMBlock;
940
941typedef struct RAMList {
942 uint8_t *phys_dirty;
Alex Williamsonf471a172010-06-11 11:11:42 -0600943 QLIST_HEAD(ram, RAMBlock) blocks;
944} RAMList;
945extern RAMList ram_list;
bellardedf75d52004-01-04 17:43:30 +0000946
Marcelo Tosattic9027602010-03-01 20:25:08 -0300947extern const char *mem_path;
948extern int mem_prealloc;
949
bellardedf75d52004-01-04 17:43:30 +0000950/* physical memory access */
pbrook0f459d12008-06-09 00:20:13 +0000951
952/* MMIO pages are identified by a combination of an IO device index and
953 3 flags. The ROMD code stores the page ram offset in iotlb entry,
954 so only a limited number of ids are avaiable. */
955
bellard98699962005-11-26 10:29:22 +0000956#define IO_MEM_NB_ENTRIES (1 << (TARGET_PAGE_BITS - IO_MEM_SHIFT))
bellardedf75d52004-01-04 17:43:30 +0000957
pbrook0f459d12008-06-09 00:20:13 +0000958/* Flags stored in the low bits of the TLB virtual address. These are
959 defined so that fast path ram access is all zeros. */
960/* Zero if TLB entry is valid. */
961#define TLB_INVALID_MASK (1 << 3)
962/* Set if TLB entry references a clean RAM page. The iotlb entry will
963 contain the page physical address. */
964#define TLB_NOTDIRTY (1 << 4)
965/* Set if TLB entry is an IO callback. */
966#define TLB_MMIO (1 << 5)
967
aliguori74576192008-10-06 14:02:03 +0000968#define VGA_DIRTY_FLAG 0x01
969#define CODE_DIRTY_FLAG 0x02
aliguori74576192008-10-06 14:02:03 +0000970#define MIGRATION_DIRTY_FLAG 0x08
bellard0a962c02005-02-10 22:00:27 +0000971
bellard1ccde1c2004-02-06 19:46:14 +0000972/* read dirty bit (return 0 or 1) */
Anthony Liguoric227f092009-10-01 16:12:16 -0500973static inline int cpu_physical_memory_is_dirty(ram_addr_t addr)
bellard1ccde1c2004-02-06 19:46:14 +0000974{
Alex Williamsonf471a172010-06-11 11:11:42 -0600975 return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] == 0xff;
bellard0a962c02005-02-10 22:00:27 +0000976}
977
Yoshiaki Tamuraca39b462010-03-23 16:39:52 +0900978static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr)
979{
Alex Williamsonf471a172010-06-11 11:11:42 -0600980 return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS];
Yoshiaki Tamuraca39b462010-03-23 16:39:52 +0900981}
982
Anthony Liguoric227f092009-10-01 16:12:16 -0500983static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
bellard0a962c02005-02-10 22:00:27 +0000984 int dirty_flags)
985{
Alex Williamsonf471a172010-06-11 11:11:42 -0600986 return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
bellard1ccde1c2004-02-06 19:46:14 +0000987}
988
Anthony Liguoric227f092009-10-01 16:12:16 -0500989static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
bellard1ccde1c2004-02-06 19:46:14 +0000990{
Alex Williamsonf471a172010-06-11 11:11:42 -0600991 ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
bellard1ccde1c2004-02-06 19:46:14 +0000992}
993
Yoshiaki Tamuraca39b462010-03-23 16:39:52 +0900994static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr,
995 int dirty_flags)
996{
Alex Williamsonf471a172010-06-11 11:11:42 -0600997 return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags;
Yoshiaki Tamuraca39b462010-03-23 16:39:52 +0900998}
999
1000static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start,
1001 int length,
1002 int dirty_flags)
1003{
1004 int i, mask, len;
1005 uint8_t *p;
1006
1007 len = length >> TARGET_PAGE_BITS;
1008 mask = ~dirty_flags;
Alex Williamsonf471a172010-06-11 11:11:42 -06001009 p = ram_list.phys_dirty + (start >> TARGET_PAGE_BITS);
Yoshiaki Tamuraca39b462010-03-23 16:39:52 +09001010 for (i = 0; i < len; i++) {
1011 p[i] &= mask;
1012 }
1013}
1014
Anthony Liguoric227f092009-10-01 16:12:16 -05001015void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
bellard0a962c02005-02-10 22:00:27 +00001016 int dirty_flags);
bellard04c504c2005-08-21 09:24:50 +00001017void cpu_tlb_update_dirty(CPUState *env);
bellard1ccde1c2004-02-06 19:46:14 +00001018
aliguori74576192008-10-06 14:02:03 +00001019int cpu_physical_memory_set_dirty_tracking(int enable);
1020
1021int cpu_physical_memory_get_dirty_tracking(void);
1022
Anthony Liguoric227f092009-10-01 16:12:16 -05001023int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
1024 target_phys_addr_t end_addr);
aliguori2bec46d2008-11-24 20:21:41 +00001025
Anthony PERARDe5896b12011-02-07 12:19:23 +01001026int cpu_physical_log_start(target_phys_addr_t start_addr,
1027 ram_addr_t size);
1028
1029int cpu_physical_log_stop(target_phys_addr_t start_addr,
1030 ram_addr_t size);
1031
Stefan Weil055403b2010-10-22 23:03:32 +02001032void dump_exec_info(FILE *f, fprintf_function cpu_fprintf);
Paul Brookb3755a92010-03-12 16:54:58 +00001033#endif /* !CONFIG_USER_ONLY */
1034
1035int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
1036 uint8_t *buf, int len, int is_write);
1037
bellard5a9fdfe2003-06-15 20:02:25 +00001038#endif /* CPU_ALL_H */