From 850dc2722b8ca17302d89c483b63693fa2fe9ef5 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sun, 28 May 2017 19:03:08 +0100 Subject: [PATCH] math/mpx.c: Fix two's-complement storing. Oh, dear. This was a bit wrong. * The internal representation, in terms of `mpw' vectors, is always nonnegative. Remove the bogus sign-extension machinery for `mpx_load*2cn'. * The logic for sign-extending octet vectors in `mpx_store*2cn' was the wrong way round. Fix it. * Rather than sign-extending `mpw' vectors, it's necessary to apply a correction when we reach the end of an octet vector in `mpx_load*2cn'. Introduce a new argument to `MPX_LOADSTORE' to carry the necessary correction logic, and use it. * The test functions used a single `mpw' vector length for both positive and negative values, which meant that the logic for sign- extending octet strings on output wasn't exercised. Fix the test: so that it now does two passes, forcing both sign-extension on output and zero-extension on input. --- math/mpx.c | 115 ++++++++++++++++++++++++++++++++++--------------------------- math/t/mpx | 36 ++++++++++++++++++- 2 files changed, 100 insertions(+), 51 deletions(-) diff --git a/math/mpx.c b/math/mpx.c index e759c5f2..18baf2f2 100644 --- a/math/mpx.c +++ b/math/mpx.c @@ -122,6 +122,7 @@ * @obits@ = width of output units, in bits * @oavail@ = condition expression: is output space available? * @putbits@ = function or macro: write its argument to output + * @fixfinal@ = statements to fix shift register at the end * @clear@ = statements to clear remainder of output * * Use: Generates a function to convert between a sequence of @@ -141,7 +142,7 @@ #define MPX_LOADSTORE(name, wconst, oconst, decls, \ ibits, iavail, getbits, obits, oavail, putbits, \ - clear) \ + fixfinal, clear) \ \ void mpx_##name(wconst mpw *v, wconst mpw *vl, \ oconst void *pp, size_t sz) \ @@ -157,7 +158,10 @@ void mpx_##name(wconst mpw *v, wconst mpw *vl, \ } \ \ flush: \ - while (bits > 0) MPX_PUTBITS(ibits, obits, oavail, putbits); \ + if (bits) { \ + fixfinal; \ + while (bits > 0) MPX_PUTBITS(ibits, obits, oavail, putbits); \ + } \ clear; \ } @@ -190,13 +194,14 @@ flush: \ *v++ = _t; \ } while (0) -#define FLUSHW_2CN do { \ - if (c) MPX_ONE(v, vl); \ - else MPX_ZERO(v, vl); \ +#define FIXFINALW_2CN do { \ + if (c && !w && !t); \ + else if (bits == 8) t ^= ~(mpw)0xffu; \ + else t ^= ((mpw)1 << (MPW_BITS - bits + 8)) - 256u; \ } while (0) #define FLUSHO_2CN do { \ - memset(p, c ? 0xff : 0, q - p); \ + memset(p, c ? 0 : 0xff, q - p); \ } while (0) /* --- @mpx_storel@ --- * @@ -215,7 +220,7 @@ flush: \ MPX_LOADSTORE(storel, const, EMPTY, EMPTY, MPW_BITS, (v < vl), GETMPW, 8, (p < q), PUTOCTETI, - { memset(p, 0, q - p); }) + EMPTY, { memset(p, 0, q - p); }) /* --- @mpx_loadl@ --- * * @@ -233,7 +238,7 @@ MPX_LOADSTORE(storel, const, EMPTY, EMPTY, MPX_LOADSTORE(loadl, EMPTY, const, EMPTY, 8, (p < q), GETOCTETI, MPW_BITS, (v < vl), PUTMPW, - { MPX_ZERO(v, vl); }) + EMPTY, { MPX_ZERO(v, vl); }) /* --- @mpx_storeb@ --- * @@ -252,7 +257,7 @@ MPX_LOADSTORE(loadl, EMPTY, const, EMPTY, MPX_LOADSTORE(storeb, const, EMPTY, EMPTY, MPW_BITS, (v < vl), GETMPW, 8, (p < q), PUTOCTETD, - { memset(p, 0, q - p); }) + EMPTY, { memset(p, 0, q - p); }) /* --- @mpx_loadb@ --- * * @@ -270,7 +275,7 @@ MPX_LOADSTORE(storeb, const, EMPTY, EMPTY, MPX_LOADSTORE(loadb, EMPTY, const, EMPTY, 8, (p < q), GETOCTETD, MPW_BITS, (v < vl), PUTMPW, - { MPX_ZERO(v, vl); }) + EMPTY, { MPX_ZERO(v, vl); }) /* --- @mpx_storel2cn@ --- * * @@ -289,7 +294,7 @@ MPX_LOADSTORE(loadb, EMPTY, const, EMPTY, MPX_LOADSTORE(storel2cn, const, EMPTY, DECL_2CN, MPW_BITS, (v < vl), GETMPW_2CN, 8, (p < q), PUTOCTETI, - { FLUSHO_2CN; }) + EMPTY, { FLUSHO_2CN; }) /* --- @mpx_loadl2cn@ --- * * @@ -308,7 +313,7 @@ MPX_LOADSTORE(storel2cn, const, EMPTY, DECL_2CN, MPX_LOADSTORE(loadl2cn, EMPTY, const, DECL_2CN, 8, (p < q), GETOCTETI, MPW_BITS, (v < vl), PUTMPW_2CN, - { FLUSHW_2CN; }) + { FIXFINALW_2CN; }, { MPX_ZERO(v, vl); }) /* --- @mpx_storeb2cn@ --- * * @@ -327,7 +332,7 @@ MPX_LOADSTORE(loadl2cn, EMPTY, const, DECL_2CN, MPX_LOADSTORE(storeb2cn, const, EMPTY, DECL_2CN, MPW_BITS, (v < vl), GETMPW_2CN, 8, (p < q), PUTOCTETD, - { FLUSHO_2CN; }) + EMPTY, { FLUSHO_2CN; }) /* --- @mpx_loadb2cn@ --- * * @@ -346,7 +351,7 @@ MPX_LOADSTORE(storeb2cn, const, EMPTY, DECL_2CN, MPX_LOADSTORE(loadb2cn, EMPTY, const, DECL_2CN, 8, (p < q), GETOCTETD, MPW_BITS, (v < vl), PUTMPW_2CN, - { FLUSHW_2CN; }) + { FIXFINALW_2CN; }, { MPX_ZERO(v, vl); }) /*----- Logical shifting --------------------------------------------------*/ @@ -1376,29 +1381,34 @@ static int loadstore(dstr *v) static int twocl(dstr *v) { dstr d = DSTR_INIT; - mpw *m, *ml; - size_t sz; + mpw *m, *ml0, *ml1; + size_t sz0, sz1, szmax; int ok = 1; + int i; - sz = v[0].len; if (v[1].len > sz) sz = v[1].len; - dstr_ensure(&d, sz); + sz0 = MPW_RQ(v[0].len); sz1 = MPW_RQ(v[1].len); + dstr_ensure(&d, v[0].len > v[1].len ? v[0].len : v[1].len); - sz = MPW_RQ(sz); - m = xmalloc(MPWS(sz)); - ml = m + sz; + szmax = sz0 > sz1 ? sz0 : sz1; + m = xmalloc(MPWS(szmax)); + ml0 = m + sz0; ml1 = m + sz1; - mpx_loadl(m, ml, v[0].buf, v[0].len); - mpx_storel2cn(m, ml, d.buf, v[1].len); - if (memcmp(d.buf, v[1].buf, v[1].len)) { - dumpbits("\n*** storel2cn failed", d.buf, v[1].len); - ok = 0; - } + for (i = 0; i < 2; i++) { + if (i) ml0 = ml1 = m + szmax; - mpx_loadl2cn(m, ml, v[1].buf, v[1].len); - mpx_storel(m, ml, d.buf, v[0].len); - if (memcmp(d.buf, v[0].buf, v[0].len)) { - dumpbits("\n*** loadl2cn failed", d.buf, v[0].len); - ok = 0; + mpx_loadl(m, ml0, v[0].buf, v[0].len); + mpx_storel2cn(m, ml0, d.buf, v[1].len); + if (memcmp(d.buf, v[1].buf, v[1].len)) { + dumpbits("\n*** storel2cn failed", d.buf, v[1].len); + ok = 0; + } + + mpx_loadl2cn(m, ml1, v[1].buf, v[1].len); + mpx_storel(m, ml1, d.buf, v[0].len); + if (memcmp(d.buf, v[0].buf, v[0].len)) { + dumpbits("\n*** loadl2cn failed", d.buf, v[0].len); + ok = 0; + } } if (!ok) { @@ -1415,29 +1425,34 @@ static int twocl(dstr *v) static int twocb(dstr *v) { dstr d = DSTR_INIT; - mpw *m, *ml; - size_t sz; + mpw *m, *ml0, *ml1; + size_t sz0, sz1, szmax; int ok = 1; + int i; - sz = v[0].len; if (v[1].len > sz) sz = v[1].len; - dstr_ensure(&d, sz); + sz0 = MPW_RQ(v[0].len); sz1 = MPW_RQ(v[1].len); + dstr_ensure(&d, v[0].len > v[1].len ? v[0].len : v[1].len); - sz = MPW_RQ(sz); - m = xmalloc(MPWS(sz)); - ml = m + sz; + szmax = sz0 > sz1 ? sz0 : sz1; + m = xmalloc(MPWS(szmax)); + ml0 = m + sz0; ml1 = m + sz1; - mpx_loadb(m, ml, v[0].buf, v[0].len); - mpx_storeb2cn(m, ml, d.buf, v[1].len); - if (memcmp(d.buf, v[1].buf, v[1].len)) { - dumpbits("\n*** storeb2cn failed", d.buf, v[1].len); - ok = 0; - } + for (i = 0; i < 2; i++) { + if (i) ml0 = ml1 = m + szmax; - mpx_loadb2cn(m, ml, v[1].buf, v[1].len); - mpx_storeb(m, ml, d.buf, v[0].len); - if (memcmp(d.buf, v[0].buf, v[0].len)) { - dumpbits("\n*** loadb2cn failed", d.buf, v[0].len); - ok = 0; + mpx_loadb(m, ml0, v[0].buf, v[0].len); + mpx_storeb2cn(m, ml0, d.buf, v[1].len); + if (memcmp(d.buf, v[1].buf, v[1].len)) { + dumpbits("\n*** storeb2cn failed", d.buf, v[1].len); + ok = 0; + } + + mpx_loadb2cn(m, ml1, v[1].buf, v[1].len); + mpx_storeb(m, ml1, d.buf, v[0].len); + if (memcmp(d.buf, v[0].buf, v[0].len)) { + dumpbits("\n*** loadb2cn failed", d.buf, v[0].len); + ok = 0; + } } if (!ok) { diff --git a/math/t/mpx b/math/t/mpx index bf104e91..f5caed27 100644 --- a/math/t/mpx +++ b/math/t/mpx @@ -23,8 +23,25 @@ load-store { 2cb { "" ""; 00 00; + 0000 00; + 000000 00; + 00000000 00; + 0000000000 00; + 00 0000; + 00 000000; + 00 00000000; + 00 0000000000; 000000 00000000000000000000; - 01 ff; + 0001 ff; + 000001 ff; + 00000001 ff; + 0000000001 ff; + 01 ffffff; + 01 ffffffff; + 01 ffffffffff; + 01 ffff; + 00007f01 80ff; + 40 ffffffffffffffffffffffc0; 0123456789abcdef fedcba9876543211; 0123456789abcdef fffffffedcba9876543211; 0100000000 ffffff00000000; @@ -35,8 +52,25 @@ load-store { 2cl { "" ""; 00 00; + 0000 00; + 000000 00; + 00000000 00; + 0000000000 00; + 00 0000; + 00 000000; + 00 00000000; + 00 0000000000; 000000 00000000000000000000; + 0100 ff; + 010000 ff; + 01000000 ff; + 0100000000 ff; + 01 ffffff; + 01 ffffffff; + 01 ffffffffff; 01 ff; + 017f0000 ff80; + 40 c0ffffffffffffffffffffff; efcdab8967452301 1132547698badcfe; efcdab8967452301 1132547698badcfeffffffff; 0000000001 00000000ffffffff; -- 2.11.0