211 lines
5.3 KiB
C++
211 lines
5.3 KiB
C++
/*******************************************************************************
|
|
HARPtools by Chad D. Kersey, Summer 2011
|
|
*******************************************************************************/
|
|
#ifndef __OBJ_H
|
|
#define __OBJ_H
|
|
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <list>
|
|
#include <stdlib.h>
|
|
|
|
#include "types.h"
|
|
#include "archdef.h"
|
|
#include "instruction.h"
|
|
#include "enc.h"
|
|
#include "asm-tokens.h"
|
|
|
|
namespace Harp {
|
|
class Decoder;
|
|
class Encoder;
|
|
|
|
class Ref {
|
|
public:
|
|
std::string name;
|
|
Ref(const std::string &n, bool r, Size ib = 0):
|
|
name(n), bound(false), relative(r), ibase(ib) { }
|
|
virtual ~Ref() { }
|
|
virtual void bind(Addr addr, Addr base = 0) = 0;
|
|
virtual Addr getAddr() const = 0;
|
|
|
|
bool bound, relative;
|
|
Size ibase;
|
|
};
|
|
|
|
/* Used in not-yet-encoded code objects, plain old data. */
|
|
class SimpleRef : public Ref {
|
|
public:
|
|
SimpleRef(const std::string &name, Addr &addr, bool rel = false) :
|
|
Ref(name, rel), addr(addr) { }
|
|
virtual void bind(Addr addr, Addr base = 0) {
|
|
std::cout << "Attempted to bind a SimpleRef.\n";
|
|
exit(1);
|
|
}
|
|
virtual Addr getAddr() const { return this->addr; }
|
|
Byte *getAddrPtr() { return (Byte*)&addr; }
|
|
|
|
private:
|
|
Addr &addr;
|
|
};
|
|
|
|
/* Used in already-encoded code objects. */
|
|
class OffsetRef : public Ref {
|
|
public:
|
|
OffsetRef(
|
|
const std::string &name, std::vector<Byte> &v, Size offset, Size bits,
|
|
Size ws, bool rel = false, Size ibase = 0
|
|
) : Ref(name, rel, ibase), data(v), offset(offset), bits(bits), wordSize(ws)
|
|
{}
|
|
|
|
virtual void bind(Addr addr, Addr base = 0) {
|
|
Size bytes(bits/8), remainder(bits%8);
|
|
|
|
if (relative) {
|
|
addr = addr - base;
|
|
Word_s addr_s(addr);
|
|
if ((addr_s >> bits) != ~0ull && (addr_s >> bits) != 0) goto noFit;
|
|
} else {
|
|
Addr mask = (1ull<<bits)-1;
|
|
if (addr > mask) goto noFit;
|
|
}
|
|
|
|
{ Byte mask((1ull<<remainder) - 1);
|
|
Size i;
|
|
for (i = 0; i < bytes; i++) {
|
|
data[offset+i] = addr & 0xff;
|
|
addr >>= 8;
|
|
}
|
|
data[offset+i] &= ~mask;
|
|
data[offset+i] |= (addr&mask);
|
|
bound = true;
|
|
}
|
|
|
|
return;
|
|
noFit:
|
|
std::cout << "Attempt to bind a " << bits << "-bit "
|
|
<< (relative?"":"non-") << "relative symbol to an address"
|
|
" it cannot reach.\n";
|
|
exit(1);
|
|
}
|
|
|
|
virtual Addr getAddr() const {
|
|
Size bytes = bits/8, remainder = bits%8;
|
|
Byte mask((1<<remainder)-1);
|
|
Addr a(data[offset]&mask);
|
|
|
|
for (Size i = 0; i < bytes-1; i++) {
|
|
a |= data[offset + bytes - i - 1];
|
|
a <<= 8;
|
|
}
|
|
return a;
|
|
}
|
|
|
|
Size getOffset() const { return offset; }
|
|
Size getBits() const { return bits; }
|
|
|
|
private:
|
|
std::vector<Byte> &data;
|
|
Size offset, bits, wordSize;
|
|
};
|
|
|
|
class Chunk {
|
|
public:
|
|
Chunk(std::string n, Size a = 0, Word f = 0) :
|
|
name(n), alignment(a), bound(false), flags(f), global(false) {}
|
|
virtual ~Chunk() { for (Size i = 0; i < refs.size(); i++) delete refs[i]; }
|
|
void bind(Addr a) { address = a; bound = true; }
|
|
void setGlobal() { global = true; }
|
|
bool isGlobal() const { return global; }
|
|
std::string name;
|
|
Size alignment;
|
|
bool bound, global;
|
|
Addr address;
|
|
Word flags;
|
|
std::vector<Ref*> refs;
|
|
};
|
|
|
|
class TextChunk : public Chunk {
|
|
public:
|
|
TextChunk(std::string n, Size a = 0, Word f = 0)
|
|
: Chunk(n, a, f), instructions() {}
|
|
|
|
~TextChunk() {
|
|
for (Size i = 0; i < instructions.size(); i++) delete instructions[i];
|
|
}
|
|
|
|
std::vector<Instruction*> instructions;
|
|
};
|
|
|
|
class DataChunk : public Chunk {
|
|
public:
|
|
DataChunk(std::string n, Size a = 0, Word f = 0)
|
|
: Chunk(n, a, f), size(0), contents() {}
|
|
Size size;
|
|
std::vector<Byte> contents; /* 0 to size bytes in length. */
|
|
};
|
|
|
|
class Obj {
|
|
public:
|
|
~Obj() { for (Size i = 0; i < chunks.size(); i++) delete chunks[i]; }
|
|
std::vector<Chunk*> chunks;
|
|
Size entry;
|
|
};
|
|
|
|
class DynObj : public Obj {
|
|
public:
|
|
std::vector<std::string> deps;
|
|
};
|
|
|
|
class ObjReader {
|
|
public:
|
|
virtual Obj *read(std::istream &input) = 0;
|
|
private:
|
|
};
|
|
|
|
class ObjWriter {
|
|
public:
|
|
virtual void write(std::ostream &output, const Obj &o) = 0;
|
|
private:
|
|
};
|
|
|
|
class AsmReader : public ObjReader {
|
|
public:
|
|
AsmReader(ArchDef arch) :
|
|
wordSize(arch.getWordSize()), nRegs(arch.getNRegs()) {}
|
|
virtual Obj *read(std::istream &input);
|
|
private:
|
|
Size wordSize, nRegs;
|
|
|
|
// Operand type sequences indexed by argument class
|
|
enum ArgType {AT_END, AT_REG, AT_PREG, AT_LIT};
|
|
static ArgType operandtype_table[][4]; // ArgClass -> ArgType[arg_idx]
|
|
};
|
|
|
|
class HOFReader : public ObjReader {
|
|
public:
|
|
HOFReader(ArchDef &arch) : arch(arch) {}
|
|
Obj *read(std::istream &input);
|
|
private:
|
|
const ArchDef &arch;
|
|
};
|
|
|
|
class AsmWriter : public ObjWriter {
|
|
public:
|
|
AsmWriter(ArchDef arch): wordSize(arch.getWordSize()) {}
|
|
virtual void write(std::ostream &output, const Obj &obj);
|
|
private:
|
|
Size wordSize;
|
|
};
|
|
|
|
class HOFWriter : public ObjWriter {
|
|
public:
|
|
HOFWriter(ArchDef &arch) : arch(arch) {}
|
|
virtual void write(std::ostream &output, const Obj &obj);
|
|
private:
|
|
const ArchDef &arch;
|
|
};
|
|
};
|
|
|
|
#endif
|