VOGONS

Common searches


First post, by guest

User metadata

Similar to my post about the AAA instruction - DAA doesn't work either and fails 538 out of 6144 variations on the following test.

Trusting Intel docs is always risky business ;->

------ Test Case source code (cut here) --------

#pragma inline

/*#define MUTATION /**/
//---------------------------------------------------------------------------
// See if DAA works as expected
//---------------------------------------------------------------------------
// Compile this program with Borland C++ version 3.1 like this:
//
// bcc -v daa.c
//---------------------------------------------------------------------------
#include <stdio.h>
#include <process.h>
#include <dos.h>

typedef unsigned long ULONG;
typedef unsigned short USHORT;
typedef unsigned char UCHAR;

ULONG FailCount = 0L;
ULONG VarCount = 0L;

#define CF_SET 0x01
#define PF_SET 0x04
#define AF_SET 0x10
#define ZF_SET 0x40
#define SF_SET 0x80
#define CF_CLEAR 0x00
#define PF_CLEAR 0x00
#define AF_CLEAR 0x00
#define ZF_CLEAR 0x00
#define SF_CLEAR 0x00

#define GetUCsf(c) ((((UCHAR)(c)) & 0x80) ? SF_SET : SF_CLEAR)
#define GetUCzf(c) ((((UCHAR)(c)) == 0x00) ? ZF_SET : ZF_CLEAR)

UCHAR GetUCpf(UCHAR c)
{
asm mov cx, 8
asm xor al, al
asm mov ah, c
ploop:
asm shr ah, 1
asm adc al, 0
asm loop ploop
asm and ax, 1
return (UCHAR)(_AX ? PF_CLEAR : PF_SET);
}

//-------------------------------------------------------------------------
// Figure out what the result of an DAA will be
//-------------------------------------------------------------------------
void GetDAA(UCHAR ALin, UCHAR FLAGin, UCHAR *ALout, UCHAR *FLAGout)
{
UCHAR f = 0;
UCHAR wrap;

wrap = ((ALin >= 0xFA) ? 1 : 0);

if (((ALin & 0x0F) > 9) || (FLAGin & AF_SET))
{
ALin += 6;
f |= AF_SET;
}
else
{
f &= ~AF_SET;
}

if ((ALin > 0x9F) || (FLAGin & CF_SET) || wrap)
{
ALin += 0x60;
f |= CF_SET;
}
else
{
f &= ~CF_SET;
}

f |= GetUCzf(ALin);
f |= GetUCsf(ALin);
f |= GetUCpf(ALin);

*FLAGout = f;
*ALout = ALin;
}

void CheckVals(UCHAR af,UCHAR cf,UCHAR al,UCHAR ef,UCHAR rf,UCHAR ea,UCHAR ra)
{
VarCount++;
if (ra != ea)
{
FailCount++;
printf("FAIL:CF=%d AF=%d, AL mismatch. Initial=%02X Expected=%02X Got=%02X\n",
cf, af, al, ea, ra);
}

VarCount++;
if ((ef & CF_SET) != (rf & CF_SET))
{
FailCount++;
printf("FAIL:CF=%d AF=%d, CF mismatch. Init AL=%02X Exp CF=%02X Got CF=%02X\n",
cf, af, al, (ef & CF_SET), (rf & CF_SET));
}

VarCount++;
if ((ef & AF_SET) != (rf & AF_SET))
{
FailCount++;
printf("FAIL:CF=%d AF=%d, AF mismatch. Init AL=%02X Exp AF=%02X Got AF=%02X\n",
cf, af, al, (ef & AF_SET), (rf & AF_SET));
}

VarCount++;
if ((ef & ZF_SET) != (rf & ZF_SET))
{
FailCount++;
printf("FAIL:CF=%d AF=%d, ZF mismatch. Init AL=%02X Exp ZF=%02X Got ZF=%02X\n",
cf, af, al, (ef & ZF_SET), (rf & ZF_SET));
}

VarCount++;
if ((ef & PF_SET) != (rf & PF_SET))
{
FailCount++;
printf("FAIL:CF=%d AF=%d, PF mismatch. Init AL=%02X Exp PF=%02X Got PF=%02X\n",
cf, af, al, (ef & PF_SET), (rf & PF_SET));
}

VarCount++;
if ((ef & SF_SET) != (rf & SF_SET))
{
FailCount++;
printf("FAIL:CF=%d AF=%d, SF mismatch. Init AL=%02X Exp SF=%02X Got SF=%02X\n",
cf, af, al, (ef & SF_SET), (rf & SF_SET));
}
}

void main(void)
{
USHORT AXval;

printf(
"+-----------------------------------------------------------------+\n"
"+ Test to validate behavior of 386/486/P5 silicon on DAA behavior +\n"
"+-----------------------------------------------------------------+\n"
);

for (AXval=0; AXval < 256; AXval++)
{
UCHAR ExpectedAL;
UCHAR ExpectedFlags;
UCHAR ReturnedFlags;
UCHAR ReturnedAL;

//---------------------------------------------------------------
// Try out AXval with AF=0 CF=0
//---------------------------------------------------------------
GetDAA((UCHAR)AXval, (AF_CLEAR|CF_CLEAR), &ExpectedAL, &ExpectedFlags);
_AH = (AF_CLEAR | CF_CLEAR);
asm sahf
asm mov ax, word ptr AXval
asm daa
#ifdef MUTATION
asm inc al
asm cmc
#endif
ReturnedAL = _AL;
ReturnedFlags = _FLAGS;
CheckVals(0,0,AXval,ExpectedFlags,ReturnedFlags,ExpectedAL,ReturnedAL);

//---------------------------------------------------------------
// Try out AXval with AF=1 CF=1
//---------------------------------------------------------------
GetDAA((UCHAR)AXval, (AF_SET|CF_SET), &ExpectedAL, &ExpectedFlags);
_AH = (AF_SET | CF_SET);
asm sahf
asm mov ax, word ptr AXval
asm daa
#ifdef MUTATION
asm inc al
asm cmc
#endif
ReturnedAL = _AL;
ReturnedFlags = _FLAGS;
CheckVals(1,1,AXval,ExpectedFlags,ReturnedFlags,ExpectedAL,ReturnedAL);

//---------------------------------------------------------------
// Try out AXval with AF=1 CF=0
//---------------------------------------------------------------
GetDAA((UCHAR)AXval, (AF_SET|CF_CLEAR), &ExpectedAL, &ExpectedFlags);
_AH = (AF_SET | CF_CLEAR);
asm sahf
asm mov ax, word ptr AXval
asm daa
#ifdef MUTATION
asm inc al
asm cmc
#endif
ReturnedAL = _AL;
ReturnedFlags = _FLAGS;
CheckVals(1,0,AXval,ExpectedFlags,ReturnedFlags,ExpectedAL,ReturnedAL);

//---------------------------------------------------------------
// Try out AXval with AF=0 CF=1
//---------------------------------------------------------------
GetDAA((UCHAR)AXval, (AF_CLEAR|CF_SET), &ExpectedAL, &ExpectedFlags);
_AH = (AF_CLEAR | CF_SET);
asm sahf
asm mov ax, word ptr AXval
asm daa
#ifdef MUTATION
asm inc al
asm cmc
#endif
ReturnedAL = _AL;
ReturnedFlags = _FLAGS;
CheckVals(0,1,AXval,ExpectedFlags,ReturnedFlags,ExpectedAL,ReturnedAL);
}

printf("Points tested = %lu\n", VarCount);
printf("Failures = %lu\n", FailCount);
if (FailCount != 0)
{
printf("*** THIS TEST FAILS! ***\n");
exit(-1);
}
printf("*** THIS TEST PASSED ***\n");
exit(0);
}