e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information.
1cbb892011-04-25Martin Stjernholm || $Id$
e576bb2002-10-11Martin Nilsson */
55d3e12001-07-26Marcus Comstedt 
9299942001-08-15Marcus Comstedt #define PPC_INSTR_B_FORM(OPCD,BO,BI,BD,AA,LK) \ add_to_program(((OPCD)<<26)|((BO)<<21)|((BI)<<16)| \ (((BD)&0x3fff)<<2)|((AA)<<1)|(LK)) #define PPC_INSTR_D_FORM(OPCD,S,A,d) \ add_to_program(((OPCD)<<26)|((S)<<21)|((A)<<16)|((d)&0xffff))
2f19202002-10-23Marcus Comstedt #define PPC_INSTR_I_FORM(OPCD,LI,AA,LK) \ add_to_program(((OPCD)<<26)|((LI)&0x03fffffc)|((AA)<<1)|(LK))
9299942001-08-15Marcus Comstedt #define PPC_INSTR_M_FORM(OPCD,S,A,SH,MB,ME,Rc) \ add_to_program(((OPCD)<<26)|((S)<<21)|((A)<<16)|((SH)<<11)| \ ((MB)<<6)|((ME)<<1)|(Rc))
2f19202002-10-23Marcus Comstedt #define PPC_INSTR_XL_FORM(OPCD,BO,BI,CRBB,XO,LK) \ add_to_program(((OPCD)<<26)|((BO)<<21)|((BI)<<16)|((CRBB)<<11)| \ ((XO)<<1)|(LK))
0ea6742002-04-08Marcus Comstedt #define PPC_INSTR_XFX_FORM(OPCD,S,SPR,XO) \ add_to_program(((OPCD)<<26)|((S)<<21)|((SPR)<<11)|((XO)<<1))
9299942001-08-15Marcus Comstedt  #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 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)
44ac872001-08-16Marcus Comstedt #define ORI(A,S,UIMM) PPC_INSTR_D_FORM(24,S,A,UIMM)
9299942001-08-15Marcus Comstedt #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)
44ac872001-08-16Marcus Comstedt #define LHA(D,A,d) PPC_INSTR_D_FORM(42,D,A,d)
9299942001-08-15Marcus Comstedt  #define RLWINM(S,A,SH,MB,ME) PPC_INSTR_M_FORM(21,S,A,SH,MB,ME,0)
0ea6742002-04-08Marcus Comstedt #define MFSPR(D,SPR) PPC_INSTR_XFX_FORM(31,D,(((SPR)&0x1f)<<5)|(((SPR)&0x3e0)>>5),339) #define MTSPR(D,SPR) PPC_INSTR_XFX_FORM(31,D,(((SPR)&0x1f)<<5)|(((SPR)&0x3e0)>>5),467)
9299942001-08-15Marcus Comstedt 
600b022003-12-09Henrik Grubbström (Grubba) #define BCLR(BO,BI) PPC_INSTR_XL_FORM(19,BO,BI,0,16,0)
2f19202002-10-23Marcus Comstedt #define BCLRL(BO,BI) PPC_INSTR_XL_FORM(19,BO,BI,0,16,1) #define B(LI) PPC_INSTR_I_FORM(18,LI,0,0) #define BL(LI) PPC_INSTR_I_FORM(18,LI,0,1) #define BLA(LI) PPC_INSTR_I_FORM(18,LI,1,1)
600b022003-12-09Henrik Grubbström (Grubba) #define LOW_GET_JUMP() (PROG_COUNTER[JUMP_EPILOGUE_SIZE]) #define LOW_SKIPJUMP() (SET_PROG_COUNTER(PROG_COUNTER + JUMP_EPILOGUE_SIZE + 1))
55d3e12001-07-26Marcus Comstedt  #define SET_REG(REG, X) do { \ INT32 val_ = X; \ INT32 reg_ = REG; \ if ((-32768 <= val_) && (val_ <= 32767)) { \ /* addi reg,0,val */ \
9299942001-08-15Marcus Comstedt  ADDI(reg_, 0, val_); \
55d3e12001-07-26Marcus Comstedt  } else { \ /* addis reg,0,%hi(val) */ \
9299942001-08-15Marcus Comstedt  ADDIS(reg_, 0, val_ >> 16); \
55d3e12001-07-26Marcus Comstedt  if (val_ & 0xffff) { \ /* ori reg,reg,%lo(val) */ \
9299942001-08-15Marcus Comstedt  ORI(reg_, reg_, val_); \
55d3e12001-07-26Marcus Comstedt  } \ } \ } while(0)
2f19202002-10-23Marcus Comstedt #define PPC_SPREG_LR 8
f8c9b92002-11-04Marcus Comstedt #define PPC_REG_RET 3
03b57f2001-09-19Marcus Comstedt 
9299942001-08-15Marcus Comstedt #define PPC_REG_ARG1 3 #define PPC_REG_ARG2 4
44ac872001-08-16Marcus Comstedt #define PPC_REG_ARG3 5
18f2e12001-08-16Marcus Comstedt 
0ea6742002-04-08Marcus Comstedt #define PPC_REG_PIKE_PC 7
18f2e12001-08-16Marcus Comstedt #define PPC_REG_PIKE_MARK_SP 8
9299942001-08-15Marcus Comstedt #define PPC_REG_PIKE_FP 9 #define PPC_REG_PIKE_SP 10
d218702005-05-24Jonas Wallden #define PPC_REG_PIKE_INTERP 29 /* 31 */
9299942001-08-15Marcus Comstedt 
0ea6742002-04-08Marcus Comstedt extern int ppc32_codegen_state, ppc32_codegen_last_pc;
9299942001-08-15Marcus Comstedt void ppc32_flush_code_generator_state(void); #define FLUSH_CODE_GENERATOR_STATE ppc32_flush_code_generator_state #define PPC_CODEGEN_FP_ISSET 1 #define PPC_CODEGEN_SP_ISSET 2 #define PPC_CODEGEN_SP_NEEDSSTORE 4
18f2e12001-08-16Marcus Comstedt #define PPC_CODEGEN_MARK_SP_ISSET 8 #define PPC_CODEGEN_MARK_SP_NEEDSSTORE 16
0ea6742002-04-08Marcus Comstedt #define PPC_CODEGEN_PC_ISSET 32
9299942001-08-15Marcus Comstedt  #define LOAD_FP_REG() do { \ if(!(ppc32_codegen_state & PPC_CODEGEN_FP_ISSET)) { \ /* lwz pike_fp,frame_pointer(pike_interpreter) */ \ LWZ(PPC_REG_PIKE_FP, PPC_REG_PIKE_INTERP, \ OFFSETOF(Pike_interpreter, frame_pointer)); \ ppc32_codegen_state |= PPC_CODEGEN_FP_ISSET; \ } \ } while(0) #define LOAD_SP_REG() do { \ if(!(ppc32_codegen_state & PPC_CODEGEN_SP_ISSET)) { \ /* lwz pike_sp,stack_pointer(pike_interpreter) */ \ LWZ(PPC_REG_PIKE_SP, PPC_REG_PIKE_INTERP, \ OFFSETOF(Pike_interpreter, stack_pointer)); \ ppc32_codegen_state |= PPC_CODEGEN_SP_ISSET; \ } \ } while(0)
18f2e12001-08-16Marcus Comstedt #define LOAD_MARK_SP_REG() do { \ if(!(ppc32_codegen_state & PPC_CODEGEN_MARK_SP_ISSET)) { \ /* lwz pike_mark_sp,mark_stack_pointer(pike_interpreter) */ \ LWZ(PPC_REG_PIKE_MARK_SP, PPC_REG_PIKE_INTERP, \ OFFSETOF(Pike_interpreter, mark_stack_pointer)); \ ppc32_codegen_state |= PPC_CODEGEN_MARK_SP_ISSET; \ } \ } while(0)
9299942001-08-15Marcus Comstedt #define INCR_SP_REG(n) do { \ /* addi pike_sp,pike_sp,n */ \ ADDI(PPC_REG_PIKE_SP, PPC_REG_PIKE_SP, n); \ ppc32_codegen_state |= PPC_CODEGEN_SP_NEEDSSTORE; \ } while(0)
18f2e12001-08-16Marcus Comstedt #define INCR_MARK_SP_REG(n) do { \ /* addi pike_mark_sp,pike_mark_sp,n */ \ ADDI(PPC_REG_PIKE_MARK_SP, PPC_REG_PIKE_MARK_SP, n); \ ppc32_codegen_state |= PPC_CODEGEN_MARK_SP_NEEDSSTORE; \ } while(0)
0ea6742002-04-08Marcus Comstedt #define UPDATE_PC() do { \ INT32 tmp = PIKE_PC; \ if(ppc32_codegen_state & PPC_CODEGEN_PC_ISSET) { \ INT32 diff = (tmp-ppc32_codegen_last_pc)*sizeof(PIKE_OPCODE_T); \
f79d362002-05-11Martin Stjernholm  if (diff) { \ if ((-32768 <= diff) && (diff <= 32767)) { \ /* addi pike_pc,pike_pc,diff */ \
0ea6742002-04-08Marcus Comstedt  ADDI(PPC_REG_PIKE_PC, PPC_REG_PIKE_PC, diff); \
f79d362002-05-11Martin Stjernholm  } else { \ /* addis pike_pc,pike_pc,%hi(diff) */ \ ADDIS(PPC_REG_PIKE_PC, PPC_REG_PIKE_PC, (diff+32768)>>16); \ if ((diff &= 0xffff) > 32767) \ diff -= 65536; \ if (diff) { \ /* addi pike_pc,pike_pc,%lo(diff) */ \ ADDI(PPC_REG_PIKE_PC, PPC_REG_PIKE_PC, diff); \ } \
0ea6742002-04-08Marcus Comstedt  } \ } \ } else { \ /* bl .+4 */ \
2f19202002-10-23Marcus Comstedt  BL(4); \
0ea6742002-04-08Marcus Comstedt  /* mflr pike_pc */ \
2f19202002-10-23Marcus Comstedt  MFSPR(PPC_REG_PIKE_PC, PPC_SPREG_LR); \
0ea6742002-04-08Marcus Comstedt  /* addi pike_pc,pike_pc,-4 */ \ ADDI(PPC_REG_PIKE_PC, PPC_REG_PIKE_PC, -sizeof(PIKE_OPCODE_T)); \ } \ ppc32_codegen_last_pc = tmp; \ ppc32_codegen_state |= PPC_CODEGEN_PC_ISSET; \ LOAD_FP_REG(); \ /* stw pike_pc,pc(pike_fp) */ \ STW(PPC_REG_PIKE_PC, PPC_REG_PIKE_FP, OFFSETOF(pike_frame, pc)); \
55d3e12001-07-26Marcus Comstedt  } while(0)
f79d362002-05-11Martin Stjernholm #define ADJUST_PIKE_PC(pc) do { \ ppc32_codegen_last_pc = pc; \ ppc32_codegen_state |= PPC_CODEGEN_PC_ISSET; \ } while (0)
55d3e12001-07-26Marcus Comstedt #define ins_pointer(PTR) add_to_program((INT32)(PTR)) #define read_pointer(OFF) (Pike_compiler->new_program->program[(INT32)(OFF)]) #define upd_pointer(OFF,PTR) (Pike_compiler->new_program->program[(INT32)(OFF)] = (INT32)(PTR)) #define ins_align(ALIGN) #define ins_byte(VAL) add_to_program((INT32)(VAL)) #define ins_data(VAL) add_to_program((INT32)(VAL))
600b022003-12-09Henrik Grubbström (Grubba) INT32 ppc32_ins_f_jump(unsigned int a, int backward_jump); INT32 ppc32_ins_f_jump_with_arg(unsigned int a, unsigned INT32 b, int backward_jump); INT32 ppc32_ins_f_jump_with_2_args(unsigned int a, unsigned INT32 b, unsigned INT32 c, int backward_jump);
807a8c2001-08-16Marcus Comstedt void ppc32_update_f_jump(INT32 offset, INT32 to_offset); INT32 ppc32_read_f_jump(INT32 offset); #define INS_F_JUMP ppc32_ins_f_jump
f8c9b92002-11-04Marcus Comstedt #define INS_F_JUMP_WITH_ARG ppc32_ins_f_jump_with_arg #define INS_F_JUMP_WITH_TWO_ARGS ppc32_ins_f_jump_with_2_args
807a8c2001-08-16Marcus Comstedt #define UPDATE_F_JUMP ppc32_update_f_jump #define READ_F_JUMP ppc32_read_f_jump
55d3e12001-07-26Marcus Comstedt #define READ_INCR_BYTE(PC) (((PC)++)[0])
9299942001-08-15Marcus Comstedt #if 0
55d3e12001-07-26Marcus Comstedt #define RELOCATE_program(P, NEW) do { \ PIKE_OPCODE_T *op_ = NEW; \ struct program *p_ = P; \ size_t rel_ = p_->num_relocations; \
0ea6742002-04-08Marcus Comstedt  INT32 disp_, delta_ = p_->program - op_; \
55d3e12001-07-26Marcus Comstedt  while (rel_--) { \ DO_IF_DEBUG( \ if ((op_[p_->relocations[rel_]] & 0xfc000002) != \ 0x48000000) { \
5aad932002-08-15Marcus Comstedt  Pike_fatal("Bad relocation: %d, off:%d, opcode: 0x%08x\n", \
55d3e12001-07-26Marcus Comstedt  rel_, p_->relocations[rel_], \ op_[p_->relocations[rel_]]); \ } \ ); \
0ea6742002-04-08Marcus Comstedt  disp_ = op_[p_->relocations[rel_]] & 0x03ffffff; \ if(disp_ & 0x02000000) \ disp_ -= 0x04000000; \ disp_ += delta_ << 2; \ if(disp_ < -33554432 || disp_ > 33554431) \
5aad932002-08-15Marcus Comstedt  Pike_fatal("Relocation %d out of range!\n", disp_); \
55d3e12001-07-26Marcus Comstedt  op_[p_->relocations[rel_]] = 0x48000000 | \
0ea6742002-04-08Marcus Comstedt  (disp_ & 0x03ffffff); \
55d3e12001-07-26Marcus Comstedt  } \ } while(0)
9299942001-08-15Marcus Comstedt #endif
55d3e12001-07-26Marcus Comstedt 
6850222001-07-30Marcus Comstedt extern void ppc32_flush_instruction_cache(void *addr, size_t len); #define FLUSH_INSTRUCTION_CACHE ppc32_flush_instruction_cache
0ea6742002-04-08Marcus Comstedt #if 0
55d3e12001-07-26Marcus Comstedt struct dynamic_buffer_s; void ppc32_encode_program(struct program *p, struct dynamic_buffer_s *buf); void ppc32_decode_program(struct program *p); #define ENCODE_PROGRAM(P, BUF) ppc32_encode_program(P, BUF) #define DECODE_PROGRAM(P) ppc32_decode_program(p)
0ea6742002-04-08Marcus Comstedt #endif
9a41452001-08-01Marcus Comstedt 
9299942001-08-15Marcus Comstedt #ifdef PIKE_CPU_REG_PREFIX #define PPC_REGNAME(n) PIKE_CPU_REG_PREFIX #n
3ff1ea2001-08-14Marcus Comstedt #else
9299942001-08-15Marcus Comstedt #define PPC_REGNAME(n) #n
3ff1ea2001-08-14Marcus Comstedt #endif
9299942001-08-15Marcus Comstedt #define CALL_MACHINE_CODE(pc) \ __asm__ __volatile__( " mtctr %0\n" \
d218702005-05-24Jonas Wallden  " mr "PPC_REGNAME(29)",%1\n" \
9299942001-08-15Marcus Comstedt  " bctr" \ : \ : "r" (pc), "r" (&Pike_interpreter) \
d218702005-05-24Jonas Wallden  : "ctr", "lr", "cc", "memory", "r29", "r0", \
9299942001-08-15Marcus Comstedt  "r3", "r4", "r5", "r6", "r7", "r8", "r9", \
3ff1ea2001-08-14Marcus Comstedt  "r10", "r11", "r12")
f8c9b92002-11-04Marcus Comstedt  #define OPCODE_INLINE_BRANCH
4f86a92003-12-09Henrik Grubbström (Grubba) /* #define OPCODE_RETURN_JUMPADDR */
600b022003-12-09Henrik Grubbström (Grubba)  #ifdef OPCODE_RETURN_JUMPADDR /* Don't need an lvalue in this case. */ #define PROG_COUNTER ((INT32 *)__builtin_return_address(0)) #define JUMP_EPILOGUE_SIZE 2 #define JUMP_SET_TO_PC_AT_NEXT(PC) \ ((PC) = PROG_COUNTER + JUMP_EPILOGUE_SIZE) #else /* !OPCODE_RETURN_JUMPADDR */ #ifdef __linux /* SVR4 ABI */ #define PROG_COUNTER (((INT32 **)__builtin_frame_address(1))[1]) #else /* PowerOpen ABI */ #define PROG_COUNTER (((INT32 **)__builtin_frame_address(1))[2]) #endif #define JUMP_EPILOGUE_SIZE 0 #endif /* !OPCODE_RETURN_JUMPADDR */
f8c9b92002-11-04Marcus Comstedt 
e1cbf12002-11-08Marcus Comstedt #ifdef PIKE_DEBUG void ppc32_disassemble_code(void *addr, size_t bytes); #define DISASSEMBLE_CODE(ADDR, BYTES) ppc32_disassemble_code(ADDR, BYTES) #endif