Fixed bugs in addx, subx, and cmpm

(cmpm was setting the CC codes based on a garbage source operand, so fixing that might fix a lot of other problems)
This commit is contained in:
Peter Rutenbar 2015-09-10 16:27:00 -04:00
parent 7f8b393fcc
commit 1ab8a6a988

View File

@ -1038,72 +1038,53 @@ static void inst_adda (void) {
} }
} }
/*static void inst_addx (void) {
~decompose(shoe.op, 1101 xxx 1 ss 00 r yyy);
const uint16_t sz = 1 << s;
} */
static void inst_addx (void) { static void inst_addx (void) {
~decompose(shoe.op, 1101 xxx 1 ss 00 r yyy); ~decompose(shoe.op, 1101 xxx 1 ss 00 m yyy);
const uint8_t sz = 1<<s; const uint8_t sz = 1 << s;
const uint8_t extend_bit = (sr_x() != 0); uint32_t S, D, R;
uint8_t Sm, Dm, Rm; if (!m) {
// Register -> register
if (!r) { // x and y are data registers S = shoe.d[y];
// Sm = mib(shoe.d[y] + extend_bit, sz); // FIXME: I am almost certain this is wrong D = shoe.d[x];
Sm = mib(shoe.d[y], sz); R = S + D + sr_x();
Dm = mib(shoe.d[x], sz);
const uint32_t R = shoe.d[y] + extend_bit + shoe.d[x];
// slog("addx: S d[%u] = 0x%x, D d[%u] = 0x%x, R = 0x%x\n", crop(shoe.d[y], sz), crop(shoe.d[x], sz), crop(R, sz));
set_d(x, R, sz); set_d(x, R, sz);
Rm = mib(R, sz);
if (chop(R, sz)) // Z is cleared only if result is non-zero
set_sr_z(0);
} }
else { // memory to memory else {
// FIXME: Definitely broken! // Memory -> memory
// The subx version thinks that (sz==1) means predecrement 2 bytes, but I have no idea where it got that logic from. // Usual rules apply for byte-size if x or y is a7
assert(y!=7 && x!=7); const uint32_t source_addr = shoe.a[y] - (y == 7 ? 2 : 1);
const uint32_t predec_y = shoe.a[y] - sz; // The decrements are cumulative if x==y
const uint32_t predec_x = shoe.a[x] - sz; const uint32_t dest_addr = ((x == y) ? source_addr : shoe.a[x]) - (x == 7 ? 2 : 1);
const uint32_t S = lget(predec_y, 4); S = lget(source_addr, sz);
if sunlikely(shoe.abort) return ;
const uint32_t D = lget(predec_x, 4);
if sunlikely(shoe.abort) return ; if sunlikely(shoe.abort) return ;
// Sm = mib(S + extend_bit, sz); // FIXME: sure you want to do this? D = lget(dest_addr, sz);
Sm = mib(S, sz);
Dm = mib(D, sz);
const uint32_t R = S + extend_bit + D;
Rm = mib(R, sz);
const uint32_t chopped_R = chop(R, sz);
lset(chopped_R, sz, shoe.dat);
if sunlikely(shoe.abort) return ; if sunlikely(shoe.abort) return ;
shoe.a[y] = predec_y; R = S + D + sr_x();
shoe.a[x] = predec_x;
if (chopped_R) // Z is cleared only if result is non-zero lset(dest_addr, sz, R);
set_sr_z(0); if sunlikely(shoe.abort) return ;
shoe.a[y] = source_addr;
shoe.a[x] = dest_addr;
} }
const _Bool Sm = mib(S, sz);
const _Bool Dm = mib(D, sz);
const _Bool Rm = mib(R, sz);
if (chop(R, sz))
set_sr_z(0); // Z is cleared only if result is non-zero
set_sr_v((Sm && Dm && !Rm) || (!Sm && !Dm && Rm)); set_sr_v((Sm && Dm && !Rm) || (!Sm && !Dm && Rm));
set_sr_c((Sm && Dm) || (!Rm && Dm) || (Sm && !Rm)); set_sr_c((Sm && Dm) || (!Rm && Dm) || (Sm && !Rm));
set_sr_x(sr_c()); set_sr_x((Sm && Dm) || (!Rm && Dm) || (Sm && !Rm));
set_sr_n(Rm); set_sr_n(Rm);
} }
static void inst_cmp (void) { static void inst_cmp (void) {
// cmp <ea>, Dn // cmp <ea>, Dn
// <ea> -> source // <ea> -> source
@ -1178,35 +1159,29 @@ static void inst_cmpa (void) {
static void inst_cmpm (void) { static void inst_cmpm (void) {
~decompose(shoe.op, 1011 xxx 1 ss 001 yyy); ~decompose(shoe.op, 1011 xxx 1 ss 001 yyy);
const uint8_t sz = 1 << s; const uint8_t sz = 1 << s;
const uint32_t ax = shoe.a[x];
const uint32_t ay = shoe.a[y] + ((x==y) ? sz : 0); // if x==y, then we pop the stack twice
const uint32_t dst = lget(ax, sz); const uint32_t source_addr = shoe.a[y];
// Usual rules apply for byte-size if x or y is a7 (
const uint32_t post_source_addr = source_addr + sz + (y == 7 && sz == 1);
const uint32_t dest_addr = (x == y) ? post_source_addr : shoe.a[x];
// The increments are cumulative if x==y
const uint32_t post_dest_addr = dest_addr + sz + (x == 7 && sz == 1);
const uint32_t S = lget(source_addr, sz);
if sunlikely(shoe.abort) return ; if sunlikely(shoe.abort) return ;
const uint32_t src = lget(ay, sz); const uint32_t D = lget(dest_addr, sz);
if sunlikely(shoe.abort) return ; if sunlikely(shoe.abort) return ;
// *I believe* that if x==y, then that register will only be incremented *once* const uint32_t R = D - S;
// WRONG!
if (sz == 1) shoe.a[y] = post_source_addr;
assert(x!=7 && y!=7); shoe.a[x] = post_dest_addr;
if (x == y) { const _Bool Sm = mib(S, sz);
shoe.a[x] += sz + sz; const _Bool Dm = mib(D, sz);
} const _Bool Rm = mib(R, sz);
else {
shoe.a[x] += sz;
shoe.a[y] += sz;
}
const uint8_t Sm = ea_n(sz);
const uint8_t Dm = mib(dst,sz);
const uint32_t R = dst - src;
const uint8_t Rm = mib(R, sz);
set_sr_z(chop(R, sz) == 0); set_sr_z(chop(R, sz) == 0);
set_sr_n(Rm); set_sr_n(Rm);
@ -2090,60 +2065,53 @@ static void inst_pea (void) {
// decrement the stack pointer if lset didn't abort // decrement the stack pointer if lset didn't abort
shoe.a[7] -= 4; shoe.a[7] -= 4;
} }
static void inst_subx (void) {
~decompose(shoe.op, 1001 yyy 1 ss 00 m xxx);
const uint8_t sz = 1<<s;
if (m) {
assert(x!=7 && y!=7);
assert(sz != 1); // If this ever fires, the next line is broken
const uint8_t predecrement_sz = s?(1<<s):2; // predecrement-mode for size==byte decrements by 2 bytes
const uint32_t predecrement_x = shoe.a[x]-predecrement_sz;
const uint32_t predecrement_y = shoe.a[y]-predecrement_sz;
const uint32_t src = lget(predecrement_x, sz); static void inst_subx (void) {
if sunlikely(shoe.abort) return ; ~decompose(shoe.op, 1001 xxx 1 ss 00 m yyy);
const uint8_t sz = 1 << s;
const uint32_t dst = lget(predecrement_y, sz);
if sunlikely(shoe.abort) return ; uint32_t S, D, R;
const uint32_t result = dst - src - (sr_x()?1:0); if (!m) {
// Register -> register
lset(predecrement_y, sz, result); S = shoe.d[y];
D = shoe.d[x];
shoe.a[x] = predecrement_x; R = D - S - sr_x();
shoe.a[y] = predecrement_y; set_d(x, R, sz);
const uint8_t Sm = mib(src, sz);
const uint8_t Dm = mib(dst, sz);
const uint8_t Rm = mib(result, sz);
set_sr_v((!Sm && Dm && !Rm) || (Sm && !Dm && Rm));
set_sr_c((Sm && !Dm) || (Rm && !Dm) || (Sm && Rm));
set_sr_x(sr_c());
set_sr_n(Rm);
if (chop(result, sz)!=0)
set_sr_z(0);
} }
else { else {
const uint32_t src = shoe.d[x]; // Memory -> memory
const uint32_t dst = shoe.d[y]; // Usual rules apply for byte-size if x or y is a7
const uint32_t result = dst - src - (sr_x()?1:0); const uint32_t source_addr = shoe.a[y] - (y == 7 ? 2 : 1);
// The decrements are cumulative if x==y
const uint32_t dest_addr = ((x == y) ? source_addr : shoe.a[x]) - (x == 7 ? 2 : 1);
set_d(y, result, sz); S = lget(source_addr, sz);
if sunlikely(shoe.abort) return ;
const uint8_t Sm = mib(src, sz); D = lget(dest_addr, sz);
const uint8_t Dm = mib(dst, sz); if sunlikely(shoe.abort) return ;
const uint8_t Rm = mib(result, sz);
set_sr_v((!Sm && Dm && !Rm) || (Sm && !Dm && Rm)); R = D - S - sr_x();
set_sr_c((Sm && !Dm) || (Rm && !Dm) || (Sm && Rm));
set_sr_x(sr_c()); lset(dest_addr, sz, R);
set_sr_n(Rm); if sunlikely(shoe.abort) return ;
if (chop(result, sz)!=0)
set_sr_z(0); shoe.a[y] = source_addr;
shoe.a[x] = dest_addr;
} }
const _Bool Sm = mib(S, sz);
const _Bool Dm = mib(D, sz);
const _Bool Rm = mib(R, sz);
if (chop(R, sz)!=0)
set_sr_z(0); // Z is cleared only if result is non-zero
set_sr_v((!Sm && Dm && !Rm) || (Sm && !Dm && Rm));
set_sr_c((Sm && !Dm) || (Rm && !Dm) || (Sm && Rm));
set_sr_x((Sm && !Dm) || (Rm && !Dm) || (Sm && Rm));
set_sr_n(Rm);
} }
static void inst_suba (void) { static void inst_suba (void) {
@ -2236,7 +2204,7 @@ static void inst_nop (void) {}
static void inst_chk (void) { static void inst_chk (void) {
~decompose(shoe.op, 0100 rrr 1s 0 MMMMMM); ~decompose(shoe.op, 0100 rrr 1s 0 MMMMMM);
const uint8_t sz = s ? 2 : 4; const uint8_t sz = 4 >> s;
call_ea_read(M, sz); call_ea_read(M, sz);