cpu-all.h revision 677833bc953b6cb418c701facbdcf4aa18d6c44e
/*
* defines common to all virtual CPUs
*
* Copyright (c) 2003 Fabrice Bellard
*
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef CPU_ALL_H
#define CPU_ALL_H
#define WORDS_ALIGNED
#endif
/* some important defines:
*
* WORDS_ALIGNED : if defined, the host cpu can only make word aligned
* memory accesses.
*
* WORDS_BIGENDIAN : if defined, the host cpu is big endian and
* otherwise little endian.
*
* (TARGET_WORDS_ALIGNED : same for target cpu (not supported yet))
*
* TARGET_WORDS_BIGENDIAN : same for target cpu
*/
#include "bswap.h"
#if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
#define BSWAP_NEEDED
#endif
#ifdef BSWAP_NEEDED
{
return bswap16(s);
}
{
return bswap32(s);
}
{
return bswap64(s);
}
{
*s = bswap16(*s);
}
{
*s = bswap32(*s);
}
{
*s = bswap64(*s);
}
#else
{
return s;
}
{
return s;
}
{
return s;
}
{
}
{
}
{
}
#endif
#if TARGET_LONG_SIZE == 4
#else
#endif
/* NOTE: arm FPA is horrible as double 32 bit words are stored in big
endian ! */
typedef union {
double d;
struct {
} l;
#else
struct {
} l;
#endif
} CPU_DoubleU;
/* CPU memory access without any memory or io remapping */
/*
* the generic syntax for the memory accesses is:
*
* load: ld{type}{sign}{size}{endian}_{access_type}(ptr)
*
* store: st{type}{size}{endian}_{access_type}(ptr, val)
*
* type is:
* (empty): integer access
* f : float access
*
* sign is:
* (empty): for floats or 32 bit size
* u : unsigned
* s : signed
*
* size is:
* b: 8 bits
* w: 16 bits
* l: 32 bits
* q: 64 bits
*
* endian is:
* (empty): target cpu endianness or 8 bit access
* r : reversed target cpu endianness (not implemented yet)
* be : big endian (not implemented yet)
* le : little endian (not implemented yet)
*
* access_type is:
* raw : host memory access
* user : user mode access using soft MMU
* kernel : kernel mode access using soft MMU
*/
#ifdef VBOX
#if !defined(REMR3PHYSREADWRITE_DEFINED)
#define REMR3PHYSREADWRITE_DEFINED
/* Header sharing between vbox & qemu is rather ugly. */
void remR3GrowDynRange(unsigned long physaddr);
#endif
{
return remR3PhysReadUByte(ptr);
}
{
return remR3PhysReadSByte(ptr);
}
{
remR3PhysWriteByte(ptr, v);
}
#else
{
}
{
}
{
}
#endif
it is a system wide setting : bad */
/* conservative code for little endian unaligned accesses */
{
#ifdef __powerpc__
int val;
return val;
#else
return p[0] | (p[1] << 8);
#endif
}
{
#ifdef __powerpc__
int val;
#else
#endif
}
{
#ifdef __powerpc__
int val;
return val;
#else
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
#endif
}
{
}
{
#ifdef __powerpc__
#else
p[0] = v;
p[1] = v >> 8;
#endif
}
{
#ifdef __powerpc__
#else
p[0] = v;
p[1] = v >> 8;
p[2] = v >> 16;
p[3] = v >> 24;
#endif
}
{
}
/* float access */
{
union {
float f;
uint32_t i;
} u;
return u.f;
}
{
union {
float f;
uint32_t i;
} u;
u.f = v;
}
{
CPU_DoubleU u;
return u.d;
}
{
CPU_DoubleU u;
u.d = v;
}
{
#if defined(__i386__)
int val;
asm volatile ("movzwl %1, %0\n"
"xchgb %b0, %h0\n"
: "=q" (val)
return val;
#else
return ((b[0] << 8) | b[1]);
#endif
}
{
#if defined(__i386__)
int val;
asm volatile ("movzwl %1, %0\n"
"xchgb %b0, %h0\n"
: "=q" (val)
#else
#endif
}
{
#if defined(__i386__) || defined(__x86_64__)
int val;
asm volatile ("movl %1, %0\n"
"bswap %0\n"
: "=r" (val)
return val;
#else
return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
#endif
}
{
uint32_t a,b;
return (((uint64_t)a<<32)|b);
}
{
#if defined(__i386__)
asm volatile ("xchgb %b0, %h0\n"
"movw %w0, %1\n"
: "=q" (v)
#else
d[0] = v >> 8;
d[1] = v;
#endif
}
{
#if defined(__i386__) || defined(__x86_64__)
asm volatile ("bswap %0\n"
"movl %0, %1\n"
: "=r" (v)
#else
d[0] = v >> 24;
d[1] = v >> 16;
d[2] = v >> 8;
d[3] = v;
#endif
}
{
}
/* float access */
{
union {
float f;
uint32_t i;
} u;
return u.f;
}
{
union {
float f;
uint32_t i;
} u;
u.f = v;
}
{
CPU_DoubleU u;
return u.d;
}
{
CPU_DoubleU u;
u.d = v;
}
#else
#ifdef VBOX
{
return remR3PhysReadUWord(ptr);
}
{
return remR3PhysReadSWord(ptr);
}
{
return remR3PhysReadULong(ptr);
}
{
return val;
}
{
}
{
}
{
remR3PhysWriteBytes(ptr, &v, sizeof(v));
}
/* float access */
{
float val;
return val;
}
{
double val;
return val;
}
{
remR3PhysWriteBytes(ptr, &v, sizeof(v));
}
{
remR3PhysWriteBytes(ptr, &v, sizeof(v));
}
#else
{
}
{
}
{
}
{
}
{
}
{
}
{
}
/* float access */
{
return *(float *)ptr;
}
{
return *(double *)ptr;
}
{
*(float *)ptr = v;
}
{
*(double *)ptr = v;
}
#endif /* VBOX */
#endif
/* MMU memory access macros */
/* NOTE: we use double casts if pointers and target_ulong have
different sizes */
#if defined(CONFIG_USER_ONLY)
/* if user mode, no other memory access functions */
#define ldub_kernel(p) ldub_raw(p)
#define ldsb_kernel(p) ldsb_raw(p)
#define lduw_kernel(p) lduw_raw(p)
#define ldsw_kernel(p) ldsw_raw(p)
#define ldl_kernel(p) ldl_raw(p)
#define ldfl_kernel(p) ldfl_raw(p)
#define ldfq_kernel(p) ldfq_raw(p)
#define stb_kernel(p, v) stb_raw(p, v)
#define stw_kernel(p, v) stw_raw(p, v)
#define stl_kernel(p, v) stl_raw(p, v)
#define stq_kernel(p, v) stq_raw(p, v)
#define stfl_kernel(p, v) stfl_raw(p, v)
#endif /* defined(CONFIG_USER_ONLY) */
/* page related stuff */
extern unsigned long qemu_real_host_page_size;
extern unsigned long qemu_host_page_bits;
extern unsigned long qemu_host_page_size;
extern unsigned long qemu_host_page_mask;
/* same as PROT_xxx */
#define PAGE_READ 0x0001
#define PAGE_WRITE 0x0002
#define PAGE_EXEC 0x0004
#define PAGE_VALID 0x0008
/* original state of the write flag (used when tracking self-modifying
code */
#define PAGE_WRITE_ORG 0x0010
int page_get_flags(unsigned long address);
#define SINGLE_CPU_DEFINES
#ifdef SINGLE_CPU_DEFINES
#if defined(TARGET_I386)
#define CPUState CPUX86State
#define cpu_init cpu_x86_init
#define cpu_exec cpu_x86_exec
#define cpu_gen_code cpu_x86_gen_code
#elif defined(TARGET_ARM)
#define CPUState CPUARMState
#define cpu_init cpu_arm_init
#define cpu_exec cpu_arm_exec
#define cpu_gen_code cpu_arm_gen_code
#elif defined(TARGET_SPARC)
#define CPUState CPUSPARCState
#define cpu_init cpu_sparc_init
#define cpu_exec cpu_sparc_exec
#define cpu_gen_code cpu_sparc_gen_code
#elif defined(TARGET_PPC)
#define CPUState CPUPPCState
#define cpu_init cpu_ppc_init
#define cpu_exec cpu_ppc_exec
#define cpu_gen_code cpu_ppc_gen_code
#else
#endif
#endif /* SINGLE_CPU_DEFINES */
int flags);
extern CPUState *cpu_single_env;
extern int code_copy_enabled;
#ifdef VBOX
/** Executes a single instruction. cpu_exec() will normally return EXCP_SINGLE_INSTR. */
#define CPU_INTERRUPT_SINGLE_INSTR 0x0040
/** Executing a CPU_INTERRUPT_SINGLE_INSTR request, quit the cpu_loop. (for exceptions and suchlike) */
#define CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT 0x0080
/** VM execution was interrupted by VMR3Reset, VMR3Suspend or VMR3PowerOff. */
#define CPU_INTERRUPT_RC 0x0100
/** Exit current TB to process an external interrupt request (also in op.c!!) */
#define CPU_INTERRUPT_EXTERNAL_EXIT 0x0200
/** Exit current TB to process an external interrupt request (also in op.c!!) */
#define CPU_INTERRUPT_EXTERNAL_HARD 0x0400
/** Exit current TB to process an external interrupt request (also in op.c!!) */
#define CPU_INTERRUPT_EXTERNAL_TIMER 0x0800
/** Exit current TB to process an external interrupt request (also in op.c!!) */
#define CPU_INTERRUPT_EXTERNAL_DMA 0x1000
#endif /* VBOX */
/* Return the physical page corresponding to a virtual one. Use it
only for debugging because no protection checks are done. Return -1
if no page found. */
#define CPU_LOG_TB_OUT_ASM (1 << 0)
/* define log items */
typedef struct CPULogItem {
int mask;
const char *name;
const char *help;
} CPULogItem;
extern CPULogItem cpu_log_items[];
void cpu_set_log(int log_flags);
void cpu_set_log_filename(const char *filename);
int cpu_str_to_log_mask(const char *str);
/* IO ports API */
/* NOTE: as these functions may be even used when there is an isa
brige on non x86 targets, we always defined them */
#ifndef NO_CPU_IO_DEFS
#endif
/* memory API */
#if !defined(VBOX)
extern int phys_ram_fd;
#endif /* !VBOX */
extern int phys_ram_size;
#ifndef VBOX
extern uint8_t *phys_ram_base;
#endif
extern uint8_t *phys_ram_dirty;
/* physical memory access */
#define IO_MEM_NB_ENTRIES 256
#define IO_MEM_SHIFT 4
#ifdef VBOX
#endif
unsigned long size,
unsigned long phys_offset);
int cpu_register_io_memory(int io_index,
void *opaque);
{
}
{
}
/* read dirty bit (return 0 or 1) */
{
}
{
}
void dump_exec_info(FILE *f,
#ifdef VBOX
#endif
#endif /* CPU_ALL_H */