package org.reasm.m68k.assembly.internal;
import java.io.IOException;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
import org.reasm.commons.source.LogicalLineReader;
import org.reasm.commons.source.Syntax;
import org.reasm.m68k.messages.InvalidCharacterInHexDirectiveErrorMessage;
import org.reasm.messages.OddNumberOfCharactersInHexDirectiveErrorMessage;
/**
* The <code>HEX</code> directive.
*
* @author Francis Gagné
*/
@Immutable
class HexDirective extends Mnemonic {
@Nonnull
static final HexDirective HEX = new HexDirective();
private static int getHexDigitValue(int codePoint) {
if (Syntax.isDigit(codePoint)) {
return codePoint - '0';
}
// 'a'..'f' => 'A'..'F'
codePoint &= ~0x20;
if (codePoint >= 'A' && codePoint <= 'F') {
return codePoint - ('A' - 10);
}
return -1;
}
private HexDirective() {
}
@Override
void assemble(M68KAssemblyContext context) throws IOException {
context.sizeNotAllowed();
final LogicalLineReader reader = context.logicalLineReader;
final int numberOfOperands = context.numberOfOperands;
for (int i = 0; i < numberOfOperands; i++) {
context.prepareOperandReader(i);
for (int currentCodePoint; !reader.atEnd(); reader.advance(), reader.skipWhitespace()) {
currentCodePoint = reader.getCurrentCodePoint();
assert currentCodePoint != -1;
// Parse the first nybble of a nybble pair.
int hexDigitValue = getHexDigitValue(currentCodePoint);
if (hexDigitValue == -1) {
context.addMessage(new InvalidCharacterInHexDirectiveErrorMessage(currentCodePoint));
// Continue to next operand.
break;
}
byte byteValue = (byte) (hexDigitValue << 4);
reader.advance();
reader.skipWhitespace();
if (reader.atEnd()) {
context.addMessage(new OddNumberOfCharactersInHexDirectiveErrorMessage());
// Continue to next operand.
break;
}
currentCodePoint = reader.getCurrentCodePoint();
assert currentCodePoint != -1;
// Parse the second nybble of a nybble pair.
hexDigitValue = getHexDigitValue(currentCodePoint);
if (hexDigitValue == -1) {
context.addMessage(new InvalidCharacterInHexDirectiveErrorMessage(currentCodePoint));
// Continue to next operand.
break;
}
byteValue |= hexDigitValue;
// Add the parsed byte to the buffer.
context.builder.appendAssembledData(byteValue);
}
}
}
}