仕様の変更
前回の仕様に、グローバル変数を定義する方法を追加します。
疑似関数
疑似関数を追加します。これらは関数を呼び出す手順で呼び出すものとします。
- muls
- mulu
- divs
- divu
- sin
- cos
- sqrt
- itof
- itod
プログラムを実行する処理
コードの後半の部分は Visual Studio が自動的に補完したもので、まだ動かせるようにはなっていません。
void executeInstruction(const string& line, CPUState& cpu) { if (cpu.debug) cout << "Executing: " << line << endl; string label; string opcode; size_t spacePos = line.find(' '); std::vector<Operand> operands; if (spacePos != std::string::npos) { opcode = line.substr(0, spacePos); string operands_str = line.substr(spacePos); size_t commaPos = operands_str.find(','); // かっこで囲まれた部分をとばす size_t parenPos = operands_str.find('('); if (parenPos != std::string::npos) { size_t closePos = operands_str.substr(parenPos).find(')') + parenPos; commaPos = operands_str.substr(closePos).find(',') + closePos; } if (commaPos != std::string::npos) { operands.push_back(Operand(operands_str.substr(0, commaPos))); operands.push_back(Operand(operands_str.substr(commaPos))); } else { operands.push_back(Operand(operands_str)); } } else { opcode = line; // オペコードのみの場合 } Instruction instruction(label, opcode); if(instruction.is_move_instruction()) { // MOVE命令の処理 if (operands.size() != 2) { cerr << "Invalid MOVE instruction: " << line << endl; return; } Operand& src = operands[0]; Operand& dst = operands[1]; int32_t value = src.get_value(instruction.data_size()); dst.set_value(value, instruction.data_size()); } else if (instruction.is_movem_instruction()) { // MOVEM命令の処理 if (operands.size() != 2) { cerr << "Invalid MOVEM instruction: " << line << endl; return; } Operand& regs = operands[0]; Operand& addr = operands[1]; int32_t address = addr.get_address(); for (char reg : regs.get_string()) { if (reg == 'd') continue; // dレジスタは無視 int regIndex = reg - '0'; cpu.stack.push_back(cpu.d[regIndex]); cpu.a[7] -= 4; } } else if (instruction.is_jump_instruction()) { // JMP命令の処理 if (operands.size() != 1) { cerr << "Invalid JMP instruction: " << line << endl; return; } string label = operands[0].get_string(); if (cpu.labelTable.count(label)) { cpu.pc = cpu.labelTable[label]; return; // skip increment } else { cerr << "Unknown label in JMP: " << label << endl; } } else if (instruction.is_conditional_jump_instruction()) { // 条件付きジャンプ命令の処理 if (operands.size() != 1) { cerr << "Invalid conditional jump instruction: " << line << endl; return; } string label = operands[0].get_string(); if (cpu.labelTable.count(label)) { string condition = instruction.get_jump_condition(); if ((condition == "E" && cpu.is_zero) || (condition == "NE" && !cpu.is_zero) || (condition == "G" && !cpu.is_zero && !cpu.is_sign) || (condition == "GE" && !cpu.is_sign) || (condition == "L" && cpu.is_sign) || (condition == "LE" && (cpu.is_sign || cpu.is_zero)) || (condition == "A" && !cpu.is_carry && !cpu.is_zero) || (condition == "AE" && !cpu.is_carry) || (condition == "B" && cpu.is_carry) || (condition == "BE" && cpu.is_carry) || (condition == "S" && cpu.is_sign) || (condition == "NS" && !cpu.is_sign) || (condition == "O" && cpu.is_overflow) || (condition == "NO" && !cpu.is_overflow)) { cpu.pc = cpu.labelTable[label]; return; // skip increment } } else { cerr << "Unknown label in conditional jump: " << label << endl; } } else if (instruction.is_jsr_instruction()) { // JSR命令の処理 if (operands.size() != 1) { cerr << "Invalid JSR instruction: " << line << endl; return; } string label = operands[0].get_string(); if (cpu.labelTable.count(label)) { cpu.stack.push_back(cpu.pc + 1); cpu.a[7] -= 4; cpu.pc = cpu.labelTable[label]; return; // skip increment } else { cerr << "Unknown label in JSR: " << label << endl; } } else if (instruction.is_rts_instruction()) { // RTS命令の処理 if (!cpu.stack.empty()) { cpu.pc = cpu.stack.back(); cpu.stack.pop_back(); cpu.a[7] += 4; return; // skip increment } else { cerr << "Return stack empty!" << endl; } } else if (instruction.is_lea_instruction()) { // LEA命令の処理 if (operands.size() != 2) { cerr << "Invalid LEA instruction: " << line << endl; return; } Operand& src = operands[0]; Operand& dst = operands[1]; int32_t val = src.get_value(4); // .Lは4バイト if (dst.get_string()[0] == 'a') { cpu.a[dst.get_string()[1] - '0'] = val; // Aレジスタに設定 } } else if (instruction.is_pea_instruction()) { // PEA命令の処理 if (operands.size() != 1) { cerr << "Invalid PEA instruction: " << line << endl; return; } Operand& operand = operands[0]; int32_t addr = operand.get_address(); cpu.stack.push_back(addr); cpu.a[7] -= 4; // スタックポインタを調整 } else if (instruction.is_link_instruction()) { // LINK命令の処理 if (operands.size() != 2) { cerr << "Invalid LINK instruction: " << line << endl; return; } string reg = operands[0].get_string(); int32_t offset = operands[1].get_value(4); // .Lは4バイト if (reg[0] == 'a') { int regIndex = reg[1] - '0'; cpu.stack.push_back(cpu.a[regIndex]); cpu.a[regIndex] = cpu.a[7]; cpu.a[7] -= offset; // スタックポインタを調整 } else { cerr << "Invalid register in LINK: " << reg << endl; } } else if (instruction.is_unlk_instruction()) { // UNLK命令の処理 if (operands.size() != 1) { cerr << "Invalid UNLK instruction: " << line << endl; return; } string reg = operands[0].get_string(); if (reg[0] == 'a') { int regIndex = reg[1] - '0'; cpu.a[7] = cpu.a[regIndex]; cpu.a[regIndex] = cpu.stack.back(); cpu.stack.pop_back(); } else { cerr << "Invalid register in UNLK: " << reg << endl; } } 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 val = src.get_value(instruction.data_size()); if (dst.get_string()[0] == 'a') { cpu.a[dst.get_string()[1] - '0'] += val; // Aレジスタに加算 } else if (dst.get_string()[0] == 'd') { cpu.d[dst.get_string()[1] - '0'] += val; // Dレジスタに加算 } } 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 val = src.get_value(instruction.data_size()); if (dst.get_string()[0] == ' a') { cpu.a[dst.get_string()[1] - '0'] -= val; // Aレジスタから減算 } else if (dst.get_string()[0] == 'd') { cpu.d[dst.get_string()[1] - '0'] -= val; // Dレジスタから減算 } } 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 s = src.get_value(instruction.data_size()); int32_t d = dst.get_value(instruction.data_size()); cpu.is_zero = (s == d); cpu.is_sign = (s < 0); cpu.is_carry = (s < d); cpu.is_overflow = ((s < 0 && d >= 0 && s > d) || (s >= 0 && d < 0 && s < d)); if (cpu.debug) cout << "Compare " << s << " and " << d << endl; } else if (instruction.is_neg_instruction()) { // NEG命令の処理 if (operands.size() != 1) { cerr << "Invalid NEG instruction: " << line << endl; return; } Operand& dst = operands[0]; int32_t val = dst.get_value(instruction.data_size()); dst.set_value(-val, instruction.data_size()); } else if (instruction.is_tst_instruction()) { // TST命令の処理 if (operands.size() != 1) { cerr << "Invalid TST instruction: " << line << endl; return; } Operand& dst = operands[0]; int32_t val = dst.get_value(instruction.data_size()); cpu.is_zero = (val == 0); cpu.is_sign = (val < 0); cpu.is_carry = (val < 0); // TSTは符号ビットをチェック cpu.is_overflow = false; // TSTではオーバーフローは考慮しない if (cpu.debug) cout << "Test " << val << endl; } else if (instruction.is_and_instruction()) { // AND命令の処理 if (operands.size() != 2) { cerr << "Invalid AND instruction: " << line << endl; return; } Operand& src = operands[0]; Operand& dst = operands[1]; int32_t val = src.get_value(instruction.data_size()); int32_t dst_val = dst.get_value(instruction.data_size()); dst.set_value(dst_val & val, instruction.data_size()); } else if (instruction.is_or_instruction()) { // OR命令の処理 if (operands.size() != 2) { cerr << "Invalid OR instruction: " << line << endl; return; } Operand& src = operands[0]; Operand& dst = operands[1]; int32_t val = src.get_value(instruction.data_size()); int32_t dst_val = dst.get_value(instruction.data_size()); dst.set_value(dst_val | val, instruction.data_size()); } else if (instruction.is_eor_instruction()) { // XOR命令の処理 if (operands.size() != 2) { cerr << "Invalid EOR instruction: " << line << endl; return; } Operand& src = operands[0]; Operand& dst = operands[1]; int32_t val = src.get_value(instruction.data_size()); int32_t dst_val = dst.get_value(instruction.data_size()); dst.set_value(dst_val ^ val, instruction.data_size()); } else if (instruction.is_not_instruction()) { // NOT命令の処理 if (operands.size() != 1) { cerr << "Invalid NOT instruction: " << line << endl; return; } Operand& dst = operands[0]; int32_t val = dst.get_value(instruction.data_size()); dst.set_value(~val, instruction.data_size()); } else if (instruction.is_shift_instruction()) { // シフト命令の処理 if (operands.size() != 2) { cerr << "Invalid shift instruction: " << line << endl; return; } Operand& src = operands[0]; Operand& dst = operands[1]; int32_t val = src.get_value(4); // .Lは4バイト int32_t dst_val = dst.get_value(instruction.data_size()); if (instruction.is_left_shift()) { dst.set_value(dst_val << val, instruction.data_size()); } else { dst.set_value(dst_val >> val, instruction.data_size()); } } else if (instruction.is_rotate_instruction()) { // ローテート命令の処理 if (operands.size() != 2) { cerr << "Invalid rotate instruction: " << line << endl; return; } Operand& src = operands[0]; Operand& dst = operands[1]; int32_t val = src.get_value(4); // .Lは4バイト int32_t dst_val = dst.get_value(instruction.data_size()); if (instruction.mnemonic_upper.find("ROL") == 0) { dst.set_value((dst_val << val) | (dst_val >> (32 - val)), instruction.data_size()); } else if (instruction.mnemonic_upper.find("ROR") == 0) { dst.set_value((dst_val >> val) | (dst_val << (32 - val)), instruction.data_size()); } } cpu.pc++; }

