void parseExp(std::map<identifier,Expression> &values, std::string input) { const std::regex inputRegex(std::string("(((NOT)|((\\d+|[a-z]{1,2}) (AND|OR|LSHIFT|RSHIFT))) |(\\d+)|([a-z]{1,2}))(\\d*|[a-z]{1,2}) -> ([a-z]{1,2})")); std::smatch inputMatch; if(std::regex_match(input, inputMatch, inputRegex)){ Expression::Operation op = Expression::Operation::EQ; /**/ if (inputMatch[3].matched) op = Expression::Operation::NOT; else if(inputMatch[6].str()== "AND") op = Expression::Operation::AND; else if(inputMatch[6].str()== "OR") op = Expression::Operation::OR; else if(inputMatch[6].str()=="LSHIFT") op = Expression::Operation::LSHIFT; else if(inputMatch[6].str()=="RSHIFT") op = Expression::Operation::RSHIFT; identifier id = inputMatch[10].str(); if(op==Expression::Operation::NOT){ values[id] = {op,parseOperand(inputMatch[9].str())}; }else if(op==Expression::Operation::EQ){ if(inputMatch[8].matched) values[id] = {op,parseOperand(inputMatch[8].str())}; else values[id] = {op,parseOperand(inputMatch[7].str())}; }else{ values[id] = {op,parseOperand(inputMatch[5].str()),parseOperand(inputMatch[9].str())}; } std::cout << id << "<-" << values[id] << std::endl; } }
/** * Parses instructions with a SOPP encoding * * MAGIC (9) | OP (7) | SIMM (16) */ isa_op_code* parseSOPP(isa_instr instr, int argc, char **args) { char *simm_str; isa_operand *simm_op; // ISA operand structs isa_op_code *op_code; // Generated opcode struct op_code = (isa_op_code *) malloc(sizeof(isa_op_code)); if (argc < 1) ERROR("number of passed operands is too low"); // Setup arguments simm_str = args[0]; // Parse operands op_code->code = instr.op_code; op_code->literal_set = 0; // SIMM simm_op = parseOperand(simm_str, 16); if (simm_op->op_type.type != LITERAL) ERROR("non-literal value supplied for SIMM operand"); // We use a 16 bit inline literal here op_code->code |= (uint16_t) simm_op->value; free(simm_op); return op_code; }
/** * Parses instructions with a VOPC encoding * * MAGIC (7) | OP (8) | VSRC1 (8) | SSRC0 (9) | [LITERAL (32)] */ isa_op_code* parseVOPC(isa_instr instr, int argc, char **args) { char *vsrc1_str, *src0_str; int has_vcc; isa_operand *vsrc1_op, *src0_op; // ISA operand structs isa_op_code *op_code; // Generated opcode struct op_code = (isa_op_code *) malloc(sizeof(isa_op_code)); if (argc < 2) ERROR("number of passed operands is too low"); has_vcc = argc == 3; // Setup arguments src0_str = args[0 + has_vcc]; vsrc1_str = args[1 + has_vcc]; // Parse operands op_code->code = instr.op_code; op_code->literal = 0; op_code->literal_set = 0; // SRC0 src0_op = parseOperand(src0_str); if (src0_op->op_type.type == LITERAL) setLiteralOperand(op_code, src0_op); else if (src0_op->op_type.type == VGPR) src0_op->op_code += 256; op_code->code |= src0_op->op_code; // VSRC1 vsrc1_op = parseOperand(vsrc1_str); if (vsrc1_op->op_type.type != VGPR) ERROR("VSRC1 must be of VGPR type"); op_code->code |= vsrc1_op->op_code << 9; free(vsrc1_op); free(src0_op); return op_code; }
tOperand parseLabelOperand(char *operand_name, tDatabase label_values) { tOperand operand; tAddress value = getLabelValue(operand_name, label_values); if (value == -1) { operand = parseOperand(operand_name); } else { operand.type = 0; operand.value = value; } return operand; }
/** * Parses instructions with a MUBUF encoding * * MAGIC (6) | r | OP (7) | r | LDS | ADDR64 | GLC * | IDXEN | OFFEN | OFFSET (12) | SOFFSET(8) | TFE * | SLC | r | SRSRC (5) | VDATA (8) | VADDR (8) */ isa_op_code* parseMUBUF(isa_instr instr, int argc, char **args) { char *vdata_str, *vaddr_str, *srsrc_str, *soffset_str; int i, j; isa_operand *vdata_op, *vaddr_op, // ISA operand structs *srsrc_op, *soffset_op; isa_op_code *op_code; // Generated opcode struct op_code = (isa_op_code *) malloc(sizeof(isa_op_code)); if (argc < 4) ERROR("number of passed operands is too low"); // Setup arguments vdata_str = args[0]; vaddr_str = args[1]; srsrc_str = args[2]; soffset_str = args[3]; // Parse operands op_code->code = instr.op_code; op_code->literal = 0; op_code->literal_set = 1; // VDATA vdata_op = parseOperand(vdata_str); if (vdata_op->op_type.type != VGPR) ERROR("VDATA operand must be a VGPR"); op_code->literal |= vdata_op->op_code << 8; // VADDR vaddr_op = parseOperand(vaddr_str); if (vaddr_op->op_type.type != VGPR) ERROR("VADDR operand must be a VGPR"); op_code->literal |= vaddr_op->op_code; // SRSRC srsrc_op = parseOperand(srsrc_str); // This field is missing 2 bits from LSB srsrc_op->op_code >>= 2; if (srsrc_op->op_type.type != SGPR) ERROR("SRSRC operand must be an SGPR"); op_code->literal |= srsrc_op->op_code << 16; // SOFFSET soffset_op = parseOperand(soffset_str); if (soffset_op->op_type.type != SGPR && soffset_op->op_type.type != M0 && soffset_op->op_type.type != ZERO && soffset_op->op_type.type != INL_POS && soffset_op->op_type.type != INL_NEG) ERROR("SOFFSET operand must be an SGPR, M0 or inline constant"); op_code->literal |= soffset_op->op_code << 24; // Parse optional parameters for (i = 4; i < argc; ++i) { // Convert to upper case for (j = 0; args[i][j]; ++j) args[i][j] = (char) toupper(args[i][j]); if (strcmp(args[i], "OFFEN") == 0) op_code->code |= (1 << 12); else if (strcmp(args[i], "IDXEN") == 0) op_code->code |= (1 << 13); else if (strcmp(args[i], "GLC") == 0) op_code->code |= (1 << 14); else if (strcmp(args[i], "ADDR64") == 0) op_code->code |= (1 << 15); else if (strcmp(args[i], "LDS") == 0) op_code->code |= (1 << 16); else if (strcmp(args[i], "SLC") == 0) op_code->literal |= (1 << 22); else if (strcmp(args[i], "TFE") == 0) op_code->literal |= (1 << 23); else if (strncmp(args[i], "OFFSET:", strlen("OFFSET:")) == 0) { isa_operand *offset_op = parseOperand(args[i] + strlen("OFFSET:")); if (!isConstantOperand(offset_op)) ERROR("non-literal value supplied for OFFSET operand"); op_code->code |= offset_op->value; free(offset_op); } } free(vdata_op); free(vaddr_op); free(srsrc_op); free(soffset_op); return op_code; }
void ArgState::run(int argc, const char** argv) { bool keepgoing = true; ukoct_ASSERT(stage == STAGE_PARSE, "Running must only happen at parsing stage."); // PARSING if (keepgoing) { std::vector<std::string> badOptions; std::vector<std::string> badArgs; parser.parse(argc, argv); if (!parser.gotRequired(badOptions)) { for(int i=0; i < badOptions.size(); ++i) err() << "Missing required option " << badOptions[i] << ".\n"; err(false) << "Check `" << ukoct_NAME << " -h` for help." << std::endl; keepgoing = false; } if (keepgoing && !parser.gotExpected(badOptions)) { for(int i=0; i < badOptions.size(); ++i) err() << "Wrong arguments for option " << badOptions[i] << ".\n"; err(false) << "Check `" << ukoct_NAME << " -h` for help." << std::endl; keepgoing = false; } if (keepgoing && !parser.gotValid(badOptions, badArgs)) { for(int i=0; i < badOptions.size(); ++i) err() << "Got invalid argument \"" << badArgs[i] << "\" for option " << badOptions[i] << "." << std::endl; err(false) << "Check `" << ukoct_NAME << " -h` for help." << std::endl; keepgoing = false; } } if (keepgoing) { keepgoing = callOptionGroups(); } if (keepgoing) { // Input if (parser.firstArgs.size() > 1) { inputOperand.inputStream.fileName = *parser.firstArgs.back(); dbg() << "Found input file \"" << inputOperand.inputStream.fileName << "\"." << std::endl; } for (auto& ezGroup : parser.groups) { const Option* option = NULL; for (auto& flag : ezGroup->flags) { auto it = options.find(*flag); if (it != options.end()) { option = it->second; break; } } ukoct_ASSERT(option != NULL, "Option Groups must register an option object."); std::vector<std::vector<std::string> > multiArgs; ezGroup->getMultiStrings(multiArgs); // If the option takes any arguments, or if giving an // argument is optional and was not given, ez will return // a non-empty multi-argument array[i][j] where each [i] is // the specific occurrence (that coincides in index with // the parseIndex vector in the OptionGroup), and [j] is // the split option (if any). array[i] should not be empty. if (!multiArgs.empty()) { for (size_t i = 0; i < multiArgs.size(); ++i) { Operand multiOperand; multiOperand.option = option; multiOperand.parseIndex = ezGroup->parseIndex.size() == multiArgs.size() ? ezGroup->parseIndex[i] : 0; // Because of the defaults multiOperand.ezGroup = ezGroup; multiOperand.args = multiArgs[i]; multiOperand.stage = STAGE_PARSE; keepgoing = callOptionGroups(multiOperand); if (keepgoing) { operands.push_back(multiOperand); } else { break; } } } else { // In case the option doesn't take any arguments, // just insert each parseIndex to the operands list. // Those will be further sorted and then for (auto& parseIndex : ezGroup->parseIndex) { Operand operandOccurrence; operandOccurrence.option = option; operandOccurrence.parseIndex = parseIndex; operandOccurrence.ezGroup = ezGroup; operandOccurrence.stage = STAGE_PARSE; keepgoing = callOptionGroups(operandOccurrence); if (keepgoing) { operands.push_back(operandOccurrence); } else { break; } } } if (!keepgoing) { break; } } } if (keepgoing && totalActions == 0) { keepgoing = false; err() << "Please specify at least one action." << std::endl; err(false) << "Check `" << ukoct_NAME << " -h` for help." << std::endl; exitCode = RETEARG; keepgoing = false; } // Open files/streams if (keepgoing) { keepgoing = parseInputOperand(inputOperand) && parseOutputOperand(outputOperand); } if (keepgoing) { for (auto& operand : operands) { keepgoing = parseOperand(operand); if (!keepgoing) break; } } // INIT if (keepgoing) { stage = STAGE_INIT; std::sort(operands.begin(), operands.end()); keepgoing = callOptionGroups(); } if (keepgoing) { for (auto& operand : operands) { operand.stage = STAGE_INIT; keepgoing = callOptionGroups(operand); if (!keepgoing) { break; } } } // RUN if (keepgoing) { stage = STAGE_EXEC; keepgoing = callOptionGroups(); } if (keepgoing) { unsigned int actionIdx = 1; for (auto& operand : operands) { operand.stage = STAGE_EXEC; operand.actionIdx = actionIdx; keepgoing = callOptionGroups(operand); if (!keepgoing) { break; } else { ++actionIdx; } } } // PRINT RESULTS if (keepgoing && printTimings) { // TODO Print results } }
/** * Parses instructions with a SMRD encoding * * MAGIC (5) | OP (5) | SDST (7) | SBASE (6) | IMM (1) | OFFSET (8) | * [LITERAL (32)] */ isa_op_code* parseSMRD(isa_instr instr, int argc, char **args) { char *sdst_str, *sbase_str, *offset_str; isa_operand *sdst_op, *sbase_op, *offset_op; // ISA operand structs isa_op_code *op_code; // Generated opcode struct if (argc < 3) ERROR("number of passed operands is too low"); // Setup arguments sdst_str = args[0]; sbase_str = args[1]; offset_str = args[2]; op_code = (isa_op_code *) malloc(sizeof(isa_op_code)); // Parse operands op_code->code = instr.op_code; op_code->literal_set = 0; // SDST sdst_op = parseOperand(sdst_str, SDST); if (sdst_op->op_type.type != SGPR && sdst_op->op_type.type != VCC_LO && sdst_op->op_type.type != VCC_HI) ERROR("wrong type of operand for SDST in the SMRD format"); op_code->code |= sdst_op->op_code << 15; // SBASE sbase_op = parseOperand(sbase_str, SBASE); if (sbase_op->op_type.type != SGPR) ERROR("wrong type of operand for SBASE in the SMRD format"); // This field is missing the LSB // It can only be a multiple of two sbase_op->op_code >>= 1; op_code->code |= sbase_op->op_code << 9; // OFFSET offset_op = parseOperand(offset_str, OFFSET); if (offset_op->op_type.type != SGPR) { // If it's not an SGPR then it is a literal byte value // It is easier to simply reparse, because inline constant literals // are only supported up to 64 char *end; if (strncmp(offset_str, "0x", 2) == 0) { offset_op->op_code = strtol((const char*) offset_str+2, &end, 16); } else { offset_op->op_code = strtol((const char*) offset_str, &end, 10); } // Also set the IMM bit op_code->code |= (1 << 8); } op_code->code |= offset_op->op_code; free(sdst_op); free(sbase_op); free(offset_op); return op_code; }
/** * Parses instructions with a MIMG encoding * * MAGIC (6) | S | OP (7) | L | T | R | D | G | U | DMASK * | r | r | SSAMP (5) | SRSRC(5) | VDATA(8) | VADDR(8) */ isa_op_code* parseMIMG(isa_instr instr, int argc, char **args) { char *vdata_str, *vaddr_str, *ssamp_str, *srsrc_str; int i, j; isa_operand *vdata_op, *vaddr_op, // ISA operand structs *ssamp_op, *srsrc_op; isa_op_code *op_code; // Generated opcode struct op_code = (isa_op_code *) malloc(sizeof(isa_op_code)); if (argc < 4) ERROR("number of passed operands is too low"); // Setup arguments vdata_str = args[0]; vaddr_str = args[1]; srsrc_str = args[2]; ssamp_str = args[3]; // Parse operands op_code->code = instr.op_code; op_code->literal = 0; op_code->literal_set = 1; // VDATA vdata_op = parseOperand(vdata_str); if (vdata_op->op_type.type != VGPR) ERROR("VDATA operand must be a VGPR"); op_code->literal |= vdata_op->op_code << 8; // VADDR vaddr_op = parseOperand(vaddr_str); if (vaddr_op->op_type.type != VGPR) ERROR("VADDR operand must be a VGPR"); op_code->literal |= vaddr_op->op_code; // SRSRC srsrc_op = parseOperand(srsrc_str); // This field is missing 2 bits from LSB srsrc_op->op_code >>= 2; if (srsrc_op->op_type.type != SGPR) ERROR("SRSRC operand must be an SGPR"); op_code->literal |= srsrc_op->op_code << 16; // SSAMP ssamp_op = parseOperand(ssamp_str); if (ssamp_op->op_type.type != SGPR) ERROR("SSAMP operand must be an SGPR"); // This field is also missing 2 bits from the LSB ssamp_op->op_code >>= 2; op_code->literal |= ssamp_op->op_code << 21; // Parse optional parameters for (i = 4; i < argc; ++i) { // Convert to upper case for (j = 0; args[i][j]; ++j) args[i][j] = (char) toupper(args[i][j]); if (strcmp(args[i], "SLC") == 0) op_code->code |= (1 << 25); else if (strcmp(args[i], "LWE") == 0) op_code->code |= (1 << 17); else if (strcmp(args[i], "TFE") == 0) op_code->code |= (1 << 16); else if (strcmp(args[i], "R128") == 0) op_code->code |= (1 << 15); else if (strcmp(args[i], "DA") == 0) op_code->code |= (1 << 14); else if (strcmp(args[i], "GLC") == 0) op_code->code |= (1 << 13); else if (strcmp(args[i], "UNORM") == 0) op_code->code |= (1 << 12); else if (strncmp(args[i], "DMASK:", strlen("DMASK:")) == 0) { isa_operand *dmask_op = parseOperand(args[i] + strlen("DMASK:")); if (!isConstantOperand(dmask_op)) ERROR("non-literal value supplied for DMASK operand"); // Only 4 bits are needed dmask_op->value &= 0xF; op_code->code |= (dmask_op->value) << 8; free(dmask_op); } } free(vdata_op); free(vaddr_op); free(srsrc_op); free(ssamp_op); return op_code; }