Merge branch 'tcg-sparc' of git://repo.or.cz/qemu/rth

* 'tcg-sparc' of git://repo.or.cz/qemu/rth:
  tcg-sparc: Preserve branch destinations during retranslation
  tcg-sparc: Fix and enable direct TB chaining.
  tcg-sparc: Add %g/%o registers to alloc_order
  tcg-sparc: Use defines for temporaries.
  tcg-sparc: Mask shift immediates to avoid illegal insns.
  tcg-sparc: Clean up cruft stemming from attempts to use global registers.
  tcg-sparc: Change AREG0 in generated code to %i0.
  tcg-sparc: Support GUEST_BASE.
  tcg-sparc: Fix qemu_ld/st to handle 32-bit host.
  tcg-sparc: Assume v9 cpu always, i.e. force v8plus in 32-bit mode.
  tcg-sparc: Don't MAP_FIXED on top of the program
  tcg-sparc: Fix ADDX opcode.
  tcg-sparc: Hack in qemu_ld/st64 for 32-bit.
  linux-user: Use memcpy in get_user/put_user.
This commit is contained in:
Blue Swirl 2012-09-22 17:59:15 +00:00
commit 04cbbdeefd
9 changed files with 521 additions and 629 deletions

52
configure vendored
View File

@ -111,7 +111,6 @@ source_path=`dirname "$0"`
cpu="" cpu=""
interp_prefix="/usr/gnemul/qemu-%M" interp_prefix="/usr/gnemul/qemu-%M"
static="no" static="no"
sparc_cpu=""
cross_prefix="" cross_prefix=""
audio_drv_list="" audio_drv_list=""
audio_card_list="ac97 es1370 sb16 hda" audio_card_list="ac97 es1370 sb16 hda"
@ -241,21 +240,6 @@ for opt do
;; ;;
--disable-debug-info) debug_info="no" --disable-debug-info) debug_info="no"
;; ;;
--sparc_cpu=*)
sparc_cpu="$optarg"
case $sparc_cpu in
v7|v8|v8plus|v8plusa)
cpu="sparc"
;;
v9)
cpu="sparc64"
;;
*)
echo "undefined SPARC architecture. Exiting";
exit 1
;;
esac
;;
esac esac
done done
# OS specific # OS specific
@ -343,8 +327,6 @@ elif check_define __i386__ ; then
elif check_define __x86_64__ ; then elif check_define __x86_64__ ; then
cpu="x86_64" cpu="x86_64"
elif check_define __sparc__ ; then elif check_define __sparc__ ; then
# We can't check for 64 bit (when gcc is biarch) or V8PLUSA
# They must be specified using --sparc_cpu
if check_define __arch64__ ; then if check_define __arch64__ ; then
cpu="sparc64" cpu="sparc64"
else else
@ -792,8 +774,6 @@ for opt do
;; ;;
--enable-uname-release=*) uname_release="$optarg" --enable-uname-release=*) uname_release="$optarg"
;; ;;
--sparc_cpu=*)
;;
--enable-werror) werror="yes" --enable-werror) werror="yes"
;; ;;
--disable-werror) werror="no" --disable-werror) werror="no"
@ -881,35 +861,17 @@ for opt do
esac esac
done done
#
# If cpu ~= sparc and sparc_cpu hasn't been defined, plug in the right
# QEMU_CFLAGS/LDFLAGS (assume sparc_v8plus for 32-bit and sparc_v9 for 64-bit)
#
host_guest_base="no" host_guest_base="no"
case "$cpu" in case "$cpu" in
sparc) case $sparc_cpu in sparc)
v7|v8)
QEMU_CFLAGS="-mcpu=${sparc_cpu} -D__sparc_${sparc_cpu}__ $QEMU_CFLAGS"
;;
v8plus|v8plusa)
QEMU_CFLAGS="-mcpu=ultrasparc -D__sparc_${sparc_cpu}__ $QEMU_CFLAGS"
;;
*) # sparc_cpu not defined in the command line
QEMU_CFLAGS="-mcpu=ultrasparc -D__sparc_v8plus__ $QEMU_CFLAGS"
esac
LDFLAGS="-m32 $LDFLAGS" LDFLAGS="-m32 $LDFLAGS"
QEMU_CFLAGS="-m32 -ffixed-g2 -ffixed-g3 $QEMU_CFLAGS" QEMU_CFLAGS="-m32 -mcpu=ultrasparc $QEMU_CFLAGS"
if test "$solaris" = "no" ; then host_guest_base="yes"
QEMU_CFLAGS="-ffixed-g1 -ffixed-g6 $QEMU_CFLAGS"
fi
;; ;;
sparc64) sparc64)
QEMU_CFLAGS="-m64 -mcpu=ultrasparc -D__sparc_v9__ $QEMU_CFLAGS"
LDFLAGS="-m64 $LDFLAGS" LDFLAGS="-m64 $LDFLAGS"
QEMU_CFLAGS="-ffixed-g5 -ffixed-g6 -ffixed-g7 $QEMU_CFLAGS" QEMU_CFLAGS="-m64 -mcpu=ultrasparc $QEMU_CFLAGS"
if test "$solaris" != "no" ; then host_guest_base="yes"
QEMU_CFLAGS="-ffixed-g1 $QEMU_CFLAGS"
fi
;; ;;
s390) s390)
QEMU_CFLAGS="-m31 -march=z990 $QEMU_CFLAGS" QEMU_CFLAGS="-m31 -march=z990 $QEMU_CFLAGS"
@ -4131,10 +4093,6 @@ fi
if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then
case "$ARCH" in case "$ARCH" in
sparc)
# -static is used to avoid g1/g3 usage by the dynamic linker
ldflags="$linker_script -static $ldflags"
;;
alpha | s390x) alpha | s390x)
# The default placement of the application is fine. # The default placement of the application is fine.
;; ;;

View File

@ -316,9 +316,7 @@ void disas(FILE *out, void *code, unsigned long size)
print_insn = print_insn_alpha; print_insn = print_insn_alpha;
#elif defined(__sparc__) #elif defined(__sparc__)
print_insn = print_insn_sparc; print_insn = print_insn_sparc;
#if defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__)
disasm_info.mach = bfd_mach_sparc_v9b; disasm_info.mach = bfd_mach_sparc_v9b;
#endif
#elif defined(__arm__) #elif defined(__arm__)
print_insn = print_insn_arm; print_insn = print_insn_arm;
#elif defined(__MIPSEB__) #elif defined(__MIPSEB__)

View File

@ -132,9 +132,10 @@ static inline void tlb_flush(CPUArchState *env, int flush_global)
#define CODE_GEN_AVG_BLOCK_SIZE 64 #define CODE_GEN_AVG_BLOCK_SIZE 64
#endif #endif
#if defined(_ARCH_PPC) || defined(__x86_64__) || defined(__arm__) || defined(__i386__) #if defined(__arm__) || defined(_ARCH_PPC) \
#define USE_DIRECT_JUMP || defined(__x86_64__) || defined(__i386__) \
#elif defined(CONFIG_TCG_INTERPRETER) || defined(__sparc__) \
|| defined(CONFIG_TCG_INTERPRETER)
#define USE_DIRECT_JUMP #define USE_DIRECT_JUMP
#endif #endif
@ -244,6 +245,8 @@ static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
__asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg)); __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
#endif #endif
} }
#elif defined(__sparc__)
void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr);
#else #else
#error tb_set_jmp_target1 is missing #error tb_set_jmp_target1 is missing
#endif #endif

12
exec.c
View File

@ -86,7 +86,7 @@ static int nb_tbs;
/* any access to the tbs or the page table must use this lock */ /* any access to the tbs or the page table must use this lock */
spinlock_t tb_lock = SPIN_LOCK_UNLOCKED; spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
#if defined(__arm__) || defined(__sparc_v9__) #if defined(__arm__) || defined(__sparc__)
/* The prologue must be reachable with a direct jump. ARM and Sparc64 /* The prologue must be reachable with a direct jump. ARM and Sparc64
have limited branch ranges (possibly also PPC) so place it in a have limited branch ranges (possibly also PPC) so place it in a
section close to code segment. */ section close to code segment. */
@ -541,10 +541,9 @@ static void code_gen_alloc(unsigned long tb_size)
/* Cannot map more than that */ /* Cannot map more than that */
if (code_gen_buffer_size > (800 * 1024 * 1024)) if (code_gen_buffer_size > (800 * 1024 * 1024))
code_gen_buffer_size = (800 * 1024 * 1024); code_gen_buffer_size = (800 * 1024 * 1024);
#elif defined(__sparc_v9__) #elif defined(__sparc__) && HOST_LONG_BITS == 64
// Map the buffer below 2G, so we can use direct calls and branches // Map the buffer below 2G, so we can use direct calls and branches
flags |= MAP_FIXED; start = (void *) 0x40000000UL;
start = (void *) 0x60000000UL;
if (code_gen_buffer_size > (512 * 1024 * 1024)) if (code_gen_buffer_size > (512 * 1024 * 1024))
code_gen_buffer_size = (512 * 1024 * 1024); code_gen_buffer_size = (512 * 1024 * 1024);
#elif defined(__arm__) #elif defined(__arm__)
@ -582,10 +581,9 @@ static void code_gen_alloc(unsigned long tb_size)
/* Cannot map more than that */ /* Cannot map more than that */
if (code_gen_buffer_size > (800 * 1024 * 1024)) if (code_gen_buffer_size > (800 * 1024 * 1024))
code_gen_buffer_size = (800 * 1024 * 1024); code_gen_buffer_size = (800 * 1024 * 1024);
#elif defined(__sparc_v9__) #elif defined(__sparc__) && HOST_LONG_BITS == 64
// Map the buffer below 2G, so we can use direct calls and branches // Map the buffer below 2G, so we can use direct calls and branches
flags |= MAP_FIXED; addr = (void *) 0x40000000UL;
addr = (void *) 0x60000000UL;
if (code_gen_buffer_size > (512 * 1024 * 1024)) { if (code_gen_buffer_size > (512 * 1024 * 1024)) {
code_gen_buffer_size = (512 * 1024 * 1024); code_gen_buffer_size = (512 * 1024 * 1024);
} }

View File

@ -289,46 +289,29 @@ static inline int access_ok(int type, abi_ulong addr, abi_ulong size)
* struct has been locked - usually with lock_user_struct(). * struct has been locked - usually with lock_user_struct().
*/ */
#define __put_user(x, hptr)\ #define __put_user(x, hptr)\
({\ ({ __typeof(*hptr) pu_ = (x);\
switch(sizeof(*hptr)) {\ switch(sizeof(*hptr)) {\
case 1:\ case 1: break;\
*(uint8_t *)(hptr) = (uint8_t)(typeof(*hptr))(x);\ case 2: pu_ = tswap16(pu_); break; \
break;\ case 4: pu_ = tswap32(pu_); break; \
case 2:\ case 8: pu_ = tswap64(pu_); break; \
*(uint16_t *)(hptr) = tswap16((uint16_t)(typeof(*hptr))(x));\ default: abort();\
break;\
case 4:\
*(uint32_t *)(hptr) = tswap32((uint32_t)(typeof(*hptr))(x));\
break;\
case 8:\
*(uint64_t *)(hptr) = tswap64((typeof(*hptr))(x));\
break;\
default:\
abort();\
}\ }\
memcpy(hptr, &pu_, sizeof(pu_)); \
0;\ 0;\
}) })
#define __get_user(x, hptr) \ #define __get_user(x, hptr) \
({\ ({ __typeof(*hptr) gu_; \
memcpy(&gu_, hptr, sizeof(gu_)); \
switch(sizeof(*hptr)) {\ switch(sizeof(*hptr)) {\
case 1:\ case 1: break; \
x = (typeof(*hptr))*(uint8_t *)(hptr);\ case 2: gu_ = tswap16(gu_); break; \
break;\ case 4: gu_ = tswap32(gu_); break; \
case 2:\ case 8: gu_ = tswap64(gu_); break; \
x = (typeof(*hptr))tswap16(*(uint16_t *)(hptr));\ default: abort();\
break;\
case 4:\
x = (typeof(*hptr))tswap32(*(uint32_t *)(hptr));\
break;\
case 8:\
x = (typeof(*hptr))tswap64(*(uint64_t *)(hptr));\
break;\
default:\
/* avoid warning */\
x = 0;\
abort();\
}\ }\
(x) = gu_; \
0;\ 0;\
}) })

View File

@ -218,7 +218,7 @@ static inline int64_t cpu_get_real_ticks(void)
return val; return val;
} }
#elif defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__) #elif defined(__sparc__)
static inline int64_t cpu_get_real_ticks (void) static inline int64_t cpu_get_real_ticks (void)
{ {
@ -227,6 +227,8 @@ static inline int64_t cpu_get_real_ticks (void)
asm volatile("rd %%tick,%0" : "=r"(rval)); asm volatile("rd %%tick,%0" : "=r"(rval));
return rval; return rval;
#else #else
/* We need an %o or %g register for this. For recent enough gcc
there is an "h" constraint for that. Don't bother with that. */
union { union {
uint64_t i64; uint64_t i64;
struct { struct {
@ -234,8 +236,8 @@ static inline int64_t cpu_get_real_ticks (void)
uint32_t low; uint32_t low;
} i32; } i32;
} rval; } rval;
asm volatile("rd %%tick,%1; srlx %1,32,%0" asm volatile("rd %%tick,%%g1; srlx %%g1,32,%0; mov %%g1,%1"
: "=r"(rval.i32.high), "=r"(rval.i32.low)); : "=r"(rval.i32.high), "=r"(rval.i32.low) : : "g1");
return rval.i64; return rval.i64;
#endif #endif
} }

File diff suppressed because it is too large Load Diff

View File

@ -66,22 +66,19 @@ typedef enum {
#define TCG_CT_CONST_S13 0x200 #define TCG_CT_CONST_S13 0x200
/* used for function call generation */ /* used for function call generation */
#define TCG_REG_CALL_STACK TCG_REG_I6 #define TCG_REG_CALL_STACK TCG_REG_O6
#ifdef __arch64__
// Reserve space for AREG0 #if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_STACK_MINFRAME (176 + 4 * (int)sizeof(long) + \ #define TCG_TARGET_STACK_BIAS 2047
TCG_STATIC_CALL_ARGS_SIZE) #define TCG_TARGET_STACK_ALIGN 16
#define TCG_TARGET_CALL_STACK_OFFSET (2047 - 16) #define TCG_TARGET_CALL_STACK_OFFSET (128 + 6*8 + TCG_TARGET_STACK_BIAS)
#define TCG_TARGET_STACK_ALIGN 16
#else #else
// AREG0 + one word for alignment #define TCG_TARGET_STACK_BIAS 0
#define TCG_TARGET_STACK_MINFRAME (92 + (2 + 1) * (int)sizeof(long) + \ #define TCG_TARGET_STACK_ALIGN 8
TCG_STATIC_CALL_ARGS_SIZE) #define TCG_TARGET_CALL_STACK_OFFSET (64 + 4 + 6*4)
#define TCG_TARGET_CALL_STACK_OFFSET TCG_TARGET_STACK_MINFRAME
#define TCG_TARGET_STACK_ALIGN 8
#endif #endif
#ifdef __arch64__ #if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_EXTEND_ARGS 1 #define TCG_TARGET_EXTEND_ARGS 1
#endif #endif
@ -127,13 +124,9 @@ typedef enum {
#define TCG_TARGET_HAS_movcond_i64 0 #define TCG_TARGET_HAS_movcond_i64 0
#endif #endif
#ifdef CONFIG_SOLARIS #define TCG_TARGET_HAS_GUEST_BASE
#define TCG_AREG0 TCG_REG_G2
#elif defined(__sparc_v9__) #define TCG_AREG0 TCG_REG_I0
#define TCG_AREG0 TCG_REG_G5
#else
#define TCG_AREG0 TCG_REG_G6
#endif
static inline void flush_icache_range(tcg_target_ulong start, static inline void flush_icache_range(tcg_target_ulong start,
tcg_target_ulong stop) tcg_target_ulong stop)

View File

@ -1449,7 +1449,8 @@ static void temp_allocate_frame(TCGContext *s, int temp)
{ {
TCGTemp *ts; TCGTemp *ts;
ts = &s->temps[temp]; ts = &s->temps[temp];
#ifndef __sparc_v9__ /* Sparc64 stack is accessed with offset of 2047 */ #if !(defined(__sparc__) && TCG_TARGET_REG_BITS == 64)
/* Sparc64 stack is accessed with offset of 2047 */
s->current_frame_offset = (s->current_frame_offset + s->current_frame_offset = (s->current_frame_offset +
(tcg_target_long)sizeof(tcg_target_long) - 1) & (tcg_target_long)sizeof(tcg_target_long) - 1) &
~(sizeof(tcg_target_long) - 1); ~(sizeof(tcg_target_long) - 1);