package org.reasm.m68k.assembly.internal; import java.io.IOException; import javax.annotation.Nonnull; import javax.annotation.concurrent.Immutable; import org.reasm.AssemblyMessage; import org.reasm.Value; import org.reasm.m68k.messages.AlignmentMustNotBeZeroOrNegativeErrorMessage; import com.google.common.primitives.UnsignedLongs; /** * The <code>ALIGN</code> directive. * * @author Francis Gagné */ @Immutable class AlignDirective extends Mnemonic { @Nonnull static final AlignDirective ALIGN = new AlignDirective(); @Nonnull private static final CardinalValueVisitor.ErrorFactory NEGATIVE_VALUE_ERROR_FACTORY = new CardinalValueVisitor.ErrorFactory() { @Override public AssemblyMessage createMessage() { return new AlignmentMustNotBeZeroOrNegativeErrorMessage(); } }; @Override void assemble(M68KAssemblyContext context) throws IOException { context.sizeNotAllowed(); if (context.requireNumberOfOperands(1)) { final Value alignmentValue = evaluateExpressionOperand(context, 0); if (alignmentValue != null) { final CardinalValueVisitor alignmentVisitor = context.cardinalValueVisitor; alignmentVisitor.reset(1, NEGATIVE_VALUE_ERROR_FACTORY); Value.accept(alignmentValue, alignmentVisitor); final long alignment = alignmentVisitor.getValue(); if (alignment != 0) { final long remainder = UnsignedLongs.remainder(context.programCounter, alignment); final long paddingSize = remainder == 0 ? 0 : alignment - remainder; for (long i = 0; UnsignedLongs.compare(i, paddingSize) < 0; i++) { context.appendByte((byte) 0); } } else { context.addTentativeMessage(new AlignmentMustNotBeZeroOrNegativeErrorMessage()); } } } } }