a00f6f2007-04-01Marcus Comstedt /* || 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. */ /*
f2da612017-07-17Marcus Comstedt  * Machine code generator for 64 bit PowerPC
a00f6f2007-04-01Marcus Comstedt  * * Marcus Comstedt 20010726 */ #include "operators.h" #include "constants.h" #include "object.h" #include "builtin_functions.h" /* Get MakeDataExecutable from CarbonLib on Mac OS X */ #ifdef HAVE_CORESERVICES_CORESERVICES_H #include <CoreServices/CoreServices.h> #endif #if PIKE_BYTEORDER == 1234 #define MAKE_TYPE_WORD(t,st) ((t)|((st)<<16)) #else #define MAKE_TYPE_WORD(t,st) ((st)|((t)<<16)) #endif
74ad732018-05-19Marcus Comstedt #if _CALL_ELF == 2 #define ADD_CALL(X) do { \ INT64 func_=(INT64)(void*)(X); \ \ SET_REG64(12, func_); \ /* mtlr r12 */ \ MTSPR(12, PPC_SPREG_LR); \ /* blrl */ \ BCLRL(20, 0); \ } while(0) #else
a00f6f2007-04-01Marcus Comstedt #define ADD_CALL(X) do { \ INT64 func_=(INT64)(void*)(X); \ \ SET_REG64(11, (func_+32768)&~0xffff); \ if ((func_ &= 0xffff) > 32767) \ func_ -= 65536; \
159c912015-10-21Marcus Comstedt  /* ldu r0,%lo(func)(r11) */ \ LDU(0, 11, func_); \ /* ld r2,%8(r11) */ \ LD(2, 11, 8); \
a00f6f2007-04-01Marcus Comstedt  /* mtlr r0 */ \ MTSPR(0, PPC_SPREG_LR); \ /* blrl */ \ BCLRL(20, 0); \ } while(0)
74ad732018-05-19Marcus Comstedt #endif
a00f6f2007-04-01Marcus Comstedt int ppc64_codegen_state = 0, ppc64_codegen_last_pc = 0; static int last_prog_id=-1; void ppc64_flush_code_generator_state() { if(ppc64_codegen_state & PPC_CODEGEN_SP_NEEDSSTORE) { /* stw pike_sp,stack_pointer(pike_interpreter) */ STD(PPC_REG_PIKE_SP, PPC_REG_PIKE_INTERP,
d97eb72011-07-10Henrik Grubbström (Grubba)  OFFSETOF(Pike_interpreter_struct, stack_pointer));
a00f6f2007-04-01Marcus Comstedt  } if(ppc64_codegen_state & PPC_CODEGEN_MARK_SP_NEEDSSTORE) { /* stw pike_mark_sp,mark_stack_pointer(pike_interpreter) */ STD(PPC_REG_PIKE_MARK_SP, PPC_REG_PIKE_INTERP,
d97eb72011-07-10Henrik Grubbström (Grubba)  OFFSETOF(Pike_interpreter_struct, mark_stack_pointer));
a00f6f2007-04-01Marcus Comstedt  } ppc64_codegen_state = 0; last_prog_id=-1; } INT32 ppc64_get_local_addr(int reg, INT32 arg) { INT32 offs = arg * sizeof(struct svalue); LOAD_FP_REG(); /* ld reg,locals(pike_fp) */ LD(reg, PPC_REG_PIKE_FP, OFFSETOF(pike_frame, locals)); if(offs > 32767) { /* addis reg,reg,%hi(offs) */ ADDIS(reg, reg, (offs+32768)>>16); if((offs &= 0xffff) > 32767) offs -= 65536; } return offs; } void ppc64_push_svalue(int reg, INT32 offs, int force_reftype) { int e; LOAD_SP_REG(); if(offs > (INT32)(32768-sizeof(struct svalue))) { /* addi r,r,offs */ ADDI(reg, reg, offs); offs = 0; } if(sizeof(struct svalue) > 16) { for(e=8;e<(int)sizeof(struct svalue);e+=8) { if( e == OFFSETOF(svalue,u.refs)) continue; /* ld r0,e+offs(r) */ LD(0, reg, e+offs); /* std r0,e(pike_sp) */ STD(0, PPC_REG_PIKE_SP, e); } }
13670c2015-05-25Martin Nilsson 
a00f6f2007-04-01Marcus Comstedt  /* ld r0,offs(r) */ LD(0, reg, offs); /* ld r11,refs+offs(r) */ LD(11, reg, offs+OFFSETOF(svalue,u.refs)); /* std r0,0(pike_sp) */ STD(0, PPC_REG_PIKE_SP, 0); if(!force_reftype) { #if PIKE_BYTEORDER == 1234
86bafd2013-08-14Marcus Comstedt  /* rldicl r0,r0,61,51 */ RLDICL(0, 0, 61, 51);
a00f6f2007-04-01Marcus Comstedt #else
86bafd2013-08-14Marcus Comstedt  /* rldicl r0,r0,13,51 */ RLDICL(0, 0, 13, 51);
a00f6f2007-04-01Marcus Comstedt #endif } /* std r11,refs(pike_sp) */ STD(11, PPC_REG_PIKE_SP, OFFSETOF(svalue,u.refs)); if(!force_reftype) {
86bafd2013-08-14Marcus Comstedt  /* cmplwi r0,MIN_REF_TYPE>>3 */ CMPLI(0, 0, MIN_REF_TYPE>>3);
a00f6f2007-04-01Marcus Comstedt  } INCR_SP_REG(sizeof(struct svalue)); if(!force_reftype) {
86bafd2013-08-14Marcus Comstedt  /* bne bork */ BC(4, 2, 4);
a00f6f2007-04-01Marcus Comstedt  } /* lwz r0,0(r11) */ LWZ(0, 11, 0); /* addic r0,r0,1 */ ADDIC(0, 0, 1); /* stw r0,0(r11) */ STW(0, 11, 0); /* bork: */ } void ppc64_push_constant(INT32 arg) { INT32 offs; struct svalue *sval = &Pike_compiler->new_program->constants[arg].sval; /* * Note: The constants table may contain UNDEFINED in case of being * called through decode_value() in PORTABLE_BYTECODE mode. */
96a3b32014-06-24Henrik Grubbström (Grubba)  if(!REFCOUNTED_TYPE(TYPEOF(*sval)) && !SUBTYPEOF(*sval)) {
a00f6f2007-04-01Marcus Comstedt  int e; INT64 last=0; LOAD_SP_REG(); for(e=0;e<(int)sizeof(struct svalue);e+=8) { if(e==0 || *(INT64 *)(((char *)sval)+e) != last) SET_REG64(0, last = *(INT64 *)(((char *)sval)+e)); /* std r0,e(pike_sp) */ STD(0, PPC_REG_PIKE_SP, e); }
13670c2015-05-25Martin Nilsson  INCR_SP_REG(sizeof(struct svalue));
a00f6f2007-04-01Marcus Comstedt  return; } LOAD_FP_REG();
78f61d2008-02-28Henrik Grubbström (Grubba)  /* ld r3,context(pike_fp) */ LD(PPC_REG_ARG1, PPC_REG_PIKE_FP, OFFSETOF(pike_frame, context)); /* ld r3,prog(r3) */ LD(PPC_REG_ARG1, PPC_REG_ARG1, OFFSETOF(inherit, prog));
a00f6f2007-04-01Marcus Comstedt  /* ld r3,constants(r3) */ LD(PPC_REG_ARG1, PPC_REG_ARG1, OFFSETOF(program, constants)); offs = arg*sizeof(struct program_constant)+OFFSETOF(program_constant, sval); if(offs > 32767) { /* addis r3,r3,%hi(offs) */ ADDIS(PPC_REG_ARG1, PPC_REG_ARG1, (offs+32768)>>16); if((offs &= 0xffff) > 32767) offs -= 65536; }
4a93e82013-06-11Henrik Grubbström (Grubba)  ppc64_push_svalue(PPC_REG_ARG1, offs, !!REFCOUNTED_TYPE(TYPEOF(*sval)));
a00f6f2007-04-01Marcus Comstedt } void ppc64_push_local(INT32 arg) { INT32 offs; offs = ppc64_get_local_addr(PPC_REG_ARG1, arg); ppc64_push_svalue(PPC_REG_ARG1, offs, 0); } void ppc64_local_lvalue(INT32 arg) { INT32 offs; int e; offs = ppc64_get_local_addr(PPC_REG_ARG1, arg); LOAD_SP_REG(); SET_REG32(0, 0); STW(0, PPC_REG_PIKE_SP, 4); STW(0, PPC_REG_PIKE_SP, sizeof(struct svalue)+4); for(e=8;e<(int)(2*sizeof(struct svalue));e+=8) { if( e == OFFSETOF(svalue,u.lval) || e == sizeof(struct svalue) ) continue; /* std r0,e(pike_sp) */ STD(0, PPC_REG_PIKE_SP, e); } if(offs) { /* addi r3,r3,offs */ ADDI(PPC_REG_ARG1, PPC_REG_ARG1, offs); } /* li r0,T_SVALUE_PTR */ SET_REG32(0, MAKE_TYPE_WORD(T_SVALUE_PTR, 0)); /* stw r0,0(pike_sp) */ STW(0, PPC_REG_PIKE_SP, 0); /* li r0,T_VOID */ SET_REG32(0, MAKE_TYPE_WORD(T_VOID, 0)); /* stw r0,sizeof(struct svalue)(pike_sp) */ STW(0, PPC_REG_PIKE_SP, sizeof(struct svalue)); /* stw r3,u.lval(pike_sp) */ STD(PPC_REG_ARG1, PPC_REG_PIKE_SP, OFFSETOF(svalue,u.lval));
13670c2015-05-25Martin Nilsson  INCR_SP_REG(sizeof(struct svalue)*2);
a00f6f2007-04-01Marcus Comstedt } void ppc64_push_global(INT32 arg) { LOAD_FP_REG();
78f61d2008-02-28Henrik Grubbström (Grubba)  /* ld r5,context(pike_fp) */ LD(PPC_REG_ARG3, PPC_REG_PIKE_FP, OFFSETOF(pike_frame, context));
a00f6f2007-04-01Marcus Comstedt  /* ld r4,current_object(pike_fp) */
13670c2015-05-25Martin Nilsson  LD(PPC_REG_ARG2, PPC_REG_PIKE_FP,
a00f6f2007-04-01Marcus Comstedt  OFFSETOF(pike_frame, current_object));
78f61d2008-02-28Henrik Grubbström (Grubba)  /* lha r5,identifier_level(r5) */ LHA(PPC_REG_ARG3, PPC_REG_ARG3, OFFSETOF(inherit, identifier_level));
a00f6f2007-04-01Marcus Comstedt  if(arg > 32767) { /* addis r5,r5,%hi(arg) */ ADDIS(PPC_REG_ARG3, PPC_REG_ARG3, (arg+32768)>>16); if((arg &= 0xffff) > 32767) arg -= 65536; } if(ppc64_codegen_state & PPC_CODEGEN_SP_ISSET) { /* mr r3,pike_sp */ ORI(PPC_REG_ARG1, PPC_REG_PIKE_SP, 0); } else {
13670c2015-05-25Martin Nilsson  /* ld r3,stack_pointer(pike_interpreter) */
a00f6f2007-04-01Marcus Comstedt  LD(PPC_REG_ARG1, PPC_REG_PIKE_INTERP,
d97eb72011-07-10Henrik Grubbström (Grubba)  OFFSETOF(Pike_interpreter_struct, stack_pointer));
a00f6f2007-04-01Marcus Comstedt  } if(arg) { /* addi r5,r5,arg */ ADDI(PPC_REG_ARG3, PPC_REG_ARG3, arg); } FLUSH_CODE_GENERATOR_STATE(); ADD_CALL(low_object_index_no_free); LOAD_SP_REG(); INCR_SP_REG(sizeof(struct svalue)); }
2ac1ca2017-07-17Marcus Comstedt void ppc64_push_int(INT64 x, int s)
a00f6f2007-04-01Marcus Comstedt { LOAD_SP_REG(); SET_REG32(0, 0); if(sizeof(struct svalue) > 16) { int e; for(e=8;e<(int)sizeof(struct svalue);e+=8) { if( e == OFFSETOF(svalue,u.integer)) continue; /* std r0,e(pike_sp) */ STD(0, PPC_REG_PIKE_SP, e); } } STW(0, PPC_REG_PIKE_SP, 4); if(x != 0)
2ac1ca2017-07-17Marcus Comstedt  SET_REG64(0, x);
a00f6f2007-04-01Marcus Comstedt  STD(0, PPC_REG_PIKE_SP, OFFSETOF(svalue,u.integer)); if(x != MAKE_TYPE_WORD(PIKE_T_INT, s)) SET_REG32(0, MAKE_TYPE_WORD(PIKE_T_INT, s)); STW(0, PPC_REG_PIKE_SP, 0);
13670c2015-05-25Martin Nilsson  INCR_SP_REG(sizeof(struct svalue));
a00f6f2007-04-01Marcus Comstedt } void ppc64_push_string(INT32 arg, int st) { INT32 offs; LOAD_FP_REG(); LOAD_SP_REG();
13670c2015-05-25Martin Nilsson 
78f61d2008-02-28Henrik Grubbström (Grubba)  /* ld r11,context(pike_fp) */ LD(11, PPC_REG_PIKE_FP, OFFSETOF(pike_frame, context)); /* ld r11,prog(r11) */ LD(11, 11, OFFSETOF(inherit, prog));
a00f6f2007-04-01Marcus Comstedt  /* ld r11,strings(r11) */ LD(11, 11, OFFSETOF(program, strings)); offs = arg*sizeof(struct pike_string *); if(offs > 32767) { /* addis r11,r11,%hi(offs) */ ADDIS(11, 11, (offs+32768)>>16); if((offs &= 0xffff) > 32767) offs -= 65536; } /* ld r11,offs(r11) */ LD(11, 11, offs);
13670c2015-05-25Martin Nilsson 
a00f6f2007-04-01Marcus Comstedt  SET_REG32(0, 0); if(sizeof(struct svalue) > 16) { int e; for(e=8;e<(int)sizeof(struct svalue);e+=8) { if( e == OFFSETOF(svalue,u.string)) continue; /* std r0,e(pike_sp) */ STD(0, PPC_REG_PIKE_SP, e); } } STW(0, PPC_REG_PIKE_SP, 4); STD(11, PPC_REG_PIKE_SP, OFFSETOF(svalue,u.string)); if(st) SET_REG32(0, MAKE_TYPE_WORD(PIKE_T_STRING, 1)); else SET_REG32(0, MAKE_TYPE_WORD(PIKE_T_STRING, 0)); STW(0, PPC_REG_PIKE_SP, 0); /* lwz r0,0(r11) */ LWZ(0, 11, 0); /* addic r0,r0,1 */ ADDIC(0, 0, 1); /* stw r0,0(r11) */ STW(0, 11, 0);
13670c2015-05-25Martin Nilsson  INCR_SP_REG(sizeof(struct svalue));
a00f6f2007-04-01Marcus Comstedt } void ppc64_mark(void) { LOAD_SP_REG(); LOAD_MARK_SP_REG(); /* std pike_sp, 0(pike_mark_sp) */ STD(PPC_REG_PIKE_SP, PPC_REG_PIKE_MARK_SP, 0); INCR_MARK_SP_REG(sizeof(struct svalue *)); } static void ppc64_escape_catch(void) { LOAD_FP_REG(); /* ld r3,catch_ctx(pike_interpreter) */ LD(PPC_REG_ARG1, PPC_REG_PIKE_INTERP,
d97eb72011-07-10Henrik Grubbström (Grubba)  OFFSETOF(Pike_interpreter_struct, catch_ctx));
a00f6f2007-04-01Marcus Comstedt  /* ld r4,recovery.previous(r3) */ LD(PPC_REG_ARG2, PPC_REG_ARG1, OFFSETOF(catch_context, recovery.previous)); /* std r4,recoveries(pike_interpreter) */ STD(PPC_REG_ARG2, PPC_REG_PIKE_INTERP,
d97eb72011-07-10Henrik Grubbström (Grubba)  OFFSETOF(Pike_interpreter_struct, recoveries));
a00f6f2007-04-01Marcus Comstedt  /* ld r4,prev(r3) */ LD(PPC_REG_ARG2, PPC_REG_ARG1, OFFSETOF(catch_context, prev)); /* std r4,catch_ctx(pike_interpreter) */ STD(PPC_REG_ARG2, PPC_REG_PIKE_INTERP,
d97eb72011-07-10Henrik Grubbström (Grubba)  OFFSETOF(Pike_interpreter_struct, catch_ctx));
a00f6f2007-04-01Marcus Comstedt  FLUSH_CODE_GENERATOR_STATE(); ADD_CALL(really_free_catch_context); } static void maybe_update_pc(void) { static unsigned int last_num_linenumbers=~0; if(last_prog_id != Pike_compiler->new_program->id || last_num_linenumbers != Pike_compiler->new_program->num_linenumbers) { last_prog_id=Pike_compiler->new_program->id; last_num_linenumbers = Pike_compiler->new_program->num_linenumbers; UPDATE_PC(); } }
82b2ff2018-05-23Marcus Comstedt #ifdef OPCODE_INLINE_RETURN void ppc64_ins_entry(void) {
f319122018-07-12Marcus Comstedt  /* stdu r1, -128(r1) */ STDU(1, 1, -128);
82b2ff2018-05-23Marcus Comstedt  /* mflr r0 */ MFSPR(0, PPC_SPREG_LR);
f319122018-07-12Marcus Comstedt  /* std r0, 144(r1) */ STD(0, 1, 144); /* std r2, 120(r1) */ STD(2, 1, 120);
82b2ff2018-05-23Marcus Comstedt } #endif /* OPCODE_INLINE_RETURN */
a00f6f2007-04-01Marcus Comstedt void ins_f_byte(unsigned int b) { void *addr;
82b2ff2018-05-23Marcus Comstedt  INT32 rel_addr;
a00f6f2007-04-01Marcus Comstedt  b-=F_OFFSET; #ifdef PIKE_DEBUG
c957e82019-10-12Marcus Comstedt  if(b > MAX_SUPPORTED_INSTR)
a00f6f2007-04-01Marcus Comstedt  Pike_error("Instruction too big %d\n",b); #endif maybe_update_pc(); addr = instrs[b].address; #ifdef PIKE_DEBUG if (d_flag < 3) #endif /* This is not very pretty */ switch(b) { case F_MARK2 - F_OFFSET: ppc64_mark(); case F_MARK - F_OFFSET: ppc64_mark(); return; case F_CONST0 - F_OFFSET: ppc64_push_int(0, 0); return;
13670c2015-05-25Martin Nilsson 
a00f6f2007-04-01Marcus Comstedt  case F_CONST1 - F_OFFSET: ppc64_push_int(1, 0); return;
13670c2015-05-25Martin Nilsson 
a00f6f2007-04-01Marcus Comstedt  case F_CONST_1 - F_OFFSET: ppc64_push_int(-1, 0); return;
13670c2015-05-25Martin Nilsson 
a00f6f2007-04-01Marcus Comstedt  case F_MAKE_ITERATOR - F_OFFSET: { SET_REG32(PPC_REG_ARG1, 1); addr = (void *)f_get_iterator; } break; case F_ADD - F_OFFSET: SET_REG32(PPC_REG_ARG1, 2); addr = (void *)f_add; break; case F_EXIT_CATCH - F_OFFSET: ppc64_push_int(0, 1); case F_ESCAPE_CATCH - F_OFFSET: ppc64_escape_catch(); return;
82b2ff2018-05-23Marcus Comstedt  #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;
fbe10f2019-09-03Henrik Grubbström (Grubba)  case F_CATCH_AT - F_OFFSET: /* Special argument for the F_CATCH_AT instruction. */ addr = inter_return_opcode_F_CATCH_AT; /* 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;
82b2ff2018-05-23Marcus Comstedt #endif
a00f6f2007-04-01Marcus Comstedt  } FLUSH_CODE_GENERATOR_STATE(); ADD_CALL(addr);
82b2ff2018-05-23Marcus Comstedt #ifdef OPCODE_INLINE_RETURN if (instrs[b].flags & I_RETURN) { /* cmpdi r3,-1 */ CMPI(1, PPC_REG_RET, -1);
f319122018-07-12Marcus Comstedt  /* bne .+24 */ BC(4, 2, 6); /* ld r0, 144(r1) */ LD(0, 1, 144); /* ld r2, 120(r1) */ LD(2, 1, 120); /* addi r1, r1, 128 */ ADDI(1, 1, 128);
82b2ff2018-05-23Marcus Comstedt  /* 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
a00f6f2007-04-01Marcus Comstedt #ifdef OPCODE_RETURN_JUMPADDR if (instrs[b].flags & I_JUMP) { /* This is the code that JUMP_EPILOGUE_SIZE compensates for. */ /* mtlr r3 */ MTSPR(PPC_REG_RET, PPC_SPREG_LR); /* blr */ BCLR(20, 0);
82b2ff2018-05-23Marcus Comstedt  #ifdef OPCODE_INLINE_RETURN
fbe10f2019-09-03Henrik Grubbström (Grubba)  if ((b == F_CATCH - F_OFFSET) || (b == F_CATCH_AT - F_OFFSET)) {
82b2ff2018-05-23Marcus Comstedt  Pike_compiler->new_program->program[rel_addr] += (PIKE_PC - rel_addr)*4; } #endif
a00f6f2007-04-01Marcus Comstedt  } #endif } void ins_f_byte_with_arg(unsigned int a, INT32 b) { maybe_update_pc(); #ifdef PIKE_DEBUG if (d_flag < 3) #endif switch(a) { case F_MARK_AND_LOCAL: ppc64_mark(); case F_LOCAL: ppc64_push_local(b); return; case F_LOCAL_LVALUE: ppc64_local_lvalue(b); return; case F_MARK_AND_GLOBAL: ppc64_mark(); case F_GLOBAL: ppc64_push_global(b); return; case F_MARK_AND_STRING: ppc64_mark(); case F_STRING: ppc64_push_string(b, 0); return; case F_ARROW_STRING: ppc64_push_string(b, 1); return; case F_NUMBER: ppc64_push_int(b, 0); return; case F_NEG_NUMBER:
2ac1ca2017-07-17Marcus Comstedt  ppc64_push_int(-(INT64)b, 0);
a00f6f2007-04-01Marcus Comstedt  return; case F_CONSTANT: ppc64_push_constant(b); return; /* * And this would work nicely for all non-dynamically loaded * functions. Unfortunately there is no way to know if it is * dynamically loaded or not at this point... */ case F_MARK_CALL_BUILTIN: case F_CALL_BUILTIN1: if(Pike_compiler->new_program->constants[b].sval.u.efun->internal_flags & CALLABLE_DYNAMIC) break; if(a == F_CALL_BUILTIN1) SET_REG32(PPC_REG_ARG1, 1); else SET_REG32(PPC_REG_ARG1, 0); FLUSH_CODE_GENERATOR_STATE(); ADD_CALL(Pike_compiler->new_program->constants[b].sval.u.efun->function); return; } SET_REG32(PPC_REG_ARG1, b); ins_f_byte(a); return; } void ins_f_byte_with_2_args(unsigned int a, INT32 b, INT32 c) { maybe_update_pc(); #ifdef PIKE_DEBUG if (d_flag < 3) #endif switch(a) { case F_2_LOCALS: ppc64_push_local(b); ppc64_push_local(c); return; } SET_REG32(PPC_REG_ARG1, b); SET_REG32(PPC_REG_ARG2, c); ins_f_byte(a); return; } INT32 ppc64_ins_f_jump(unsigned int a, int backward_jump) { INT32 ret, pos_=0; int (*test_func)(void); if(a == F_BRANCH) test_func = NULL;
fbe10f2019-09-03Henrik Grubbström (Grubba)  else if(a == F_CATCH || a == F_CATCH_AT || a == F_RECUR ||
a00f6f2007-04-01Marcus Comstedt  a == F_RECUR_AND_POP || a == F_TAIL_RECUR) return -1; else if(a<F_OFFSET || !(instrs[a-F_OFFSET].flags & I_BRANCH) || !(test_func = instrs[a-F_OFFSET].address)) Pike_fatal("ppc64_ins_f_jump: invalid branch op %d\n", a);
4ea9152010-09-16Marcus Comstedt  maybe_update_pc();
a00f6f2007-04-01Marcus Comstedt  FLUSH_CODE_GENERATOR_STATE(); if(test_func) { ADD_CALL(test_func); /* cmpldi r3,0 */ CMPLI(1, PPC_REG_RET, 0); /* beq .+8 */ BC(12, 2, 2); pos_ = PIKE_PC; } if(backward_jump) { ADD_CALL(branch_check_threads_etc); if(pos_) Pike_compiler->new_program->program[pos_-1] += 4*(PIKE_PC-pos_); }
cc7cf42015-10-14Martin Nilsson  ret=(INT32) PIKE_PC;
a00f6f2007-04-01Marcus Comstedt  /* b . */ B(0); return ret; } INT32 ppc64_ins_f_jump_with_arg(unsigned int a, unsigned INT32 b, int backward_jump) { if(a == F_COND_RECUR) return -1; SET_REG32(PPC_REG_ARG1, b); return ppc64_ins_f_jump(a, backward_jump); } INT32 ppc64_ins_f_jump_with_2_args(unsigned int a, unsigned INT32 b, unsigned INT32 c, int backward_jump) { SET_REG32(PPC_REG_ARG1, b); SET_REG32(PPC_REG_ARG2, c); return ppc64_ins_f_jump(a, backward_jump); } void ppc64_update_f_jump(INT32 offset, INT32 to_offset) { PIKE_OPCODE_T *op = &Pike_compiler->new_program->program[offset]; *op = (*op & 0xfc000003) | (((to_offset - offset)<<2)&0x03fffffc); } INT32 ppc64_read_f_jump(INT32 offset) { INT32 delta = ((read_pointer(offset)&0x03fffffc)>>2); if(delta >= 0x800000) delta -= 0x1000000; return offset + delta; } void ppc64_flush_instruction_cache(void *addr, size_t len) { INT64 a; #ifdef HAVE_MAKEDATAEXECUTABLE /* Call optimized cache flushing in Mac OS X */ MakeDataExecutable(addr, len); return; #endif #ifdef _POWER #ifdef _AIX __asm__(".machine \"pwr\""); #endif /* Method as described in * * http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixassem/alangref/clf.htm */ len >>= 2; for(a = (INT64)addr; len>0; --len) { __asm__("clf 0,%0" : : "r" (a)); a += 4; } __asm__("dcs"); __asm__("ics"); #else /* !_POWER */ #ifdef _AIX __asm__(".machine \"ppc\""); #endif len >>= 2; for(a = (INT64)addr; len>0; --len) { __asm__("icbi 0,%0" : : "r" (a)); __asm__("dcbst 0,%0" : : "r" (a)); a += 4; } __asm__("sync"); __asm__("isync"); #endif /* _POWER */ } #if 0
2d10fb2016-12-29Arne Goedeke #define addstr(s, l) buffer_memcpy(buf, (s), (l))
a00f6f2007-04-01Marcus Comstedt #define adddata2(s,l) addstr((char *)(s),(l) * sizeof((s)[0]));
2d10fb2016-12-29Arne Goedeke void ppc64_encode_program(struct program *p, struct byte_buffer *buf)
a00f6f2007-04-01Marcus Comstedt { size_t prev = 0, rel; /* De-relocate the program... */ for (rel = 0; rel < p->num_relocations; rel++) { size_t off = p->relocations[rel]; INT32 opcode; #ifdef PIKE_DEBUG if (off < prev) { Pike_fatal("Relocations in bad order!\n"); } #endif /* PIKE_DEBUG */ adddata2(p->program + prev, off - prev); #ifdef PIKE_DEBUG if ((p->program[off] & 0xfc000002) != 0x48000000) Pike_fatal("Bad relocation: %d, off:%d, opcode: 0x%08x\n", rel, off, p->program[off]); #endif /* PIKE_DEBUG */ /* Relocate to 0 */ opcode = p->program[off] & 0x03ffffff; opcode += (INT32)(void *)(p->program+off); adddata2(&opcode, 1); prev = off+4; } adddata2(p->program + prev, p->num_program - prev); } void ppc64_decode_program(struct program *p) { /* Relocate the program... */ PIKE_OPCODE_T *prog = p->program; size_t rel = p->num_relocations; while (rel--) { PIKE_OPCODE_T *o = prog+p->relocations[rel]; INT32 disp = *o - (INT32)(void*)o; if(disp < -33554432 || disp > 33554431) Pike_fatal("Relocation %d out of range!\n", disp); *o = 0x48000000 | (disp & 0x03ffffff); } } #endif void ppc64_disassemble_code(void *addr, size_t bytes) { /* Short forms of multicharacter opcode forms:
13670c2015-05-25Martin Nilsson 
a00f6f2007-04-01Marcus Comstedt  F = XFX G = XFL L = XL O = XO Z = XS S = SC N = MD W = MDS E = DS */ static const char *opname[] = {
13670c2015-05-25Martin Nilsson  NULL, NULL, "Dtdi", "Dtwi", NULL, NULL, NULL, "Dmulli",
a00f6f2007-04-01Marcus Comstedt  "Dsubfic", NULL, "Dcmpli", "Dcmpi", "Daddic", "Daddic.", "Daddi", "Daddis", NULL, "Ssc", NULL, NULL, "Mrlwimi", "Mrlwinm", NULL, "Mrlwnm", "Dori", "Doris", "Dxori", "Dxoris", "Dandi.", "Dandis.", NULL, NULL, "Dlwz", "Dlwzu", "Dlbz", "Dlbzu", "Dstw", "Dstwu", "Dstb", "Dstbu", "Dlhz", "Dlhzu", "Dlha", "Dlhau", "Dsth", "Dsthu", "Dlmw", "Dstmw", "Dlfs", "Dlfsu", "Dlfd", "Dlfdu", "Dstfs", "Dstfsu", "Dstfd", "Dstfdu", }; static const char *opname_bcx[] = { "Bbc", "Bbcl", "Bbca", "Bbcla", }; static const char *opname_bx[] = { "Ib", "Ibl", "Iba", "Ibla", }; static const char *opname_19[] = { "Lcreqv", "Lcror", NULL, NULL, NULL, "Lmcrf", "Lrfid", "Lbcctr", "Lbclr", NULL, "Lcrnor", "Lcrxor", "Lrfi", "Lcrand", "Lcrorc", NULL, "Lisync", "Lcrnand", "Lcrandc", }; static short opxo_19[] = { 289, 449, 0, 0, 0, 0, 18, 528, 16, 0, 33, 193, 50, 257, 417, 0, 150, 225, 129, }; static const char *opname_31_010[] = { "Osubfc", "Omulhdu", "Oaddc", "Omulhwu", "Oneg", NULL, "Oadd", NULL, NULL, "Omulhd", NULL, "Omulhw", "Osubfe", NULL, "Oadde", NULL, "Osubfme", "Omulld", "Oaddme", "Omullw", "Osubfze", "Odivd", "Oaddze", "Odivw", "Osubf", "Odivdu", NULL, "Odivwu", }; static short opxo_31_010[] = { 8, 9, 10, 11, 104, 0, 266, 0, 0, 73, 0, 75, 136, 0, 138, 0, 232, 233, 234, 235, 200, 489, 202, 491, 40, 457, 0, 459, }; static const char *opname_31_100[] = { "Xmtmsrd", NULL, "Xslbmte", NULL, "Xtlbiel", NULL, "Xmtmsr", NULL, "Fmtcrf", "Xmfcr", "Xslbia", "Xslbmfev", "Xtlbia", "Fmftb", "Xmtsrin", "Xmfsr", NULL, "Fmtspr", NULL, "Fmfspr", "Xmtsr", "Xslbmfee", "Xslbie", "Xmfmsr", "Xtlbie", "Xmfsrin", }; static short opxo_31_100[] = { 178, 0, 402, 0, 274, 0, 146, 0, 144, 19, 498, 851, 370, 371, 242, 595, 0, 467, 0, 339, 210, 915, 434, 83, 306, 659, }; static const char *opname_31_101[] = { "Xdcba", NULL, "Xlfsx", "Xlwbrx", "Xlswx", "Xsthux", "Xecowx", NULL, NULL, "Xdcbi", NULL, "Xlhaux", NULL, "Xlwaux", "Xstwx", "Xstwcx.", "Xstdx", "Xlwzux", "Xdcbst", "Xldux", "Xlbzx", "Xdcbf", NULL, "Xldarx", NULL, "Xstfiwx", "Xicbi", NULL, NULL, NULL, NULL, "Xstfsx", "Xstwbrx", "Xstswx", "Xlfsux", "Xtlbsync", NULL, "Xlfdx", "Xsync", "Xlswi", NULL, NULL, NULL, "Xlhzx", "Xdcbt", NULL, "Xstwux", NULL, "Xstdux", "Xstbx", "Xstdcx.", NULL, "Xlbzux", NULL, NULL, NULL, NULL, NULL, "Xdcbz", NULL, NULL, "Xlhbrx", NULL, "Xstfsux", NULL, NULL, "Xstfdx", NULL, "Xstswi", "Xlfdux", NULL, NULL, "Xsthx", NULL, NULL, "Xlhzux", "Xeciwx", NULL, "Xlhax", NULL, "Xlwax", "Xstbux", "Xdcbtst", NULL, "Xlwzx", NULL, "Xldx", "Xlwarx", NULL, NULL, "Xsthbrx", NULL, NULL, NULL, NULL, NULL, "Xeieio", NULL, "Xstfdux", }; static short opxo_31_101[] = { 758, 0, 535, 534, 533, 439, 438, 0, 0, 470, 0, 375, 0, 373, 151, 150, 149, 55, 54, 53, 87, 86, 0, 84, 0, 983, 982, 0, 0, 0, 0, 663, 662, 661, 567, 566, 0, 599, 598, 597, 0, 0, 0, 279, 278, 0, 183, 0, 181, 215, 214, 0, 119, 0, 0, 0, 0, 0, 1014, 0, 0, 790, 0, 695, 0, 0, 727, 0, 725, 631, 0, 0, 407, 0, 0, 311, 310, 0, 343, 0, 341, 247, 246, 0, 23, 0, 21, 20, 0, 0, 918, 0, 0, 0, 0, 0, 854, 0, 759, }; static const char *opname_31_110[] = { NULL, NULL, "Xextsh", NULL, "Xextsb", NULL, "Xsld", "Xcntlzw", "Xsrd", "Xslw", "Xsrad", "Xsrw", "Xsraw", "Xextsw", "Xsrawi", }; static short opxo_31_110[] = { 0, 0, 922, 0, 954, 0, 27, 26, 539, 24, 794, 536, 792, 986, 824, }; static const char *opname_31_111[] = { "Xand", "Xandc", NULL, "Xnor", NULL, NULL, NULL, NULL, "Xeqv", "Xxor", NULL, NULL, "Xorc", "Xor", "Xnand", NULL, }; static const char *opname_59[] = { NULL, NULL, "Afdivs", NULL, "Afsubs", "Afadds", "Afsqrts", NULL, "Afres", "Afmuls", NULL, NULL, "Afmsubs", "Afmadds", "Afnmsubs", "Afnmadds" }; static const char *opname_63_0[] = { NULL, "Xfnabs", "Xfabs", NULL, NULL, "Xfcmpu", NULL, NULL, "Xfcmpo", NULL, "Xmtfsb1", "Xmcrfs", NULL, "Xmtfsb0", "Xfctiwz", "Xfctiw", "Xfneg", "Xfrsp", NULL, "Xfmr", NULL, NULL, "Gmtfsf", NULL, NULL, NULL, NULL, NULL, "Xfctidz", "Xfctid", "Xmtfsfi", NULL, "Xfcfid", NULL, "Xmffs", }; static short opxo_63_0[] = { 0, 136, 264, 0, 0, 0, 0, 0, 32, 0, 38, 64, 0, 70, 15, 14, 40, 12, 0, 72, 0, 0, 711, 0, 0, 0, 0, 0, 815, 814, 134, 0, 846, 0, 583, }; static const char *opname_63_1[] = { NULL, NULL, "Afdiv", NULL, "Afsub", "Afadd", "Afsqrt", "Afsel", NULL, "Afmul", "Afrsqrte", NULL, "Afmsub", "Afmadd", "Afnmsub", "Afnmadd" }; unsigned INT32 *code = addr; size_t len = (bytes+3)>>2; while(len--) { int opcd, xo=0, form; const char *instr_name; unsigned INT32 instr = *code; fprintf(stderr, "%p %08x ", code++, instr); switch(opcd = ((instr>>26)&63)) { case 16: /* bcx, B-Form */ instr_name = opname_bcx[instr&3]; break; case 18: /* bx, I-Form */ instr_name = opname_bx[instr&3]; break; case 19: { int h; xo = (instr>>1)&1023; h = (xo^119)%19;
13670c2015-05-25Martin Nilsson  instr_name = (xo == opxo_19[h]? opname_19[h]:NULL);
a00f6f2007-04-01Marcus Comstedt  } break; case 30: /* 64 bit rotate, MD or MDS form */ xo = (instr>>2)&7; switch(xo) { case 0: instr_name = "Nrldicl"; break; case 1: instr_name = "Nrldicr"; break; case 2: instr_name = "Nrldic"; break; case 3: instr_name = "Nrldimi"; break; case 4: instr_name = ((instr&2)? "Wrldcr":"Wrldcl"); break; default: instr_name = NULL; break; } break; case 31: xo = (instr>>1)&1023; switch((xo>>2)&7) { int h; case 0: switch(xo) { case 0: instr_name = "Xcmp"; break; case 32: instr_name = "Xcmpl"; break; case 512: instr_name = "Xmcrxr"; break; default: instr_name = NULL; break; } break; case 1: switch(xo) { case 4: instr_name = "Xtw"; break; case 58: instr_name = "Xcntlzd"; break; case 68: instr_name = "Xtd"; break; case 711: instr_name = "Zsradi"; break; default: instr_name = NULL; break; } break; case 2: h = ((xo&0x1ff)^160)%28; instr_name = ((xo&0x1ff) == opxo_31_010[h]? opname_31_010[h]:NULL); break; case 4: h = (xo^98)%26; instr_name = (xo == opxo_31_100[h]? opname_31_100[h]:NULL);
2eb0642015-10-14Marcus Comstedt  if(instr & (1<<20)) {
dac3c22008-06-26Marcus Comstedt  if(xo == 144) instr_name = "Fmtocrf"; else if(xo == 19) instr_name = "Fmfocrf";
2eb0642015-10-14Marcus Comstedt  }
a00f6f2007-04-01Marcus Comstedt  break; case 5: h = (xo^67)%99; instr_name = (xo == opxo_31_101[h]? opname_31_101[h]:NULL); break; case 6: h = (xo^195)%15; instr_name = (xo == opxo_31_110[h]? opname_31_110[h]:NULL); break; case 7: instr_name = ((xo & 0x21f)==0x1c? opname_31_111[(xo>>5)&15]:NULL); break; default: instr_name = NULL; break; } break; case 58: /* 64-bit load, DS-Form */ xo = instr&3; switch(xo) { case 0: instr_name = "Eld"; break; case 1: instr_name = "Eldu"; break; case 2: instr_name = "Elwa"; break; default: instr_name = NULL; break; } break; case 59: /* single precision math, A-Form */ xo = (instr>>1)&0x1f; instr_name = ((xo&0x10)? opname_59[xo&15] : NULL); break; case 62: /* 64-bit store, DS-Form */ xo = instr&3; switch(xo) { case 0: instr_name = "Estd"; break; case 1: instr_name = "Estdu"; break; default: instr_name = NULL; break; } break; case 63: /* double precision math */ if(instr&0x20) { xo = (instr>>1)&0x1f; instr_name = opname_63_1[xo&15]; } else { int h; xo = (instr>>1)&0x3ff; h = (xo^355)%35; instr_name = (xo == opxo_63_0[h]? opname_63_0[h]:NULL); } break; default: instr_name = (opcd < 56? opname[opcd] : NULL); break; } form = (instr_name? *instr_name++ : '?'); switch(form) { case 'I': fprintf(stderr, "%s 0x%lx\n", instr_name, (instr&0x03fffffc)+((instr&2)? 0:(INT64)(code-1))); break; case 'B': /* Maybe pretty-print BO/BI here? */ fprintf(stderr, "%s %d,%d,0x%lx\n", instr_name, (instr>>21)&31, (instr>>16)&31, (instr&0x0000fffc)+((instr&2)? 0:(INT64)(code-1))); break; case 'S': /* really 'SC' */ fprintf(stderr, "%s\n", instr_name); break; case 'D': case 'E': /* really 'DS' */ { INT32 imm = instr & 0xffff; char immtext[8]; if(form == 'E') imm &= ~3; if((imm & 0x8000) && opcd != 10 && (opcd < 24 || opcd > 29)) imm -= 0x10000; if(imm<0) sprintf(immtext, "-0x%x", -imm); else sprintf(immtext, "0x%x", imm); if(opcd == 2 || opcd == 3) fprintf(stderr, "%s %d,r%d,%s\n", instr_name, (instr>>21)&31, (instr>>16)&31, immtext); else if(opcd == 10 || opcd == 11) fprintf(stderr, "%s cr%d,%d,r%d,%s\n", instr_name, (instr>>23)&7, (instr>>21)&1, (instr>>16)&31, immtext);
dac3c22008-06-26Marcus Comstedt  else if(opcd >= 48 && opcd < 56) fprintf(stderr, "%s fr%d,%s(r%d)\n", instr_name, (instr>>21)&31, immtext, (instr>>16)&31);
a00f6f2007-04-01Marcus Comstedt  else if(opcd >= 32) fprintf(stderr, "%s r%d,%s(r%d)\n", instr_name, (instr>>21)&31, immtext, (instr>>16)&31); else if(opcd >= 24 && opcd <= 29) fprintf(stderr, "%s r%d,r%d,%s\n", instr_name, (instr>>16)&31, (instr>>21)&31, immtext); else fprintf(stderr, "%s r%d,r%d,%s\n", instr_name, (instr>>21)&31, (instr>>16)&31, immtext); } break; case 'X': if(opcd == 63) { if(xo & 8) fprintf(stderr, "%s%s fr%d,fr%d\n", instr_name, ((instr&1)? ".":""), (instr>>21)&31, (instr>>11)&31); else if(xo & 512) fprintf(stderr, "%s%s fr%d\n", instr_name, ((instr&1)? ".":""), (instr>>21)&31); else if(xo & 128) fprintf(stderr, "%s%s crf%d,%d\n", instr_name, ((instr&1)? ".":""), (instr>>23)&7, (instr>>12)&15); else if(xo & 2) fprintf(stderr, "%s%s crb%d\n", instr_name, ((instr&1)? ".":""), (instr>>21)&31); else if(xo & 64) fprintf(stderr, "%s crf%d,crf%d\n", instr_name, (instr>>23)&7, (instr>>18)&7); else fprintf(stderr, "%s crf%d,fr%d,fr%d\n", instr_name, (instr>>23)&7, (instr>>16)&31, (instr>>11)&31);
dac3c22008-06-26Marcus Comstedt  } else if((xo & 543)==535) {
a00f6f2007-04-01Marcus Comstedt  fprintf(stderr, "%s fr%d,r%d,r%d\n", instr_name, (instr>>21)&31, (instr>>16)&31, (instr>>11)&31); } else { if (xo == 824) fprintf(stderr, "%s%s r%d,r%d,%d\n", instr_name, ((instr&1)? ".":""), (instr>>16)&31, (instr>>21)&31, (instr>>11)&31); else if(!(xo & 991)) fprintf(stderr, "%s crf%d,%d,r%d,r%d\n", instr_name, (instr>>23)&7, (instr>>21)&1, (instr>>16)&31, (instr>>11)&31);
dac3c22008-06-26Marcus Comstedt  else if((xo & 27)==24 || ((xo>>8)|(xo&255))==27)
a00f6f2007-04-01Marcus Comstedt  fprintf(stderr, "%s%s r%d,r%d,r%d\n", instr_name, ((instr&1)? ".":""), (instr>>16)&31, (instr>>21)&31, (instr>>11)&31); else if(!(xo & 24)) { if(xo&4) fprintf(stderr, "%s %d,r%d,r%d\n", instr_name, (instr>>21)&31, (instr>>16)&31, (instr>>11)&31); else fprintf(stderr, "%s crf%d\n", instr_name, (instr>>23)&7); } else if(xo & 8) fprintf(stderr, "%s%s r%d,r%d\n", instr_name, ((instr&1)? ".":""), (instr>>16)&31, (instr>>21)&31); else if(!(xo & 772)) {
dac3c22008-06-26Marcus Comstedt  if((xo & 96)==96)
a00f6f2007-04-01Marcus Comstedt  fprintf(stderr, "%s r%d,r%d\n", instr_name, (instr>>21)&31, (instr>>11)&31); else if((xo & 192)==192) fprintf(stderr, "%s %d,r%d\n", instr_name, (instr>>16)&15, (instr>>21)&31);
dac3c22008-06-26Marcus Comstedt  else if(xo & 128) fprintf(stderr, "%s r%d,%d\n", instr_name, (instr>>21)&31, (instr>>16)&1); else fprintf(stderr, "%s r%d\n", instr_name, (instr>>21)&31); } else if((xo & 639)==597)
a00f6f2007-04-01Marcus Comstedt  fprintf(stderr, "%s r%d,r%d,%d\n", instr_name, (instr>>21)&31, (instr>>16)&31, (instr>>11)&31);
dac3c22008-06-26Marcus Comstedt  else if(xo == 370 || xo == 498 || xo == 566 || xo == 598 || xo == 854)
a00f6f2007-04-01Marcus Comstedt  fprintf(stderr, "%s\n", instr_name);
dac3c22008-06-26Marcus Comstedt  else if(!(xo & 4)) { if((xo & 479)==274)
a00f6f2007-04-01Marcus Comstedt  fprintf(stderr, "%s r%d,%d\n", instr_name,
dac3c22008-06-26Marcus Comstedt  (instr>>11)&31, (instr>>21)&1);
2eb0642015-10-14Marcus Comstedt  else if(xo & 32)
a00f6f2007-04-01Marcus Comstedt  fprintf(stderr, "%s r%d\n", instr_name, (instr>>11)&31);
dac3c22008-06-26Marcus Comstedt  else if(xo == 595) fprintf(stderr, "%s r%d,%d\n", instr_name, (instr>>21)&31, (instr>>16)&15); else fprintf(stderr, "%s r%d,r%d\n", instr_name, (instr>>21)&31, (instr>>11)&31); } else if(instr_name[0]=='d' || instr_name[0]=='i') { if(xo == 278) fprintf(stderr, "%s r%d,r%d,%d\n", instr_name, (instr>>16)&31, (instr>>11)&31, (instr>>21)&3); else fprintf(stderr, "%s r%d,r%d\n", instr_name, (instr>>16)&31, (instr>>11)&31); } else
a00f6f2007-04-01Marcus Comstedt  fprintf(stderr, "%s r%d,r%d,r%d\n", instr_name, (instr>>21)&31, (instr>>16)&31, (instr>>11)&31); } break; case 'L': /* really 'XL' */ if(!xo) fprintf(stderr, "%s cr%d,cr%d\n", instr_name, (instr>>23)&7, (instr>>18)&7); else if((xo & 511) == 16)
dac3c22008-06-26Marcus Comstedt  /* Maybe pretty-print BO/BI/BH here? */ fprintf(stderr, "%s%s %d,%d,%d\n", instr_name, ((instr&1)? "l":""), (instr>>21)&31, (instr>>16)&31, (instr>>11)&3);
13670c2015-05-25Martin Nilsson  else if(xo&1)
a00f6f2007-04-01Marcus Comstedt  fprintf(stderr, "%s crb%d,crb%d,crb%d\n", instr_name, (instr>>21)&31, (instr>>16)&31, (instr>>11)&31); else fprintf(stderr, "%s\n", instr_name); break; case 'F': /* really 'XFX' */ {
dac3c22008-06-26Marcus Comstedt  int arg = (!(xo & 256)? (instr>>12)&255 :
a00f6f2007-04-01Marcus Comstedt  ((instr>>6)&0x3e0)|((instr>>16)&31)); if(xo&128) fprintf(stderr, "%s %d,r%d\n", instr_name, arg, (instr>>21)&31); else fprintf(stderr, "%s r%d,%d\n", instr_name, (instr>>21)&31, arg); } break; case 'G': /* really 'XFL' */ fprintf(stderr, "%s%s 0x%x,fr%d\n", instr_name, ((instr&1)? ".":""), (instr>>17)&255, (instr>>11)&31); break; case 'O': /* really 'XO' */ if((xo&0x41)==0x40) fprintf(stderr, "%s%s%s r%d,r%d\n", instr_name, ((instr&(1<<10))? "o":""), ((instr&1)? ".":""), (instr>>21)&31, (instr>>16)&31); else fprintf(stderr, "%s%s%s r%d,r%d,r%d\n", instr_name, ((instr&(1<<10))? "o":""), ((instr&1)? ".":""), (instr>>21)&31, (instr>>16)&31, (instr>>11)&31); break; case 'Z': /* really 'XS' */ fprintf(stderr, "%s%s r%d,r%d,%d\n", instr_name, ((instr&1)? ".":""), (instr>>16)&31, (instr>>21)&31, ((instr>>11)&31)|((instr&2)<<4)); break; case 'A': if(xo<22) fprintf(stderr, "%s%s fr%d,fr%d,fr%d\n", instr_name, ((instr&1)? ".":""), (instr>>21)&31, (instr>>16)&31, (instr>>11)&31); else if(xo >= 28 || xo == 23) fprintf(stderr, "%s%s fr%d,fr%d,fr%d,fr%d\n", instr_name, ((instr&1)? ".":""), (instr>>21)&31, (instr>>16)&31, (instr>>6)&31, (instr>>11)&31); else if(xo & 1) fprintf(stderr, "%s%s fr%d,fr%d,fr%d\n", instr_name, ((instr&1)? ".":""), (instr>>21)&31, (instr>>16)&31, (instr>>6)&31); else fprintf(stderr, "%s%s fr%d,fr%d\n", instr_name, ((instr&1)? ".":""), (instr>>21)&31, (instr>>11)&31); break; case 'M': fprintf(stderr, (opcd==23? "%s%s r%d,r%d,r%d,%d,%d\n" : "%s%s r%d,r%d,%d,%d,%d\n"), instr_name, ((instr&1)? ".":""), (instr>>16)&31, (instr>>21)&31, (instr>>11)&31, (instr>>6)&31, (instr>>1)&31); break;
dac3c22008-06-26Marcus Comstedt  case 'N': /* really 'MD' */
a00f6f2007-04-01Marcus Comstedt  fprintf(stderr, "%s%s r%d,r%d,%d,%d\n", instr_name, ((instr&1)? ".":""), (instr>>16)&31, (instr>>21)&31, ((instr>>11)&31)|((instr&2)<<4), ((instr>>6)&31)|(instr&32)); break;
dac3c22008-06-26Marcus Comstedt  case 'W': /* really 'MDS' */
a00f6f2007-04-01Marcus Comstedt  fprintf(stderr, "%s%s r%d,r%d,r%d,%d\n", instr_name, ((instr&1)? ".":""), (instr>>16)&31, (instr>>21)&31, (instr>>11)&31, ((instr>>6)&31)|(instr&32)); break; default: fprintf(stderr, ".long 0x%x\n", instr); break; } } }