]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blob - utils/mb-dasm.cpp
Add scripts and programs for firmware
[fpga/lx-cpu1/tumbl.git] / utils / mb-dasm.cpp
1 /*******************************************************************************
2 *
3 *   File:         dasm.c
4 *   Description:  Disassembler for TUMBL binary code.
5 *   Syntax:       mb-dasm [binFilename]
6 *                 if no binFilename specified, defaults to imem.bin in local
7 *                 directory.
8 *
9 *   Author:       Huib Lincklaen Arriens
10 *   Date:         August 2010
11 *
12 *   Note:         No checks, e.g. on inputfile being a multiple of 4 bytes
13 *
14 ********************************************************************************/
15
16
17 #include <stdio.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #include <iostream>
21 #include <fstream>
22 #include <iomanip>
23
24
25 // TUMBL Opcodes to be handled explicitely
26 #define OP_CMP        0x05
27
28 #define OP_MUL        0x10
29 #define OP_BS         0x11
30 #define OP_IDIV       0x12
31 #define OP_FSL        0x13
32 #define OP_FP         0x16
33 #define OP_MULI       0x18
34 #define OP_BSI        0x19
35 #define OP_FSLD       0x1B
36
37 #define OP_SEXT       0x24
38 #define OP_SPR        0x25
39 #define OP_BR         0x26 // for br brd brld bra brad brald brk
40 #define OP_BRC        0x27 // for beq bne blt ble bgt bge
41 #define OP_IMM        0x2C
42 #define OP_RTBD       0x2D
43 #define OP_BRI        0x2E // for bri brid brlid brai braid
44 #define OP_BRCI       0x2F // for beqi bnei blti blei bgti bgei
45
46
47 using namespace std;
48
49 static const int MAXMEM = 65536;
50
51 static const char   *opc_Tbl[] =
52     { "add     ", "rsub    ", "addc    ", "rsubc   ", "addk    ", "x_cmp   ", "addkc   ", "rsubkc  ",
53       "addi    ", "rsubi   ", "addic   ", "rsubic  ", "addik   ", "rsubik  ", "addikc  ", "rsubikc ",
54       "mul     ", "bs      ", "idiv    ", "FSLd    ", "--      ", "--      ", "FPI     ", "--      ",
55       "muli    ", "bsi     ", "--      ", "FSL     ", "--      ", "--      ", "--      ", "--      ",
56       "or      ", "and     ", "xor     ", "andn    ", "sext    ", "SPR     ", "br      ", "brc     ",
57       "ori     ", "andi    ", "xori    ", "andni   ", "imm     ", "rtbd    ", "bri     ", "brci    ",
58       "lbu     ", "lhu     ", "lw      ", "--      ", "sb      ", "sh      ", "sw      ", "--      ",
59       "lbui    ", "lhui    ", "lwi     ", "--      ", "sbi     ", "shi     ", "swi     ", "--      " };
60
61 static const char   *brc_Tbl[] =
62     { "beq", "bne", "blt", "ble", "bgt", "bge" };
63
64
65 char          s1str[80] = "";
66 char          s2str[25] = "";
67 const char    spc_str[17] = "                ";
68 unsigned int  imem[MAXMEM];
69 unsigned int  mem_size;
70
71
72 void  print_Usage (char *cmd_name)
73 {
74     fprintf( stderr, "Usage: %s [binFilename]\n", cmd_name);
75     fprintf( stderr, "where the optional binFilename references a binary (Little Endian) code file.\n");
76     fprintf( stderr, "If not specified binFilename tries to read imem.bin in the local directory.\n");
77 }
78
79 void  read_bin (char *binFilename, unsigned int *imem, unsigned int *mem_size)
80 {
81     ifstream  binFile( binFilename, ios::in | ios::binary );
82     // the next type should be "char" because the iostream needs it like that ....
83     char      bin_bytes[MAXMEM];  // 4 Bytes in a Word
84     int       isize;
85     int       i, j;
86
87     cout << "Reading " << binFilename << " ..." << endl << endl;
88     if ( binFile.fail() ) {cout << "Cannot open " << binFilename << " ..." << endl; exit (1);}
89     // get length of file:
90     binFile.seekg (0, ios::end);
91     isize = binFile.tellg();
92     if (isize > sizeof(bin_bytes)) {
93         cout << binFilename << " larger than " << MAXMEM/1024 << " kBytes ("
94                                                 << MAXMEM/4096 << " kWords) ..." << endl << endl;
95         exit (1);
96     }
97     *mem_size = isize/4;
98     binFile.seekg (0, ios::beg);
99     // read data as a block:
100     binFile.read (bin_bytes, isize);
101     if ( binFile.fail() ) {cout << "Read error ..." << endl; exit (2);}
102     binFile.close();
103     for (i = 0, j = 0; i < isize; i += 4, j++ ) {
104         // remember iostream only read signed chars ...
105         imem[j] = ((unsigned char)bin_bytes[i] << 24) +
106                       ((unsigned char)bin_bytes[i+1] << 16) +
107                           ((unsigned char)bin_bytes[i+2] << 8) +
108                               (unsigned char)bin_bytes[i+3];
109     }
110 }
111
112 void  disasm (unsigned int pci)
113 {
114     unsigned int  pcb, ins;
115     unsigned int  opc;
116     unsigned int  rd, ra, rb, imm;
117     int           s_imm;
118     unsigned int  s1len;
119     bool          a, l, d, b;
120     bool          xpand, valid_code;
121
122     pcb = 4*pci;
123     ins = imem[pci];
124     // decode the current instruction
125     opc = (ins >> 26) & 0x3F;
126     ra  = (ins >> 16) & 0x1F;
127     rd  = (ins >> 21) & 0x1F;
128     if (!(opc & 0x08)) {
129         rb  = (ins >> 11) & 0x1F;
130         imm = ins & 0x07FF;           // not really imm!!
131         sprintf (s2str, "r%d, r%d, r%d", rd, ra, rb);
132     }
133     else {
134         imm   = ins & 0xFFFF;
135         // 32 bit extension of a 16 bit or an 8 bit number
136         s_imm = imm & 0x8000 ? 0xffff0000 | imm : imm;
137         sprintf (s2str, "r%d, r%d, 0x%0x", rd, ra, imm);
138     }
139
140     if (ins == 0)
141         sprintf (s1str, "nop");
142     else {
143         xpand = 1;
144         switch (opc)
145         {
146             case OP_BR:                 // BR / BRA / BRD / BRAD / BRLD / BRALD
147                 if ((ra & 0x1F) == 0x0C)  // BRK
148                 {
149                     printf ("BRK");    //// ??????
150                 }
151                 l = ra & 0x04;
152                 a = ra & 0x08;
153                 d = ra & 0x10;
154                 b = (ra & 0x1F) == 0x0C;
155                 if (b) sprintf (s1str, "brk     r%d, r%d", rd, rb);
156                 else
157                     if (!l) {
158                         s1len = sprintf (s1str, "br%s%s", a ? "a" : "", d ? "d" : "");
159                         sprintf (s1str, "%s  r%d", strncat(s1str,"    ",6-s1len), rb);
160                     } else {
161                         s1len = sprintf (s1str, "br%sl%s", a ? "a" : "", d ? "d" : "");
162                         sprintf (s1str, "%s  r%d, r%d", strncat(s1str,"    ",6-s1len), rd, rb);
163                     }
164                 break;
165             case OP_BRC:
166                 if ((rd & 0xf) <= 0x5)
167                     sprintf (s1str, "%s%s    r%d, 0x%x", brc_Tbl[rd & 0xf], rd & 0x10 ? "d" : " ", ra, rb);
168                 else
169                     sprintf (s1str, "brc (opcode 0x27) has some errors, please check\n");
170                 break;
171             case OP_BRI:                // BRI / BRAI / BRID / BRAID / BRLID / BRAILD
172                 if ((ra & 0x1F) == 0x0C)  // BRK
173                     printf ("BRK");    //// ??????
174                 l = ra & 0x04;
175                 a = ra & 0x08;
176                 d = ra & 0x10;
177                 b = (ra & 0x1F) == 0x0C;
178                 if (b) sprintf (s1str, "brki    r%d, 0x%x", rd, imm);
179                 else {
180                     if (!l) {
181                         s1len = sprintf (s1str, "bri%s%s", a ? "a" : "", d ? "d" : "" );
182                         s1len = sprintf (s1str, "%s  %d", strncat(s1str,"    ",6-s1len), s_imm);
183                     } else {
184                         s1len = sprintf (s1str, "bri%sl%s", a ? "a" : "", d ? "d" : "");
185                         s1len = sprintf (s1str, "%s  r%d, %d", strncat(s1str,"    ",6-s1len), rd, s_imm);
186                     }
187                     if (a)
188                         sprintf (s1str, "%s// 0x%x", strncat(s1str,spc_str,25-s1len), imm);
189                     else
190                         sprintf (s1str, "%s// 0x%x", strncat(s1str,spc_str,25-s1len), pcb + s_imm);
191                 }
192                 break;
193             case OP_BRCI:
194                 if ((rd & 0xf) <= 0x5) {
195                     s1len = sprintf (s1str, "%si%s   r%d, %d", brc_Tbl[rd & 0xf], rd & 0x10 ? "d" : " ", ra, s_imm);
196                     sprintf (s1str, "%s// 0x%x", strncat(s1str,spc_str,25-s1len), pcb + s_imm);
197                 } else
198                     sprintf (s1str, "brci (opcode 0x2f) has some errors, please check\n");
199                 break;
200             case OP_BSI:
201                 sprintf (s2str, "r%d, r%d, 0x%0x", rd, ra, imm & 0x1F);
202                 //  !! no break
203             case OP_BS:
204                 if (imm & 0x400)    // left shift
205                     s1len = sprintf (s1str, "bsll%s   %s", opc & 0x08 ? "i" : " ", s2str);
206                 else
207                     s1len = sprintf (s1str, "bsr%s%s   %s",
208                                   imm & 0x200 ? "a" : "l", opc & 0x08 ? "i" : " ", s2str);
209                 break;
210             case OP_CMP:            // or RSUBK
211                 if (imm & 1)
212                     sprintf (s1str, "cmp%s    %s", imm & 2 ? "u" : " ", s2str);
213                 else
214                     sprintf (s1str, "rsubk   %s", s2str);
215                 break;
216             case OP_FP:
217                 sprintf (s1str, "Floating Point Instruction   NOT IMPLEMENTED IN TUMBL");
218                 break;
219             case OP_FSL:
220             case OP_FSLD:
221                 sprintf (s1str, "FSL Instruction              NOT IMPLEMENTED IN TUMBL");
222                 break;
223             case OP_IDIV:
224                 s1len = sprintf (s1str, "idiv%s   %s", imm & 0x02 ? "u" : " ", s2str);
225                 sprintf (s1str, "%s    NOT IMPLEMENTED IN TUMBL", strncat(s1str,spc_str,25-s1len));
226                 break;
227             case OP_IMM:
228                 sprintf (s1str, "imm     0x%04x           // %d", imm, s_imm);
229                 break;
230             case OP_MUL:
231             case OP_MULI:
232                 s1len = sprintf (s1str, "%s%s", opc_Tbl[opc], s2str);
233                 break;
234             case OP_RTBD:
235                 valid_code = 1;
236                 switch(rd) {
237                     case 0x12:  sprintf (s2str, "rtbd"); break;     // RTBD
238                     case 0x11:  sprintf (s2str, "rtid"); break;     // RTID
239                     case 0x14:  sprintf (s2str, "rted"); break;     // RTED
240                     case 0x10:  sprintf (s2str, "rtsd"); break;     // RTSD
241                     default:
242                         sprintf (s1str, "Illegal subopcode in OP_RTBD");
243                         valid_code = 0;
244                 }
245                 if (valid_code)
246                     sprintf (s1str, "%s    r%d, 0x%x", s2str, ra, imm);
247                 break;
248             case OP_SEXT:
249                 valid_code = 1;
250                 switch (imm) {
251                     case 0x61:  sprintf (s2str, "sext16"); break;   // SEXT16
252                     case 0x60:  sprintf (s2str, "sext8 "); break;   // SEXT8
253                     case 0x01:  sprintf (s2str, "sra   "); break;   // SRA
254                     case 0x21:  sprintf (s2str, "src   "); break;   // SRC
255                     case 0x41:  sprintf (s2str, "srl   "); break;   // SRL
256                     default :
257                         sprintf (s1str, "OP_SEXT has some errors, please check" );
258                         valid_code = 0;
259                     }
260                 if (valid_code)
261                     sprintf (s1str, "%s  r%d, r%d", s2str, rd, ra);
262                 break;
263             case OP_SPR:
264                 sprintf (s1str, "SP-Reg Instruction           NOT IMPLEMENTED IN TUMBL");
265                 break;
266             default:
267                 xpand = 0;
268         }   // switch (opc)
269
270         if (!xpand) {
271             if (strncmp(opc_Tbl[opc],"--",2))
272                 sprintf (s1str, "%s%s", opc_Tbl[opc], s2str);
273             else
274                 sprintf (s1str, "Unknown instruction / possibly data ?");
275         }
276     }
277     printf ("%6x:  %08x    %s\n", pcb, ins, s1str);
278 }
279
280
281 int main(int argc, char *argv[])
282 {
283     char binFilename[132];
284
285     // note: strncmp == 0 if the parts of the strings are equal
286     if ((argc > 2) || ((argc == 2) && !strncmp(argv[1],"-",1))) {
287         print_Usage( argv[0]);
288         return (1);
289     }
290
291     if (argc == 2)
292         sprintf( binFilename, argv[1]);
293     else
294         sprintf( binFilename, "imem.bin");
295     read_bin (binFilename, imem, &mem_size);
296     for (int pci = 0; pci < mem_size; pci++)
297         disasm (pci);
298 }
299