On 02/13/2010 06:58 PM, Blue Swirl wrote:
V9 ABI gives more registers to application use.

Except that glibc uses those---in theory, as I see it, it should be compiled with fixed g2 and g3 to leave them to the application. I get it now.

It may be possible to make the workaround a big less ugly (I'm thinking of avoiding #undef/#define by using assembly). I made a patch (see attachment, just FYI), maybe sometime I'll try it using self-virtualized qemu.

Paolo
commit 59ca12838278bed97ce5cc311f90ddfec7953047
Author: Paolo Bonzini <pbonz...@redhat.com>
Date:   Sat Feb 13 21:13:12 2010 +0100

    make sparc workaround less ugly
    
    Not-quite-signed-off-by: Paolo Bonzini <pbonz...@redhat.com>

diff --git a/cpu-exec.c b/cpu-exec.c
index badd5d7..01b7143 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -39,9 +39,14 @@
 #endif
 
 #if defined(__sparc__) && !defined(CONFIG_SOLARIS)
-// Work around ugly bugs in glibc that mangle global register contents
-#undef env
+/* glibc will mangle global register contents.  To work around this,
+ * we avoid using the global register in this file, and place back
+ * cpu_single_env in AREG0 before giving control to target-* routines.
+ */
+#define export_env()   asm ("mov %0, %%" AREG0 : : "r" (cpu_single_env) : 
AREG0); 
 #define env cpu_single_env
+#else
+#define export_env()
 #endif
 
 int tb_invalidated_flag;
@@ -257,11 +262,7 @@ int cpu_exec(CPUState *env1)
     /* prepare setjmp context for exception handling */
     for(;;) {
         if (setjmp(env->jmp_env) == 0) {
-#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
-#undef env
-                    env = cpu_single_env;
-#define env cpu_single_env
-#endif
+            export_env();
             /* if an exception is pending, we execute it here */
             if (env->exception_index >= 0) {
                 if (env->exception_index >= EXCP_INTERRUPT) {
@@ -387,11 +388,7 @@ int cpu_exec(CPUState *env1)
                             env->interrupt_request &= ~(CPU_INTERRUPT_HARD | 
CPU_INTERRUPT_VIRQ);
                             intno = cpu_get_pic_interrupt(env);
                             qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing 
hardware INT=0x%02x\n", intno);
-#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
-#undef env
-                    env = cpu_single_env;
-#define env cpu_single_env
-#endif
+                            export_env();
                             do_interrupt(intno, 0, 0, 0, 1);
                             /* ensure that no TB jump will be modified as
                                the program flow was changed */
@@ -603,12 +600,8 @@ int cpu_exec(CPUState *env1)
                 if (!unlikely (env->exit_request)) {
                     env->current_tb = tb;
                     tc_ptr = tb->tc_ptr;
-                /* execute the generated code */
-#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
-#undef env
-                    env = cpu_single_env;
-#define env cpu_single_env
-#endif
+                    /* execute the generated code */
+                    export_env();
                     next_tb = tcg_qemu_tb_exec(tc_ptr);
                     env->current_tb = NULL;
                     if ((next_tb & 3) == 2) {

Reply via email to