239 lines
7.1 KiB
C
239 lines
7.1 KiB
C
/*
|
|
*
|
|
* PRU Debug Program - disassembly routines
|
|
* (c) Copyright 2011 by Arctica Technologies
|
|
* Written by Steven Anderson
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <errno.h>
|
|
#include <termios.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/select.h>
|
|
|
|
#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 short Imm;
|
|
unsigned char OP, ALUOP, Rs2Sel, Rs2, Rs1Sel, Rs1, RdSel, Rd, IO, Imm2, SUBOP, Test;
|
|
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 (Test == 7) {
|
|
sprintf(str, "QBA %d", BrOff);
|
|
} else {
|
|
if (IO) {
|
|
sprintf(str, "QB%s %d, R%u%s, %u", f4_inst[Test], BrOff, Rs1, sis[Rs1Sel], Imm);
|
|
} 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;
|
|
}
|
|
}
|
|
|