void CodeEmitter::emitValue(AstNode valueNode, Word word) { if(valueNode.type == AstNode::ReferenceNode) { word.instruction.mod = 0; word.instruction.adr = -1; markReference(valueNode.sValue); emitWord(word); } else if(valueNode.type == AstNode::ParenNode) { word.instruction.adr = -1; if(valueNode.children.front().type == AstNode::ReferenceNode) { AstNode referenceNode = valueNode.children.front(); word.instruction.mod = 1; markReference(referenceNode.sValue); } else if(valueNode.children.front().type == AstNode::ParenNode) { AstNode secondParenNode = valueNode.children.front(); if(secondParenNode.children.front().type == AstNode::ReferenceNode) { AstNode referenceNode = secondParenNode.children.front(); word.instruction.mod = 2; markReference(referenceNode.sValue); } else { emitterError("wrong paren content"); } } else { emitterError("wrong paren content"); } emitWord(word); } else if(valueNode.type == AstNode::NumberNode) { word.instruction.mod = 0; word.instruction.adr = valueNode.aValue; emitWord(word); } else { emitterError("wrong instruction argument"); } }
static void emitDword( unsigned long dword ) { unsigned short hi,lo; hi = dword >> 16; lo = dword & 0xffff; emitWord( lo ); emitWord( hi ); }
void process_fill() { char sz = 'b'; int64_t count; int64_t val; int64_t nn; if (*inptr=='.') { inptr++; if (strchr("bchwBCHW",*inptr)) { sz = tolower(*inptr); inptr++; } else printf("Illegal fill size.\r\n"); } SkipSpaces(); NextToken(); count = expr(); prevToken(); need(','); NextToken(); val = expr(); prevToken(); for (nn = 0; nn < count; nn++) switch(sz) { case 'b': emitByte(val); break; case 'c': emitChar(val); break; case 'h': emitHalf(val); break; case 'w': emitWord(val); break; } }
void CodeEmitter::emitInstruction(AstNode node) { std::string name = node.sValue; Word word; word.data = 0; word.instruction.code = _opcodes[name]; if(name == "null" || name == "halt" || name == "dump") { emitWord(word); } else if(name[0] == 'j') { if(node.children.size() == 1 && node.children.front().type == AstNode::ReferenceNode) { markReference(node.children.front().sValue); word.instruction.adr = -1; emitWord(word); } else { emitterError("wrong jump arguments"); } } else if(name == "print") { if(node.children.size() == 1) { if(node.children.front().type == AstNode::RegisterNode) { word.instruction.acu = node.children.front().sValue == "B" ? 1 : 0; word.instruction.usr = 0; emitWord(word); } else { word.instruction.usr = 1; emitValue(node.children.front(), word); } } else { emitterError("too many print arguments"); } } else { if(node.children.size() == 2 && node.children.front().type == AstNode::RegisterNode) { AstNode registerNode = node.children.front(); if (registerNode.sValue != "A" && registerNode.sValue != "B") { emitterError("wrong register name"); } word.instruction.acu = registerNode.sValue == "B" ? 1 : 0; AstNode valueNode = node.children.back(); emitValue(valueNode, word); } else { emitterError("wrong instruction arguments"); } } }
void process_dw() { int64_t val; SkipSpaces(); while(token!=tk_eol) { SkipSpaces(); if (*inptr=='"') { inptr++; while (*inptr!='"') { if (*inptr=='\\') { inptr++; switch(*inptr) { case '\\': emitWord('\\'); inptr++; break; case 'r': emitWord(0x13); inptr++; break; case 'n': emitWord(0x0A); inptr++; break; case 'b': emitWord('\b'); inptr++; break; case '"': emitWord('"'); inptr++; break; default: inptr++; break; } } else { emitWord(*inptr); inptr++; } } inptr++; } else if (*inptr=='\'') { inptr++; emitWord(*inptr); inptr++; if (*inptr!='\'') { printf("Missing ' in character constant.\r\n"); } } else { NextToken(); val = expr(); // A pointer to an object might be emitted as a data word. if (bGen && lastsym) if( lastsym->segment < 5) sections[segment+7].AddRel(sections[segment].index,((lastsym-syms+1) << 32) | 6 | (lastsym->isExtern ? 128 : 0)); emitWord(val); prevToken(); } SkipSpaces(); if (*inptr!=',') break; inptr++; } ScanToEOL(); }
void CodeEmitter::emitDataWords(std::vector<AstNode> words) { Word word; for(AstNode node : words) { if(node.type == AstNode::NumberNode) { word.data = node.aValue; emitWord(word); } else if(node.type == AstNode::MultinumberNode) { for(int i = 0; i < node.aValue; ++i) { word.data = node.bValue; emitWord(word); } } else if(node.type == AstNode::ReferenceNode) { markDataReference(node.sValue); word.data = -2; emitWord(word); } else { emitterError("only numbers and references can follow .WORD directive"); } } }
std::vector<Word> CodeEmitter::emitCode() { Word main; main.data = 0; emitWord(main); for(const AstNode node : _ast.rootNode.children) { switch(_currentSection) { case NullSection: { if(node.type == AstNode::DirectiveNode && node.sValue == ".UNIT") { _currentSection = UnitSection; } else { emitterError("code should start with .UNIT section"); } break; } case UnitSection: { if(node.type == AstNode::DirectiveNode && node.sValue == ".DATA") { _currentSection = DataSection; } else { emitterError("data section should follow after .UNIT section"); } break; } case DataSection: { if(node.type == AstNode::DirectiveNode && node.sValue == ".CODE") { _mainLabel = _words.size(); _currentSection = CodeSection; } else if(node.type == AstNode::LabelNode) { _labels[node.sValue] = _words.size(); } else if(node.type == AstNode::DirectiveNode && node.sValue == ".WORD") { emitDataWords(node.children); } else { emitterError("data section can contain only .WORD directives and references"); } break; } case CodeSection: { if(node.type == AstNode::DirectiveNode && node.sValue == ".END") { _currentSection = EndSection; } else if(node.type == AstNode::LabelNode) { _labels[node.sValue] = _words.size(); } else if(node.type == AstNode::InstructionNode) { emitInstruction(node); } else { emitterError("data section can contain only .WORD directives and labels"); } break; } case EndSection: { emitterError("no code allowed after .END"); break; } default: { emitterError("critical error"); } } } resolveReferences(); _words[0].data = _mainLabel * 4; return _words; }