VOGONS

Common searches


First post, by guest

User metadata

These bug(s) are exceptionally tragic - the Borland compilers all used the NPX's BCD operations for number formatting in the runtime libraries and depend heavily on it working. Any app that used the RTL's sprintf() for example, to form display text for score outputs or any screen data will be completely hosed.

Of course, correct BCD operations *DEPEND* on the 80 bit temp real format float format being implemented correctly ;-> If temp reals are busted, so is BCD, and so are 64 bit long integers (which are just the mantissa part of an 80 bit temp real)

Three tests here:

BCD.COM - fails 146 out of 146 variations
BCD2.EXE - fails 376 out of 376 variations
BCD3.EXE - fails 1074 out of 1074 variations

------ BCDUTIL.H (used by BCD2.C and BCD3.C --------

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <process.h>

typedef unsigned char UCHAR;
typedef unsigned char BCD[10];

BCD Result; /* Result from FBSTP */
BCD TestNum; /* Source to do FBLD from */
BCD Result2; /* What we expected */

unsigned FailFlag = 0; /* counts test failures */
unsigned VarCount = 0; /* counts test variations */

/*---------------------------------------------------------------------
Display a BCD number
---------------------------------------------------------------------*/
char prbuf[30];
int digit = 0;
int bufpos = 0;

void PrintBCDnum(BCD *BCDnum)
{
int i;

prbuf[0] = ((*BCDnum)[9] & 0x80) ? '-' : '+';

digit = 1;
bufpos = 1;
for (i=8; i>=0; i--)
{
unsigned char cL,cH;

cL = cH = (*BCDnum);
cL &= 0x0F;
cH &= 0xF0;
cH = cH >> 4;
cL = '0'+cL;
cH = '0'+cH;

prbuf[bufpos++] = cH;
if ((digit % 3) == 0)
{
prbuf[bufpos++] = ',';
}
digit++;

prbuf[bufpos++] = cL;
if ((digit % 3) == 0)
{
if (digit != 18)
prbuf[bufpos++] = ',';
}
digit++;
}
prbuf[bufpos++] = 0;
printf(prbuf);
}

/*---------------------------------------------------------------------
Construct a BCD number in a variable
---------------------------------------------------------------------*/
void MakeBCD(BCD* var, char *n)
{
int i;
UCHAR sign = 0x00;
char *s;

/* Determine sign. Default is + */

if (*n == '+')
{
sign = 0x00;
n++;
}
if (*n == '-')
{
sign = 0x80;
n++;
}
(*var)[9] = sign;


/* Remember where the first digit started */

s = n;

/* Scan till NULL, then back up 1 character */

while (*n)
n++;
n--;

/* Default target to zeros */

for (i=0; i<9; i++)
(*var) = 0x00;

/* Walk backward filling in results, stop when we pass 's' */

i = 0;
while (s <= n)
{
UCHAR u,l;

u=0;
l = (*n-- - '0');
if (s <= n)
u = (*n-- - '0');
(*var)[i++] = ((u << 4) | l);
}
}

/*---------------------------------------------------------------------
Move one BCD number to another
---------------------------------------------------------------------*/
void CopyBCD(BCD *source, BCD *target)
{
int i;

for (i=0; i<10; i++)
(*target) = (*source);
}

/*---------------------------------------------------------------------
Compare two BCD numbers
---------------------------------------------------------------------*/
void CompBCD(BCD *n1, BCD *n2)
{
int i;

for (i=0; i<10; i++)
if ( (*n1) != (*n2) )
{
printf(" <---- FAIL!");
FailFlag++;
return;
}
}

void summary(void)
{
/*---------------------------------------------------------------------
End of test summary results
---------------------------------------------------------------------*/
printf("\n-------- Test results summary --------\n\n");
printf("\tTotal Variations = %u\n", VarCount);
printf("\tPASSED Variations = %u\n", (VarCount - FailFlag));
printf("\tFAILED Variations = %u\n", FailFlag);

printf(FailFlag ?
"\n\tThis test FAILED :-(\n" :
"\n\tThis test PASSES :-)\n");

exit (FailFlag? -1 : 0);
}

--------- BCD2.C ----------------------------

#pragma inline
/*---------------------------------------------------------------------
Test for correct FBLD/FBSTP operation
-----------------------------------------------------------------------
Compile me with TC 2.0 or BC 3.1 using the -f87 switch
---------------------------------------------------------------------*/
#include "bcdutil.h"

void _setenvp(void){}
void _setargv(void){}


/*---------------------------------------------------------------------
Display Load/Store results and check result
---------------------------------------------------------------------*/
void ShowNumbers(void)
{
printf("\tFBLD source = ");
PrintBCDnum(&TestNum);
printf("\n");

printf("\tFBSTP result = ");
PrintBCDnum(&Result);

CompBCD(&TestNum, &Result);
printf("\n\n");
}

/*---------------------------------------------------------------------
Do BCD Load/Store of TestNum to Result
---------------------------------------------------------------------*/
void DoTest(void)
{
VarCount++;
asm finit
asm fbld tbyte ptr TestNum
asm fbstp tbyte ptr Result
}

#define TESTIT {DoTest(); ShowNumbers();}
#define TEST_TITLE(text) printf("%s\n\n",text);
#define TESTNUM(v) MakeBCD(&TestNum,v)
#define TEST(orig) {TESTNUM(orig); TESTIT;}

/*---------------------------------------------------------------------
Start of test code
---------------------------------------------------------------------*/
void main(void)
{
TEST_TITLE("*** +/- 0 ***");

TEST("+0");
TEST("-0");

TEST_TITLE("*** Walking high significant digit to left (+) w/1 ***");

TEST("+000000000000000001");
TEST("+000000000000000010");
TEST("+000000000000000100");
TEST("+000000000000001000");
TEST("+000000000000010000");
TEST("+000000000000100000");
TEST("+000000000001000000");
TEST("+000000000010000000");
TEST("+000000000100000000");
TEST("+000000001000000000");
TEST("+000000010000000000");
TEST("+000000100000000000");
TEST("+000001000000000000");
TEST("+000010000000000000");
TEST("+000100000000000000");
TEST("+001000000000000000");
TEST("+010000000000000000");
TEST("+100000000000000000");

TEST_TITLE("*** Walking high significant digit to left (-) w/1 ***");

TEST("-000000000000000001");
TEST("-000000000000000010");
TEST("-000000000000000100");
TEST("-000000000000001000");
TEST("-000000000000010000");
TEST("-000000000000100000");
TEST("-000000000001000000");
TEST("-000000000010000000");
TEST("-000000000100000000");
TEST("-000000001000000000");
TEST("-000000010000000000");
TEST("-000000100000000000");
TEST("-000001000000000000");
TEST("-000010000000000000");
TEST("-000100000000000000");
TEST("-001000000000000000");
TEST("-010000000000000000");
TEST("-100000000000000000");

TEST_TITLE("*** Walking high significant digit to left (+) w/2 ***");

TEST("+000000000000000002");
TEST("+000000000000000020");
TEST("+000000000000000200");
TEST("+000000000000002000");
TEST("+000000000000020000");
TEST("+000000000000200000");
TEST("+000000000002000000");
TEST("+000000000020000000");
TEST("+000000000200000000");
TEST("+000000002000000000");
TEST("+000000020000000000");
TEST("+000000200000000000");
TEST("+000002000000000000");
TEST("+000020000000000000");
TEST("+000200000000000000");
TEST("+002000000000000000");
TEST("+020000000000000000");
TEST("+200000000000000000");

TEST_TITLE("*** Walking high significant digit to left (-) w/2 ***");

TEST("-000000000000000002");
TEST("-000000000000000020");
TEST("-000000000000000200");
TEST("-000000000000002000");
TEST("-000000000000020000");
TEST("-000000000000200000");
TEST("-000000000002000000");
TEST("-000000000020000000");
TEST("-000000000200000000");
TEST("-000000002000000000");
TEST("-000000020000000000");
TEST("-000000200000000000");
TEST("-000002000000000000");
TEST("-000020000000000000");
TEST("-000200000000000000");
TEST("-002000000000000000");
TEST("-020000000000000000");
TEST("-200000000000000000");

TEST_TITLE("*** Walking high significant digit to left (+) w/3 ***");

TEST("+000000000000000003");
TEST("+000000000000000030");
TEST("+000000000000000300");
TEST("+000000000000003000");
TEST("+000000000000030000");
TEST("+000000000000300000");
TEST("+000000000003000000");
TEST("+000000000030000000");
TEST("+000000000300000000");
TEST("+000000003000000000");
TEST("+000000030000000000");
TEST("+000000300000000000");
TEST("+000003000000000000");
TEST("+000030000000000000");
TEST("+000300000000000000");
TEST("+003000000000000000");
TEST("+030000000000000000");
TEST("+300000000000000000");

TEST_TITLE("*** Walking high significant digit to left (-) w/3 ***");

TEST("-000000000000000003");
TEST("-000000000000000030");
TEST("-000000000000000300");
TEST("-000000000000003000");
TEST("-000000000000030000");
TEST("-000000000000300000");
TEST("-000000000003000000");
TEST("-000000000030000000");
TEST("-000000000300000000");
TEST("-000000003000000000");
TEST("-000000030000000000");
TEST("-000000300000000000");
TEST("-000003000000000000");
TEST("-000030000000000000");
TEST("-000300000000000000");
TEST("-003000000000000000");
TEST("-030000000000000000");
TEST("-300000000000000000");

TEST_TITLE("*** Walking high significant digit to left (+) w/4 ***");

TEST("+000000000000000004");
TEST("+000000000000000040");
TEST("+000000000000000400");
TEST("+000000000000004000");
TEST("+000000000000040000");
TEST("+000000000000400000");
TEST("+000000000004000000");
TEST("+000000000040000000");
TEST("+000000000400000000");
TEST("+000000004000000000");
TEST("+000000040000000000");
TEST("+000000400000000000");
TEST("+000004000000000000");
TEST("+000040000000000000");
TEST("+000400000000000000");
TEST("+004000000000000000");
TEST("+040000000000000000");
TEST("+400000000000000000");

TEST_TITLE("*** Walking high significant digit to left (-) w/4 ***");

TEST("-000000000000000004");
TEST("-000000000000000040");
TEST("-000000000000000400");
TEST("-000000000000004000");
TEST("-000000000000040000");
TEST("-000000000000400000");
TEST("-000000000004000000");
TEST("-000000000040000000");
TEST("-000000000400000000");
TEST("-000000004000000000");
TEST("-000000040000000000");
TEST("-000000400000000000");
TEST("-000004000000000000");
TEST("-000040000000000000");
TEST("-000400000000000000");
TEST("-004000000000000000");
TEST("-040000000000000000");
TEST("-400000000000000000");

TEST_TITLE("*** Walking high significant digit to left (+) w/5 ***");

TEST("+000000000000000005");
TEST("+000000000000000050");
TEST("+000000000000000500");
TEST("+000000000000005000");
TEST("+000000000000050000");
TEST("+000000000000500000");
TEST("+000000000005000000");
TEST("+000000000050000000");
TEST("+000000000500000000");
TEST("+000000005000000000");
TEST("+000000050000000000");
TEST("+000000500000000000");
TEST("+000005000000000000");
TEST("+000050000000000000");
TEST("+000500000000000000");
TEST("+005000000000000000");
TEST("+050000000000000000");
TEST("+500000000000000000");

TEST_TITLE("*** Walking high significant digit to left (-) w/5 ***");

TEST("-000000000000000005");
TEST("-000000000000000050");
TEST("-000000000000000500");
TEST("-000000000000005000");
TEST("-000000000000050000");
TEST("-000000000000500000");
TEST("-000000000005000000");
TEST("-000000000050000000");
TEST("-000000000500000000");
TEST("-000000005000000000");
TEST("-000000050000000000");
TEST("-000000500000000000");
TEST("-000005000000000000");
TEST("-000050000000000000");
TEST("-000500000000000000");
TEST("-005000000000000000");
TEST("-050000000000000000");
TEST("-500000000000000000");

TEST_TITLE("*** Walking high significant digit to left (+) w/6 ***");

TEST("+000000000000000006");
TEST("+000000000000000060");
TEST("+000000000000000600");
TEST("+000000000000006000");
TEST("+000000000000060000");
TEST("+000000000000600000");
TEST("+000000000006000000");
TEST("+000000000060000000");
TEST("+000000000600000000");
TEST("+000000006000000000");
TEST("+000000060000000000");
TEST("+000000600000000000");
TEST("+000006000000000000");
TEST("+000060000000000000");
TEST("+000600000000000000");
TEST("+006000000000000000");
TEST("+060000000000000000");
TEST("+600000000000000000");

TEST_TITLE("*** Walking high significant digit to left (-) w/6 ***");

TEST("-000000000000000006");
TEST("-000000000000000060");
TEST("-000000000000000600");
TEST("-000000000000006000");
TEST("-000000000000060000");
TEST("-000000000000600000");
TEST("-000000000006000000");
TEST("-000000000060000000");
TEST("-000000000600000000");
TEST("-000000006000000000");
TEST("-000000060000000000");
TEST("-000000600000000000");
TEST("-000006000000000000");
TEST("-000060000000000000");
TEST("-000600000000000000");
TEST("-006000000000000000");
TEST("-060000000000000000");
TEST("-600000000000000000");

TEST_TITLE("*** Walking high significant digit to left (+) w/7 ***");

TEST("+000000000000000007");
TEST("+000000000000000070");
TEST("+000000000000000700");
TEST("+000000000000007000");
TEST("+000000000000070000");
TEST("+000000000000700000");
TEST("+000000000007000000");
TEST("+000000000070000000");
TEST("+000000000700000000");
TEST("+000000007000000000");
TEST("+000000070000000000");
TEST("+000000700000000000");
TEST("+000007000000000000");
TEST("+000070000000000000");
TEST("+000700000000000000");
TEST("+007000000000000000");
TEST("+070000000000000000");
TEST("+700000000000000000");

TEST_TITLE("*** Walking high significant digit to left (-) w/7 ***");

#if 1
/* Hit compiler limits here!!! on 3.1 compiler*/
TEST("-000000000000000007");
TEST("-000000000000000070");
TEST("-000000000000000700");
TEST("-000000000000007000");
TEST("-000000000000070000");
TEST("-000000000000700000");
TEST("-000000000007000000");
TEST("-000000000070000000");
TEST("-000000000700000000");
TEST("-000000007000000000");
TEST("-000000070000000000");
TEST("-000000700000000000");
#endif
TEST("-000007000000000000");
TEST("-000070000000000000");
TEST("-000700000000000000");
TEST("-007000000000000000");
TEST("-070000000000000000");
TEST("-700000000000000000");

TEST_TITLE("*** Walking high significant digit to left (+) w/8 ***");

TEST("+000000000000000008");
TEST("+000000000000000080");
TEST("+000000000000000800");
TEST("+000000000000008000");
TEST("+000000000000080000");
TEST("+000000000000800000");
TEST("+000000000008000000");
TEST("+000000000080000000");
TEST("+000000000800000000");
TEST("+000000008000000000");
TEST("+000000080000000000");
TEST("+000000800000000000");
TEST("+000008000000000000");
TEST("+000080000000000000");
TEST("+000800000000000000");
TEST("+008000000000000000");
TEST("+080000000000000000");
TEST("+800000000000000000");

TEST_TITLE("*** Walking high significant digit to left (-) w/8 ***");

TEST("-000000000000000008");
TEST("-000000000000000080");
TEST("-000000000000000800");
TEST("-000000000000008000");
TEST("-000000000000080000");
TEST("-000000000000800000");
TEST("-000000000008000000");
TEST("-000000000080000000");
TEST("-000000000800000000");
TEST("-000000008000000000");
TEST("-000000080000000000");
TEST("-000000800000000000");
TEST("-000008000000000000");
TEST("-000080000000000000");
TEST("-000800000000000000");
TEST("-008000000000000000");
TEST("-080000000000000000");
TEST("-800000000000000000");

TEST_TITLE("*** Walking high significant digit to left (+) w/9 ***");

TEST("+000000000000000009");
TEST("+000000000000000090");
TEST("+000000000000000900");
TEST("+000000000000009000");
TEST("+000000000000090000");
TEST("+000000000000900000");
TEST("+000000000009000000");
TEST("+000000000090000000");
TEST("+000000000900000000");
TEST("+000000009000000000");
TEST("+000000090000000000");
TEST("+000000900000000000");
TEST("+000009000000000000");
TEST("+000090000000000000");
TEST("+000900000000000000");
TEST("+009000000000000000");
TEST("+090000000000000000");
TEST("+900000000000000000");

TEST_TITLE("*** Walking high significant digit to left (-) w/9 ***");

TEST("-000000000000000009");
TEST("-000000000000000090");
TEST("-000000000000000900");
TEST("-000000000000009000");
TEST("-000000000000090000");
TEST("-000000000000900000");
TEST("-000000000009000000");
TEST("-000000000090000000");
TEST("-000000000900000000");
TEST("-000000009000000000");
TEST("-000000090000000000");
TEST("-000000900000000000");
TEST("-000009000000000000");
TEST("-000090000000000000");
TEST("-000900000000000000");
TEST("-009000000000000000");
TEST("-090000000000000000");
TEST("-900000000000000000");

#if 1
/* Hit compiler limits here!!! on 3.1 compiler */

TEST_TITLE("*** all 1's through all 9's (+/-) ***");

TEST("+111111111111111111");
TEST("+222222222222222222");
TEST("+333333333333333333");
TEST("+444444444444444444");
TEST("+555555555555555555");
TEST("+666666666666666666");
TEST("+777777777777777777");
TEST("+888888888888888888");
TEST("+999999999999999999");

TEST("-111111111111111111");
TEST("-222222222222222222");
TEST("-333333333333333333");
TEST("-444444444444444444");
TEST("-555555555555555555");
TEST("-666666666666666666");
TEST("-777777777777777777");
TEST("-888888888888888888");
TEST("-999999999999999999");

TEST_TITLE("*** Misc numbers ***");

TEST("+443322110987654321");
TEST("-443322110987654321");

TEST("+003302010907050301");
TEST("-003302010907050301");

TEST("+003020100980604020");
TEST("-003020100980604020");

TEST("+000999000999900000");
TEST("-000999000999900000");

TEST("+000099900099990000");
TEST("-000099900099990000");

TEST("+000009909099990000");
TEST("-000009909099990000");

TEST("+000000909099990000");
TEST("-000000909099990000");

TEST("+000000009099990000");
TEST("-000000009099990000");

TEST("+000000000999900000");
TEST("-000000000999900000");

TEST_TITLE("*** 2 through 8 (+/-) ***");

TEST("+2");
TEST("+3");
TEST("+4");
TEST("+5");
TEST("+6");
TEST("+7");
TEST("+8");

TEST("-2");
TEST("-3");
TEST("-4");
TEST("-5");
TEST("-6");
TEST("-7");
TEST("-8");
#endif

summary();
}

----------- BCD3.C ---------------

#pragma inline
/*---------------------------------------------------------------------
Test for correct FBLD/FBSTP/FADD operation
-----------------------------------------------------------------------
Compile me with Borland C++ 3.1 using the -f87 switch
---------------------------------------------------------------------*/
#include "bcdutil.h"

void _setenvp(void){}
void _setargv(void){}


/*---------------------------------------------------------------------
Display Load/Store results and check result
---------------------------------------------------------------------*/
void ShowNumbers(void)
{
printf("\tOriginal Number = ");
PrintBCDnum(&TestNum);
printf("\n");

printf("\tResult Number = ");
PrintBCDnum(&Result);
printf("\n");

printf("\tExpected result = ");
PrintBCDnum(&Result2);

CompBCD(&Result, &Result2);
printf("\n\n");
}

/*---------------------------------------------------------------------
Do BCD Load/Add/Store of TestNum to Result
---------------------------------------------------------------------*/
void DoTest(void)
{
VarCount++;
asm finit
asm fbld tbyte ptr TestNum
asm fld1
asm fadd
asm fbstp tbyte ptr Result
}

#define TESTIT {DoTest(); ShowNumbers();}
#define TEST_TITLE(text) printf("%s\n\n",text);
#define TESTNUM(v) MakeBCD(&TestNum,v)
#define EXPECT(v) MakeBCD(&Result2,v)
#define TEST(orig,expect) {TESTNUM(orig); EXPECT(expect); TESTIT;}

/*---------------------------------------------------------------------
Start of test code
---------------------------------------------------------------------*/
void main(void)
{
TEST_TITLE("*** ADD 1 to +/- 0 ***");

TEST("+0","+1");
TEST("-0","+1");

TEST_TITLE("*** ADD 1 to misc numbers ***");

TEST("+443322110987654321","+443322110987654322");
TEST("-443322110987654321","-443322110987654320");

TEST_TITLE("*** ADD 1 to sliding 1 (+) ***");

TEST("+1","+2");
TEST("+10","+11");
TEST("+100","+101");
TEST("+1000","+1001");
TEST("+10000","+10001");
TEST("+100000","+100001");
TEST("+1000000","+1000001");
TEST("+10000000","+10000001");
TEST("+100000000","+100000001");
TEST("+1000000000","+1000000001");
TEST("+10000000000","+10000000001");
TEST("+100000000000","+100000000001");
TEST("+1000000000000","+1000000000001");
TEST("+10000000000000","+10000000000001");
TEST("+100000000000000","+100000000000001");
TEST("+1000000000000000","+1000000000000001");
TEST("+10000000000000000","+10000000000000001");
TEST("+100000000000000000","+100000000000000001");

TEST_TITLE("*** ADD 1 to sliding 9 (+) ***");

TEST("+9","+10");
TEST("+90","+91");
TEST("+900","+901");
TEST("+9000","+9001");
TEST("+90000","+90001");
TEST("+900000","+900001");
TEST("+9000000","+9000001");
TEST("+90000000","+90000001");
TEST("+900000000","+900000001");
TEST("+9000000000","+9000000001");
TEST("+90000000000","+90000000001");
TEST("+900000000000","+900000000001");
TEST("+9000000000000","+9000000000001");
TEST("+90000000000000","+90000000000001");
TEST("+900000000000000","+900000000000001");
TEST("+9000000000000000","+9000000000000001");
TEST("+90000000000000000","+90000000000000001");
TEST("+900000000000000000","+900000000000000001");

TEST_TITLE("*** Moving high significant digit to left (-) w/1 ***");

TEST("-10","-9");
TEST("-100","-99");
TEST("-1000","-999");
TEST("-10000","-9999");
TEST("-100000","-99999");
TEST("-1000000","-999999");
TEST("-10000000","-9999999");
TEST("-100000000","-99999999");
TEST("-1000000000","-999999999");
TEST("-10000000000","-9999999999");
TEST("-100000000000","-99999999999");
TEST("-1000000000000","-999999999999");
TEST("-10000000000000","-9999999999999");
TEST("-100000000000000","-99999999999999");
TEST("-1000000000000000","-999999999999999");
TEST("-10000000000000000","-9999999999999999");
TEST("-100000000000000000","-99999999999999999");

TEST_TITLE("*** all 1's through all 8's (+/-) ***");

TEST("+111111111111111111","+111111111111111112");
TEST("+222222222222222222","+222222222222222223");
TEST("+333333333333333333","+333333333333333334");
TEST("+444444444444444444","+444444444444444445");
TEST("+555555555555555555","+555555555555555556");
TEST("+666666666666666666","+666666666666666667");
TEST("+777777777777777777","+777777777777777778");
TEST("+888888888888888888","+888888888888888889");

TEST("-111111111111111111","-111111111111111110");
TEST("-222222222222222222","-222222222222222221");
TEST("-333333333333333333","-333333333333333332");
TEST("-444444444444444444","-444444444444444443");
TEST("-555555555555555555","-555555555555555554");
TEST("-666666666666666666","-666666666666666665");
TEST("-777777777777777777","-777777777777777776");
TEST("-888888888888888888","-888888888888888887");
TEST("-999999999999999999","-999999999999999998");

TEST_TITLE("*** 500 random numbers (fairly small) ***");

{
int i, rnum;
long lrnum;
char buf1[20], buf2[20];

randomize();
for (i=0; i<500; i++)
{
rnum = random(32766);
lrnum = rnum * 20082112L;
sprintf(buf1, "%ld", lrnum);
sprintf(buf2, "%ld", lrnum+1L);
TEST(buf1, buf2);
}
}

TEST_TITLE("*** 500 mostly random numbers (generally big) ***");

{
int i,j;
char buf1[20], buf2[20];

randomize();
for (i=0; i<500; i++)
{
for (j=0; j<18; j++)
{
buf1[j+1] = buf2[j+1] = (random(10) + '0');
}

if (i & 1)
{
buf1[0] = '-';
buf2[0] = '-';
if (buf1[18] == '0')
{
buf1[18] = '1';
buf2[18] = '0';
}
else
buf2[18] = (buf1[18] - 1);
}
else
{
buf1[0] = '+';
buf2[0] = '+';
if (buf1[18] == '9')
{
buf1[18] = '8';
buf2[18] = '9';
}
else
buf2[18] = (buf1[18] + 1);
}
buf1[19] = buf2[19] = 0;

TEST(buf1, buf2);
}
}
summary();
}

------ BCD.ASM --------

;---------------------------------------------------------------------------
; Test of BCD instructions -- WARNING! this test isn't exhaustive
;---------------------------------------------------------------------------
; Tony Ingenoso, 8/22/1995
;---------------------------------------------------------------------------
GENERATE_TEST_SKELETON = 1

SILENT_PASS = 0
include ..\TESTMACS.INC
FOR8086 ;; To work on any CPU type
jmp near ptr xtestcode

irpc n,0123456789
.RADIX 16
Big&n&n label tbyte
db 9 dup (&n&n),0
.RADIX 10
endm

irpc n,0123456789
.RADIX 16
MinusBig&n&n label tbyte
db 9 dup (&n&n),80
.RADIX 10
endm

irpc n,0123456789
.RADIX 16
pD17_&n&n label tbyte
db 8 dup (&n&n),0&n,0
.RADIX 10
endm

irpc n,0123456789
.RADIX 16
mD17_&n&n label tbyte
db 8 dup (&n&n),0&n,80
.RADIX 10
endm

irpc n,0123456789
.RADIX 16
pD16_&n&n label tbyte
db 8 dup (&n&n),0,0
.RADIX 10
endm

irpc n,0123456789
.RADIX 16
mD16_&n&n label tbyte
db 8 dup (&n&n),0,80
.RADIX 10
endm

irpc n,0123456789
.RADIX 16
pD15_&n&n label tbyte
db 7 dup (&n&n),0&n,0,0
.RADIX 10
endm

irpc n,0123456789
.RADIX 16
mD15_&n&n label tbyte
db 7 dup (&n&n),0&n,0,80
.RADIX 10
endm

irpc n,0123456789
.RADIX 16
pD14_&n&n label tbyte
db 7 dup (&n&n),0,0,0
.RADIX 10
endm

irpc n,0123456789
.RADIX 16
mD14_&n&n label tbyte
db 7 dup (&n&n),0,0,80
.RADIX 10
endm

irpc n,0123456789
.RADIX 16
pD13_&n&n label tbyte
db 6 dup (&n&n),0&n,0,0,0
.RADIX 10
endm

irpc n,0123456789
.RADIX 16
mD13_&n&n label tbyte
db 6 dup (&n&n),0&n,0,0,80
.RADIX 10
endm

irpc n,0123456789
.RADIX 16
pD8_&n&n label tbyte
db 4 dup (&n&n),0,0,0,0,0,0
.RADIX 10
endm

irpc n,0123456789
.RADIX 16
mD8_&n&n label tbyte
db 4 dup (&n&n),0,0,0,0,0,80
.RADIX 10
endm

irpc n,0123456789
.RADIX 16
pD4_&n&n label tbyte
db 2 dup (&n&n),0,0,0,0,0,0,0,0
.RADIX 10
endm

irpc n,0123456789
.RADIX 16
mD4_&n&n label tbyte
db 2 dup (&n&n),0,0,0,0,0,0,0,80
.RADIX 10
endm


ResultBuf label tbyte
db 10 dup (0)

;------------------------------------------------
; Put some wierd stuff into ResultBuf
;------------------------------------------------
WhackResult proc near
mov byte ptr ResultBuf+0, 5Ah
mov byte ptr ResultBuf+1, 0A5h
mov byte ptr ResultBuf+2, 0
mov byte ptr ResultBuf+3, -1
mov byte ptr ResultBuf+4, 12h
mov byte ptr ResultBuf+5, 34h
mov byte ptr ResultBuf+6, 92h
mov byte ptr ResultBuf+7, 26h
mov byte ptr ResultBuf+8, 54h
mov byte ptr ResultBuf+9, 07h
ret
WhackResult endp


;-----------------------------------------------------------
; Compares two 10 byte things and returns with ZF set/clear
;-----------------------------------------------------------
COMPARE10 macro Val1,Val2
local EndComp
if (CPU386)
push eax
mov eax, dword ptr Val1
cmp eax, dword ptr Val2
jne EndComp
mov eax, dword ptr Val1+4
cmp eax, dword ptr Val2+4
jne EndComp
mov ax, word ptr Val1+8
cmp ax, word ptr Val2+8
EndComp:
pop eax
else
push ax
mov ax, word ptr Val1+0
cmp ax, word ptr Val2+0
jne EndComp
mov ax, word ptr Val1+2
cmp ax, word ptr Val2+2
jne EndComp
mov ax, word ptr Val1+4
cmp ax, word ptr Val2+4
jne EndComp
mov ax, word ptr Val1+6
cmp ax, word ptr Val2+6
jne EndComp
mov ax, word ptr Val1+8
cmp ax, word ptr Val2+8
EndComp:
pop ax
endif
endm

;----------------------------------------------------
; Test basic BCD load/store functionality
;----------------------------------------------------
FBLDTEST macro TestNum,TestDescription
local done,tpass,tfail
INCVARCOUNT
call WhackResult
finit
fbld tbyte ptr TestNum
nop
fbstp tbyte ptr ResultBuf
if (CPU8086)
fwait
endif
COMPARE10 TestNum,ResultBuf
jne tfail
PASS TestDescription
jmp done
tfail:
FAIL TestDescription
done:
endm


;///////////////////////////////////////////////////////////////////////////
;/// Start of test code ///
;///////////////////////////////////////////////////////////////////////////

xtestcode label near
;
; ------------------- Positive numbers ----------------------
;
FBLDTEST Big00,"FBLD/FBSTP +000000000000000000d BCD number"
FBLDTEST Big11,"FBLD/FBSTP +111111111111111111d BCD number"
FBLDTEST Big22,"FBLD/FBSTP +222222222222222222d BCD number"
FBLDTEST Big33,"FBLD/FBSTP +333333333333333333d BCD number"
FBLDTEST Big44,"FBLD/FBSTP +444444444444444444d BCD number"
FBLDTEST Big55,"FBLD/FBSTP +555555555555555555d BCD number"
FBLDTEST Big66,"FBLD/FBSTP +666666666666666666d BCD number"
FBLDTEST Big77,"FBLD/FBSTP +777777777777777777d BCD number"
FBLDTEST Big88,"FBLD/FBSTP +888888888888888888d BCD number"
FBLDTEST Big99,"FBLD/FBSTP +999999999999999999d BCD number"

FBLDTEST pD17_99,"FBLD/FBSTP +099999999999999999d BCD number"
FBLDTEST pD16_99,"FBLD/FBSTP +009999999999999999d BCD number"
FBLDTEST pD15_99,"FBLD/FBSTP +000999999999999999d BCD number"
FBLDTEST pD14_99,"FBLD/FBSTP +000099999999999999d BCD number"
FBLDTEST pD13_99,"FBLD/FBSTP +000009999999999999d BCD number"
FBLDTEST pD8_99, "FBLD/FBSTP +000000000099999999d BCD number"
FBLDTEST pD4_99, "FBLD/FBSTP +000000000000009999d BCD number"

FBLDTEST pD17_88,"FBLD/FBSTP +088888888888888888d BCD number"
FBLDTEST pD16_88,"FBLD/FBSTP +008888888888888888d BCD number"
FBLDTEST pD15_88,"FBLD/FBSTP +000888888888888888d BCD number"
FBLDTEST pD14_88,"FBLD/FBSTP +000088888888888888d BCD number"
FBLDTEST pD13_88,"FBLD/FBSTP +000008888888888888d BCD number"
FBLDTEST pD8_88, "FBLD/FBSTP +000000000088888888d BCD number"
FBLDTEST pD4_88, "FBLD/FBSTP +000000000000008888d BCD number"

FBLDTEST pD17_77,"FBLD/FBSTP +077777777777777777d BCD number"
FBLDTEST pD16_77,"FBLD/FBSTP +007777777777777777d BCD number"
FBLDTEST pD15_77,"FBLD/FBSTP +000777777777777777d BCD number"
FBLDTEST pD14_77,"FBLD/FBSTP +000077777777777777d BCD number"
FBLDTEST pD13_77,"FBLD/FBSTP +000007777777777777d BCD number"
FBLDTEST pD8_77, "FBLD/FBSTP +000000000077777777d BCD number"
FBLDTEST pD4_77, "FBLD/FBSTP +000000000000007777d BCD number"

FBLDTEST pD17_66,"FBLD/FBSTP +066666666666666666d BCD number"
FBLDTEST pD16_66,"FBLD/FBSTP +006666666666666666d BCD number"
FBLDTEST pD15_66,"FBLD/FBSTP +000666666666666666d BCD number"
FBLDTEST pD14_66,"FBLD/FBSTP +000066666666666666d BCD number"
FBLDTEST pD13_66,"FBLD/FBSTP +000006666666666666d BCD number"
FBLDTEST pD8_66, "FBLD/FBSTP +000000000066666666d BCD number"
FBLDTEST pD4_66, "FBLD/FBSTP +000000000000006666d BCD number"

FBLDTEST pD17_55,"FBLD/FBSTP +055555555555555555d BCD number"
FBLDTEST pD16_55,"FBLD/FBSTP +005555555555555555d BCD number"
FBLDTEST pD15_55,"FBLD/FBSTP +000555555555555555d BCD number"
FBLDTEST pD14_55,"FBLD/FBSTP +000055555555555555d BCD number"
FBLDTEST pD13_55,"FBLD/FBSTP +000005555555555555d BCD number"
FBLDTEST pD8_55, "FBLD/FBSTP +000000000055555555d BCD number"
FBLDTEST pD4_55, "FBLD/FBSTP +000000000000005555d BCD number"

FBLDTEST pD17_44,"FBLD/FBSTP +044444444444444444d BCD number"
FBLDTEST pD16_44,"FBLD/FBSTP +004444444444444444d BCD number"
FBLDTEST pD15_44,"FBLD/FBSTP +000444444444444444d BCD number"
FBLDTEST pD14_44,"FBLD/FBSTP +000044444444444444d BCD number"
FBLDTEST pD13_44,"FBLD/FBSTP +000004444444444444d BCD number"
FBLDTEST pD8_44, "FBLD/FBSTP +000000000044444444d BCD number"
FBLDTEST pD4_44, "FBLD/FBSTP +000000000000004444d BCD number"

FBLDTEST pD17_33,"FBLD/FBSTP +033333333333333333d BCD number"
FBLDTEST pD16_33,"FBLD/FBSTP +003333333333333333d BCD number"
FBLDTEST pD15_33,"FBLD/FBSTP +000333333333333333d BCD number"
FBLDTEST pD14_33,"FBLD/FBSTP +000033333333333333d BCD number"
FBLDTEST pD13_33,"FBLD/FBSTP +000003333333333333d BCD number"
FBLDTEST pD8_33, "FBLD/FBSTP +000000000033333333d BCD number"
FBLDTEST pD4_33, "FBLD/FBSTP +000000000000003333d BCD number"

FBLDTEST pD17_22,"FBLD/FBSTP +022222222222222222d BCD number"
FBLDTEST pD16_22,"FBLD/FBSTP +002222222222222222d BCD number"
FBLDTEST pD15_22,"FBLD/FBSTP +000222222222222222d BCD number"
FBLDTEST pD14_22,"FBLD/FBSTP +000022222222222222d BCD number"
FBLDTEST pD13_22,"FBLD/FBSTP +000002222222222222d BCD number"
FBLDTEST pD8_22, "FBLD/FBSTP +000000000022222222d BCD number"
FBLDTEST pD4_22, "FBLD/FBSTP +000000000000002222d BCD number"

FBLDTEST pD17_11,"FBLD/FBSTP +011111111111111111d BCD number"
FBLDTEST pD16_11,"FBLD/FBSTP +001111111111111111d BCD number"
FBLDTEST pD15_11,"FBLD/FBSTP +000111111111111111d BCD number"
FBLDTEST pD14_11,"FBLD/FBSTP +000011111111111111d BCD number"
FBLDTEST pD13_11,"FBLD/FBSTP +000001111111111111d BCD number"
FBLDTEST pD8_11, "FBLD/FBSTP +000000000011111111d BCD number"
FBLDTEST pD4_11, "FBLD/FBSTP +000000000000001111d BCD number"
;
; ------------------- Negative numbers ----------------------
;
FBLDTEST MinusBig00,"FBLD/FBSTP -000000000000000000d BCD number"
FBLDTEST MinusBig11,"FBLD/FBSTP -111111111111111111d BCD number"
FBLDTEST MinusBig22,"FBLD/FBSTP -222222222222222222d BCD number"
FBLDTEST MinusBig33,"FBLD/FBSTP -333333333333333333d BCD number"
FBLDTEST MinusBig44,"FBLD/FBSTP -444444444444444444d BCD number"
FBLDTEST MinusBig55,"FBLD/FBSTP -555555555555555555d BCD number"
FBLDTEST MinusBig66,"FBLD/FBSTP -666666666666666666d BCD number"
FBLDTEST MinusBig77,"FBLD/FBSTP -777777777777777777d BCD number"
FBLDTEST MinusBig88,"FBLD/FBSTP -888888888888888888d BCD number"
FBLDTEST MinusBig99,"FBLD/FBSTP -999999999999999999d BCD number"

FBLDTEST mD17_99,"FBLD/FBSTP -099999999999999999d BCD number"
FBLDTEST mD16_99,"FBLD/FBSTP -009999999999999999d BCD number"
FBLDTEST mD15_99,"FBLD/FBSTP -000999999999999999d BCD number"
FBLDTEST mD14_99,"FBLD/FBSTP -000099999999999999d BCD number"
FBLDTEST mD13_99,"FBLD/FBSTP -000009999999999999d BCD number"
FBLDTEST mD8_99, "FBLD/FBSTP -000000000099999999d BCD number"
FBLDTEST mD4_99, "FBLD/FBSTP -000000000000009999d BCD number"

FBLDTEST mD17_88,"FBLD/FBSTP -088888888888888888d BCD number"
FBLDTEST mD16_88,"FBLD/FBSTP -008888888888888888d BCD number"
FBLDTEST mD15_88,"FBLD/FBSTP -000888888888888888d BCD number"
FBLDTEST mD14_88,"FBLD/FBSTP -000088888888888888d BCD number"
FBLDTEST mD13_88,"FBLD/FBSTP -000008888888888888d BCD number"
FBLDTEST mD8_88, "FBLD/FBSTP -000000000088888888d BCD number"
FBLDTEST mD4_88, "FBLD/FBSTP -000000000000008888d BCD number"

FBLDTEST mD17_77,"FBLD/FBSTP -077777777777777777d BCD number"
FBLDTEST mD16_77,"FBLD/FBSTP -007777777777777777d BCD number"
FBLDTEST mD15_77,"FBLD/FBSTP -000777777777777777d BCD number"
FBLDTEST mD14_77,"FBLD/FBSTP -000077777777777777d BCD number"
FBLDTEST mD13_77,"FBLD/FBSTP -000007777777777777d BCD number"
FBLDTEST mD8_77, "FBLD/FBSTP -000000000077777777d BCD number"
FBLDTEST mD4_77, "FBLD/FBSTP -000000000000007777d BCD number"

FBLDTEST mD17_66,"FBLD/FBSTP -066666666666666666d BCD number"
FBLDTEST mD16_66,"FBLD/FBSTP -006666666666666666d BCD number"
FBLDTEST mD15_66,"FBLD/FBSTP -000666666666666666d BCD number"
FBLDTEST mD14_66,"FBLD/FBSTP -000066666666666666d BCD number"
FBLDTEST mD13_66,"FBLD/FBSTP -000006666666666666d BCD number"
FBLDTEST mD8_66, "FBLD/FBSTP -000000000066666666d BCD number"
FBLDTEST mD4_66, "FBLD/FBSTP -000000000000006666d BCD number"

FBLDTEST mD17_55,"FBLD/FBSTP -055555555555555555d BCD number"
FBLDTEST mD16_55,"FBLD/FBSTP -005555555555555555d BCD number"
FBLDTEST mD15_55,"FBLD/FBSTP -000555555555555555d BCD number"
FBLDTEST mD14_55,"FBLD/FBSTP -000055555555555555d BCD number"
FBLDTEST mD13_55,"FBLD/FBSTP -000005555555555555d BCD number"
FBLDTEST mD8_55, "FBLD/FBSTP -000000000055555555d BCD number"
FBLDTEST mD4_55, "FBLD/FBSTP -000000000000005555d BCD number"

FBLDTEST mD17_44,"FBLD/FBSTP -044444444444444444d BCD number"
FBLDTEST mD16_44,"FBLD/FBSTP -004444444444444444d BCD number"
FBLDTEST mD15_44,"FBLD/FBSTP -000444444444444444d BCD number"
FBLDTEST mD14_44,"FBLD/FBSTP -000044444444444444d BCD number"
FBLDTEST mD13_44,"FBLD/FBSTP -000004444444444444d BCD number"
FBLDTEST mD8_44, "FBLD/FBSTP -000000000044444444d BCD number"
FBLDTEST mD4_44, "FBLD/FBSTP -000000000000004444d BCD number"

FBLDTEST mD17_33,"FBLD/FBSTP -033333333333333333d BCD number"
FBLDTEST mD16_33,"FBLD/FBSTP -003333333333333333d BCD number"
FBLDTEST mD15_33,"FBLD/FBSTP -000333333333333333d BCD number"
FBLDTEST mD14_33,"FBLD/FBSTP -000033333333333333d BCD number"
FBLDTEST mD13_33,"FBLD/FBSTP -000003333333333333d BCD number"
FBLDTEST mD8_33, "FBLD/FBSTP -000000000033333333d BCD number"
FBLDTEST mD4_33, "FBLD/FBSTP -000000000000003333d BCD number"

FBLDTEST mD17_22,"FBLD/FBSTP -022222222222222222d BCD number"
FBLDTEST mD16_22,"FBLD/FBSTP -002222222222222222d BCD number"
FBLDTEST mD15_22,"FBLD/FBSTP -000222222222222222d BCD number"
FBLDTEST mD14_22,"FBLD/FBSTP -000022222222222222d BCD number"
FBLDTEST mD13_22,"FBLD/FBSTP -000002222222222222d BCD number"
FBLDTEST mD8_22, "FBLD/FBSTP -000000000022222222d BCD number"
FBLDTEST mD4_22, "FBLD/FBSTP -000000000000002222d BCD number"

FBLDTEST mD17_11,"FBLD/FBSTP -011111111111111111d BCD number"
FBLDTEST mD16_11,"FBLD/FBSTP -001111111111111111d BCD number"
FBLDTEST mD15_11,"FBLD/FBSTP -000111111111111111d BCD number"
FBLDTEST mD14_11,"FBLD/FBSTP -000011111111111111d BCD number"
FBLDTEST mD13_11,"FBLD/FBSTP -000001111111111111d BCD number"
FBLDTEST mD8_11, "FBLD/FBSTP -000000000011111111d BCD number"
FBLDTEST mD4_11, "FBLD/FBSTP -000000000000001111d BCD number"

include ..\SUMMARY.INC

---------- SUMMARY.INC (used by BCD.ASM) ------

DISPLAY_SUMMARY label near
;------------------------------------------------------------
; Test exit and overall PASS/FAIL message display
;------------------------------------------------------------
jmp RealSummary

;---------------------------------------------------------
; Binary to ASCII decimal conversion and display
;---------------------------------------------------------

ASCbuf db 16 dup (0)

;---------------------------------------------------------
; Converts a signed integer to ASCII (31 bytes)
;
; In: ax = integer to convert
; ds:di = destination for NULL terminated string
; Side effects: ds:di points to 0 terminator byte after string
;---------------------------------------------------------
itoa proc near
mov bx,10 ;radix 10
if 0
sahf ;negative?
jns @@positive
neg ax ;switch to positive
mov byte ptr [di],'-' ;save minus sign
inc di
endif
@@positive:
xor dx,dx ;to handle -32768 correctly
div bx
push dx ;save digit
or ax,ax ;done?
jz @@save
call @@positive
@@save:
pop ax ;restore digit
or al,30h ;convert to ASCII
mov [di],ax ;also NULL terminates
inc di
ret
itoa endp

B2DC proc near
push cs
pop ds
push cs
pop es
cld
mov di,offset ASCbuf
push di
call itoa
if 0
inc di
mov ax,0a0dh ;cr, lf
stosw
endif
mov ax,9 * 256 + '$' ;ah = 9, al = '$'
stosb
pop dx
int 21h ;print string
ret
B2DC endp

AnyFailMsg db "***********************************************",13,10
db "* There were FAILURES during this test!!! *",13,10
db "***********************************************",13,10,'$'

NoFailMsg db "***********************************************",13,10
db "* This test passes with NO failures *",13,10
db "***********************************************",13,10,'$'

TotalMsgBig db "More than 65,535$"
TotalMsg db "Total variations: $"
FailsMsg db "Failed variations: $"

NumVars dw VARIATIONCOUNT

RealSummary label near
ShowMsg CRLF
ShowMsg TotalMsg
mov ax, NumVars
or ax, ax
jnz VarsOK
if (CPU386)
mov eax, dword ptr VarCount ; Take this number instead...
test eax, 0FFFF0000h
jz VarsOK
else
mov cx, word ptr VarCount+2
mov ax, word ptr VarCount
jcxz VarsOK
endif
ShowMsg TotalMsgBig
jmp VarsDispContinue
VarsOK:
call B2DC
VarsDispContinue:
ShowMsg CRLF

ShowMsg FailsMsg
mov ax, word ptr FailFlag
call B2DC
ShowMsg CRLF

if (CPU386)
cmp FailFlag, 0
else
mov ax, word ptr FailFlag+0
or ax, word ptr FailFlag+2
endif
je TestPass
ShowMsg AnyFailMsg

mov ax, 4CFFh
int 21h

TestPass:

ShowMsg NoFailMsg
mov ax, 4C00h
int 21h

;;******************************************************************
align 16
dd 0
dd 0
dd 0
dd 0
dd 0
align 16
EndOfTestLabel label word

ifdef GENERATE_TEST_SKELETON
DOENDSEG equ testcode ends
DOENDLAB equ end start
else
DOENDSEG equ ;;;
DOENDLAB equ ;;;
endif
DOENDSEG
DOENDLAB

-------- TESTMACS.INC (used by BCD.ASM) -----

ifdef GENERATE_TEST_SKELETON
testcode segment use16 para public 'code'
assume cs:testcode
org 100h
start label near
jmp ___TESTSTART
endif

ifndef SILENT_PASS
SILENT_PASS = 0
endif
VARIATIONCOUNT = 0

CPU386 equ (@Cpu and 8)
CPU286 equ (@Cpu and 4)
CPU186 equ (@Cpu and 2)
CPU8086 equ (@Cpu and 1)

FOR386p macro
local foo,msg
.386p
.387
%out ***************************
%out * Assembling for 386p/387 *
%out ***************************
jmp foo
msg db "ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿",13,10
db "³ This test can run on 386p/387 ³",13,10
db "ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ",13,10,'$'
foo: push dx
push ax
push ds
push cs
pop ds
mov ah, 9
mov dx, offset msg
int 21h
pop ds
pop ax
pop dx
endm

FOR386 macro
local foo,msg
.386
.387
%out ***************************
%out * Assembling for 386/387 *
%out ***************************
jmp foo
msg db "ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿",13,10
db "³ This test can run on 386/387 ³",13,10
db "ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ",13,10,'$'
foo: push dx
push ax
push ds
push cs
pop ds
mov ah, 9
mov dx, offset msg
int 21h
pop ds
pop ax
pop dx
endm

FOR286 macro
local foo,msg
.286
.287
%out ***************************
%out * Assembling for 286/287 *
%out ***************************
jmp foo
msg db "ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿",13,10
db "³ This test can run on 286+/287+ ³",13,10
db "ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ",13,10,'$'
foo: push dx
push ax
push ds
push cs
pop ds
mov ah, 9
mov dx, offset msg
int 21h
pop ds
pop ax
pop dx
endm

FOR8086 macro
local foo,msg
.8086
.8087
%out ***************************
%out * Assembling for 8086/8087*
%out ***************************
jmp foo
msg db "ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿",13,10
db "³ This test can run on 8086+/8087+ ³",13,10
db "ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ",13,10,'$'
foo: push dx
push ax
push ds
push cs
pop ds
mov ah, 9
mov dx, offset msg
int 21h
pop ds
pop ax
pop dx
endm

FailFlag dd 0
VarCount dd 0

INCFAILCOUNT macro
pushf
if (CPU386)
inc cs:FailFlag
else
add word ptr cs:FailFlag+0, 1
adc word ptr cs:FailFlag+2, 0
endif
popf
endm

INCVARCOUNT macro
VARIATIONCOUNT = VARIATIONCOUNT + 1
endm

INCVARCOUNTX macro
pushf
if (CPU386)
inc cs:VarCount
else
add word ptr cs:VarCount+0, 1
adc word ptr cs:VarCount+2, 0
endif
popf
endm

ife SILENT_PASS
PassText db " PASS: $"
endif
FailText db " FAIL: $"
CRLF db 13,10,'$'

ShowMsg macro msg
if (CPU186)
pusha
else
push ax
push bx
push cx
push dx
push bp
push si
push di
endif
push ds
push cs
pop ds
mov ah,9
mov dx,offset msg
int 21h
pop ds
if (CPU186)
popa
else
pop di
pop si
pop bp
pop dx
pop cx
pop bx
pop ax
endif
endm

INFORM macro mtext
local foobar, msg1
if SILENT_PASS eq 0
jmp foobar
msg1 db mtext,13,10,'$'
foobar:
pushf
ShowMsg msg1
popf
endif
endm

FailProc proc near
if (CPU186)
pusha
else
push ax
push bx
push cx
push dx
push bp
push si
push di
endif
push ds
push es
push cs
pop ds
INCFAILCOUNT
mov ah, 9
push dx
mov dx, offset FailText
int 21h
pop dx
mov ah, 9
int 21h
mov dx, offset CRLF
mov ah, 9
int 21h
pop es
pop ds
if (CPU186)
popa
else
pop di
pop si
pop bp
pop dx
pop cx
pop bx
pop ax
endif
ret
FailProc endp


PassProc proc near
ife SILENT_PASS
if (CPU186)
pusha
else
push ax
push bx
push cx
push dx
push bp
push si
push di
endif
push ds
push es
push cs
pop ds
mov ah, 9
push dx
mov dx, offset PassText
int 21h
pop dx
mov ah, 9
int 21h
mov dx, offset CRLF
mov ah, 9
int 21h
pop es
pop ds
if (CPU186)
popa
else
pop di
pop si
pop bp
pop dx
pop cx
pop bx
pop ax
endif
endif
ret
PassProc endp


FAIL macro mtext
local foobar, message
jmp foobar
message db mtext,'$'
foobar:
push dx
mov dx, offset message
call FailProc
pop dx
endm

FAILNE macro mtext,docr
local foobar, message, ok
je ok
jmp foobar
message db mtext
ifnb <docr>
db 13,10
endif
db '$'
foobar:
push dx
mov dx, offset message
call FailProc
pop dx
ok:
endm

PASS macro mtext,docr
local foobar, message
ife SILENT_PASS
jmp foobar
ifb <docr>
message db mtext,'$'
else
message db mtext,13,10,'$'
endif
foobar:
push dx
mov dx, offset message
call PassProc
pop dx
endif
endm

NOTEMSG macro mtext
local foobar,message
if SILENT_PASS eq 0
jmp foobar
message db mtext,13,10,'$'
foobar: pushf
push ds
push ax
push dx
push cs
pop ds
mov ah, 9
mov dx, offset message
int 21h
pop dx
pop ax
pop ds
popf
endif
endm

CALLNE macro target
local foo
je foo
call target
foo:
endm



;;******************************************************************
ifdef GENERATE_TEST_SKELETON
___TESTSTART label near
endif


---------- MAKEFILE to build these three tests -------

#CC = tcc
CC = bcc

all: bcd.com bcd2.exe bcd3.exe makefile
copy *.exe ..
copy *.com ..

bcd.com: bcd.asm ..\summary.inc ..\testmacs.inc makefile
tasm bcd
tlink /t bcd
del bcd.obj
del bcd.map

bcd2.exe: bcd2.c bcdutil.h makefile
bcc -f87 -Etasm bcd2.c
del bcd2.obj
del bcd2.map

bcd3.exe: bcd3.c bcdutil.h makefile
bcc -f87 -Etasm bcd3.c
del bcd3.obj
del bcd3.map

Reply 2 of 8, by guest

User metadata

As a graphic and easily reproduced example of how this BCD stuff affects app visual displays simply fire up a copy of Borland's Turbo Debugger (I used the one that came with the BC 3.1 Pro package.

In the assembly window assemble an FINIT and an FLDPI and execute those two instructions

Now go to the numeric processor view window - the value displayed for ST(0) will be ZERO, not Pi.

Turbo Debugger was largely written using Turbo C, and thus uses the C runtime numeric formatting capability, which ultimately depends on BCD ops to create its output strings. I know this for fact, because I was the Borland guy at the time who added the 80 bit long double support to these RTL routines when 80 bit "long double" support was introduced for Turbo C 2.0.

Reply 3 of 8, by mirekluza

User metadata
Rank DOSBox Moderator
Rank
DOSBox Moderator

Perhaps I saw this bug in action. There is a sample application (spreadsheet TCalc) in some older Borland compilers (I think it was in Turbo C++ 1.01 - freely available from Borland). The showed numbers were wrong there (just 0 worked ok).

Mirek

Reply 4 of 8, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

> fbld tbyte ptr TestNum

this opcode isn't implemented.

> Now go to the numeric processor view window - the value displayed
> for ST(0) will be ZERO, not Pi.

this has nothing to do with BCD encoding. the value is
zero because FSAVE isn't implemented.
it works perfectly (tried bp7 td) when FSAVE is implemented.

> I know this for fact, because I was the Borland guy at the time
> who added the 80 bit long double support to these RTL routines

i couldn't see it being used anywhere by td

...and as dosbox uses 64bit lib routines to emulate the fpu,
there won't be bitcorrect 80bit-bcds anyways.

wd

Reply 5 of 8, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

I implemented fsave.
Look at vogons for the details (bugs)
I changed it a bit in my localtree. Will publish details if I'm happy with it

Water flows down the stream
How to ask questions the smart way!

Reply 6 of 8, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

commited it to the cvs.
fsave works fine now.

wd is right. 80 bits will probably broken now and then as we use 64 bits internally.
(i convert them when saving and loading.)

Water flows down the stream
How to ask questions the smart way!

Reply 7 of 8, by MooglyGuy

User metadata
Rank Newbie
Rank
Newbie

Would someone do me a favor and check out how well Crusher v3.2, by Soleau Software runs? For some reason, all of the monsters are far too fast (bad timers? It runs flawlessly in real mode on a 1.2GHz machine), the graphics are slightly messed up, and the score is messed up after a while, it suddenly becomes something to the effect of 999.999, which is why I posted it here, since it might have something to do with BCD.

Reply 8 of 8, by tonyi

User metadata
Rank Newbie
Rank
Newbie

If BCD's were twiddled on a load/store such that only the high order BCD digits get chopped, then the impact would be reduced to those values in the range of the national debt.

Not being in normalized form like an ordinary float is what causes the most problem - losing the bottom bits of an 80 bit temp real on a 64 bit float conversion usually leaves you with something that still somewhat workable although less accurate - a small heavily denormalized number could result in a zero though...

Losing the least significant BCD digits (which are in reality very significant because this is an exact representation format) is harsh though - now its the difference between something like 1234567 and 2056 (completely made up numbers here) rather than 1.2345678912345 and 1.23456789 where the results are at least [somewhat] similar.