/******************************************************************************* HARPtools by Chad D. Kersey, Summer 2011 *******************************************************************************/ #ifndef __OBJ_H #define __OBJ_H #include #include #include #include #include #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 &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< mask) goto noFit; } { Byte mask((1ull<>= 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< &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 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 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 contents; /* 0 to size bytes in length. */ }; class Obj { public: ~Obj() { for (Size i = 0; i < chunks.size(); i++) delete chunks[i]; } std::vector chunks; Size entry; }; class DynObj : public Obj { public: std::vector 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