📄 instrumenttype.cpp
字号:
#include "StdAfx.h"
#include "InstrumentType.h"
#include "CompilingErrorException.h"
#include <fstream>
#include <sstream>
#include <iostream>
map<string, InstrumentInformation>& InstrumentType::infoTable = InitInfoTable();
#ifndef AddOperation
#define AddOperation(name) if (infoTable.find(#name) != infoTable.end()) infoTable[#name].operation=&ALUOp::name
#endif
#ifndef AddOperation2
#define AddOperation2(name) if (infoTable.find(LToD(#name)) != infoTable.end()) infoTable[LToD(#name)].operation=&ALUOp::name
#endif
string LToD(const char* s){
string ret;
for (unsigned i = 0; s[i] != '\0'; ++i) ret += (s[i] == '_') ? '.' : s[i];
return ret;
}
InstrumentType::InstrumentType(void){
ifstream fin("Lable.ini");
string word;
while (fin >> word){
lableInstrument.insert(word);
}
zeroExtendInstrument.insert("andi");
zeroExtendInstrument.insert("ori");
}
map<string, InstrumentInformation>& InstrumentType::InitInfoTable(string ininame){
map<string, InstrumentInformation>& infoTable = *(new map<string, InstrumentInformation>);
ifstream fin(ininame.c_str());
InstrumentInformation item;
while(fin >> item.name){
string s;
item.encoding = "";
for (int i = 0; i < 8; ++i){
fin >> s;
item.encoding += s;
}
fin >> item.syntax;
fin >> item.com;
infoTable[item.name] = item;
}
AddOperation(add);
AddOperation(addi);
AddOperation(addiu);
AddOperation(addu);
AddOperation(and);
AddOperation(andi);
AddOperation(beq);
AddOperation(bgez);
AddOperation(bgezal);
AddOperation(bgtz);
AddOperation(blez);
AddOperation(bltz);
AddOperation(bltzal);
AddOperation(bne);
AddOperation(div);
AddOperation(divu);
AddOperation(j);
AddOperation(jal);
AddOperation(jr);
AddOperation(lb);
AddOperation(lui);
AddOperation(lw);
AddOperation(mfhi);
AddOperation(mflo);
AddOperation(mult);
AddOperation(multu);
AddOperation(noop);
AddOperation(or);
AddOperation(ori);
AddOperation(sb);
AddOperation(sll);
AddOperation(sllv);
AddOperation(slt);
AddOperation(slti);
AddOperation(sltiu);
AddOperation(sltu);
AddOperation(sra);
AddOperation(srl);
AddOperation(srlv);
AddOperation(sub);
AddOperation(subu);
AddOperation(sw);
AddOperation(syscall);
AddOperation(xor);
AddOperation(xori);
AddOperation2(swcl);
AddOperation2(sdcl);
AddOperation2(add_s);
AddOperation2(add_d);
AddOperation2(div_s);
AddOperation2(div_d);
AddOperation2(mul_s);
AddOperation2(mul_d);
AddOperation2(sub_s);
AddOperation2(sub_d);
AddOperation2(bclt);
AddOperation2(bclf);
AddOperation2(c_eq_s);
AddOperation2(c_eq_d);
AddOperation2(c_lt_s);
AddOperation2(c_lt_d);
AddOperation2(c_le_s);
AddOperation2(c_le_d);
AddOperation(mfc0);
AddOperation(mfc1);
AddOperation(mtc0);
AddOperation(mtc1);
return infoTable;
}
// return the num of arguments of given instrument.
int InstrumentType::ArgumentNumOfInstrument(string name){
if (name == "syscall" || name == "noop" || name == "nop") return 0;
return infoTable[name].syntax.length();
}
void InstrumentType::SetAsmCode(vector<string>& asmCode){
AsmCode = asmCode;
InstrumentInformation &info = infoCurrentSentence;
info = infoTable[asmCode[0]];
for (int j = 0; j < ArgumentNumOfInstrument(info.name); ++j){
switch (info.syntax[j]){
case 'd': d = RegisterToInt(asmCode[j + 1], info.com[0]); break;
case 's': s = RegisterToInt(asmCode[j + 1], info.com[1]); break;
case 't': t = RegisterToInt(asmCode[j + 1], info.com[2]); break;
case 'i': i = StringToInt(asmCode[j + 1]); break;
case 'h': h = StringToInt(asmCode[j + 1]); break;
}
}
int si = 0;
for (int j = 0; j < 32; ++j) if (info.encoding[j] == 'i') ++si;
i = extend(i, si, info.name);
TranslateAsmToBinary();
}
bool InstrumentType::equal(string a, string b){
if (a.length() != b.length()) return false;
for (unsigned i = 0; i < a.length(); ++i)
if (a[i] != b[i] && (a[i] == '0' || a[i] == '1' )) return false;
return true;
}
void InstrumentType::SetBinaryCode(string& binaryCode){
// TODO parser d, s, t, i, h
map<string, InstrumentInformation>::iterator item;
BinaryCode = binaryCode;
d = s = t = i = h = 0;
int si = 0;
for(item = infoTable.begin(); item != infoTable.end(); ++item)
if (equal(item->second.encoding, binaryCode)) break;
if (item == infoTable.end()) throw CompilingErrorException("Unknow binary instrument.");
infoCurrentSentence = item->second;
for (int j = 0; j < 32; ++j){
switch(infoCurrentSentence.encoding[j]){
case 'd': d = d * 2 + binaryCode[j] - '0'; break;
case 's': s = s * 2 + binaryCode[j] - '0'; break;
case 't': t = t * 2 + binaryCode[j] - '0'; break;
case 'h': h = h * 2 + binaryCode[j] - '0'; break;
case 'i': i = i * 2 + binaryCode[j] - '0'; ++si; break;
}
}
i = extend(i, si, infoCurrentSentence.name);
TranslateBinaryToCode();
TranslateBinaryToAsm();
}
int InstrumentType::extend(int immValue, int length, string& name){
if (length && name != "j" && name != "jal" && name != "andi" && name != "ori" && name != "xori"){
if (immValue & (1 << (length - 1))){
for (int i = length; i < 32; ++i) immValue &= 1 << i;
}
}
return immValue;
}
string InstrumentType::TranslateAsmToBinary(){
// TODO
int d = this->d;
int s = this->s;
int t = this->t;
int i = this->i;
int h = this->h;
InstrumentInformation &info = infoCurrentSentence;
BinaryCode = info.encoding;
for (int j = 31; j >= 0; --j){
switch(info.encoding[j]){
case '-': BinaryCode[j] = '0'; break;
case 'd': BinaryCode[j] = (d & 1) ? '1' : '0'; d >>= 1; break;
case 's': BinaryCode[j] = (s & 1) ? '1' : '0'; s >>= 1; break;
case 't': BinaryCode[j] = (t & 1) ? '1' : '0'; t >>= 1; break;
case 'h': BinaryCode[j] = (h & 1) ? '1' : '0'; h >>= 1; break;
case 'i': BinaryCode[j] = (i & 1) ? '1' : '0'; i >>= 1; break;
}
}
TranslateBinaryToCode();
return BinaryCode;
}
int InstrumentType::StringToInt(string& str){
istringstream is(str);
if (str[0] == '$') is.get();
int value;
is >> value;
return value;
}
int InstrumentType::RegisterToInt(string name, char com){
static GeneralRegister gr;
if (com == 'g'){
try{
return gr.GetID(name);
}
catch(RegistersErrorException e){
throw CompilingErrorException(e.msg);
}
}
return StringToInt(name);
}
string InstrumentType::IntToString(int num){
ostringstream os;
os << num;
return os.str();
}
string InstrumentType::IntToName(int id, char com){
static GeneralRegister gr;
if (com == 'g'){
return gr.GetName(id);
}
return "$" + IntToString(id);
}
string InstrumentType::TranslateBinaryToAsm(){
InstrumentInformation &info = infoCurrentSentence;
AsmCode.clear();
AsmCode.push_back(info.name);
for (int j = 0; j < ArgumentNumOfInstrument(info.name); ++j){
switch(info.syntax[j]){
case 'd': AsmCode.push_back(IntToName(d, info.com[0]));break;
case 's': AsmCode.push_back(IntToName(s, info.com[1]));break;
case 't': AsmCode.push_back(IntToName(t, info.com[2]));break;
case 'h': AsmCode.push_back(IntToString(h));break;
case 'i': AsmCode.push_back(IntToString(i));break;
}
}
return GetAsmCode();
}
void InstrumentType::Run(CPUData& Data){
SetCodeRegister(Data.Mem.Load(Data.PC.GetPC()));
infoCurrentSentence.operation(d, s, t, i, h, Data);
}
string InstrumentType::GetAsmCode(){
string ret = AsmCode[0];
InstrumentInformation &info = infoCurrentSentence;
if (info.name == "sw" || info.name == "lw" || info.name == "sb" || info.name == "lb"){
ret += " " + AsmCode[1] + ", " + AsmCode[2] + "(" + AsmCode[3] + ")";
return ret;
}
for (unsigned i = 1; i < AsmCode.size(); ++i){
ret += " " + AsmCode[i];
if (i != AsmCode.size() - 1) ret += ",";
}
return ret;
}
string InstrumentType::GetBinaryCode(){
return BinaryCode;
}
void InstrumentType::SetCodeRegister(RegisterType &Code){
CodeRegister = Code;
TranslateCodeToBinary();
SetBinaryCode(BinaryCode);
}
RegisterType InstrumentType::GetCodeRegister(){
return CodeRegister;
}
void InstrumentType::TranslateCodeToBinary(){
unsigned code = CodeRegister.UIntV;
BinaryCode = "";
for (int i = 31; i >= 0; --i) BinaryCode += (code & (1 << i)) ? '1' : '0';
}
void InstrumentType::TranslateBinaryToCode(){
unsigned code = 0;
for (int i = 0; i < 32; ++i) code = code * 2 + BinaryCode[i] - '0';
CodeRegister.UIntV = code;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -