/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.dx.dex.code;

import com.android.dx.rop.code.RegisterSpec;
import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.rop.code.SourcePosition;
import com.android.dx.rop.type.Type;
import com.android.dx.util.AnnotatedOutput;

/**
 * Combination instruction which turns into a variable number of
 * {@code move*} instructions to move a set of registers into
 * registers starting at {@code 0} sequentially. This is used
 * in translating an instruction whose register requirements cannot
 * be met using a straightforward choice of a single opcode.
 */
public final class HighRegisterPrefix extends VariableSizeInsn {
    /** {@code null-ok;} cached instructions, if constructed */
    private SimpleInsn[] insns;

    /**
     * Constructs an instance. The output address of this instance is initially
     * unknown ({@code -1}).
     *
     * @param position {@code non-null;} source position
     * @param registers {@code non-null;} source registers
     */
    public HighRegisterPrefix(SourcePosition position,
                              RegisterSpecList registers) {
        super(position, registers);

        if (registers.size() == 0) {
            throw new IllegalArgumentException("registers.size() == 0");
        }

        insns = null;
    }

    /** {@inheritDoc} */
    @Override
    public int codeSize() {
        int result = 0;

        calculateInsnsIfNecessary();

        for (SimpleInsn insn : insns) {
            result += insn.codeSize();
        }

        return result;
    }

    /** {@inheritDoc} */
    @Override
    public void writeTo(AnnotatedOutput out) {
        calculateInsnsIfNecessary();

        for (SimpleInsn insn : insns) {
            insn.writeTo(out);
        }
    }

    /**
     * Helper for {@link #codeSize} and {@link #writeTo} which sets up
     * {@link #insns} if not already done.
     */
    private void calculateInsnsIfNecessary() {
        if (insns != null) {
            return;
        }

        RegisterSpecList registers = getRegisters();
        int sz = registers.size();

        insns = new SimpleInsn[sz];

        for (int i = 0, outAt = 0; i < sz; i++) {
            RegisterSpec src = registers.get(i);
            insns[i] = moveInsnFor(src, outAt);
            outAt += src.getCategory();
        }
    }

    /** {@inheritDoc} */
    @Override
    public DalvInsn withRegisters(RegisterSpecList registers) {
        return new HighRegisterPrefix(getPosition(), registers);
    }

    /** {@inheritDoc} */
    @Override
    protected String argString() {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    protected String listingString0(boolean noteIndices) {
        RegisterSpecList registers = getRegisters();
        int sz = registers.size();
        StringBuffer sb = new StringBuffer(100);

        for (int i = 0, outAt = 0; i < sz; i++) {
            RegisterSpec src = registers.get(i);
            SimpleInsn insn = moveInsnFor(src, outAt);

            if (i != 0) {
                sb.append('\n');
            }

            sb.append(insn.listingString0(noteIndices));

            outAt += src.getCategory();
        }

        return sb.toString();
    }

    /**
     * Returns the proper move instruction for the given source spec
     * and destination index.
     *
     * @param src {@code non-null;} the source register spec
     * @param destIndex {@code >= 0;} the destination register index
     * @return {@code non-null;} the appropriate move instruction
     */
    private static SimpleInsn moveInsnFor(RegisterSpec src, int destIndex) {
        return DalvInsn.makeMove(SourcePosition.NO_INFO,
                RegisterSpec.make(destIndex, src.getType()),
                src);
    }
}
