/* Prints the instruction by calling print_arguments after proper matching: */ int print_insn_crx(bfd_vma memaddr, struct disassemble_info *info) { int is_decoded; /* Nonzero means instruction has a match. */ /* Initialize global variables: */ cst4flag = 0; size_changed = 0; /* Retrieve the encoding from current memory location: */ get_words_at_PC(memaddr, info); /* Find a matching opcode in table: */ is_decoded = match_opcode(); /* If found, print the instruction's mnemonic and arguments: */ if ((is_decoded > 0) && (((words[0] << 16) != 0) || (words[1] != 0))) { info->fprintf_func(info->stream, "%s", instruction->mnemonic); if ((currInsn.nargs = get_number_of_operands()) != 0) info->fprintf_func(info->stream, "\t"); make_instruction(); print_arguments(&currInsn, memaddr, info); return currInsn.size; } /* No match found: */ info->fprintf_func(info->stream, "%s ", ILLEGAL); return 2; }
static int check_c_ret(uint32_t **instr) { uint16_t *instr1; int i; for (i = 0; i < 2; i++) { instr1 = (uint16_t *)(*instr) + i; if (match_opcode(*instr1, (MATCH_C_JR | (X_RA << RD_SHIFT)), (MASK_C_JR | RD_MASK))) { *instr = (uint32_t *)instr1; return (1); } } return (0); }
static int check_c_sdsp(uint32_t **instr) { uint16_t *instr1; int i; for (i = 0; i < 2; i++) { instr1 = (uint16_t *)(*instr) + i; if (match_opcode(*instr1, (MATCH_C_SDSP | RS2_C_RA), (MASK_C_SDSP | RS2_C_MASK))) { *instr = (uint32_t *)instr1; return (1); } } return (0); }
int fbt_provide_module_function(linker_file_t lf, int symindx, linker_symval_t *symval, void *opaque) { fbt_probe_t *fbt, *retfbt; uint32_t *instr, *limit; const char *name; char *modname; int patchval; int rval; modname = opaque; name = symval->name; /* Check if function is excluded from instrumentation */ if (fbt_excluded(name)) return (0); instr = (uint32_t *)(symval->value); limit = (uint32_t *)(symval->value + symval->size); /* Look for sd operation */ for (; instr < limit; instr++) { /* Look for a non-compressed store of ra to sp */ if (match_opcode(*instr, (MATCH_SD | RS2_RA | RS1_SP), (MASK_SD | RS2_MASK | RS1_MASK))) { rval = DTRACE_INVOP_SD; patchval = FBT_PATCHVAL; break; } /* Look for a 'C'-compressed store of ra to sp. */ if (check_c_sdsp(&instr)) { rval = DTRACE_INVOP_C_SDSP; patchval = FBT_C_PATCHVAL; break; } } if (instr >= limit) return (0); fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO); fbt->fbtp_name = name; fbt->fbtp_id = dtrace_probe_create(fbt_id, modname, name, FBT_ENTRY, 3, fbt); fbt->fbtp_patchpoint = instr; fbt->fbtp_ctl = lf; fbt->fbtp_loadcnt = lf->loadcnt; fbt->fbtp_savedval = *instr; fbt->fbtp_patchval = patchval; fbt->fbtp_rval = rval; fbt->fbtp_symindx = symindx; fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; fbt_probetab[FBT_ADDR2NDX(instr)] = fbt; lf->fbt_nentries++; retfbt = NULL; again: for (; instr < limit; instr++) { /* Look for non-compressed return */ if (match_opcode(*instr, (MATCH_JALR | (X_RA << RS1_SHIFT)), (MASK_JALR | RD_MASK | RS1_MASK | IMM_MASK))) { rval = DTRACE_INVOP_RET; patchval = FBT_PATCHVAL; break; } /* Look for 'C'-compressed return */ if (check_c_ret(&instr)) { rval = DTRACE_INVOP_C_RET; patchval = FBT_C_PATCHVAL; break; } } if (instr >= limit) return (0); /* * We have a winner! */ fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO); fbt->fbtp_name = name; if (retfbt == NULL) { fbt->fbtp_id = dtrace_probe_create(fbt_id, modname, name, FBT_RETURN, 3, fbt); } else { retfbt->fbtp_probenext = fbt; fbt->fbtp_id = retfbt->fbtp_id; } retfbt = fbt; fbt->fbtp_patchpoint = instr; fbt->fbtp_ctl = lf; fbt->fbtp_loadcnt = lf->loadcnt; fbt->fbtp_symindx = symindx; fbt->fbtp_rval = rval; fbt->fbtp_savedval = *instr; fbt->fbtp_patchval = patchval; fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; fbt_probetab[FBT_ADDR2NDX(instr)] = fbt; lf->fbt_nentries++; instr++; goto again; }
// do the same work as m68k_disasm but some instructions dis-assembled by the // UAE engine use a weird/wrong naming scheme so we remap them here rather than // touching the newcpu.c & table68k files because this file may be updated when // upgrading the UAE engine. int m68k_dasm(char **line, uint32_t addr) { char output[1024]; int offset; gchar** split; int idx; // get UAE disassembly offset = m68k_disasm(output, addr); // split string into address, opcode and operand split = g_strsplit(output, " ", 3); // search for opcode to rewrite idx = match_opcode(split[1]); if(idx != -1) { gchar *tmp; switch(idx) { case 0: /* ORI to SR #<data>,SR */ { char c = split[1][5]; g_free(split[1]); split[1] = g_strdup_printf("ORI.%c", c); tmp = g_strconcat(split[2], ",SR", NULL); g_free(split[2]); split[2] = tmp; } break; case 1: /* ANDI to SR #<data>,SR */ { char c = split[1][6]; g_free(split[1]); split[1] = g_strdup_printf("ANDI.%c", c); tmp = g_strconcat(split[2], ",SR", NULL); g_free(split[2]); split[2] = tmp; } break; case 2: /* EORI to SR #<data>,SR */ { char c = split[1][6]; g_free(split[1]); split[1] = g_strdup_printf("EORI.%c", c); tmp = g_strconcat(split[2], ",SR", NULL); g_free(split[2]); split[2] = tmp; } break; case 3: /* MOVE from SR: SR,<ea> */ { char c = split[1][6]; g_free(split[1]); split[1] = g_strdup_printf("MOVE.%c", c); tmp = g_strconcat("SR,", split[2], NULL); g_free(split[2]); split[2] = tmp; } break; case 4: /* MOVE to SR: <ea>,SR */ { char c = split[1][6]; g_free(split[1]); split[1] = g_strdup_printf("MOVE.%c", c); tmp = g_strconcat(split[2], ",SR", NULL); g_free(split[2]); split[2] = tmp; } break; case 5: /* MOVE An,USP */ g_free(split[1]); split[1] = g_strdup("MOVE"); tmp = g_strconcat(split[2], ",USP", NULL); g_free(split[2]); split[2] = tmp; break; case 6: /* MOVE USP,An */ g_free(split[1]); split[1] = g_strdup("MOVE"); tmp = g_strconcat("USP,", split[2], NULL); g_free(split[2]); split[2] = tmp; break; case 7: /* MOVEM <ea>,<list> */ { char c = split[1][6]; char *p, *q; uint16_t mask; g_free(split[1]); split[1] = g_strdup_printf("MOVEM.%c", c); p = split[2]; q = strchr(split[2], ','); q++; sscanf(p, "#$%" SCNx16, &mask); if(q[0] != '-') tmp = g_strdup_printf("%s,%s", q, create_reg_lists(mask)); else tmp = g_strdup_printf("%s,%s", q, create_rev_reg_lists(mask)); g_free(split[2]); split[2] = tmp; } break; case 8: /* MOVEM <list>, <ea> */ { char c = split[1][6]; char *p, *q; uint16_t mask; g_free(split[1]); split[1] = g_strdup_printf("MOVEM.%c", c); p = split[2]; q = strchr(split[2], ','); q++; sscanf(p, "#$%" SCNx16, &mask); if(q[0] != '-') tmp = g_strdup_printf("%s,%s", create_reg_lists(mask), q); else tmp = g_strdup_printf("%s,%s", q, create_rev_reg_lists(mask)); g_free(split[2]); split[2] = tmp; } break; case 9: /* MOVEP <Dx>,<(d16,Ay)> */ case 10: /* MOVEP <(d16,Ay)>,<Dx> */ { char c = split[1][6]; g_free(split[1]); split[1] = g_strdup_printf("MOVEP.%c", c); } break; case 11: /* TRAP #<vector> */ case 12: /* RESET.L */ case 13: /* NOP.L */ case 14: /* STOP.L */ case 15: /* RTE.L */ case 16: /* RTS.L */ case 17: /* JMP.L */ case 18: /* LEA.L */ { char *p = strchr(split[1], '.'); if(p) *p = '\0'; } break; case 20: /* BRA */ { tmp = g_strdup_printf("BRA.%c", split[1][3]); g_free(split[1]); split[1] = tmp; } break; case 19: /* BTST */ default: break; } } // search for [value] and reject it at end of line if(strchr(split[2], '[')) { char *p = strchr(split[2], '['); char *q = strrchr(split[2], ']'); char tmp[256]; p--; q++; strncpy(tmp, p, q - p); tmp[q-p] = '\0'; strcpy(p, q); strcat(split[2], tmp); } *line = g_strdup_printf("%s %s %s", split[0] ? split[0] : "", split[1] ? split[1] : "", split[2] ? split[2] : ""); g_strfreev(split); return offset; }