DIV, JMP & RTS fix

This commit is contained in:
folkert van heusden 2022-03-24 16:17:35 +01:00
parent c761ff824d
commit 85327f0d6b

51
cpu.cpp
View file

@ -294,20 +294,14 @@ uint16_t cpu::getGAMAddress(const uint8_t mode, const int reg, const bool word_m
return getRegister(reg, prev_mode); return getRegister(reg, prev_mode);
case 2: case 2:
temp = getRegister(reg, prev_mode); temp = getRegister(reg, prev_mode);
if (reg == 6 || reg == 7) addRegister(reg, prev_mode, !word_mode || reg == 6 || reg == 7 ? 2 : 1);
addRegister(reg, prev_mode, 2);
else
addRegister(reg, prev_mode, word_mode ? 1 : 2);
return temp; return temp;
case 3: case 3:
temp = b -> readWord(getRegister(reg, prev_mode)); temp = b -> readWord(getRegister(reg, prev_mode));
addRegister(reg, prev_mode, 2); addRegister(reg, prev_mode, 2);
return temp; return temp;
case 4: case 4:
if (reg == 6 || reg == 7) addRegister(reg, prev_mode, !word_mode || reg == 6 || reg == 7 ? -2 : -1);
addRegister(reg, prev_mode, -2);
else
addRegister(reg, prev_mode, word_mode ? -1 : -2);
return getRegister(reg, prev_mode); return getRegister(reg, prev_mode);
case 5: case 5:
addRegister(reg, prev_mode, -2); addRegister(reg, prev_mode, -2);
@ -496,25 +490,32 @@ bool cpu::additional_double_operand_instructions(const uint16_t instr)
setPSW_v(true); setPSW_v(true);
setPSW_c(true); setPSW_c(true);
break; return true;
} }
int32_t R0R1 = (getRegister(reg) << 16) | getRegister(reg + 1); int32_t R0R1 = (getRegister(reg) << 16) | getRegister(reg + 1);
int32_t quot = R0R1 / divider; int32_t quot = R0R1 / divider;
uint16_t rem = R0R1 % divider; uint16_t rem = R0R1 % divider;
fprintf(stderr, "value: %d, divider: %d, gives: %d / %d\n", R0R1, divider, quot, rem); fprintf(stderr, "value: %d, divider: %d, gives: %d / %d\n", R0R1, divider, quot, rem);
fprintf(stderr, "value: %o, divider: %o, gives: %o / %o\n", R0R1, divider, quot, rem); fprintf(stderr, "value: %o, divider: %o, gives: %o / %o\n", R0R1, divider, quot, rem);
// TODO: handle results out of range // TODO: handle results out of range
setPSW_n(quot < 0);
setPSW_z(quot == 0);
setPSW_c(false);
if (quot > 32767 || quot < -32768) {
setPSW_v(true);
return true;
}
setRegister(reg, quot); setRegister(reg, quot);
setRegister(reg + 1, rem); setRegister(reg + 1, rem);
setPSW_n(quot < 0); setPSW_v(false);
setPSW_z(quot == 0);
setPSW_v(quot > 32767 || quot < -32768);
setPSW_c(false);
return true; return true;
} }
@ -1168,14 +1169,22 @@ bool cpu::misc_operations(const uint16_t instr)
} }
if ((instr & ~0b111111) == 0b0000000001000000) { // JMP if ((instr & ~0b111111) == 0b0000000001000000) { // JMP
int dst_mode = (instr >> 3) & 7, dst_reg = instr & 7; int dst_mode = (instr >> 3) & 7;
bool word_mode = false;
setPC(getGAMAddress(dst_mode, dst_reg, word_mode, false)); if (dst_mode == 0) // cannot jump to a register
trap(010);
else {
int dst_reg = instr & 7;
bool word_mode = false;
setPC(getGAMAddress(dst_mode, dst_reg, word_mode, false));
}
return true; return true;
} }
if ((instr & 0b1111111000000000) == 0b0000100000000000) { // JSR if ((instr & 0b1111111000000000) == 0b0000100000000000) { // JSR
const int link_reg = (instr >> 6) & 7; int link_reg = (instr >> 6) & 7;
uint16_t dst_value = getGAMAddress((instr >> 3) & 7, instr & 7, false, false); uint16_t dst_value = getGAMAddress((instr >> 3) & 7, instr & 7, false, false);
// PUSH link // PUSH link
@ -1193,11 +1202,13 @@ bool cpu::misc_operations(const uint16_t instr)
if ((instr & 0b1111111111111000) == 0b0000000010000000) { // RTS if ((instr & 0b1111111111111000) == 0b0000000010000000) { // RTS
const int link_reg = instr & 7; const int link_reg = instr & 7;
uint16_t v = popStack();
// MOVE link, PC // MOVE link, PC
setPC(getRegister(link_reg, false)); setPC(getRegister(link_reg, false));
// POP link // POP link
setRegister(link_reg, false, popStack()); setRegister(link_reg, false, v);
return true; return true;
} }