This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

BCD [was Re: Algol front end]


Yes, Realia COBOL was great.  I used it for midly large file processing
(the full payroll for a 120.000 inhabitants city) and was amazed at the
speed of its filesystem and especially of its numerics.  Much faster than
a Bull (then honeywell) DPS/4.

Anyway here is some code that I dug out...

---

/* packed decimal 8-digit add */

#define ONES4 (UINT_MAX / 15)       /* 0x11111111 */
#define EIGHTS4 (ONES4 * 8)         /* 0x88888888 */
#define SIXES4  (ONES4 * 6)         /* 0x66666666 */


/* carry_out:c = a + b + carry_in */
add_ssaaaa (carry_out, c, 0, a, 0, b + carry_in);

b3 =    c & EIGHTS4;
carry = (a | b) & ~c & EIGHTS4;  /* carry generated (overflow in bit 3) */
gen   = ((c & SIXES4) * 7) & b3; /* out of range generated (101? or 110?) */
prop  = ((c & ONES4)  * 8) & b3; /* carry propagated (1001) */

do
  {
    old = carry;
    carry |= gen;
    gen = prop & (carry << 4);  /* propagate carry... */
  }
while (carry != old);

/* carry_out:c = c + carry_out:carry */
add_ssaaaa (carry_out, c, carry_out, carry, 0, c);


---


/* ASCII 4-digit add */

#define ONES8      (UINT_MAX / CHAR_MAX) /* 0x01010101 */
#define EIGHTS8    (ONES8 * 8)           /* 0x08080808 */
#define SIXES8     (ONES8 * 6)           /* 0x06060606 */
#define SIXTEENS8  (ONES8 * 16)          /* 0x10101010 */
#define ASC_ZEROS8 (ONES8 * '0')         /* 0x30303030 */

c = a + b;

carry = (c & SIXTEENS8) >> 1;
b3    = c & EIGHTS8;
carry = (a | b) & ~c & EIGHTS4;  /* carry generated (overflow in bit 3) */
gen   = ((c & SIXES8) * 7) & b3; /* out of range generated (101? or 110?) */
prop  = ((c & ONES8)  * 8) & b3; /* carry propagated (1001) */

do
  {
    old = carry;
    carry |= gen;
    gen = prop & (carry << 8);  /* propagate carry... */
  }
while (carry != old);

carry = (carry >> 3) * 246 - ASC_ZEROS8;

/* carry_out:c = c + carry_out:carry */
add_ssaaaa (carry_out, c, 0, carry, 0, c);


---

The only thing I don't like is the carry-propagation loop.  Robert, do you
think it is avoidable (yes, it is unrollable)???

When writing this kind of code for a COBOL system, treelang could be
useful.  You could write all the required inlines as C code, convert them
to treelang, and then load them at run-time so that they are automatically
inlined.  Maybe the treelang could also be automatically generated by a
Perl script.

For sorting/merging code, GNU sort has all the required functionalities
and more.  If days were 48h I would surely love working on the COBOL/GCC
runtime; maybe even 30h would suffice. :-)

Paolo


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]