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

Subversion Repositories forwardcom

[/] [forwardcom/] [bintools/] [main.cpp] - Blame information for rev 144

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

Line No. Rev Author Line
1 63 Agner
/****************************  main.cpp   *******************************
2
* Author:        Agner Fog
3
* Date created:  2017-04-17
4
* Last modified: 2020-11-25
5
* Version:       1.11
6
* Project:       Binary tools for ForwardCom instruction set
7
* Description:   This includes assembler, disassembler, linker, library
8
*                manager, and emulator in one program
9
*
10
* Instructions:
11
* Run with option -h for help
12
*
13
* For detailed instructions, see forwardcom.pdf
14
*
15
* (c) Copyright 2017-2020 GNU General Public License version 3
16
* http://www.gnu.org/licenses
17
*****************************************************************************/
18
 
19
#include "stdafx.h"
20
 
21
// Check if running on little endian system
22
static void CheckEndianness();
23
 
24
// Buffer for symbol names is made global in order to make it accessible to operators:
25
// bool operator < (ElfFWC_Sym2 const &, ElfFWC_Sym2 const &)
26
// bool operator < (SStringEntry const & a, SStringEntry const & b)
27
// bool operator < (SSymbolEntry const & a, SSymbolEntry const & b)
28
CTextFileBuffer symbolNameBuffer;      // Buffer for symbol names during assembly, linking, and library operations
29
 
30
 
31
                                       // Main. Program starts here
32
int main(int argc, char * argv[]) {
33
    CheckEndianness();                  // Check that machine is little-endian
34
 
35
#ifdef  _DEBUG
36
   // For debugging only: Read command line from file resp.txt
37
    if (argc == 1) {
38
        char commandline[] = "@resp.txt";
39
        char * dummyarg[] = { argv[0],  commandline};
40
        argc = 2; argv = dummyarg;
41
    }
42
#endif
43
 
44
    cmd.readCommandLine(argc, argv);             // Read command line parameters   
45
    if (cmd.job == CMDL_JOB_HELP) return 0;      // Help screen has been printed. Do nothing else
46
 
47
    CConverter maincvt;                          // This object takes care of all conversions etc.
48
    maincvt.go();                                // Do everything the command line says
49
 
50
    if (cmd.verbose && cmd.job != CMDL_JOB_EMU)  printf("\n"); // End with newline
51
    if (err.getWorstError()) cmd.mainReturnValue = err.getWorstError(); // Return with error code
52
    return cmd.mainReturnValue;
53
}
54
 
55
 
56
CConverter::CConverter() {
57
    // Constructor
58
}
59
 
60
void CConverter::go() {
61
    // Do whatever the command line parameters say
62
 
63
    switch (cmd.job) {
64
    case CMDL_JOB_DUMP:
65
        // File dump requested
66
        readInputFile();
67
        if (err.number()) return;
68
        switch (fileType) {
69
        case FILETYPE_FWC: case FILETYPE_ELF:
70
            dumpELF();  break;
71
        default:
72
            err.submit(ERR_DUMP_NOT_SUPPORTED, getFileFormatName(fileType));  // Dump of this file type not supported
73
        }
74
        printf("\n");                              // New line
75
        break;
76
 
77
    case CMDL_JOB_ASS:
78
        // assemble
79
        readInputFile();
80
        if (err.number()) return;
81
        assemble();
82
        break;
83
 
84
    case CMDL_JOB_DIS:
85
        // disassemble
86
        readInputFile();
87
        if (err.number()) return;
88
        disassemble();
89
        break;
90
 
91
    case CMDL_JOB_LINK:
92
    case CMDL_JOB_RELINK:
93
        link();          // linker
94
        break;
95
 
96
    case CMDL_JOB_LIB:
97
        readInputFile();
98
        if (err.number()) return;
99
        lib();        // library manager
100
        break;
101
 
102
    case CMDL_JOB_EMU:
103
        emulate();    // emulator
104
        break;
105
 
106
    case 0: return; // no job. command line error
107
 
108
    default:
109
        err.submit(ERR_INTERNAL);
110
    }
111
}
112
 
113
// read input file
114
void CConverter::readInputFile() {
115
    // Ignore nonexisting filename when building library
116
    int IgnoreError = (cmd.fileOptions & CMDL_FILE_IN_IF_EXISTS);
117
    // Read input file
118
    read(cmd.getFilename(cmd.inputFile), IgnoreError);
119
    if (cmd.job == CMDL_JOB_ASS) fileType = FILETYPE_ASM;
120
    else getFileType();                 // Determine file type
121
    if (err.number()) return;           // Return if error
122
    cmd.inputType = fileType;           // Save input file type in cmd for access from other modules
123
    if (cmd.outputType == 0) {
124
        // desired type not specified
125
        cmd.outputType = fileType;
126
    }
127
}
128
 
129
void CConverter::dumpELF() {
130
    // Dump ELF file
131
    // Make object for interpreting 32 bit ELF file
132
    CELF elf;
133
    *this >> elf;                      // Give it my buffer
134
    elf.parseFile();                   // Parse file buffer
135
    if (err.number()) return;          // Return if error
136
    elf.dump(cmd.dumpOptions);         // Dump file
137
    *this << elf;                      // Take back my buffer
138
}
139
 
140
void CConverter::assemble() {
141
    // Aassemble to ELF file
142
    // Make instance of assembler
143
    CAssembler ass;
144
    if (err.number()) return;
145
    *this >> ass;                      // Give it my buffer
146
    ass.go();                          // run
147
}
148
 
149
void CConverter::disassemble() {
150
    // Disassemble ELF file
151
    // Make instance of disassembler
152
    CDisassembler dis;
153
    if (err.number()) return;
154
    *this >> dis;                      // Give it my buffer
155
    dis.parseFile();                   // Parse file buffer
156
    if (err.number()) return;          // Return if error
157
    dis.getComponents1();              // Get components from ELF file
158
    dis.go();                          // Convert
159
}
160
 
161
void CConverter::lib() {
162
    // Library manager
163
    // Make instance of library manager
164
    CLibrary libmanager;
165
    if (err.number()) return;
166
    *this >> libmanager;               // Give it my buffer
167
    libmanager.go();                   // Do the job
168
}
169
 
170
void CConverter::link() {
171
    // Linker
172
    // Make instance of linker
173
    CLinker linker;
174
    linker.go();                   // Do the job
175
}
176
 
177
void CConverter::emulate() {
178
    // Emulator
179
    // Make instance of linker
180
    CEmulator emulator;
181
    emulator.go();                   // Do the job
182
}
183
 
184
// Convert half precision floating point number to single precision
185
// Optional support for subnormals
186
// NAN payload is right-justified for ForwardCom
187
float half2float(uint32_t half, bool supportSubnormal) {
188
    union {
189
        uint32_t hhh;
190
        float fff;
191
        struct {
192
            uint32_t mant: 23;
193
            uint32_t expo:  8;
194
            uint32_t sign:  1;
195
        };
196
    } u;
197
 
198
    u.hhh  = (half & 0x7fff) << 13;              // Exponent and mantissa
199
    u.hhh += 0x38000000;                         // Adjust exponent bias
200
    if ((half & 0x7C00) == 0) {// Subnormal
201
        if (supportSubnormal) {
202
            u.hhh = 0x3F800000 - (24 << 23);     // 2^-24
203
            u.fff *= int(half & 0x3FF);          // subnormal value = mantissa * 2^-24
204
        }
205
        else {
206
            u.hhh = 0;                           // make zero
207
        }
208
    }
209
    if ((half & 0x7C00) == 0x7C00) {             // infinity or nan
210
        u.expo = 0xFF;
211
        if (half & 0x3FF) {  // nan
212
            u.mant = 1 << 22 | (half & 0x1FF);   // NAN payload is right-justified only in ForwardCom
213
        }
214
    }
215
    u.hhh |= (half & 0x8000) << 16;              // sign bit
216
    return u.fff;
217
}
218
 
219
// Convert floating point number to half precision.
220
// Round to nearest or even. 
221
// Optional support for subnormals
222
// NAN payload is right-justified
223
uint16_t float2half(float x, bool supportSubnormal) {
224
    union {                                      // single precision float
225
        float f;
226
        struct {
227
            uint32_t mant: 23;
228
            uint32_t expo:  8;
229
            uint32_t sign:  1;
230
        };
231
    } u;
232
    union {                                      // half precision float
233
        uint16_t h;
234
        struct {
235
            uint16_t mant: 10;
236
            uint16_t expo:  5;
237
            uint16_t sign:  1;
238
        };
239
    } v;
240
    u.f = x;
241
    v.sign = u.sign;
242
    v.mant = u.mant >> 13;                       // get upper part of mantissa
243
    if (u.mant & (1 << 12)) {                    // round to nearest or even
244
        if ((u.mant & ((1 << 12) - 1)) || (v.mant & 1)) { // round up if odd or remaining bits are nonzero
245
            v.h++;                               // overflow here will give infinity
246
        }
247
    }
248
    v.expo = u.expo - 0x70;
249
    if (u.expo == 0xFF) {                        // infinity or nan
250
        v.expo = 0x1F;
251
        if (u.mant != 0) {                       // Nan
252
            v.mant = (u.mant & 0x1FF) | 0x200;   // NAN payload is right-justified only in ForwardCom        
253
        }
254
    }
255
    else if (u.expo > 0x8E) {
256
        v.expo = 0x1F;  v.mant = 0;              // overflow -> inf
257
    }
258
    else if (u.expo < 0x71) {
259
        v.expo = 0;
260
        if (supportSubnormal) {
261
            u.expo += 24;
262
            u.sign = 0;
263
            v.mant = int(u.f) & 0x3FF;
264
        }
265
        else {
266
            v.mant = 0;                          // underflow -> 0
267
        }
268
    }
269
    return v.h;
270
}
271
 
272
// Convert double precision floating point number to half precision. 
273
// subnormals optionally supported
274
// Nan payloads not preserved
275
uint16_t double2half(double x, bool supportSubnormal) {
276
    union {
277
        double d;
278
        struct {
279
            uint64_t mant: 52;
280
            uint64_t expo: 11;
281
            uint64_t sign:  1;
282
        };
283
    } u;
284
    union {
285
        uint16_t h;
286
        struct {
287
            uint16_t mant: 10;
288
            uint16_t expo:  5;
289
            uint16_t sign:  1;
290
        };
291
    } v;
292
    u.d = x;
293
    v.mant = u.mant >> 42;                       // get upper part of mantissa
294
    if (u.mant & ((uint64_t)1 << 41)) {          // round to nearest or even
295
        if ((u.mant & (((uint64_t)1 << 41) - 1)) || (v.mant & 1)) { // round up if odd or remaining bits are nonzero
296
            v.h++;                               // overflow here will give infinity
297
        }
298
    }
299
    v.expo = u.expo - 0x3F0;
300
    v.sign = u.sign;
301
    if (u.expo == 0x7FF) {
302
        v.expo = 0x1F;                           // infinity or nan
303
        if (u.mant != 0 && v.mant == 0) v.mant = 0x200;  // make sure output is a nan if input is nan
304
    }
305
    else if (u.expo > 0x40E) {
306
        v.expo = 0x1F;  v.mant = 0;              // overflow -> inf
307
    }
308
    else if (u.expo < 0x3F1) {                   // underflow
309
        v.expo = 0;
310
        if (supportSubnormal) {
311
            u.expo += 24;
312
            u.sign = 0;
313
            v.mant = int(u.d) & 0x3FF;
314
        }
315
        else {
316
            v.mant = 0;                          // underflow -> 0
317
        }
318
    }
319
    return v.h;
320
}
321
 
322
 
323
// Check that we are running on a machine with little-endian memory 
324
// organization and right data representation
325
static void CheckEndianness() {
326
    static uint8_t bytes[4] = { 1, 2, 3, 0xC0 };
327
    uint8_t * bb = bytes;
328
    if (*(uint32_t*)bb != 0xC0030201) {
329
        err.submit(ERR_BIG_ENDIAN);        // Big endian
330
    }
331
    if (*(int32_t*)bb != -1073544703) {
332
        err.submit(ERR_BIG_ENDIAN);        // not two's complement
333
    }
334
    *(float*)bb = 1.0f;
335
    if (*(uint32_t*)bb != 0x3F800000) {
336
        err.submit(ERR_BIG_ENDIAN);        // Not IEEE floating point format
337
    }
338
}
339
 
340
 
341
// Bit scan reverse. Returns floor(log2(x)), 0 if x = 0
342
uint32_t bitScanReverse(uint64_t x) {
343
    uint32_t s = 32;  // shift count
344
    uint32_t r = 0;   // return value
345
    uint64_t y;       // x >> s
346
    do {
347
        y = x >> s;
348
        if (y) {
349
            r += s;
350
            x = y;
351
        }
352
        s >>= 1;
353
    }
354
    while (s);
355
    return r;
356
}
357
 
358
// Bit scan forward. Returns index to the lowest set bit, 0 if x = 0
359
uint32_t bitScanForward(uint64_t x) {
360
    uint32_t s = 32;  // shift count
361
    uint32_t r = 0;   // return value
362
    if (x == 0) return 0;
363
    do {
364
        if ((x & (((uint64_t)1 << s) - 1)) == 0) {
365
            x >>= s;
366
            r += s;
367
        }
368
        s >>= 1;
369
    }
370
    while (s);
371
    return r;
372
}
373
 
374
const char * timestring(uint32_t t) {
375
    // Convert 32 bit time stamp to string
376
    // Fix the problem that time_t may be 32 bit or 64 bit
377
    union {
378
        time_t t;
379
        uint32_t t32;
380
    } utime;
381
    utime.t = 0;
382
    utime.t32 = t;
383
    const char * string = ctime(&utime.t);
384
    if (string == 0) string = "?";
385
    return string;
386
}

powered by: WebSVN 2.1.0

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