int ASMParser::cvtNumString2Number(string s) // Converts a string to an integer. Assumes s is something like "-231" and produces -231 { if (!isNumberString(s)) { cerr << "Non-numberic string passed to cvtNumString2Number" << endl; return 0; } int k = 1; int val = 0; for (int i = s.length()-1; i>0; i--) { char c = s.at(i); val = val + k*((int)(c - '0')); k = k*10; } if (isSign(s.at(0))) { if (s.at(0) == '-') val = -1*val; } else { val = val + k*((int)(s.at(0) - '0')); } return val; }
bool ASMParser::getOperands(Instruction &i, Opcode o, string *operand, int operand_count) // Given an Opcode, a string representing the operands, and the number of operands, // breaks operands apart and stores fields into Instruction. { if(operand_count != opcodes.numOperands(o)) return false; int rs, rt, rd, imm; imm = 0; rs = rt = rd = NumRegisters; int rs_p = opcodes.RSposition(o); int rt_p = opcodes.RTposition(o); int rd_p = opcodes.RDposition(o); int imm_p = opcodes.IMMposition(o); if(rs_p != -1){ rs = registers.getNum(operand[rs_p]); if(rs == NumRegisters) return false; } if(rt_p != -1){ rt = registers.getNum(operand[rt_p]); if(rt == NumRegisters) return false; } if(rd_p != -1){ rd = registers.getNum(operand[rd_p]); if(rd == NumRegisters) return false; } if(imm_p != -1){ if(isNumberString(operand[imm_p])){ // does it have a numeric immediate field? imm = cvtNumString2Number(operand[imm_p]); if(((abs(imm) & 0xFFFF0000)<<1)) // too big a number to fit return false; } else{ if(opcodes.isIMMLabel(o)){ // Can the operand be a label? // Assign the immediate field an address imm = myLabelAddress; myLabelAddress += 4; // increment the label generator } else // There is an error return false; } } i.setValues(o, rs, rt, rd, imm); return true; }
bool ExpressionCell::_compute() { if (this->computed) return this->error ? false : true; if (data[0]!='=') { this->error = true; this->computed = true; this->data = "#parce_expr_error"; return false; } enum {EQUAL='=', PLUS='+', MINUS='-', MULTIPLICATION='*', DIVISION='\\'} signState=EQUAL; int leftValue = 0; int rightArgBegin = 1; for (unsigned int i=1; i<data.size()+1; i++) { if ( (i == data.size()-1) || isSign(data[i]) ) { int rightValue = 0; string rightArg = data.substr(rightArgBegin, i-1); if (isNumberString(rightArg)) rightValue = atoi(rightArg.c_str()); else if (isCellString(rightArg)) { pair<int, int> cellCoord = parseCellCoordinate(rightArg); Cell *cell = getCell(cellCoord.first, cellCoord.second); // if cell not found or cell can't be computed => error if (cell == NULL || !cell->compute() || !cell->isNumber()) { this->error = true; this->computed = true; this->data = "#incorrect_cell_"+rightArg; return false; } rightValue = cell->getNumber(); } // Compute operation switch (signState) { case EQUAL: leftValue = rightValue; break; case PLUS: leftValue += rightValue; break; case MINUS: leftValue -= rightValue; break; case MULTIPLICATION: leftValue *= rightValue; break; case DIVISION: if (rightValue == 0) { this->error = true; this->computed = true; this->data = "#division_by_zero"; return false; } leftValue /= rightValue; break; } } if ( i == data.size()-1 ) break; // set next sing if (data[i] == '+') signState = PLUS; if (data[i] == '-') signState = MINUS; if (data[i] == '*') signState = MULTIPLICATION; if (data[i] == '/') signState = DIVISION; } this->error = false; this->computed = true; this->data = std::to_string(leftValue); this->data_int = leftValue; return true; }