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>ABCD</code>, <code>ADDX</code>, <code>SBCD</code> and <code>SUBX</code> instructions. * * @author Francis Gagné */ @Immutable class AddSubWithExtendInstruction extends TwoEaInstruction { @Immutable private static class AbcdSbcd extends AddSubWithExtendInstruction { AbcdSbcd(int fixedBits) { super(fixedBits); } @Override InstructionSize getInstructionSize(M68KAssemblyContext context) { final InstructionSize size = context.parseIntegerInstructionSize(); if (size != InstructionSize.DEFAULT && size != InstructionSize.BYTE) { context.addInvalidSizeAttributeErrorMessage(); } return InstructionSize.BYTE; } } @Nonnull static final AddSubWithExtendInstruction ABCD = new AddSubWithExtendInstruction.AbcdSbcd(0b100 << 12); @Nonnull static final AddSubWithExtendInstruction ADDX = new AddSubWithExtendInstruction(0b101 << 12); @Nonnull static final AddSubWithExtendInstruction SBCD = new AddSubWithExtendInstruction.AbcdSbcd(0b000 << 12); @Nonnull static final AddSubWithExtendInstruction SUBX = new AddSubWithExtendInstruction(0b001 << 12); @Nonnull private static final Set<AddressingMode> DATA_REGISTER_DIRECT_OR_ADDRESS_REGISTER_INDIRECT_WITH_PREDECREMENT = Collections .unmodifiableSet(EnumSet.of(AddressingMode.DATA_REGISTER_DIRECT, AddressingMode.ADDRESS_REGISTER_INDIRECT_WITH_PREDECREMENT)); private final int fixedBits; AddSubWithExtendInstruction(int fixedBits) { this.fixedBits = fixedBits | 0b10000001 << 8; } @Override void assemble(M68KAssemblyContext context, InstructionSize size, EffectiveAddress ea0, EffectiveAddress ea1) throws IOException { final int mode; if (ea0.isDataRegisterDirect() && ea1.isDataRegisterDirect()) { // Register to register mode = 0; } else if (ea0.isAddressRegisterIndirectWithPredecrement() && ea1.isAddressRegisterIndirectWithPredecrement()) { // Memory to memory mode = 1 << 3; } else { return; } context.appendWord((short) (this.fixedBits | ea1.getRegister() << 9 | encodeIntegerSizeStandard(size) | mode | ea0 .getRegister())); } @Override Set<AddressingMode> getValidAddressingModesForDestinationOperand(InstructionSet instructionSet, EffectiveAddress ea0) { if (ea0.isDataRegisterDirect()) { return AddressingModeCategory.DATA_REGISTER_DIRECT; } if (ea0.isAddressRegisterIndirectWithPredecrement()) { return AddressingModeCategory.ADDRESS_REGISTER_INDIRECT_WITH_PREDECREMENT; } return DATA_REGISTER_DIRECT_OR_ADDRESS_REGISTER_INDIRECT_WITH_PREDECREMENT; } @Override Set<AddressingMode> getValidAddressingModesForSourceOperand(InstructionSet instructionSet) { return DATA_REGISTER_DIRECT_OR_ADDRESS_REGISTER_INDIRECT_WITH_PREDECREMENT; } }