package org.reasm.m68k.assembly.internal; import java.io.IOException; import java.util.Set; import javax.annotation.Nonnull; import javax.annotation.concurrent.Immutable; import org.reasm.m68k.messages.MovemRequiresARegisterListInExactlyOneOperandErrorMessage; /** * The <code>MOVEM</code> instruction. * * @author Francis Gagné */ @Immutable class MovemInstruction extends TwoOperandIntegerInstruction { @Nonnull static final MovemInstruction MOVEM = new MovemInstruction(); private MovemInstruction() { } @Override void assemble(M68KAssemblyContext context, InstructionSize size) throws IOException { if (size == InstructionSize.BYTE) { context.addInvalidSizeAttributeErrorMessage(); size = InstructionSize.DEFAULT; } final EffectiveAddress ea = context.ea0; final Set<GeneralPurposeRegister> registerListLeft = parseRegisterList(context, 0); final Set<GeneralPurposeRegister> registerListRight = parseRegisterList(context, 1); final Set<GeneralPurposeRegister> registerList; final int direction; if (registerListLeft != null) { if (registerListRight != null) { context.addMessage(new MovemRequiresARegisterListInExactlyOneOperandErrorMessage()); return; } context.getEffectiveAddress(context.getOperandText(1), AddressingModeCategory.CONTROL_ALTERABLE_WITH_PREDECREMENT, size, 4, ea); registerList = registerListLeft; direction = 0; } else { if (registerListRight == null) { context.addMessage(new MovemRequiresARegisterListInExactlyOneOperandErrorMessage()); return; } context.getEffectiveAddress(context.getOperandText(0), AddressingModeCategory.CONTROL_WITH_POSTINCREMENT, size, 4, ea); registerList = registerListRight; direction = 1 << 10; } ea.word0 |= 0b01001000_10000000 | direction | (size == InstructionSize.LONG ? 1 << 6 : 0); short registerMask = 0; if (ea.isAddressRegisterIndirectWithPredecrement()) { for (GeneralPurposeRegister register : registerList) { registerMask |= 1 << 15 - register.ordinal(); } } else { for (GeneralPurposeRegister register : registerList) { registerMask |= 1 << register.ordinal(); } } context.appendWord(ea.word0); context.appendWord(registerMask); context.appendEffectiveAddress(ea, 1); } }