package uk.jordandoyle.titan.asm;
import com.google.common.base.CharMatcher;
import com.google.common.io.BaseEncoding;
import uk.jordandoyle.titan.asm.instruction.Instruction;
import uk.jordandoyle.titan.asm.instruction.InstructionFactory;
import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.Deque;
public final class Assembly {
private Deque<Instruction> instructions = new ArrayDeque<>();
public void parseString(String instruction) throws IllegalAccessException, InstantiationException {
ByteBuffer bytes = ByteBuffer.wrap(BaseEncoding.base16().decode(CharMatcher.whitespace().removeFrom(instruction)));
while (bytes.hasRemaining()) {
int b = Byte.toUnsignedInt(bytes.get());
System.out.println("PARSING: " + Integer.toBinaryString(b) + " - " + Integer.toHexString(b));
byte highNibble = (byte) ((b >> 4) & 0x0F);
System.out.println("Opcode: " + String.format("%4s", Integer.toBinaryString(highNibble)).replace(' ', '0'));
byte lowNibble = (byte) (b & 0x0F);
System.out.println("Low nibble: " + String.format("%4s", Integer.toBinaryString(lowNibble)).replace(' ', '0'));
Instruction i = this.getInstruction(highNibble, lowNibble);
if (i == null) {
System.out.println("---");
continue;
}
Class<?>[] types = i.getOperandTypes();
System.out.println("Parameters: " + types.length);
for (int n = 0; n < types.length; n++) {
if (n == 0 && i.useCondAsOperand()) {
System.out.println("Param: " + String.format("%4s", Integer.toBinaryString(lowNibble)).replace(' ', '0'));
continue;
}
Class<?> type = types[n];
if (type.isAssignableFrom(byte.class)) {
byte param = bytes.get();
System.out.println("Param: " + String.format("%8s", Integer.toBinaryString(param)).replace(' ', '0'));
byte paramHighNibble = (byte) ((param >> 4) & 0x0F);
System.out.println(String.format("> Low nibble: %4s (%s)",
Integer.toBinaryString(paramHighNibble),
Integer.toHexString(paramHighNibble)));
byte paramLowNibble = (byte) (param & 0x0F);
System.out.println(String.format("> Low nibble: %4s (%s)",
Integer.toBinaryString(paramLowNibble),
Integer.toHexString(paramLowNibble)));
} else if (type.isAssignableFrom(short.class)) {
int param = ((bytes.get() & 0xFF) << 8) + (bytes.get() & 0xFF);
System.out.println("Param: (short) " + param);
} else {
System.out.println("ERROR: Class wanted " + type.getName() + " - we couldn't provide it.");
byte param = bytes.get();
System.out.println("Param: " + String.format("%8s", Integer.toBinaryString(param)).replace(' ', '0'));
}
}
System.out.println("---");
}
}
private Instruction getInstruction(byte highNibble, byte lowNibble) throws IllegalAccessException, InstantiationException {
for (InstructionFactory.InstructionType f : InstructionFactory.InstructionType.values()) {
Instruction i = f.getInstruction().newInstance();
if (i.getOpcode() == highNibble && (i.useCondAsOperand() || i.getCond() == lowNibble)) {
System.out.println("Added " + f.name());
return i;
}
}
System.out.println("ERROR: couldn't find instruction for op " + highNibble + ", cond " + lowNibble);
return null;
}
}