/*
AssemblerOperandParserStage9900.java
(c) 2010-2014 Edward Swartz
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
*/
package v9t9.tools.asm.inst9900;
import v9t9.tools.asm.AssemblerOperandParserStage;
import v9t9.tools.asm.AssemblerTokenizer;
import v9t9.tools.asm.Equate;
import v9t9.tools.asm.IAssembler;
import v9t9.tools.asm.ParseException;
import v9t9.tools.asm.Symbol;
import v9t9.tools.asm.operand.hl.AddrOperand;
import v9t9.tools.asm.operand.hl.AssemblerOperand;
import v9t9.tools.asm.operand.hl.BinaryOperand;
import v9t9.tools.asm.operand.hl.ConstPoolRefOperand;
import v9t9.tools.asm.operand.hl.ImmediateOperand;
import v9t9.tools.asm.operand.hl.NumberOperand;
import v9t9.tools.asm.operand.hl.RegIncOperand;
import v9t9.tools.asm.operand.hl.RegIndOperand;
import v9t9.tools.asm.operand.hl.RegOffsOperand;
import v9t9.tools.asm.operand.hl.StringOperand;
import v9t9.tools.asm.operand.hl.SymbolOperand;
import v9t9.tools.asm.operand.hl.UnaryOperand;
import v9t9.tools.asm.operand.ll.LLImmedOperand;
public class AssemblerOperandParserStage9900 extends
AssemblerOperandParserStage {
public AssemblerOperandParserStage9900(IAssembler assembler) {
super(assembler);
}
@Override
protected AssemblerOperand parseTargetSpecificOperand(int t)
throws ParseException {
switch (t) {
case '+': {
AssemblerOperand op = parseFactor();
if (op instanceof NumberOperand)
return op;
if (op instanceof RegIndOperand) {
return new RegIncOperand(((RegIndOperand) op).getReg());
}
throw new ParseException("Suspicious use of + for " + op);
}
case '-': {
AssemblerOperand op = parseFactor();
return new UnaryOperand('-', op);
}
case '*':
return parseRegIndInc();
case '@':
return parseAddr();
case '#': {
// const table
boolean isHigh = false;
if (tokenizer.nextToken() == '<') {
isHigh = true;
} else {
tokenizer.pushBack();
}
AssemblerOperand op = parseFactor();
if (isHigh) {
op = new BinaryOperand('/', op, new ImmediateOperand(new LLImmedOperand(256)));
}
return new ConstPoolRefOperand(op);
}
case AssemblerTokenizer.NUMBER:
case AssemblerTokenizer.CHAR:
tokenizer.pushBack();
return parseNumber();
case AssemblerTokenizer.ID:
Symbol symbol = assembler.referenceSymbol(tokenizer.getString());
if (symbol instanceof Equate) {
return ((Equate) symbol).getValue();
}
return new SymbolOperand(symbol);
case AssemblerTokenizer.STRING:
return new StringOperand(tokenizer.getString());
case AssemblerTokenizer.EOF:
throw new ParseException("Unexpected end of line");
}
return null;
}
private AssemblerOperand parseRegIndInc() throws ParseException {
AssemblerOperand reg = parseFactor();
int t = tokenizer.nextToken();
if (t == '+') {
reg = new RegIncOperand(reg);
} else {
reg = new RegIndOperand(reg);
tokenizer.pushBack();
}
return reg;
}
private AssemblerOperand parseAddr() throws ParseException {
AssemblerOperand addr = parseExpr();
int t = tokenizer.nextToken();
if (t == '(') {
AssemblerOperand reg = parseFactor();
t = tokenizer.nextToken();
if (t != ')') {
throw new ParseException("Expected ')': " + tokenizer.currentToken());
}
return new RegOffsOperand(addr, reg);
} else {
tokenizer.pushBack();
return new AddrOperand(addr);
}
}
}