From 1ab8a6a988c748535a895ddd315cbf5250761605 Mon Sep 17 00:00:00 2001 From: Peter Rutenbar Date: Thu, 10 Sep 2015 16:27:00 -0400 Subject: [PATCH] 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) --- core/cpu.c | 200 ++++++++++++++++++++++------------------------------- 1 file changed, 84 insertions(+), 116 deletions(-) diff --git a/core/cpu.c b/core/cpu.c index 1ecd64f..ef17dd7 100644 --- a/core/cpu.c +++ b/core/cpu.c @@ -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) { - ~decompose(shoe.op, 1101 xxx 1 ss 00 r yyy); - const uint8_t sz = 1< register + S = shoe.d[y]; + D = shoe.d[x]; + R = S + D + sr_x(); 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 - // FIXME: Definitely broken! - // The subx version thinks that (sz==1) means predecrement 2 bytes, but I have no idea where it got that logic from. - assert(y!=7 && x!=7); - const uint32_t predec_y = shoe.a[y] - sz; - const uint32_t predec_x = shoe.a[x] - sz; + else { + // Memory -> memory + // Usual rules apply for byte-size if x or y is a7 + 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); - const uint32_t S = lget(predec_y, 4); - if sunlikely(shoe.abort) return ; - const uint32_t D = lget(predec_x, 4); + S = lget(source_addr, sz); if sunlikely(shoe.abort) return ; - // Sm = mib(S + extend_bit, sz); // FIXME: sure you want to do this? - 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); + D = lget(dest_addr, sz); if sunlikely(shoe.abort) return ; - shoe.a[y] = predec_y; - shoe.a[x] = predec_x; + R = S + D + sr_x(); - if (chopped_R) // Z is cleared only if result is non-zero - set_sr_z(0); + lset(dest_addr, sz, R); + 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_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); } - static void inst_cmp (void) { // cmp , Dn // -> source @@ -1178,35 +1159,29 @@ static void inst_cmpa (void) { static void inst_cmpm (void) { ~decompose(shoe.op, 1011 xxx 1 ss 001 yyy); - 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 ; - const uint32_t src = lget(ay, sz); + const uint32_t D = lget(dest_addr, sz); if sunlikely(shoe.abort) return ; - // *I believe* that if x==y, then that register will only be incremented *once* - // WRONG! + const uint32_t R = D - S; - if (sz == 1) - assert(x!=7 && y!=7); + shoe.a[y] = post_source_addr; + shoe.a[x] = post_dest_addr; - if (x == y) { - shoe.a[x] += sz + 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); + const _Bool Sm = mib(S, sz); + const _Bool Dm = mib(D, sz); + const _Bool Rm = mib(R, sz); set_sr_z(chop(R, sz) == 0); set_sr_n(Rm); @@ -2090,60 +2065,53 @@ static void inst_pea (void) { // decrement the stack pointer if lset didn't abort shoe.a[7] -= 4; } - -static void inst_subx (void) { - ~decompose(shoe.op, 1001 yyy 1 ss 00 m xxx); - const uint8_t sz = 1< register + S = shoe.d[y]; + D = shoe.d[x]; + R = D - S - sr_x(); + set_d(x, R, sz); } else { - const uint32_t src = shoe.d[x]; - const uint32_t dst = shoe.d[y]; - const uint32_t result = dst - src - (sr_x()?1:0); + // Memory -> memory + // Usual rules apply for byte-size if x or y is a7 + 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); - const uint8_t Dm = mib(dst, sz); - const uint8_t Rm = mib(result, sz); + D = lget(dest_addr, sz); + if sunlikely(shoe.abort) return ; - 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); + R = D - S - sr_x(); + + lset(dest_addr, sz, R); + 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)!=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) { @@ -2236,7 +2204,7 @@ static void inst_nop (void) {} static void inst_chk (void) { ~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);