Skip to contentSkip to conversation

HPPA (PA-RISC) host support [v2]

PATCH New Stuart Brady 1 participant 1 message Apr 12, 2008 Kbuild

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 HPPA (PA-RISC) host support [v2]

Hi,

The attached patch adds partially working HPPA (PA-RISC) Linux host support. As hppa-dis.c is quite large, and is unchanged, I haven't attached it. It was attached separately with the initial version of this patch, submitted on 2008-03-23.

Changes from the initial version of the patch include the following:

* The instruction masks and values for dyngen prologue/epilogue removal have been corrected and are now properly commented.

* tcg/hppa/relocs.h has been moved into tcg/hppa/tcg-target.h, as there seemed to be no real benefit in having an extra header.

* hppa_process_stubs() and related code has been moved from tcg-target.h into tcg-dyngen.c, as that is the only place in which it is used.

* tcg_out_call() has been implemented.

* tcg_out_qemu_ld() and tcg_out_qemu_st() have been partially implemented. Unaligned loads/stores are not yet handled for linux-user targets, and 64-bit loads/stores and loads/stores with 64-bit target addresses need testing.

* op_sar_i32 had the source/target registers for VEXTRS swapped.

* r3 is now marked as reserved, as it is used as the frame pointer.

* r1, r3 and r18 have been removed from tcg_target_reg_alloc_order[] as they are reserved, and r17, r14, r15, r16 (the dyngen 'AREG' registers) have been added to the end.

* r20 is now used as a temporary register instead of r26, as r26 is used to pass the first argument in a helper call.

* tcg_out_mov() now uses the OR insn instead of LDO, as hppa-dis.c only disassembles the OR form into the COPY psuedo-insn.

Unfortunately, I have found that mips-softmmu emulation only works with this patch if MIPS_SINGLE_STEP is defined. I do not yet understand how this could make a difference.

The i386-softmmu target now starts booting the linux-0.2.img test, but it crashes when entering userspace. Strangely, upon examining the core dump and comparing this to the -d out_asm output in /tmp/qemu.log, it seems that a small section of code is sometimes 'cut out' of the code buffer -- I am not sure why this is happening, but I should probably try the ARM target to eliminate any problems involving dyngen.

I had previously forgotten to mention that sparc32plus-linux-user, sparc64-linux-user and ppc64-softmmu do not yet build, due to problems regarding GCC (and possibly binutils).

Once again, thanks to Randolph Chung for a lot of the dyngen work.

Here's a diffstat of the changes:

 Makefile.target         |    8 
 configure               |    7 
 cpu-all.h               |   11 
 cpu-exec.c              |   29 +
 dis-asm.h               |    4 
 disas.c                 |    2 
 dyngen-exec.h           |    7 
 dyngen.c                |  129 ++++++
 hppa.ld                 |  214 ++++++++++
 tcg/hppa/tcg-target.c   |  980 ++++++++++++++++++++++++++++++++++++++++++++++++
 tcg/hppa/tcg-target.h   |  204 +++++++++
 tcg/i386/tcg-target.c   |    3 
 tcg/sparc/tcg-target.c  |    3 
 tcg/tcg-dyngen.c        |   50 ++
 tcg/tcg.c               |   30 +
 tcg/x86_64/tcg-target.c |    3 
 16 files changed, 1671 insertions(+), 13 deletions(-)

Cheers,

Signature · 1 line
Stuart Brady
configure +7 -0
diff -urpN qemu-orig/configure qemu-new/configure
@@ -50,6 +50,9 @@ case "$cpu" in
   cris)
     cpu="cris"
   ;;
+  parisc|parisc64)
+    cpu="hppa"
+  ;;
   ia64)
     cpu="ia64"
   ;;
@@ -576,6 +579,7 @@ else
 
 # if cross compiling, cannot launch a program, so make a static guess
 if test "$cpu" = "armv4b" \
+     -o "$cpu" = "hppa" \
      -o "$cpu" = "m68k" \
      -o "$cpu" = "mips" \
      -o "$cpu" = "mips64" \
@@ -865,6 +869,9 @@ elif test "$cpu" = "armv4l" ; then
 elif test "$cpu" = "cris" ; then
   echo "ARCH=cris" >> $config_mak
   echo "#define HOST_CRIS 1" >> $config_h
+elif test "$cpu" = "hppa" ; then
+  echo "ARCH=hppa" >> $config_mak
+  echo "#define HOST_HPPA 1" >> $config_h
 elif test "$cpu" = "ia64" ; then
   echo "ARCH=ia64" >> $config_mak
   echo "#define HOST_IA64 1" >> $config_h
cpu-all.h +10 -1
diff -urpN qemu-orig/cpu-all.h qemu-new/cpu-all.h
@@ -20,7 +20,7 @@
 #ifndef CPU_ALL_H
 #define CPU_ALL_H
 
-#if defined(__arm__) || defined(__sparc__) || defined(__mips__)
+#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__)
 #define WORDS_ALIGNED
 #endif
 
@@ -952,6 +952,15 @@ static inline int64_t cpu_get_real_ticks
     return val;
 }
 
+#elif defined(__hppa__)
+
+static inline int64_t cpu_get_real_ticks(void)
+{
+    int val;
+    asm volatile ("mfctl %%cr16, %0" : "=r"(val));
+    return val;
+}
+
 #elif defined(__ia64)
 
 static inline int64_t cpu_get_real_ticks(void)
cpu-exec.c +29 -0
diff -urpN qemu-orig/cpu-exec.c qemu-new/cpu-exec.c
@@ -657,6 +657,17 @@ int cpu_exec(CPUState *env1)
                                        "o0", "o1", "o2", "o3", "o4", "o5",
                                        "l0", "l1", "l2", "l3", "l4", "l5",
                                        "l6", "l7");
+#elif defined(__hppa__)
+                asm volatile ("ble  0(%%sr4,%1)\n"
+                              "copy %%r31,%%r18\n"
+                              "copy %%r28,%0\n"
+                              : "=r" (T0)
+                              : "r" (gen_func)
+                              : "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+                                "r8", "r9", "r10", "r11", "r12", "r13",
+                                "r18", "r19", "r20", "r21", "r22", "r23",
+                                "r24", "r25", "r26", "r27", "r28", "r29",
+                                "r30", "r31");
 #elif defined(__arm__)
                 asm volatile ("mov pc, %0\n\t"
                               ".global exec_loop\n\t"
@@ -1488,6 +1499,24 @@ int cpu_signal_handler(int host_signum, 
                              is_write, &uc->uc_sigmask, puc);
 }
 
+#elif defined(__hppa__)
+
+int cpu_signal_handler(int host_signum, void *pinfo,
+                       void *puc)
+{
+    struct siginfo *info = pinfo; 
+    struct ucontext *uc = puc;
+    unsigned long pc;
+    int is_write;
+    
+    pc = uc->uc_mcontext.sc_iaoq[0];
+    /* FIXME: compute is_write */
+    is_write = 0;
+    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
+                             is_write,
+                             &uc->uc_sigmask, puc);
+}
+
 #else
 
 #error host CPU specific signal handler needed
disas.c +2 -0
diff -urpN qemu-orig/disas.c qemu-new/disas.c
@@ -279,6 +279,8 @@ void disas(FILE *out, void *code, unsign
     print_insn = print_insn_m68k;
 #elif defined(__s390__)
     print_insn = print_insn_s390;
+#elif defined(__hppa__)
+    print_insn = print_insn_hppa;
 #else
     fprintf(out, "0x%lx: Asm output not supported on this arch\n",
 	    (long) code);
dis-asm.h +4 -0
diff -urpN qemu-orig/dis-asm.h qemu-new/dis-asm.h
@@ -157,6 +157,10 @@ enum bfd_architecture
 #define bfd_mach_ppc_7400      7400
   bfd_arch_rs6000,     /* IBM RS/6000 */
   bfd_arch_hppa,       /* HP PA RISC */
+#define bfd_mach_hppa10        10
+#define bfd_mach_hppa11        11
+#define bfd_mach_hppa20        20
+#define bfd_mach_hppa20w       25
   bfd_arch_d10v,       /* Mitsubishi D10V */
   bfd_arch_z8k,        /* Zilog Z8000 */
 #define bfd_mach_z8001         1
dyngen.c +127 -2

167 lines not on this page · raw message

dyngen-exec.h +7 -0
diff -urpN qemu-orig/dyngen-exec.h qemu-new/dyngen-exec.h
@@ -124,6 +124,11 @@ extern int printf(const char *, ...);
 #define AREG1 "r4"
 #define AREG2 "r5"
 #define AREG3 "r6"
+#elif defined(__hppa__)
+#define AREG0 "r17"
+#define AREG1 "r14"
+#define AREG2 "r15"
+#define AREG3 "r16"
 #elif defined(__mips__)
 #define AREG0 "fp"
 #define AREG1 "s0"
@@ -279,6 +284,8 @@ extern int __op_jmp0, __op_jmp1, __op_jm
 #elif defined(__mips__)
 #define EXIT_TB() asm volatile ("jr $ra")
 #define GOTO_LABEL_PARAM(n) asm volatile (".set noat; la $1, " ASM_NAME(__op_gen_label) #n "; jr $1; .set at")
+#elif defined(__hppa__)
+#define GOTO_LABEL_PARAM(n) asm volatile ("b,n " ASM_NAME(__op_gen_label) #n)
 #else
 #error unsupported CPU
 #endif
hppa.ld +214 -0

214 lines not on this page · raw message

Makefile.target +8 -0
diff -urpN qemu-orig/Makefile.target qemu-new/Makefile.target
@@ -128,6 +128,11 @@ ifeq ($(ARCH),alpha)
 CFLAGS+=-msmall-data
 endif
 
+ifeq ($(ARCH),hppa)
+OP_CFLAGS=-O1 -fno-delayed-branch
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+endif
+
 ifeq ($(ARCH),ia64)
 CFLAGS+=-mno-sdata
 OP_CFLAGS+=-mno-sdata
@@ -267,6 +272,9 @@ endif
 ifeq ($(findstring sh4, $(TARGET_ARCH) $(ARCH)),sh4)
 LIBOBJS+=sh4-dis.o
 endif
+ifeq ($(findstring hppa, $(TARGET_BASE_ARCH) $(ARCH)),hppa)
+LIBOBJS+=hppa-dis.o
+endif
 ifeq ($(findstring s390, $(TARGET_ARCH) $(ARCH)),s390)
 LIBOBJS+=s390-dis.o
 endif
tcg/hppa/tcg-target.c +980 -0

980 lines not on this page · raw message

tcg/hppa/tcg-target.h +204 -0

204 lines not on this page · raw message

tcg/i386/tcg-target.c +2 -1
diff -urpN qemu-orig/tcg/i386/tcg-target.c qemu-new/tcg/i386/tcg-target.c
@@ -47,8 +47,9 @@ const int tcg_target_call_iarg_regs[3] =
 const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX };
 
 static void patch_reloc(uint8_t *code_ptr, int type, 
-                        tcg_target_long value)
+                        tcg_target_long value, tcg_target_long addend)
 {
+    value += addend;
     switch(type) {
     case R_386_32:
         *(uint32_t *)code_ptr = value;
tcg/sparc/tcg-target.c +2 -1
diff -urpN qemu-orig/tcg/sparc/tcg-target.c qemu-new/tcg/sparc/tcg-target.c
@@ -88,8 +88,9 @@ static const int tcg_target_call_oarg_re
 };
 
 static void patch_reloc(uint8_t *code_ptr, int type,
-                        tcg_target_long value)
+                        tcg_target_long value, tcg_target_long addend)
 {
+    value += addend;
     switch (type) {
     case R_SPARC_32:
         if (value != (uint32_t)value)
tcg/tcg.c +23 -7
diff -urpN qemu-orig/tcg/tcg.c qemu-new/tcg/tcg.c
@@ -53,7 +53,7 @@
 
 
 static void patch_reloc(uint8_t *code_ptr, int type, 
-                        tcg_target_long value);
+                        tcg_target_long value, tcg_target_long addend);
 
 TCGOpDef tcg_op_defs[] = {
 #define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
@@ -100,7 +100,7 @@ void tcg_out_reloc(TCGContext *s, uint8_
         /* FIXME: This may break relocations on RISC targets that
            modify instruction fields in place.  The caller may not have 
            written the initial value.  */
-        patch_reloc(code_ptr, type, l->u.value + addend);
+        patch_reloc(code_ptr, type, l->u.value, addend);
     } else {
         /* add a new relocation entry */
         r = tcg_malloc(sizeof(TCGRelocation));
@@ -123,7 +123,7 @@ static void tcg_out_label(TCGContext *s,
         tcg_abort();
     r = l->u.first_reloc;
     while (r != NULL) {
-        patch_reloc(r->ptr, r->type, value + r->addend);
+        patch_reloc(r->ptr, r->type, value, r->addend);
         r = r->next;
     }
     l->has_value = 1;
@@ -1442,7 +1442,7 @@ static int tcg_reg_alloc_call(TCGContext
     int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
     TCGArg arg, func_arg;
     TCGTemp *ts;
-    tcg_target_long stack_offset, call_stack_size;
+    tcg_target_long stack_offset, call_stack_size, func_addr;
     int const_func_arg;
     TCGRegSet allocated_regs;
     const TCGArgConstraint *arg_ct;
@@ -1464,7 +1464,11 @@ static int tcg_reg_alloc_call(TCGContext
     call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
     call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
         ~(TCG_TARGET_STACK_ALIGN - 1);
+#ifdef TCG_TARGET_STACK_GROWSUP
+    tcg_out_addi(s, TCG_REG_CALL_STACK, call_stack_size);
+#else
     tcg_out_addi(s, TCG_REG_CALL_STACK, -call_stack_size);
+#endif
 
     stack_offset = 0;
     for(i = nb_regs; i < nb_params; i++) {
@@ -1487,7 +1491,11 @@ static int tcg_reg_alloc_call(TCGContext
         } else {
             tcg_abort();
         }
+#ifdef TCG_TARGET_STACK_GROWSUP
+        stack_offset -= sizeof(tcg_target_long);
+#else
         stack_offset += sizeof(tcg_target_long);
+#endif
     }
     
     /* assign input registers */
@@ -1516,6 +1524,10 @@ static int tcg_reg_alloc_call(TCGContext
     func_arg = args[nb_oargs + nb_iargs - 1];
     arg_ct = &def->args_ct[0];
     ts = &s->temps[func_arg];
+    func_addr = ts->val;
+#ifdef HOST_HPPA
+    func_addr = (tcg_target_long)__canonicalize_funcptr_for_compare((void *)func_addr);
+#endif
     const_func_arg = 0;
     if (ts->val_type == TEMP_VAL_MEM) {
         reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
@@ -1529,12 +1541,12 @@ static int tcg_reg_alloc_call(TCGContext
         }
         func_arg = reg;
     } else if (ts->val_type == TEMP_VAL_CONST) {
-        if (tcg_target_const_match(ts->val, arg_ct)) {
+        if (tcg_target_const_match(func_addr, arg_ct)) {
             const_func_arg = 1;
-            func_arg = ts->val;
+            func_arg = func_addr;
         } else {
             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
-            tcg_out_movi(s, ts->type, reg, ts->val);
+            tcg_out_movi(s, ts->type, reg, func_addr);
             func_arg = reg;
         }
     } else {
@@ -1574,7 +1586,11 @@ static int tcg_reg_alloc_call(TCGContext
 
     tcg_out_op(s, opc, &func_arg, &const_func_arg);
     
+#ifdef TCG_TARGET_STACK_GROWSUP
+    tcg_out_addi(s, TCG_REG_CALL_STACK, -call_stack_size);
+#else
     tcg_out_addi(s, TCG_REG_CALL_STACK, call_stack_size);
+#endif
 
     /* assign output registers and emit moves if needed */
     for(i = 0; i < nb_oargs; i++) {
tcg/tcg-dyngen.c +50 -0

66 lines not on this page · raw message

tcg/x86_64/tcg-target.c +2 -1
diff -urpN qemu-orig/tcg/x86_64/tcg-target.c qemu-new/tcg/x86_64/tcg-target.c
@@ -74,8 +74,9 @@ const int tcg_target_call_oarg_regs[2] =
 };
 
 static void patch_reloc(uint8_t *code_ptr, int type, 
-                        tcg_target_long value)
+                        tcg_target_long value, tcg_target_long addend)
 {
+    value += addend;
     switch(type) {
     case R_X86_64_32:
         if (value != (uint32_t)value)