package org.reasm.m68k.assembly.internal; import java.io.IOException; import javax.annotation.Nonnull; import org.reasm.Function; import org.reasm.StringValue; import org.reasm.Value; import org.reasm.expressions.UnaryOperator; import org.reasm.m68k.messages.FunctionCannotBeConvertedToRealErrorMessage; final class DcFloatValueVisitor implements DcValueVisitor { private static double unsignedToFloat(long value) { if (value < 0) { // value >= 2**63 // By shifting, we lose the least significant bit, but a double doesn't have enough precision to represent that bit // anyway. return (value >>> 1) * 2.; } return value; } @Nonnull private final M68KAssemblyContext context; @Nonnull private InstructionSize size = InstructionSize.DEFAULT; private double output; DcFloatValueVisitor(@Nonnull M68KAssemblyContext context) { this.context = context; } @Override public void encode() throws IOException { switch (this.size) { case SINGLE: this.context.appendLong(Float.floatToRawIntBits((float) this.output)); break; case DOUBLE: default: this.context.appendQuad(Double.doubleToRawLongBits(this.output)); break; case EXTENDED: throw new RuntimeException("DC[B].X not implemented yet"); case PACKED: throw new RuntimeException("DC[B].P not implemented yet"); } } @Override public void reset(InstructionSize size) { this.size = size; this.output = 0; } @Override public Void visitFloat(double value) { this.output = value; return null; } @Override public Void visitFunction(Function value) { this.context.addTentativeMessage(new FunctionCannotBeConvertedToRealErrorMessage()); return null; } @Override public Void visitSignedInt(long value) { return this.visitFloat(value); } @Override public Void visitString(String value) { // Pass the value through the unary plus operator to convert it to a real value. return Value.accept(UnaryOperator.UNARY_PLUS.apply(new StringValue(value), this.context.getEvaluationContext()), this); } @Override public Void visitUndetermined() { return null; } @Override public Void visitUnsignedInt(long value) { return this.visitFloat(DcFloatValueVisitor.unsignedToFloat(value)); } }