HRESULT Vc4Disasm::ParseLoadImmInstruction(VC4_QPU_INSTRUCTION Instruction) { if (VC4_QPU_GET_WADDR_ADD(Instruction) != VC4_QPU_WADDR_NOP) { this->xprintf(TEXT("%s%s%s "), VC4_QPU_Name_Op_Move, ((VC4_QPU_GET_IMMEDIATE_TYPE(Instruction) == VC4_QPU_IMMEDIATE_TYPE_32) ? TEXT("") : (VC4_QPU_GET_IMMEDIATE_TYPE(Instruction) == VC4_QPU_IMMEDIATE_TYPE_PER_ELEMENT_SIGNED) ? TEXT("_per_element_signed") : (VC4_QPU_GET_IMMEDIATE_TYPE(Instruction) == VC4_QPU_IMMEDIATE_TYPE_PER_ELEMENT_UNSIGNED) ? TEXT("per_element_unsigned") : TEXT("Invalid")), (VC4_QPU_IS_SETFLAGS_SET(Instruction) ? VC4_QPU_Name_SetFlag : VC4_QPU_Name_Empty)); ParseWrite(Instruction, true); this->xprintf(TEXT("%s"), VC4_QPU_LOOKUP_STRING(COND, VC4_QPU_GET_COND_ADD(Instruction))); this->xprintf(TEXT(", ")); this->xprintf(TEXT("0x%08x"), VC4_QPU_GET_IMMEDIATE_32(Instruction)); } else { this->xprintf(TEXT("%s"), VC4_QPU_LOOKUP_STRING(OPCODE_ADD, VC4_QPU_OPCODE_ADD_NOP)); } this->xprintf(TEXT(" ; ")); if (VC4_QPU_GET_WADDR_MUL(Instruction) != VC4_QPU_WADDR_NOP) { this->xprintf(TEXT("%s%s%s "), VC4_QPU_Name_Op_Move, ((VC4_QPU_GET_IMMEDIATE_TYPE(Instruction) == VC4_QPU_IMMEDIATE_TYPE_32) ? TEXT("") : (VC4_QPU_GET_IMMEDIATE_TYPE(Instruction) == VC4_QPU_IMMEDIATE_TYPE_PER_ELEMENT_SIGNED) ? TEXT("_per_element_signed") : (VC4_QPU_GET_IMMEDIATE_TYPE(Instruction) == VC4_QPU_IMMEDIATE_TYPE_PER_ELEMENT_UNSIGNED) ? TEXT("per_element_unsigned") : TEXT("Invalid")), (VC4_QPU_IS_SETFLAGS_SET(Instruction) ? VC4_QPU_Name_SetFlag : VC4_QPU_Name_Empty)); ParseWrite(Instruction, false); this->xprintf(TEXT("%s"), VC4_QPU_LOOKUP_STRING(COND, VC4_QPU_GET_COND_MUL(Instruction))); this->xprintf(TEXT(", ")); this->xprintf(TEXT("0x%08x"), VC4_QPU_GET_IMMEDIATE_32(Instruction)); } else { this->xprintf(TEXT("%s"), VC4_QPU_LOOKUP_STRING(OPCODE_MUL, VC4_QPU_OPCODE_MUL_NOP)); } return S_OK; }
NodeWrite* Parser::ParseWrite(bool isFirst, bool isWriteln) { NodeWrite* ans = NULL; t = sc.GetNextToken(); if (isFirst) t = RequireToken("(", "\"(\" expected"); if (t.GetType() == string_const) { ans = new NodeWriteStr(STR, "\""+t.GetValue().substr(1, t.GetValue().size()-2)+"\""); t = sc.GetNextToken(); } else { NodeExpression* exp = ParseComparision(); OutputType T; if (exp->GetType()->IsInt()) T = INT; else T = FLOAT; ans = new NodeWriteExp(T, exp); } if (t.GetValue() == ",") ans->SetNext(ParseWrite(false, isWriteln)); else { t = RequireToken(")", "\")\" expected"); if (isWriteln) ans->SetNext(new NodeWriteln()); } return ans; }
HRESULT Vc4Disasm::ParseMulOp(VC4_QPU_INSTRUCTION Instruction) { this->xprintf(TEXT("%s%s%s "), (VC4_QPU_IS_OPCODE_MUL_MOV(Instruction) ? VC4_QPU_Name_Op_Move : VC4_QPU_LOOKUP_STRING(OPCODE_MUL, VC4_QPU_GET_OPCODE_MUL(Instruction))), (VC4_QPU_IS_SETFLAGS_SET(Instruction) ? VC4_QPU_Name_SetFlag : VC4_QPU_Name_Empty), (VC4_QPU_IS_OPCODE_MUL_NOP(Instruction) ? VC4_QPU_Name_Empty : VC4_QPU_LOOKUP_STRING(COND, VC4_QPU_GET_COND_MUL(Instruction)))); if (!VC4_QPU_IS_OPCODE_MUL_NOP(Instruction)) { ParseWrite(Instruction, false); this->xprintf(TEXT(", ")); if (!VC4_QPU_IS_OPCODE_MUL_MOV(Instruction)) { ParseRead(Instruction, VC4_QPU_GET_MUL_A(Instruction)); this->xprintf(TEXT(", ")); } if (VC4_QPU_IS_OPCODE_LOAD_SM(Instruction) && (VC4_QPU_GET_MUL_B(Instruction) == VC4_QPU_ALU_REG_B)) { ParseSmallImmediate(Instruction); } else { ParseRead(Instruction, VC4_QPU_GET_MUL_B(Instruction)); } } return S_OK; }
NodeStatement* Parser::ParseElement() { if (t.GetValue() == "begin") return ParseBlock(); if (t.GetValue() == "if") return ParseIf(); if (t.GetValue() == "while") return ParseWhile(); if (t.GetValue() == "repeat") return ParseRepeat(); if (t.GetValue() == "for") return ParseFor(); if (t.GetValue() == "write") return ParseWrite(true, false); if (t.GetValue() == "writeln") return ParseWrite(true, true); if (t.GetValue() == "exit") { t = sc.GetNextToken(); return new StatementExit(true); } if (t.GetType() == identifier) { bool found = false; _Table::iterator it = TableStack.Find(t.GetValue(), found); if (found) { if (it->second->IsProc() || it->second->IsFunc()) { t = sc.GetNextToken(); return ParseSub((SymProc*)it->second); } } return ParseAssignment(); } if (t.GetValue() == "(") { return ParseAssignment(); } throw Error("Statement error", t); }
HRESULT Vc4Disasm::ParseBranchInstruction(VC4_QPU_INSTRUCTION Instruction) { this->xprintf(TEXT("%s%s "), (VC4_QPU_IS_BRANCH_RELATIVE(Instruction) ? TEXT("brr") : TEXT("bra")), (VC4_QPU_LOOKUP_STRING(BRANCH_COND, VC4_QPU_GET_BRANCH_COND(Instruction)))); if (VC4_QPU_IS_BRANCH_USE_RADDR_A(Instruction)) { ParseReadAddr(VC4_QPU_GET_BRANCH_RADDR_A(Instruction), true); } if (VC4_QPU_GET_IMMEDIATE_32(Instruction) != 0) { this->xprintf(TEXT("+0x%x"), VC4_QPU_GET_IMMEDIATE_32(Instruction)); } if ((VC4_QPU_GET_WADDR_ADD(Instruction) != VC4_QPU_WADDR_NOP) || (VC4_QPU_GET_WADDR_MUL(Instruction) != VC4_QPU_WADDR_NOP)) { this->xprintf(TEXT("; ret_addr saved to ")); ParseWrite(Instruction, true, false); this->xprintf(TEXT(" ")); ParseWrite(Instruction, false, false); } return S_OK; }