more MMR1 rework

This commit is contained in:
folkert van heusden 2024-04-12 20:47:39 +02:00
parent 92642c0e17
commit f2d8c7d5f9
Signed by untrusted user who does not match committer: folkert
GPG key ID: 6B6455EDFEED3BD1
2 changed files with 62 additions and 23 deletions

75
cpu.cpp
View file

@ -363,20 +363,16 @@ void cpu::queue_interrupt(const uint8_t level, const uint8_t vector)
DOLOG(debug, false, "Queueing interrupt vector %o (IPL %d, current: %d), n: %zu", vector, level, getPSW_spl(), it->second.size());
}
void cpu::addToMMR1(const uint8_t mode, const uint8_t reg, const word_mode_t word_mode)
void cpu::addToMMR1(const gam_rc_t & g)
{
bool neg = mode == 4 || mode == 5;
if (word_mode == wm_word || reg >= 6 || mode == 6 || mode == 7)
b->addToMMR1(neg ? -2 : 2, reg);
else
b->addToMMR1(neg ? -1 : 1, reg);
if (g.mmr1_update.has_value())
b->addToMMR1(g.mmr1_update.value().delta, g.mmr1_update.value().reg);
}
// GAM = general addressing modes
gam_rc_t cpu::getGAM(const uint8_t mode, const uint8_t reg, const word_mode_t word_mode, const rm_selection_t mode_selection, const bool read_value)
{
gam_rc_t g { word_mode, mode_selection, i_space, mode, { }, { }, { } };
gam_rc_t g { word_mode, mode_selection, i_space, mode, { }, { }, { }, { } };
d_i_space_t isR7_space = reg == 7 ? i_space : (b->get_use_data_space(getPSW_runmode()) ? d_space : i_space);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ always d_space here? TODO
@ -400,20 +396,20 @@ gam_rc_t cpu::getGAM(const uint8_t mode, const uint8_t reg, const word_mode_t wo
if (read_value)
g.value = b->read(g.addr.value(), word_mode, mode_selection, false, isR7_space);
addRegister(reg, mode_selection, word_mode == wm_word || reg == 7 || reg == 6 ? 2 : 1);
addToMMR1(mode, reg, word_mode == wm_word || reg == 7 || reg == 6 ? wm_word : wm_byte);
g.mmr1_update = { word_mode == wm_word || reg == 7 || reg == 6 ? 2 : 1, reg };
break;
case 3: // @(Rn)+ / @#a
g.addr = b->read(getRegister(reg, mode_selection), wm_word, mode_selection, false, isR7_space);
// might be wrong: the adds should happen when the read is really performed, because of traps
addRegister(reg, mode_selection, 2);
addToMMR1(mode, reg, wm_word);
g.mmr1_update = { 2, reg };
g.space = d_space;
if (read_value)
g.value = b->read(g.addr.value(), word_mode, mode_selection, false, g.space);
break;
case 4: // -(Rn)
addRegister(reg, mode_selection, word_mode == wm_word || reg == 7 || reg == 6 ? -2 : -1);
addToMMR1(mode, reg, word_mode == wm_word || reg == 7 || reg == 6 ? wm_word : wm_byte);
g.mmr1_update = { word_mode == wm_word || reg == 7 || reg == 6 ? -2 : -1, reg };
g.space = d_space;
g.addr = getRegister(reg, mode_selection);
if (read_value)
@ -421,7 +417,7 @@ gam_rc_t cpu::getGAM(const uint8_t mode, const uint8_t reg, const word_mode_t wo
break;
case 5: // @-(Rn)
addRegister(reg, mode_selection, -2);
addToMMR1(mode, reg, wm_word);
g.mmr1_update = { -2, reg };
g.addr = b->read(getRegister(reg, mode_selection), wm_word, mode_selection, false, isR7_space);
g.space = d_space;
if (read_value)
@ -494,21 +490,19 @@ bool cpu::double_operand_instructions(const uint16_t instr)
switch(operation) {
case 0b001: { // MOV/MOVB Move Word/Byte
gam_rc_t g_src;
if (word_mode == wm_byte && dst_mode == 0) {
g_src = getGAM(src_mode, src_reg, word_mode, rm_cur);
gam_rc_t g_src = getGAM(src_mode, src_reg, word_mode, rm_cur);
if (word_mode == wm_byte && dst_mode == 0)
setRegister(dst_reg, int8_t(g_src.value.value())); // int8_t: sign extension
}
else {
auto g_dst = getGAM(dst_mode, dst_reg, word_mode, rm_cur, false);
g_src = getGAM(src_mode, src_reg, word_mode, rm_cur);
addToMMR1(g_dst);
set_flags = putGAM(g_dst, g_src.value.value());
}
addToMMR1(g_src);
if (set_flags)
setPSW_flags_nzv(g_src.value.value(), word_mode);
@ -517,8 +511,10 @@ bool cpu::double_operand_instructions(const uint16_t instr)
case 0b010: { // CMP/CMPB Compare Word/Byte
auto g_dst = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
addToMMR1(g_dst);
gam_rc_t g_src = getGAM(src_mode, src_reg, word_mode, rm_cur);
addToMMR1(g_src);
uint16_t temp = (g_src.value.value() - g_dst.value.value()) & (word_mode == wm_byte ? 0xff : 0xffff);
@ -532,8 +528,10 @@ bool cpu::double_operand_instructions(const uint16_t instr)
case 0b011: { // BIT/BITB Bit Test Word/Byte
auto g_dst = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
addToMMR1(g_dst);
gam_rc_t g_src = getGAM(src_mode, src_reg, word_mode, rm_cur);
addToMMR1(g_src);
uint16_t result = (g_dst.value.value() & g_src.value.value()) & (word_mode == wm_byte ? 0xff : 0xffff);
@ -544,8 +542,10 @@ bool cpu::double_operand_instructions(const uint16_t instr)
case 0b100: { // BIC/BICB Bit Clear Word/Byte
auto g_dst = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
addToMMR1(g_dst);
gam_rc_t g_src = getGAM(src_mode, src_reg, word_mode, rm_cur);
addToMMR1(g_src);
uint16_t result = g_dst.value.value() & ~g_src.value.value();
@ -558,8 +558,10 @@ bool cpu::double_operand_instructions(const uint16_t instr)
case 0b101: { // BIS/BISB Bit Set Word/Byte
// TODO: retain MSB for register operations?
auto g_dst = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
addToMMR1(g_dst);
gam_rc_t g_src = getGAM(src_mode, src_reg, word_mode, rm_cur);
addToMMR1(g_src);
uint16_t result = g_dst.value.value() | g_src.value.value();
@ -574,8 +576,10 @@ bool cpu::double_operand_instructions(const uint16_t instr)
case 0b110: { // ADD/SUB Add/Subtract Word
auto g_dst = getGAM(dst_mode, dst_reg, wm_word, rm_cur);
addToMMR1(g_dst);
auto g_ssrc = getGAM(src_mode, src_reg, wm_word, rm_cur);
addToMMR1(g_ssrc);
int16_t result = 0;
@ -632,6 +636,7 @@ bool cpu::additional_double_operand_instructions(const uint16_t instr)
int16_t R1 = getRegister(reg);
auto R2g = getGAM(dst_mode, dst_reg, wm_word, rm_cur);
addToMMR1(R2g);
int16_t R2 = R2g.value.value();
int32_t result = R1 * R2;
@ -648,6 +653,7 @@ bool cpu::additional_double_operand_instructions(const uint16_t instr)
case 1: { // DIV
auto R2g = getGAM(dst_mode, dst_reg, wm_word, rm_cur);
addToMMR1(R2g);
int16_t divider = R2g.value.value();
int32_t R0R1 = (uint32_t(getRegister(reg)) << 16) | getRegister(reg | 1);
@ -694,6 +700,7 @@ bool cpu::additional_double_operand_instructions(const uint16_t instr)
uint32_t R = getRegister(reg), oldR = R;
auto g_dst = getGAM(dst_mode, dst_reg, wm_word, rm_cur);
addToMMR1(g_dst);
uint16_t shift = g_dst.value.value() & 077;
bool sign = SIGN(R, wm_word);
@ -745,6 +752,7 @@ bool cpu::additional_double_operand_instructions(const uint16_t instr)
uint32_t R0R1 = (uint32_t(getRegister(reg)) << 16) | getRegister(reg | 1);
auto g_dst = getGAM(dst_mode, dst_reg, wm_word, rm_cur);
addToMMR1(g_dst);
uint16_t shift = g_dst.value.value() & 077;
bool sign = R0R1 & 0x80000000;
@ -801,6 +809,7 @@ bool cpu::additional_double_operand_instructions(const uint16_t instr)
case 4: { // XOR (word only)
uint16_t reg_v = getRegister(reg); // in case it is R7
auto g_dst = getGAM(dst_mode, dst_reg, wm_word, rm_cur);
addToMMR1(g_dst);
uint16_t vl = g_dst.value.value() ^ reg_v;
bool set_flags = putGAM(g_dst, vl);
@ -840,6 +849,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
return false;
auto g_dst = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
addToMMR1(g_dst);
uint16_t v = g_dst.value.value();
@ -867,6 +877,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
}
else {
auto g_dst = getGAM(dst_mode, dst_reg, word_mode, rm_cur, false);
addToMMR1(g_dst);
set_flags = putGAM(g_dst, 0);
}
@ -894,6 +905,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
}
else {
auto a = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
addToMMR1(a);
v = a.value.value();
if (word_mode == wm_byte)
@ -928,6 +940,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
}
else {
auto a = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
addToMMR1(a);
int32_t vl = (a.value.value() + 1) & (word_mode == wm_byte ? 0xff : 0xffff);
bool set_flags = b->write(a.addr.value(), a.word_mode, vl, a.mode_selection, a.space).is_psw == false;
@ -959,6 +972,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
}
else {
auto a = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
addToMMR1(a);
int32_t vl = (a.value.value() - 1) & (word_mode == wm_byte ? 0xff : 0xffff);
bool set_flags = b->write(a.addr.value(), a.word_mode, vl, a.mode_selection, a.space).is_psw == false;
@ -990,6 +1004,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
}
else {
auto a = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
addToMMR1(a);
uint16_t v = -a.value.value();
bool set_flags = b->write(a.addr.value(), a.word_mode, v, a.mode_selection, a.space).is_psw == false;
@ -1024,6 +1039,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
}
else {
auto a = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
addToMMR1(a);
const uint16_t vo = a.value.value();
bool org_c = getPSW_c();
uint16_t v = (vo + org_c) & (word_mode == wm_byte ? 0x00ff : 0xffff);
@ -1060,6 +1076,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
}
else {
auto a = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
addToMMR1(a);
const uint16_t vo = a.value.value();
bool org_c = getPSW_c();
uint16_t v = (vo - org_c) & (word_mode == wm_byte ? 0xff : 0xffff);
@ -1077,7 +1094,9 @@ bool cpu::single_operand_instructions(const uint16_t instr)
}
case 0b000101111: { // TST/TSTB
uint16_t v = getGAM(dst_mode, dst_reg, word_mode, rm_cur).value.value();
auto g = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
uint16_t v = g.value.value();
addToMMR1(g);
setPSW_flags_nzv(v, word_mode);
setPSW_c(false);
@ -1105,6 +1124,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
}
else {
auto a = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
addToMMR1(a);
uint16_t t = a.value.value();
bool new_carry = t & 1;
@ -1150,6 +1170,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
}
else {
auto a = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
addToMMR1(a);
uint16_t t = a.value.value();
bool new_carry = false;
@ -1196,6 +1217,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
}
else {
auto a = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
addToMMR1(a);
uint16_t v = a.value.value();
uint16_t hb = word_mode == wm_byte ? v & 128 : v & 32768;
@ -1236,6 +1258,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
}
else {
auto a = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
addToMMR1(a);
uint16_t vl = a.value.value();
uint16_t v = (vl << 1) & (word_mode == wm_byte ? 0xff : 0xffff);
@ -1262,6 +1285,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
else {
// calculate address in current address space
auto a = getGAMAddress(dst_mode, dst_reg, wm_word);
addToMMR1(a);
int prev_run_mode = getPSW_prev_runmode();
bool is_d = word_mode == wm_byte;
@ -1308,6 +1332,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
setRegister(dst_reg, v, rm_prev);
else {
auto a = getGAMAddress(dst_mode, dst_reg, wm_word);
addToMMR1(a);
b->mmudebug(a.addr.value());
@ -1363,6 +1388,7 @@ bool cpu::single_operand_instructions(const uint16_t instr)
}
else { // SXT
auto g_dst = getGAM(dst_mode, dst_reg, word_mode, rm_cur);
addToMMR1(g_dst);
uint16_t vl = -getPSW_n();
@ -1593,7 +1619,9 @@ bool cpu::misc_operations(const uint16_t instr)
int dst_reg = instr & 7;
setPC(getGAMAddress(dst_mode, dst_reg, wm_word).addr.value());
auto g = getGAMAddress(dst_mode, dst_reg, wm_word);
addToMMR1(g);
setPC(g.addr.value());
return true;
}
@ -1605,7 +1633,8 @@ bool cpu::misc_operations(const uint16_t instr)
int dst_reg = instr & 7;
auto dst_value = getGAMAddress(dst_mode, dst_reg, wm_word).addr.value();
auto a = getGAMAddress(dst_mode, dst_reg, wm_word);
auto dst_value = a.addr.value();
int link_reg = (instr >> 6) & 7;
@ -1613,6 +1642,8 @@ bool cpu::misc_operations(const uint16_t instr)
pushStack(getRegister(link_reg));
b->addToMMR1(-2, 6);
addToMMR1(a);
// MOVE PC,link
setRegister(link_reg, getPC());

10
cpu.h
View file

@ -15,12 +15,20 @@
#include "bus.h"
typedef struct {
int delta;
unsigned reg;
} mmr1_delta_t;
typedef struct {
word_mode_t word_mode;
rm_selection_t mode_selection;
d_i_space_t space;
int access_mode;
// for MMR1 register
std::optional<mmr1_delta_t> mmr1_update;
std::optional<uint16_t> addr;
std::optional<int> reg;
@ -64,7 +72,7 @@ private:
uint16_t addRegister(const int nr, const rm_selection_t mode_selection, const uint16_t value);
void addToMMR1(const uint8_t mode, const uint8_t reg, const word_mode_t word_mode);
void addToMMR1(const gam_rc_t & g);
gam_rc_t getGAM(const uint8_t mode, const uint8_t reg, const word_mode_t word_mode, const rm_selection_t mode_selection, const bool read_value = true);
gam_rc_t getGAMAddress(const uint8_t mode, const int reg, const word_mode_t word_mode);