package net.katsuster.semu;

import java.util.*;

/**
 * ARM コプロセッサ。
 *
 * @author katsuhiro
 */
public class CoProc {
    private int no;
    private CPU cpu;
    private Map<Integer, Register> cregs;

    /**
     * コプロセッサを生成します。
     *
     * @param no  コプロセッサ番号
     * @param cpu コプロセッサが接続されている CPU
     */
    public CoProc(int no, CPU cpu) {
        this.no = no;
        this.cpu = cpu;
        this.cregs = new HashMap<Integer, Register>();
    }

    /**
     * コプロセッサ番号を取得します。
     *
     * @return コプロセッサ番号
     */
    public int getNumber() {
        return no;
    }

    /**
     * コプロセッサが接続されている CPU を取得します。
     *
     * @return コプロセッサが取得されている CPU
     */
    public CPU getCPU() {
        return cpu;
    }

    /**
     * コプロセッサレジスタの定義を追加します。
     *
     * @param cn   コプロセッサレジスタ番号
     * @param name レジスタ名
     */
    public void addCReg(int cn, String name) {
        cregs.put(cn, new Register(name, 0));
    }

    /**
     * コプロセッサレジスタの定義を追加します。
     *
     * @param cn   コプロセッサレジスタ番号
     * @param name レジスタ名
     * @param val  レジスタの初期値
     */
    public void addCReg(int cn, String name, int val) {
        cregs.put(cn, new Register(name, val));
    }

    /**
     * コプロセッサレジスタ番号を取得します。
     *
     * レジスタ番号は、4ビットずつのフィールドに分かれています。
     * ビット [15:12]: CRn
     * ビット [11:8]: opcode_1
     * ビット [7:4]: CRm
     * ビット [3:0]: opcode_2
     * を指定します。
     *
     * @param crn
     * @param opcode1
     * @param crm
     * @param opcode2
     * @return
     */
    public static int getCRegID(int crn, int opcode1, int crm, int opcode2) {
        return ((crn & 0x0f) << 12) |
                ((opcode1 & 0x07) << 8) |
                ((crm & 0x0f) << 4) |
                ((opcode2 & 0x07) << 0);
    }

    /**
     * コプロセッサレジスタ番号が有効かどうかを取得します。
     *
     * @param cn コプロセッサレジスタ番号
     * @return 指定したレジスタが存在するなら true、存在しなければ false
     */
    public boolean validCRegNumber(int cn) {
        return cregs.containsKey(cn);
    }

    /**
     * コプロセッサレジスタの値を取得します。
     *
     * レジスタ番号は、4ビットずつのフィールドに分かれています。
     * ビット [15:12]: CRn
     * ビット [11:8]: opcode_1
     * ビット [7:4]: CRm
     * ビット [3:0]: opcode_2
     * を指定します。
     *
     * @param cn コプロセッサレジスタ番号
     * @return レジスタの値
     */
    public int getCReg(int cn) {
        Register r;

        r = cregs.get(cn);
        if (r == null) {
            throw new IllegalArgumentException(String.format(
                    "Illegal coproc %d reg(%08x).", getNumber(), cn));
        }

        return r.getValue();
    }

    /**
     * コプロセッサレジスタの値を設定します。
     *
     * レジスタ番号は、4ビットずつのフィールドに分かれています。
     * ビット [15:12]: CRn
     * ビット [11:8]: opcode_1
     * ビット [7:4]: CRm
     * ビット [3:0]: opcode_2
     * を指定します。
     *
     * @param cn   コプロセッサレジスタ番号
     * @param val 新しいレジスタの値
     */
    public void setCReg(int cn, int val) {
        Register r;

        r = cregs.get(cn);
        if (r == null) {
            throw new IllegalArgumentException(String.format(
                    "Illegal coproc %d reg(%08x).", getNumber(), cn));
        }

        r.setValue(val);
    }

    @Override
    public String toString() {
        return String.format("p%d", getNumber());
    }
}

@@ -683,18 +683,18 @@
  %E3%82%B3%E3%83%97%E3%83%AD%E3%82%BB%E3%83%83%E3%82%B5%E3%81%8C
-%E5%8F%96%E5%BE%97
+%E6%8E%A5%E7%B6%9A
 %E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B CP

fix comments.