lots of errors

This commit is contained in:
felsabbagh3
2019-02-09 20:17:17 -05:00
parent 8128d2e250
commit 0c3a73a896
8 changed files with 1676 additions and 1591 deletions

View File

@@ -1,7 +1,7 @@
################################################################################ ################################################################################
# HARPtools by Chad D. Kersey, Summer 2011 # # HARPtools by Chad D. Kersey, Summer 2011 #
################################################################################ ################################################################################
CXXFLAGS ?= -fPIC -O3 # -g -DUSE_DEBUG=3 -DPRINT_ACTIVE_THREADS CXXFLAGS ?= -std=c++11 -fPIC -O3 # -g -DUSE_DEBUG=3 -DPRINT_ACTIVE_THREADS
LDLIBS ?= -pthread LDLIBS ?= -pthread
PREFIX ?= /usr/local PREFIX ?= /usr/local

View File

@@ -28,75 +28,75 @@ static void decodeError(string msg) {
} }
void Encoder::encodeChunk(DataChunk &dest, const TextChunk &src) { void Encoder::encodeChunk(DataChunk &dest, const TextChunk &src) {
typedef vector<Instruction*>::const_iterator vec_it; // typedef vector<Instruction*>::const_iterator vec_it;
const vector<Instruction*> &s(src.instructions); // const vector<Instruction*> &s(src.instructions);
vector<Byte> &d(dest.contents); // vector<Byte> &d(dest.contents);
/* Keep encoding the instructions. */ // /* Keep encoding the instructions. */
Size n = 0; // Size n = 0;
/* For each instruction. */ // /* For each instruction. */
for (vec_it i = s.begin(); i != s.end(); i++) { // for (vec_it i = s.begin(); i != s.end(); i++) {
Ref *ref; // Ref *ref;
/* Perform the encoding. */ // /* Perform the encoding. */
n += encode(ref, d, n, **i); // n += encode(ref, d, n, **i);
/* Add reference if necessary. */ // /* Add reference if necessary. */
if (ref != NULL) { // if (ref != NULL) {
ref->ibase = n; // ref->ibase = n;
dest.refs.push_back(ref); // dest.refs.push_back(ref);
} // }
} // }
dest.alignment = src.alignment; // dest.alignment = src.alignment;
dest.flags = src.flags; // dest.flags = src.flags;
dest.address = src.address; // dest.address = src.address;
dest.bound = src.bound; // dest.bound = src.bound;
if (src.isGlobal()) dest.setGlobal(); // if (src.isGlobal()) dest.setGlobal();
d.resize(n); // d.resize(n);
dest.size = n; // dest.size = n;
} }
void Decoder::decodeChunk(TextChunk &dest, const DataChunk &src) { void Decoder::decodeChunk(TextChunk &dest, const DataChunk &src) {
typedef vector<Instruction*>::const_iterator vec_it; // typedef vector<Instruction*>::const_iterator vec_it;
const vector<Byte> &v(src.contents); // const vector<Byte> &v(src.contents);
Size n = 0; // Size n = 0;
setRefs(src.refs); // setRefs(src.refs);
while (n < src.contents.size()) { // while (n < src.contents.size()) {
Instruction *inst = decode(v, n); // Instruction *inst = decode(v, n);
if (inst->hasRefLiteral()) { // if (inst->hasRefLiteral()) {
dest.refs.push_back(inst->getRefLiteral()); // dest.refs.push_back(inst->getRefLiteral());
} // }
dest.instructions.push_back(inst); // dest.instructions.push_back(inst);
} // }
dest.alignment = src.alignment; // dest.alignment = src.alignment;
dest.flags = src.flags; // dest.flags = src.flags;
dest.address = src.address; // dest.address = src.address;
dest.bound = src.bound; // dest.bound = src.bound;
if (src.isGlobal()) dest.setGlobal(); // if (src.isGlobal()) dest.setGlobal();
clearRefs(); // clearRefs();
} // }
void Decoder::setRefs(const std::vector<Ref*> &refVec) { // void Decoder::setRefs(const std::vector<Ref*> &refVec) {
haveRefs = true; // haveRefs = true;
typedef std::vector<Ref*>::const_iterator vec_ci; // typedef std::vector<Ref*>::const_iterator vec_ci;
for (vec_ci i = refVec.begin(); i != refVec.end(); i++) { // for (vec_ci i = refVec.begin(); i != refVec.end(); i++) {
OffsetRef *oref = dynamic_cast<OffsetRef*>(*i); // OffsetRef *oref = dynamic_cast<OffsetRef*>(*i);
if (oref) { // if (oref) {
refMap[oref->getOffset()] = *i; // refMap[oref->getOffset()] = *i;
} else { // } else {
decodeError("Unknown Ref type in Decoder::setRefs"); // decodeError("Unknown Ref type in Decoder::setRefs");
} // }
} // }
} }
Instruction *ByteDecoder::decode(const vector<Byte> &v, Size &n) { Instruction *ByteDecoder::decode(const vector<Byte> &v, Size &n) {
@@ -242,27 +242,34 @@ static unsigned ceilLog2(RegNum x) {
return z; return z;
} }
static Word mask(Size bits) {
return (1ull<<bits)-1;
}
static void getSizes(const ArchDef &arch, Size &n, Size& o, Size &r, Size &p,
Size &i1, Size &i2, Size &i3)
{
n = arch.getWordSize() * 8;
o = 7;
r = ceilLog2(arch.getNRegs());
p = 0;
i1 = n - 1 - p - o;
i2 = i1 - r;
i3 = i2 - r;
}
WordDecoder::WordDecoder(const ArchDef &arch) { WordDecoder::WordDecoder(const ArchDef &arch) {
getSizes(arch, n, o, r, p, i1, i2, i3);
if (p > r) r = p; inst_s = arch.getWordSize() * 8;
oMask = mask(o); rMask = mask(r); pMask = mask(p); opcode_s = 7;
i1Mask = mask(i1); i2Mask = mask(i2); i3Mask = mask(i3); reg_s = 5;
func3_s = 3;
shift_opcode = 0;
shift_rd = opcode_s;
shift_func3 = opcode_s + reg_s;
shift_rs1 = opcode_s + reg_s + func3_s;
shift_rs2 = opcode_s + reg_s + func3_s + reg_s;
shift_func7 = opcode_s + reg_s + func3_s + reg_s + reg_s;
shift_j_u_immed = opcode_s + reg_s;
shift_s_b_immed = opcode_s + reg_s + func3_s + reg_s + reg_s;
shift_i_immed = opcode_s + reg_s + func3_s + reg_s;
reg_mask = 0x1f;
func3_mask = 0x7;
func7_mask = 0x7f;
opcode_mask = 0x7f;
i_immed_mask = 0xfff;
s_immed_mask = 0xfff;
b_immed_mask = 0x1fff;
u_immed_mask = 0xfffff;
j_immed_mask = 0xfffff;
} }
Word signExt(Word w, Size bit, Word mask) { Word signExt(Word w, Size bit, Word mask) {
@@ -278,69 +285,83 @@ Instruction *WordDecoder::decode(const std::vector<Byte> &v, Size &idx) {
bool predicated = false; bool predicated = false;
if (predicated) { inst.setPred((code>>(n-p-1))&pMask); } if (predicated) { inst.setPred((code>>(n-p-1))&pMask); }
Instruction::Opcode op = (Instruction::Opcode)((code>>i1)&oMask); Instruction::Opcode op = (Instruction::Opcode)((code>>shift_opcode)&opcode_mask);
inst.setOpcode(op); inst.setOpcode(op);
bool usedImm(false); bool usedImm(false);
switch(Instruction::instTable[op].argClass) {
case Instruction::AC_NONE: switch(Instruction::instTable[op].iType)
{
case Instruction::InstType::N_TYPE:
break; break;
case Instruction::AC_1IMM: case Instruction::InstType::R_TYPE:
inst.setSrcImm(signExt(code&i1Mask, i1, i1Mask)); inst.setDestReg((code>>shift_rd) & reg_mask);
inst.setSrcReg((code>>shift_rs1) & reg_mask);
inst.setSrcReg((code>>shift_rs2) & reg_mask);
inst.setFunc3 ((code>>shift_func3) & func3_mask);
inst.setFunc7 ((code>>shift_func7) & func7_mask);
break;
case Instruction::InstType::I_TYPE
inst.setDestReg((code>>shift_rd) & reg_mask);
inst.setSrcReg((code>>shift_rs1) & reg_mask);
inst.setFunc3 ((code>>shift_func3) & func3_mask);
inst.setSrcImm(signExt(code>>shift_i_immed, 12, i_immed_mask));
usedImm = true; usedImm = true;
break; break;
case Instruction::AC_2IMM: case Instruction::InstType::S_TYPE:
inst.setDestReg((code>>i2)&rMask);
inst.setSrcImm(signExt(code&i2Mask, i2, i2Mask)); inst.setSrcReg((code>>shift_rs1) & reg_mask);
inst.setSrcReg((code>>shift_rs2) & reg_mask);
inst.setFunc3 ((code>>shift_func3) & func3_mask);
word dest_bits = (code>>shift_rd) & reg_mask;
Word imm_bits = (code>>shift_s_b_immed & func7_mask);
Word imeed = (imm_bits << reg_s) | dest_bits;
inst.setSrcImm(signExt(imeed, 12, s_immed_mask));
usedImm = true; usedImm = true;
break; break;
case Instruction::AC_3IMM: case Instruction::InstType::B_TYPE:
inst.setDestReg((code>>i2)&rMask);
inst.setSrcReg((code>>i3)&rMask); inst.setSrcReg((code>>shift_rs1) & reg_mask);
inst.setSrcImm(signExt(code&i3Mask, i3, i3Mask)); inst.setSrcReg((code>>shift_rs2) & reg_mask);
inst.setFunc3 ((code>>shift_func3) & func3_mask);
word dest_bits = (code>>shift_rd) & reg_mask;
Word imm_bits = (code>>shift_s_b_immed & func7_mask);
Word bit_11 = dest_bits & 0x1;
Word bit_4_1 = dest_bits >> 1;
Word bit_10_5 = imm_bits & 0x3f;
Word bit_12 = imm_bits >> 6;
Word imeed = 0 | (bits_4_1 << 1) | (bit_10_5 << 5) | (bit_11 << 11) | (bit_12 << 12);
inst.setSrcImm(signExt(imeed, 13, b_immed_mask));
usedImm = true; usedImm = true;
break; break;
case Instruction::AC_3IMMSRC: case Instruction::InstType::U_TYPE:
inst.setSrcReg((code>>i2)&rMask); inst.setDestReg((code>>shift_rd) & reg_mask);
inst.setSrcReg((code>>i3)&rMask); inst.setSrcImm(signExt(code>>shift_j_u_immed, 20, u_immed_mask));
inst.setSrcImm(signExt(code&i3Mask, i3, i3Mask));
usedImm = true; usedImm = true;
break; break;
case Instruction::AC_1REG: case Instruction::InstType::J_TYPE:
inst.setSrcReg((code>>i2)&rMask); inst.setDestReg((code>>shift_rd) & reg_mask);
// [20 | 10:1 | 11 | 19:12]
Word unordered = code>>shift_j_u_immed;
Word bits_19_12 = unordered & 0xff;
Word bit_11 = (unordered>>8) & 0x1;
Word bits_10_1 = (unordered >> 9) & 0x3ff;
Word bit_20 = (unordered>>19) & 0x1;
Word imeed = 0 | (bits_10_1 << 1) | (bit_11 << 11) | (bits_19_12 << 12) | (bit20 << 20);
inst.setSrcImm(signExt(imeed, 20, j_immed_mask));
usedImm = true;
break; break;
case Instruction::AC_2REG: defualt:
inst.setDestReg((code>>i2)&rMask);
inst.setSrcReg((code>>i3)&rMask);
break;
case Instruction::AC_3REG:
inst.setDestReg((code>>i2)&rMask);
inst.setSrcReg((code>>i3)&rMask);
inst.setSrcReg((code>>(i3-r))&rMask);
break;
case Instruction::AC_3REGSRC:
inst.setSrcReg((code>>i2)&rMask);
inst.setSrcReg((code>>i3)&rMask);
inst.setSrcReg((code>>(i3-r))&rMask);
break;
case Instruction::AC_PREG_REG:
inst.setDestPReg((code>>i2)&pMask);
inst.setSrcReg((code>>i3)&rMask);
break;
case Instruction::AC_2PREG:
inst.setDestPReg((code>>i2)&pMask);
inst.setSrcPReg((code>>i3)&pMask);
break;
case Instruction::AC_3PREG:
inst.setDestPReg((code>>i2)&pMask);
inst.setSrcPReg((code>>i3)&pMask);
inst.setSrcPReg((code>>(i3-r))&pMask);
break;
case Instruction::AC_2REGSRC:
inst.setSrcReg((code>>i2)&rMask);
inst.setSrcReg((code>>i3)&rMask);
break;
defualt:
cout << "Unrecognized argument class in word decoder.\n"; cout << "Unrecognized argument class in word decoder.\n";
exit(1); exit(1);
} }
@@ -359,120 +380,120 @@ Instruction *WordDecoder::decode(const std::vector<Byte> &v, Size &idx) {
return &inst; return &inst;
} }
WordEncoder::WordEncoder(const ArchDef &arch) { // WordEncoder::WordEncoder(const ArchDef &arch) {
getSizes(arch, n, o, r, p, i1, i2, i3); // getSizes(arch, n, o, r, p, i1, i2, i3);
if (p > r) r = p; // if (p > r) r = p;
oMask = mask(o); rMask = mask(r); pMask = mask(p); // oMask = mask(o); rMask = mask(r); pMask = mask(p);
i1Mask = mask(i1); i2Mask = mask(i2); i3Mask = mask(i3); // i1Mask = mask(i1); i2Mask = mask(i2); i3Mask = mask(i3);
} // }
Size WordEncoder::encode(Ref *&ref, std::vector<Byte> &v, // Size WordEncoder::encode(Ref *&ref, std::vector<Byte> &v,
Size idx, Instruction &i) // Size idx, Instruction &i)
{ // {
Word code = 0; // Word code = 0;
Size bitsWritten = 0; // Size bitsWritten = 0;
/* Predicate/predicated bit */ // /* Predicate/predicated bit */
if (i.hasPred()) { // if (i.hasPred()) {
code = 1 << p; // code = 1 << p;
code |= (i.getPred()&pMask); // code |= (i.getPred()&pMask);
if (i.getPred() > pMask) { // if (i.getPred() > pMask) {
cout << "Predicate in " << i << " does not fit in encoding.\n"; // cout << "Predicate in " << i << " does not fit in encoding.\n";
exit(1); // exit(1);
} // }
} // }
bitsWritten += (1 + p); // bitsWritten += (1 + p);
/* Opcode */ // /* Opcode */
code <<= o; // code <<= o;
code |= (i.getOpcode()&oMask); // code |= (i.getOpcode()&oMask);
if (i.getOpcode() > oMask) { // if (i.getOpcode() > oMask) {
cout << "Opcode in " << i << " does not fit in encoding.\n"; // cout << "Opcode in " << i << " does not fit in encoding.\n";
exit(1); // exit(1);
} // }
bitsWritten += o; // bitsWritten += o;
if (i.hasRDest()) { // if (i.hasRDest()) {
code <<= r; // code <<= r;
code |= i.getRDest(); // code |= i.getRDest();
bitsWritten += r; // bitsWritten += r;
if (i.getRDest() > rMask) { // if (i.getRDest() > rMask) {
cout << "Destination register in " << i << " does not fit in encoding.\n"; // cout << "Destination register in " << i << " does not fit in encoding.\n";
exit(1); // exit(1);
} // }
} // }
if (i.hasPDest()) { // if (i.hasPDest()) {
code <<= r; // code <<= r;
code |= i.getPDest(); // code |= i.getPDest();
bitsWritten += r; // bitsWritten += r;
if (i.getPDest() > rMask) { // if (i.getPDest() > rMask) {
cout << "Destination predicate in " <<i<< " does not fit in encoding.\n"; // cout << "Destination predicate in " <<i<< " does not fit in encoding.\n";
exit(1); // exit(1);
} // }
} // }
for (Size j = 0; j < i.getNRSrc(); j++) { // for (Size j = 0; j < i.getNRSrc(); j++) {
code <<= r; // code <<= r;
code |= i.getRSrc(j); // code |= i.getRSrc(j);
bitsWritten += r; // bitsWritten += r;
if (i.getRSrc(j) > rMask) { // if (i.getRSrc(j) > rMask) {
cout << "Source register " << j << " in " << i // cout << "Source register " << j << " in " << i
<< " does not fit in encoding.\n"; // << " does not fit in encoding.\n";
exit(1); // exit(1);
} // }
} // }
for (Size j = 0; j < i.getNPSrc(); j++) { // for (Size j = 0; j < i.getNPSrc(); j++) {
code <<= r; // code <<= r;
code |= i.getPSrc(j); // code |= i.getPSrc(j);
bitsWritten += r; // bitsWritten += r;
if (i.getPSrc(j) > rMask) { // if (i.getPSrc(j) > rMask) {
cout << "Source predicate " << j << " in " << i // cout << "Source predicate " << j << " in " << i
<< " does not fit in encoding.\n"; // << " does not fit in encoding.\n";
exit(1); // exit(1);
} // }
} // }
if (i.hasRefLiteral()) { // if (i.hasRefLiteral()) {
Ref *r = i.getRefLiteral(); // Ref *r = i.getRefLiteral();
ref = new OffsetRef(r->name, v, idx, n - bitsWritten, n, i.hasRelImm()); // ref = new OffsetRef(r->name, v, idx, n - bitsWritten, n, i.hasRelImm());
} else { // } else {
ref = NULL; // ref = NULL;
} // }
if (i.hasImm()) { // if (i.hasImm()) {
if (bitsWritten == n - i1) { // if (bitsWritten == n - i1) {
code <<= i1; // code <<= i1;
code |= (i.getImm()&i1Mask); // code |= (i.getImm()&i1Mask);
bitsWritten += i1; // bitsWritten += i1;
Word_s ws(i.getImm()); // Word_s ws(i.getImm());
if ((ws >> i1) != 0 && (ws >> i1) != -1) goto tooBigImm; // if ((ws >> i1) != 0 && (ws >> i1) != -1) goto tooBigImm;
} else if (bitsWritten == n - i2) { // } else if (bitsWritten == n - i2) {
code <<= i2; // code <<= i2;
code |= (i.getImm()&i2Mask); // code |= (i.getImm()&i2Mask);
bitsWritten += i2; // bitsWritten += i2;
Word_s ws(i.getImm()); // Word_s ws(i.getImm());
if ((ws >> i2) != 0 && (ws >> i2) != -1) goto tooBigImm; // if ((ws >> i2) != 0 && (ws >> i2) != -1) goto tooBigImm;
} else if (bitsWritten == n - i3) { // } else if (bitsWritten == n - i3) {
code <<= i3; // code <<= i3;
code |= (i.getImm()&i3Mask); // code |= (i.getImm()&i3Mask);
bitsWritten += i3; // bitsWritten += i3;
Word_s ws(i.getImm()); // Word_s ws(i.getImm());
if ((ws >> i3) != 0 && (ws >> i3) != -1) goto tooBigImm; // if ((ws >> i3) != 0 && (ws >> i3) != -1) goto tooBigImm;
} else { // } else {
cout << "WordEncoder::encode() could not encode: " << i << '\n'; // cout << "WordEncoder::encode() could not encode: " << i << '\n';
exit(1); // exit(1);
} // }
} // }
if (bitsWritten < n) code <<= (n - bitsWritten); // if (bitsWritten < n) code <<= (n - bitsWritten);
writeWord(v, idx, n/8, code); // writeWord(v, idx, n/8, code);
return n/8; // return n/8;
tooBigImm: // tooBigImm:
cout << "Immediate in " << i << " too large to encode.\n"; // cout << "Immediate in " << i << " too large to encode.\n";
exit(1); // exit(1);
} // }

View File

@@ -50,158 +50,158 @@ HarpToolMode findMode(int argc, char** argv) {
} }
int asm_main(int argc, char **argv) { int asm_main(int argc, char **argv) {
string archString("8w32/32/8/8"), outFileName("a.out.HOF"), // string archString("8w32/32/8/8"), outFileName("a.out.HOF"),
inFileName(argv[argc-1]); // inFileName(argv[argc-1]);
bool showHelp; // bool showHelp;
/* Get command line arguments. */ // /* Get command line arguments. */
CommandLineArgFlag fh("-h", "--help", "", showHelp); // CommandLineArgFlag fh("-h", "--help", "", showHelp);
CommandLineArgSetter<string>fo("-o", "--output", "", outFileName); // CommandLineArgSetter<string>fo("-o", "--output", "", outFileName);
CommandLineArgSetter<string>fa("-a", "--arch", "", archString); // CommandLineArgSetter<string>fa("-a", "--arch", "", archString);
CommandLineArg::readArgs(argc-1, argv); // CommandLineArg::readArgs(argc-1, argv);
if (showHelp || argc == 0) { // if (showHelp || argc == 0) {
cout << Help::asmHelp; // cout << Help::asmHelp;
exit(0); // exit(0);
} // }
ArchDef arch(archString); // ArchDef arch(archString);
D(0, "Created ArchDef for " << string(arch)); // D(0, "Created ArchDef for " << string(arch));
/* Create an appropriate encoder. */ // /* Create an appropriate encoder. */
Encoder *enc; // Encoder *enc;
switch (arch.getEncChar()) { // switch (arch.getEncChar()) {
case 'b': enc = new ByteEncoder(arch); break; // case 'b': enc = new ByteEncoder(arch); break;
case 'w': enc = new WordEncoder(arch); break; // case 'w': enc = new WordEncoder(arch); break;
defaulet: // defaulet:
cout << "Unknown encoding type, \"" << arch.getEncChar() << "\"\n"; // cout << "Unknown encoding type, \"" << arch.getEncChar() << "\"\n";
exit(1); // exit(1);
} // }
/* Open files. */ // /* Open files. */
if (outFileName == "") { // if (outFileName == "") {
cout << "HARP Assembler: No output filename given.\n"; // cout << "HARP Assembler: No output filename given.\n";
exit(1); // exit(1);
} // }
ifstream asmFile(inFileName.c_str()); // ifstream asmFile(inFileName.c_str());
ofstream outFile(outFileName.c_str()); // ofstream outFile(outFileName.c_str());
if (!asmFile) { // if (!asmFile) {
cout << "Could not open \"" << inFileName << "\" for reading.\n"; // cout << "Could not open \"" << inFileName << "\" for reading.\n";
exit(1); // exit(1);
} // }
if (!outFile) { // if (!outFile) {
cout << "Could not open \"" << outFileName << "\" for writing.\n"; // cout << "Could not open \"" << outFileName << "\" for writing.\n";
exit(1); // exit(1);
} // }
/* Read an Obj from the assembly file. */ // /* Read an Obj from the assembly file. */
D(0, "Passing AsmReader ArchDef: " << string(arch)); // D(0, "Passing AsmReader ArchDef: " << string(arch));
AsmReader ar(arch); // AsmReader ar(arch);
Obj *o = ar.read(asmFile); // Obj *o = ar.read(asmFile);
/* Encode the text chunks read from the assembly file. */ // /* Encode the text chunks read from the assembly file. */
for (Size j = 0; j < o->chunks.size(); j++) { // for (Size j = 0; j < o->chunks.size(); j++) {
Chunk *&c = o->chunks[j]; // Chunk *&c = o->chunks[j];
TextChunk *tc; // TextChunk *tc;
DataChunk *dc; // DataChunk *dc;
if ((tc = dynamic_cast<TextChunk*>(c)) != NULL) { // if ((tc = dynamic_cast<TextChunk*>(c)) != NULL) {
/* Encode it. */ // /* Encode it. */
dc = new DataChunk(tc->name); // dc = new DataChunk(tc->name);
enc->encodeChunk(*dc, *tc); // enc->encodeChunk(*dc, *tc);
/* Delete the text chunk. */ // /* Delete the text chunk. */
delete tc; // delete tc;
/* Do the switch. */ // /* Do the switch. */
c = dc; // c = dc;
} // }
} // }
asmFile.close(); // asmFile.close();
delete enc; // delete enc;
/* Write a HOF binary. */ // /* Write a HOF binary. */
D(0, "Creating a HOFWriter, passing it ArchDef: " << string(arch)); // D(0, "Creating a HOFWriter, passing it ArchDef: " << string(arch));
HOFWriter hw(arch); // HOFWriter hw(arch);
hw.write(outFile, *o); // hw.write(outFile, *o);
outFile.close(); // outFile.close();
delete o; // delete o;
return 0; return 0;
} }
int disasm_main(int argc, char **argv) { int disasm_main(int argc, char **argv) {
bool showHelp; // bool showHelp;
string outFileName("a.out.s"), archString("8w32/32/8/8"); // string outFileName("a.out.s"), archString("8w32/32/8/8");
/* Get command line arguments. */ // /* Get command line arguments. */
CommandLineArgFlag fh("-h", "--help", "", showHelp); // CommandLineArgFlag fh("-h", "--help", "", showHelp);
CommandLineArgSetter<string>fa("-a", "--arch", "", archString); // CommandLineArgSetter<string>fa("-a", "--arch", "", archString);
CommandLineArgSetter<string>fo("-o", "--output", "", outFileName); // CommandLineArgSetter<string>fo("-o", "--output", "", outFileName);
if (argc != 0) CommandLineArg::readArgs(argc-1, argv); // if (argc != 0) CommandLineArg::readArgs(argc-1, argv);
if (argc == 0 || showHelp) { // if (argc == 0 || showHelp) {
cout << Help::disasmHelp; // cout << Help::disasmHelp;
exit(0); // exit(0);
} // }
ifstream objFile(argv[argc-1]); // ifstream objFile(argv[argc-1]);
ofstream outFile(outFileName.c_str()); // ofstream outFile(outFileName.c_str());
ArchDef arch(archString); // ArchDef arch(archString);
if (!objFile) { // if (!objFile) {
cout << "Disassembler could not open \"" << argv[argc-1] // cout << "Disassembler could not open \"" << argv[argc-1]
<< "\" for reading.\n"; // << "\" for reading.\n";
exit(1); // exit(1);
} // }
if (!outFile) { // if (!outFile) {
cout << "Disassembler could not open \"" << outFileName // cout << "Disassembler could not open \"" << outFileName
<< "\" for output.\n"; // << "\" for output.\n";
exit(1); // exit(1);
} // }
HOFReader hr(arch); // HOFReader hr(arch);
Obj *o = hr.read(objFile); // Obj *o = hr.read(objFile);
objFile.close(); // objFile.close();
Decoder *dec; // Decoder *dec;
switch (arch.getEncChar()) { // switch (arch.getEncChar()) {
case 'b': dec = new ByteDecoder(arch); break; // case 'b': dec = new ByteDecoder(arch); break;
case 'w': dec = new WordDecoder(arch); break; // case 'w': dec = new WordDecoder(arch); break;
default: // default:
cout << "Unrecognized encoding character for disassembler.\n"; // cout << "Unrecognized encoding character for disassembler.\n";
exit(1); // exit(1);
} // }
/* Decode the chunks read from the object. */ // /* Decode the chunks read from the object. */
for (Size j = 0; j < o->chunks.size(); j++) { // for (Size j = 0; j < o->chunks.size(); j++) {
Chunk *&c = o->chunks[j]; // Chunk *&c = o->chunks[j];
if (c->flags & EX_USR) { // if (c->flags & EX_USR) {
TextChunk *tc; // TextChunk *tc;
DataChunk *dc; // DataChunk *dc;
if ((dc = dynamic_cast<DataChunk*>(c)) != NULL) { // if ((dc = dynamic_cast<DataChunk*>(c)) != NULL) {
TextChunk *tc = new TextChunk(dc->name); // TextChunk *tc = new TextChunk(dc->name);
dec->decodeChunk(*tc, *dc); // dec->decodeChunk(*tc, *dc);
delete dc; // delete dc;
c = tc; // c = tc;
} // }
} // }
} // }
delete dec; // delete dec;
AsmWriter aw(arch); // AsmWriter aw(arch);
aw.write(outFile, *o); // aw.write(outFile, *o);
outFile.close(); // outFile.close();
delete o; // delete o;
return 0; return 0;
} }
@@ -254,117 +254,117 @@ int emu_main(int argc, char **argv) {
} }
int ld_main(int argc, char **argv) { int ld_main(int argc, char **argv) {
bool showHelp, mustResolveRefs(true); // bool showHelp, mustResolveRefs(true);
string outFileName("a.out.bin"), archString("8w32/32/8/8"), // string outFileName("a.out.bin"), archString("8w32/32/8/8"),
formatString("bin"); // formatString("bin");
Size nObjects; // Size nObjects;
Addr binOffset(0); // Addr binOffset(0);
/* Get command line arguments. */ // /* Get command line arguments. */
CommandLineArgFlag fh("-h", "--help", "", showHelp); // CommandLineArgFlag fh("-h", "--help", "", showHelp);
CommandLineArgSetter<string>fa("-a", "--arch", "", archString); // CommandLineArgSetter<string>fa("-a", "--arch", "", archString);
CommandLineArgSetter<string>ff("-f", "--format", "", formatString); // CommandLineArgSetter<string>ff("-f", "--format", "", formatString);
CommandLineArgSetter<Addr> foffset("--offset", "", binOffset); // CommandLineArgSetter<Addr> foffset("--offset", "", binOffset);
CommandLineArgSetter<string>fo("-o", "--output", "", outFileName); // CommandLineArgSetter<string>fo("-o", "--output", "", outFileName);
int firstInput(0), newArgc; // int firstInput(0), newArgc;
for (size_t i = 0; i < argc; i++) { // for (size_t i = 0; i < argc; i++) {
if (*(argv[i]) != '-') { firstInput = i; newArgc = i; break; } // if (*(argv[i]) != '-') { firstInput = i; newArgc = i; break; }
else if (string(argv[i]) == "--") { firstInput = i+1; newArgc = i; break; } // else if (string(argv[i]) == "--") { firstInput = i+1; newArgc = i; break; }
else i++; /* Skip both the switch and its argument. */ // else i++; /* Skip both the switch and its argument. */
} // }
nObjects = argc - firstInput; // nObjects = argc - firstInput;
if (argc != 0) CommandLineArg::readArgs(newArgc, argv); // if (argc != 0) CommandLineArg::readArgs(newArgc, argv);
if (argc == 0 || showHelp) { // if (argc == 0 || showHelp) {
cout << Help::ldHelp; // cout << Help::ldHelp;
exit(0); // exit(0);
} // }
if (firstInput == argc) { // if (firstInput == argc) {
cout << "Linker: no input files given.\n"; // cout << "Linker: no input files given.\n";
exit(1); // exit(1);
} // }
ArchDef arch(archString); // ArchDef arch(archString);
/* Read all of the objects, assign addresses to their chunks, and place them // /* Read all of the objects, assign addresses to their chunks, and place them
in an address map.*/ // in an address map.*/
vector<Obj *> objects(nObjects); // vector<Obj *> objects(nObjects);
vector<DataChunk*> chunks; // vector<DataChunk*> chunks;
map<string, Addr> gChunkMap; // map<string, Addr> gChunkMap;
Addr nextOffset(binOffset); // Addr nextOffset(binOffset);
for (Size i = 0; i < nObjects; i++) { // for (Size i = 0; i < nObjects; i++) {
map <string, Addr> lChunkMap; // map <string, Addr> lChunkMap;
/* Read the object. */ // /* Read the object. */
HOFReader hr(arch); // HOFReader hr(arch);
ifstream objFile(argv[firstInput + i]); // ifstream objFile(argv[firstInput + i]);
if (!objFile) { // if (!objFile) {
cout << "Could not open \"" << argv[firstInput + i] // cout << "Could not open \"" << argv[firstInput + i]
<< "\" for reading.\n"; // << "\" for reading.\n";
exit(1); // exit(1);
} // }
objects[i] = hr.read(objFile); // objects[i] = hr.read(objFile);
/* Assign addresses to chunks. */ // /* Assign addresses to chunks. */
Obj &obj = *objects[i]; // Obj &obj = *objects[i];
for (Size j = 0; j < obj.chunks.size(); j++) { // for (Size j = 0; j < obj.chunks.size(); j++) {
DataChunk *c = dynamic_cast<DataChunk*>(obj.chunks[j]); // DataChunk *c = dynamic_cast<DataChunk*>(obj.chunks[j]);
if (c->alignment != 0 && nextOffset % c->alignment) // if (c->alignment != 0 && nextOffset % c->alignment)
nextOffset += c->alignment - (nextOffset % c->alignment); // nextOffset += c->alignment - (nextOffset % c->alignment);
c->bind(nextOffset); // c->bind(nextOffset);
chunks.push_back(c); // chunks.push_back(c);
if (obj.chunks[j]->name != "") { // if (obj.chunks[j]->name != "") {
if (c->isGlobal()) gChunkMap[c->name] = nextOffset; // if (c->isGlobal()) gChunkMap[c->name] = nextOffset;
else lChunkMap[c->name] = nextOffset; // else lChunkMap[c->name] = nextOffset;
} // }
nextOffset += (c->size); // nextOffset += (c->size);
} // }
/* Resolve local references. */ // /* Resolve local references. */
for (Size i = 0; i < obj.chunks.size(); i++) { // for (Size i = 0; i < obj.chunks.size(); i++) {
DataChunk *dc = dynamic_cast<DataChunk*>(obj.chunks[i]); // DataChunk *dc = dynamic_cast<DataChunk*>(obj.chunks[i]);
for (Size j = 0; j < dc->refs.size(); j++) { // for (Size j = 0; j < dc->refs.size(); j++) {
Ref &ref = *(dc->refs[j]); // Ref &ref = *(dc->refs[j]);
if (lChunkMap.find(dc->refs[j]->name) != lChunkMap.end()) { // if (lChunkMap.find(dc->refs[j]->name) != lChunkMap.end()) {
dc->refs[j]->bind(lChunkMap[dc->refs[j]->name], // dc->refs[j]->bind(lChunkMap[dc->refs[j]->name],
dc->address + dc->refs[j]->ibase); // dc->address + dc->refs[j]->ibase);
} // }
} // }
} // }
} // }
/* Resolve references. */ // /* Resolve references. */
for (Size i = 0; i < chunks.size(); i++) { // for (Size i = 0; i < chunks.size(); i++) {
DataChunk *dc = chunks[i]; // DataChunk *dc = chunks[i];
for (Size j = 0; j < dc->refs.size(); j++) { // for (Size j = 0; j < dc->refs.size(); j++) {
Ref &ref = *(dc->refs[j]); // Ref &ref = *(dc->refs[j]);
if (!ref.bound && (gChunkMap.find(ref.name) != gChunkMap.end())) { // if (!ref.bound && (gChunkMap.find(ref.name) != gChunkMap.end())) {
ref.bind(gChunkMap[ref.name], dc->address + ref.ibase); // ref.bind(gChunkMap[ref.name], dc->address + ref.ibase);
} else if (!ref.bound && mustResolveRefs) { // } else if (!ref.bound && mustResolveRefs) {
cout << "Undefined symbol: \"" << ref.name << "\"\n"; // cout << "Undefined symbol: \"" << ref.name << "\"\n";
exit(1); // exit(1);
} // }
} // }
} // }
/* Write out the chunks. */ // /* Write out the chunks. */
ofstream outFile(outFileName.c_str()); // ofstream outFile(outFileName.c_str());
for (Size i = 0; i < chunks.size(); i++) { // for (Size i = 0; i < chunks.size(); i++) {
if (outFile.tellp() > chunks[i]->address - binOffset) { // if (outFile.tellp() > chunks[i]->address - binOffset) {
cout << "Linker internal error. Wrote past next chunk address.\n"; // cout << "Linker internal error. Wrote past next chunk address.\n";
exit(1); // exit(1);
} // }
while (outFile.tellp() < chunks[i]->address - binOffset) outFile.put('\0'); // while (outFile.tellp() < chunks[i]->address - binOffset) outFile.put('\0');
outFile.seekp(chunks[i]->address - binOffset); // outFile.seekp(chunks[i]->address - binOffset);
outFile.write((char*)&chunks[i]->contents[0], chunks[i]->contents.size()); // outFile.write((char*)&chunks[i]->contents[0], chunks[i]->contents.size());
} // }
/* Clean up. */ // /* Clean up. */
for (Size i = 0; i < nObjects; i++) delete objects[i]; // for (Size i = 0; i < nObjects; i++) delete objects[i];
return 0; return 0;
} }

View File

@@ -51,6 +51,17 @@ namespace Harp {
private: private:
Size n, o, r, p, i1, i2, i3; Size n, o, r, p, i1, i2, i3;
Word oMask, rMask, pMask, i1Mask, i2Mask, i3Mask; Word oMask, rMask, pMask, i1Mask, i2Mask, i3Mask;
// FARES
Size inst_s, opcode_s, reg_s, func3_s;
Size shift_opcode, shift_rd, shift_rs1, shift_rs2, shift_func3, shift_func7;
Size shift_j_u_immed, shift_s_b_immed, shift_i_immed;
Word reg_mask, func3_mask, func7_mask, opcode_mask, i_immed_mask,
s_immed_mask, b_immed_mask, u_immed_mask, j_immed_mask;
}; };
class ByteDecoder : public Decoder { class ByteDecoder : public Decoder {

View File

@@ -4,6 +4,7 @@
#ifndef __INSTRUCTION_H #ifndef __INSTRUCTION_H
#define __INSTRUCTION_H #define __INSTRUCTION_H
#include <map>
#include <iostream> #include <iostream>
#include "types.h" #include "types.h"
@@ -24,34 +25,52 @@ namespace Harp {
class Instruction { class Instruction {
public: public:
enum Opcode { NOP, DI, EI, TLBADD, TLBFLUSH, NEG, NOT, AND, enum Opcode
OR, XOR, ADD, SUB, MUL, DIV, MOD, SHL, {
SHR, ANDI, ORI, XORI, ADDI, SUBI, MULI, DIVI, NOP = 0,
MODI, SHLI, SHRI, JALI, JALR, JMPI, JMPR, CLONE, R_INST = 51,
JALIS, JALRS, JMPRT, LD, ST, LDI, RTOP, ANDP, L_INST = 3,
ORP, XORP, NOTP, ISNEG, ISZERO, HALT, TRAP, JMPRU, I_INST = 19,
SKEP, RETI, TLBRM, ITOF, FTOI, FADD, FSUB, FMUL, S_INST = 35,
FDIV, FNEG, WSPAWN, SPLIT, JOIN, BAR }; B_INST = 99,
enum ArgClass { LUI_INST = 55,
AC_NONE, AC_2REG, AC_2IMM, AC_3REG, AC_3PREG, AC_3IMM, AC_3REGSRC, AUIPC_INST = 23,
AC_1IMM, AC_1REG, AC_3IMMSRC, AC_PREG_REG, AC_2PREG, AC_2REGSRC JAL_INST = 111,
}; JALR_INST = 103,
enum InstType { SYS_INST = 115
ITYPE_NULL, ITYPE_INTBASIC, ITYPE_INTMUL, ITYPE_INTDIV, ITYPE_STACK, ITYPE_BR, };
ITYPE_CALL, ITYPE_RET, ITYPE_TRAP, ITYPE_FPBASIC, ITYPE_FPMUL, ITYPE_FPDIV
}; enum InstType { N_TYPE, R_TYPE, I_TYPE, S_TYPE, B_TYPE, U_TYPE, J_TYPE };
// We build a table of instruction information out of this. // We build a table of instruction information out of this.
static struct InstTableEntry { struct InstTableEntry_t {
const char *opString; const char *opString;
bool controlFlow, relAddress, allSrcArgs, privileged; bool controlFlow, relAddress, allSrcArgs, privileged;
ArgClass argClass;
InstType iType; InstType iType;
} instTable[];
};
Instruction() : Instruction() :
predicated(false), nRsrc(0), nPsrc(0), immsrcPresent(false), predicated(false), nRsrc(0), nPsrc(0), immsrcPresent(false),
rdestPresent(false), pdestPresent(false), refLiteral(NULL) {} rdestPresent(false), pdestPresent(false), refLiteral(NULL)
{
instTable = std::map<int, struct InstTableEntry_t>
{
{Opcode::NOP, {"nop" , false, false, false, false, InstType::N_TYPE }},
{Opcode::R_INST, {"r_type", false, false, false, false, InstType::R_TYPE }},
{Opcode::L_INST, {"load" , false, false, false, false, InstType::I_TYPE }},
{Opcode::I_INST, {"i_type", false, false, false, false, InstType::I_TYPE }},
{Opcode::S_INST, {"store" , false, false, false, false, InstType::I_TYPE }},
{Opcode::B_INST, {"branch", true , false, false, false, InstType::B_TYPE }},
{Opcode::LUI_INST, {"lui" , false, false, false, false, InstType::U_TYPE }},
{Opcode::AUIPC_INST, {"auipc" , false, false, false, false, InstType::U_TYPE }},
{Opcode::JAL_INST, {"jal" , true , false, false, false, InstType::J_TYPE }},
{Opcode::JALR_INST, {"jalr" , true , false, false, false, InstType::I_TYPE }},
{Opcode::SYS_INST, {"SYS" , true , false, false, false, InstType::I_TYPE }}
};
}
void executeOn(Warp &warp); void executeOn(Warp &warp);
friend std::ostream &operator<<(std::ostream &, Instruction &); friend std::ostream &operator<<(std::ostream &, Instruction &);
@@ -61,6 +80,8 @@ namespace Harp {
void setPred (RegNum pReg) { predicated = true; pred = pReg; } void setPred (RegNum pReg) { predicated = true; pred = pReg; }
void setDestReg (RegNum destReg) { rdestPresent = true; rdest = destReg; } void setDestReg (RegNum destReg) { rdestPresent = true; rdest = destReg; }
void setSrcReg (RegNum srcReg) { rsrc[nRsrc++] = srcReg; } void setSrcReg (RegNum srcReg) { rsrc[nRsrc++] = srcReg; }
void setFunc3 (Word func3) { this->func3 = func3; }
void setFunc7 (Word func7) { this->func7 = func7; }
void setDestPReg(RegNum dPReg) { pdestPresent = true; pdest = dPReg; } void setDestPReg(RegNum dPReg) { pdestPresent = true; pdest = dPReg; }
void setSrcPReg (RegNum srcPReg) { psrc[nPsrc++] = srcPReg; } void setSrcPReg (RegNum srcPReg) { psrc[nPsrc++] = srcPReg; }
Word *setSrcImm () { immsrcPresent = true; immsrc = 0xa5; return &immsrc;} Word *setSrcImm () { immsrcPresent = true; immsrc = 0xa5; return &immsrc;}
@@ -85,7 +106,7 @@ namespace Harp {
Ref *getRefLiteral() const { return refLiteral; } Ref *getRefLiteral() const { return refLiteral; }
/* Getters used as table lookup. */ /* Getters used as table lookup. */
bool hasRelImm() const { return instTable[op].relAddress; } bool hasRelImm() const { return (*(instTable.find(op))).second.relAddress; }
private: private:
bool predicated; bool predicated;
@@ -95,10 +116,22 @@ namespace Harp {
RegNum rsrc[MAX_REG_SOURCES], psrc[MAX_PRED_SOURCES]; RegNum rsrc[MAX_REG_SOURCES], psrc[MAX_PRED_SOURCES];
bool immsrcPresent; bool immsrcPresent;
Word immsrc; Word immsrc;
Word func3;
Word func7;
bool rdestPresent, pdestPresent; bool rdestPresent, pdestPresent;
RegNum rdest, pdest; RegNum rdest, pdest;
Ref *refLiteral; Ref *refLiteral;
public:
static std::map<int, struct InstTableEntry_t> instTable;
}; };
}; };
#endif #endif
// static struct InstTableEntry {
// const char *opString;
// bool controlFlow, relAddress, allSrcArgs, privileged;
// InstType iType;
// };

View File

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

View File

@@ -20,93 +20,28 @@ using namespace std;
/* It is important that this stays consistent with the Harp::Instruction::Opcode /* It is important that this stays consistent with the Harp::Instruction::Opcode
enum. */ enum. */
Instruction::InstTableEntry Instruction::instTable[] = {
//str cflow relad allsrc priv argcl itype
{"nop", false, false, false, false, AC_NONE, ITYPE_NULL },
{"di", false, false, false, true, AC_NONE, ITYPE_NULL },
{"ei", false, false, false, true, AC_NONE, ITYPE_NULL },
{"tlbadd", false, false, true, true, AC_3REGSRC, ITYPE_NULL },
{"tlbflush", false, false, false, true, AC_NONE, ITYPE_NULL },
{"neg", false, false, false, false, AC_2REG, ITYPE_INTBASIC},
{"not", false, false, false, false, AC_2REG, ITYPE_INTBASIC},
{"and", false, false, false, false, AC_3REG, ITYPE_INTBASIC},
{"or", false, false, false, false, AC_3REG, ITYPE_INTBASIC},
{"xor", false, false, false, false, AC_3REG, ITYPE_INTBASIC},
{"add", false, false, false, false, AC_3REG, ITYPE_INTBASIC},
{"sub", false, false, false, false, AC_3REG, ITYPE_INTBASIC},
{"mul", false, false, false, false, AC_3REG, ITYPE_INTMUL },
{"div", false, false, false, false, AC_3REG, ITYPE_INTDIV },
{"mod", false, false, false, false, AC_3REG, ITYPE_INTDIV },
{"shl", false, false, false, false, AC_3REG, ITYPE_INTBASIC},
{"shr", false, false, false, false, AC_3REG, ITYPE_INTBASIC},
{"andi", false, false, false, false, AC_3IMM, ITYPE_INTBASIC},
{"ori", false, false, false, false, AC_3IMM, ITYPE_INTBASIC},
{"xori", false, false, false, false, AC_3IMM, ITYPE_INTBASIC},
{"addi", false, false, false, false, AC_3IMM, ITYPE_INTBASIC},
{"subi", false, false, false, false, AC_3IMM, ITYPE_INTBASIC},
{"muli", false, false, false, false, AC_3IMM, ITYPE_INTMUL },
{"divi", false, false, false, false, AC_3IMM, ITYPE_INTDIV },
{"modi", false, false, false, false, AC_3IMM, ITYPE_INTDIV },
{"shli", false, false, false, false, AC_3IMM, ITYPE_INTBASIC},
{"shri", false, false, false, false, AC_3IMM, ITYPE_INTBASIC},
{"jali", true, true, false, false, AC_2IMM, ITYPE_CALL },
{"jalr", true, false, false, false, AC_2REG, ITYPE_CALL },
{"jmpi", true, true, true, false, AC_1IMM, ITYPE_BR },
{"jmpr", true, false, true, false, AC_1REG, ITYPE_RET },
{"clone", true, false, false, false, AC_1REG, ITYPE_NULL },
{"jalis", true, true, false, false, AC_3IMM, ITYPE_CALL },
{"jalrs", true, false, false, false, AC_3REG, ITYPE_CALL },
{"jmprt", true, false, true, false, AC_1REG, ITYPE_RET },
{"ld", false, false, false, false, AC_3IMM, ITYPE_NULL },
{"st", false, false, true, false, AC_3IMMSRC, ITYPE_NULL },
{"ldi", false, false, false, false, AC_2IMM, ITYPE_NULL },
{"rtop", false, false, false, false, AC_PREG_REG, ITYPE_NULL },
{"andp", false, false, false, false, AC_3PREG, ITYPE_INTBASIC},
{"orp", false, false, false, false, AC_3PREG, ITYPE_INTBASIC},
{"xorp", false, false, false, false, AC_3PREG, ITYPE_INTBASIC},
{"notp", false, false, false, false, AC_2PREG, ITYPE_INTBASIC},
{"isneg", false, false, false, false, AC_PREG_REG, ITYPE_INTBASIC},
{"iszero", false, false, false, false, AC_PREG_REG, ITYPE_INTBASIC},
{"halt", false, false, false, false, AC_NONE, ITYPE_NULL },
{"trap", true, false, false, false, AC_NONE, ITYPE_TRAP },
{"jmpru", false, false, false, true, AC_1REG, ITYPE_RET },
{"skep", false, false, false, true, AC_1REG, ITYPE_NULL },
{"reti", true, false, false, true, AC_NONE, ITYPE_RET },
{"tlbrm", false, false, false, true, AC_1REG, ITYPE_NULL },
{"itof", false, false, false, false, AC_2REG, ITYPE_FPBASIC },
{"ftoi", false, false, false, false, AC_2REG, ITYPE_FPBASIC },
{"fadd", false, false, false, false, AC_3REG, ITYPE_FPBASIC },
{"fsub", false, false, false, false, AC_3REG, ITYPE_FPBASIC },
{"fmul", false, false, false, false, AC_3REG, ITYPE_FPMUL },
{"fdiv", false, false, false, false, AC_3REG, ITYPE_FPDIV },
{"fneg", false, false, false, false, AC_2REG, ITYPE_FPBASIC },
{"wspawn", false, false, true, false, AC_3REG, ITYPE_NULL },
{"split", false, false, true, false, AC_NONE, ITYPE_NULL },
{"join", false, false, true, false, AC_NONE, ITYPE_NULL },
{"bar", false, false, true, false, AC_2REGSRC, ITYPE_NULL },
{NULL,false,false,false,false,AC_NONE,ITYPE_NULL}/////// End of table.
};
ostream &Harp::operator<<(ostream& os, Instruction &inst) { ostream &Harp::operator<<(ostream& os, Instruction &inst) {
os << dec; os << dec;
if (inst.predicated) { // if (inst.predicated) {
os << "@p" << dec << inst.pred << " ? "; // os << "@p" << dec << inst.pred << " ? ";
} // }
os << Instruction::instTable[inst.op].opString << ' '; // os << inst.instTable[inst.op].opString << ' ';
if (inst.rdestPresent) os << "%r" << dec << inst.rdest << ' '; // if (inst.rdestPresent) os << "%r" << dec << inst.rdest << ' ';
if (inst.pdestPresent) os << "@p" << inst.pdest << ' '; // if (inst.pdestPresent) os << "@p" << inst.pdest << ' ';
for (int i = 0; i < inst.nRsrc; i++) { // for (int i = 0; i < inst.nRsrc; i++) {
os << "%r" << dec << inst.rsrc[i] << ' '; // os << "%r" << dec << inst.rsrc[i] << ' ';
} // }
for (int i = 0; i < inst.nPsrc; i++) { // for (int i = 0; i < inst.nPsrc; i++) {
os << "@p" << dec << inst.psrc[i] << ' '; // os << "@p" << dec << inst.psrc[i] << ' ';
} // }
if (inst.immsrcPresent) { // if (inst.immsrcPresent) {
if (inst.refLiteral) os << inst.refLiteral->name; // if (inst.refLiteral) os << inst.refLiteral->name;
else os << "#0x" << hex << inst.immsrc; // else os << "#0x" << hex << inst.immsrc;
} // }
os << inst.instTable[inst.op].opString;
os << ';'; os << ';';
return os; return os;
@@ -134,6 +69,11 @@ bool checkUnanimous(unsigned p, const std::vector<std::vector<Reg<bool> > >& m,
return true; return true;
} }
Word signExt(Word w, Size bit, Word mask) {
if (w>>(bit-1)) w |= ~mask;
return w;
}
void Instruction::executeOn(Warp &c) { void Instruction::executeOn(Warp &c) {
D(3, "Begin instruction execute."); D(3, "Begin instruction execute.");
@@ -165,7 +105,7 @@ void Instruction::executeOn(Warp &c) {
// If we have a load, overwriting a register's contents, we have to make sure // If we have a load, overwriting a register's contents, we have to make sure
// ahead of time it will not fault. Otherwise we may perform an indirect load // ahead of time it will not fault. Otherwise we may perform an indirect load
// by mistake. // by mistake.
if (op == LD && rdest == rsrc[0]) { if (op == L_INST && rdest == rsrc[0]) {
for (Size t = 0; t < c.activeThreads; t++) { for (Size t = 0; t < c.activeThreads; t++) {
if ((!predicated || c.pred[t][pred]) && c.tmask[t]) { if ((!predicated || c.pred[t][pred]) && c.tmask[t]) {
Word memAddr = c.reg[t][rsrc[0]] + immsrc; Word memAddr = c.reg[t][rsrc[0]] + immsrc;
@@ -183,261 +123,341 @@ void Instruction::executeOn(Warp &c) {
// If this thread is masked out, don't execute the instruction, unless it's // If this thread is masked out, don't execute the instruction, unless it's
// a split or join. // a split or join.
if (((predicated && !pReg[pred]) || !c.tmask[t]) && // if (((predicated && !pReg[pred]) || !c.tmask[t]) &&
op != SPLIT && op != JOIN) continue; // op != SPLIT && op != JOIN) continue;
++c.insts; ++c.insts;
Word memAddr; Word memAddr;
Word shift_by;
switch (op) { switch (op) {
case NOP: break; case NOP: break;
case DI: c.interruptEnable = false; case R_INST:
break; switch (func3)
case EI: c.interruptEnable = true; {
break; case 0:
case TLBADD: c.core->mem.tlbAdd(reg[rsrc[0]], reg[rsrc[1]], reg[rsrc[2]]); if (func7)
break; {
case TLBFLUSH: c.core->mem.tlbFlush(); reg[rdest] = reg[rsrc[0]] - reg[rsrc[1]];
break;
case ADD: reg[rdest] = reg[rsrc[0]] + reg[rsrc[1]];
reg[rdest].trunc(wordSz); reg[rdest].trunc(wordSz);
break; }
case SUB: reg[rdest] = reg[rsrc[0]] - reg[rsrc[1]]; else
{
reg[rdest] = reg[rsrc[0]] + reg[rsrc[1]];
reg[rdest].trunc(wordSz); reg[rdest].trunc(wordSz);
break; }
case MUL: reg[rdest] = reg[rsrc[0]] * reg[rsrc[1]]; break;
case 1:
reg[rdest] = reg[rsrc[0]] << reg[rsrc[1]];
reg[rdest].trunc(wordSz); reg[rdest].trunc(wordSz);
break; break;
case DIV: if (reg[rsrc[1]] == 0) throw DomainException(); case 2:
reg[rdest] = reg[rsrc[0]] / reg[rsrc[1]]; if ( Word_s(reg[rsrc[0]]) < Word_s(reg[rsrc[1]]))
break; {
case SHL: reg[rdest] = reg[rsrc[0]] << reg[rsrc[1]]; reg[rdest] = 1;
}
else
{
reg[rdest] = 0;
}
break;
case 3:
if ( Word_u(reg[rsrc[0]]) < Word_u(reg[rsrc[1]]))
{
reg[rdest] = 1;
}
else
{
reg[rdest] = 0;
}
break;
case 4:
reg[rdest] = reg[rsrc[0]] ^ reg[rsrc[1]];
break;
case 5:
if (func7)
{
reg[rdest] = Word_s(reg[rsrc[0]]) >> Word_s(reg[rsrc[1]]);
reg[rdest].trunc(wordSz); reg[rdest].trunc(wordSz);
break; }
case SHR: reg[rdest] = Word_s(reg[rsrc[0]]) >> reg[rsrc[1]]; else
{
reg[rdest] = Word_u(reg[rsrc[0]]) >> Word_u(reg[rsrc[1]]);
reg[rdest].trunc(wordSz); reg[rdest].trunc(wordSz);
break; }
case MOD: if (reg[rsrc[1]] == 0) throw DomainException(); break;
reg[rdest] = reg[rsrc[0]] % reg[rsrc[1]]; case 6:
break; reg[rdest] = reg[rsrc[0]] | reg[rsrc[1]];
case AND: reg[rdest] = reg[rsrc[0]] & reg[rsrc[1]]; break;
break; case 7:
case OR: reg[rdest] = reg[rsrc[0]] | reg[rsrc[1]]; reg[rdest] = reg[rsrc[0]] & reg[rsrc[1]];
break; break;
case XOR: reg[rdest] = reg[rsrc[0]] ^ reg[rsrc[1]]; default:
break; cout << "ERROR: UNSUPPORTED R INST\n";
case NEG: reg[rdest] = -(Word_s)reg[rsrc[0]]; exit(1);
reg[rdest].trunc(wordSz); }
break; break;
case NOT: reg[rdest] = ~(Word_s)reg[rsrc[0]];
reg[rdest].trunc(wordSz); case L_INST:
break; memAddr = (reg[rsrc[0]] + immsrc) & 0xFFFFFF00;
case ADDI: reg[rdest] = reg[rsrc[0]] + immsrc; shift_by = (reg[rsrc[0]] + immsrc) & 0x000000FF;
reg[rdest].trunc(wordSz);
break;
case SUBI: reg[rdest] = reg[rsrc[0]] - immsrc;
reg[rdest].trunc(wordSz);
break;
case MULI: reg[rdest] = reg[rsrc[0]] * immsrc;
reg[rdest].trunc(wordSz);
break;
case DIVI: if (immsrc == 0) throw DomainException();
reg[rdest] = reg[rsrc[0]] / immsrc;
break;
case MODI: if (immsrc == 0) throw DomainException();
reg[rdest] = reg[rsrc[0]] % immsrc;
break;
case SHRI: reg[rdest] = Word_s(reg[rsrc[0]]) >> immsrc;
break;
case SHLI: reg[rdest] = reg[rsrc[0]] << immsrc;
reg[rdest].trunc(wordSz);
break;
case ANDI: reg[rdest] = reg[rsrc[0]] & immsrc;
break;
case ORI: reg[rdest] = reg[rsrc[0]] | immsrc;
break;
case XORI: reg[rdest] = reg[rsrc[0]] ^ immsrc;
break;
case JMPI: if (!pcSet) nextPc = c.pc + immsrc;
pcSet = true;
break;
case JALI: reg[rdest] = c.pc;
if (!pcSet) nextPc = c.pc + immsrc;
pcSet = true;
break;
case JALR: reg[rdest] = c.pc;
if (!pcSet) nextPc = reg[rsrc[0]];
pcSet = true;
break;
case JMPR: if (!pcSet) nextPc = reg[rsrc[0]];
pcSet = true;
break;
case CLONE: c.reg[reg[rsrc[0]]] = reg;
break;
case JALIS: nextActiveThreads = reg[rsrc[0]];
reg[rdest] = c.pc;
if (!pcSet) nextPc = c.pc + immsrc;
pcSet = true;
break;
case JALRS: nextActiveThreads = reg[rsrc[0]];
reg[rdest] = c.pc;
if (!pcSet) nextPc = reg[rsrc[1]];
pcSet = true;
break;
case JMPRT: nextActiveThreads = 1;
if (!pcSet) nextPc = reg[rsrc[0]];
pcSet = true;
break;
case LD: ++c.loads;
memAddr = reg[rsrc[0]] + immsrc;
#ifdef EMU_INSTRUMENTATION #ifdef EMU_INSTRUMENTATION
Harp::OSDomain::osDomain-> Harp::OSDomain::osDomain->
do_mem(0, memAddr, c.core->mem.virtToPhys(memAddr), 8, true); do_mem(0, memAddr, c.core->mem.virtToPhys(memAddr), 8, true);
#endif #endif
reg[rdest] = c.core->mem.read(memAddr, c.supervisorMode); switch (func3)
c.memAccesses.push_back(Warp::MemAccess(false, memAddr)); {
break;
case ST: ++c.stores;
memAddr = reg[rsrc[1]] + immsrc;
c.core->mem.write(memAddr, reg[rsrc[0]], c.supervisorMode);
c.memAccesses.push_back(Warp::MemAccess(true, memAddr));
#ifdef EMU_INSTRUMENTATION
Harp::OSDomain::osDomain->
do_mem(0, memAddr, c.core->mem.virtToPhys(memAddr), 8, true);
#endif
break;
case LDI: reg[rdest] = immsrc;
reg[rdest].trunc(wordSz);
break;
case RTOP: pReg[pdest] = reg[rsrc[0]];
break;
case ISZERO: pReg[pdest] = !reg[rsrc[0]];
break;
case NOTP: pReg[pdest] = !(pReg[psrc[0]]);
break;
case ANDP: pReg[pdest] = pReg[psrc[0]] & pReg[psrc[1]];
break;
case ORP: pReg[pdest] = pReg[psrc[0]] | pReg[psrc[1]];
break;
case XORP: pReg[pdest] = pReg[psrc[0]] != pReg[psrc[1]];
break;
case ISNEG: pReg[pdest] = (1ll<<(wordSz*8 - 1))&reg[rsrc[0]];
break;
case HALT: c.activeThreads = 0;
nextActiveThreads = 0;
break;
case TRAP: c.interrupt(0);
break;
case JMPRU: c.supervisorMode = false;
if (!pcSet) nextPc = reg[rsrc[0]];
pcSet = true;
break;
case SKEP: c.core->interruptEntry = reg[rsrc[0]];
break;
case RETI: if (t == 0) {
c.tmask = c.shadowTmask;
nextActiveThreads = c.shadowActiveThreads;
c.interruptEnable = c.shadowInterruptEnable;
c.supervisorMode = c.shadowSupervisorMode;
for (unsigned i = 0; i < reg.size(); ++i)
reg[i] = c.shadowReg[i];
for (unsigned i = 0; i < pReg.size(); ++i)
pReg[i] = c.shadowPReg[i];
if (!pcSet) { nextPc = c.shadowPc; pcSet = true; }
}
break;
case ITOF: reg[rdest] = Float(double(Word_s(reg[rsrc[0]])), wordSz);
break;
case FTOI: reg[rdest] = Word_s(double(Float(reg[rsrc[0]], wordSz)));
reg[rdest].trunc(wordSz);
break;
case FNEG: reg[rdest] = Float(-double(Float(reg[rsrc[0]],wordSz)),wordSz);
break;
case FADD: reg[rdest] = Float(double(Float(reg[rsrc[0]], wordSz)) +
double(Float(reg[rsrc[1]], wordSz)),wordSz);
break;
case FSUB: reg[rdest] = Float(double(Float(reg[rsrc[0]], wordSz)) -
double(Float(reg[rsrc[1]], wordSz)),wordSz);
break;
case FMUL: reg[rdest] = Float(double(Float(reg[rsrc[0]], wordSz)) *
double(Float(reg[rsrc[1]], wordSz)),wordSz);
break;
case FDIV: reg[rdest] = Float(double(Float(reg[rsrc[0]], wordSz)) /
double(Float(reg[rsrc[1]], wordSz)),wordSz);
break;
case SPLIT: if (sjOnce) {
sjOnce = false;
if (checkUnanimous(pred, c.pred, c.tmask)) {
DomStackEntry e(c.tmask);
e.uni = true;
c.domStack.push(e);
break;
}
DomStackEntry e(pred, c.pred, c.tmask, c.pc);
c.domStack.push(c.tmask);
c.domStack.push(e);
for (unsigned i = 0; i < e.tmask.size(); ++i)
c.tmask[i] = !e.tmask[i] && c.tmask[i];
}
break;
case JOIN: if (sjOnce) {
sjOnce = false;
if (!c.domStack.empty() && c.domStack.top().uni) {
D(2, "Uni branch at join");
c.tmask = c.domStack.top().tmask;
c.domStack.pop();
break;
}
if (!c.domStack.top().fallThrough) {
if (!pcSet) nextPc = c.domStack.top().pc;
pcSet = true;
}
c.tmask = c.domStack.top().tmask;
c.domStack.pop();
}
break;
case WSPAWN: if (sjOnce) {
sjOnce = false;
D(0, "Spawning a new warp.");
for (unsigned i = 0; i < c.core->w.size(); ++i) {
Warp &newWarp(c.core->w[i]);
if (newWarp.spawned == false) {
newWarp.pc = reg[rsrc[0]];
newWarp.reg[0][rdest] = reg[rsrc[1]];
newWarp.activeThreads = 1;
newWarp.supervisorMode = false;
newWarp.spawned = true;
break;
}
}
}
break;
case BAR: if (sjOnce) {
sjOnce = false;
Word id(reg[rsrc[0]]), n(reg[rsrc[1]]);
set<Warp*> &b(c.core->b[id]);
// Add current warp to the barrier and halt.
b.insert(&c);
c.shadowActiveThreads = c.activeThreads;
nextActiveThreads = 0;
D(2, "Barrier " << id << ' ' << b.size() << " of " << n);
// If the barrier's full, reactivate warps waiting at it
if (b.size() == n) {
set<Warp*>::iterator it;
for (it = b.begin(); it != b.end(); ++it)
(*it)->activeThreads = (*it)->shadowActiveThreads;
c.core->b.erase(id);
nextActiveThreads = c.shadowActiveThreads;
}
}
break;
case 0:
// LB
reg[rdest] = signExt((c.core->mem.read(memAddr, c.supervisorMode) >> shift_by) & 0xFF, 8, 0xFF);
break;
case 1:
// LH
reg[rdest] = signExt((c.core->mem.read(memAddr, c.supervisorMode) >> shift_by) & 0xFFFF, 16, 0xFF);
break;
case 2:
reg[rdest] = Word_s(c.core->mem.read(memAddr, c.supervisorMode) & 0xFFFFFFFF);
break;
case 4:
// LBU
reg[rdest] = Word_u((c.core->mem.read(memAddr, c.supervisorMode) >> shift_by) & 0xFF);
break;
case 5:
reg[rdest] = Word_s((c.core->mem.read(memAddr, c.supervisorMode) >> shift_by) & 0xFFFF);
default:
cout << "ERROR: UNSUPPORTED L INST\n";
exit(1);
c.memAccesses.push_back(Warp::MemAccess(false, memAddr));
}
break;
case I_INST:
break;
case S_INST:
break;
case B_INST:
break;
case LUI_INST:
break;
case AUIPC_INST:
break;
case JAL_INST:
break;
case JALR_INST:
break;
case SYS_INST:
break;
default: default:
cout << "ERROR: Unsupported instruction: " << *this << "\n"; cout << "ERROR: Unsupported instruction: " << *this << "\n";
exit(1); exit(1);
// case SHL:
// break;
// case SHR:
// break;
// case ADDI: reg[rdest] = reg[rsrc[0]] + immsrc;
// reg[rdest].trunc(wordSz);
// break;
// case SUBI: reg[rdest] = reg[rsrc[0]] - immsrc;
// reg[rdest].trunc(wordSz);
// break;
// case SHRI: reg[rdest] = Word_s(reg[rsrc[0]]) >> immsrc;
// break;
// case SHLI: reg[rdest] = reg[rsrc[0]] << immsrc;
// reg[rdest].trunc(wordSz);
// break;
// case ANDI: reg[rdest] = reg[rsrc[0]] & immsrc;
// break;
// case ORI: reg[rdest] = reg[rsrc[0]] | immsrc;
// break;
// case XORI: reg[rdest] = reg[rsrc[0]] ^ immsrc;
// break;
// case JMPI: if (!pcSet) nextPc = c.pc + immsrc;
// pcSet = true;
// break;
// case JALI: reg[rdest] = c.pc;
// if (!pcSet) nextPc = c.pc + immsrc;
// pcSet = true;
// break;
// case JALR: reg[rdest] = c.pc;
// if (!pcSet) nextPc = reg[rsrc[0]];
// pcSet = true;
// break;
// case JMPR: if (!pcSet) nextPc = reg[rsrc[0]];
// pcSet = true;
// break;
// case JALIS: nextActiveThreads = reg[rsrc[0]];
// reg[rdest] = c.pc;
// if (!pcSet) nextPc = c.pc + immsrc;
// pcSet = true;
// break;
// case JALRS: nextActiveThreads = reg[rsrc[0]];
// reg[rdest] = c.pc;
// if (!pcSet) nextPc = reg[rsrc[1]];
// pcSet = true;
// break;
// case JMPRT: nextActiveThreads = 1;
// if (!pcSet) nextPc = reg[rsrc[0]];
// pcSet = true;
// break;
// case LD: ++c.loads;
// memAddr = reg[rsrc[0]] + immsrc;
// #ifdef EMU_INSTRUMENTATION
// Harp::OSDomain::osDomain->
// do_mem(0, memAddr, c.core->mem.virtToPhys(memAddr), 8, true);
// #endif
// reg[rdest] = c.core->mem.read(memAddr, c.supervisorMode);
// c.memAccesses.push_back(Warp::MemAccess(false, memAddr));
// break;
// case ST: ++c.stores;
// memAddr = reg[rsrc[1]] + immsrc;
// c.core->mem.write(memAddr, reg[rsrc[0]], c.supervisorMode);
// c.memAccesses.push_back(Warp::MemAccess(true, memAddr));
// #ifdef EMU_INSTRUMENTATION
// Harp::OSDomain::osDomain->
// do_mem(0, memAddr, c.core->mem.virtToPhys(memAddr), 8, true);
// #endif
// break;
// case LDI: reg[rdest] = immsrc;
// reg[rdest].trunc(wordSz);
// break;
// case RTOP: pReg[pdest] = reg[rsrc[0]];
// break;
// case ISZERO: pReg[pdest] = !reg[rsrc[0]];
// break;
// case NOTP: pReg[pdest] = !(pReg[psrc[0]]);
// break;
// case ANDP: pReg[pdest] = pReg[psrc[0]] & pReg[psrc[1]];
// break;
// case ORP: pReg[pdest] = pReg[psrc[0]] | pReg[psrc[1]];
// break;
// case XORP: pReg[pdest] = pReg[psrc[0]] != pReg[psrc[1]];
// break;
// case ISNEG: pReg[pdest] = (1ll<<(wordSz*8 - 1))&reg[rsrc[0]];
// break;
// case HALT: c.activeThreads = 0;
// nextActiveThreads = 0;
// break;
// case TRAP: c.interrupt(0);
// break;
// case JMPRU: c.supervisorMode = false;
// if (!pcSet) nextPc = reg[rsrc[0]];
// pcSet = true;
// break;
// case SKEP: c.core->interruptEntry = reg[rsrc[0]];
// break;
// case RETI: if (t == 0) {
// c.tmask = c.shadowTmask;
// nextActiveThreads = c.shadowActiveThreads;
// c.interruptEnable = c.shadowInterruptEnable;
// c.supervisorMode = c.shadowSupervisorMode;
// for (unsigned i = 0; i < reg.size(); ++i)
// reg[i] = c.shadowReg[i];
// for (unsigned i = 0; i < pReg.size(); ++i)
// pReg[i] = c.shadowPReg[i];
// if (!pcSet) { nextPc = c.shadowPc; pcSet = true; }
// }
// break;
// case ITOF: reg[rdest] = Float(double(Word_s(reg[rsrc[0]])), wordSz);
// break;
// case FTOI: reg[rdest] = Word_s(double(Float(reg[rsrc[0]], wordSz)));
// reg[rdest].trunc(wordSz);
// break;
// case FNEG: reg[rdest] = Float(-double(Float(reg[rsrc[0]],wordSz)),wordSz);
// break;
// case FADD: reg[rdest] = Float(double(Float(reg[rsrc[0]], wordSz)) +
// double(Float(reg[rsrc[1]], wordSz)),wordSz);
// break;
// case FSUB: reg[rdest] = Float(double(Float(reg[rsrc[0]], wordSz)) -
// double(Float(reg[rsrc[1]], wordSz)),wordSz);
// break;
// case FMUL: reg[rdest] = Float(double(Float(reg[rsrc[0]], wordSz)) *
// double(Float(reg[rsrc[1]], wordSz)),wordSz);
// break;
// case FDIV: reg[rdest] = Float(double(Float(reg[rsrc[0]], wordSz)) /
// double(Float(reg[rsrc[1]], wordSz)),wordSz);
// break;
// case SPLIT: if (sjOnce) {
// sjOnce = false;
// if (checkUnanimous(pred, c.pred, c.tmask)) {
// DomStackEntry e(c.tmask);
// e.uni = true;
// c.domStack.push(e);
// break;
// }
// DomStackEntry e(pred, c.pred, c.tmask, c.pc);
// c.domStack.push(c.tmask);
// c.domStack.push(e);
// for (unsigned i = 0; i < e.tmask.size(); ++i)
// c.tmask[i] = !e.tmask[i] && c.tmask[i];
// }
// break;
// case JOIN: if (sjOnce) {
// sjOnce = false;
// if (!c.domStack.empty() && c.domStack.top().uni) {
// D(2, "Uni branch at join");
// c.tmask = c.domStack.top().tmask;
// c.domStack.pop();
// break;
// }
// if (!c.domStack.top().fallThrough) {
// if (!pcSet) nextPc = c.domStack.top().pc;
// pcSet = true;
// }
// c.tmask = c.domStack.top().tmask;
// c.domStack.pop();
// }
// break;
// case WSPAWN: if (sjOnce) {
// sjOnce = false;
// D(0, "Spawning a new warp.");
// for (unsigned i = 0; i < c.core->w.size(); ++i) {
// Warp &newWarp(c.core->w[i]);
// if (newWarp.spawned == false) {
// newWarp.pc = reg[rsrc[0]];
// newWarp.reg[0][rdest] = reg[rsrc[1]];
// newWarp.activeThreads = 1;
// newWarp.supervisorMode = false;
// newWarp.spawned = true;
// break;
// }
// }
// }
// break;
// case BAR: if (sjOnce) {
// sjOnce = false;
// Word id(reg[rsrc[0]]), n(reg[rsrc[1]]);
// set<Warp*> &b(c.core->b[id]);
// // Add current warp to the barrier and halt.
// b.insert(&c);
// c.shadowActiveThreads = c.activeThreads;
// nextActiveThreads = 0;
// D(2, "Barrier " << id << ' ' << b.size() << " of " << n);
// // If the barrier's full, reactivate warps waiting at it
// if (b.size() == n) {
// set<Warp*>::iterator it;
// for (it = b.begin(); it != b.end(); ++it)
// (*it)->activeThreads = (*it)->shadowActiveThreads;
// c.core->b.erase(id);
// nextActiveThreads = c.shadowActiveThreads;
// }
// }
// break;
// default:
// cout << "ERROR: Unsupported instruction: " << *this << "\n";
// exit(1);
} }
} }

File diff suppressed because it is too large Load Diff