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

Subversion Repositories forwardcom

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 62 to Rev 63
    Reverse comparison

Rev 62 → Rev 63

/forwardcom/bintools/main.cpp
0,0 → 1,386
/**************************** main.cpp *******************************
* Author: Agner Fog
* Date created: 2017-04-17
* Last modified: 2020-11-25
* Version: 1.11
* Project: Binary tools for ForwardCom instruction set
* Description: This includes assembler, disassembler, linker, library
* manager, and emulator in one program
*
* Instructions:
* Run with option -h for help
*
* For detailed instructions, see forwardcom.pdf
*
* (c) Copyright 2017-2020 GNU General Public License version 3
* http://www.gnu.org/licenses
*****************************************************************************/
 
#include "stdafx.h"
 
// Check if running on little endian system
static void CheckEndianness();
 
// Buffer for symbol names is made global in order to make it accessible to operators:
// bool operator < (ElfFWC_Sym2 const &, ElfFWC_Sym2 const &)
// bool operator < (SStringEntry const & a, SStringEntry const & b)
// bool operator < (SSymbolEntry const & a, SSymbolEntry const & b)
CTextFileBuffer symbolNameBuffer; // Buffer for symbol names during assembly, linking, and library operations
 
 
// Main. Program starts here
int main(int argc, char * argv[]) {
CheckEndianness(); // Check that machine is little-endian
 
#ifdef _DEBUG
// For debugging only: Read command line from file resp.txt
if (argc == 1) {
char commandline[] = "@resp.txt";
char * dummyarg[] = { argv[0], commandline};
argc = 2; argv = dummyarg;
}
#endif
 
cmd.readCommandLine(argc, argv); // Read command line parameters
if (cmd.job == CMDL_JOB_HELP) return 0; // Help screen has been printed. Do nothing else
 
CConverter maincvt; // This object takes care of all conversions etc.
maincvt.go(); // Do everything the command line says
 
if (cmd.verbose && cmd.job != CMDL_JOB_EMU) printf("\n"); // End with newline
if (err.getWorstError()) cmd.mainReturnValue = err.getWorstError(); // Return with error code
return cmd.mainReturnValue;
}
 
 
CConverter::CConverter() {
// Constructor
}
 
void CConverter::go() {
// Do whatever the command line parameters say
 
switch (cmd.job) {
case CMDL_JOB_DUMP:
// File dump requested
readInputFile();
if (err.number()) return;
switch (fileType) {
case FILETYPE_FWC: case FILETYPE_ELF:
dumpELF(); break;
default:
err.submit(ERR_DUMP_NOT_SUPPORTED, getFileFormatName(fileType)); // Dump of this file type not supported
}
printf("\n"); // New line
break;
 
case CMDL_JOB_ASS:
// assemble
readInputFile();
if (err.number()) return;
assemble();
break;
 
case CMDL_JOB_DIS:
// disassemble
readInputFile();
if (err.number()) return;
disassemble();
break;
 
case CMDL_JOB_LINK:
case CMDL_JOB_RELINK:
link(); // linker
break;
 
case CMDL_JOB_LIB:
readInputFile();
if (err.number()) return;
lib(); // library manager
break;
 
case CMDL_JOB_EMU:
emulate(); // emulator
break;
 
case 0: return; // no job. command line error
 
default:
err.submit(ERR_INTERNAL);
}
}
 
// read input file
void CConverter::readInputFile() {
// Ignore nonexisting filename when building library
int IgnoreError = (cmd.fileOptions & CMDL_FILE_IN_IF_EXISTS);
// Read input file
read(cmd.getFilename(cmd.inputFile), IgnoreError);
if (cmd.job == CMDL_JOB_ASS) fileType = FILETYPE_ASM;
else getFileType(); // Determine file type
if (err.number()) return; // Return if error
cmd.inputType = fileType; // Save input file type in cmd for access from other modules
if (cmd.outputType == 0) {
// desired type not specified
cmd.outputType = fileType;
}
}
 
void CConverter::dumpELF() {
// Dump ELF file
// Make object for interpreting 32 bit ELF file
CELF elf;
*this >> elf; // Give it my buffer
elf.parseFile(); // Parse file buffer
if (err.number()) return; // Return if error
elf.dump(cmd.dumpOptions); // Dump file
*this << elf; // Take back my buffer
}
 
void CConverter::assemble() {
// Aassemble to ELF file
// Make instance of assembler
CAssembler ass;
if (err.number()) return;
*this >> ass; // Give it my buffer
ass.go(); // run
}
 
void CConverter::disassemble() {
// Disassemble ELF file
// Make instance of disassembler
CDisassembler dis;
if (err.number()) return;
*this >> dis; // Give it my buffer
dis.parseFile(); // Parse file buffer
if (err.number()) return; // Return if error
dis.getComponents1(); // Get components from ELF file
dis.go(); // Convert
}
 
void CConverter::lib() {
// Library manager
// Make instance of library manager
CLibrary libmanager;
if (err.number()) return;
*this >> libmanager; // Give it my buffer
libmanager.go(); // Do the job
}
 
void CConverter::link() {
// Linker
// Make instance of linker
CLinker linker;
linker.go(); // Do the job
}
 
void CConverter::emulate() {
// Emulator
// Make instance of linker
CEmulator emulator;
emulator.go(); // Do the job
}
 
// Convert half precision floating point number to single precision
// Optional support for subnormals
// NAN payload is right-justified for ForwardCom
float half2float(uint32_t half, bool supportSubnormal) {
union {
uint32_t hhh;
float fff;
struct {
uint32_t mant: 23;
uint32_t expo: 8;
uint32_t sign: 1;
};
} u;
 
u.hhh = (half & 0x7fff) << 13; // Exponent and mantissa
u.hhh += 0x38000000; // Adjust exponent bias
if ((half & 0x7C00) == 0) {// Subnormal
if (supportSubnormal) {
u.hhh = 0x3F800000 - (24 << 23); // 2^-24
u.fff *= int(half & 0x3FF); // subnormal value = mantissa * 2^-24
}
else {
u.hhh = 0; // make zero
}
}
if ((half & 0x7C00) == 0x7C00) { // infinity or nan
u.expo = 0xFF;
if (half & 0x3FF) { // nan
u.mant = 1 << 22 | (half & 0x1FF); // NAN payload is right-justified only in ForwardCom
}
}
u.hhh |= (half & 0x8000) << 16; // sign bit
return u.fff;
}
 
// Convert floating point number to half precision.
// Round to nearest or even.
// Optional support for subnormals
// NAN payload is right-justified
uint16_t float2half(float x, bool supportSubnormal) {
union { // single precision float
float f;
struct {
uint32_t mant: 23;
uint32_t expo: 8;
uint32_t sign: 1;
};
} u;
union { // half precision float
uint16_t h;
struct {
uint16_t mant: 10;
uint16_t expo: 5;
uint16_t sign: 1;
};
} v;
u.f = x;
v.sign = u.sign;
v.mant = u.mant >> 13; // get upper part of mantissa
if (u.mant & (1 << 12)) { // round to nearest or even
if ((u.mant & ((1 << 12) - 1)) || (v.mant & 1)) { // round up if odd or remaining bits are nonzero
v.h++; // overflow here will give infinity
}
}
v.expo = u.expo - 0x70;
if (u.expo == 0xFF) { // infinity or nan
v.expo = 0x1F;
if (u.mant != 0) { // Nan
v.mant = (u.mant & 0x1FF) | 0x200; // NAN payload is right-justified only in ForwardCom
}
}
else if (u.expo > 0x8E) {
v.expo = 0x1F; v.mant = 0; // overflow -> inf
}
else if (u.expo < 0x71) {
v.expo = 0;
if (supportSubnormal) {
u.expo += 24;
u.sign = 0;
v.mant = int(u.f) & 0x3FF;
}
else {
v.mant = 0; // underflow -> 0
}
}
return v.h;
}
 
// Convert double precision floating point number to half precision.
// subnormals optionally supported
// Nan payloads not preserved
uint16_t double2half(double x, bool supportSubnormal) {
union {
double d;
struct {
uint64_t mant: 52;
uint64_t expo: 11;
uint64_t sign: 1;
};
} u;
union {
uint16_t h;
struct {
uint16_t mant: 10;
uint16_t expo: 5;
uint16_t sign: 1;
};
} v;
u.d = x;
v.mant = u.mant >> 42; // get upper part of mantissa
if (u.mant & ((uint64_t)1 << 41)) { // round to nearest or even
if ((u.mant & (((uint64_t)1 << 41) - 1)) || (v.mant & 1)) { // round up if odd or remaining bits are nonzero
v.h++; // overflow here will give infinity
}
}
v.expo = u.expo - 0x3F0;
v.sign = u.sign;
if (u.expo == 0x7FF) {
v.expo = 0x1F; // infinity or nan
if (u.mant != 0 && v.mant == 0) v.mant = 0x200; // make sure output is a nan if input is nan
}
else if (u.expo > 0x40E) {
v.expo = 0x1F; v.mant = 0; // overflow -> inf
}
else if (u.expo < 0x3F1) { // underflow
v.expo = 0;
if (supportSubnormal) {
u.expo += 24;
u.sign = 0;
v.mant = int(u.d) & 0x3FF;
}
else {
v.mant = 0; // underflow -> 0
}
}
return v.h;
}
 
 
// Check that we are running on a machine with little-endian memory
// organization and right data representation
static void CheckEndianness() {
static uint8_t bytes[4] = { 1, 2, 3, 0xC0 };
uint8_t * bb = bytes;
if (*(uint32_t*)bb != 0xC0030201) {
err.submit(ERR_BIG_ENDIAN); // Big endian
}
if (*(int32_t*)bb != -1073544703) {
err.submit(ERR_BIG_ENDIAN); // not two's complement
}
*(float*)bb = 1.0f;
if (*(uint32_t*)bb != 0x3F800000) {
err.submit(ERR_BIG_ENDIAN); // Not IEEE floating point format
}
}
 
 
// Bit scan reverse. Returns floor(log2(x)), 0 if x = 0
uint32_t bitScanReverse(uint64_t x) {
uint32_t s = 32; // shift count
uint32_t r = 0; // return value
uint64_t y; // x >> s
do {
y = x >> s;
if (y) {
r += s;
x = y;
}
s >>= 1;
}
while (s);
return r;
}
 
// Bit scan forward. Returns index to the lowest set bit, 0 if x = 0
uint32_t bitScanForward(uint64_t x) {
uint32_t s = 32; // shift count
uint32_t r = 0; // return value
if (x == 0) return 0;
do {
if ((x & (((uint64_t)1 << s) - 1)) == 0) {
x >>= s;
r += s;
}
s >>= 1;
}
while (s);
return r;
}
 
const char * timestring(uint32_t t) {
// Convert 32 bit time stamp to string
// Fix the problem that time_t may be 32 bit or 64 bit
union {
time_t t;
uint32_t t32;
} utime;
utime.t = 0;
utime.t32 = t;
const char * string = ctime(&utime.t);
if (string == 0) string = "?";
return string;
}

powered by: WebSVN 2.1.0

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