Merge r1663-r1666:

- AIX5 build changes

- genoffsets.c: print the offsets of a few more ppc registers

- Get rid of a bunch of ad-hoc hacks which hardwire in certain
  assumptions about guest and host ABIs.  Instead pass that info
  in a VexMiscInfo structure.  This cleans up various grotty bits.

- Add to ppc32 guest state, redirection-stack stuff already present
  in ppc64 guest state.  This is to enable function redirection/
  wrapping in the presence of TOC pointers in 32-bit mode.

- Add to both ppc32 and ppc64 guest states, a new pseudo-register
  LR_AT_SC.  This holds the link register value at the most recent
  'sc', so that AIX can back up to restart a syscall if needed.

- Add to both ppc32 and ppc64 guest states, a SPRG3 register.

- Use VexMiscInfo to handle 'sc' on AIX differently from Linux:
  on AIX, 'sc' continues at the location stated in the link 
  register, not at the next insn.



git-svn-id: svn://svn.valgrind.org/vex/trunk@1669 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/Makefile b/Makefile
index dd7d827..10e9787 100644
--- a/Makefile
+++ b/Makefile
@@ -137,6 +137,18 @@
 	if [ ! -f TAG_ppc64_linux ] ; then rm -f $(LIB_OBJS) TAG_* libvex.a ; fi
 	touch TAG_ppc64_linux
 
+libvex_ppc32_aix5.a: TAG_ppc32_aix5 libvex.a
+	mv -f libvex.a libvex_ppc32_aix5.a
+TAG_ppc32_aix5:
+	if [ ! -f TAG_ppc32_aix5 ] ; then rm -f $(LIB_OBJS) TAG_* libvex.a ; fi
+	touch TAG_ppc32_aix5
+
+libvex_ppc64_aix5.a: TAG_ppc64_aix5 libvex.a
+	mv -f libvex.a libvex_ppc64_aix5.a
+TAG_ppc64_aix5:
+	if [ ! -f TAG_ppc64_aix5 ] ; then rm -f $(LIB_OBJS) TAG_* libvex.a ; fi
+	touch TAG_ppc64_aix5
+
 
 # This doesn't get rid of priv/main/vex_svnversion.h, because
 # that can't be regenerated in the final Valgrind tarball, and
@@ -148,9 +160,10 @@
 
 version:
 	rm -f priv/main/vex_svnversion.h
-	echo -n "\""  > priv/main/vex_svnversion.h
+	cat quote.txt   >> priv/main/vex_svnversion.h
 	svnversion -n . >> priv/main/vex_svnversion.h
-	echo "\""  >> priv/main/vex_svnversion.h
+	cat quote.txt   >> priv/main/vex_svnversion.h
+	cat newline.txt >> priv/main/vex_svnversion.h
 
 minidist: version
 	rm -f vex--minidist-2005MMDD.tar
diff --git a/auxprogs/genoffsets.c b/auxprogs/genoffsets.c
index 13ea551..4d0b767 100644
--- a/auxprogs/genoffsets.c
+++ b/auxprogs/genoffsets.c
@@ -143,6 +143,9 @@
   printf("#define OFFSET_ppc32_GPR0      %3d\n",
          offsetof(VexGuestPPC32State,guest_GPR0));
 
+  printf("#define OFFSET_ppc32_GPR2      %3d\n",
+         offsetof(VexGuestPPC32State,guest_GPR2));
+
   printf("#define OFFSET_ppc32_GPR3      %3d\n",
          offsetof(VexGuestPPC32State,guest_GPR3));
 
@@ -161,6 +164,12 @@
   printf("#define OFFSET_ppc32_GPR8      %3d\n",
          offsetof(VexGuestPPC32State,guest_GPR8));
 
+  printf("#define OFFSET_ppc32_GPR9      %3d\n",
+         offsetof(VexGuestPPC32State,guest_GPR9));
+
+  printf("#define OFFSET_ppc32_GPR10     %3d\n",
+         offsetof(VexGuestPPC32State,guest_GPR10));
+
   printf("#define OFFSET_ppc32_CIA       %3d\n",
          offsetof(VexGuestPPC32State,guest_CIA));
 
@@ -173,6 +182,9 @@
   printf("#define OFFSET_ppc64_GPR0     %4d\n",
          offsetof(VexGuestPPC64State,guest_GPR0));
 
+  printf("#define OFFSET_ppc64_GPR2     %4d\n",
+         offsetof(VexGuestPPC64State,guest_GPR2));
+
   printf("#define OFFSET_ppc64_GPR3     %4d\n",
          offsetof(VexGuestPPC64State,guest_GPR3));
 
@@ -191,6 +203,12 @@
   printf("#define OFFSET_ppc64_GPR8     %4d\n",
          offsetof(VexGuestPPC64State,guest_GPR8));
 
+  printf("#define OFFSET_ppc64_GPR9     %4d\n",
+         offsetof(VexGuestPPC64State,guest_GPR9));
+
+  printf("#define OFFSET_ppc64_GPR10    %4d\n",
+         offsetof(VexGuestPPC64State,guest_GPR10));
+
   printf("#define OFFSET_ppc64_CIA      %4d\n",
          offsetof(VexGuestPPC64State,guest_CIA));
 
diff --git a/newline.txt b/newline.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/newline.txt
@@ -0,0 +1 @@
+
diff --git a/priv/guest-amd64/gdefs.h b/priv/guest-amd64/gdefs.h
index 36100be..01a8642 100644
--- a/priv/guest-amd64/gdefs.h
+++ b/priv/guest-amd64/gdefs.h
@@ -66,6 +66,7 @@
                            Addr64       guest_IP,
                            VexArch      guest_arch,
                            VexArchInfo* archinfo,
+                           VexMiscInfo* miscinfo,
                            Bool         host_bigendian );
 
 /* Used by the optimiser to specialise calls to helpers. */
diff --git a/priv/guest-amd64/toIR.c b/priv/guest-amd64/toIR.c
index 74fc124..a6588f9 100644
--- a/priv/guest-amd64/toIR.c
+++ b/priv/guest-amd64/toIR.c
@@ -1931,14 +1931,24 @@
    generates an AbiHint to say that -128(%rsp) .. -1(%rsp) should now
    be regarded as uninitialised.
 */
-static void make_redzone_AbiHint ( IRTemp new_rsp, HChar* who )
+static 
+void make_redzone_AbiHint ( VexMiscInfo* vmi, IRTemp new_rsp, HChar* who )
 {
+   Int szB = vmi->guest_stack_redzone_size;
+   vassert(szB >= 0);
+
+   /* A bit of a kludge.  Currently the only AbI we've guested AMD64
+      for is ELF.  So just check it's the expected 128 value
+      (paranoia). */
+   vassert(szB == 128);
+
    if (0) vex_printf("AbiHint: %s\n", who);
    vassert(typeOfIRTemp(irbb->tyenv, new_rsp) == Ity_I64);
-   stmt( IRStmt_AbiHint( 
-            binop(Iop_Sub64, mkexpr(new_rsp), mkU64(128)), 
-            128 
-         ));
+   if (szB > 0)
+      stmt( IRStmt_AbiHint( 
+               binop(Iop_Sub64, mkexpr(new_rsp), mkU64(szB)), 
+               szB
+            ));
 }
 
 
@@ -3626,7 +3636,8 @@
 
 /* Group 5 extended opcodes. */
 static
-ULong dis_Grp5 ( Prefix pfx, Int sz, Long delta, DisResult* dres )
+ULong dis_Grp5 ( VexMiscInfo* vmi,
+                 Prefix pfx, Int sz, Long delta, DisResult* dres )
 {
    Int     len;
    UChar   modrm;
@@ -3666,7 +3677,7 @@
             assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
             putIReg64(R_RSP, mkexpr(t2));
             storeLE( mkexpr(t2), mkU64(guest_RIP_bbstart+delta+1));
-            make_redzone_AbiHint(t2, "call-Ev(reg)");
+            make_redzone_AbiHint(vmi, t2, "call-Ev(reg)");
             jmp_treg(Ijk_Call,t3);
             dres->whatNext = Dis_StopHere;
             showSz = False;
@@ -3721,7 +3732,7 @@
             assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
             putIReg64(R_RSP, mkexpr(t2));
             storeLE( mkexpr(t2), mkU64(guest_RIP_bbstart+delta+len));
-            make_redzone_AbiHint(t2, "call-Ev(mem)");
+            make_redzone_AbiHint(vmi, t2, "call-Ev(mem)");
             jmp_treg(Ijk_Call,t3);
             dres->whatNext = Dis_StopHere;
             showSz = False;
@@ -7565,7 +7576,7 @@
 //.. }
 
 static
-void dis_ret ( ULong d64 )
+void dis_ret ( VexMiscInfo* vmi, ULong d64 )
 {
    IRTemp t1 = newTemp(Ity_I64); 
    IRTemp t2 = newTemp(Ity_I64);
@@ -7574,7 +7585,7 @@
    assign(t2, loadLE(Ity_I64,mkexpr(t1)));
    assign(t3, binop(Iop_Add64, mkexpr(t1), mkU64(8+d64)));
    putIReg64(R_RSP, mkexpr(t3));
-   make_redzone_AbiHint(t3, "ret");
+   make_redzone_AbiHint(vmi, t3, "ret");
    jmp_treg(Ijk_Ret,t2);
 }
 
@@ -8218,7 +8229,8 @@
              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
              void*        callback_opaque,
              Long         delta64,
-             VexArchInfo* archinfo 
+             VexArchInfo* archinfo,
+             VexMiscInfo* vmi
           )
 {
    IRType    ty;
@@ -12170,7 +12182,7 @@
    case 0xC3: /* RET */
       if (haveF2(pfx)) goto decode_failure;
       /* F3 is acceptable on AMD. */
-      dis_ret(0);
+      dis_ret(vmi, 0);
       dres.whatNext = Dis_StopHere;
       DIP(haveF3(pfx) ? "rep ; ret\n" : "ret\n");
       break;
@@ -12184,7 +12196,7 @@
       assign(t1, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
       putIReg64(R_RSP, mkexpr(t1));
       storeLE( mkexpr(t1), mkU64(guest_RIP_bbstart+delta));
-      make_redzone_AbiHint(t1, "call-d32");
+      make_redzone_AbiHint(vmi, t1, "call-d32");
       if (resteerOkFn( callback_opaque, (Addr64)d64) ) {
          /* follow into the call target. */
          dres.whatNext   = Dis_Resteer;
@@ -13711,7 +13723,7 @@
 
    case 0xFF: /* Grp5 Ev */
       if (haveF2orF3(pfx)) goto decode_failure;
-      delta = dis_Grp5 ( pfx, sz, delta, &dres );
+      delta = dis_Grp5 ( vmi, pfx, sz, delta, &dres );
       break;
 
    /* ------------------------ Escapes to 2-byte opcodes -- */
@@ -14340,6 +14352,7 @@
                            Addr64       guest_IP,
                            VexArch      guest_arch,
                            VexArchInfo* archinfo,
+                           VexMiscInfo* miscinfo,
                            Bool         host_bigendian_IN )
 {
    DisResult dres;
@@ -14357,7 +14370,7 @@
    guest_RIP_next_mustcheck = False;
 
    dres = disInstr_AMD64_WRK ( put_IP, resteerOkFn, callback_opaque,
-                               delta, archinfo );
+                               delta, archinfo, miscinfo );
 
    /* If disInstr_AMD64_WRK tried to figure out the next rip, check it
       got it right.  Failure of this assertion is serious and denotes
diff --git a/priv/guest-generic/bb_to_IR.c b/priv/guest-generic/bb_to_IR.c
index c79f4b4..e262a55 100644
--- a/priv/guest-generic/bb_to_IR.c
+++ b/priv/guest-generic/bb_to_IR.c
@@ -101,6 +101,7 @@
                  /*IN*/ Bool             host_bigendian,
                  /*IN*/ VexArch          arch_guest,
                  /*IN*/ VexArchInfo*     archinfo_guest,
+                 /*IN*/ VexMiscInfo*     miscinfo_both,
                  /*IN*/ IRType           guest_word_type,
                  /*IN*/ Bool             do_self_check,
                  /*IN*/ Bool             (*preamble_function)(void*,IRBB*),
@@ -234,6 +235,7 @@
                             guest_IP_curr_instr,
                             arch_guest,
                             archinfo_guest,
+                            miscinfo_both,
                             host_bigendian );
 
       /* stay sane ... */
@@ -342,6 +344,7 @@
 
       UInt     len2check, adler32;
       IRTemp   tistart_tmp, tilen_tmp;
+      HWord    p_adler_helper;
 
       vassert(vge->n_used == 1);
       len2check = vge->len[0];
@@ -373,6 +376,10 @@
      irbb->stmts[selfcheck_idx+3]
         = IRStmt_Put( offB_TILEN, IRExpr_Tmp(tilen_tmp) );
 
+     p_adler_helper = miscinfo_both->host_ppc_calls_use_fndescrs
+                      ? ((HWord*)(&genericg_compute_adler32))[0]
+                      : (HWord)&genericg_compute_adler32;
+
      irbb->stmts[selfcheck_idx+4]
         = IRStmt_Exit( 
              IRExpr_Binop( 
@@ -381,11 +388,7 @@
                    Ity_I32, 
                    2/*regparms*/, 
                    "genericg_compute_adler32",
-#if defined(__powerpc__) && defined(__powerpc64__)
-                   (void*)((ULong*)(&genericg_compute_adler32))[0],
-#else
-                   &genericg_compute_adler32,
-#endif
+                   (void*)p_adler_helper,
                    mkIRExprVec_2( 
                       mkIRExpr_HWord( (HWord)guest_code ), 
                       mkIRExpr_HWord( (HWord)len2check )
diff --git a/priv/guest-generic/bb_to_IR.h b/priv/guest-generic/bb_to_IR.h
index 935b920..e1fab3b 100644
--- a/priv/guest-generic/bb_to_IR.h
+++ b/priv/guest-generic/bb_to_IR.h
@@ -143,6 +143,9 @@
       /*IN*/  VexArch      guest_arch,
       /*IN*/  VexArchInfo* archinfo,
 
+      /* Misc info about guest and host */
+      /*IN*/  VexMiscInfo* miscinfo,
+
       /* Is the host bigendian? */
       /*IN*/  Bool         host_bigendian
 
@@ -164,6 +167,7 @@
                  /*IN*/ Bool             host_bigendian,
                  /*IN*/ VexArch          arch_guest,
                  /*IN*/ VexArchInfo*     archinfo_guest,
+                 /*IN*/ VexMiscInfo*     miscinfo_both,
                  /*IN*/ IRType           guest_word_type,
                  /*IN*/ Bool             do_self_check,
                  /*IN*/ Bool             (*preamble_function)(void*,IRBB*),
diff --git a/priv/guest-ppc/gdefs.h b/priv/guest-ppc/gdefs.h
index 3f9295d..1c9aaa9 100644
--- a/priv/guest-ppc/gdefs.h
+++ b/priv/guest-ppc/gdefs.h
@@ -67,6 +67,7 @@
                          Addr64       guest_IP,
                          VexArch      guest_arch,
                          VexArchInfo* archinfo,
+                         VexMiscInfo* miscinfo,
                          Bool         host_bigendian );
 
 /* Used by the optimiser to specialise calls to helpers. */
diff --git a/priv/guest-ppc/ghelpers.c b/priv/guest-ppc/ghelpers.c
index 300f13c..8eb35b2 100644
--- a/priv/guest-ppc/ghelpers.c
+++ b/priv/guest-ppc/ghelpers.c
@@ -78,7 +78,7 @@
 /* Reads a complete, consistent 64-bit TB value. */
 ULong ppcg_dirtyhelper_MFTB ( void )
 {
-#  if defined(__powerpc__)
+#  if defined(__powerpc__) || defined(_AIX)
    ULong res;
    UInt  lo, hi1, hi2;
    while (1) {
@@ -320,6 +320,7 @@
 /* VISIBLE TO LIBVEX CLIENT */
 void LibVEX_GuestPPC32_initialise ( /*OUT*/VexGuestPPC32State* vex_state )
 {
+   Int i;
    vex_state->guest_GPR0  = 0;
    vex_state->guest_GPR1  = 0;
    vex_state->guest_GPR2  = 0;
@@ -464,6 +465,14 @@
    vex_state->guest_TILEN   = 0;
 
    vex_state->guest_NRADDR = 0;
+   vex_state->guest_NRADDR_GPR2 = 0;
+
+   vex_state->guest_REDIR_SP = -1;
+   for (i = 0; i < VEX_GUEST_PPC32_REDIR_STACK_SIZE; i++)
+      vex_state->guest_REDIR_STACK[i] = 0;
+
+   vex_state->guest_CIA_AT_SC = 0;
+   vex_state->guest_SPRG3_RO = 0;
 }
 
 
@@ -620,6 +629,9 @@
    vex_state->guest_REDIR_SP = -1;
    for (i = 0; i < VEX_GUEST_PPC64_REDIR_STACK_SIZE; i++)
       vex_state->guest_REDIR_STACK[i] = 0;
+
+   vex_state->guest_CIA_AT_SC = 0;
+   vex_state->guest_SPRG3_RO = 0;
 }
 
 
@@ -733,7 +745,7 @@
 
           /* Describe any sections to be regarded by Memcheck as
              'always-defined'. */
-          .n_alwaysDefd = 8,
+          .n_alwaysDefd = 12,
 
           .alwaysDefd 
 	  = { /*  0 */ ALWAYSDEFD32(guest_CIA),
@@ -743,7 +755,11 @@
 	      /*  4 */ ALWAYSDEFD32(guest_VSCR),
 	      /*  5 */ ALWAYSDEFD32(guest_FPROUND),
 	      /*  6 */ ALWAYSDEFD32(guest_RESVN),
-	      /*  7 */ ALWAYSDEFD32(guest_NRADDR)
+              /*  7 */ ALWAYSDEFD32(guest_NRADDR),
+	      /*  8 */ ALWAYSDEFD32(guest_NRADDR_GPR2),
+	      /*  9 */ ALWAYSDEFD32(guest_REDIR_SP),
+	      /* 10 */ ALWAYSDEFD32(guest_REDIR_STACK),
+	      /* 11 */ ALWAYSDEFD32(guest_CIA_AT_SC)
             }
         };
 
@@ -767,7 +783,7 @@
 
           /* Describe any sections to be regarded by Memcheck as
              'always-defined'. */
-          .n_alwaysDefd = 11,
+          .n_alwaysDefd = 12,
 
           .alwaysDefd 
 	  = { /*  0 */ ALWAYSDEFD64(guest_CIA),
@@ -780,7 +796,8 @@
 	      /*  7 */ ALWAYSDEFD64(guest_NRADDR),
 	      /*  8 */ ALWAYSDEFD64(guest_NRADDR_GPR2),
 	      /*  9 */ ALWAYSDEFD64(guest_REDIR_SP),
-	      /* 10 */ ALWAYSDEFD64(guest_REDIR_STACK)
+	      /* 10 */ ALWAYSDEFD64(guest_REDIR_STACK),
+	      /* 11 */ ALWAYSDEFD64(guest_CIA_AT_SC)
             }
         };
 
diff --git a/priv/guest-ppc/toIR.c b/priv/guest-ppc/toIR.c
index 9b9e5a7..0d23e73 100644
--- a/priv/guest-ppc/toIR.c
+++ b/priv/guest-ppc/toIR.c
@@ -75,7 +75,7 @@
        Non-Java mode would give us more inaccuracy, as our intermediate
        results would then be zeroed, too.
 
-   - 64-bit mode: AbiHints for the stack red zone are only emitted for
+   - AbiHints for the stack red zone are only emitted for
        unconditional calls and returns (bl, blr).  They should also be
        emitted for conditional calls and returns, but we don't have a 
        way to express that right now.  Ah well.
@@ -102,7 +102,7 @@
       7C210B78 (or 1,1,1)   %R3 = client_request ( %R4 )
       7C421378 (or 2,2,2)   %R3 = guest_NRADDR
       7C631B78 (or 3,3,3)   branch-and-link-to-noredir %R11
-      7C842378 (or 4,4,4)   %R3 = guest_NRADDR_GPR2 (64-bit mode only)
+      7C842378 (or 4,4,4)   %R3 = guest_NRADDR_GPR2
 
    Any other bytes following the 16-byte preamble are illegal and
    constitute a failure in instruction decoding.  This all assumes
@@ -178,17 +178,21 @@
 // Given a pointer to a function as obtained by "& functionname" in C,
 // produce a pointer to the actual entry point for the function.  For
 // most platforms it's the identity function.  Unfortunately, on
-// ppc64-linux it isn't (sigh).
-static void* fnptr_to_fnentry( void* f )
+// ppc64-linux it isn't (sigh) and ditto for ppc32-aix5 and
+// ppc64-aix5.
+static void* fnptr_to_fnentry( VexMiscInfo* vmi, void* f )
 {
-#if defined(__powerpc64__)
-   /* f is a pointer to a 3-word function descriptor, of which
-      the first word is the entry address. */
-   ULong* fdescr = (ULong*)f;
-   return (void*)(fdescr[0]);
-#else
-   return f;
-#endif
+   if (vmi->host_ppc_calls_use_fndescrs) {
+      /* f is a pointer to a 3-word function descriptor, of which the
+         first word is the entry address. */
+      /* note, this is correct even with cross-jitting, since this is
+         purely a host issue, not a guest one. */
+      HWord* fdescr = (HWord*)f;
+      return (void*)(fdescr[0]);
+   } else {
+      /* Simple; "& f" points directly at the code for f. */
+      return f;
+   }
 }
 
 
@@ -213,25 +217,24 @@
    (mode64 ? offsetof(VexGuestPPC64State, _x) : \
              offsetof(VexGuestPPC32State, _x))
 
-#define OFFB_CIA        offsetofPPCGuestState(guest_CIA)
-#define OFFB_LR         offsetofPPCGuestState(guest_LR)
-#define OFFB_CTR        offsetofPPCGuestState(guest_CTR)
-#define OFFB_XER_SO     offsetofPPCGuestState(guest_XER_SO)
-#define OFFB_XER_OV     offsetofPPCGuestState(guest_XER_OV)
-#define OFFB_XER_CA     offsetofPPCGuestState(guest_XER_CA)
-#define OFFB_XER_BC     offsetofPPCGuestState(guest_XER_BC)
-#define OFFB_FPROUND    offsetofPPCGuestState(guest_FPROUND)
-#define OFFB_VRSAVE     offsetofPPCGuestState(guest_VRSAVE)
-#define OFFB_VSCR       offsetofPPCGuestState(guest_VSCR)
-#define OFFB_EMWARN     offsetofPPCGuestState(guest_EMWARN)
-#define OFFB_TISTART    offsetofPPCGuestState(guest_TISTART)
-#define OFFB_TILEN      offsetofPPCGuestState(guest_TILEN)
-#define OFFB_RESVN      offsetofPPCGuestState(guest_RESVN)
-#define OFFB_NRADDR     offsetofPPCGuestState(guest_NRADDR)
-
-/* This only exists in the 64-bit guest state */
-#define OFFB64_NRADDR_GPR2 \
-                        offsetof(VexGuestPPC64State,guest_NRADDR_GPR2)
+#define OFFB_CIA         offsetofPPCGuestState(guest_CIA)
+#define OFFB_CIA_AT_SC   offsetofPPCGuestState(guest_CIA_AT_SC)
+#define OFFB_SPRG3_RO    offsetofPPCGuestState(guest_SPRG3_RO)
+#define OFFB_LR          offsetofPPCGuestState(guest_LR)
+#define OFFB_CTR         offsetofPPCGuestState(guest_CTR)
+#define OFFB_XER_SO      offsetofPPCGuestState(guest_XER_SO)
+#define OFFB_XER_OV      offsetofPPCGuestState(guest_XER_OV)
+#define OFFB_XER_CA      offsetofPPCGuestState(guest_XER_CA)
+#define OFFB_XER_BC      offsetofPPCGuestState(guest_XER_BC)
+#define OFFB_FPROUND     offsetofPPCGuestState(guest_FPROUND)
+#define OFFB_VRSAVE      offsetofPPCGuestState(guest_VRSAVE)
+#define OFFB_VSCR        offsetofPPCGuestState(guest_VSCR)
+#define OFFB_EMWARN      offsetofPPCGuestState(guest_EMWARN)
+#define OFFB_TISTART     offsetofPPCGuestState(guest_TISTART)
+#define OFFB_TILEN       offsetofPPCGuestState(guest_TILEN)
+#define OFFB_RESVN       offsetofPPCGuestState(guest_RESVN)
+#define OFFB_NRADDR      offsetofPPCGuestState(guest_NRADDR)
+#define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
 
 
 /*------------------------------------------------------------*/
@@ -324,6 +327,8 @@
     PPC_GST_TISTART,// For icbi: start of area to invalidate
     PPC_GST_TILEN,  // For icbi: length of area to invalidate
     PPC_GST_RESVN,  // For lwarx/stwcx.
+    PPC_GST_CIA_AT_SC, // the CIA of the most recently executed SC insn
+    PPC_GST_SPRG3_RO, // SPRG3
     PPC_GST_MAX
 } PPC_GST;
 
@@ -1203,19 +1208,28 @@
 }
 
 
-/* Generate AbiHints which mark points at which the ELF ppc64 ABI says
-   that the stack red zone (viz, -288(r1) .. -1(r1)) becomes
-   undefined.  That is at function calls and returns.  Only in 64-bit
-   mode - ELF ppc32 doesn't have this "feature".
+/* Generate AbiHints which mark points at which the ELF or PowerOpen
+   ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
+   N) becomes undefined.  That is at function calls and returns.  ELF
+   ppc32 doesn't have this "feature" (how fortunate for it).
 */
-static void make_redzone_AbiHint ( HChar* who )
+static void make_redzone_AbiHint ( VexMiscInfo* vmi, HChar* who )
 {
+   Int szB = vmi->guest_stack_redzone_size;
    if (0) vex_printf("AbiHint: %s\n", who);
-   vassert(mode64);
-   stmt( IRStmt_AbiHint( 
-            binop(Iop_Sub64, getIReg(1), mkU64(288)), 
-            288 
-   ));
+   vassert(szB >= 0);
+   if (szB > 0) {
+      if (mode64)
+         stmt( IRStmt_AbiHint( 
+                  binop(Iop_Sub64, getIReg(1), mkU64(szB)), 
+                  szB
+         ));
+      else
+         stmt( IRStmt_AbiHint( 
+                  binop(Iop_Sub32, getIReg(1), mkU32(szB)), 
+                  szB
+         ));
+   }
 }
 
 
@@ -2051,6 +2065,12 @@
 {
    IRType ty = mode64 ? Ity_I64 : Ity_I32;
    switch (reg) {
+   case PPC_GST_SPRG3_RO:
+      return IRExpr_Get( OFFB_SPRG3_RO, ty );
+
+   case PPC_GST_CIA: 
+      return IRExpr_Get( OFFB_CIA, ty );
+
    case PPC_GST_LR: 
       return IRExpr_Get( OFFB_LR, ty );
 
@@ -2181,6 +2201,10 @@
    IRType ty_src = typeOfIRExpr(irbb->tyenv,src );
    vassert( reg < PPC_GST_MAX );
    switch (reg) {
+   case PPC_GST_CIA_AT_SC: 
+      vassert( ty_src == ty );
+      stmt( IRStmt_Put( OFFB_CIA_AT_SC, src ) );
+      break;
    case PPC_GST_CIA: 
       vassert( ty_src == ty );
       stmt( IRStmt_Put( OFFB_CIA, src ) );
@@ -3714,7 +3738,7 @@
 /*
   Integer Store Instructions
 */
-static Bool dis_int_store ( UInt theInstr )
+static Bool dis_int_store ( UInt theInstr, VexMiscInfo* vmi )
 {
    /* D-Form, X-Form, DS-Form */
    UChar opc1    = ifieldOPC(theInstr);
@@ -4211,6 +4235,7 @@
   Integer Branch Instructions
 */
 static Bool dis_branch ( UInt theInstr, 
+                         VexMiscInfo* vmi,
                          /*OUT*/DisResult* dres,
                          Bool (*resteerOkFn)(void*,Addr64),
                          void* callback_opaque )
@@ -4263,8 +4288,10 @@
 
       if (flag_LK) {
          putGST( PPC_GST_LR, e_nia );
-         if (mode64)
-            make_redzone_AbiHint( "branch-and-link (unconditional call)" );
+         if (vmi->guest_ppc_zap_RZ_at_bl
+             && vmi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) )
+            make_redzone_AbiHint( vmi, 
+                                  "branch-and-link (unconditional call)" );
       }
 
       if (resteerOkFn( callback_opaque, tgt )) {
@@ -4378,8 +4405,8 @@
                   Ijk_Boring,
                   c_nia ));
 
-	 if (vanilla_return && mode64)
-            make_redzone_AbiHint( "branch-to-lr (unconditional return)" );
+	 if (vanilla_return && vmi->guest_ppc_zap_RZ_at_blr)
+            make_redzone_AbiHint( vmi, "branch-to-lr (unconditional return)" );
 
          /* blrl is pretty strange; it's like a return that sets the
             return address of its caller to the insn following this
@@ -4627,7 +4654,8 @@
 /*
   System Linkage Instructions
 */
-static Bool dis_syslink ( UInt theInstr, DisResult* dres )
+static Bool dis_syslink ( UInt theInstr, 
+                          VexMiscInfo* miscinfo, DisResult* dres )
 {
    IRType ty = mode64 ? Ity_I64 : Ity_I32;
 
@@ -4638,11 +4666,22 @@
 
    // sc  (System Call, PPC32 p504)
    DIP("sc\n");
-   
+
+   /* Copy CIA into the CIA_AT_SC pseudo-register, so that on AIX
+      Valgrind can back the guest up to this instruction if it needs
+      to restart the syscall. */
+   putGST( PPC_GST_CIA_AT_SC, getGST( PPC_GST_CIA ) );
+
    /* It's important that all ArchRegs carry their up-to-date value
       at this point.  So we declare an end-of-block here, which
       forces any TempRegs caching ArchRegs to be flushed. */
-   irbb->next     = mkSzImm( ty, nextInsnAddr() );
+   /* At this point, AIX's behaviour differs from Linux's: AIX resumes
+      after the syscall at %lr, whereas Linux does the obvious thing
+      and resumes at the next instruction.  Hence we need to encode
+      that into the generated IR. */
+   irbb->next     = miscinfo->guest_ppc_sc_continues_at_LR
+                       ? /*AIXishly*/getGST( PPC_GST_LR )
+                       : /*Linuxfully*/mkSzImm( ty, nextInsnAddr() );
    irbb->jumpkind = Ijk_Sys_syscall;
 
    dres->whatNext = Dis_StopHere;
@@ -5193,7 +5232,7 @@
 /*
   Processor Control Instructions
 */
-static Bool dis_proc_ctl ( UInt theInstr )
+static Bool dis_proc_ctl ( VexMiscInfo* vmi, UInt theInstr )
 {
    UChar opc1     = ifieldOPC(theInstr);
    
@@ -5290,7 +5329,12 @@
          putIReg( rD_addr, mkSzWiden32(ty, getGST( PPC_GST_VRSAVE ),
                                        /* Signed */False) );
          break;
-         
+
+      case 0x103:
+         DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
+         putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
+         break;
+
       default:
          vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
          return False;
@@ -5304,7 +5348,7 @@
                               val, 
                               0/*regparms*/, 
                               "ppcg_dirtyhelper_MFTB", 
-                              fnptr_to_fnentry(&ppcg_dirtyhelper_MFTB), 
+                              fnptr_to_fnentry(vmi, &ppcg_dirtyhelper_MFTB), 
                               args );
       /* execute the dirty call, dumping the result in val. */
       stmt( IRStmt_Dirty(d) );
@@ -6708,7 +6752,7 @@
 /*
   AltiVec Load Instructions
 */
-static Bool dis_av_load ( UInt theInstr )
+static Bool dis_av_load ( VexMiscInfo* vmi, UInt theInstr )
 {
    /* X-Form */
    UChar opc1     = ifieldOPC(theInstr);
@@ -6744,13 +6788,13 @@
          d = unsafeIRDirty_0_N (
                         0/*regparms*/, 
                         "ppc32g_dirtyhelper_LVS",
-                        fnptr_to_fnentry(&ppc32g_dirtyhelper_LVS),
+                        fnptr_to_fnentry(vmi, &ppc32g_dirtyhelper_LVS),
                         args );
       } else {
          d = unsafeIRDirty_0_N (
                         0/*regparms*/, 
                         "ppc64g_dirtyhelper_LVS",
-                        fnptr_to_fnentry(&ppc64g_dirtyhelper_LVS),
+                        fnptr_to_fnentry(vmi, &ppc64g_dirtyhelper_LVS),
                         args );
       }
       DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
@@ -6777,13 +6821,13 @@
          d = unsafeIRDirty_0_N (
                         0/*regparms*/, 
                         "ppc32g_dirtyhelper_LVS",
-                        fnptr_to_fnentry(&ppc32g_dirtyhelper_LVS),
+                        fnptr_to_fnentry(vmi, &ppc32g_dirtyhelper_LVS),
                         args );
       } else {
          d = unsafeIRDirty_0_N (
                         0/*regparms*/, 
                         "ppc64g_dirtyhelper_LVS",
-                        fnptr_to_fnentry(&ppc64g_dirtyhelper_LVS),
+                        fnptr_to_fnentry(vmi, &ppc64g_dirtyhelper_LVS),
                         args );
       }
       DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
@@ -8694,7 +8738,8 @@
              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
              void*        callback_opaque,
              Long         delta64,
-             VexArchInfo* archinfo 
+             VexArchInfo* archinfo,
+             VexMiscInfo* miscinfo
           )
 {
    UChar     opc1;
@@ -8797,14 +8842,12 @@
             goto decode_success;
          }
          else
-         if (mode64 
-             && getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
+         if (getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
             /* %R3 = guest_NRADDR_GPR2 */
             DIP("r3 = guest_NRADDR_GPR2\n");
             delta += 20;
             dres.len = 20;
-            vassert(ty == Ity_I64);
-            putIReg(3, IRExpr_Get( OFFB64_NRADDR_GPR2, ty ));
+            putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
             goto decode_success;
          }
          /* We don't know what it is.  Set opc1/opc2 so decode_failure
@@ -8860,7 +8903,7 @@
    /* Integer Store Instructions */
    case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
    case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
-      if (dis_int_store( theInstr )) goto decode_success;
+      if (dis_int_store( theInstr, miscinfo )) goto decode_success;
       goto decode_failure;
 
    /* Integer Load and Store Multiple Instructions */
@@ -8870,13 +8913,14 @@
 
    /* Branch Instructions */
    case 0x12: case 0x10: // b, bc
-      if (dis_branch(theInstr, &dres, resteerOkFn, callback_opaque)) 
+      if (dis_branch(theInstr, miscinfo, &dres, 
+                               resteerOkFn, callback_opaque)) 
          goto decode_success;
       goto decode_failure;
 
    /* System Linkage Instructions */
    case 0x11: // sc
-      if (dis_syslink(theInstr, &dres)) goto decode_success;
+      if (dis_syslink(theInstr, miscinfo, &dres)) goto decode_success;
       goto decode_failure;
 
    /* Trap Instructions */
@@ -8941,7 +8985,7 @@
    /* 64bit Integer Stores */
    case 0x3E:  // std, stdu
       if (!mode64) goto decode_failure;
-      if (dis_int_store( theInstr )) goto decode_success;
+      if (dis_int_store( theInstr, miscinfo )) goto decode_success;
       goto decode_failure;
 
    case 0x3F:
@@ -9033,7 +9077,8 @@
          
       /* Branch Instructions */
       case 0x210: case 0x010: // bcctr, bclr
-         if (dis_branch(theInstr, &dres, resteerOkFn, callback_opaque)) 
+         if (dis_branch(theInstr, miscinfo, &dres, 
+                                  resteerOkFn, callback_opaque)) 
             goto decode_success;
          goto decode_failure;
          
@@ -9129,13 +9174,13 @@
       /* Integer Store Instructions */
       case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
       case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
-         if (dis_int_store( theInstr )) goto decode_success;
+         if (dis_int_store( theInstr, miscinfo )) goto decode_success;
          goto decode_failure;
 
       /* 64bit Integer Store Instructions */
       case 0x0B5: case 0x095: // stdux, stdx
          if (!mode64) goto decode_failure;
-         if (dis_int_store( theInstr )) goto decode_success;
+         if (dis_int_store( theInstr, miscinfo )) goto decode_success;
          goto decode_failure;
 
       /* Integer Load and Store with Byte Reverse Instructions */
@@ -9173,7 +9218,7 @@
       /* Processor Control Instructions */
       case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
       case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
-         if (dis_proc_ctl( theInstr )) goto decode_success;
+         if (dis_proc_ctl( miscinfo, theInstr )) goto decode_success;
          goto decode_failure;
 
       /* Cache Management Instructions */
@@ -9229,7 +9274,7 @@
       case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
       case 0x067: case 0x167:             // lvx, lvxl
          if (!allow_V) goto decode_noV;
-         if (dis_av_load( theInstr )) goto decode_success;
+         if (dis_av_load( miscinfo, theInstr )) goto decode_success;
          goto decode_failure;
 
       /* AV Store */
@@ -9469,6 +9514,7 @@
                          Addr64       guest_IP,
                          VexArch      guest_arch,
                          VexArchInfo* archinfo,
+                         VexMiscInfo* miscinfo,
                          Bool         host_bigendian_IN )
 {
    IRType     ty;
@@ -9504,7 +9550,7 @@
    guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
 
    dres = disInstr_PPC_WRK ( put_IP, resteerOkFn, callback_opaque,
-                             delta, archinfo );
+                             delta, archinfo, miscinfo );
 
    return dres;
 }
diff --git a/priv/guest-x86/gdefs.h b/priv/guest-x86/gdefs.h
index 4ceaaa8..1a53a48 100644
--- a/priv/guest-x86/gdefs.h
+++ b/priv/guest-x86/gdefs.h
@@ -66,6 +66,7 @@
                          Addr64       guest_IP,
                          VexArch      guest_arch,
                          VexArchInfo* archinfo,
+                         VexMiscInfo* miscinfo,
                          Bool         host_bigendian );
 
 /* Used by the optimiser to specialise calls to helpers. */
diff --git a/priv/guest-x86/toIR.c b/priv/guest-x86/toIR.c
index 8edb730..08ae111 100644
--- a/priv/guest-x86/toIR.c
+++ b/priv/guest-x86/toIR.c
@@ -12902,6 +12902,7 @@
                          Addr64       guest_IP,
                          VexArch      guest_arch,
                          VexArchInfo* archinfo,
+                         VexMiscInfo* miscinfo,
                          Bool         host_bigendian_IN )
 {
    DisResult dres;
diff --git a/priv/host-amd64/hdefs.h b/priv/host-amd64/hdefs.h
index a8475e9..9fd5ee6 100644
--- a/priv/host-amd64/hdefs.h
+++ b/priv/host-amd64/hdefs.h
@@ -725,7 +725,9 @@
 extern AMD64Instr*  genSpill_AMD64         ( HReg rreg, Int offset, Bool );
 extern AMD64Instr*  genReload_AMD64        ( HReg rreg, Int offset, Bool );
 extern void         getAllocableRegs_AMD64 ( Int*, HReg** );
-extern HInstrArray* iselBB_AMD64           ( IRBB*, VexArch, VexArchInfo* );
+extern HInstrArray* iselBB_AMD64           ( IRBB*, VexArch,
+                                                    VexArchInfo*,
+                                                    VexMiscInfo* );
 
 #endif /* ndef __LIBVEX_HOST_AMD64_HDEFS_H */
 
diff --git a/priv/host-amd64/isel.c b/priv/host-amd64/isel.c
index 5911779..07b159d 100644
--- a/priv/host-amd64/isel.c
+++ b/priv/host-amd64/isel.c
@@ -3801,8 +3801,9 @@
 
 /* Translate an entire BB to amd64 code. */
 
-HInstrArray* iselBB_AMD64 ( IRBB* bb, VexArch arch_host,
-                                      VexArchInfo* archinfo_host )
+HInstrArray* iselBB_AMD64 ( IRBB* bb, VexArch      arch_host,
+                                      VexArchInfo* archinfo_host,
+                                      VexMiscInfo* vmi/*UNUSED*/ )
 {
    Int      i, j;
    HReg     hreg, hregHI;
diff --git a/priv/host-ppc/hdefs.c b/priv/host-ppc/hdefs.c
index 9c866dd..2085157 100644
--- a/priv/host-ppc/hdefs.c
+++ b/priv/host-ppc/hdefs.c
@@ -1123,67 +1123,13 @@
 
 /* Pretty Print instructions */
 static void ppLoadImm ( HReg dst, ULong imm, Bool mode64 ) {
-#if 1
    vex_printf("li_word ");
    ppHRegPPC(dst);
    if (!mode64) {
-      vassert(imm == (ULong)(Long)(Int)(UInt)imm);
       vex_printf(",0x%08x", (UInt)imm);
    } else {
       vex_printf(",0x%016llx", imm);
    }
-#else
-   if (imm >= 0xFFFFFFFFFFFF8000ULL || imm < 0x8000) {
-      // sign-extendable from 16 bits
-      vex_printf("li ");
-      ppHRegPPC(dst);
-      vex_printf(",0x%x", (UInt)imm);
-   } else {
-      if (imm >= 0xFFFFFFFF80000000ULL || imm < 0x80000000ULL) {
-         // sign-extendable from 32 bits
-         vex_printf("lis ");
-         ppHRegPPC(dst);
-         vex_printf(",0x%x ; ", (UInt)(imm >> 16));
-         vex_printf("ori ");
-         ppHRegPPC(dst);
-         vex_printf(",");
-         ppHRegPPC(dst);
-         vex_printf(",0x%x", (UInt)(imm & 0xFFFF));
-      } else {
-         // full 64bit immediate load: 5 (five!) insns.
-         vassert(mode64);
-
-         // load high word
-         vex_printf("lis ");
-         ppHRegPPC(dst);
-         vex_printf(",0x%x ; ", (UInt)(imm >> 48) & 0xFFFF);
-         vex_printf("ori ");
-         ppHRegPPC(dst);
-         vex_printf(",");
-         ppHRegPPC(dst);
-         vex_printf(",0x%x ; ", (UInt)(imm >> 32) & 0xFFFF);
-         
-         // shift r_dst low word to high word => rldicr
-         vex_printf("rldicr ");
-         ppHRegPPC(dst);
-         vex_printf(",");
-         ppHRegPPC(dst);
-         vex_printf(",32,31 ; ");
-
-         // load low word
-         vex_printf("oris ");
-         ppHRegPPC(dst);
-         vex_printf(",");
-         ppHRegPPC(dst);
-         vex_printf(",0x%x ; ", (UInt)(imm >> 16) & 0xFFFF);
-         vex_printf("ori ");
-         ppHRegPPC(dst);
-         vex_printf(",");
-         ppHRegPPC(dst);
-         vex_printf(",0x%x", (UInt)(imm >>  0) & 0xFFFF);
-      }
-   }
-#endif
 }
 
 static void ppMovReg ( HReg dst, HReg src ) {
@@ -2496,19 +2442,26 @@
          vassert(mode64);
 
          // load high word
+
          // lis r_dst, (imm>>48) & 0xFFFF
          p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF);
+
          // ori r_dst, r_dst, (imm>>32) & 0xFFFF
-         p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF);
+         if ((imm>>32) & 0xFFFF)
+            p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF);
          
          // shift r_dst low word to high word => rldicr
          p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1);
 
          // load low word
+
          // oris r_dst, r_dst, (imm>>16) & 0xFFFF
-         p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF);
+         if ((imm>>16) & 0xFFFF)
+            p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF);
+
          // ori r_dst, r_dst, (imm) & 0xFFFF
-         p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
+         if (imm & 0xFFFF)
+            p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
       }
    }
    return p;
diff --git a/priv/host-ppc/hdefs.h b/priv/host-ppc/hdefs.h
index 54d3f74..ca71731 100644
--- a/priv/host-ppc/hdefs.h
+++ b/priv/host-ppc/hdefs.h
@@ -838,7 +838,9 @@
 extern PPCInstr*    genSpill_PPC         ( HReg rreg, UShort offsetB, Bool mode64 );
 extern PPCInstr*    genReload_PPC        ( HReg rreg, UShort offsetB, Bool mode64 );
 extern void         getAllocableRegs_PPC ( Int*, HReg**, Bool mode64 );
-extern HInstrArray* iselBB_PPC           ( IRBB*, VexArch, VexArchInfo* );
+extern HInstrArray* iselBB_PPC           ( IRBB*, VexArch,
+                                                  VexArchInfo*,
+                                                  VexMiscInfo* );
 
 #endif /* ndef __LIBVEX_HOST_PPC_HDEFS_H */
 
diff --git a/priv/host-ppc/isel.c b/priv/host-ppc/isel.c
index 89f88d3..4dda13d 100644
--- a/priv/host-ppc/isel.c
+++ b/priv/host-ppc/isel.c
@@ -253,6 +253,9 @@
       was most recently set.  Setting to NULL is always safe.  Used to
       avoid redundant settings of the FPU's rounding mode, as
       described in set_FPU_rounding_mode below.
+
+    - A VexMiscInfo*, needed for knowing how to generate
+      function calls for this target
 */
  
 typedef
@@ -275,6 +278,8 @@
       Bool         mode64;
 
       IRExpr*      previous_rm;
+
+      VexMiscInfo* vmi;
    }
    ISelEnv;
  
@@ -532,7 +537,7 @@
 
 /* Given a guest-state array descriptor, an index expression and a
    bias, generate a PPCAMode pointing at the relevant piece of 
-   guest state.  Only needed in 64-bit mode. */
+   guest state.  */
 static
 PPCAMode* genGuestArrayOffset ( ISelEnv* env, IRArray* descr,
                                 IRExpr* off, Int bias )
@@ -542,23 +547,22 @@
    Int  nElems = descr->nElems;
    Int  shift  = 0;
 
-   vassert(env->mode64);
-
    /* Throw out any cases we don't need.  In theory there might be a
       day where we need to handle others, but not today. */
 
    if (nElems != 16 && nElems != 32)
-      vpanic("genGuestArrayOffset(ppc64 host)(1)");
+      vpanic("genGuestArrayOffset(ppc host)(1)");
 
    switch (elemSz) {
+      case 4:  shift = 2; break;
       case 8:  shift = 3; break;
-      default: vpanic("genGuestArrayOffset(ppc64 host)(2)");
+      default: vpanic("genGuestArrayOffset(ppc host)(2)");
    }
 
    if (bias < -100 || bias > 100) /* somewhat arbitrarily */
-      vpanic("genGuestArrayOffset(ppc64 host)(3)");
+      vpanic("genGuestArrayOffset(ppc host)(3)");
    if (descr->base < 0 || descr->base > 2000) /* somewhat arbitrarily */
-     vpanic("genGuestArrayOffset(ppc64 host)(4)");
+     vpanic("genGuestArrayOffset(ppc host)(4)");
 
    /* Compute off into a reg, %off.  Then return:
 
@@ -580,7 +584,7 @@
                     PPCRH_Imm(False/*signed*/, toUShort(nElems-1))));
    addInstr(env, PPCInstr_Shft(
                     Pshft_SHL, 
-                    False/*64-bit shift*/,
+                    env->mode64 ? False : True/*F:64-bit, T:32-bit shift*/,
                     rtmp, rtmp, 
                     PPCRH_Imm(False/*unsigned*/, toUShort(shift))));
    addInstr(env, PPCInstr_Alu(
@@ -631,6 +635,11 @@
    ULong       target;
    Bool        mode64 = env->mode64;
 
+   /* Do we need to force use of an odd-even reg pair for 64-bit
+      args? */
+   Bool regalign_int64s
+      = (!mode64) && env->vmi->host_ppc32_regalign_int64_args;
+
    /* Marshal args for a call and do the call.
 
       If passBBP is True, %rbp (the baseblock pointer) is to be passed
@@ -756,8 +765,9 @@
                                       iselWordExpr_R(env, args[i]) ));
             } else { // Ity_I64
                HReg rHi, rLo;
-               if (argreg%2 == 1) // ppc32 abi spec for passing LONG_LONG
-                  argreg++;       // XXX: odd argreg => even rN
+               if (regalign_int64s && (argreg%2) == 1) 
+                              // ppc32 ELF abi spec for passing LONG_LONG
+                  argreg++;   // XXX: odd argreg => even rN
                vassert(argreg < PPC_N_REGPARMS-1);
                iselInt64Expr(&rHi,&rLo, env, args[i]);
                argiregs |= (1 << (argreg+3));
@@ -799,8 +809,9 @@
                tmpregs[argreg] = iselWordExpr_R(env, args[i]);
             } else { // Ity_I64
                HReg rHi, rLo;
-               if (argreg%2 == 1) // ppc32 abi spec for passing LONG_LONG
-                  argreg++;       // XXX: odd argreg => even rN
+               if (regalign_int64s && (argreg%2) == 1)
+                             // ppc32 ELF abi spec for passing LONG_LONG
+                  argreg++;  // XXX: odd argreg => even rN
                vassert(argreg < PPC_N_REGPARMS-1);
                iselInt64Expr(&rHi,&rLo, env, args[i]);
                tmpregs[argreg++] = rHi;
@@ -1788,17 +1799,23 @@
       break;
    }
 
-   case Iex_GetI: 
+   case Iex_GetI: {
+      PPCAMode* src_am
+         = genGuestArrayOffset( env, e->Iex.GetI.descr,
+                                     e->Iex.GetI.ix, e->Iex.GetI.bias );
+      HReg r_dst = newVRegI(env);
       if (mode64 && ty == Ity_I64) {
-         PPCAMode* src_am
-            = genGuestArrayOffset( env, e->Iex.GetI.descr,
-                                        e->Iex.GetI.ix, e->Iex.GetI.bias );
-         HReg r_dst = newVRegI(env);
          addInstr(env, PPCInstr_Load( toUChar(8),
                                       r_dst, src_am, mode64 ));
          return r_dst;
       }
+      if ((!mode64) && ty == Ity_I32) {
+         addInstr(env, PPCInstr_Load( toUChar(4),
+                                      r_dst, src_am, mode64 ));
+         return r_dst;
+      }
       break;
+   }
 
    /* --------- CCALL --------- */
    case Iex_CCall: {
@@ -2485,8 +2502,8 @@
       HReg  tLo = newVRegI(env);
       HReg  tHi = newVRegI(env);
       vassert(e->Iex.Const.con->tag == Ico_U64);
-      addInstr(env, PPCInstr_LI(tHi, wHi, False/*mode32*/));
-      addInstr(env, PPCInstr_LI(tLo, wLo, False/*mode32*/));
+      addInstr(env, PPCInstr_LI(tHi, (Long)(Int)wHi, False/*mode32*/));
+      addInstr(env, PPCInstr_LI(tLo, (Long)(Int)wLo, False/*mode32*/));
       *rHi = tHi;
       *rLo = tLo;
       return;
@@ -3674,21 +3691,26 @@
    }
       
    /* --------- Indexed PUT --------- */
-   case Ist_PutI:
-      if (mode64) {
-         PPCAMode* dst_am
-            = genGuestArrayOffset(
-                 env, stmt->Ist.PutI.descr, 
-                      stmt->Ist.PutI.ix, stmt->Ist.PutI.bias );
-         IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data);
-         if (ty == Ity_I64) {
-            HReg r_src = iselWordExpr_R(env, stmt->Ist.PutI.data);
-            addInstr(env, PPCInstr_Store( toUChar(8),
-                                          dst_am, r_src, mode64 ));
-            return;
-         }
+   case Ist_PutI: {
+      PPCAMode* dst_am
+         = genGuestArrayOffset(
+              env, stmt->Ist.PutI.descr, 
+                   stmt->Ist.PutI.ix, stmt->Ist.PutI.bias );
+      IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data);
+      if (mode64 && ty == Ity_I64) {
+         HReg r_src = iselWordExpr_R(env, stmt->Ist.PutI.data);
+         addInstr(env, PPCInstr_Store( toUChar(8),
+                                       dst_am, r_src, mode64 ));
+         return;
+      }
+      if ((!mode64) && ty == Ity_I32) {
+         HReg r_src = iselWordExpr_R(env, stmt->Ist.PutI.data);
+         addInstr(env, PPCInstr_Store( toUChar(4),
+                                       dst_am, r_src, mode64 ));
+         return;
       }
       break;
+   }
 
    /* --------- TMP --------- */
    case Ist_Tmp: {
@@ -3856,8 +3878,9 @@
 
 /* Translate an entire BB to ppc code. */
 
-HInstrArray* iselBB_PPC ( IRBB* bb, VexArch arch_host,
-                                    VexArchInfo* archinfo_host )
+HInstrArray* iselBB_PPC ( IRBB* bb, VexArch      arch_host,
+                                    VexArchInfo* archinfo_host,
+                                    VexMiscInfo* vmi )
 {
    Int      i, j;
    HReg     hreg, hregHI;
@@ -3904,6 +3927,7 @@
    /* and finally ... */
    env->hwcaps      = hwcaps_host;
    env->previous_rm = NULL;
+   env->vmi         = vmi;
 
    /* For each IR temporary, allocate a suitably-kinded virtual
       register. */
diff --git a/priv/host-x86/hdefs.h b/priv/host-x86/hdefs.h
index c4ea61d..2958190 100644
--- a/priv/host-x86/hdefs.h
+++ b/priv/host-x86/hdefs.h
@@ -665,7 +665,9 @@
 extern X86Instr*    genSpill_X86         ( HReg rreg, Int offset, Bool );
 extern X86Instr*    genReload_X86        ( HReg rreg, Int offset, Bool );
 extern void         getAllocableRegs_X86 ( Int*, HReg** );
-extern HInstrArray* iselBB_X86           ( IRBB*, VexArch, VexArchInfo* );
+extern HInstrArray* iselBB_X86           ( IRBB*, VexArch,
+                                                  VexArchInfo*,
+                                                  VexMiscInfo* );
 
 #endif /* ndef __LIBVEX_HOST_X86_HDEFS_H */
 
diff --git a/priv/host-x86/isel.c b/priv/host-x86/isel.c
index 22e3ef6..d22b656 100644
--- a/priv/host-x86/isel.c
+++ b/priv/host-x86/isel.c
@@ -3604,8 +3604,9 @@
 
 /* Translate an entire BB to x86 code. */
 
-HInstrArray* iselBB_X86 ( IRBB* bb, VexArch arch_host,
-                                    VexArchInfo* archinfo_host )
+HInstrArray* iselBB_X86 ( IRBB* bb, VexArch      arch_host,
+                                    VexArchInfo* archinfo_host,
+                                    VexMiscInfo* vmi/*UNUSED*/ )
 {
    Int      i, j;
    HReg     hreg, hregHI;
diff --git a/priv/main/vex_main.c b/priv/main/vex_main.c
index 0475f68..a590774 100644
--- a/priv/main/vex_main.c
+++ b/priv/main/vex_main.c
@@ -193,7 +193,8 @@
    HInstr*      (*genReload)   ( HReg, Int, Bool );
    void         (*ppInstr)     ( HInstr*, Bool );
    void         (*ppReg)       ( HReg );
-   HInstrArray* (*iselBB)      ( IRBB*, VexArch, VexArchInfo* );
+   HInstrArray* (*iselBB)      ( IRBB*, VexArch, VexArchInfo*, 
+                                                 VexMiscInfo* );
    Int          (*emit)        ( UChar*, Int, HInstr*, Bool, void* );
    IRExpr*      (*specHelper)  ( HChar*, IRExpr** );
    Bool         (*preciseMemExnsFn) ( Int, Int );
@@ -432,6 +433,7 @@
                      host_is_bigendian,
                      vta->arch_guest,
                      &vta->archinfo_guest,
+                     &vta->miscinfo_both,
                      guest_word_type,
                      vta->do_self_check,
                      vta->preamble_function,
@@ -558,7 +560,8 @@
                    " Instruction selection "
                    "------------------------\n");
 
-   vcode = iselBB ( irbb, vta->arch_host, &vta->archinfo_host );
+   vcode = iselBB ( irbb, vta->arch_host, &vta->archinfo_host, 
+                                          &vta->miscinfo_both );
 
    vexAllocSanityCheck();
 
@@ -695,7 +698,6 @@
 }
 
 
-
 /* Write default settings info *vai. */
 void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
 {
@@ -703,6 +705,17 @@
    vai->ppc_cache_line_szB = 0;
 }
 
+/* Write default settings info *vmi. */
+void LibVEX_default_VexMiscInfo ( /*OUT*/VexMiscInfo* vmi )
+{
+   vmi->guest_stack_redzone_size       = 0;
+   vmi->guest_ppc_zap_RZ_at_blr        = False;
+   vmi->guest_ppc_zap_RZ_at_bl         = NULL;
+   vmi->guest_ppc_sc_continues_at_LR   = False;
+   vmi->host_ppc_calls_use_fndescrs    = False;
+   vmi->host_ppc32_regalign_int64_args = False;
+}
+
 
 /* Return a string showing the hwcaps in a nice way.  The string will
    be NULL for invalid combinations of flags, so these functions also
diff --git a/pub/libvex.h b/pub/libvex.h
index 26fe0b0..f1cbd97 100644
--- a/pub/libvex.h
+++ b/pub/libvex.h
@@ -110,8 +110,8 @@
 
 
 /* This struct is a bit of a hack, but is needed to carry misc
-   important bits of info about an arch.  Fields which are optional or
-   ignored on some arch should be set to zero. */
+   important bits of info about an arch.  Fields which are meaningless
+   or ignored for the platform in question should be set to zero. */
 
 typedef
    struct {
@@ -127,6 +127,90 @@
 void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai );
 
 
+/* This struct carries guest and host ABI variant information that may
+   be needed.  Fields which are meaningless or ignored for the
+   platform in question should be set to zero.
+
+   Settings which are believed to be correct are:
+
+   guest_stack_redzone_size
+      guest is ppc32-linux                ==> 0
+      guest is ppc64-linux                ==> 288
+      guest is ppc32-aix5                 ==> 220
+      guest is ppc64-aix5                 ==> unknown
+      guest is amd64-linux                ==> 128
+      guest is other                      ==> inapplicable
+
+   guest_ppc_zap_RZ_at_blr
+      guest is ppc64-linux                ==> True
+      guest is ppc32-linux                ==> False
+      guest is ppc64-aix5                 ==> unknown
+      guest is ppc32-aix5                 ==> False
+      guest is other                      ==> inapplicable
+
+   guest_ppc_zap_RZ_at_bl
+      guest is ppc64-linux                ==> const True
+      guest is ppc32-linux                ==> const False
+      guest is ppc64-aix5                 ==> unknown
+      guest is ppc32-aix5                 ==> True except for calls to
+                                              millicode, $SAVEFn, $RESTFn
+      guest is other                      ==> inapplicable
+
+   guest_ppc_sc_continues_at_LR:
+      guest is ppc32-aix5  or ppc64-aix5  ==> True
+      guest is ppc32-linux or ppc64-linux ==> False
+      guest is other                      ==> inapplicable
+
+   host_ppc_calls_use_fndescrs:
+      host is ppc32-linux                 ==> False
+      host is ppc64-linux                 ==> True
+      host is ppc32-aix5 or ppc64-aix5    ==> True
+      host is other                       ==> inapplicable
+
+   host_ppc32_regalign_int64_args:
+      host is ppc32-linux                 ==> True
+      host is ppc32-aix5                  ==> False
+      host is other                       ==> inapplicable
+*/
+
+typedef
+   struct {
+      /* PPC and AMD64 GUESTS only: how many bytes below the 
+         stack pointer are validly addressible? */
+      Int guest_stack_redzone_size;
+
+      /* PPC GUESTS only: should we zap the stack red zone at a 'blr'
+         (function return) ? */
+      Bool guest_ppc_zap_RZ_at_blr;
+
+      /* PPC GUESTS only: should we zap the stack red zone at a 'bl'
+         (function call) ?  Is supplied with the guest address of the
+         target of the call since that may be significant.  If NULL,
+         is assumed equivalent to a fn which always returns False. */
+      Bool (*guest_ppc_zap_RZ_at_bl)(Addr64);
+
+      /* PPC32/PPC64 GUESTS only: where does the kernel resume after
+         'sc'?  False => Linux style, at the next insn.  True => AIX
+         style, at the address stated in the link register. */
+      Bool guest_ppc_sc_continues_at_LR;
+
+      /* PPC32/PPC64 HOSTS only: does '&f' give us a pointer to a
+         function descriptor on the host, or to the function code
+         itself?  True => descriptor, False => code. */
+      Bool host_ppc_calls_use_fndescrs;
+
+      /* PPC32 HOSTS only: when generating code to pass a 64-bit value
+         (actual parameter) in a pair of regs, should we skip an arg
+         reg if it is even-numbered?  True => yes, False => no. */
+      Bool host_ppc32_regalign_int64_args;
+   }
+   VexMiscInfo;
+
+/* Write default settings info *vmi. */
+extern 
+void LibVEX_default_VexMiscInfo ( /*OUT*/VexMiscInfo* vmi );
+
+
 /*-------------------------------------------------------*/
 /*--- Control of Vex's optimiser (iropt).             ---*/
 /*-------------------------------------------------------*/
@@ -320,11 +404,13 @@
    many of them, it seems better to have a structure. */
 typedef
    struct {
-      /* IN: The instruction sets we are translating from and to. */
+      /* IN: The instruction sets we are translating from and to.  And
+         guest/host misc info. */
       VexArch      arch_guest;
       VexArchInfo  archinfo_guest;
       VexArch      arch_host;
       VexArchInfo  archinfo_host;
+      VexMiscInfo  miscinfo_both;
 
       /* IN: an opaque value which is passed as the first arg to all
          callback functions supplied in this struct.  Vex has no idea
diff --git a/pub/libvex_basictypes.h b/pub/libvex_basictypes.h
index 370f5f9..d22bc63 100644
--- a/pub/libvex_basictypes.h
+++ b/pub/libvex_basictypes.h
@@ -135,6 +135,7 @@
 
 #undef VEX_HOST_WORDSIZE
 
+/* The following 4 work OK for Linux. */
 #if defined(__x86_64__)
 #   define VEX_HOST_WORDSIZE 8
 #elif defined(__i386__)
@@ -143,6 +144,12 @@
 #   define VEX_HOST_WORDSIZE 8
 #elif defined(__powerpc__) && !defined(__powerpc64__)
 #   define VEX_HOST_WORDSIZE 4
+
+#elif defined(_AIX) && !defined(__64BIT__)
+#   define VEX_HOST_WORDSIZE 4
+#elif defined(_AIX) && defined(__64BIT__)
+#   define VEX_HOST_WORDSIZE 8
+
 #else
 #   error "Vex: Fatal: Can't establish the host architecture"
 #endif
diff --git a/pub/libvex_guest_ppc32.h b/pub/libvex_guest_ppc32.h
index 4203e3b..7c8bb9b 100644
--- a/pub/libvex_guest_ppc32.h
+++ b/pub/libvex_guest_ppc32.h
@@ -55,6 +55,8 @@
 /*--- Vex's representation of the PPC32 CPU state             ---*/
 /*---------------------------------------------------------------*/
 
+#define VEX_GUEST_PPC32_REDIR_STACK_SIZE (16/*entries*/ * 2/*words per entry*/)
+
 typedef
    struct {
       /* General Purpose Registers */
@@ -214,10 +216,25 @@
          Note, this is only set for wrap-style redirects, not for
          replace-style ones. */
       /* 956 */ UInt guest_NRADDR;
+      /* 960 */ UInt guest_NRADDR_GPR2; /* needed by aix */
+
+     /* A grows-upwards stack for hidden saves/restores of LR and R2
+        needed for function interception and wrapping on ppc32-aix5.
+        A horrible hack.  REDIR_SP points to the highest live entry,
+        and so starts at -1. */
+      /* 964 */ UInt guest_REDIR_SP;
+      /* 968 */ UInt guest_REDIR_STACK[VEX_GUEST_PPC32_REDIR_STACK_SIZE];
+
+      /* Needed for AIX: CIA at the last SC insn.  Used when backing up
+         to restart a syscall that has been interrupted by a signal. */
+      /* ??? */ UInt guest_CIA_AT_SC; 
+
+      /* SPRG3, which AIUI is readonly in user space.  Needed for
+         threading on AIX. */
+      /* ??? */ UInt guest_SPRG3_RO;
 
       /* Padding to make it have an 8-aligned size */
-      /* 956 */ UInt  padding;
-      /* 960 */
+      /* UInt  padding; */
    }
    VexGuestPPC32State;
 
diff --git a/pub/libvex_guest_ppc64.h b/pub/libvex_guest_ppc64.h
index fec4e56..12b7134 100644
--- a/pub/libvex_guest_ppc64.h
+++ b/pub/libvex_guest_ppc64.h
@@ -266,6 +266,14 @@
       /* 1128 */ ULong guest_REDIR_SP;
       /* 1136 */ ULong guest_REDIR_STACK[VEX_GUEST_PPC64_REDIR_STACK_SIZE];
 
+      /* Needed for AIX: CIA at the last SC insn.  Used when backing up
+         to restart a syscall that has been interrupted by a signal. */
+      /* ???? */ ULong guest_CIA_AT_SC; 
+
+      /* SPRG3, which AIUI is readonly in user space.  Needed for
+         threading on AIX. */
+      /* ???? */ ULong guest_SPRG3_RO;
+
       /* Padding to make it have an 8-aligned size */
       /* UInt  padding; */
    }
diff --git a/quote.txt b/quote.txt
new file mode 100644
index 0000000..9d68933
--- /dev/null
+++ b/quote.txt
@@ -0,0 +1 @@
+"
\ No newline at end of file
diff --git a/test_main.c b/test_main.c
index 0680ae4..3ca12ce 100644
--- a/test_main.c
+++ b/test_main.c
@@ -67,6 +67,7 @@
    VexControl vcon;
    VexGuestExtents vge;
    VexArchInfo vai_x86, vai_amd64, vai_ppc32;
+   VexMiscInfo vmi;
    VexTranslateArgs vta;
 
    if (argc != 2) {
@@ -135,6 +136,8 @@
       vai_ppc32.hwcaps = 0;
       vai_ppc32.ppc_cache_line_szB = 128;
 
+      LibVEX_default_VexMiscInfo(&vmi);
+
       /* ----- Set up args for LibVEX_Translate ----- */
 #if 1 /* ppc32 -> ppc32 */
       vta.arch_guest     = VexArchPPC32;
@@ -154,6 +157,7 @@
       vta.arch_host      = VexArchX86;
       vta.archinfo_host  = vai_x86;
 #endif
+      vta.miscinfo_both   = vmi;
       vta.guest_bytes     = origbuf;
       vta.guest_bytes_addr = (Addr64)orig_addr;
       vta.callback_opaque = NULL;