VirtualBox

source: vbox/trunk/src/recompiler/cpu-all.h@ 29722

Last change on this file since 29722 was 29250, checked in by vboxsync, 15 years ago

iprt/asm*.h: split out asm-math.h, don't include asm-*.h from asm.h, don't include asm.h from sup.h. Fixed a couple file headers.

  • Property svn:eol-style set to native
File size: 36.3 KB
Line 
1/*
2 * defines common to all virtual CPUs
3 *
4 * 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
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21/*
22 * Sun LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
23 * other than GPL or LGPL is available it will apply instead, Sun elects to use only
24 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
25 * a choice of LGPL license versions is made available with the language indicating
26 * that LGPLv2 or any later version may be used, or where a choice of which version
27 * of the LGPL is applied is otherwise unspecified.
28 */
29#ifndef CPU_ALL_H
30#define CPU_ALL_H
31
32#ifdef VBOX
33# ifndef LOG_GROUP
34# define LOG_GROUP LOG_GROUP_REM
35# endif
36# include <VBox/log.h>
37# include <VBox/pgm.h> /* PGM_DYNAMIC_RAM_ALLOC */
38#endif
39
40#if defined(__arm__) || defined(__sparc__)
41#define WORDS_ALIGNED
42#endif
43
44/* some important defines:
45 *
46 * WORDS_ALIGNED : if defined, the host cpu can only make word aligned
47 * memory accesses.
48 *
49 * WORDS_BIGENDIAN : if defined, the host cpu is big endian and
50 * otherwise little endian.
51 *
52 * (TARGET_WORDS_ALIGNED : same for target cpu (not supported yet))
53 *
54 * TARGET_WORDS_BIGENDIAN : same for target cpu
55 */
56
57#include "bswap.h"
58
59#if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
60#define BSWAP_NEEDED
61#endif
62
63#ifdef BSWAP_NEEDED
64
65static inline uint16_t tswap16(uint16_t s)
66{
67 return bswap16(s);
68}
69
70static inline uint32_t tswap32(uint32_t s)
71{
72 return bswap32(s);
73}
74
75static inline uint64_t tswap64(uint64_t s)
76{
77 return bswap64(s);
78}
79
80static inline void tswap16s(uint16_t *s)
81{
82 *s = bswap16(*s);
83}
84
85static inline void tswap32s(uint32_t *s)
86{
87 *s = bswap32(*s);
88}
89
90static inline void tswap64s(uint64_t *s)
91{
92 *s = bswap64(*s);
93}
94
95#else
96
97#ifndef VBOX
98static inline uint16_t tswap16(uint16_t s)
99#else
100DECLINLINE(uint16_t) tswap16(uint16_t s)
101#endif
102{
103 return s;
104}
105
106#ifndef VBOX
107static inline uint32_t tswap32(uint32_t s)
108#else
109DECLINLINE(uint32_t) tswap32(uint32_t s)
110#endif
111{
112 return s;
113}
114
115#ifndef VBOX
116static inline uint64_t tswap64(uint64_t s)
117#else
118DECLINLINE(uint64_t) tswap64(uint64_t s)
119#endif
120{
121 return s;
122}
123
124#ifndef VBOX
125static inline void tswap16s(uint16_t *s)
126#else
127DECLINLINE(void) tswap16s(uint16_t *s)
128#endif
129{
130}
131
132#ifndef VBOX
133static inline void tswap32s(uint32_t *s)
134#else
135DECLINLINE(void) tswap32s(uint32_t *s)
136#endif
137{
138}
139
140#ifndef VBOX
141static inline void tswap64s(uint64_t *s)
142#else
143DECLINLINE(void) tswap64s(uint64_t *s)
144#endif
145{
146}
147
148#endif
149
150#if TARGET_LONG_SIZE == 4
151#define tswapl(s) tswap32(s)
152#define tswapls(s) tswap32s((uint32_t *)(s))
153#define bswaptls(s) bswap32s(s)
154#else
155#define tswapl(s) tswap64(s)
156#define tswapls(s) tswap64s((uint64_t *)(s))
157#define bswaptls(s) bswap64s(s)
158#endif
159
160typedef union {
161 float32 f;
162 uint32_t l;
163} CPU_FloatU;
164
165/* NOTE: arm FPA is horrible as double 32 bit words are stored in big
166 endian ! */
167typedef union {
168 float64 d;
169#if defined(WORDS_BIGENDIAN) \
170 || (defined(__arm__) && !defined(__VFP_FP__) && !defined(CONFIG_SOFTFLOAT))
171 struct {
172 uint32_t upper;
173 uint32_t lower;
174 } l;
175#else
176 struct {
177 uint32_t lower;
178 uint32_t upper;
179 } l;
180#endif
181 uint64_t ll;
182} CPU_DoubleU;
183
184#ifdef TARGET_SPARC
185typedef union {
186 float128 q;
187#if defined(WORDS_BIGENDIAN) \
188 || (defined(__arm__) && !defined(__VFP_FP__) && !defined(CONFIG_SOFTFLOAT))
189 struct {
190 uint32_t upmost;
191 uint32_t upper;
192 uint32_t lower;
193 uint32_t lowest;
194 } l;
195 struct {
196 uint64_t upper;
197 uint64_t lower;
198 } ll;
199#else
200 struct {
201 uint32_t lowest;
202 uint32_t lower;
203 uint32_t upper;
204 uint32_t upmost;
205 } l;
206 struct {
207 uint64_t lower;
208 uint64_t upper;
209 } ll;
210#endif
211} CPU_QuadU;
212#endif
213
214/* CPU memory access without any memory or io remapping */
215
216/*
217 * the generic syntax for the memory accesses is:
218 *
219 * load: ld{type}{sign}{size}{endian}_{access_type}(ptr)
220 *
221 * store: st{type}{size}{endian}_{access_type}(ptr, val)
222 *
223 * type is:
224 * (empty): integer access
225 * f : float access
226 *
227 * sign is:
228 * (empty): for floats or 32 bit size
229 * u : unsigned
230 * s : signed
231 *
232 * size is:
233 * b: 8 bits
234 * w: 16 bits
235 * l: 32 bits
236 * q: 64 bits
237 *
238 * endian is:
239 * (empty): target cpu endianness or 8 bit access
240 * r : reversed target cpu endianness (not implemented yet)
241 * be : big endian (not implemented yet)
242 * le : little endian (not implemented yet)
243 *
244 * access_type is:
245 * raw : host memory access
246 * user : user mode access using soft MMU
247 * kernel : kernel mode access using soft MMU
248 */
249
250#ifdef VBOX
251void remAbort(int rc, const char *pszTip) __attribute__((__noreturn__));
252
253void remR3PhysRead(RTGCPHYS SrcGCPhys, void *pvDst, unsigned cb);
254RTCCUINTREG remR3PhysReadU8(RTGCPHYS SrcGCPhys);
255RTCCINTREG remR3PhysReadS8(RTGCPHYS SrcGCPhys);
256RTCCUINTREG remR3PhysReadU16(RTGCPHYS SrcGCPhys);
257RTCCINTREG remR3PhysReadS16(RTGCPHYS SrcGCPhys);
258RTCCUINTREG remR3PhysReadU32(RTGCPHYS SrcGCPhys);
259RTCCINTREG remR3PhysReadS32(RTGCPHYS SrcGCPhys);
260uint64_t remR3PhysReadU64(RTGCPHYS SrcGCPhys);
261int64_t remR3PhysReadS64(RTGCPHYS SrcGCPhys);
262void remR3PhysWrite(RTGCPHYS DstGCPhys, const void *pvSrc, unsigned cb);
263void remR3PhysWriteU8(RTGCPHYS DstGCPhys, uint8_t val);
264void remR3PhysWriteU16(RTGCPHYS DstGCPhys, uint16_t val);
265void remR3PhysWriteU32(RTGCPHYS DstGCPhys, uint32_t val);
266void remR3PhysWriteU64(RTGCPHYS DstGCPhys, uint64_t val);
267
268#ifndef REM_PHYS_ADDR_IN_TLB
269void *remR3TlbGCPhys2Ptr(CPUState *env1, target_ulong physAddr, int fWritable);
270#endif
271
272#endif /* VBOX */
273
274#if defined(VBOX) && defined(REM_PHYS_ADDR_IN_TLB)
275
276DECLINLINE(uint8_t) ldub_p(void *ptr)
277{
278 VBOX_CHECK_ADDR(ptr);
279 return remR3PhysReadU8((uintptr_t)ptr);
280}
281
282DECLINLINE(int8_t) ldsb_p(void *ptr)
283{
284 VBOX_CHECK_ADDR(ptr);
285 return remR3PhysReadS8((uintptr_t)ptr);
286}
287
288DECLINLINE(void) stb_p(void *ptr, int v)
289{
290 VBOX_CHECK_ADDR(ptr);
291 remR3PhysWriteU8((uintptr_t)ptr, v);
292}
293
294DECLINLINE(uint32_t) lduw_le_p(void *ptr)
295{
296 VBOX_CHECK_ADDR(ptr);
297 return remR3PhysReadU16((uintptr_t)ptr);
298}
299
300DECLINLINE(int32_t) ldsw_le_p(void *ptr)
301{
302 VBOX_CHECK_ADDR(ptr);
303 return remR3PhysReadS16((uintptr_t)ptr);
304}
305
306DECLINLINE(void) stw_le_p(void *ptr, int v)
307{
308 VBOX_CHECK_ADDR(ptr);
309 remR3PhysWriteU16((uintptr_t)ptr, v);
310}
311
312DECLINLINE(uint32_t) ldl_le_p(void *ptr)
313{
314 VBOX_CHECK_ADDR(ptr);
315 return remR3PhysReadU32((uintptr_t)ptr);
316}
317
318DECLINLINE(void) stl_le_p(void *ptr, int v)
319{
320 VBOX_CHECK_ADDR(ptr);
321 remR3PhysWriteU32((uintptr_t)ptr, v);
322}
323
324DECLINLINE(void) stq_le_p(void *ptr, uint64_t v)
325{
326 VBOX_CHECK_ADDR(ptr);
327 remR3PhysWriteU64((uintptr_t)ptr, v);
328}
329
330DECLINLINE(uint64_t) ldq_le_p(void *ptr)
331{
332 VBOX_CHECK_ADDR(ptr);
333 return remR3PhysReadU64((uintptr_t)ptr);
334}
335
336#undef VBOX_CHECK_ADDR
337
338/* float access */
339
340DECLINLINE(float32) ldfl_le_p(void *ptr)
341{
342 union {
343 float32 f;
344 uint32_t i;
345 } u;
346 u.i = ldl_le_p(ptr);
347 return u.f;
348}
349
350DECLINLINE(void) stfl_le_p(void *ptr, float32 v)
351{
352 union {
353 float32 f;
354 uint32_t i;
355 } u;
356 u.f = v;
357 stl_le_p(ptr, u.i);
358}
359
360DECLINLINE(float64) ldfq_le_p(void *ptr)
361{
362 CPU_DoubleU u;
363 u.l.lower = ldl_le_p(ptr);
364 u.l.upper = ldl_le_p((uint8_t*)ptr + 4);
365 return u.d;
366}
367
368DECLINLINE(void) stfq_le_p(void *ptr, float64 v)
369{
370 CPU_DoubleU u;
371 u.d = v;
372 stl_le_p(ptr, u.l.lower);
373 stl_le_p((uint8_t*)ptr + 4, u.l.upper);
374}
375
376#else /* !(VBOX && REM_PHYS_ADDR_IN_TLB) */
377
378static inline int ldub_p(void *ptr)
379{
380 return *(uint8_t *)ptr;
381}
382
383static inline int ldsb_p(void *ptr)
384{
385 return *(int8_t *)ptr;
386}
387
388static inline void stb_p(void *ptr, int v)
389{
390 *(uint8_t *)ptr = v;
391}
392
393/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
394 kernel handles unaligned load/stores may give better results, but
395 it is a system wide setting : bad */
396#if defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
397
398/* conservative code for little endian unaligned accesses */
399static inline int lduw_le_p(void *ptr)
400{
401#ifdef __powerpc__
402 int val;
403 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
404 return val;
405#else
406 uint8_t *p = ptr;
407 return p[0] | (p[1] << 8);
408#endif
409}
410
411static inline int ldsw_le_p(void *ptr)
412{
413#ifdef __powerpc__
414 int val;
415 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
416 return (int16_t)val;
417#else
418 uint8_t *p = ptr;
419 return (int16_t)(p[0] | (p[1] << 8));
420#endif
421}
422
423static inline int ldl_le_p(void *ptr)
424{
425#ifdef __powerpc__
426 int val;
427 __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
428 return val;
429#else
430 uint8_t *p = ptr;
431 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
432#endif
433}
434
435static inline uint64_t ldq_le_p(void *ptr)
436{
437 uint8_t *p = ptr;
438 uint32_t v1, v2;
439 v1 = ldl_le_p(p);
440 v2 = ldl_le_p(p + 4);
441 return v1 | ((uint64_t)v2 << 32);
442}
443
444static inline void stw_le_p(void *ptr, int v)
445{
446#ifdef __powerpc__
447 __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
448#else
449 uint8_t *p = ptr;
450 p[0] = v;
451 p[1] = v >> 8;
452#endif
453}
454
455static inline void stl_le_p(void *ptr, int v)
456{
457#ifdef __powerpc__
458 __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
459#else
460 uint8_t *p = ptr;
461 p[0] = v;
462 p[1] = v >> 8;
463 p[2] = v >> 16;
464 p[3] = v >> 24;
465#endif
466}
467
468static inline void stq_le_p(void *ptr, uint64_t v)
469{
470 uint8_t *p = ptr;
471 stl_le_p(p, (uint32_t)v);
472 stl_le_p(p + 4, v >> 32);
473}
474
475/* float access */
476
477static inline float32 ldfl_le_p(void *ptr)
478{
479 union {
480 float32 f;
481 uint32_t i;
482 } u;
483 u.i = ldl_le_p(ptr);
484 return u.f;
485}
486
487static inline void stfl_le_p(void *ptr, float32 v)
488{
489 union {
490 float32 f;
491 uint32_t i;
492 } u;
493 u.f = v;
494 stl_le_p(ptr, u.i);
495}
496
497static inline float64 ldfq_le_p(void *ptr)
498{
499 CPU_DoubleU u;
500 u.l.lower = ldl_le_p(ptr);
501 u.l.upper = ldl_le_p(ptr + 4);
502 return u.d;
503}
504
505static inline void stfq_le_p(void *ptr, float64 v)
506{
507 CPU_DoubleU u;
508 u.d = v;
509 stl_le_p(ptr, u.l.lower);
510 stl_le_p(ptr + 4, u.l.upper);
511}
512
513#else
514
515static inline int lduw_le_p(void *ptr)
516{
517 return *(uint16_t *)ptr;
518}
519
520static inline int ldsw_le_p(void *ptr)
521{
522 return *(int16_t *)ptr;
523}
524
525static inline int ldl_le_p(void *ptr)
526{
527 return *(uint32_t *)ptr;
528}
529
530static inline uint64_t ldq_le_p(void *ptr)
531{
532 return *(uint64_t *)ptr;
533}
534
535static inline void stw_le_p(void *ptr, int v)
536{
537 *(uint16_t *)ptr = v;
538}
539
540static inline void stl_le_p(void *ptr, int v)
541{
542 *(uint32_t *)ptr = v;
543}
544
545static inline void stq_le_p(void *ptr, uint64_t v)
546{
547 *(uint64_t *)ptr = v;
548}
549
550/* float access */
551
552static inline float32 ldfl_le_p(void *ptr)
553{
554 return *(float32 *)ptr;
555}
556
557static inline float64 ldfq_le_p(void *ptr)
558{
559 return *(float64 *)ptr;
560}
561
562static inline void stfl_le_p(void *ptr, float32 v)
563{
564 *(float32 *)ptr = v;
565}
566
567static inline void stfq_le_p(void *ptr, float64 v)
568{
569 *(float64 *)ptr = v;
570}
571#endif
572#endif /* !VBOX */
573
574#if !defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
575
576#ifndef VBOX
577static inline int lduw_be_p(void *ptr)
578{
579#if defined(__i386__)
580 int val;
581 asm volatile ("movzwl %1, %0\n"
582 "xchgb %b0, %h0\n"
583 : "=q" (val)
584 : "m" (*(uint16_t *)ptr));
585 return val;
586#else
587 uint8_t *b = (uint8_t *) ptr;
588 return ((b[0] << 8) | b[1]);
589#endif
590}
591#else /* VBOX */
592DECLINLINE(int) lduw_be_p(void *ptr)
593{
594#if defined(__i386__) && !defined(_MSC_VER)
595 int val;
596 asm volatile ("movzwl %1, %0\n"
597 "xchgb %b0, %h0\n"
598 : "=q" (val)
599 : "m" (*(uint16_t *)ptr));
600 return val;
601#else
602 uint8_t *b = (uint8_t *) ptr;
603 return ((b[0] << 8) | b[1]);
604#endif
605}
606#endif
607
608#ifndef VBOX
609static inline int ldsw_be_p(void *ptr)
610{
611#if defined(__i386__)
612 int val;
613 asm volatile ("movzwl %1, %0\n"
614 "xchgb %b0, %h0\n"
615 : "=q" (val)
616 : "m" (*(uint16_t *)ptr));
617 return (int16_t)val;
618#else
619 uint8_t *b = (uint8_t *) ptr;
620 return (int16_t)((b[0] << 8) | b[1]);
621#endif
622}
623#else
624DECLINLINE(int) ldsw_be_p(void *ptr)
625{
626#if defined(__i386__) && !defined(_MSC_VER)
627 int val;
628 asm volatile ("movzwl %1, %0\n"
629 "xchgb %b0, %h0\n"
630 : "=q" (val)
631 : "m" (*(uint16_t *)ptr));
632 return (int16_t)val;
633#else
634 uint8_t *b = (uint8_t *) ptr;
635 return (int16_t)((b[0] << 8) | b[1]);
636#endif
637}
638#endif
639
640#ifndef VBOX
641static inline int ldl_be_p(void *ptr)
642{
643#if defined(__i386__) || defined(__x86_64__)
644 int val;
645 asm volatile ("movl %1, %0\n"
646 "bswap %0\n"
647 : "=r" (val)
648 : "m" (*(uint32_t *)ptr));
649 return val;
650#else
651 uint8_t *b = (uint8_t *) ptr;
652 return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
653#endif
654}
655#else
656DECLINLINE(int) ldl_be_p(void *ptr)
657{
658#if (defined(__i386__) || defined(__x86_64__)) && !defined(_MSC_VER)
659 int val;
660 asm volatile ("movl %1, %0\n"
661 "bswap %0\n"
662 : "=r" (val)
663 : "m" (*(uint32_t *)ptr));
664 return val;
665#else
666 uint8_t *b = (uint8_t *) ptr;
667 return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
668#endif
669}
670#endif
671
672#ifndef VBOX
673static inline uint64_t ldq_be_p(void *ptr)
674#else
675DECLINLINE(uint64_t) ldq_be_p(void *ptr)
676#endif
677{
678 uint32_t a,b;
679 a = ldl_be_p(ptr);
680 b = ldl_be_p((uint8_t*)ptr+4);
681 return (((uint64_t)a<<32)|b);
682}
683
684#ifndef VBOX
685static inline void stw_be_p(void *ptr, int v)
686{
687#if defined(__i386__)
688 asm volatile ("xchgb %b0, %h0\n"
689 "movw %w0, %1\n"
690 : "=q" (v)
691 : "m" (*(uint16_t *)ptr), "0" (v));
692#else
693 uint8_t *d = (uint8_t *) ptr;
694 d[0] = v >> 8;
695 d[1] = v;
696#endif
697}
698#else
699DECLINLINE(void) stw_be_p(void *ptr, int v)
700{
701#if defined(__i386__) && !defined(_MSC_VER)
702 asm volatile ("xchgb %b0, %h0\n"
703 "movw %w0, %1\n"
704 : "=q" (v)
705 : "m" (*(uint16_t *)ptr), "0" (v));
706#else
707 uint8_t *d = (uint8_t *) ptr;
708 d[0] = v >> 8;
709 d[1] = v;
710#endif
711}
712
713#endif /* VBOX */
714
715#ifndef VBOX
716static inline void stl_be_p(void *ptr, int v)
717{
718#if defined(__i386__) || defined(__x86_64__)
719 asm volatile ("bswap %0\n"
720 "movl %0, %1\n"
721 : "=r" (v)
722 : "m" (*(uint32_t *)ptr), "0" (v));
723#else
724 uint8_t *d = (uint8_t *) ptr;
725 d[0] = v >> 24;
726 d[1] = v >> 16;
727 d[2] = v >> 8;
728 d[3] = v;
729#endif
730}
731#else
732DECLINLINE(void) stl_be_p(void *ptr, int v)
733{
734#if !defined(_MSC_VER) && (defined(__i386__) || defined(__x86_64__))
735 asm volatile ("bswap %0\n"
736 "movl %0, %1\n"
737 : "=r" (v)
738 : "m" (*(uint32_t *)ptr), "0" (v));
739#else
740 uint8_t *d = (uint8_t *) ptr;
741 d[0] = v >> 24;
742 d[1] = v >> 16;
743 d[2] = v >> 8;
744 d[3] = v;
745#endif
746}
747#endif /* VBOX */
748
749#ifndef VBOX
750static inline void stq_be_p(void *ptr, uint64_t v)
751#else
752DECLINLINE(void) stq_be_p(void *ptr, uint64_t v)
753#endif
754{
755 stl_be_p(ptr, v >> 32);
756 stl_be_p((uint8_t*)ptr + 4, v);
757}
758
759/* float access */
760#ifndef VBOX
761static inline float32 ldfl_be_p(void *ptr)
762#else
763DECLINLINE(float32) ldfl_be_p(void *ptr)
764#endif
765{
766 union {
767 float32 f;
768 uint32_t i;
769 } u;
770 u.i = ldl_be_p(ptr);
771 return u.f;
772}
773
774#ifndef VBOX
775static inline void stfl_be_p(void *ptr, float32 v)
776#else
777DECLINLINE(void) stfl_be_p(void *ptr, float32 v)
778#endif
779{
780 union {
781 float32 f;
782 uint32_t i;
783 } u;
784 u.f = v;
785 stl_be_p(ptr, u.i);
786}
787
788#ifndef VBOX
789static inline float64 ldfq_be_p(void *ptr)
790#else
791DECLINLINE(float64) ldfq_be_p(void *ptr)
792#endif
793{
794 CPU_DoubleU u;
795 u.l.upper = ldl_be_p(ptr);
796 u.l.lower = ldl_be_p((uint8_t*)ptr + 4);
797 return u.d;
798}
799
800#ifndef VBOX
801static inline void stfq_be_p(void *ptr, float64 v)
802#else
803DECLINLINE(void) stfq_be_p(void *ptr, float64 v)
804#endif
805{
806 CPU_DoubleU u;
807 u.d = v;
808 stl_be_p(ptr, u.l.upper);
809 stl_be_p((uint8_t*)ptr + 4, u.l.lower);
810}
811
812#else
813
814static inline int lduw_be_p(void *ptr)
815{
816 return *(uint16_t *)ptr;
817}
818
819static inline int ldsw_be_p(void *ptr)
820{
821 return *(int16_t *)ptr;
822}
823
824static inline int ldl_be_p(void *ptr)
825{
826 return *(uint32_t *)ptr;
827}
828
829static inline uint64_t ldq_be_p(void *ptr)
830{
831 return *(uint64_t *)ptr;
832}
833
834static inline void stw_be_p(void *ptr, int v)
835{
836 *(uint16_t *)ptr = v;
837}
838
839static inline void stl_be_p(void *ptr, int v)
840{
841 *(uint32_t *)ptr = v;
842}
843
844static inline void stq_be_p(void *ptr, uint64_t v)
845{
846 *(uint64_t *)ptr = v;
847}
848
849/* float access */
850
851static inline float32 ldfl_be_p(void *ptr)
852{
853 return *(float32 *)ptr;
854}
855
856static inline float64 ldfq_be_p(void *ptr)
857{
858 return *(float64 *)ptr;
859}
860
861static inline void stfl_be_p(void *ptr, float32 v)
862{
863 *(float32 *)ptr = v;
864}
865
866static inline void stfq_be_p(void *ptr, float64 v)
867{
868 *(float64 *)ptr = v;
869}
870
871#endif
872
873/* target CPU memory access functions */
874#if defined(TARGET_WORDS_BIGENDIAN)
875#define lduw_p(p) lduw_be_p(p)
876#define ldsw_p(p) ldsw_be_p(p)
877#define ldl_p(p) ldl_be_p(p)
878#define ldq_p(p) ldq_be_p(p)
879#define ldfl_p(p) ldfl_be_p(p)
880#define ldfq_p(p) ldfq_be_p(p)
881#define stw_p(p, v) stw_be_p(p, v)
882#define stl_p(p, v) stl_be_p(p, v)
883#define stq_p(p, v) stq_be_p(p, v)
884#define stfl_p(p, v) stfl_be_p(p, v)
885#define stfq_p(p, v) stfq_be_p(p, v)
886#else
887#define lduw_p(p) lduw_le_p(p)
888#define ldsw_p(p) ldsw_le_p(p)
889#define ldl_p(p) ldl_le_p(p)
890#define ldq_p(p) ldq_le_p(p)
891#define ldfl_p(p) ldfl_le_p(p)
892#define ldfq_p(p) ldfq_le_p(p)
893#define stw_p(p, v) stw_le_p(p, v)
894#define stl_p(p, v) stl_le_p(p, v)
895#define stq_p(p, v) stq_le_p(p, v)
896#define stfl_p(p, v) stfl_le_p(p, v)
897#define stfq_p(p, v) stfq_le_p(p, v)
898#endif
899
900/* MMU memory access macros */
901
902#if defined(CONFIG_USER_ONLY)
903/* On some host systems the guest address space is reserved on the host.
904 * This allows the guest address space to be offset to a convenient location.
905 */
906//#define GUEST_BASE 0x20000000
907#define GUEST_BASE 0
908
909/* All direct uses of g2h and h2g need to go away for usermode softmmu. */
910#define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE))
911#define h2g(x) ((target_ulong)(x - GUEST_BASE))
912#define saddr(x) g2h(x)
913#define laddr(x) g2h(x)
914
915#else /* !CONFIG_USER_ONLY */
916/* NOTE: we use double casts if pointers and target_ulong have
917 different sizes */
918#define saddr(x) (uint8_t *)(long)(x)
919#define laddr(x) (uint8_t *)(long)(x)
920#endif
921
922#define ldub_raw(p) ldub_p(laddr((p)))
923#define ldsb_raw(p) ldsb_p(laddr((p)))
924#define lduw_raw(p) lduw_p(laddr((p)))
925#define ldsw_raw(p) ldsw_p(laddr((p)))
926#define ldl_raw(p) ldl_p(laddr((p)))
927#define ldq_raw(p) ldq_p(laddr((p)))
928#define ldfl_raw(p) ldfl_p(laddr((p)))
929#define ldfq_raw(p) ldfq_p(laddr((p)))
930#define stb_raw(p, v) stb_p(saddr((p)), v)
931#define stw_raw(p, v) stw_p(saddr((p)), v)
932#define stl_raw(p, v) stl_p(saddr((p)), v)
933#define stq_raw(p, v) stq_p(saddr((p)), v)
934#define stfl_raw(p, v) stfl_p(saddr((p)), v)
935#define stfq_raw(p, v) stfq_p(saddr((p)), v)
936
937
938#if defined(CONFIG_USER_ONLY)
939
940/* if user mode, no other memory access functions */
941#define ldub(p) ldub_raw(p)
942#define ldsb(p) ldsb_raw(p)
943#define lduw(p) lduw_raw(p)
944#define ldsw(p) ldsw_raw(p)
945#define ldl(p) ldl_raw(p)
946#define ldq(p) ldq_raw(p)
947#define ldfl(p) ldfl_raw(p)
948#define ldfq(p) ldfq_raw(p)
949#define stb(p, v) stb_raw(p, v)
950#define stw(p, v) stw_raw(p, v)
951#define stl(p, v) stl_raw(p, v)
952#define stq(p, v) stq_raw(p, v)
953#define stfl(p, v) stfl_raw(p, v)
954#define stfq(p, v) stfq_raw(p, v)
955
956#define ldub_code(p) ldub_raw(p)
957#define ldsb_code(p) ldsb_raw(p)
958#define lduw_code(p) lduw_raw(p)
959#define ldsw_code(p) ldsw_raw(p)
960#define ldl_code(p) ldl_raw(p)
961
962#define ldub_kernel(p) ldub_raw(p)
963#define ldsb_kernel(p) ldsb_raw(p)
964#define lduw_kernel(p) lduw_raw(p)
965#define ldsw_kernel(p) ldsw_raw(p)
966#define ldl_kernel(p) ldl_raw(p)
967#define ldfl_kernel(p) ldfl_raw(p)
968#define ldfq_kernel(p) ldfq_raw(p)
969#define stb_kernel(p, v) stb_raw(p, v)
970#define stw_kernel(p, v) stw_raw(p, v)
971#define stl_kernel(p, v) stl_raw(p, v)
972#define stq_kernel(p, v) stq_raw(p, v)
973#define stfl_kernel(p, v) stfl_raw(p, v)
974#define stfq_kernel(p, vt) stfq_raw(p, v)
975
976#endif /* defined(CONFIG_USER_ONLY) */
977
978/* page related stuff */
979
980#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
981#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
982#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK)
983
984/* ??? These should be the larger of unsigned long and target_ulong. */
985extern unsigned long qemu_real_host_page_size;
986extern unsigned long qemu_host_page_bits;
987extern unsigned long qemu_host_page_size;
988extern unsigned long qemu_host_page_mask;
989
990#define HOST_PAGE_ALIGN(addr) (((addr) + qemu_host_page_size - 1) & qemu_host_page_mask)
991
992/* same as PROT_xxx */
993#define PAGE_READ 0x0001
994#define PAGE_WRITE 0x0002
995#define PAGE_EXEC 0x0004
996#define PAGE_BITS (PAGE_READ | PAGE_WRITE | PAGE_EXEC)
997#define PAGE_VALID 0x0008
998/* original state of the write flag (used when tracking self-modifying
999 code */
1000#define PAGE_WRITE_ORG 0x0010
1001#define PAGE_RESERVED 0x0020
1002
1003void page_dump(FILE *f);
1004int page_get_flags(target_ulong address);
1005void page_set_flags(target_ulong start, target_ulong end, int flags);
1006int page_check_range(target_ulong start, target_ulong len, int flags);
1007void page_unprotect_range(target_ulong data, target_ulong data_size);
1008
1009#define SINGLE_CPU_DEFINES
1010#ifdef SINGLE_CPU_DEFINES
1011
1012#if defined(TARGET_I386)
1013
1014#define CPUState CPUX86State
1015#define cpu_init cpu_x86_init
1016#define cpu_exec cpu_x86_exec
1017#define cpu_gen_code cpu_x86_gen_code
1018#define cpu_signal_handler cpu_x86_signal_handler
1019
1020#elif defined(TARGET_ARM)
1021
1022#define CPUState CPUARMState
1023#define cpu_init cpu_arm_init
1024#define cpu_exec cpu_arm_exec
1025#define cpu_gen_code cpu_arm_gen_code
1026#define cpu_signal_handler cpu_arm_signal_handler
1027
1028#elif defined(TARGET_SPARC)
1029
1030#define CPUState CPUSPARCState
1031#define cpu_init cpu_sparc_init
1032#define cpu_exec cpu_sparc_exec
1033#define cpu_gen_code cpu_sparc_gen_code
1034#define cpu_signal_handler cpu_sparc_signal_handler
1035
1036#elif defined(TARGET_PPC)
1037
1038#define CPUState CPUPPCState
1039#define cpu_init cpu_ppc_init
1040#define cpu_exec cpu_ppc_exec
1041#define cpu_gen_code cpu_ppc_gen_code
1042#define cpu_signal_handler cpu_ppc_signal_handler
1043
1044#elif defined(TARGET_M68K)
1045#define CPUState CPUM68KState
1046#define cpu_init cpu_m68k_init
1047#define cpu_exec cpu_m68k_exec
1048#define cpu_gen_code cpu_m68k_gen_code
1049#define cpu_signal_handler cpu_m68k_signal_handler
1050
1051#elif defined(TARGET_MIPS)
1052#define CPUState CPUMIPSState
1053#define cpu_init cpu_mips_init
1054#define cpu_exec cpu_mips_exec
1055#define cpu_gen_code cpu_mips_gen_code
1056#define cpu_signal_handler cpu_mips_signal_handler
1057
1058#elif defined(TARGET_SH4)
1059#define CPUState CPUSH4State
1060#define cpu_init cpu_sh4_init
1061#define cpu_exec cpu_sh4_exec
1062#define cpu_gen_code cpu_sh4_gen_code
1063#define cpu_signal_handler cpu_sh4_signal_handler
1064
1065#else
1066
1067#error unsupported target CPU
1068
1069#endif
1070
1071#endif /* SINGLE_CPU_DEFINES */
1072
1073void cpu_dump_state(CPUState *env, FILE *f,
1074 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1075 int flags);
1076
1077DECLNORETURN(void) cpu_abort(CPUState *env, const char *fmt, ...);
1078extern CPUState *first_cpu;
1079extern CPUState *cpu_single_env;
1080extern int64_t qemu_icount;
1081extern int use_icount;
1082
1083#define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */
1084#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */
1085#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
1086#define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
1087#define CPU_INTERRUPT_FIQ 0x10 /* Fast interrupt pending. */
1088#define CPU_INTERRUPT_HALT 0x20 /* CPU halt wanted */
1089#define CPU_INTERRUPT_SMI 0x40 /* (x86 only) SMI interrupt pending */
1090#define CPU_INTERRUPT_DEBUG 0x80 /* Debug event occured. */
1091#define CPU_INTERRUPT_VIRQ 0x100 /* virtual interrupt pending. */
1092#define CPU_INTERRUPT_NMI 0x200 /* NMI pending. */
1093
1094#ifdef VBOX
1095/** Executes a single instruction. cpu_exec() will normally return EXCP_SINGLE_INSTR. */
1096#define CPU_INTERRUPT_SINGLE_INSTR 0x0400
1097/** Executing a CPU_INTERRUPT_SINGLE_INSTR request, quit the cpu_loop. (for exceptions and suchlike) */
1098#define CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT 0x0800
1099/** VM execution was interrupted by VMR3Reset, VMR3Suspend or VMR3PowerOff. */
1100#define CPU_INTERRUPT_RC 0x1000
1101/** Exit current TB to process an external interrupt request (also in op.c!!) */
1102#define CPU_INTERRUPT_EXTERNAL_EXIT 0x2000
1103/** Exit current TB to process an external interrupt request (also in op.c!!) */
1104#define CPU_INTERRUPT_EXTERNAL_HARD 0x4000
1105/** Exit current TB to process an external interrupt request (also in op.c!!) */
1106#define CPU_INTERRUPT_EXTERNAL_TIMER 0x8000
1107/** Exit current TB to process an external interrupt request (also in op.c!!) */
1108#define CPU_INTERRUPT_EXTERNAL_DMA 0x10000
1109#endif /* VBOX */
1110void cpu_interrupt(CPUState *s, int mask);
1111void cpu_reset_interrupt(CPUState *env, int mask);
1112
1113int cpu_watchpoint_insert(CPUState *env, target_ulong addr, int type);
1114int cpu_watchpoint_remove(CPUState *env, target_ulong addr);
1115void cpu_watchpoint_remove_all(CPUState *env);
1116int cpu_breakpoint_insert(CPUState *env, target_ulong pc);
1117int cpu_breakpoint_remove(CPUState *env, target_ulong pc);
1118void cpu_breakpoint_remove_all(CPUState *env);
1119
1120#define SSTEP_ENABLE 0x1 /* Enable simulated HW single stepping */
1121#define SSTEP_NOIRQ 0x2 /* Do not use IRQ while single stepping */
1122#define SSTEP_NOTIMER 0x4 /* Do not Timers while single stepping */
1123
1124void cpu_single_step(CPUState *env, int enabled);
1125void cpu_reset(CPUState *s);
1126
1127/* Return the physical page corresponding to a virtual one. Use it
1128 only for debugging because no protection checks are done. Return -1
1129 if no page found. */
1130target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
1131
1132#define CPU_LOG_TB_OUT_ASM (1 << 0)
1133#define CPU_LOG_TB_IN_ASM (1 << 1)
1134#define CPU_LOG_TB_OP (1 << 2)
1135#define CPU_LOG_TB_OP_OPT (1 << 3)
1136#define CPU_LOG_INT (1 << 4)
1137#define CPU_LOG_EXEC (1 << 5)
1138#define CPU_LOG_PCALL (1 << 6)
1139#define CPU_LOG_IOPORT (1 << 7)
1140#define CPU_LOG_TB_CPU (1 << 8)
1141
1142/* define log items */
1143typedef struct CPULogItem {
1144 int mask;
1145 const char *name;
1146 const char *help;
1147} CPULogItem;
1148
1149extern CPULogItem cpu_log_items[];
1150
1151void cpu_set_log(int log_flags);
1152void cpu_set_log_filename(const char *filename);
1153int cpu_str_to_log_mask(const char *str);
1154
1155/* IO ports API */
1156
1157/* NOTE: as these functions may be even used when there is an isa
1158 brige on non x86 targets, we always defined them */
1159#ifndef NO_CPU_IO_DEFS
1160void cpu_outb(CPUState *env, int addr, int val);
1161void cpu_outw(CPUState *env, int addr, int val);
1162void cpu_outl(CPUState *env, int addr, int val);
1163int cpu_inb(CPUState *env, int addr);
1164int cpu_inw(CPUState *env, int addr);
1165int cpu_inl(CPUState *env, int addr);
1166#endif
1167
1168/* address in the RAM (different from a physical address) */
1169#ifdef USE_KQEMU
1170typedef uint32_t ram_addr_t;
1171#else
1172typedef unsigned long ram_addr_t;
1173#endif
1174
1175/* memory API */
1176
1177#ifndef VBOX
1178extern int phys_ram_size;
1179extern int phys_ram_fd;
1180extern int phys_ram_size;
1181#else /* VBOX */
1182extern RTGCPHYS phys_ram_size;
1183/** This is required for bounds checking the phys_ram_dirty accesses. */
1184extern RTGCPHYS phys_ram_dirty_size;
1185#endif /* VBOX */
1186#if !defined(VBOX)
1187extern uint8_t *phys_ram_base;
1188#endif
1189extern uint8_t *phys_ram_dirty;
1190
1191/* physical memory access */
1192
1193/* MMIO pages are identified by a combination of an IO device index and
1194 3 flags. The ROMD code stores the page ram offset in iotlb entry,
1195 so only a limited number of ids are avaiable. */
1196
1197#define IO_MEM_SHIFT 3
1198#define IO_MEM_NB_ENTRIES (1 << (TARGET_PAGE_BITS - IO_MEM_SHIFT))
1199
1200#define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */
1201#define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */
1202#define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT)
1203#define IO_MEM_NOTDIRTY (3 << IO_MEM_SHIFT)
1204
1205/* Acts like a ROM when read and like a device when written. */
1206#define IO_MEM_ROMD (1)
1207#define IO_MEM_SUBPAGE (2)
1208#define IO_MEM_SUBWIDTH (4)
1209
1210/* Flags stored in the low bits of the TLB virtual address. These are
1211 defined so that fast path ram access is all zeros. */
1212/* Zero if TLB entry is valid. */
1213#define TLB_INVALID_MASK (1 << 3)
1214/* Set if TLB entry references a clean RAM page. The iotlb entry will
1215 contain the page physical address. */
1216#define TLB_NOTDIRTY (1 << 4)
1217/* Set if TLB entry is an IO callback. */
1218#define TLB_MMIO (1 << 5)
1219
1220typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
1221typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
1222
1223void cpu_register_physical_memory(target_phys_addr_t start_addr,
1224 ram_addr_t size,
1225 ram_addr_t phys_offset);
1226uint32_t cpu_get_physical_page_desc(target_phys_addr_t addr);
1227ram_addr_t qemu_ram_alloc(ram_addr_t);
1228void qemu_ram_free(ram_addr_t addr);
1229int cpu_register_io_memory(int io_index,
1230 CPUReadMemoryFunc **mem_read,
1231 CPUWriteMemoryFunc **mem_write,
1232 void *opaque);
1233CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index);
1234CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index);
1235
1236void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
1237 int len, int is_write);
1238#ifndef VBOX
1239static inline void cpu_physical_memory_read(target_phys_addr_t addr,
1240 uint8_t *buf, int len)
1241#else
1242DECLINLINE(void) cpu_physical_memory_read(target_phys_addr_t addr,
1243 uint8_t *buf, int len)
1244#endif
1245{
1246 cpu_physical_memory_rw(addr, buf, len, 0);
1247}
1248#ifndef VBOX
1249static inline void cpu_physical_memory_write(target_phys_addr_t addr,
1250 const uint8_t *buf, int len)
1251#else
1252DECLINLINE(void) cpu_physical_memory_write(target_phys_addr_t addr,
1253 const uint8_t *buf, int len)
1254#endif
1255{
1256 cpu_physical_memory_rw(addr, (uint8_t *)buf, len, 1);
1257}
1258uint32_t ldub_phys(target_phys_addr_t addr);
1259uint32_t lduw_phys(target_phys_addr_t addr);
1260uint32_t ldl_phys(target_phys_addr_t addr);
1261uint64_t ldq_phys(target_phys_addr_t addr);
1262void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val);
1263void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val);
1264void stb_phys(target_phys_addr_t addr, uint32_t val);
1265void stw_phys(target_phys_addr_t addr, uint32_t val);
1266void stl_phys(target_phys_addr_t addr, uint32_t val);
1267void stq_phys(target_phys_addr_t addr, uint64_t val);
1268
1269void cpu_physical_memory_write_rom(target_phys_addr_t addr,
1270 const uint8_t *buf, int len);
1271int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
1272 uint8_t *buf, int len, int is_write);
1273
1274#define VGA_DIRTY_FLAG 0x01
1275#define CODE_DIRTY_FLAG 0x02
1276#define KQEMU_DIRTY_FLAG 0x04
1277#define MIGRATION_DIRTY_FLAG 0x08
1278
1279/* read dirty bit (return 0 or 1) */
1280#ifndef VBOX
1281static inline int cpu_physical_memory_is_dirty(ram_addr_t addr)
1282{
1283 return phys_ram_dirty[addr >> TARGET_PAGE_BITS] == 0xff;
1284}
1285#else
1286DECLINLINE(int) cpu_physical_memory_is_dirty(ram_addr_t addr)
1287{
1288 if (RT_UNLIKELY((addr >> TARGET_PAGE_BITS) >= phys_ram_dirty_size))
1289 {
1290 Log(("cpu_physical_memory_is_dirty: %RGp\n", (RTGCPHYS)addr));
1291 /*AssertMsgFailed(("cpu_physical_memory_is_dirty: %RGp\n", (RTGCPHYS)addr));*/
1292 return 0;
1293 }
1294 return phys_ram_dirty[addr >> TARGET_PAGE_BITS] == 0xff;
1295}
1296#endif
1297
1298#ifndef VBOX
1299static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
1300 int dirty_flags)
1301{
1302 return phys_ram_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
1303}
1304#else
1305DECLINLINE(int) cpu_physical_memory_get_dirty(ram_addr_t addr,
1306 int dirty_flags)
1307{
1308 if (RT_UNLIKELY((addr >> TARGET_PAGE_BITS) >= phys_ram_dirty_size))
1309 {
1310 Log(("cpu_physical_memory_is_dirty: %RGp\n", (RTGCPHYS)addr));
1311 /*AssertMsgFailed(("cpu_physical_memory_is_dirty: %RGp\n", (RTGCPHYS)addr));*/
1312 return 0xff & dirty_flags; /** @todo I don't think this is the right thing to return, fix! */
1313 }
1314 return phys_ram_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
1315}
1316#endif
1317
1318#ifndef VBOX
1319static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
1320{
1321 phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
1322}
1323#else
1324DECLINLINE(void) cpu_physical_memory_set_dirty(ram_addr_t addr)
1325{
1326 if (RT_UNLIKELY((addr >> TARGET_PAGE_BITS) >= phys_ram_dirty_size))
1327 {
1328 Log(("cpu_physical_memory_is_dirty: %RGp\n", (RTGCPHYS)addr));
1329 /*AssertMsgFailed(("cpu_physical_memory_is_dirty: %RGp\n", (RTGCPHYS)addr));*/
1330 return;
1331 }
1332 phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
1333}
1334#endif
1335
1336void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1337 int dirty_flags);
1338void cpu_tlb_update_dirty(CPUState *env);
1339
1340int cpu_physical_memory_set_dirty_tracking(int enable);
1341
1342int cpu_physical_memory_get_dirty_tracking(void);
1343
1344void dump_exec_info(FILE *f,
1345 int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
1346
1347/*******************************************/
1348/* host CPU ticks (if available) */
1349
1350#ifdef VBOX
1351# include <iprt/asm-amd64-x86.h>
1352
1353DECLINLINE(int64_t) cpu_get_real_ticks(void)
1354{
1355 return ASMReadTSC();
1356}
1357
1358#elif defined(__powerpc__)
1359
1360static inline uint32_t get_tbl(void)
1361{
1362 uint32_t tbl;
1363 asm volatile("mftb %0" : "=r" (tbl));
1364 return tbl;
1365}
1366
1367static inline uint32_t get_tbu(void)
1368{
1369 uint32_t tbl;
1370 asm volatile("mftbu %0" : "=r" (tbl));
1371 return tbl;
1372}
1373
1374static inline int64_t cpu_get_real_ticks(void)
1375{
1376 uint32_t l, h, h1;
1377 /* NOTE: we test if wrapping has occurred */
1378 do {
1379 h = get_tbu();
1380 l = get_tbl();
1381 h1 = get_tbu();
1382 } while (h != h1);
1383 return ((int64_t)h << 32) | l;
1384}
1385
1386#elif defined(__i386__)
1387
1388static inline int64_t cpu_get_real_ticks(void)
1389{
1390 int64_t val;
1391 asm volatile ("rdtsc" : "=A" (val));
1392 return val;
1393}
1394
1395#elif defined(__x86_64__)
1396
1397static inline int64_t cpu_get_real_ticks(void)
1398{
1399 uint32_t low,high;
1400 int64_t val;
1401 asm volatile("rdtsc" : "=a" (low), "=d" (high));
1402 val = high;
1403 val <<= 32;
1404 val |= low;
1405 return val;
1406}
1407
1408#elif defined(__ia64)
1409
1410static inline int64_t cpu_get_real_ticks(void)
1411{
1412 int64_t val;
1413 asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory");
1414 return val;
1415}
1416
1417#elif defined(__s390__)
1418
1419static inline int64_t cpu_get_real_ticks(void)
1420{
1421 int64_t val;
1422 asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc");
1423 return val;
1424}
1425
1426#elif defined(__sparc_v9__)
1427
1428static inline int64_t cpu_get_real_ticks (void)
1429{
1430#if defined(_LP64)
1431 uint64_t rval;
1432 asm volatile("rd %%tick,%0" : "=r"(rval));
1433 return rval;
1434#else
1435 union {
1436 uint64_t i64;
1437 struct {
1438 uint32_t high;
1439 uint32_t low;
1440 } i32;
1441 } rval;
1442 asm volatile("rd %%tick,%1; srlx %1,32,%0"
1443 : "=r"(rval.i32.high), "=r"(rval.i32.low));
1444 return rval.i64;
1445#endif
1446}
1447#else
1448/* The host CPU doesn't have an easily accessible cycle counter.
1449 Just return a monotonically increasing vlue. This will be totally wrong,
1450 but hopefully better than nothing. */
1451static inline int64_t cpu_get_real_ticks (void)
1452{
1453 static int64_t ticks = 0;
1454 return ticks++;
1455}
1456#endif
1457
1458/* profiling */
1459#ifdef CONFIG_PROFILER
1460static inline int64_t profile_getclock(void)
1461{
1462 return cpu_get_real_ticks();
1463}
1464
1465extern int64_t kqemu_time, kqemu_time_start;
1466extern int64_t qemu_time, qemu_time_start;
1467extern int64_t tlb_flush_time;
1468extern int64_t kqemu_exec_count;
1469extern int64_t dev_time;
1470extern int64_t kqemu_ret_int_count;
1471extern int64_t kqemu_ret_excp_count;
1472extern int64_t kqemu_ret_intr_count;
1473
1474#endif
1475
1476#ifdef VBOX
1477void tb_invalidate_virt(CPUState *env, uint32_t eip);
1478#endif /* VBOX */
1479
1480#endif /* CPU_ALL_H */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette