OpenCores
URL https://opencores.org/ocsvn/lxp32/lxp32/trunk

Subversion Repositories lxp32

[/] [lxp32/] [trunk/] [tools/] [src/] [lxp32dump/] [disassembler.cpp] - Blame information for rev 6

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ring0_mipt
/*
2
 * Copyright (c) 2016 by Alex I. Kuznetsov.
3
 *
4
 * Part of the LXP32 CPU IP core.
5
 *
6
 * This module implements members of the Disassembler class.
7
 */
8
 
9
#include "disassembler.h"
10
 
11
#include <sstream>
12
#include <stdexcept>
13
 
14
/*
15
 * Disassembler::Operand class members
16
 */
17
 
18
Disassembler::Operand::Operand(Type t,int value):
19
        _type(t),_value(value) {}
20
 
21
Disassembler::Operand::Type Disassembler::Operand::type() const {
22
        return _type;
23
}
24
 
25
int Disassembler::Operand::value() const {
26
        return _value;
27
}
28
 
29
/*
30
 * Disassembler class members
31
 */
32
 
33
Disassembler::Disassembler(std::istream &is,std::ostream &os):
34 6 ring0_mipt
        _is(is),_os(os),_fmt(Bin),_preferAliases(true),_lineNumber(0),_pos(0) {}
35 2 ring0_mipt
 
36
void Disassembler::setFormat(Format fmt) {
37
        _fmt=fmt;
38
}
39
 
40
void Disassembler::setBase(Word base) {
41
        _pos=base;
42
}
43
 
44 6 ring0_mipt
void Disassembler::setPreferAliases(bool b) {
45
        _preferAliases=b;
46
}
47
 
48 2 ring0_mipt
void Disassembler::dump() {
49
        Word word;
50
 
51
        for(;;) {
52
                auto offset=_pos;
53
                if(!getWord(word)) break;
54
                auto opcode=word>>26;
55
 
56
                std::string instruction;
57
 
58
                bool lcValid=false;
59
                Word lcOperand;
60
 
61
                switch(opcode) {
62
                case 0x10:
63
                        instruction=decodeAdd(word);
64
                        break;
65
                case 0x18:
66
                        instruction=decodeAnd(word);
67
                        break;
68
                case 0x21:
69
                        instruction=decodeCall(word);
70
                        break;
71
                case 0x15:
72
                        instruction=decodeDivs(word);
73
                        break;
74
                case 0x14:
75
                        instruction=decodeDivu(word);
76
                        break;
77
                case 0x02:
78
                        instruction=decodeHlt(word);
79
                        break;
80
                case 0x20:
81
                        instruction=decodeJmp(word);
82
                        break;
83
                case 0x01:
84
                        instruction=decodeLc(word,lcValid,lcOperand);
85
                        break;
86
                case 0x0B:
87
                        instruction=decodeLsb(word);
88
                        break;
89
                case 0x0A:
90
                        instruction=decodeLub(word);
91
                        break;
92
                case 0x08:
93
                        instruction=decodeLw(word);
94
                        break;
95
                case 0x17:
96
                        instruction=decodeMods(word);
97
                        break;
98
                case 0x16:
99
                        instruction=decodeModu(word);
100
                        break;
101
                case 0x12:
102
                        instruction=decodeMul(word);
103
                        break;
104
                case 0x00:
105
                        instruction=decodeNop(word);
106
                        break;
107
                case 0x19:
108
                        instruction=decodeOr(word);
109
                        break;
110
                case 0x0E:
111
                        instruction=decodeSb(word);
112
                        break;
113
                case 0x1C:
114
                        instruction=decodeSl(word);
115
                        break;
116
                case 0x1F:
117
                        instruction=decodeSrs(word);
118
                        break;
119
                case 0x1E:
120
                        instruction=decodeSru(word);
121
                        break;
122
                case 0x11:
123
                        instruction=decodeSub(word);
124
                        break;
125
                case 0x0C:
126
                        instruction=decodeSw(word);
127
                        break;
128
                case 0x1A:
129
                        instruction=decodeXor(word);
130
                        break;
131
                default:
132
                        if((opcode>>4)==0x03) instruction=decodeCjmpxx(word);
133 6 ring0_mipt
                        else if((opcode>>3)==0x05) instruction=decodeLcs(word);
134 2 ring0_mipt
                        else instruction=decodeWord(word);
135
                }
136
 
137
                auto size=instruction.size();
138
                std::size_t padding=0;
139
                if(size<32) padding=32-size;
140
 
141
                _os<<'\t'<<instruction<<std::string(padding,' ')<<"// ";
142
                _os<<hex(offset)<<": "<<hex(word);
143
                if(lcValid) _os<<' '<<hex(lcOperand);
144
                _os<<std::endl;
145
        }
146
}
147
 
148
bool Disassembler::getWord(Word &w) {
149
        if(_fmt==Bin) {
150
                char buf[sizeof(Word)] {}; // zero-initialize
151
                _is.read(buf,sizeof(Word));
152
 
153
                auto n=static_cast<std::size_t>(_is.gcount());
154
                if(n==0) return false;
155
                if(n<sizeof(Word)) std::cerr<<"Warning: last word is truncated"<<std::endl;
156
 
157
                w=(static_cast<unsigned char>(buf[3])<<24)|(static_cast<unsigned char>(buf[2])<<16)|
158
                        (static_cast<unsigned char>(buf[1])<<8)|static_cast<unsigned char>(buf[0]);
159
        }
160
        else {
161
                try {
162
                        std::string line;
163
                        if(!std::getline(_is,line)) return false;
164
                        _lineNumber++;
165
 
166
                        if(_fmt==Textio) w=std::stoul(line,nullptr,2);
167
                        else if(_fmt==Dec) w=std::stoul(line,nullptr,10);
168
                        else if(_fmt==Hex) w=std::stoul(line,nullptr,16);
169
                        else return false;
170
                }
171
                catch(std::exception &) {
172
                        throw std::runtime_error("Bad literal at line "+std::to_string(_lineNumber));
173
                }
174
        }
175
        _pos+=sizeof(Word);
176
        return true;
177
}
178
 
179 6 ring0_mipt
std::string Disassembler::str(const Operand &op) {
180
        if(op.type()==Operand::Register) {
181
                if(!_preferAliases) return "r"+std::to_string(op.value());
182
                else if(op.value()>=240&&op.value()<=247) return "iv"+std::to_string(op.value()-240);
183
                else if(op.value()==252) return "cr";
184
                else if(op.value()==253) return "irp";
185
                else if(op.value()==254) return "rp";
186
                else if(op.value()==255) return "sp";
187
                else return "r"+std::to_string(op.value());
188
        }
189
        else return std::to_string(op.value());
190
}
191
 
192 2 ring0_mipt
Disassembler::Operand Disassembler::decodeRd1Operand(Word w) {
193
        int value=(w>>8)&0xFF;
194
        if(w&0x02000000) return Operand(Operand::Register,value);
195
        else {
196
                if(value>127) value-=256;
197
                return Operand(Operand::Direct,value);
198
        }
199
}
200
 
201
Disassembler::Operand Disassembler::decodeRd2Operand(Word w) {
202
        int value=w&0xFF;
203
        if(w&0x01000000) return Operand(Operand::Register,value);
204
        else {
205
                if(value>127) value-=256;
206
                return Operand(Operand::Direct,value);
207
        }
208
}
209
 
210
Disassembler::Operand Disassembler::decodeDstOperand(Word w) {
211
        int value=(w>>16)&0xFF;
212
        return Operand(Operand::Register,value);
213
}
214
 
215
std::string Disassembler::decodeSimpleInstruction(const std::string &op,Word w) {
216
        std::ostringstream oss;
217
        auto dst=decodeDstOperand(w);
218
        auto rd1=decodeRd1Operand(w);
219
        auto rd2=decodeRd2Operand(w);
220 6 ring0_mipt
        oss<<op<<' '<<str(dst)<<", "<<str(rd1)<<", "<<str(rd2);
221 2 ring0_mipt
        return oss.str();
222
}
223
 
224
std::string Disassembler::decodeAdd(Word w) {
225
        std::ostringstream oss;
226
 
227
        auto dst=decodeDstOperand(w);
228
        auto rd1=decodeRd1Operand(w);
229
        auto rd2=decodeRd2Operand(w);
230
 
231 6 ring0_mipt
        if(rd2.type()==Operand::Direct&&rd2.value()==0&&_preferAliases)
232
                oss<<"mov "<<str(dst)<<", "<<str(rd1);
233 2 ring0_mipt
        else
234 6 ring0_mipt
                oss<<"add "<<str(dst)<<", "<<str(rd1)<<", "<<str(rd2);
235 2 ring0_mipt
 
236
        return oss.str();
237
}
238
 
239
std::string Disassembler::decodeAnd(Word w) {
240
        return decodeSimpleInstruction("and",w);
241
}
242
 
243
std::string Disassembler::decodeCall(Word w) {
244
        auto dst=decodeDstOperand(w);
245
        auto rd1=decodeRd1Operand(w);
246
        auto rd2=decodeRd2Operand(w);
247
 
248
        if(dst.value()!=0xFE) return decodeWord(w);
249
        if(rd1.type()!=Operand::Register) return decodeWord(w);
250
        if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
251
 
252 6 ring0_mipt
        return "call "+str(rd1);
253 2 ring0_mipt
}
254
 
255
std::string Disassembler::decodeCjmpxx(Word w) {
256
        auto jumpType=(w>>26)&0x0F;
257
        std::string op;
258
 
259
        switch(jumpType) {
260
        case 0x8:
261
                op="cjmpe";
262
                break;
263
        case 0x4:
264
                op="cjmpne";
265
                break;
266
        case 0x2:
267
                op="cjmpug";
268
                break;
269
        case 0xA:
270
                op="cjmpuge";
271
                break;
272
        case 0x1:
273
                op="cjmpsg";
274
                break;
275
        case 0x9:
276
                op="cjmpsge";
277
                break;
278
        default:
279
                return decodeWord(w);
280
        }
281
 
282
        return decodeSimpleInstruction(op,w);
283
}
284
 
285
std::string Disassembler::decodeDivs(Word w) {
286
        auto rd2=decodeRd2Operand(w);
287
        if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w);
288
        return decodeSimpleInstruction("divs",w);
289
}
290
 
291
std::string Disassembler::decodeDivu(Word w) {
292
        auto rd2=decodeRd2Operand(w);
293
        if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w);
294
        return decodeSimpleInstruction("divu",w);
295
}
296
 
297
std::string Disassembler::decodeHlt(Word w) {
298
        if(w!=0x08000000) return decodeWord(w);
299
        return "hlt";
300
}
301
 
302
std::string Disassembler::decodeJmp(Word w) {
303
        auto dst=decodeDstOperand(w);
304
        auto rd1=decodeRd1Operand(w);
305
        auto rd2=decodeRd2Operand(w);
306
 
307
        if(dst.value()!=0) return decodeWord(w);
308
        if(rd1.type()!=Operand::Register) return decodeWord(w);
309
        if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
310
 
311 6 ring0_mipt
        if(rd1.value()==253&&_preferAliases) return "iret";
312
        if(rd1.value()==254&&_preferAliases) return "ret";
313
        return "jmp "+str(rd1);
314 2 ring0_mipt
}
315
 
316
std::string Disassembler::decodeLc(Word w,bool &valid,Word &operand) {
317
        auto dst=decodeDstOperand(w);
318
        auto rd1=decodeRd1Operand(w);
319
        auto rd2=decodeRd2Operand(w);
320
 
321
        valid=false;
322
 
323
        if(rd1.type()!=Operand::Direct||rd1.value()!=0) return decodeWord(w);
324
        if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
325
 
326
        bool b=getWord(operand);
327
        if(!b) return decodeWord(w);
328
 
329
        valid=true;
330 6 ring0_mipt
        return "lc "+str(dst)+", 0x"+hex(operand);
331 2 ring0_mipt
}
332
 
333 6 ring0_mipt
std::string Disassembler::decodeLcs(Word w) {
334
        auto dst=decodeDstOperand(w);
335
        auto operand=w&0xFFFF;
336
        operand|=(w>>8)&0x001F0000;
337
        if(operand&0x00100000) operand|=0xFFE00000;
338
        return "lcs "+str(dst)+", 0x"+hex(operand);
339
}
340
 
341 2 ring0_mipt
std::string Disassembler::decodeLsb(Word w) {
342
        std::ostringstream oss;
343
 
344
        auto dst=decodeDstOperand(w);
345
        auto rd1=decodeRd1Operand(w);
346
        auto rd2=decodeRd2Operand(w);
347
 
348
        if(rd1.type()!=Operand::Register) return decodeWord(w);
349
        if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
350
 
351 6 ring0_mipt
        return "lsb "+str(dst)+", "+str(rd1);
352 2 ring0_mipt
}
353
 
354
std::string Disassembler::decodeLub(Word w) {
355
        std::ostringstream oss;
356
 
357
        auto dst=decodeDstOperand(w);
358
        auto rd1=decodeRd1Operand(w);
359
        auto rd2=decodeRd2Operand(w);
360
 
361
        if(rd1.type()!=Operand::Register) return decodeWord(w);
362
        if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
363
 
364 6 ring0_mipt
        return "lub "+str(dst)+", "+str(rd1);
365 2 ring0_mipt
}
366
 
367
std::string Disassembler::decodeLw(Word w) {
368
        std::ostringstream oss;
369
 
370
        auto dst=decodeDstOperand(w);
371
        auto rd1=decodeRd1Operand(w);
372
        auto rd2=decodeRd2Operand(w);
373
 
374
        if(rd1.type()!=Operand::Register) return decodeWord(w);
375
        if(rd2.type()!=Operand::Direct||rd2.value()!=0) return decodeWord(w);
376
 
377 6 ring0_mipt
        return "lw "+str(dst)+", "+str(rd1);
378 2 ring0_mipt
}
379
 
380
std::string Disassembler::decodeMods(Word w) {
381
        auto rd2=decodeRd2Operand(w);
382
        if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w);
383
        return decodeSimpleInstruction("mods",w);
384
}
385
 
386
std::string Disassembler::decodeModu(Word w) {
387
        auto rd2=decodeRd2Operand(w);
388
        if(rd2.type()==Operand::Direct&&rd2.value()==0) return decodeWord(w);
389
        return decodeSimpleInstruction("modu",w);
390
}
391
 
392
std::string Disassembler::decodeMul(Word w) {
393
        return decodeSimpleInstruction("mul",w);
394
}
395
 
396
std::string Disassembler::decodeNop(Word w) {
397
        if(w!=0) return decodeWord(w);
398
        return "nop";
399
}
400
 
401
std::string Disassembler::decodeOr(Word w) {
402
        return decodeSimpleInstruction("or",w);
403
}
404
 
405
std::string Disassembler::decodeSb(Word w) {
406
        std::ostringstream oss;
407
 
408
        auto dst=decodeDstOperand(w);
409
        auto rd1=decodeRd1Operand(w);
410
        auto rd2=decodeRd2Operand(w);
411
 
412
        if(dst.value()!=0) return decodeWord(w);
413
        if(rd1.type()!=Operand::Register) return decodeWord(w);
414
 
415 6 ring0_mipt
        return "sb "+str(rd1)+", "+str(rd2);
416 2 ring0_mipt
}
417
 
418
std::string Disassembler::decodeSl(Word w) {
419
        auto rd2=decodeRd2Operand(w);
420
        if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w);
421
        return decodeSimpleInstruction("sl",w);
422
}
423
 
424
std::string Disassembler::decodeSrs(Word w) {
425
        auto rd2=decodeRd2Operand(w);
426
        if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w);
427
        return decodeSimpleInstruction("srs",w);
428
}
429
 
430
std::string Disassembler::decodeSru(Word w) {
431
        auto rd2=decodeRd2Operand(w);
432
        if(rd2.type()==Operand::Direct&&(rd2.value()<0||rd2.value()>31)) return decodeWord(w);
433
        return decodeSimpleInstruction("sru",w);
434
}
435
 
436
std::string Disassembler::decodeSub(Word w) {
437 6 ring0_mipt
        std::ostringstream oss;
438
 
439
        auto dst=decodeDstOperand(w);
440
        auto rd1=decodeRd1Operand(w);
441
        auto rd2=decodeRd2Operand(w);
442
 
443
        if(rd1.type()==Operand::Direct&&rd1.value()==0&&_preferAliases)
444
                oss<<"neg "<<str(dst)<<", "<<str(rd2);
445
        else
446
                oss<<"sub "<<str(dst)<<", "<<str(rd1)<<", "<<str(rd2);
447
 
448
        return oss.str();
449 2 ring0_mipt
}
450
 
451
std::string Disassembler::decodeSw(Word w) {
452
        std::ostringstream oss;
453
 
454
        auto dst=decodeDstOperand(w);
455
        auto rd1=decodeRd1Operand(w);
456
        auto rd2=decodeRd2Operand(w);
457
 
458
        if(dst.value()!=0) return decodeWord(w);
459
        if(rd1.type()!=Operand::Register) return decodeWord(w);
460
 
461 6 ring0_mipt
        return "sw "+str(rd1)+", "+str(rd2);
462 2 ring0_mipt
}
463
 
464
std::string Disassembler::decodeXor(Word w) {
465
        std::ostringstream oss;
466
 
467
        auto dst=decodeDstOperand(w);
468
        auto rd1=decodeRd1Operand(w);
469
        auto rd2=decodeRd2Operand(w);
470
 
471 6 ring0_mipt
        if(rd2.type()==Operand::Direct&&rd2.value()==-1&&_preferAliases)
472
                oss<<"not "<<str(dst)<<", "<<str(rd1);
473 2 ring0_mipt
        else
474 6 ring0_mipt
                oss<<"xor "<<str(dst)<<", "<<str(rd1)<<", "<<str(rd2);
475 2 ring0_mipt
 
476
        return oss.str();
477
}
478
 
479
std::string Disassembler::decodeWord(Word w) {
480
        return ".word 0x"+hex(w);
481
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.