diff --git a/src/code/ppc32.c b/src/code/ppc32.c
index c1478b006d214203e7b9904128e6b9b7855b1077..66623ee093436ce0e32ad10b592919d8a524980b 100644
--- a/src/code/ppc32.c
+++ b/src/code/ppc32.c
@@ -413,9 +413,22 @@ static void maybe_update_pc(void)
   }
 }
 
+#ifdef OPCODE_INLINE_RETURN
+void ppc32_ins_entry(void)
+{
+  /* stwu r1, -32(r1) */
+  STWU(1, 1, -32);
+  /* mflr r0 */
+  MFSPR(0, PPC_SPREG_LR);
+  /* stw r0, 36(r1) */
+  STW(0, 1, 36);
+}
+#endif /* OPCODE_INLINE_RETURN */
+
 void ins_f_byte(unsigned int b)
 {
   void *addr;
+  INT32 rel_addr;
 
   b-=F_OFFSET;
 #ifdef PIKE_DEBUG
@@ -465,10 +478,54 @@ void ins_f_byte(unsigned int b)
   case F_ESCAPE_CATCH - F_OFFSET:
     ppc32_escape_catch();
     return;
+
+#ifdef OPCODE_INLINE_RETURN
+  case F_CATCH - F_OFFSET:
+    /* Special argument for the F_CATCH instruction. */
+    addr = inter_return_opcode_F_CATCH;
+    /* bl .+4 */
+    BL(4);
+    /* mflr r3 */
+    MFSPR(PPC_REG_ARG1, PPC_SPREG_LR);
+    rel_addr = PIKE_PC;
+    /* addi r3, r3, offs */
+    ADDI(PPC_REG_ARG1, PPC_REG_ARG1, 4);
+    break;
+#endif
   }
 
   FLUSH_CODE_GENERATOR_STATE();
   ADD_CALL(addr);
+#ifdef OPCODE_INLINE_RETURN
+  if (instrs[b].flags & I_RETURN) {
+    /* cmpwi r3,-1 */
+    CMPI(0, PPC_REG_RET, -1);
+    /* bne .+20 */
+    BC(4, 2, 5);
+    /* lwz r0, 36(r1) */
+    LWZ(0, 1, 36);
+    /* addi r1, r1, 32 */
+    ADDI(1, 1, 32);
+    /* mtlr r0 */
+    MTSPR(0, PPC_SPREG_LR);
+    /* blr */
+    BCLR(20, 0);
+
+    if ((b + F_OFFSET) == F_RETURN_IF_TRUE) {
+      /* Kludge. We must check if the ret addr is
+       * orig_addr + JUMP_EPILOGUE_SIZE. */
+
+      /* mflr r0 */
+      MFSPR(0, PPC_SPREG_LR);
+      /* subf r0, r0, r3 */
+      SUBF(0, 0, PPC_REG_RET);
+      /* cmplwi r0, JUMP_EPILOGUE_SIZE */
+      CMPLI(0, 0, JUMP_EPILOGUE_SIZE*4);
+      /* beq .+12 */
+      BC(12, 2, 3);
+    }
+  }
+#endif
 #ifdef OPCODE_RETURN_JUMPADDR
   if (instrs[b].flags & I_JUMP) {
     /* This is the code that JUMP_EPILOGUE_SIZE compensates for. */
@@ -476,6 +533,12 @@ void ins_f_byte(unsigned int b)
     MTSPR(PPC_REG_RET, PPC_SPREG_LR);
     /* blr */
     BCLR(20, 0);
+
+#ifdef OPCODE_INLINE_RETURN
+    if (b == F_CATCH - F_OFFSET) {
+      Pike_compiler->new_program->program[rel_addr] += (PIKE_PC - rel_addr)*4;
+    }
+#endif
   }
 #endif
 }
diff --git a/src/code/ppc32.h b/src/code/ppc32.h
index d2832bdcebb771d83e4380fe6cc2094893cff945..2eab2918e97e6820140ec124e2ca3de995ecf224 100644
--- a/src/code/ppc32.h
+++ b/src/code/ppc32.h
@@ -19,16 +19,20 @@
 		     ((XO)<<1)|(LK))
 #define PPC_INSTR_XFX_FORM(OPCD,S,SPR,XO)			\
       add_to_program(((OPCD)<<26)|((S)<<21)|((SPR)<<11)|((XO)<<1))
+#define PPC_INSTR_XO_FORM(OPCD,D,A,B,OE,XO,Rc)				\
+      add_to_program(((OPCD)<<26)|((D)<<21)|((A)<<16)|((B)<<11)|((OE)<<10)|((XO)<<1)|(Rc))
 
 #define BC(BO,BI,BD) PPC_INSTR_B_FORM(16,BO,BI,BD,0,0)
 
 #define CMPLI(crfD,A,UIMM) PPC_INSTR_D_FORM(10,crfD,A,UIMM)
+#define CMPI(crfD,A,UIMM) PPC_INSTR_D_FORM(11,crfD,A,UIMM)
 #define ADDIC(D,A,SIMM) PPC_INSTR_D_FORM(12,D,A,SIMM)
 #define ADDI(D,A,SIMM) PPC_INSTR_D_FORM(14,D,A,SIMM)
 #define ADDIS(D,A,SIMM) PPC_INSTR_D_FORM(15,D,A,SIMM)
 #define ORI(A,S,UIMM) PPC_INSTR_D_FORM(24,S,A,UIMM)
 #define LWZ(D,A,d) PPC_INSTR_D_FORM(32,D,A,d)
 #define STW(S,A,d) PPC_INSTR_D_FORM(36,S,A,d)
+#define STWU(S,A,d) PPC_INSTR_D_FORM(37,S,A,d)
 #define LHA(D,A,d) PPC_INSTR_D_FORM(42,D,A,d)
 
 #define RLWINM(S,A,SH,MB,ME) PPC_INSTR_M_FORM(21,S,A,SH,MB,ME,0)
@@ -42,6 +46,8 @@
 #define BL(LI) PPC_INSTR_I_FORM(18,LI,0,1)
 #define BLA(LI) PPC_INSTR_I_FORM(18,LI,1,1)
 
+#define SUBF(D,A,B) PPC_INSTR_XO_FORM(31,D,A,B,0,40,0)
+
 #define LOW_GET_JUMP()	((INT32)PROG_COUNTER[JUMP_EPILOGUE_SIZE])
 #define LOW_SKIPJUMP()	(SET_PROG_COUNTER(PROG_COUNTER + JUMP_EPILOGUE_SIZE + 1))
 
@@ -235,7 +241,7 @@ void ppc32_decode_program(struct program *p);
 #define CALL_MACHINE_CODE(pc)						    \
   __asm__ __volatile__( "	mtctr %0\n"				    \
 			"	mr "PPC_REGNAME(29)",%1\n"		    \
-			"	bctr"					    \
+			"	bctrl"					    \
 			:						    \
 			: "r" (pc), "r" (Pike_interpreter_pointer)	    \
 			: "ctr", "lr", "cc", "memory", "r29", "r0",	    \
@@ -244,6 +250,7 @@ void ppc32_decode_program(struct program *p);
 
 #define OPCODE_INLINE_BRANCH
 #define OPCODE_RETURN_JUMPADDR
+#define OPCODE_INLINE_RETURN
 
 #ifdef OPCODE_RETURN_JUMPADDR
 
@@ -269,6 +276,17 @@ void ppc32_decode_program(struct program *p);
 #endif /* !OPCODE_RETURN_JUMPADDR */
 
 
+#ifdef OPCODE_INLINE_RETURN
+
+/* Size of the prologue added by INS_ENTRY() (in PIKE_OPCODE_T's). */
+#define ENTRY_PROLOGUE_SIZE	3
+
+void ppc32_ins_entry(void);
+#define INS_ENTRY()	ppc32_ins_entry()
+
+#endif /* OPCODE_INLINE_RETURN */
+
+
 #ifdef PIKE_DEBUG
 void ppc32_disassemble_code(void *addr, size_t bytes);
 #define DISASSEMBLE_CODE(ADDR, BYTES)	ppc32_disassemble_code(ADDR, BYTES)
diff --git a/src/code/ppc64.c b/src/code/ppc64.c
index 1b6dfc471c60bcf721d4638be101838828885a25..3385dcab5361c8b1e96c6fb11dd9f6b2bc90b5fe 100644
--- a/src/code/ppc64.c
+++ b/src/code/ppc64.c
@@ -409,9 +409,22 @@ static void maybe_update_pc(void)
   }
 }
 
+#ifdef OPCODE_INLINE_RETURN
+void ppc64_ins_entry(void)
+{
+  /* stdu r1, -64(r1) */
+  STDU(1, 1, -64);
+  /* mflr r0 */
+  MFSPR(0, PPC_SPREG_LR);
+  /* std r0, 80(r1) */
+  STD(0, 1, 80);
+}
+#endif /* OPCODE_INLINE_RETURN */
+
 void ins_f_byte(unsigned int b)
 {
   void *addr;
+  INT32 rel_addr;
 
   b-=F_OFFSET;
 #ifdef PIKE_DEBUG
@@ -461,10 +474,54 @@ void ins_f_byte(unsigned int b)
   case F_ESCAPE_CATCH - F_OFFSET:
     ppc64_escape_catch();
     return;
+
+#ifdef OPCODE_INLINE_RETURN
+  case F_CATCH - F_OFFSET:
+    /* Special argument for the F_CATCH instruction. */
+    addr = inter_return_opcode_F_CATCH;
+    /* bl .+4 */
+    BL(4);
+    /* mflr r3 */
+    MFSPR(PPC_REG_ARG1, PPC_SPREG_LR);
+    rel_addr = PIKE_PC;
+    /* addi r3, r3, offs */
+    ADDI(PPC_REG_ARG1, PPC_REG_ARG1, 4);
+    break;
+#endif
   }
 
   FLUSH_CODE_GENERATOR_STATE();
   ADD_CALL(addr);
+#ifdef OPCODE_INLINE_RETURN
+  if (instrs[b].flags & I_RETURN) {
+    /* cmpdi r3,-1 */
+    CMPI(1, PPC_REG_RET, -1);
+    /* bne .+20 */
+    BC(4, 2, 5);
+    /* ld r0, 80(r1) */
+    LD(0, 1, 80);
+    /* addi r1, r1, 64 */
+    ADDI(1, 1, 64);
+    /* mtlr r0 */
+    MTSPR(0, PPC_SPREG_LR);
+    /* blr */
+    BCLR(20, 0);
+
+    if ((b + F_OFFSET) == F_RETURN_IF_TRUE) {
+      /* Kludge. We must check if the ret addr is
+       * orig_addr + JUMP_EPILOGUE_SIZE. */
+
+      /* mflr r0 */
+      MFSPR(0, PPC_SPREG_LR);
+      /* subf r0, r0, r3 */
+      SUBF(0, 0, PPC_REG_RET);
+      /* cmpldi r0, JUMP_EPILOGUE_SIZE */
+      CMPLI(1, 0, JUMP_EPILOGUE_SIZE*4);
+      /* beq .+12 */
+      BC(12, 2, 3);
+    }
+  }
+#endif
 #ifdef OPCODE_RETURN_JUMPADDR
   if (instrs[b].flags & I_JUMP) {
     /* This is the code that JUMP_EPILOGUE_SIZE compensates for. */
@@ -472,6 +529,12 @@ void ins_f_byte(unsigned int b)
     MTSPR(PPC_REG_RET, PPC_SPREG_LR);
     /* blr */
     BCLR(20, 0);
+
+#ifdef OPCODE_INLINE_RETURN
+    if (b == F_CATCH - F_OFFSET) {
+      Pike_compiler->new_program->program[rel_addr] += (PIKE_PC - rel_addr)*4;
+    }
+#endif
   }
 #endif
 }
diff --git a/src/code/ppc64.h b/src/code/ppc64.h
index 67e8f60f498865c4a9d6d3d28d061aa0c5229e51..d8c6ec8e184890042ed44c1343bff3f2205913cc 100644
--- a/src/code/ppc64.h
+++ b/src/code/ppc64.h
@@ -24,10 +24,13 @@
 		     ((XO)<<1)|(LK))
 #define PPC_INSTR_XFX_FORM(OPCD,S,SPR,XO)			\
       add_to_program(((OPCD)<<26)|((S)<<21)|((SPR)<<11)|((XO)<<1))
+#define PPC_INSTR_XO_FORM(OPCD,D,A,B,OE,XO,Rc)				\
+      add_to_program(((OPCD)<<26)|((D)<<21)|((A)<<16)|((B)<<11)|((OE)<<10)|((XO)<<1)|(Rc))
 
 #define BC(BO,BI,BD) PPC_INSTR_B_FORM(16,BO,BI,BD,0,0)
 
 #define CMPLI(crfD,A,UIMM) PPC_INSTR_D_FORM(10,crfD,A,UIMM)
+#define CMPI(crfD,A,UIMM) PPC_INSTR_D_FORM(11,crfD,A,UIMM)
 #define ADDIC(D,A,SIMM) PPC_INSTR_D_FORM(12,D,A,SIMM)
 #define ADDI(D,A,SIMM) PPC_INSTR_D_FORM(14,D,A,SIMM)
 #define ADDIS(D,A,SIMM) PPC_INSTR_D_FORM(15,D,A,SIMM)
@@ -39,6 +42,7 @@
 #define LD(D,A,ds) PPC_INSTR_DS_FORM(58,D,A,ds,0)
 #define LDU(D,A,ds) PPC_INSTR_DS_FORM(58,D,A,ds,1)
 #define STD(S,A,ds) PPC_INSTR_DS_FORM(62,S,A,ds,0)
+#define STDU(S,A,ds) PPC_INSTR_DS_FORM(62,S,A,ds,1)
 
 #define RLWINM(S,A,SH,MB,ME) PPC_INSTR_M_FORM(21,S,A,SH,MB,ME,0)
 #define RLDICL(S,A,SH,MB) PPC_INSTR_MD_FORM(30,S,A,SH,MB,0,0)
@@ -53,6 +57,8 @@
 #define BL(LI) PPC_INSTR_I_FORM(18,LI,0,1)
 #define BLA(LI) PPC_INSTR_I_FORM(18,LI,1,1)
 
+#define SUBF(D,A,B) PPC_INSTR_XO_FORM(31,D,A,B,0,40,0)
+
 #define LOW_GET_JUMP()	((INT32)PROG_COUNTER[JUMP_EPILOGUE_SIZE])
 #define LOW_SKIPJUMP()	(SET_PROG_COUNTER(PROG_COUNTER + JUMP_EPILOGUE_SIZE + 1))
 
@@ -266,7 +272,7 @@ void ppc64_decode_program(struct program *p);
 #define CALL_MACHINE_CODE(pc)						    \
   __asm__ __volatile__( "	mtctr %0\n"				    \
 			"	mr "PPC_REGNAME(29)",%1\n"		    \
-			"	bctr"					    \
+			"	bctrl"					    \
 			:						    \
 			: "r" (pc), "r" (Pike_interpreter_pointer)	    \
 			: "ctr", "lr", "cc", "memory", "r29", "r0", "r2",   \
@@ -275,6 +281,7 @@ void ppc64_decode_program(struct program *p);
 
 #define OPCODE_INLINE_BRANCH
 #define OPCODE_RETURN_JUMPADDR
+#define OPCODE_INLINE_RETURN
 
 #ifdef OPCODE_RETURN_JUMPADDR
 
@@ -300,6 +307,17 @@ void ppc64_decode_program(struct program *p);
 #endif /* !OPCODE_RETURN_JUMPADDR */
 
 
+#ifdef OPCODE_INLINE_RETURN
+
+/* Size of the prologue added by INS_ENTRY() (in PIKE_OPCODE_T's). */
+#define ENTRY_PROLOGUE_SIZE	3
+
+void ppc64_ins_entry(void);
+#define INS_ENTRY()	ppc64_ins_entry()
+
+#endif /* OPCODE_INLINE_RETURN */
+
+
 #ifdef PIKE_DEBUG
 void ppc64_disassemble_code(void *addr, size_t bytes);
 #define DISASSEMBLE_CODE(ADDR, BYTES)	ppc64_disassemble_code(ADDR, BYTES)