]> git.proxmox.com Git - mirror_qemu.git/blobdiff - tcg/hppa/tcg-target.c
exec: move include files to include/exec/
[mirror_qemu.git] / tcg / hppa / tcg-target.c
index ffdaf004ea64f2eb0e7eadc9be7e5ec919c7a096..5b27cf6f124aaff719b8e4a13b7f62b8c6e43a4b 100644 (file)
@@ -175,12 +175,6 @@ static void patch_reloc(uint8_t *code_ptr, int type,
     *insn_ptr = insn;
 }
 
-/* maximum number of register used for input function arguments */
-static inline int tcg_target_get_call_iarg_regs_count(int flags)
-{
-    return 4;
-}
-
 /* parse target specific constraints */
 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
 {
@@ -336,9 +330,9 @@ static int tcg_target_const_match(tcg_target_long val,
 #define INSN_COMIBF     (INSN_OP(0x23))
 
 /* supplied by libgcc */
-extern void *__canonicalize_funcptr_for_compare(void *);
+extern void *__canonicalize_funcptr_for_compare(const void *);
 
-static void tcg_out_mov(TCGContext *s, int ret, int arg)
+static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
 {
     /* PA1.1 defines COPY as OR r,0,t; PA2.0 defines COPY as LDO 0(r),t
        but hppa-dis.c is unaware of this definition */
@@ -349,7 +343,7 @@ static void tcg_out_mov(TCGContext *s, int ret, int arg)
 }
 
 static void tcg_out_movi(TCGContext *s, TCGType type,
-                         int ret, tcg_target_long arg)
+                         TCGReg ret, tcg_target_long arg)
 {
     if (check_fit_tl(arg, 14)) {
         tcg_out32(s, INSN_LDO | INSN_R1(ret)
@@ -393,15 +387,15 @@ static void tcg_out_ldst(TCGContext *s, int ret, int addr,
 }
 
 /* This function is required by tcg.c.  */
-static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
-                              int arg1, tcg_target_long arg2)
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
+                              TCGReg arg1, tcg_target_long arg2)
 {
     tcg_out_ldst(s, ret, arg1, arg2, INSN_LDW);
 }
 
 /* This function is required by tcg.c.  */
-static inline void tcg_out_st(TCGContext *s, TCGType type, int ret,
-                              int arg1, tcg_target_long arg2)
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg ret,
+                              TCGReg arg1, tcg_target_long arg2)
 {
     tcg_out_ldst(s, ret, arg1, arg2, INSN_STW);
 }
@@ -467,6 +461,14 @@ static inline void tcg_out_dep(TCGContext *s, int ret, int arg,
               | INSN_SHDEP_CP(31 - ofs) | INSN_DEP_LEN(len));
 }
 
+static inline void tcg_out_depi(TCGContext *s, int ret, int arg,
+                                unsigned ofs, unsigned len)
+{
+    assert(ofs < 32 && len <= 32 - ofs);
+    tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(arg)
+              | INSN_SHDEP_CP(31 - ofs) | INSN_DEP_LEN(len));
+}
+
 static inline void tcg_out_shd(TCGContext *s, int ret, int hi, int lo,
                                unsigned count)
 {
@@ -498,9 +500,8 @@ static void tcg_out_ori(TCGContext *s, int ret, int arg, tcg_target_ulong m)
     }
     assert(bs1 == 32 || (1ul << bs1) > m);
 
-    tcg_out_mov(s, ret, arg);
-    tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(-1)
-              | INSN_SHDEP_CP(31 - bs0) | INSN_DEP_LEN(bs1 - bs0));
+    tcg_out_mov(s, TCG_TYPE_I32, ret, arg);
+    tcg_out_depi(s, ret, -1, bs0, bs1 - bs0);
 }
 
 static void tcg_out_andi(TCGContext *s, int ret, int arg, tcg_target_ulong m)
@@ -528,9 +529,8 @@ static void tcg_out_andi(TCGContext *s, int ret, int arg, tcg_target_ulong m)
     if (ls1 == 32) {
         tcg_out_extr(s, ret, arg, 0, ls0, 0);
     } else {
-        tcg_out_mov(s, ret, arg);
-        tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(0)
-                  | INSN_SHDEP_CP(31 - ls0) | INSN_DEP_LEN(ls1 - ls0));
+        tcg_out_mov(s, TCG_TYPE_I32, ret, arg);
+        tcg_out_depi(s, ret, 0, ls0, ls1 - ls0);
     }
 }
 
@@ -608,7 +608,7 @@ static void tcg_out_rotr(TCGContext *s, int ret, int arg, int creg)
 static void tcg_out_bswap16(TCGContext *s, int ret, int arg, int sign)
 {
     if (ret != arg) {
-        tcg_out_mov(s, ret, arg);             /* arg =  xxAB */
+        tcg_out_mov(s, TCG_TYPE_I32, ret, arg); /* arg =  xxAB */
     }
     tcg_out_dep(s, ret, ret, 16, 8);          /* ret =  xBAB */
     tcg_out_extr(s, ret, ret, 8, 16, sign);   /* ret =  ..BA */
@@ -622,7 +622,7 @@ static void tcg_out_bswap32(TCGContext *s, int ret, int arg, int temp)
     tcg_out_shd(s, ret, arg, temp, 8);    /* ret =  DCBA */
 }
 
-static void tcg_out_call(TCGContext *s, void *func)
+static void tcg_out_call(TCGContext *s, const void *func)
 {
     tcg_target_long val, hi, lo, disp;
 
@@ -638,7 +638,7 @@ static void tcg_out_call(TCGContext *s, void *func)
         tcg_out32(s, INSN_LDIL | INSN_R2(TCG_REG_R20) | reassemble_21(hi));
         tcg_out32(s, INSN_BLE_SR4 | INSN_R2(TCG_REG_R20)
                   | reassemble_17(lo >> 2));
-        tcg_out_mov(s, TCG_REG_RP, TCG_REG_R31);
+        tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_RP, TCG_REG_R31);
     }
 }
 
@@ -646,14 +646,14 @@ static void tcg_out_xmpyu(TCGContext *s, int retl, int reth,
                           int arg1, int arg2)
 {
     /* Store both words into the stack for copy to the FPU.  */
-    tcg_out_ldst(s, arg1, TCG_REG_SP, STACK_TEMP_OFS, INSN_STW);
-    tcg_out_ldst(s, arg2, TCG_REG_SP, STACK_TEMP_OFS + 4, INSN_STW);
+    tcg_out_ldst(s, arg1, TCG_REG_CALL_STACK, STACK_TEMP_OFS, INSN_STW);
+    tcg_out_ldst(s, arg2, TCG_REG_CALL_STACK, STACK_TEMP_OFS + 4, INSN_STW);
 
     /* Load both words into the FPU at the same time.  We get away
        with this because we can address the left and right half of the
        FPU registers individually once loaded.  */
     /* fldds stack_temp(sp),fr22 */
-    tcg_out32(s, INSN_FLDDS | INSN_R2(TCG_REG_SP)
+    tcg_out32(s, INSN_FLDDS | INSN_R2(TCG_REG_CALL_STACK)
               | INSN_IM5(STACK_TEMP_OFS) | INSN_T(22));
 
     /* xmpyu fr22r,fr22,fr22 */
@@ -661,15 +661,16 @@ static void tcg_out_xmpyu(TCGContext *s, int retl, int reth,
 
     /* Store the 64-bit result back into the stack.  */
     /* fstds stack_temp(sp),fr22 */
-    tcg_out32(s, INSN_FSTDS | INSN_R2(TCG_REG_SP)
+    tcg_out32(s, INSN_FSTDS | INSN_R2(TCG_REG_CALL_STACK)
               | INSN_IM5(STACK_TEMP_OFS) | INSN_T(22));
 
     /* Load the pieces of the result that the caller requested.  */
     if (reth) {
-        tcg_out_ldst(s, reth, TCG_REG_SP, STACK_TEMP_OFS, INSN_LDW);
+        tcg_out_ldst(s, reth, TCG_REG_CALL_STACK, STACK_TEMP_OFS, INSN_LDW);
     }
     if (retl) {
-        tcg_out_ldst(s, retl, TCG_REG_SP, STACK_TEMP_OFS + 4, INSN_LDW);
+        tcg_out_ldst(s, retl, TCG_REG_CALL_STACK, STACK_TEMP_OFS + 4,
+                     INSN_LDW);
     }
 }
 
@@ -685,7 +686,7 @@ static void tcg_out_add2(TCGContext *s, int destl, int desth,
     }
     tcg_out_arith(s, desth, ah, bh, INSN_ADDC);
 
-    tcg_out_mov(s, destl, tmp);
+    tcg_out_mov(s, TCG_TYPE_I32, destl, tmp);
 }
 
 static void tcg_out_sub2(TCGContext *s, int destl, int desth, int al, int ah,
@@ -706,7 +707,7 @@ static void tcg_out_sub2(TCGContext *s, int destl, int desth, int al, int ah,
     }
     tcg_out_arith(s, desth, ah, bh, INSN_SUBB);
 
-    tcg_out_mov(s, destl, tmp);
+    tcg_out_mov(s, TCG_TYPE_I32, destl, tmp);
 }
 
 static void tcg_out_branch(TCGContext *s, int label_index, int nul)
@@ -723,12 +724,15 @@ static void tcg_out_branch(TCGContext *s, int label_index, int nul)
 
         tcg_out32(s, op | reassemble_17(val));
     } else {
+        /* We need to keep the offset unchanged for retranslation.  */
+        uint32_t old_insn = *(uint32_t *)s->code_ptr;
+
         tcg_out_reloc(s, s->code_ptr, R_PARISC_PCREL17F, label_index, 0);
-        tcg_out32(s, op);
+        tcg_out32(s, op | (old_insn & 0x1f1ffdu));
     }
 }
 
-static const uint8_t tcg_cond_to_cmp_cond[10] =
+static const uint8_t tcg_cond_to_cmp_cond[] =
 {
     [TCG_COND_EQ] = COND_EQ,
     [TCG_COND_NE] = COND_EQ | COND_FALSE,
@@ -777,11 +781,14 @@ static void tcg_out_brcond(TCGContext *s, int cond, TCGArg c1,
         tcg_out32(s, op | reassemble_12(val));
         tcg_out_nop(s);
     } else {
+        /* We need to keep the offset unchanged for retranslation.  */
+        uint32_t old_insn = *(uint32_t *)s->code_ptr;
+
         tcg_out_reloc(s, s->code_ptr, R_PARISC_PCREL12F, label_index, 0);
         /* ??? Assume that all branches to undefined labels are forward.
            Which means that if the nul bit is set, the delay slot is
            not executed if the branch is taken, which is what we want.  */
-        tcg_out32(s, op | 2);
+        tcg_out32(s, op | 2 | (old_insn & 0x1ffdu));
     }
 }
 
@@ -813,13 +820,15 @@ static void tcg_out_brcond2(TCGContext *s, int cond, TCGArg al, TCGArg ah,
 {
     switch (cond) {
     case TCG_COND_EQ:
+        tcg_out_comclr(s, TCG_COND_NE, TCG_REG_R0, al, bl, blconst);
+        tcg_out_brcond(s, TCG_COND_EQ, ah, bh, bhconst, label_index);
+        break;
     case TCG_COND_NE:
-        tcg_out_comclr(s, tcg_invert_cond(cond), TCG_REG_R0, al, bl, blconst);
-        tcg_out_brcond(s, cond, ah, bh, bhconst, label_index);
+        tcg_out_brcond(s, TCG_COND_NE, al, bl, bhconst, label_index);
+        tcg_out_brcond(s, TCG_COND_NE, ah, bh, bhconst, label_index);
         break;
-
     default:
-        tcg_out_brcond(s, cond, ah, bh, bhconst, label_index);
+        tcg_out_brcond(s, tcg_high_cond(cond), ah, bh, bhconst, label_index);
         tcg_out_comclr(s, TCG_COND_NE, TCG_REG_R0, ah, bh, bhconst);
         tcg_out_brcond(s, tcg_unsigned_cond(cond),
                        al, bl, blconst, label_index);
@@ -840,9 +849,8 @@ static void tcg_out_setcond2(TCGContext *s, int cond, TCGArg ret,
 {
     int scratch = TCG_REG_R20;
 
-    if (ret != al && ret != ah
-        && (blconst || ret != bl)
-        && (bhconst || ret != bh)) {
+    /* Note that the low parts are fully consumed before scratch is set.  */
+    if (ret != ah && (bhconst || ret != bh)) {
         scratch = ret;
     }
 
@@ -854,33 +862,68 @@ static void tcg_out_setcond2(TCGContext *s, int cond, TCGArg ret,
         tcg_out_movi(s, TCG_TYPE_I32, scratch, cond == TCG_COND_NE);
         break;
 
-    default:
+    case TCG_COND_GE:
+    case TCG_COND_GEU:
+    case TCG_COND_LT:
+    case TCG_COND_LTU:
+        /* Optimize compares with low part zero.  */
+        if (bl == 0) {
+            tcg_out_setcond(s, cond, ret, ah, bh, bhconst);
+            return;
+        }
+        /* FALLTHRU */
+
+    case TCG_COND_LE:
+    case TCG_COND_LEU:
+    case TCG_COND_GT:
+    case TCG_COND_GTU:
+        /* <= : ah < bh | (ah == bh && al <= bl) */
         tcg_out_setcond(s, tcg_unsigned_cond(cond), scratch, al, bl, blconst);
         tcg_out_comclr(s, TCG_COND_EQ, TCG_REG_R0, ah, bh, bhconst);
         tcg_out_movi(s, TCG_TYPE_I32, scratch, 0);
-        tcg_out_comclr(s, cond, TCG_REG_R0, ah, bh, bhconst);
+        tcg_out_comclr(s, tcg_invert_cond(tcg_high_cond(cond)),
+                       TCG_REG_R0, ah, bh, bhconst);
         tcg_out_movi(s, TCG_TYPE_I32, scratch, 1);
         break;
+
+    default:
+        tcg_abort();
     }
 
-    tcg_out_mov(s, ret, scratch);
+    tcg_out_mov(s, TCG_TYPE_I32, ret, scratch);
 }
 
-#if defined(CONFIG_SOFTMMU)
-#include "../../softmmu_defs.h"
+static void tcg_out_movcond(TCGContext *s, int cond, TCGArg ret,
+                            TCGArg c1, TCGArg c2, int c2const,
+                            TCGArg v1, int v1const)
+{
+    tcg_out_comclr(s, tcg_invert_cond(cond), TCG_REG_R0, c1, c2, c2const);
+    if (v1const) {
+        tcg_out_movi(s, TCG_TYPE_I32, ret, v1);
+    } else {
+        tcg_out_mov(s, TCG_TYPE_I32, ret, v1);
+    }
+}
 
-static void *qemu_ld_helpers[4] = {
-    __ldb_mmu,
-    __ldw_mmu,
-    __ldl_mmu,
-    __ldq_mmu,
+#if defined(CONFIG_SOFTMMU)
+#include "exec/softmmu_defs.h"
+
+/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
+   int mmu_idx) */
+static const void * const qemu_ld_helpers[4] = {
+    helper_ldb_mmu,
+    helper_ldw_mmu,
+    helper_ldl_mmu,
+    helper_ldq_mmu,
 };
 
-static void *qemu_st_helpers[4] = {
-    __stb_mmu,
-    __stw_mmu,
-    __stl_mmu,
-    __stq_mmu,
+/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
+   uintxx_t val, int mmu_idx) */
+static const void * const qemu_st_helpers[4] = {
+    helper_stb_mmu,
+    helper_stw_mmu,
+    helper_stl_mmu,
+    helper_stq_mmu,
 };
 
 /* Load and compare a TLB entry, and branch if TLB miss.  OFFSET is set to
@@ -904,7 +947,6 @@ static int tcg_out_tlb_read(TCGContext *s, int r0, int r1, int addrlo,
        CPU_TLB_ENTRY_BITS is > 3, so we can't merge that shift with the
        add that follows.  */
     tcg_out_extr(s, r1, addrlo, TARGET_PAGE_BITS, CPU_TLB_BITS, 0);
-    tcg_out_andi(s, r0, addrlo, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
     tcg_out_shli(s, r1, r1, CPU_TLB_ENTRY_BITS);
     tcg_out_arith(s, r1, r1, TCG_AREG0, INSN_ADDL);
 
@@ -927,6 +969,13 @@ static int tcg_out_tlb_read(TCGContext *s, int r0, int r1, int addrlo,
         tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, r1, offset);
     }
 
+    /* Compute the value that ought to appear in the TLB for a hit, namely,
+       the page of the address.  We include the low N bits of the address
+       to catch unaligned accesses and force them onto the slow path.  Do
+       this computation after having issued the load from the TLB slot to
+       give the load time to complete.  */
+    tcg_out_andi(s, r0, addrlo, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
+
     /* If not equal, jump to lab_miss. */
     if (TARGET_LONG_BITS == 64) {
         tcg_out_brcond2(s, TCG_COND_NE, TCG_REG_R20, TCG_REG_R23,
@@ -937,287 +986,302 @@ static int tcg_out_tlb_read(TCGContext *s, int r0, int r1, int addrlo,
 
     return ret;
 }
-#endif
 
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
+static int tcg_out_arg_reg32(TCGContext *s, int argno, TCGArg v, bool vconst)
 {
-    int addr_reg, addr_reg2;
-    int data_reg, data_reg2;
-    int r0, r1, mem_index, s_bits, bswap;
-    tcg_target_long offset;
-#if defined(CONFIG_SOFTMMU)
-    int lab1, lab2, argreg;
-#endif
-
-    data_reg = *args++;
-    data_reg2 = (opc == 3 ? *args++ : TCG_REG_R0);
-    addr_reg = *args++;
-    addr_reg2 = (TARGET_LONG_BITS == 64 ? *args++ : TCG_REG_R0);
-    mem_index = *args;
-    s_bits = opc & 3;
-
-    r0 = TCG_REG_R26;
-    r1 = TCG_REG_R25;
-
-#if defined(CONFIG_SOFTMMU)
-    lab1 = gen_new_label();
-    lab2 = gen_new_label();
-
-    offset = tcg_out_tlb_read(s, r0, r1, addr_reg, addr_reg2, s_bits, lab1,
-                              offsetof(CPUState,
-                                       tlb_table[mem_index][0].addr_read));
-
-    /* TLB Hit.  */
-    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, (offset ? TCG_REG_R1 : r1),
-               offsetof(CPUState, tlb_table[mem_index][0].addend) - offset);
+    if (argno < 4) {
+        if (vconst) {
+            tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[argno], v);
+        } else {
+            tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[argno], v);
+        }
+    } else {
+        if (vconst && v != 0) {
+            tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R20, v);
+            v = TCG_REG_R20;
+        }
+        tcg_out_st(s, TCG_TYPE_I32, v, TCG_REG_CALL_STACK,
+                   TCG_TARGET_CALL_STACK_OFFSET - ((argno - 3) * 4));
+    }
+    return argno + 1;
+}
 
-    tcg_out_arith(s, r0, addr_reg, TCG_REG_R20, INSN_ADDL);
-    offset = TCG_REG_R0;
-#else
-    r0 = addr_reg;
-    offset = GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_R0;
+static int tcg_out_arg_reg64(TCGContext *s, int argno, TCGArg vl, TCGArg vh)
+{
+    /* 64-bit arguments must go in even reg pairs and stack slots.  */
+    if (argno & 1) {
+        argno++;
+    }
+    argno = tcg_out_arg_reg32(s, argno, vl, false);
+    argno = tcg_out_arg_reg32(s, argno, vh, false);
+    return argno;
+}
 #endif
 
+static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo_reg, int datahi_reg,
+                                   int addr_reg, int addend_reg, int opc)
+{
 #ifdef TARGET_WORDS_BIGENDIAN
-    bswap = 0;
+    const int bswap = 0;
 #else
-    bswap = 1;
+    const int bswap = 1;
 #endif
+
     switch (opc) {
     case 0:
-        tcg_out_ldst_index(s, data_reg, r0, offset, INSN_LDBX);
+        tcg_out_ldst_index(s, datalo_reg, addr_reg, addend_reg, INSN_LDBX);
         break;
     case 0 | 4:
-        tcg_out_ldst_index(s, data_reg, r0, offset, INSN_LDBX);
-        tcg_out_ext8s(s, data_reg, data_reg);
+        tcg_out_ldst_index(s, datalo_reg, addr_reg, addend_reg, INSN_LDBX);
+        tcg_out_ext8s(s, datalo_reg, datalo_reg);
         break;
     case 1:
-        tcg_out_ldst_index(s, data_reg, r0, offset, INSN_LDHX);
+        tcg_out_ldst_index(s, datalo_reg, addr_reg, addend_reg, INSN_LDHX);
         if (bswap) {
-            tcg_out_bswap16(s, data_reg, data_reg, 0);
+            tcg_out_bswap16(s, datalo_reg, datalo_reg, 0);
         }
         break;
     case 1 | 4:
-        tcg_out_ldst_index(s, data_reg, r0, offset, INSN_LDHX);
+        tcg_out_ldst_index(s, datalo_reg, addr_reg, addend_reg, INSN_LDHX);
         if (bswap) {
-            tcg_out_bswap16(s, data_reg, data_reg, 1);
+            tcg_out_bswap16(s, datalo_reg, datalo_reg, 1);
         } else {
-            tcg_out_ext16s(s, data_reg, data_reg);
+            tcg_out_ext16s(s, datalo_reg, datalo_reg);
         }
         break;
     case 2:
-        tcg_out_ldst_index(s, data_reg, r0, offset, INSN_LDWX);
+        tcg_out_ldst_index(s, datalo_reg, addr_reg, addend_reg, INSN_LDWX);
         if (bswap) {
-            tcg_out_bswap32(s, data_reg, data_reg, TCG_REG_R20);
+            tcg_out_bswap32(s, datalo_reg, datalo_reg, TCG_REG_R20);
         }
         break;
     case 3:
         if (bswap) {
-            int t = data_reg2;
-            data_reg2 = data_reg;
-            data_reg = t;
+            int t = datahi_reg;
+            datahi_reg = datalo_reg;
+            datalo_reg = t;
         }
-        if (offset == TCG_REG_R0) {
-            /* Make sure not to clobber the base register.  */
-            if (data_reg2 == r0) {
-                tcg_out_ldst(s, data_reg, r0, 4, INSN_LDW);
-                tcg_out_ldst(s, data_reg2, r0, 0, INSN_LDW);
-            } else {
-                tcg_out_ldst(s, data_reg2, r0, 0, INSN_LDW);
-                tcg_out_ldst(s, data_reg, r0, 4, INSN_LDW);
-            }
+        /* We can't access the low-part with a reg+reg addressing mode,
+           so perform the addition now and use reg_ofs addressing mode.  */
+        if (addend_reg != TCG_REG_R0) {
+            tcg_out_arith(s, TCG_REG_R20, addr_reg, addend_reg, INSN_ADD);
+            addr_reg = TCG_REG_R20;
+       }
+        /* Make sure not to clobber the base register.  */
+        if (datahi_reg == addr_reg) {
+            tcg_out_ldst(s, datalo_reg, addr_reg, 4, INSN_LDW);
+            tcg_out_ldst(s, datahi_reg, addr_reg, 0, INSN_LDW);
         } else {
-            tcg_out_addi2(s, TCG_REG_R20, r0, 4);
-            tcg_out_ldst_index(s, data_reg2, r0, offset, INSN_LDWX);
-            tcg_out_ldst_index(s, data_reg, TCG_REG_R20, offset, INSN_LDWX);
+            tcg_out_ldst(s, datahi_reg, addr_reg, 0, INSN_LDW);
+            tcg_out_ldst(s, datalo_reg, addr_reg, 4, INSN_LDW);
         }
         if (bswap) {
-            tcg_out_bswap32(s, data_reg, data_reg, TCG_REG_R20);
-            tcg_out_bswap32(s, data_reg2, data_reg2, TCG_REG_R20);
+            tcg_out_bswap32(s, datalo_reg, datalo_reg, TCG_REG_R20);
+            tcg_out_bswap32(s, datahi_reg, datahi_reg, TCG_REG_R20);
         }
         break;
     default:
         tcg_abort();
     }
+}
+
+static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
+{
+    int datalo_reg = *args++;
+    /* Note that datahi_reg is only used for 64-bit loads.  */
+    int datahi_reg = (opc == 3 ? *args++ : TCG_REG_R0);
+    int addrlo_reg = *args++;
 
 #if defined(CONFIG_SOFTMMU)
+    /* Note that addrhi_reg is only used for 64-bit guests.  */
+    int addrhi_reg = (TARGET_LONG_BITS == 64 ? *args++ : TCG_REG_R0);
+    int mem_index = *args;
+    int lab1, lab2, argno, offset;
+
+    lab1 = gen_new_label();
+    lab2 = gen_new_label();
+
+    offset = offsetof(CPUArchState, tlb_table[mem_index][0].addr_read);
+    offset = tcg_out_tlb_read(s, TCG_REG_R26, TCG_REG_R25, addrlo_reg,
+                              addrhi_reg, opc & 3, lab1, offset);
+
+    /* TLB Hit.  */
+    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20,
+               (offset ? TCG_REG_R1 : TCG_REG_R25),
+               offsetof(CPUArchState, tlb_table[mem_index][0].addend) - offset);
+    tcg_out_qemu_ld_direct(s, datalo_reg, datahi_reg, addrlo_reg,
+                           TCG_REG_R20, opc);
     tcg_out_branch(s, lab2, 1);
 
     /* TLB Miss.  */
     /* label1: */
-    tcg_out_label(s, lab1, (tcg_target_long)s->code_ptr);
+    tcg_out_label(s, lab1, s->code_ptr);
 
-    argreg = TCG_REG_R26;
-    tcg_out_mov(s, argreg--, addr_reg);
+    argno = 0;
+    argno = tcg_out_arg_reg32(s, argno, TCG_AREG0, false);
     if (TARGET_LONG_BITS == 64) {
-        tcg_out_mov(s, argreg--, addr_reg2);
+        argno = tcg_out_arg_reg64(s, argno, addrlo_reg, addrhi_reg);
+    } else {
+        argno = tcg_out_arg_reg32(s, argno, addrlo_reg, false);
     }
-    tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
+    argno = tcg_out_arg_reg32(s, argno, mem_index, true);
 
-    tcg_out_call(s, qemu_ld_helpers[s_bits]);
+    tcg_out_call(s, qemu_ld_helpers[opc & 3]);
 
     switch (opc) {
     case 0:
-        tcg_out_andi(s, data_reg, TCG_REG_RET0, 0xff);
+        tcg_out_andi(s, datalo_reg, TCG_REG_RET0, 0xff);
         break;
     case 0 | 4:
-        tcg_out_ext8s(s, data_reg, TCG_REG_RET0);
+        tcg_out_ext8s(s, datalo_reg, TCG_REG_RET0);
         break;
     case 1:
-        tcg_out_andi(s, data_reg, TCG_REG_RET0, 0xffff);
+        tcg_out_andi(s, datalo_reg, TCG_REG_RET0, 0xffff);
         break;
     case 1 | 4:
-        tcg_out_ext16s(s, data_reg, TCG_REG_RET0);
+        tcg_out_ext16s(s, datalo_reg, TCG_REG_RET0);
         break;
     case 2:
     case 2 | 4:
-        tcg_out_mov(s, data_reg, TCG_REG_RET0);
+        tcg_out_mov(s, TCG_TYPE_I32, datalo_reg, TCG_REG_RET0);
         break;
     case 3:
-        tcg_out_mov(s, data_reg, TCG_REG_RET0);
-        tcg_out_mov(s, data_reg2, TCG_REG_RET1);
+        tcg_out_mov(s, TCG_TYPE_I32, datahi_reg, TCG_REG_RET0);
+        tcg_out_mov(s, TCG_TYPE_I32, datalo_reg, TCG_REG_RET1);
         break;
     default:
         tcg_abort();
     }
 
     /* label2: */
-    tcg_out_label(s, lab2, (tcg_target_long)s->code_ptr);
+    tcg_out_label(s, lab2, s->code_ptr);
+#else
+    tcg_out_qemu_ld_direct(s, datalo_reg, datahi_reg, addrlo_reg,
+                           (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_R0), opc);
 #endif
 }
 
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
+static void tcg_out_qemu_st_direct(TCGContext *s, int datalo_reg,
+                                   int datahi_reg, int addr_reg, int opc)
 {
-    int addr_reg, addr_reg2;
-    int data_reg, data_reg2;
-    int r0, r1, mem_index, s_bits, bswap;
-#if defined(CONFIG_SOFTMMU)
-    tcg_target_long offset;
-    int lab1, lab2, argreg;
-#endif
-
-    data_reg = *args++;
-    data_reg2 = (opc == 3 ? *args++ : 0);
-    addr_reg = *args++;
-    addr_reg2 = (TARGET_LONG_BITS == 64 ? *args++ : 0);
-    mem_index = *args;
-    s_bits = opc;
-
-    r0 = TCG_REG_R26;
-    r1 = TCG_REG_R25;
-
-#if defined(CONFIG_SOFTMMU)
-    lab1 = gen_new_label();
-    lab2 = gen_new_label();
-
-    offset = tcg_out_tlb_read(s, r0, r1, addr_reg, addr_reg2, s_bits, lab1,
-                              offsetof(CPUState,
-                                       tlb_table[mem_index][0].addr_write));
-
-    /* TLB Hit.  */
-    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20, (offset ? TCG_REG_R1 : r1),
-               offsetof(CPUState, tlb_table[mem_index][0].addend) - offset);
-
-    tcg_out_arith(s, r0, addr_reg, TCG_REG_R20, INSN_ADDL);
-#else
-    /* There are no indexed stores, so if GUEST_BASE is set
-       we must do the add explicitly.  Careful to avoid R20,
-       which is used for the bswaps to follow.  */
-    if (GUEST_BASE == 0) {
-        r0 = addr_reg;
-    } else {
-        tcg_out_arith(s, TCG_REG_R31, addr_reg, TCG_GUEST_BASE_REG, INSN_ADDL);
-        r0 = TCG_REG_R31;
-    }
-#endif
-
 #ifdef TARGET_WORDS_BIGENDIAN
-    bswap = 0;
+    const int bswap = 0;
 #else
-    bswap = 1;
+    const int bswap = 1;
 #endif
+
     switch (opc) {
     case 0:
-        tcg_out_ldst(s, data_reg, r0, 0, INSN_STB);
+        tcg_out_ldst(s, datalo_reg, addr_reg, 0, INSN_STB);
         break;
     case 1:
         if (bswap) {
-            tcg_out_bswap16(s, TCG_REG_R20, data_reg, 0);
-            data_reg = TCG_REG_R20;
+            tcg_out_bswap16(s, TCG_REG_R20, datalo_reg, 0);
+            datalo_reg = TCG_REG_R20;
         }
-        tcg_out_ldst(s, data_reg, r0, 0, INSN_STH);
+        tcg_out_ldst(s, datalo_reg, addr_reg, 0, INSN_STH);
         break;
     case 2:
         if (bswap) {
-            tcg_out_bswap32(s, TCG_REG_R20, data_reg, TCG_REG_R20);
-            data_reg = TCG_REG_R20;
+            tcg_out_bswap32(s, TCG_REG_R20, datalo_reg, TCG_REG_R20);
+            datalo_reg = TCG_REG_R20;
         }
-        tcg_out_ldst(s, data_reg, r0, 0, INSN_STW);
+        tcg_out_ldst(s, datalo_reg, addr_reg, 0, INSN_STW);
         break;
     case 3:
         if (bswap) {
-            tcg_out_bswap32(s, TCG_REG_R20, data_reg, TCG_REG_R20);
-            tcg_out_bswap32(s, TCG_REG_R23, data_reg2, TCG_REG_R23);
-            data_reg2 = TCG_REG_R20;
-            data_reg = TCG_REG_R23;
+            tcg_out_bswap32(s, TCG_REG_R20, datalo_reg, TCG_REG_R20);
+            tcg_out_bswap32(s, TCG_REG_R23, datahi_reg, TCG_REG_R23);
+            datahi_reg = TCG_REG_R20;
+            datalo_reg = TCG_REG_R23;
         }
-        tcg_out_ldst(s, data_reg2, r0, 0, INSN_STW);
-        tcg_out_ldst(s, data_reg, r0, 4, INSN_STW);
+        tcg_out_ldst(s, datahi_reg, addr_reg, 0, INSN_STW);
+        tcg_out_ldst(s, datalo_reg, addr_reg, 4, INSN_STW);
         break;
     default:
         tcg_abort();
     }
 
+}
+
+static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
+{
+    int datalo_reg = *args++;
+    /* Note that datahi_reg is only used for 64-bit loads.  */
+    int datahi_reg = (opc == 3 ? *args++ : TCG_REG_R0);
+    int addrlo_reg = *args++;
+
 #if defined(CONFIG_SOFTMMU)
+    /* Note that addrhi_reg is only used for 64-bit guests.  */
+    int addrhi_reg = (TARGET_LONG_BITS == 64 ? *args++ : TCG_REG_R0);
+    int mem_index = *args;
+    int lab1, lab2, argno, next, offset;
+
+    lab1 = gen_new_label();
+    lab2 = gen_new_label();
+
+    offset = offsetof(CPUArchState, tlb_table[mem_index][0].addr_write);
+    offset = tcg_out_tlb_read(s, TCG_REG_R26, TCG_REG_R25, addrlo_reg,
+                              addrhi_reg, opc, lab1, offset);
+
+    /* TLB Hit.  */
+    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R20,
+               (offset ? TCG_REG_R1 : TCG_REG_R25),
+               offsetof(CPUArchState, tlb_table[mem_index][0].addend) - offset);
+
+    /* There are no indexed stores, so we must do this addition explitly.
+       Careful to avoid R20, which is used for the bswaps to follow.  */
+    tcg_out_arith(s, TCG_REG_R31, addrlo_reg, TCG_REG_R20, INSN_ADDL);
+    tcg_out_qemu_st_direct(s, datalo_reg, datahi_reg, TCG_REG_R31, opc);
     tcg_out_branch(s, lab2, 1);
 
     /* TLB Miss.  */
     /* label1: */
-    tcg_out_label(s, lab1, (tcg_target_long)s->code_ptr);
+    tcg_out_label(s, lab1, s->code_ptr);
 
-    argreg = TCG_REG_R26;
-    tcg_out_mov(s, argreg--, addr_reg);
+    argno = 0;
+    argno = tcg_out_arg_reg32(s, argno, TCG_AREG0, false);
     if (TARGET_LONG_BITS == 64) {
-        tcg_out_mov(s, argreg--, addr_reg2);
+        argno = tcg_out_arg_reg64(s, argno, addrlo_reg, addrhi_reg);
+    } else {
+        argno = tcg_out_arg_reg32(s, argno, addrlo_reg, false);
     }
 
+    next = (argno < 4 ? tcg_target_call_iarg_regs[argno] : TCG_REG_R20);
     switch(opc) {
     case 0:
-        tcg_out_andi(s, argreg--, data_reg, 0xff);
-        tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
+        tcg_out_andi(s, next, datalo_reg, 0xff);
+        argno = tcg_out_arg_reg32(s, argno, next, false);
         break;
     case 1:
-        tcg_out_andi(s, argreg--, data_reg, 0xffff);
-        tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
+        tcg_out_andi(s, next, datalo_reg, 0xffff);
+        argno = tcg_out_arg_reg32(s, argno, next, false);
         break;
     case 2:
-        tcg_out_mov(s, argreg--, data_reg);
-        tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
+        argno = tcg_out_arg_reg32(s, argno, datalo_reg, false);
         break;
     case 3:
-        /* Because of the alignment required by the 64-bit data argument,
-           we will always use R23/R24.  Also, we will always run out of
-           argument registers for storing mem_index, so that will have
-           to go on the stack.  */
-        if (mem_index == 0) {
-            argreg = TCG_REG_R0;
-        } else {
-            argreg = TCG_REG_R20;
-            tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
-        }
-        tcg_out_mov(s, TCG_REG_R23, data_reg2);
-        tcg_out_mov(s, TCG_REG_R24, data_reg);
-        tcg_out_st(s, TCG_TYPE_I32, argreg, TCG_REG_SP,
-                   TCG_TARGET_CALL_STACK_OFFSET - 4);
+        argno = tcg_out_arg_reg64(s, argno, datalo_reg, datahi_reg);
         break;
     default:
         tcg_abort();
     }
+    argno = tcg_out_arg_reg32(s, argno, mem_index, true);
 
-    tcg_out_call(s, qemu_st_helpers[s_bits]);
+    tcg_out_call(s, qemu_st_helpers[opc]);
 
     /* label2: */
-    tcg_out_label(s, lab2, (tcg_target_long)s->code_ptr);
+    tcg_out_label(s, lab2, s->code_ptr);
+#else
+    /* There are no indexed stores, so if GUEST_BASE is set we must do
+       the add explicitly.  Careful to avoid R20, which is used for the
+       bswaps to follow.  */
+    if (GUEST_BASE != 0) {
+        tcg_out_arith(s, TCG_REG_R31, addrlo_reg,
+                      TCG_GUEST_BASE_REG, INSN_ADDL);
+        addrlo_reg = TCG_REG_R31;
+    }
+    tcg_out_qemu_st_direct(s, datalo_reg, datahi_reg, addrlo_reg, opc);
 #endif
 }
 
@@ -1276,11 +1340,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
         }
         break;
 
-    case INDEX_op_jmp:
-        fprintf(stderr, "unimplemented jmp\n");
-        tcg_abort();
-        break;
-
     case INDEX_op_br:
         tcg_out_branch(s, args[0], 1);
         break;
@@ -1432,19 +1491,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
         tcg_out_ext16s(s, args[0], args[1]);
         break;
 
-    /* These three correspond exactly to the fallback implementation.
-       But by including them we reduce the number of TCG ops that
-       need to be generated, and these opcodes are fairly common.  */
-    case INDEX_op_neg_i32:
-        tcg_out_arith(s, args[0], TCG_REG_R0, args[1], INSN_SUB);
-        break;
-    case INDEX_op_ext8u_i32:
-        tcg_out_andi(s, args[0], args[1], 0xff);
-        break;
-    case INDEX_op_ext16u_i32:
-        tcg_out_andi(s, args[0], args[1], 0xffff);
-        break;
-
     case INDEX_op_brcond_i32:
         tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], args[3]);
         break;
@@ -1462,6 +1508,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
                          args[3], const_args[3], args[4], const_args[4]);
         break;
 
+    case INDEX_op_movcond_i32:
+        tcg_out_movcond(s, args[5], args[0], args[1], args[2], const_args[2],
+                        args[3], const_args[3]);
+        break;
+
     case INDEX_op_add2_i32:
         tcg_out_add2(s, args[0], args[1], args[2], args[3],
                      args[4], args[5], const_args[4]);
@@ -1472,6 +1523,14 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
                      args[4], args[5], const_args[2], const_args[4]);
         break;
 
+    case INDEX_op_deposit_i32:
+        if (const_args[2]) {
+            tcg_out_depi(s, args[0], args[2], args[3], args[4]);
+        } else {
+            tcg_out_dep(s, args[0], args[2], args[3], args[4]);
+        }
+        break;
+
     case INDEX_op_qemu_ld8u:
         tcg_out_qemu_ld(s, args, 0);
         break;
@@ -1515,7 +1574,6 @@ static const TCGTargetOpDef hppa_op_defs[] = {
     { INDEX_op_goto_tb, { } },
 
     { INDEX_op_call, { "ri" } },
-    { INDEX_op_jmp, { "r" } },
     { INDEX_op_br, { } },
 
     { INDEX_op_mov_i32, { "r", "r" } },
@@ -1551,13 +1609,10 @@ static const TCGTargetOpDef hppa_op_defs[] = {
 
     { INDEX_op_bswap16_i32, { "r", "r" } },
     { INDEX_op_bswap32_i32, { "r", "r" } },
-    { INDEX_op_neg_i32, { "r", "r" } },
     { INDEX_op_not_i32, { "r", "r" } },
 
     { INDEX_op_ext8s_i32, { "r", "r" } },
-    { INDEX_op_ext8u_i32, { "r", "r" } },
     { INDEX_op_ext16s_i32, { "r", "r" } },
-    { INDEX_op_ext16u_i32, { "r", "r" } },
 
     { INDEX_op_brcond_i32, { "rZ", "rJ" } },
     { INDEX_op_brcond2_i32,  { "rZ", "rZ", "rJ", "rJ" } },
@@ -1565,9 +1620,15 @@ static const TCGTargetOpDef hppa_op_defs[] = {
     { INDEX_op_setcond_i32, { "r", "rZ", "rI" } },
     { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rI", "rI" } },
 
+    /* ??? We can actually support a signed 14-bit arg3, but we
+       only have existing constraints for a signed 11-bit.  */
+    { INDEX_op_movcond_i32, { "r", "rZ", "rI", "rI", "0" } },
+
     { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rI", "rZ" } },
     { INDEX_op_sub2_i32, { "r", "r", "rI", "rZ", "rK", "rZ" } },
 
+    { INDEX_op_deposit_i32, { "r", "0", "rJ" } },
+
 #if TARGET_LONG_BITS == 32
     { INDEX_op_qemu_ld8u, { "r", "L" } },
     { INDEX_op_qemu_ld8s, { "r", "L" } },
@@ -1613,64 +1674,68 @@ static int tcg_target_callee_save_regs[] = {
     TCG_REG_R14,
     TCG_REG_R15,
     TCG_REG_R16,
-    /* R17 is the global env, so no need to save.  */
+    TCG_REG_R17, /* R17 is the global env.  */
     TCG_REG_R18
 };
 
-void tcg_target_qemu_prologue(TCGContext *s)
+#define FRAME_SIZE ((-TCG_TARGET_CALL_STACK_OFFSET \
+                     + TCG_TARGET_STATIC_CALL_ARGS_SIZE \
+                     + ARRAY_SIZE(tcg_target_callee_save_regs) * 4 \
+                     + CPU_TEMP_BUF_NLONGS * sizeof(long) \
+                     + TCG_TARGET_STACK_ALIGN - 1) \
+                    & -TCG_TARGET_STACK_ALIGN)
+
+static void tcg_target_qemu_prologue(TCGContext *s)
 {
     int frame_size, i;
 
-    /* Allocate space for the fixed frame marker.  */
-    frame_size = -TCG_TARGET_CALL_STACK_OFFSET;
-    frame_size += TCG_TARGET_STATIC_CALL_ARGS_SIZE;
-
-    /* Allocate space for the saved registers.  */
-    frame_size += ARRAY_SIZE(tcg_target_callee_save_regs) * 4;
-
-    /* Align the allocated space.  */
-    frame_size = ((frame_size + TCG_TARGET_STACK_ALIGN - 1)
-                  & -TCG_TARGET_STACK_ALIGN);
+    frame_size = FRAME_SIZE;
 
     /* The return address is stored in the caller's frame.  */
-    tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_SP, -20);
+    tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_CALL_STACK, -20);
 
     /* Allocate stack frame, saving the first register at the same time.  */
     tcg_out_ldst(s, tcg_target_callee_save_regs[0],
-                 TCG_REG_SP, frame_size, INSN_STWM);
+                 TCG_REG_CALL_STACK, frame_size, INSN_STWM);
 
     /* Save all callee saved registers.  */
     for (i = 1; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
         tcg_out_st(s, TCG_TYPE_PTR, tcg_target_callee_save_regs[i],
-                   TCG_REG_SP, -frame_size + i * 4);
+                   TCG_REG_CALL_STACK, -frame_size + i * 4);
     }
 
+    /* Record the location of the TCG temps.  */
+    tcg_set_frame(s, TCG_REG_CALL_STACK, -frame_size + i * 4,
+                  CPU_TEMP_BUF_NLONGS * sizeof(long));
+
 #ifdef CONFIG_USE_GUEST_BASE
-    /* Note that GUEST_BASE can change after the prologue is generated.
-       To combat that, load the value from the variable instead of
-       embedding a constant here.  */
-    tcg_out_ld(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG,
-               TCG_REG_R0, (tcg_target_long)&guest_base);
+    if (GUEST_BASE != 0) {
+        tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE);
+        tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
+    }
 #endif
 
+    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
+
     /* Jump to TB, and adjust R18 to be the return address.  */
-    tcg_out32(s, INSN_BLE_SR4 | INSN_R2(TCG_REG_R26));
-    tcg_out_mov(s, TCG_REG_R18, TCG_REG_R31);
+    tcg_out32(s, INSN_BLE_SR4 | INSN_R2(tcg_target_call_iarg_regs[1]));
+    tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R18, TCG_REG_R31);
 
     /* Restore callee saved registers.  */
-    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_SP, -frame_size - 20);
+    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_CALL_STACK,
+               -frame_size - 20);
     for (i = 1; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
         tcg_out_ld(s, TCG_TYPE_PTR, tcg_target_callee_save_regs[i],
-                   TCG_REG_SP, -frame_size + i * 4);
+                   TCG_REG_CALL_STACK, -frame_size + i * 4);
     }
 
     /* Deallocate stack frame and return.  */
     tcg_out32(s, INSN_BV | INSN_R2(TCG_REG_RP));
     tcg_out_ldst(s, tcg_target_callee_save_regs[0],
-                 TCG_REG_SP, -frame_size, INSN_LDWM);
+                 TCG_REG_CALL_STACK, -frame_size, INSN_LDWM);
 }
 
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
 {
     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
 
@@ -1694,11 +1759,86 @@ void tcg_target_init(TCGContext *s)
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R19); /* clobbered w/o pic */
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R20); /* reserved */
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_DP);  /* data pointer */
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);  /* stack pointer */
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);  /* stack pointer */
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R31); /* ble link reg */
-#ifdef CONFIG_USE_GUEST_BASE
-    tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
-#endif
 
     tcg_add_target_add_op_defs(hppa_op_defs);
 }
+
+typedef struct {
+    uint32_t len __attribute__((aligned((sizeof(void *)))));
+    uint32_t id;
+    uint8_t version;
+    char augmentation[1];
+    uint8_t code_align;
+    uint8_t data_align;
+    uint8_t return_column;
+} DebugFrameCIE;
+
+typedef struct {
+    uint32_t len __attribute__((aligned((sizeof(void *)))));
+    uint32_t cie_offset;
+    tcg_target_long func_start __attribute__((packed));
+    tcg_target_long func_len __attribute__((packed));
+    uint8_t def_cfa[4];
+    uint8_t ret_ofs[3];
+    uint8_t reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
+} DebugFrameFDE;
+
+typedef struct {
+    DebugFrameCIE cie;
+    DebugFrameFDE fde;
+} DebugFrame;
+
+#define ELF_HOST_MACHINE  EM_PARISC
+#define ELF_HOST_FLAGS    EFA_PARISC_1_1
+
+/* ??? BFD (and thus GDB) wants very much to distinguish between HPUX
+   and other extensions.  We don't really care, but if we don't set this
+   to *something* then the object file won't be properly matched.  */
+#define ELF_OSABI         ELFOSABI_LINUX
+
+static DebugFrame debug_frame = {
+    .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
+    .cie.id = -1,
+    .cie.version = 1,
+    .cie.code_align = 1,
+    .cie.data_align = 1,
+    .cie.return_column = 2,
+
+    .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
+    .fde.def_cfa = {
+        0x12, 30,                       /* DW_CFA_def_cfa_sf sp, ... */
+        (-FRAME_SIZE & 0x7f) | 0x80,     /* ... sleb128 -FRAME_SIZE */
+        (-FRAME_SIZE >> 7) & 0x7f
+    },
+    .fde.ret_ofs = {
+        0x11, 2, (-20 / 4) & 0x7f       /* DW_CFA_offset_extended_sf r2, 20 */
+    },
+    .fde.reg_ofs = {
+        /* This must match the ordering in tcg_target_callee_save_regs.  */
+        0x80 + 4, 0,                    /* DW_CFA_offset r4, 0 */
+        0x80 + 5, 4,                    /* DW_CFA_offset r5, 4 */
+        0x80 + 6, 8,                    /* DW_CFA_offset r6, 8 */
+        0x80 + 7, 12,                    /* ... */
+        0x80 + 8, 16,
+        0x80 + 9, 20,
+        0x80 + 10, 24,
+        0x80 + 11, 28,
+        0x80 + 12, 32,
+        0x80 + 13, 36,
+        0x80 + 14, 40,
+        0x80 + 15, 44,
+        0x80 + 16, 48,
+        0x80 + 17, 52,
+        0x80 + 18, 56,
+    }
+};
+
+void tcg_register_jit(void *buf, size_t buf_size)
+{
+    debug_frame.fde.func_start = (tcg_target_long) buf;
+    debug_frame.fde.func_len = buf_size;
+
+    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
+}