bool ArmParser::parseRegisterList(Parser& parser, int& dest, int validMask) { ArmRegisterValue reg, reg2; dest = 0; while (true) { if (parseRegister(parser,reg) == false) return false; if (parser.peekToken().type == TokenType::Minus) { parser.eatToken(); if (parseRegister(parser,reg2) == false || reg2.num < reg.num) return false; for (int i = reg.num; i <= reg2.num; i++) { dest |= (1 << i); } } else { dest |= (1 << reg.num); } if (parser.peekToken().type != TokenType::Comma) break; parser.eatToken(); } return (validMask & dest) == dest; }
bool ArmParser::parseImmediate(Parser& parser, Expression& dest) { TokenizerPosition pos = parser.getTokenizer()->getPosition(); // check if it really is an immediate ArmOpcodeVariables tempVars; if (parsePsrTransfer(parser,tempVars,false)) return false; parser.getTokenizer()->setPosition(pos); if (parseRegister(parser,tempVars.rd)) return false; parser.getTokenizer()->setPosition(pos); if (parseCopNumber(parser,tempVars.rd)) return false; parser.getTokenizer()->setPosition(pos); if (parseCopRegister(parser,tempVars.rd)) return false; parser.getTokenizer()->setPosition(pos); dest = parser.parseExpression(); return dest.isLoaded(); }
void HWInformation::parseRegisterAssociation (const xmlpp::Node *node) { //Recurse through child nodes: xmlpp::Node::NodeList list = node->get_children (); for (xmlpp::Node::NodeList::iterator iter = list.begin (); iter != list.end (); ++iter) { const xmlpp::Node *tmp = *iter; //Be paranoid assert (tmp != NULL); if (verifyCanGetName (tmp)) { if (verifyNodeName (tmp, "register")) { parseRegister (tmp); } else { Logging::log (1, "HWInformation: Warning: Unsupported name '", extractNodeName (tmp).c_str (), "' in register_association node at: ", getLine (tmp).c_str (), NULL); } } } }
bool ArmParser::parseThumbParameters(Parser& parser, const tThumbOpcode& opcode, ThumbOpcodeVariables& vars) { const u8* encoding = (const u8*) opcode.mask; ArmRegisterValue tempRegister; int value; while (*encoding != 0) { bool optional = *encoding == '/'; if (optional) encoding++; switch (*encoding++) { case 'd': // register CHECK(parseRegister(parser,vars.rd,7)); break; case 's': // register CHECK(parseRegister(parser,vars.rs,7)); break; case 'n': // register CHECK(parseRegister(parser,vars.rn,7)); break; case 'o': // register CHECK(parseRegister(parser,vars.ro,7)); break; case 'D': // register CHECK(parseRegister(parser,vars.rd,15)); break; case 'S': // register CHECK(parseRegister(parser,vars.rs,15)); break; case 'r': // forced register CHECK(parseRegister(parser,tempRegister,15)); CHECK(*encoding++ == tempRegister.num); break; case 'R': // register list value = encoding[0] | (encoding[1] << 8); CHECK(parseRegisterList(parser,vars.rlist,value)); encoding += 2; break; case 'I': // immediate case 'i': CHECK(parseImmediate(parser,vars.ImmediateExpression)); vars.ImmediateBitLen = *encoding++; break; default: CHECK(matchSymbol(parser,*(encoding-1),optional)); break; } } // the next token has to be an identifier, else the parameters aren't // completely parsed return parser.atEnd() || parser.peekToken().type == TokenType::Identifier; }
bool ArmParser::parsePseudoShift(Parser& parser, ArmOpcodeVariables& vars, int type) { vars.Shift.Type = type; if (parseRegister(parser,vars.Shift.reg) == true) { vars.Shift.ShiftByRegister = true; } else { if (parser.peekToken().type == TokenType::Hash) parser.eatToken(); if (parseImmediate(parser,vars.Shift.ShiftExpression) == false) return false; vars.Shift.ShiftByRegister = false; } vars.Shift.UseShift = true; return true; }
int getcmd(char line[], int *index, int *num, int *data_start, int *data_end) { int len = 0; int cmd = AT_CMD_END; *num = 0; *data_start = 0; *data_end = 0; if (line == NULL) return AT_CMD_NONE; len = strlen(line); while (*index < len) { cmd = toupper(line[*index]); switch (cmd) { case ' ': break; case 0: return AT_CMD_END; case '%': (*index)++; while (*index < len) { switch (toupper(line[*index])) { case ' ': break; case 0: return AT_CMD_ERR; default: return parseCommand(line, AT_CMD_FLAG_PRO_PCT, index, num, len); } (*index)++; } break; case '\\': (*index)++; while (*index < len) { switch (toupper(line[*index])) { case ' ': break; case 0: return AT_CMD_ERR; default: return parseCommand(line, AT_CMD_FLAG_PRO_BACK, index, num, len); } (*index)++; } break; case ':': (*index)++; while (*index < len) { switch (toupper(line[*index])) { case ' ': break; case 0: return AT_CMD_ERR; default: return parseCommand(line, AT_CMD_FLAG_PRO_COLON, index, num, len); } (*index)++; } break; case '-': (*index)++; while (*index < len) { switch (toupper(line[*index])) { case ' ': break; case 0: return AT_CMD_ERR; default: return parseCommand(line, AT_CMD_FLAG_PRO_MINUS, index, num, len); } (*index)++; } break; case '&': (*index)++; while (*index < len) { switch (toupper(line[*index])) { case ' ': break; case 0: return AT_CMD_ERR; case 'Z': return parseRegister(line, AT_CMD_FLAG_EXT, index, num, len, data_start, data_end, TRUE); default: return parseCommand(line, AT_CMD_FLAG_EXT, index, num, len); } (*index)++; } break; case 'D': // handle Dialing. (*index)++; *num = 0; while (*index < len) { switch (toupper(line[*index])) { case 0: return cmd; case 'T': case 'P': case 'L': *num = toupper(line[*index]); (*index)++; default: getData(line, index, len, data_start, data_end, TRUE); return cmd; } (*index)++; } return cmd; case 'S': return parseRegister(line, AT_CMD_FLAG_BAS, index, num, len, data_start, data_end, FALSE); default: return parseCommand(line, AT_CMD_FLAG_BAS, index, num, len); } (*index)++; } return cmd; }
bool ArmParser::parseArmParameters(Parser& parser, const tArmOpcode& opcode, ArmOpcodeVariables& vars) { const u8* encoding = (const u8*) opcode.mask; ArmRegisterValue tempRegister; vars.Shift.UseShift = false; vars.Shift.UseFinal = false; vars.psr = false; vars.writeback = false; vars.SignPlus = false; vars.Opcode.UseNewEncoding = false; vars.Opcode.UseNewType = false; while (*encoding != 0) { bool optional = *encoding == '/'; if (optional) encoding++; switch (*encoding++) { case 'd': // register CHECK(parseRegister(parser,vars.rd,*encoding++ == '1' ? 14 : 15)); break; case 's': // register CHECK(parseRegister(parser,vars.rs,*encoding++ == '1' ? 14 : 15)); break; case 'n': // register CHECK(parseRegister(parser,vars.rn,*encoding++ == '1' ? 14 : 15)); break; case 'm': // register CHECK(parseRegister(parser,vars.rm,*encoding++ == '1' ? 14 : 15)); break; case 'D': // cop register CHECK(parseCopRegister(parser,vars.CopData.cd)); break; case 'N': // cop register CHECK(parseCopRegister(parser,vars.CopData.cn)); break; case 'M': // cop register CHECK(parseCopRegister(parser,vars.CopData.cm)); break; case 'W': // writeback parseWriteback(parser,vars.writeback); break; case 'p': // psr parsePsr(parser,vars.psr); break; case 'P': // msr/mrs psr data CHECK(parsePsrTransfer(parser,vars,*encoding++ == '1')); break; case 'R': // register list CHECK(parseRegisterList(parser,vars.rlist,0xFFFF)); break; case 'S': // shift CHECK(parseShift(parser,vars,*encoding++ == '1')); break; case 'I': // immediate case 'i': CHECK(parseImmediate(parser,vars.ImmediateExpression)); vars.ImmediateBitLen = 32; break; case 'j': // variable bit immediate CHECK(parseImmediate(parser,vars.ImmediateExpression)); vars.ImmediateBitLen = *encoding++; break; case 'X': // cop number CHECK(parseCopNumber(parser,vars.CopData.pn)); break; case 'Y': // cop opcode number CHECK(parseImmediate(parser,vars.CopData.CpopExpression)); vars.ImmediateBitLen = 4; break; case 'Z': // cop info number CHECK(parseImmediate(parser,vars.CopData.CpinfExpression)); vars.ImmediateBitLen = 3; break; case 'z': // shift for pseudo opcodes CHECK(parsePseudoShift(parser,vars,*encoding++)); break; case 'v': // sign for register index parameter parseSign(parser,vars.SignPlus); break; default: CHECK(matchSymbol(parser,*(encoding-1),optional)); break; } } // the next token has to be an identifier, else the parameters aren't // completely parsed return parser.atEnd() || parser.peekToken().type == TokenType::Identifier; }
bool ArmParser::parseShift(Parser& parser, ArmOpcodeVariables& vars, bool immediateOnly) { // no shift is also valid vars.Shift.UseShift = false; if (parser.peekToken().type != TokenType::Comma) return true; parser.eatToken(); // load shift mode const Token& shiftMode = parser.nextToken(); if (shiftMode.type != TokenType::Identifier) return false; std::wstring stringValue = shiftMode.getStringValue(); bool hasNumber = isNumber(stringValue.back()); u64 number; // handle modeXX syntax if (hasNumber) { number = 0; u64 multiplier = 1; while (isNumber(stringValue.back())) { number += multiplier*(stringValue.back() - '0'); multiplier *= 10; stringValue.pop_back(); } } if (stringValue == L"lsl") vars.Shift.Type = 0; else if (stringValue == L"lsr") vars.Shift.Type = 1; else if (stringValue == L"asr") vars.Shift.Type = 2; else if (stringValue == L"ror") vars.Shift.Type = 3; else if (stringValue == L"rrx") vars.Shift.Type = 4; else return false; if (hasNumber) { vars.Shift.ShiftExpression = createConstExpression(number); vars.Shift.ShiftByRegister = false; } else if (parseRegister(parser,vars.Shift.reg) == true) { if (immediateOnly) return false; vars.Shift.ShiftByRegister = true; } else { if (parser.peekToken().type == TokenType::Hash) parser.eatToken(); if (parseImmediate(parser,vars.Shift.ShiftExpression) == false) return false; vars.Shift.ShiftByRegister = false; } vars.Shift.UseShift = true; return true; }