package org.reasm.m68k.assembly.internal;
import java.io.IOException;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
import org.reasm.m68k.InstructionSet;
/**
* The <code>MOVEP</code> instruction.
*
* @author Francis Gagné
*/
@Immutable
class MovepInstruction extends TwoEaInstruction {
@Nonnull
static final MovepInstruction MOVEP = new MovepInstruction();
@Nonnull
private static final Set<AddressingMode> ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT = Collections.unmodifiableSet(EnumSet
.of(AddressingMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT));
@Nonnull
private static final Set<AddressingMode> DATA_REGISTER_DIRECT_OR_ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT = Collections
.unmodifiableSet(EnumSet.of(AddressingMode.DATA_REGISTER_DIRECT,
AddressingMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT));
@Override
void assemble(M68KAssemblyContext context, InstructionSize size, EffectiveAddress ea0, EffectiveAddress ea1) throws IOException {
final EffectiveAddress eaOutput;
final int dataRegister;
int mode;
if (ea0.isAddressRegisterIndirectWithDisplacement() && ea1.isDataRegisterDirect()) {
eaOutput = ea0;
dataRegister = ea1.getRegister();
mode = 0;
} else if (ea0.isDataRegisterDirect() && ea1.isAddressRegisterIndirectWithDisplacement()) {
eaOutput = ea1;
dataRegister = ea0.getRegister();
mode = 1 << 7;
} else {
return;
}
switch (size) {
case BYTE:
context.addInvalidSizeAttributeErrorMessage();
break;
case WORD:
case DEFAULT:
default:
break;
case LONG:
mode |= 1 << 6;
break;
}
eaOutput.word0 = (short) (0b00000001_00001000 | dataRegister << 9 | mode | eaOutput.getRegister());
context.appendEffectiveAddress(eaOutput);
}
@Override
Set<AddressingMode> getValidAddressingModesForDestinationOperand(InstructionSet instructionSet, EffectiveAddress ea0) {
if (ea0.isDataRegisterDirect()) {
return ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT;
}
if (ea0.isAddressRegisterIndirectWithDisplacement()) {
return AddressingModeCategory.DATA_REGISTER_DIRECT;
}
return DATA_REGISTER_DIRECT_OR_ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT;
}
@Override
Set<AddressingMode> getValidAddressingModesForSourceOperand(InstructionSet instructionSet) {
return DATA_REGISTER_DIRECT_OR_ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT;
}
}