package org.reasm.m68k.assembly.internal;
import java.io.IOException;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
/**
* The <code>EXG</code> instruction.
*
* @author Francis Gagné
*/
@Immutable
class ExgInstruction extends TwoFixedEaInstruction {
@Nonnull
static final ExgInstruction EXG = new ExgInstruction();
private static final int OPMODE_DATA_REGISTERS = 0b01000 << 3;
private static final int OPMODE_ADDRESS_REGISTERS = 0b01001 << 3;
private static final int OPMODE_DATA_REGISTER_AND_ADDRESS_REGISTER = 0b10001 << 3;
private static void encode(@Nonnull M68KAssemblyContext context, int opmode, int registerRx, int registerRy) throws IOException {
context.appendWord((short) (0b11000001_00000000 | registerRx << 9 | opmode | registerRy));
}
private ExgInstruction() {
super(AddressingModeCategory.DATA_OR_ADDRESS_REGISTER_DIRECT, AddressingModeCategory.DATA_OR_ADDRESS_REGISTER_DIRECT);
}
@Override
void assemble(M68KAssemblyContext context, InstructionSize size, EffectiveAddress ea0, EffectiveAddress ea1) throws IOException {
if (ea0.isDataRegisterDirect()) {
if (ea1.isDataRegisterDirect()) {
// 2 data registers
encode(context, OPMODE_DATA_REGISTERS, ea0.getRegister(), ea1.getRegister());
} else if (ea1.isAddressRegisterDirect()) {
// Data register and address register
encode(context, OPMODE_DATA_REGISTER_AND_ADDRESS_REGISTER, ea0.getRegister(), ea1.getRegister());
}
} else if (ea0.isAddressRegisterDirect()) {
if (ea1.isDataRegisterDirect()) {
// Address register and data register
// The data register must be in Rx and the address register must be in Ry.
encode(context, OPMODE_DATA_REGISTER_AND_ADDRESS_REGISTER, ea1.getRegister(), ea0.getRegister());
} else if (ea1.isAddressRegisterDirect()) {
// 2 address registers
encode(context, OPMODE_ADDRESS_REGISTERS, ea0.getRegister(), ea1.getRegister());
}
}
}
@Override
InstructionSize getInstructionSize(M68KAssemblyContext context) {
final InstructionSize size = context.parseIntegerInstructionSize();
if (size != InstructionSize.DEFAULT && size != InstructionSize.LONG) {
context.addInvalidSizeAttributeErrorMessage();
}
return InstructionSize.LONG;
}
}