Services and Modeling for Embedded Software Development
Embecosm divider strip
Prev  Next

3.6. Parsing Operands

The ParseOperand function makes use of the two previously defined functions in order to parse an operand of which type is originally unknown.

[Note]Note

This section describes how this function is used in the OpenRISC 1000  implementation, specifically for how it handles memory operands. Other architectures will need to modify this function to match the needs and types of operands expected to be found in an assembly output.

In the OpenRISC 1000  architecture, there are three types of operand which need parsing by this method, registers, immediates and memory operands which are of the form imm(reg).

Firstly attempts are made to parse an operand as a register, using the previously defined ParseRegister function. If this succeeds then the operand is added to the list of operands for the instruction and the function returns.

If this does not work (the operand is not a register), an attempt is then made to parse the operand as an immediate. Should the immediate operand successfully be parsed, then it should be considered as a memory operand first, before placing it into the list of operands.

As the form of a memory operand in OpenRISC 1000  is of the form imm(reg), then the next token is evaluated to determine if it is a the start of a memory operand. If this type matches (i.e. it is a left parenthesis, the next token is evaluated as a register. Finally should the last token be a right parenthesis, then a memory operand has instead been parsed.

Should parsing as a memory operand succeed, the two components are added to the operand list whereas if the first test failed (the first operand was not an left parenthesis) just the immediate is added.

If however, no valid operand was found (either not a valid type or memory parsing failed after identifying a left parenthesis), then an error is created and returned instead.

bool OR1KAsmParser::
ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
  OR1KOperand *Op, *Op2 = 0;

  // Attempt to parse token as register
  unsigned RegNo;
  Op = ParseRegister(RegNo);
  
  // Attempt to parse token as immediate
  if (!Op) {
    Op = ParseImmediate();
    
    // If next token is left parenthesis, then attempt to parse as memory
    // operand
    if (Op)
      if (getLexer().is(AsmToken::LParen)) {
        getLexer().Lex();
        // Swap tokens around so that they can be parsed
        Op2 = Op;
        Op = ParseRegister(RegNo);

        // Invalid memory operand, fail
        if (!Op || getLexer().isNot(AsmToken::RParen)) {
          Error(Parser.getTok().getLoc(), "unknown operand");
          return true;
        }
        getLexer().Lex();
      }
  }

  // If the token could not be parsed then fail
  if (!Op) {
    Error(Parser.getTok().getLoc(), "unknown operand");
    return true;
  }

  // Push back parsed operand(s) into list of operands
  Operands.push_back(Op);
  if (Op2)
    Operands.push_back(Op2);

  return false;
}
        
Embecosm divider strip