非専門的シンギュラリティー研究所

無限に動き続けるシステムを表す方法を AI なども使って考えていきます。

アセンブラ(10)

executeInstruction 関数の処理(4)

算術演算系の命令には以下のようなものがあります。

add, adda, addq, addx

「add src, dst」は dst と src の和を dst に設定します。addx は繰り上がりの処理をします。adda は詳細が書かれていなかったので add と同様とします。addq は制限がある以外は add と同じです。

フラグは N と Z は値によって変化し、V はオーバーフロー発生のとき 1、そうでないとき 0、C と X は繰り上がりがあるとき 1、そうでないとき 0 です。

    else if (instruction.is_add_instruction()) {
        // ADD命令の処理
        if (operands.size() != 2) {
            cerr << "Invalid ADD instruction: " << line << endl;
            return;
        }
        Operand& src = operands[0];
        Operand& dst = operands[1];
        int32_t src_value = src.get_value(instruction.data_size());
        int32_t dst_value = dst.get_value(instruction.data_size());
        int extended = instruction.is_extended_operation() ? cpu.is_extended ? 1 : 0 : 0;
        int32_t value = dst_value + src_value + extended;
        dst.set_value(value, instruction.data_size());
        if (instruction.modifies_flags()) {
            // ADD命令はフラグを変更する場合がある
            cpu.set_add_status(src_value, dst_value, extended, instruction.data_size());
        }
    }
sub, suba, subq, subx

「sub src, dst」は dst と src の差を dst に設定します。subx は繰り下がりの処理をします。suba は詳細が書かれていなかったので sub と同様とします。subq は制限がある以外は sub と同じです。

フラグは N と Z は値によって変化し、V はオーバーフロー発生のとき 1、そうでないとき 0、C と X は繰り下がりあるとき 1、そうでないとき 0 です。

    else if (instruction.is_sub_instruction()) {
        // SUB命令の処理
        if (operands.size() != 2) {
            cerr << "Invalid SUB instruction: " << line << endl;
            return;
        }
        Operand& src = operands[0];
        Operand& dst = operands[1];
        int32_t src_value = src.get_value(instruction.data_size());
        int32_t dst_value = dst.get_value(instruction.data_size());
        int extended = instruction.is_extended_operation() ? cpu.is_extended ? 1 : 0 : 0;
        int32_t value = dst_value - src_value - extended;
        dst.set_value(value, instruction.data_size());
        if (instruction.modifies_flags()) {
            // SUB命令はフラグを変更する場合がある
            cpu.set_subtract_status(src_value, dst_value, extended, instruction.data_size());
        }
    }
cmp, cmpa

「cmp src, dst」は dst と src の差を計算したときのフラグを設定します。dst は変更されません。cmpa は詳細が書かれていなかったので cmp と同様とします。

フラグは N と Z は値によって変化し、V はオーバーフロー発生のとき 1、そうでないとき 0、C は繰り下がりあるとき 1、そうでないとき 0 です。X は変化しません。

    else if (instruction.is_cmp_instruction()) {
        // CMP命令の処理
        if (operands.size() != 2) {
            cerr << "Invalid CMP instruction: " << line << endl;
            return;
        }
        Operand& src = operands[0];
        Operand& dst = operands[1];
        int32_t src_value = src.get_value(instruction.data_size());
        int32_t dst_value = dst.get_value(instruction.data_size());
        if (instruction.modifies_flags()) {
            // CMP命令はフラグを変更する場合がある
            cpu.set_subtract_status(src_value, dst_value, 0, instruction.data_size());
        }
    }
neg, negx

「neg dst」は dst を符号付き数として符号を変えたものを dst に設定します。negx は繰り下がりの処理をします。

フラグは N と Z は値によって変化し、V はオーバーフロー発生のとき 1、そうでないとき 0、C と X は繰り下がりあるとき 1、そうでないとき 0 です。オーバーフロー発生とは何かは不明です。

    else if (instruction.is_neg_instruction()) {
        // NEG命令の処理
        if (operands.size() != 1) {
            cerr << "Invalid NEG instruction: " << line << endl;
            return;
        }
        Operand& dst = operands[0];
        int32_t dst_value = dst.get_value(instruction.data_size());
        int extended = instruction.is_extended_operation() ? cpu.is_extended ? 1 : 0 : 0;
        int32_t value = -dst_value - extended;
        dst.set_value(value, instruction.data_size());
        if (instruction.modifies_flags()) {
            cpu.set_neg_status(value, extended, instruction.data_size());
        }
    }
tst

「tst dst」は 0 から dst を引いたときのフラグを設定します。dst は変更されません。

フラグは N と Z は値によって変化し、V と C は 0、X は変化しません。

    else if (instruction.is_tst_instruction()) {
        // TST命令の処理
        if (operands.size() != 1) {
            cerr << "Invalid TST instruction: " << line << endl;
            return;
        }
        Operand& dst = operands[0];
        int32_t value = dst.get_value(instruction.data_size());
        if (instruction.modifies_flags()) {
            cpu.set_value_status(value, instruction.data_size());
        }
    }
clr

clr dst」は dst に 0 を設定します。

フラグは Z は 1、N と V と C は 0、X は変化しません。

    else if (instruction.is_clr_instruction()) {
        // CLR命令の処理
        if (operands.size() != 1) {
            cerr << "Invalid CLR instruction: " << line << endl;
            return;
        }
        Operand& dst = operands[0];
        int32_t value = 0;
        if (instruction.modifies_flags()) {
            cpu.set_value_status(value, instruction.data_size());
        }
    }