cleanup of cpu::single_operand_instructions

This commit is contained in:
folkert van heusden 2022-03-20 20:52:43 +01:00
parent daa940986f
commit 1ad1b9aa0a

397
cpu.cpp
View file

@ -564,126 +564,138 @@ bool cpu::additional_double_operand_instructions(const uint16_t instr)
bool cpu::single_operand_instructions(const uint16_t instr) bool cpu::single_operand_instructions(const uint16_t instr)
{ {
const uint16_t opcode = (instr >> 6) & 0b111111111; const uint16_t opcode = (instr >> 6) & 0b111111111;
const uint8_t dst = instr & 63; const uint8_t dst = instr & 63;
const uint8_t dst_mode = (dst >> 3) & 7; const uint8_t dst_mode = (dst >> 3) & 7;
const uint8_t dst_reg = dst & 7; const uint8_t dst_reg = dst & 7;
const bool word_mode = !!(instr & 0x8000); const bool word_mode = !!(instr & 0x8000);
uint16_t a = -1;
int32_t vl = -1;
uint16_t v = -1;
switch(opcode) { switch(opcode) {
case 0b00000011: // SWAB case 0b00000011: { // SWAB
if (word_mode) // handled elsewhere if (word_mode) // handled elsewhere
return false; return false;
else { else {
a = getGAMAddress(dst_mode, dst_reg, word_mode, false); uint8_t t1 = 0, t2 = 0;
uint8_t t1, t2;
uint16_t t;
if (dst_mode == 0) {
t = getRegister(dst_reg, false);
t1 = t >> 8;
t2 = t & 255;
setRegister(dst_reg, false, (t2 << 8) | t1);
}
else {
t = getRegister(dst_reg, false);
t1 = b -> readByte(a);
t2 = b -> readByte(a + 1);
b -> writeByte(a, t2); if (dst_mode == 0) {
b -> writeByte(a + 1, t1); uint16_t t = getRegister(dst_reg, false);
} t1 = t >> 8;
t2 = t & 255;
setRegister(dst_reg, false, (t2 << 8) | t1);
}
else {
uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false);
uint16_t t = getRegister(dst_reg, false);
t1 = b -> readByte(a);
t2 = b -> readByte(a + 1);
setPSW_n(t1 & 0x80); b -> writeByte(a, t2);
setPSW_z(t1 == 0); b -> writeByte(a + 1, t1);
setPSW_v(false); }
setPSW_c(false);
break;
}
case 0b000101000: // CLR/CLRB setPSW_n(t1 & 0x80);
a = getGAMAddress(dst_mode, dst_reg, word_mode, false); setPSW_z(t1 == 0);
if (dst_mode == 0) setPSW_v(false);
putGAM(dst_mode, dst_reg, word_mode, 0, false); setPSW_c(false);
else }
b -> write(a, word_mode, 0);
setPSW_n(false);
setPSW_z(true);
setPSW_v(false);
setPSW_c(false);
break;
case 0b000101001: // COM/COMB break;
a = getGAMAddress(dst_mode, dst_reg, word_mode, false); }
v = b -> read(a, word_mode);
if (word_mode) case 0b000101000: { // CLR/CLRB
v ^= 0xff; if (dst_mode == 0)
else putGAM(dst_mode, dst_reg, word_mode, 0, false);
v ^= 0xffff; else {
uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false);
setPSW_n(SIGN(v, word_mode)); b -> write(a, word_mode, 0);
setPSW_z(v == 0); }
setPSW_v(false);
setPSW_c(true);
if (dst_mode == 0) setPSW_n(false);
putGAM(dst_mode, dst_reg, word_mode, v, false); setPSW_z(true);
else setPSW_v(false);
b -> write(a, word_mode, v); setPSW_c(false);
break; break;
}
case 0b000101010: // INC/INCB case 0b000101001: { // COM/COMB
a = getGAMAddress(dst_mode, dst_reg, word_mode, false); uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false);
v = b -> read(a, word_mode); uint16_t v = b -> read(a, word_mode);
vl = (v + 1) & (word_mode ? 0xff : 0xffff);
setPSW_n(word_mode ? vl > 127 : vl > 32767);
setPSW_z(vl == 0);
setPSW_v(word_mode ? v == 0x7f : v == 0x7fff);
if (dst_mode == 0)
putGAM(dst_mode, dst_reg, word_mode, vl, false);
else
b -> write(a, word_mode, vl);
break;
case 0b000101011: // DEC/DECB if (word_mode)
a = getGAMAddress(dst_mode, dst_reg, word_mode, false); v ^= 0xff;
v = b -> read(a, word_mode); else
vl = (v - 1) & (word_mode ? 0xff : 0xffff); v ^= 0xffff;
setPSW_n(word_mode ? vl > 127 : vl > 32767);
setPSW_z(vl == 0);
setPSW_v(word_mode ? v == 0x80 : v == 0x8000);
if (dst_mode == 0)
putGAM(dst_mode, dst_reg, word_mode, vl, false);
else
b -> write(a, word_mode, vl);
break;
case 0b000101100: // NEG/NEGB setPSW_n(SIGN(v, word_mode));
a = getGAMAddress(dst_mode, dst_reg, word_mode, false); setPSW_z(v == 0);
v = b -> read(a, word_mode); setPSW_v(false);
vl = word_mode ? uint8_t(-int8_t(v)) : -int16_t(v); setPSW_c(true);
if (dst_mode == 0)
putGAM(dst_mode, dst_reg, word_mode, vl, false); if (dst_mode == 0)
else putGAM(dst_mode, dst_reg, word_mode, v, false);
b -> write(a, word_mode, vl); else
setPSW_n(SIGN(vl, word_mode)); b -> write(a, word_mode, v);
setPSW_z(vl == 0);
setPSW_v(word_mode ? vl == 0x80 : vl == 0x8000); break;
setPSW_c(vl); }
break;
case 0b000101010: { // INC/INCB
uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false);
uint16_t v = b -> read(a, word_mode);
int32_t vl = (v + 1) & (word_mode ? 0xff : 0xffff);
setPSW_n(word_mode ? vl > 127 : vl > 32767);
setPSW_z(vl == 0);
setPSW_v(word_mode ? v == 0x7f : v == 0x7fff);
if (dst_mode == 0)
putGAM(dst_mode, dst_reg, word_mode, vl, false);
else
b -> write(a, word_mode, vl);
break;
}
case 0b000101011: { // DEC/DECB
uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false);
uint16_t v = b -> read(a, word_mode);
int32_t vl = (v - 1) & (word_mode ? 0xff : 0xffff);
setPSW_n(word_mode ? vl > 127 : vl > 32767);
setPSW_z(vl == 0);
setPSW_v(word_mode ? v == 0x80 : v == 0x8000);
if (dst_mode == 0)
putGAM(dst_mode, dst_reg, word_mode, vl, false);
else
b -> write(a, word_mode, vl);
break;
}
case 0b000101100: { // NEG/NEGB
uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false);
uint16_t v = b -> read(a, word_mode);
int32_t vl = word_mode ? uint8_t(-int8_t(v)) : -int16_t(v);
if (dst_mode == 0)
putGAM(dst_mode, dst_reg, word_mode, vl, false);
else
b -> write(a, word_mode, vl);
setPSW_n(SIGN(vl, word_mode));
setPSW_z(vl == 0);
setPSW_v(word_mode ? vl == 0x80 : vl == 0x8000);
setPSW_c(vl);
break;
}
case 0b000101101: { // ADC/ADCB case 0b000101101: { // ADC/ADCB
a = getGAMAddress(dst_mode, dst_reg, word_mode, false); uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false);
uint16_t org = b -> read(a, word_mode); uint16_t org = b -> read(a, word_mode);
uint16_t new_ = org + getPSW_c(); uint16_t new_ = org + getPSW_c();
if (dst_mode == 0) if (dst_mode == 0)
putGAM(dst_mode, dst_reg, word_mode, new_, false); putGAM(dst_mode, dst_reg, word_mode, new_, false);
else else
b -> write(a, word_mode, new_); b -> write(a, word_mode, new_);
setPSW_n(SIGN(new_, word_mode)); setPSW_n(SIGN(new_, word_mode));
setPSW_z(new_ == 0); setPSW_z(new_ == 0);
setPSW_v((word_mode ? org == 0x7f : org == 0x7fff) && getPSW_c()); setPSW_v((word_mode ? org == 0x7f : org == 0x7fff) && getPSW_c());
@ -691,37 +703,41 @@ bool cpu::single_operand_instructions(const uint16_t instr)
break; break;
} }
case 0b000101110: // SBC/SBCB case 0b000101110: { // SBC/SBCB
a = getGAMAddress(dst_mode, dst_reg, word_mode, false); uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false);
//fprintf(stderr, "%d,%d\n", dst_mode, dst_reg); //fprintf(stderr, "%d,%d\n", dst_mode, dst_reg);
v = b -> read(a, word_mode); uint16_t v = b -> read(a, word_mode);
vl = (v - getPSW_c()) & (word_mode ? 0xff : 0xffff); int32_t vl = (v - getPSW_c()) & (word_mode ? 0xff : 0xffff);
if (dst_mode == 0)
putGAM(dst_mode, dst_reg, word_mode, vl, false);
else
b -> write(a, word_mode, vl);
setPSW_n(SIGN(vl, word_mode));
setPSW_z(vl == 0);
setPSW_v(vl == 0x8000);
if (v == 0 && getPSW_c()) if (dst_mode == 0)
setPSW_c(true); putGAM(dst_mode, dst_reg, word_mode, vl, false);
else else
b -> write(a, word_mode, vl);
setPSW_n(SIGN(vl, word_mode));
setPSW_z(vl == 0);
setPSW_v(vl == 0x8000);
if (v == 0 && getPSW_c())
setPSW_c(true);
else
setPSW_c(false);
break;
}
case 0b000101111: { // TST/TSTB
uint16_t v = getGAM(dst_mode, dst_reg, word_mode, false);
setPSW_n(word_mode ? v & 128 : v & 32768);
setPSW_z(v == 0);
setPSW_v(false);
setPSW_c(false); setPSW_c(false);
break; break;
}
case 0b000101111: // TST/TSTB
v = getGAM(dst_mode, dst_reg, word_mode, false);
setPSW_n(word_mode ? v & 128 : v & 32768);
setPSW_z(v == 0);
setPSW_v(false);
setPSW_c(false);
break;
case 0b000110000: { // ROR/RORB case 0b000110000: { // ROR/RORB
a = getGAMAddress(dst_mode, dst_reg, word_mode, false); uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false);
uint16_t t = b -> read(a, word_mode); uint16_t t = b -> read(a, word_mode);
bool new_carry = t & 1; bool new_carry = t & 1;
uint16_t temp = 0; uint16_t temp = 0;
if (word_mode) { if (word_mode) {
@ -750,9 +766,9 @@ bool cpu::single_operand_instructions(const uint16_t instr)
} }
case 0b000110001: { // ROL/ROLB case 0b000110001: { // ROL/ROLB
a = getGAMAddress(dst_mode, dst_reg, word_mode, false); uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false);
uint16_t t = b -> read(a, word_mode); uint16_t t = b -> read(a, word_mode);
bool new_carry = false; bool new_carry = false;
uint16_t temp = 0; uint16_t temp = 0;
if (word_mode) { if (word_mode) {
@ -782,10 +798,10 @@ bool cpu::single_operand_instructions(const uint16_t instr)
} }
case 0b000110010: { // ASR/ASRB case 0b000110010: { // ASR/ASRB
a = getGAMAddress(dst_mode, dst_reg, word_mode, false); uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false);
vl = b -> read(a, word_mode); int32_t vl = b -> read(a, word_mode);
bool hb = word_mode ? vl & 128 : vl & 32768; bool hb = word_mode ? vl & 128 : vl & 32768;
setPSW_c(vl & 1); setPSW_c(vl & 1);
vl >>= 1; vl >>= 1;
@ -805,72 +821,79 @@ bool cpu::single_operand_instructions(const uint16_t instr)
break; break;
} }
case 0b00110011: // ASL/ASLB case 0b00110011: { // ASL/ASLB
a = getGAMAddress(dst_mode, dst_reg, word_mode, false); uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false);
vl = b -> read(a, word_mode); int32_t vl = b -> read(a, word_mode);
v = (vl << 1) & (word_mode ? 0xff : 0xffff); uint16_t v = (vl << 1) & (word_mode ? 0xff : 0xffff);
setPSW_n(word_mode ? v & 0x80 : v & 0x8000); setPSW_n(word_mode ? v & 0x80 : v & 0x8000);
setPSW_z(v == 0); setPSW_z(v == 0);
setPSW_c(word_mode ? vl & 0x80 : vl & 0x8000); setPSW_c(word_mode ? vl & 0x80 : vl & 0x8000);
setPSW_v(getPSW_n() ^ getPSW_c()); setPSW_v(getPSW_n() ^ getPSW_c());
if (dst_mode == 0) if (dst_mode == 0)
putGAM(dst_mode, dst_reg, word_mode, v, false); putGAM(dst_mode, dst_reg, word_mode, v, false);
else else
b -> write(a, word_mode, v); b -> write(a, word_mode, v);
break; break;
}
case 0b00110101: // MFPD/MFPI case 0b00110101: { // MFPD/MFPI
// FIXME // FIXME
v = getGAM(dst_mode, dst_reg, word_mode, true); uint16_t v = getGAM(dst_mode, dst_reg, word_mode, true);
setPSW_n(word_mode ? v & 0x80 : v & 0x8000); setPSW_n(word_mode ? v & 0x80 : v & 0x8000);
setPSW_z(v == 0); setPSW_z(v == 0);
setPSW_v(false); setPSW_v(false);
pushStack(v); pushStack(v);
break; break;
}
case 0b00110110: // MTPI/MTPD case 0b00110110: { // MTPI/MTPD
// FIXME // FIXME
a = getGAMAddress(dst_mode, dst_reg, word_mode, false); uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false);
v = popStack(); uint16_t v = popStack();
setPSW_n(word_mode ? v & 0x80 : v & 0x8000);
setPSW_z(v == 0); setPSW_n(word_mode ? v & 0x80 : v & 0x8000);
setPSW_v(false); setPSW_z(v == 0);
if (dst_mode == 0) setPSW_v(false);
putGAM(dst_mode, dst_reg, word_mode, v, true);
else if (dst_mode == 0)
b -> write(a, word_mode, v); // ? putGAM(dst_mode, dst_reg, word_mode, v, true);
break; else
b -> write(a, word_mode, v); // ?
break;
}
case 0b000110100: // MTPS (put something in PSW) case 0b000110100: // MTPS (put something in PSW)
psw &= 0xff00; // only alter lower 8 bits psw &= 0xff00; // only alter lower 8 bits
psw |= getGAM(dst_mode, dst_reg, word_mode, false) & 0xef; // can't change bit 4 psw |= getGAM(dst_mode, dst_reg, word_mode, false) & 0xef; // can't change bit 4
break; break;
case 0b000110111: // MFPS (get PSW to something) / SXT case 0b000110111: // MFPS (get PSW to something) / SXT
if (word_mode) { // MFPS if (word_mode) { // MFPS
uint16_t temp = psw & 0xff; uint16_t temp = psw & 0xff;
if (dst_mode == 0 && sign(temp))
temp |= 0xff00;
putGAM(dst_mode, dst_reg, word_mode, temp, false); if (dst_mode == 0 && sign(temp))
} temp |= 0xff00;
else { // SXT
a = getGAMAddress(dst_mode, dst_reg, word_mode, false);
vl = getPSW_n() ? -1 : 0; putGAM(dst_mode, dst_reg, word_mode, temp, false);
}
else { // SXT
uint16_t a = getGAMAddress(dst_mode, dst_reg, word_mode, false);
setPSW_z(getPSW_n() == false); int32_t vl = getPSW_n() ? -1 : 0;
setPSW_v(false);
if (dst_mode == 0) setPSW_z(getPSW_n() == false);
putGAM(dst_mode, dst_reg, word_mode, vl, false); setPSW_v(false);
else
b -> write(a, word_mode, vl); if (dst_mode == 0)
} putGAM(dst_mode, dst_reg, word_mode, vl, false);
break; else
b -> write(a, word_mode, vl);
}
break;
default: default:
return false; return false;
} }
return true; return true;