// The kernel event notifications // Here you may take desired actions upon some kernel events static int notify(processor_t::idp_notify msgid, ...) { va_list va; va_start(va, msgid); // A well behavior processor module should call invoke_callbacks() // in his notify() function. If this function returns 0, then // the processor module should process the notification itself // Otherwise the code should be returned to the caller: int code = invoke_callbacks(HT_IDP, msgid, va); if ( code ) return code; switch ( msgid ) { case processor_t::init: // this processor is big endian inf.mf = 1; default: break; case processor_t::term: free_ioports(ports, numports); break; case processor_t::newfile: if ( choose_ioport_device(cfgname, device, sizeof(device), NULL) ) set_device_name(device, IORESP_ALL); // default configuration if ( refresh_idpflags() == 0 ) { idpflags = 0; idpflags |= NETNODE_USE_INSN_SYNTHETIC; idpflags |= NETNODE_USE_REG_ALIASES; } // patch register names according to idpflags patch_regnames(); break; case processor_t::newprc: ptype = processor_subtype_t(va_arg(va, int)); // msg("ptype = %s\n", ptype == prc_m32r ? "m32r" : ptype == prc_m32rx ? "m32rx" : "???"); break; case processor_t::oldfile: refresh_idpflags(); { char buf[MAXSTR]; if ( helper.supval(-1, buf, sizeof(buf)) > 0 ) set_device_name(buf, IORESP_NONE); } // patch register names according to idpflags patch_regnames(); break; case processor_t::savebase: case processor_t::closebase: // synchronize the database long variable with the current configuration settings #ifdef DEBUG msg("Saving configuration: synthetic insn %s, aliases registers %s\n", use_synthetic_insn() ? "true " : "false", use_reg_aliases() ? "true" : "false" ); #endif helper.altset(-1, idpflags); helper.supset(-1, device); break; } va_end(va); return(1); }
// output an instruction and its operands void idaapi out(void) { char buf[MAXSTR]; init_output_buffer(buf, sizeof(buf)); // setup the output pointer // if this DSP instruction in executed in parallel with a NOP instruction // (example: nop || machi r1, r2), first print the NOP. if ( cmd.segpref & NEXT_INSN_PARALLEL_DSP ) { out_line("nop", COLOR_INSN); OutChar(' '); out_symbol('|'); out_symbol('|'); OutChar(' '); } char postfix[3]; // postfix to eventually insert after the insn name postfix[0] = '\0'; // postfix is null by default // use synthetic option is selected if ( use_synthetic_insn() ) { if ( cmd.segpref & SYNTHETIC_SHORT ) qstrncpy(postfix, (cmd.itype == m32r_ldi ? "8" : ".s"), sizeof(postfix)); if ( cmd.segpref & SYNTHETIC_LONG ) qstrncpy(postfix, (cmd.itype == m32r_ldi ? "16" : ".l"), sizeof(postfix)); } OutMnem(8, postfix); out_one_operand(0); // output the first operand if ( cmd.Op2.type != o_void ) { out_symbol(','); OutChar(' '); out_one_operand(1); // output the second operand } if ( cmd.Op3.type != o_void ) { out_symbol(','); OutChar(' '); out_one_operand(2); // output the third operand } // output a character representation of the immediate values // embedded in the instruction as comments if ( isVoid(cmd.ea,uFlag,0) ) OutImmChar(cmd.Op1); if ( isVoid(cmd.ea,uFlag,1) ) OutImmChar(cmd.Op2); if ( isVoid(cmd.ea,uFlag,2) ) OutImmChar(cmd.Op3); // print a parallel NOP instruction unless the current instruction // is either push or pop (in this special case, nop cannot be executed in //) if ( (cmd.itype != m32r_push && cmd.itype != m32r_pop) && cmd.segpref & NEXT_INSN_PARALLEL_NOP ) { // don't print NOP if the instruction was ld/st reg, fp, and has been converted to ld/st reg, @(arg, fp) // (in other words, in the second operand is a stack variable). // because the o_displ form of ld/st insn is 32 bits, and cannot handle a parallel nop. if ( (cmd.itype != m32r_ld && cmd.itype != m32r_st) || !isStkvar1(uFlag) ) { if ( cmd.Op1.type != o_void ) OutChar(' '); out_symbol('|'); out_symbol('|'); OutChar(' '); out_line("nop", COLOR_INSN); } } if ( cmd.segpref & NEXT_INSN_PARALLEL_OTHER ) { if ( cmd.Op1.type != o_void ) OutChar(' '); out_symbol('|'); out_symbol('|'); out_symbol('\\'); } term_output_buffer(); // terminate the output string gl_comm = 1; // ask to attach a possible user- // defined comment to it MakeLine(buf); // pass the generated line to the // kernel }
// This function (called when opening the module related configuration in // the general options) will create a dialog box asking the end-user if he // wants to use synthetic instructions and register aliases. const char *idaapi set_idp_options( const char *keyword, int /*value_type*/, const void * /*value*/ ) { short opt_subs = 0; if ( keyword != NULL ) return IDPOPT_BADKEY; if ( use_synthetic_insn() ) opt_subs |= 1; if ( use_reg_aliases() ) opt_subs |= 2; static const char form[] = "HELP\n" "Mitsubishi 32-Bit (m32r) related options :\n" "\n" " Use synthetic instructions\n" "\n" " If this option is on, IDA will simplify instructions and replace\n" " them by synthetic pseudo-instructions.\n" "\n" " For example,\n" "\n" " bc label1 ; 8 bits offset \n" " bc label2 ; 24 bits offset \n" " ldi r1, #0xF \n" " ldi r2, #0x123456 \n" " st r3, @-sp \n" " ld r4, @sp+ \n" "\n" " will be replaced by\n" "\n" " bc.s label1 \n" " bc.l label2 \n" " ldi8 r1, #0xF \n" " ldi24 r2, #0x123456 \n" " push r3 \n" " pop r4 \n" "\n" " Use registers aliases\n" "\n" " If checked, IDA will use aliases names for the following registers :\n" "\n" " r13 -> fp \n" " r14 -> lr \n" " r15 -> sp \n" " cr0 -> psw \n" " cr1 -> cbr \n" " cr2 -> spi \n" " cr3 -> spu \n" " cr6 -> bpc \n" "\n" "ENDHELP\n" "m32r related options\n" "<##Substitutions" "#For example, use bc.s instead of 8-Bit bc instructions#Use ~s~ynthetic instructions:C>" "<#For example, use fp instead or r14#Use registers ~a~liases:C>>\n\n\n\n" "<~C~hoose device name:B:0::>" "\n\n\n"; AskUsingForm_c(form, &opt_subs, choose_device); idpflags = 0; // reset the configuration if ( opt_subs & 1 ) idpflags |= NETNODE_USE_INSN_SYNTHETIC; if ( opt_subs & 2 ) idpflags |= NETNODE_USE_REG_ALIASES; patch_regnames(); return IDPOPT_OK; }