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)