mirror of
https://github.com/qemu/qemu.git
synced 2024-11-25 03:43:37 +08:00
sparc support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@119 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
a98fd896cd
commit
d014c98c8d
@ -180,6 +180,12 @@ typedef struct CPUX86State {
|
||||
|
||||
/* emulator internal variables */
|
||||
CPU86_LDouble ft0;
|
||||
union {
|
||||
float f;
|
||||
double d;
|
||||
int i32;
|
||||
int64_t i64;
|
||||
} fp_convert;
|
||||
|
||||
/* segments */
|
||||
uint32_t segs[6]; /* selector values */
|
||||
|
191
dyngen.c
191
dyngen.c
@ -65,6 +65,20 @@
|
||||
#define elf_check_arch(x) ((x) == EM_IA_64)
|
||||
#define ELF_USES_RELOCA
|
||||
|
||||
#elif defined(HOST_SPARC)
|
||||
|
||||
#define ELF_CLASS ELFCLASS32
|
||||
#define ELF_ARCH EM_SPARC
|
||||
#define elf_check_arch(x) ((x) == EM_SPARC || (x) == EM_SPARC32PLUS)
|
||||
#define ELF_USES_RELOCA
|
||||
|
||||
#elif defined(HOST_SPARC64)
|
||||
|
||||
#define ELF_CLASS ELFCLASS64
|
||||
#define ELF_ARCH EM_SPARCV9
|
||||
#define elf_check_arch(x) ((x) == EM_SPARCV9)
|
||||
#define ELF_USES_RELOCA
|
||||
|
||||
#else
|
||||
#error unsupported CPU - please update the code
|
||||
#endif
|
||||
@ -326,6 +340,47 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
|
||||
copy_size = p - p_start;
|
||||
}
|
||||
break;
|
||||
case EM_SPARC:
|
||||
case EM_SPARC32PLUS:
|
||||
{
|
||||
uint8_t *p;
|
||||
p = (void *)(p_end - 8);
|
||||
if (p <= p_start)
|
||||
error("empty code for %s", name);
|
||||
if (get32((uint32_t *)(p_start + 0x0)) != 0x9de3bf98)
|
||||
error("save %%sp,-104,%%sp expected at the start of %s "
|
||||
"found [%08x]",
|
||||
name, get32((uint32_t *)(p_start + 0x0)));
|
||||
if (get32((uint32_t *)(p + 0x0)) != 0x81c7e008 ||
|
||||
get32((uint32_t *)(p + 0x4)) != 0x81e80000)
|
||||
error("ret; restore; expected at the end of %s found [%08x:%08x]",
|
||||
name,
|
||||
get32((uint32_t *)(p + 0x0)),
|
||||
get32((uint32_t *)(p + 0x4)));
|
||||
|
||||
copy_size = p - p_start;
|
||||
}
|
||||
break;
|
||||
case EM_SPARCV9:
|
||||
{
|
||||
uint8_t *p;
|
||||
p = (void *)(p_end - 8);
|
||||
if (p <= p_start)
|
||||
error("empty code for %s", name);
|
||||
if (get32((uint32_t *)(p_start + 0x0)) != 0x9de3bf40)
|
||||
error("save %%sp,-192,%%sp expected at the start of %s "
|
||||
"found [%08x]",
|
||||
name, get32((uint32_t *)(p_start + 0x0)));
|
||||
if (get32((uint32_t *)(p + 0x0)) != 0x81cfe008 ||
|
||||
get32((uint32_t *)(p + 0x4)) != 0x01000000)
|
||||
error("rett %%i7+8; nop; expected at the end of %s "
|
||||
"found [%08x:%08x]",
|
||||
name,
|
||||
get32((uint32_t *)(p + 0x0)),
|
||||
get32((uint32_t *)(p + 0x4)));
|
||||
copy_size = p - p_start;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error("unknown ELF architecture");
|
||||
}
|
||||
@ -375,6 +430,14 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
|
||||
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
|
||||
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
|
||||
if (!strstart(sym_name, "__op_param", &p)) {
|
||||
#if defined(HOST_SPARC)
|
||||
if (sym_name[0] == '.') {
|
||||
fprintf(outfile,
|
||||
"extern char __dot_%s __asm__(\"%s\");\n",
|
||||
sym_name+1, sym_name);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
fprintf(outfile, "extern char %s;\n", sym_name);
|
||||
}
|
||||
}
|
||||
@ -554,6 +617,126 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(HOST_SPARC)
|
||||
{
|
||||
char name[256];
|
||||
int type;
|
||||
int addend;
|
||||
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
|
||||
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
|
||||
sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
|
||||
if (strstart(sym_name, "__op_param", &p)) {
|
||||
snprintf(name, sizeof(name), "param%s", p);
|
||||
} else {
|
||||
if (sym_name[0] == '.')
|
||||
snprintf(name, sizeof(name),
|
||||
"(long)(&__dot_%s)",
|
||||
sym_name + 1);
|
||||
else
|
||||
snprintf(name, sizeof(name),
|
||||
"(long)(&%s)", sym_name);
|
||||
}
|
||||
type = ELF32_R_TYPE(rel->r_info);
|
||||
addend = rel->r_addend;
|
||||
switch(type) {
|
||||
case R_SPARC_32:
|
||||
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
|
||||
rel->r_offset - offset, name, addend);
|
||||
break;
|
||||
case R_SPARC_HI22:
|
||||
fprintf(outfile,
|
||||
" *(uint32_t *)(gen_code_ptr + %d) = "
|
||||
"((*(uint32_t *)(gen_code_ptr + %d)) "
|
||||
" & ~0x3fffff) "
|
||||
" | ((%s + %d) & 0x3fffff);\n",
|
||||
rel->r_offset - offset,
|
||||
rel->r_offset - offset,
|
||||
name, addend);
|
||||
break;
|
||||
case R_SPARC_LO10:
|
||||
fprintf(outfile,
|
||||
" *(uint32_t *)(gen_code_ptr + %d) = "
|
||||
"((*(uint32_t *)(gen_code_ptr + %d)) "
|
||||
" & ~0x3ff) "
|
||||
" | ((%s + %d) & 0x3ff);\n",
|
||||
rel->r_offset - offset,
|
||||
rel->r_offset - offset,
|
||||
name, addend);
|
||||
break;
|
||||
case R_SPARC_WDISP30:
|
||||
fprintf(outfile,
|
||||
" *(uint32_t *)(gen_code_ptr + %d) = "
|
||||
"((*(uint32_t *)(gen_code_ptr + %d)) "
|
||||
" & ~0x3fffffff) "
|
||||
" | ((((%s + %d) - (long)gen_code_ptr)>>2) "
|
||||
" & 0x3fffffff);\n",
|
||||
rel->r_offset - offset,
|
||||
rel->r_offset - offset,
|
||||
name, addend);
|
||||
break;
|
||||
default:
|
||||
error("unsupported sparc relocation (%d)", type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(HOST_SPARC64)
|
||||
{
|
||||
char name[256];
|
||||
int type;
|
||||
int addend;
|
||||
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
|
||||
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
|
||||
sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
|
||||
if (strstart(sym_name, "__op_param", &p)) {
|
||||
snprintf(name, sizeof(name), "param%s", p);
|
||||
} else {
|
||||
snprintf(name, sizeof(name), "(long)(&%s)", sym_name);
|
||||
}
|
||||
type = ELF64_R_TYPE(rel->r_info);
|
||||
addend = rel->r_addend;
|
||||
switch(type) {
|
||||
case R_SPARC_32:
|
||||
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
|
||||
rel->r_offset - offset, name, addend);
|
||||
break;
|
||||
case R_SPARC_HI22:
|
||||
fprintf(outfile,
|
||||
" *(uint32_t *)(gen_code_ptr + %d) = "
|
||||
"((*(uint32_t *)(gen_code_ptr + %d)) "
|
||||
" & ~0x3fffff) "
|
||||
" | ((%s + %d) & 0x3fffff);\n",
|
||||
rel->r_offset - offset,
|
||||
rel->r_offset - offset,
|
||||
name, addend);
|
||||
break;
|
||||
case R_SPARC_LO10:
|
||||
fprintf(outfile,
|
||||
" *(uint32_t *)(gen_code_ptr + %d) = "
|
||||
"((*(uint32_t *)(gen_code_ptr + %d)) "
|
||||
" & ~0x3ff) "
|
||||
" | ((%s + %d) & 0x3ff);\n",
|
||||
rel->r_offset - offset,
|
||||
rel->r_offset - offset,
|
||||
name, addend);
|
||||
break;
|
||||
case R_SPARC_WDISP30:
|
||||
fprintf(outfile,
|
||||
" *(uint32_t *)(gen_code_ptr + %d) = "
|
||||
"((*(uint32_t *)(gen_code_ptr + %d)) "
|
||||
" & ~0x3fffffff) "
|
||||
" | ((((%s + %d) - (long)gen_code_ptr)>>2) "
|
||||
" & 0x3fffffff);\n",
|
||||
rel->r_offset - offset,
|
||||
rel->r_offset - offset,
|
||||
name, addend);
|
||||
break;
|
||||
default:
|
||||
error("unsupported sparc64 relocation (%d)", type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#error unsupported CPU
|
||||
#endif
|
||||
@ -759,6 +942,14 @@ fprintf(outfile,
|
||||
case EM_IA_64:
|
||||
fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x00840008; /* br.ret.sptk.many b0;; */\n");
|
||||
break;
|
||||
case EM_SPARC:
|
||||
case EM_SPARC32PLUS:
|
||||
case EM_SPARCV9:
|
||||
/* Fill the delay slot. */
|
||||
fprintf(outfile, "*((uint32_t *)gen_code_ptr) = *((uint32_t *)gen_code_ptr - 1); /* delay slot */\n");
|
||||
fprintf(outfile, "*((uint32_t *)gen_code_ptr - 1) = 0x81c3e008; /* retl */\n");
|
||||
fprintf(outfile, "gen_code_ptr++;\n");
|
||||
break;
|
||||
default:
|
||||
error("unknown ELF architecture");
|
||||
}
|
||||
|
14
exec-i386.c
14
exec-i386.c
@ -121,6 +121,20 @@ int testandset (int *p)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __sparc__
|
||||
static inline int testandset (int *p)
|
||||
{
|
||||
int ret;
|
||||
|
||||
__asm__ __volatile__("ldstub [%1], %0"
|
||||
: "=r" (ret)
|
||||
: "r" (p)
|
||||
: "memory");
|
||||
|
||||
return (ret ? 1 : 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
int global_cpu_lock = 0;
|
||||
|
||||
void cpu_lock(void)
|
||||
|
@ -93,6 +93,7 @@ register unsigned int T0 asm("l0");
|
||||
register unsigned int T1 asm("l1");
|
||||
register unsigned int A0 asm("l2");
|
||||
register struct CPUX86State *env asm("l3");
|
||||
#define USE_FP_CONVERT
|
||||
#endif
|
||||
#ifdef __s390__
|
||||
register unsigned int T0 asm("r7");
|
||||
@ -160,6 +161,10 @@ register struct CPUX86State *env asm("r27");
|
||||
#define ST(n) (env->fpregs[(env->fpstt + (n)) & 7])
|
||||
#define ST1 ST(1)
|
||||
|
||||
#ifdef USE_FP_CONVERT
|
||||
#define FP_CONVERT (env->fp_convert)
|
||||
#endif
|
||||
|
||||
extern int __op_param1, __op_param2, __op_param3;
|
||||
#define PARAM1 ((long)(&__op_param1))
|
||||
#define PARAM2 ((long)(&__op_param2))
|
||||
|
82
op-i386.c
82
op-i386.c
@ -1605,12 +1605,22 @@ typedef union {
|
||||
|
||||
void OPPROTO op_flds_FT0_A0(void)
|
||||
{
|
||||
#ifdef USE_FP_CONVERT
|
||||
FP_CONVERT.i32 = ldl((void *)A0);
|
||||
FT0 = FP_CONVERT.f;
|
||||
#else
|
||||
FT0 = ldfl((void *)A0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OPPROTO op_fldl_FT0_A0(void)
|
||||
{
|
||||
#ifdef USE_FP_CONVERT
|
||||
FP_CONVERT.i64 = ldq((void *)A0);
|
||||
FT0 = FP_CONVERT.d;
|
||||
#else
|
||||
FT0 = ldfq((void *)A0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* helpers are needed to avoid static constant reference. XXX: find a better way */
|
||||
@ -1650,17 +1660,32 @@ void OPPROTO op_fildll_FT0_A0(void)
|
||||
|
||||
void OPPROTO op_fild_FT0_A0(void)
|
||||
{
|
||||
#ifdef USE_FP_CONVERT
|
||||
FP_CONVERT.i32 = ldsw((void *)A0);
|
||||
FT0 = (CPU86_LDouble)FP_CONVERT.i32;
|
||||
#else
|
||||
FT0 = (CPU86_LDouble)ldsw((void *)A0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OPPROTO op_fildl_FT0_A0(void)
|
||||
{
|
||||
#ifdef USE_FP_CONVERT
|
||||
FP_CONVERT.i32 = (int32_t) ldl((void *)A0);
|
||||
FT0 = (CPU86_LDouble)FP_CONVERT.i32;
|
||||
#else
|
||||
FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
|
||||
#endif
|
||||
}
|
||||
|
||||
void OPPROTO op_fildll_FT0_A0(void)
|
||||
{
|
||||
#ifdef USE_FP_CONVERT
|
||||
FP_CONVERT.i64 = (int64_t) ldq((void *)A0);
|
||||
FT0 = (CPU86_LDouble)FP_CONVERT.i64;
|
||||
#else
|
||||
FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1668,12 +1693,22 @@ void OPPROTO op_fildll_FT0_A0(void)
|
||||
|
||||
void OPPROTO op_flds_ST0_A0(void)
|
||||
{
|
||||
#ifdef USE_FP_CONVERT
|
||||
FP_CONVERT.i32 = ldl((void *)A0);
|
||||
ST0 = FP_CONVERT.f;
|
||||
#else
|
||||
ST0 = ldfl((void *)A0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OPPROTO op_fldl_ST0_A0(void)
|
||||
{
|
||||
#ifdef USE_FP_CONVERT
|
||||
FP_CONVERT.i64 = ldq((void *)A0);
|
||||
ST0 = FP_CONVERT.d;
|
||||
#else
|
||||
ST0 = ldfq((void *)A0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_X86LDOUBLE
|
||||
@ -1738,17 +1773,32 @@ void OPPROTO op_fildll_ST0_A0(void)
|
||||
|
||||
void OPPROTO op_fild_ST0_A0(void)
|
||||
{
|
||||
#ifdef USE_FP_CONVERT
|
||||
FP_CONVERT.i32 = ldsw((void *)A0);
|
||||
ST0 = (CPU86_LDouble)FP_CONVERT.i32;
|
||||
#else
|
||||
ST0 = (CPU86_LDouble)ldsw((void *)A0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OPPROTO op_fildl_ST0_A0(void)
|
||||
{
|
||||
#ifdef USE_FP_CONVERT
|
||||
FP_CONVERT.i32 = (int32_t) ldl((void *)A0);
|
||||
ST0 = (CPU86_LDouble)FP_CONVERT.i32;
|
||||
#else
|
||||
ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
|
||||
#endif
|
||||
}
|
||||
|
||||
void OPPROTO op_fildll_ST0_A0(void)
|
||||
{
|
||||
#ifdef USE_FP_CONVERT
|
||||
FP_CONVERT.i64 = (int64_t) ldq((void *)A0);
|
||||
ST0 = (CPU86_LDouble)FP_CONVERT.i64;
|
||||
#else
|
||||
ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1757,7 +1807,12 @@ void OPPROTO op_fildll_ST0_A0(void)
|
||||
|
||||
void OPPROTO op_fsts_ST0_A0(void)
|
||||
{
|
||||
#ifdef USE_FP_CONVERT
|
||||
FP_CONVERT.d = ST0;
|
||||
stfl((void *)A0, FP_CONVERT.f);
|
||||
#else
|
||||
stfl((void *)A0, (float)ST0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OPPROTO op_fstl_ST0_A0(void)
|
||||
@ -1792,22 +1847,43 @@ void OPPROTO op_fstt_ST0_A0(void)
|
||||
|
||||
void OPPROTO op_fist_ST0_A0(void)
|
||||
{
|
||||
#if defined(__sparc__) && !defined(__sparc_v9__)
|
||||
register CPU86_LDouble d asm("o0");
|
||||
#else
|
||||
CPU86_LDouble d;
|
||||
#endif
|
||||
int val;
|
||||
val = lrint(ST0);
|
||||
|
||||
d = ST0;
|
||||
val = lrint(d);
|
||||
stw((void *)A0, val);
|
||||
}
|
||||
|
||||
void OPPROTO op_fistl_ST0_A0(void)
|
||||
{
|
||||
#if defined(__sparc__) && !defined(__sparc_v9__)
|
||||
register CPU86_LDouble d asm("o0");
|
||||
#else
|
||||
CPU86_LDouble d;
|
||||
#endif
|
||||
int val;
|
||||
val = lrint(ST0);
|
||||
|
||||
d = ST0;
|
||||
val = lrint(d);
|
||||
stl((void *)A0, val);
|
||||
}
|
||||
|
||||
void OPPROTO op_fistll_ST0_A0(void)
|
||||
{
|
||||
#if defined(__sparc__) && !defined(__sparc_v9__)
|
||||
register CPU86_LDouble d asm("o0");
|
||||
#else
|
||||
CPU86_LDouble d;
|
||||
#endif
|
||||
int64_t val;
|
||||
val = llrint(ST0);
|
||||
|
||||
d = ST0;
|
||||
val = llrint(d);
|
||||
stq((void *)A0, val);
|
||||
}
|
||||
|
||||
|
@ -89,6 +89,21 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __sparc__
|
||||
|
||||
static void inline flush_icache_range(unsigned long start, unsigned long stop)
|
||||
{
|
||||
unsigned long p;
|
||||
|
||||
p = start & ~(8UL - 1UL);
|
||||
stop = (stop + (8UL - 1UL)) & ~(8UL - 1UL);
|
||||
|
||||
for (; p < stop; p += 8)
|
||||
__asm__ __volatile__("flush\t%0" : : "r" (p));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
extern FILE *logfile;
|
||||
extern int loglevel;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user