/* * hex.c * $Id: hex.c,v 1.14 2005/01/25 14:45:15 mah Exp $ * Christoph Berg * * 010811 */ #include #include #include #include #include #include "opcode.h" int intflip = 1; char *strquote(char *memory) { static char quote[18]; int i, j, c; for(i = 0, j = 0; i < 16; i++, j++) { c = memory[i] & 0x7f; if(j == 8) // insert space quote[j++] = ' '; quote[j] = 32 <= c && c < 128 ? memory[i] : '.'; } quote[17] = '\0'; return quote; } char *byte2bin(int byte) { int i; static char bin[9]; int mask = 1; for(i = 7; i >= 0; i--) { bin[i] = byte & mask ? '1' : '0'; mask <<= 1; } bin[8] = '\0'; return bin; } void fdump(char *memory, int start, int length) { // TODO address translation? //copied from hexdump int pos; int *i0, *i1, *i2, *i3; int ii0, ii1, ii2, ii3; FILE* fd; start &= ~0x0f; // clip lower 4 bits fd=fopen("output.txt","a"); fprintf(fd,"\n"); //empty line as separator for(pos = start; pos < start + length; pos += 16) { i0 = (int *)(memory+pos+0); i1 = (int *)(memory+pos+4); i2 = (int *)(memory+pos+8); i3 = (int *)(memory+pos+12); ii0 = *i0; ii1 = *i1; ii2 = *i2; ii3 = *i3; if(!intflip) {// XXX this is probably not portable ii0 = htonl(ii0); ii1 = htonl(ii1); ii2 = htonl(ii2); ii3 = htonl(ii3); } fprintf(fd,"%8x: %08x %08x %08x %08x %s\n", pos, ii0, ii1, ii2, ii3, strquote(memory+pos)); } } void hexdump(char *memory, int start, int length) { // TODO address translation? int pos; int *i0, *i1, *i2, *i3; int ii0, ii1, ii2, ii3; start &= ~0x0f; // clip lower 4 bits for(pos = start; pos < start + length; pos += 16) { i0 = (int *)(memory+pos+0); i1 = (int *)(memory+pos+4); i2 = (int *)(memory+pos+8); i3 = (int *)(memory+pos+12); ii0 = *i0; ii1 = *i1; ii2 = *i2; ii3 = *i3; if(!intflip) {// XXX this is probably not portable ii0 = htonl(ii0); ii1 = htonl(ii1); ii2 = htonl(ii2); ii3 = htonl(ii3); } printf("%8x: %08x %08x %08x %08x %s\n", pos, ii0, ii1, ii2, ii3, strquote(memory+pos)); } } void bindump(char *memory, int start, int length) { // TODO address translation? int pos; int *i0, ii0; start &= ~0x03; // clip lower 2 bits for(pos = start; pos < start + length; pos += 4) { i0 = (int *)(memory+pos+0); ii0 = *i0; if(!intflip) ii0 = htonl(ii0); printf("%8x: ", pos); printf("%s ", byte2bin(memory[pos])); printf("%s ", byte2bin(memory[pos+1])); printf("%s ", byte2bin(memory[pos+2])); printf("%s ", byte2bin(memory[pos+3])); printf(" %08x\n", ii0); } } int str2int(char *str) { if(str == NULL) return 0; if(str[0] == '0') { if(str[1] == 'x') // hex return strtol(str, NULL, 16); else // oct return strtol(str, NULL, 8); } return strtol(str, NULL, 10); } #define INT2STR_MAX 0x100 char *int2str(int i) { // ugly and dangerous, but shorter and easier to use than it was // TODO maybe replace by conditional conversion BCD // TODO maybe replace by define hack return two arguments static int stridx = 0; static char str[16][20]; stridx = (stridx+1) % 16; if(-INT2STR_MAX < i && i < INT2STR_MAX) { sprintf(str[stridx], "%d", i); } else { sprintf(str[stridx], "0x%x", i); } return str[stridx]; } char *disassemble(int command) { static char c[30]; if(command == 0) return "nop"; switch(OPCODE(command)) { // J type case OP_J: sprintf(c, "j #%d", IMM_J(command)); break; case OP_JAL: sprintf(c, "jal #%d", IMM_J(command)); break; case OP_TRAP: sprintf(c, "trap #0x%x", IMM_J(command)); break; case OP_RFE: sprintf(c, "rfe"); break; // I type case OP_LB: sprintf(c, "lb r%d,%d(r%d)", RD_I(command), IMM_I(command), RS1(command)); break; case OP_LH: sprintf(c, "lh r%d,%d(r%d)", RD_I(command), IMM_I(command), RS1(command)); break; case OP_LW: sprintf(c, "lw r%d,%d(r%d)", RD_I(command), IMM_I(command), RS1(command)); break; case OP_LBU: sprintf(c, "lbu r%d,%d(r%d)", RD_I(command), IMM_I(command), RS1(command)); break; case OP_LHU: sprintf(c, "lhu r%d,%d(r%d)", RD_I(command), IMM_I(command), RS1(command)); break; case OP_SB: sprintf(c, "sb %d(r%d),r%d", IMM_I(command), RS1(command), RD_I(command)); break; case OP_SH: sprintf(c, "sh %d(r%d),r%d", IMM_I(command), RS1(command), RD_I(command)); break; case OP_SW: sprintf(c, "sw %d(r%d),r%d", IMM_I(command), RS1(command), RD_I(command)); break; case OP_ADDIO: sprintf(c, "addio r%d,r%d,#%d", RD_I(command), RS1(command), IMM_I(command)); break; case OP_ADDI: sprintf(c, "addi r%d,r%d,#%d", RD_I(command), RS1(command), IMM_I(command)); break; case OP_SUBIO: sprintf(c, "subio r%d,r%d,#%d", RD_I(command), RS1(command), IMM_I(command)); break; case OP_SUBI: sprintf(c, "subi r%d,r%d,#%d", RD_I(command), RS1(command), IMM_I(command)); break; case OP_ANDI: sprintf(c, "andi r%d,r%d,#%d", RD_I(command), RS1(command), IMM_I(command)); break; case OP_ORI: sprintf(c, "ori r%d,r%d,#%d", RD_I(command), RS1(command), IMM_I(command)); break; case OP_XORI: sprintf(c, "xori r%d,r%d,#%d", RD_I(command), RS1(command), IMM_I(command)); break; case OP_LHGI: sprintf(c, "lhgi r%d,#%d", RD_I(command), IMM_I(command)); break; case OP_CLRI: sprintf(c, "clri r%d,r%d,#%d", RD_I(command), RS1(command), IMM_I(command)); break; case OP_SGRI: sprintf(c, "sgri r%d,r%d,#%d", RD_I(command), RS1(command), IMM_I(command)); break; case OP_SEQI: sprintf(c, "seqi r%d,r%d,#%d", RD_I(command), RS1(command), IMM_I(command)); break; case OP_SGEI: sprintf(c, "sgei r%d,r%d,#%d", RD_I(command), RS1(command), IMM_I(command)); break; case OP_SLSI: sprintf(c, "slsi r%d,r%d,#%d", RD_I(command), RS1(command), IMM_I(command)); break; case OP_SNEI: sprintf(c, "snei r%d,r%d,#%d", RD_I(command), RS1(command), IMM_I(command)); break; case OP_SLEI: sprintf(c, "slei r%d,r%d,#%d", RD_I(command), RS1(command), IMM_I(command)); break; case OP_SETI: sprintf(c, "seti r%d,r%d,#%d", RD_I(command), RS1(command), IMM_I(command)); break; case OP_BEQZ: sprintf(c, "beqz r%d,#%d", RS1(command), IMM_I(command)); break; case OP_BNEZ: sprintf(c, "bnez r%d,#%d", RS1(command), IMM_I(command)); break; case OP_JR: sprintf(c, "jr r%d", RS1(command)); break; case OP_JALR: sprintf(c, "jalr r%d", RS1(command)); break; // FI type case OP_LOAD_S: sprintf(c, "load.s fr%d,%d(r%d)",RD_I(command), IMM_I(command), RS1(command)); break; case OP_LOAD_D: sprintf(c, "load.d fr%d,%d(r%d)",RD_I(command), IMM_I(command), RS1(command)); break; case OP_STORE_S: sprintf(c, "store.s %d(r%d),fr%d", IMM_I(command), RS1(command), RD_I(command)); break; case OP_STORE_D: sprintf(c, "store.d %d(r%d),fr%d", IMM_I(command), RS1(command), RD_I(command)); break; case OP_FBEQZ: sprintf(c, "fbeqz #%d", IMM_I(command)); break; case OP_FBNEZ: sprintf(c, "fbnez #%d", IMM_I(command)); break; // R type case OP_R: switch(FUNC(command)) { case R_SLLI: sprintf(c, "slli r%d,r%d,#%d", RD_R(command), RS1(command), SA(command)); break; case R_SRLI: sprintf(c, "srli r%d,r%d,#%d", RD_R(command), RS1(command), SA(command)); break; case R_SRAI: sprintf(c, "srai r%d,r%d,#%d", RD_R(command), RS1(command), SA(command)); break; case R_SLL: sprintf(c, "sll r%d,r%d,r%d", RD_R(command), RS1(command), RS2(command)); break; case R_SRL: sprintf(c, "srl r%d,r%d,r%d", RD_R(command), RS1(command), RS2(command)); break; case R_SRA: sprintf(c, "sra r%d,r%d,r%d", RD_R(command), RS1(command), RS2(command)); break; case R_ADDO: sprintf(c, "addo r%d,r%d,r%d", RD_R(command), RS1(command), RS2(command)); break; case R_ADD: sprintf(c, "add r%d,r%d,r%d", RD_R(command), RS1(command), RS2(command)); break; case R_SUBO: sprintf(c, "subo r%d,r%d,r%d", RD_R(command), RS1(command), RS2(command)); break; case R_SUB: sprintf(c, "sub r%d,r%d,r%d", RD_R(command), RS1(command), RS2(command)); break; case R_AND: sprintf(c, "and r%d,r%d,r%d", RD_R(command), RS1(command), RS2(command)); break; case R_OR: sprintf(c, "or r%d,r%d,r%d", RD_R(command), RS1(command), RS2(command)); break; case R_XOR: sprintf(c, "xor r%d,r%d,r%d", RD_R(command), RS1(command), RS2(command)); break; case R_LHG: sprintf(c, "lhg r%d,r%d,r%d", RD_R(command), RS1(command), RS2(command)); break; case R_CLR: sprintf(c, "clr r%d", RD_R(command)); break; case R_SGR: sprintf(c, "sgr r%d,r%d,r%d", RD_R(command), RS1(command), RS2(command)); break; case R_SEQ: sprintf(c, "seq r%d,r%d,r%d", RD_R(command), RS1(command), RS2(command)); break; case R_SGE: sprintf(c, "sge r%d,r%d,r%d", RD_R(command), RS1(command), RS2(command)); break; case R_SLS: sprintf(c, "sls r%d,r%d,r%d", RD_R(command), RS1(command), RS2(command)); break; case R_SNE: sprintf(c, "sne r%d,r%d,r%d", RD_R(command), RS1(command), RS2(command)); break; case R_SLE: sprintf(c, "sle r%d,r%d,r%d", RD_R(command), RS1(command), RS2(command)); break; case R_SET: sprintf(c, "set r%d", RD_R(command)); break; case R_MOVS2I: sprintf(c, "movs2i r%d,s%d", RD_R(command), SA(command)); break; case R_MOVI2S: sprintf(c, "movs2i s%d,r%d", SA(command), RS1(command)); break; default: sprintf(c, "R? %08x", command); } break; case OP_FR: switch(FUNC(command)) { case FR_FADD: if(FMT_FR(command)==FMT_D) sprintf(c, "fadd.d fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); else sprintf(c, "fadd.s fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); break; case FR_FSUB: if(FMT_FR(command)==FMT_D) sprintf(c, "fsub.d fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); else sprintf(c, "fsub.s fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); break; case FR_FMUL: if(FMT_FR(command)==FMT_D) sprintf(c, "fmul.d fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); else sprintf(c, "fmul.s fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); break; case FR_FDIV: if(FMT_FR(command)==FMT_D) sprintf(c, "fdiv.d fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); else sprintf(c, "fdiv.s fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); break; case FR_FNEG: if(FMT_FR(command)==FMT_D) sprintf(c, "fneg.d fr%d,fr%d", RD_R(command), RS1(command)); else sprintf(c, "fneg.s fr%d,fr%d", RD_R(command), RS1(command)); break; case FR_FABS: if(FMT_FR(command)==FMT_D) sprintf(c, "fabs.d fr%d,fr%d", RD_R(command), RS1(command)); else sprintf(c, "fabs.s fr%d,fr%d", RD_R(command), RS1(command)); break; case FR_FSQT: if(FMT_FR(command)==FMT_D) sprintf(c, "fsqt.d fr%d,fr%d", RD_R(command), RS1(command)); else sprintf(c, "fsqt.s fr%d,fr%d", RD_R(command), RS1(command)); break; case FR_FREM: if(FMT_FR(command)==FMT_D) sprintf(c, "frem.d fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); else sprintf(c, "frem.s fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); break; case FR_FMOV: if(FMT_FR(command)==FMT_D) sprintf(c, "fmov.d fr%d,fr%d", RD_R(command), RS1(command)); else sprintf(c, "fmov.s fr%d,fr%d", RD_R(command), RS1(command)); break; case FR_MF2I: sprintf(c, "mf2i r%d,fr%d", RD_R(command), RS1(command)); break; case FR_MI2F: sprintf(c, "mi2f fr%d,r%d", RD_R(command), RS2(command)); break; case FR_CVT_S: // convert from single switch(FMT_FR(command)) { case FMT_D: // convert to double sprintf(c, "cvt.s.d fr%d,fr%d", RD_R(command), RS1(command)); break; case FMT_I: // convert to integer sprintf(c, "cvt.s.i fr%d,fr%d", RD_R(command), RS1(command)); break; default: printf("Unknown format: FMT? 0x%x", FMT_FR(command)); sprintf(c, "FR? %08x", command); } break; case FR_CVT_D: // convert from double switch(FMT_FR(command)) { case FMT_S: // convert to single sprintf(c, "cvt.d.s fr%d,fr%d", RD_R(command), RS1(command)); break; case FMT_I: // convert to integer sprintf(c, "cvt.d.i fr%d,fr%d", RD_R(command), RS1(command)); break; default: printf("Unknown format: FMT? 0x%x", FMT_FR(command)); sprintf(c, "FR? %08x", command); } break; case FR_CVT_I: // convert from integer switch(FMT_FR(command)) { case FMT_S: // convert to single sprintf(c, "cvt.i.s fr%d,fr%d", RD_R(command), RS1(command)); break; case FMT_D: // convert to double sprintf(c, "cvt.i.d fr%d,fr%d", RD_R(command), RS1(command)); break; default: printf("Unknown format: FMT? 0x%x", FMT_FR(command)); sprintf(c, "FR? %08x", command); } break; case FR_EQ: // float equal switch(FMT_FR(command)) { case FMT_S: // convert to single sprintf(c, "fc.eq.s fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); break; case FMT_D: // convert to double sprintf(c, "fc.eq.d fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); break; default: printf("Unknown format: FMT? 0x%x", FMT_FR(command)); sprintf(c, "FR? %08x", command); } break; case FR_NE: // float not equal switch(FMT_FR(command)) { case FMT_S: // convert to single sprintf(c, "fc.ne.s fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); break; case FMT_D: // convert to double sprintf(c, "fc.ne.d fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); break; default: printf("Unknown format: FMT? 0x%x", FMT_FR(command)); sprintf(c, "FR? %08x", command); } break; case FR_LT: // float less than switch(FMT_FR(command)) { case FMT_S: // convert to single sprintf(c, "fc.lt.s fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); break; case FMT_D: // convert to double sprintf(c, "fc.lt.d fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); break; default: printf("Unknown format: FMT? 0x%x", FMT_FR(command)); sprintf(c, "FR? %08x", command); } break; case FR_GT: // float greater than switch(FMT_FR(command)) { case FMT_S: // convert to single sprintf(c, "fc.gt.s fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); break; case FMT_D: // convert to double sprintf(c, "fc.gt.d fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); break; default: printf("Unknown format: FMT? 0x%x", FMT_FR(command)); sprintf(c, "FR? %08x", command); } break; case FR_LE: // float less equal switch(FMT_FR(command)) { case FMT_S: // convert to single sprintf(c, "fc.le.s fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); break; case FMT_D: // convert to double sprintf(c, "fc.le.d fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); break; default: printf("Unknown format: FMT? 0x%x", FMT_FR(command)); sprintf(c, "FR? %08x", command); } break; case FR_GE: // float greater equal switch(FMT_FR(command)) { case FMT_S: // convert to single sprintf(c, "fc.ge.s fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); break; case FMT_D: // convert to double sprintf(c, "fc.ge.d fr%d,fr%d,fr%d", RD_R(command), RS1(command), RS2(command)); break; default: printf("Unknown format: FMT? 0x%x", FMT_FR(command)); sprintf(c, "FR? %08x", command); } break; default: sprintf(c, "?? %08x (%x)", command, OPCODE(command)); } break; // end FR default: sprintf(c, "?? %08x (%x)", command, OPCODE(command)); } return c; } void disassemble_memory(char *memory, int start, int length) { // TODO address translation? int pos, *command; start &= ~0x03; // clip lower 2 bits for(pos = start; pos < start + length; pos += 4) { command = (int *)(memory+pos+0); printf("0x%08x: 0x%08x %s\n", pos, *command, disassemble(*command)); } } void explain(char *memory, int start) { // TODO address translation? int *command; command = (int *)(memory+start); printf("%8x: %08x %s\n", start, *command, disassemble(*command)); printf("Opcode is 0x%02x\n", OPCODE(*command)); printf("RS1 is %d\n", RS1(*command)); printf("RD_I is %d\n", RD_I(*command)); printf("IMM_I is %d\n", IMM_I(*command)); printf("RS2 is %d\n", RS2(*command)); printf("RD_R is %d\n", RD_R(*command)); printf("SA is %d\n", SA(*command)); printf("FUNC is %02x\n", FUNC(*command)); printf("IMM_J is %d\n", IMM_J(*command)); }