/* * * PRU Debug Program - disassembly routines * (c) Copyright 2011 by Arctica Technologies * Written by Steven Anderson * */ #include #include #include #include #include #include #include #include #include #include #include "prudbg.h" // util function to decode BurstLen in Format 6 instructions void GetBurstLen(char *tempstr, unsigned int BurstLen) { if (BurstLen < 124) { sprintf(tempstr, "%u", BurstLen+1); } else if (BurstLen == 124) { sprintf(tempstr, "b0"); } else if (BurstLen == 125) { sprintf(tempstr, "b1"); } else if (BurstLen == 126) { sprintf(tempstr, "b2"); } else if (BurstLen == 127) { sprintf(tempstr, "b3"); } else { sprintf(tempstr, "XX"); } } // disassemble the inst instruction and place string in str void disassemble(char *str, unsigned int inst) { unsigned char OP, ALUOP, Rs2Sel, Rs2, Rs1Sel, Rs1, RdSel, Rd, IO, SUBOP, Test, Imm2; unsigned int Imm; unsigned char LoadStore, BurstLen, RxByteAddr, Rx, Ro, RoSel, Rb; short BrOff; char tempstr[50]; char *f1_inst[] = {"ADD", "ADC", "SUB", "SUC", "LSL", "LSR", "RSB", "RSC", "AND", "OR", "XOR", "NOT", "MIN", "MAX", "CLR", "SET"}; char *f2_inst[] = { "JMP", "JAL", "LDI", "LMBD", "SCAN", "HALT", "RESERVED", "RESERVED", "RESERVED", "RESERVED", "RESERVED", "RESERVED", "RESERVED", "RESERVED", "RESERVED", "SLP" }; char *f4_inst[] = {"xx", "LT", "EQ", "LE", "GT", "NE", "GE", "A"}; char *f5_inst[] = {"xx", "BC", "BS", "xx"}; char *f6_7_inst[] = {"SBBO", "LBBO"}; char *f6_4_inst[] = {"SBCO", "LBCO"}; char *sis[] = {".b0", ".b1", ".b2", ".b3", ".w0", ".w1", ".w2", ""}; char *bytenum[] = {"", ".b1", ".b2", ".b3"}; OP = (inst & 0xE0000000) >> 29; switch (OP) { case 0: // format 1 ALUOP = (inst & 0x1E000000) >> 25; IO = (inst & 0x01000000) >> 24; Rs1Sel = (inst & 0x0000E000) >> 13; Rs1 = (inst & 0x00001F00) >> 8; RdSel = (inst & 0x000000E0) >> 5; Rd = (inst & 0x0000001F); if (IO) { Imm2 = (inst & 0x00FF0000) >> 16; sprintf(str, "%s R%u%s, R%u%s, 0x%02x", f1_inst[ALUOP], Rd, sis[RdSel], Rs1, sis[Rs1Sel], Imm2); } else { Rs2Sel = (inst & 0x00E00000) >> 21; Rs2 = (inst & 0x001F0000) >> 16; sprintf(str, "%s R%u%s, R%u%s, R%u%s", f1_inst[ALUOP], Rd, sis[RdSel], Rs1, sis[Rs1Sel], Rs2, sis[Rs2Sel]); } break; case 1: // format 2 SUBOP = (inst & 0x1E000000) >> 25; switch (SUBOP) { case 0: // JMP & JAL case 1: IO = (inst & 0x01000000) >> 24; RdSel = (inst & 0x000000E0) >> 5; Rd = (inst & 0x0000001F); if (IO) { Imm = (inst & 0x00FFFF00) >> 8; if (SUBOP == 0) sprintf(str, "%s 0x%04x", f2_inst[SUBOP], Imm); else sprintf(str, "%s R%u%s, 0x%04x", f2_inst[SUBOP], Rd, sis[RdSel], Imm); } else { Rs2Sel = (inst & 0x00E00000) >> 21; Rs2 = (inst & 0x001F0000) >> 16; if (SUBOP == 0) sprintf(str, "%s R%u%s", f2_inst[SUBOP], Rs2, sis[Rs2Sel]); else sprintf(str, "%s R%u%s, R%u%s", f2_inst[SUBOP], Rd, sis[RdSel], Rs2, sis[Rs2Sel]); } break; case 2: // LDI Imm = (inst & 0x00FFFF00) >> 8; RdSel = (inst & 0x000000E0) >> 5; Rd = (inst & 0x0000001F); sprintf(str, "%s R%u%s, 0x%04x", f2_inst[SUBOP], Rd, sis[RdSel], Imm); break; case 3: // LMBD IO = (inst & 0x01000000) >> 24; Rs1Sel = (inst & 0x0000E000) >> 13; Rs1 = (inst & 0x00001F00) >> 8; RdSel = (inst & 0x000000E0) >> 5; Rd = (inst & 0x0000001F); Rs2Sel = (inst & 0x00E00000) >> 21; Rs2 = (inst & 0x001F0000) >> 16; Imm2 = (inst & 0x00FF0000) >> 16; if (IO) { sprintf(str, "%s R%u%s, R%u%s, 0x%04x", f2_inst[SUBOP], Rd, sis[RdSel], Rs1, sis[Rs1Sel], Imm2); } else { sprintf(str, "%s R%u%s, R%u%s, R%u%s", f2_inst[SUBOP], Rd, sis[RdSel], Rs1, sis[Rs1Sel], Rs2, sis[Rs2Sel]); } break; case 4: // SCAN IO = (inst & 0x01000000) >> 24; RdSel = (inst & 0x000000E0) >> 5; Rd = (inst & 0x0000001F); Rs2Sel = (inst & 0x00E00000) >> 21; Rs2 = (inst & 0x001F0000) >> 16; Imm2 = (inst & 0x00FF0000) >> 16; if (IO) { sprintf(str, "%s R%u%s, 0x%04x", f2_inst[SUBOP], Rd, sis[RdSel], Rs1, sis[Rs1Sel], Imm2); } else { sprintf(str, "%s R%u%s, R%u%s", f2_inst[SUBOP], Rd, sis[RdSel], Rs2, sis[Rs2Sel]); } break; case 5: // HALT sprintf(str, "%s", f2_inst[SUBOP]); break; case 15: // SLP Imm = (inst & 0x00800000) >> 23; sprintf(str, "%s %u", f2_inst[SUBOP], Imm); break; default: sprintf(str, "UNKNOWN-F2"); break; } break; case 2: // Format 4a & 4b - Quick Arithmetic Test and Branch case 3: Test = (inst & 0x38000000) >> 27; IO = (inst & 0x01000000) >> 24; Rs2Sel = (inst & 0x00E00000) >> 21; Rs2 = (inst & 0x001F0000) >> 16; Rs1Sel = (inst & 0x0000E000) >> 13; Rs1 = (inst & 0x00001F00) >> 8; Imm = (inst & 0x00FF0000) >> 16; BrOff = ((inst & 0x06000000) >> 17) | (inst & 0x000000FF); if (BrOff & 0x0200) BrOff |= 0xFC00; if (IO) { if (Test == 7) { sprintf(str, "QB%s %d", f5_inst[Test], BrOff); } else { sprintf(str, "QB%s %d, R%u%s, %u", f4_inst[Test], BrOff, Rs1, sis[Rs1Sel], Imm); } } else { if (Test == 7) { sprintf(str, "QB%s %d", f5_inst[Test], BrOff); } else { sprintf(str, "QB%s %d, R%u%s, R%u%s", f4_inst[Test], BrOff, Rs1, sis[Rs1Sel], Rs2, sis[Rs2Sel]); } } break; case 6: // Format 5 - Quick bit test and banch instructions Test = (inst & 0x18000000) >> 27; IO = (inst & 0x01000000) >> 24; Rs2Sel = (inst & 0x00E00000) >> 21; Rs2 = (inst & 0x001F0000) >> 16; Rs1Sel = (inst & 0x0000E000) >> 13; Rs1 = (inst & 0x00001F00) >> 8; Imm = (inst & 0x001F0000) >> 16; BrOff = ((inst & 0x06000000) >> 17) | (inst & 0x000000FF); if (BrOff & 0x0200) BrOff |= 0xFC00; if (IO) { sprintf(str, "QB%s %d, R%u%s, %u", f5_inst[Test], BrOff, Rs1, sis[Rs1Sel], Imm); } else { sprintf(str, "QB%s %d, R%u%s, R%u%s", f5_inst[Test], BrOff, Rs1, sis[Rs1Sel], Rs2, sis[Rs2Sel]); } break; case 4: case 7: // Format 6 - LBBO/SBBO/LBCO/SBCO instructions LoadStore = (inst & 0x10000000) >> 28; BurstLen = ((inst & 0x0E000000) >> 21) | ((inst & 0x0000E000) >> 12) | ((inst & 0x00000080) >> 7); IO = (inst & 0x01000000) >> 24; RxByteAddr = (inst & 0x00000060) >> 5; Rx = (inst & 0x0000001F); RoSel = (inst & 0x00E00000) >> 21; Ro = (inst & 0x001F0000) >> 16; Rb = (inst & 0x00001F00) >> 8; Imm = (inst & 0x00FF0000) >> 16; GetBurstLen(tempstr, BurstLen); if (OP == 7) { if (IO) { sprintf(str, "%s R%u%s, R%u, %u, %s", f6_7_inst[LoadStore], Rx, bytenum[RxByteAddr], Rb, Imm, tempstr); } else { sprintf(str, "%s R%u%s, R%u, R%u%s, %s", f6_7_inst[LoadStore], Rx, bytenum[RxByteAddr], Rb, Ro, sis[RoSel], tempstr); } } else { // OP==4 if (IO) { sprintf(str, "%s R%u%s, C%u, %u, %s", f6_4_inst[LoadStore], Rx, bytenum[RxByteAddr], Rb, Imm, tempstr); } else { sprintf(str, "%s R%u%s, C%u, R%u%s, %s", f6_4_inst[LoadStore], Rx, bytenum[RxByteAddr], Rb, Ro, sis[RoSel], tempstr); } } break; default: sprintf(str, "UNKNOWN"); break; } }