Disclaimer: This information
is provided as is. There may be errors in this information. You may use this
information only if you agree that Minimalist / Coinop.org, its employees,
and noted authors will never be held responsible for any damage, injury, death,
mayhem, etc. caused by errors in the information. When working with high
voltage, never work alone and always follow safety precautions.
Document Title: [mathdis2.html (html file)]
Atari mathbox disassembler C source
/***************************************************************************
* MBDISS.C
*
* Atari mathbox disassembler C source.
*
* Copyright (c) Zonn Moore, 1996 All rights reserved.
***************************************************************************/
#include
#include
#define SUBR 1 // Subtract R from S instruction
#define NOTRS 5 // Not R and S instruction
#define r_ZERO 16
#define r_DATA 17
#define r_QREG 18
#define LDAB 0x08
#define STOP 0x08
#define Sb 0x08
#define Jb 0x04
#define Mb 0x02
#define Cb 0x01
int cnvReg( int reg, int index);
/* source indexis */
int RopVal[8] =
{ 1, 1, 0, 0, 0, 3, 3, 3};
int SopVal[8] =
{ 4, 2, 4, 2, 1, 1, 4, 0};
/* mnemonic names */
char *SourceName[5] =
{ "0", "A", "B", "D", "Q"};
char *RegName[19] =
{ "r00", "r01", "r02", "r03", "r04", "r05", "r06", "r07",
"r08", "r09", "r10", "r11", "r12", "r13", "r14", "r15",
"#00", "Dre", "Qre"
};
char *FuncName[8][2] =
{ "add", "adc",
"sbc", "sub", // SUBR
"sbc", "sub", // SUBS
"ior", "ior",
"and", "and",
"and", "and", // NOTRS
"xor", "xor",
"xnr", "xnr"
};
#if 0
char *DestName[8] =
{ "qreg",
"nop",
"rama",
"ramf",
"ramqd",
"ramd",
"ramqu",
"ramu"
};
#endif
unsigned char Prom[6][256];
void main( void)
{
FILE *inFile;
int ii, mm, pp, tt;
int ropH, ropL, sopL, sopH, func, dest;
int regH1, regH2, regL1, regL2, notf, jmpf, A10inv;
// print header
fputs( " 132 131 130 129
128 127\n\n", stdout);
fputs( " A A A A A A A A A A A A A A A A
A A A A\n", stdout);
fputs( " 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
16 17 18 19 S J M C\n\n", stdout);
fputs( " D3 D2 D1 D0 D3 D2 D1 D0 D3 D2 D1 D0 D3 D2 D1 D0
D3 D2 D1 D0 D3 D2 D1 D0\n\n", stdout);
fputs( " 1 2 3 4 20 19 18 17 14H 14L 13* 12 ST 27 28 26
LD 6 7 5 S J M 29\n\n", stdout);
fputs( " A3 A2 A1 A0 B3 B2 B1 B0 I2 I2 I1 I0 I5 I4 I3
I8 I7 I6 Cn\n\n", stdout);
fputs( "Miscellaneous notes:\n", stdout);
fputs( " C = Cin to Acc\n\n", stdout);
fputs( " if ST high, STOP\n\n", stdout);
fputs( " if LD high, Load latch with AB (A0-A7)\n\n", stdout);
fputs( " if J low, never JMP\n", stdout);
fputs( " if J high and S low, JMP to latched value\n", stdout);
fputs( " if J high and S high, JMP if (pos and no OVF) or (neg and OVF)\n\n",
stdout);
fputs( " if M low, A10= A10\n",
stdout);
fputs( " if M high and prev A18 high, A10=~A10\n",
stdout);
fputs( " if M high and prev A18 low and prev RRQ shift out 0, A10=~A10\n",
stdout);
fputs( " if M high and prev A18 low and prev RRQ shift out 1, A10= A10\n\n",
stdout);
fputs( " if A18 high,
R15=1\n", stdout);
fputs( " if S low and A18 low,
R15=0\n", stdout);
fputs( " if S high and A18 low and (pos and no OVF) or (neg and OVF),
R15=0\n", stdout);
fputs( " if S high and A18 low and (pos and OVF) or (neg and no OVF),
R15=1\n\n", stdout);
fputs( " Note that R0 of LSB goes to Q3 of MSB, making all RRQs an extension
of the ALU.\n\n", stdout);
fputs( " In lines that display two opcodes with no asterisk preceeding\n",
stdout);
fputs( " the first opcode, the two opcodes are both executed
simultaneously.\n\n", stdout);
fputs( " The lines proceeded by an asterisk indicates instructions
modified\n", stdout);
fputs( " by the S flag. The instructions marked with a '*' are executed if
the\n", stdout);
fputs( " shift of the prvious instruction shifts out a 0. Otherwise the
alternative\n", stdout);
fputs( " instruction is executed.\n\n", stdout);
fputs( "Jump table:\n", stdout);
fputs( " 00: 20 21 22 23 24 25 26 27 28 29 2A 41 2C 34 35 36\n", stdout);
fputs( " 10: 37 42 7E B8 BD 2E 2F 17 19 18 30 31 D9 EB F4 00\n\n",
stdout);
fputs( "Microcode:", stdout);
// Read in PROMS
inFile = fopen( "136002.132", "rb");
if (inFile == 0)
{ perror( "136002.132");
exit( 0);
}
fread( Prom[0], 1, 256, inFile); // read buffer
fclose( inFile); // close file
inFile = fopen( "136002.131", "rb");
if (inFile == 0)
{ perror( "136002.131");
exit( 0);
}
fread( Prom[1], 1, 256, inFile); // read buffer
fclose( inFile); // close file
inFile = fopen( "136002.130", "rb");
if (inFile == 0)
{ perror( "136002.130");
exit( 0);
}
fread( Prom[2], 1, 256, inFile); // read buffer
fclose( inFile); // close file
inFile = fopen( "136002.129", "rb");
if (inFile == 0)
{ perror( "136002.129");
exit( 0);
}
fread( Prom[3], 1, 256, inFile); // read buffer
fclose( inFile); // close file
inFile = fopen( "136002.128", "rb");
if (inFile == 0)
{ perror( "136002.128");
exit( 0);
}
fread( Prom[4], 1, 256, inFile); // read buffer
fclose( inFile); // close file
inFile = fopen( "136002.127", "rb");
if (inFile == 0)
{ perror( "136002.127");
exit( 0);
}
fread( Prom[5], 1, 256, inFile); // read buffer
fclose( inFile); // close file
// display PROMS
for (ii = 0; ii < 256; ii++)
{
printf( "\n %02X: ", ii); // print address
/* Print microcode */
for (pp = 0; pp < 6; pp++)
{
for (mm = 0x08; mm != 0; mm >>= 1)
printf( "%c", (Prom[pp][ii] & mm) ? '1' : '0');
putchar( ' ');
}
/* Point to mnemonics */
if (!(Prom[5][ii] & Mb))
A10inv = 0x00; // src doesn't change
else
A10inv = 0x02; // src based on OV and Sign
ropL = RopVal[Prom[2][ii] & 0x07];
ropH = RopVal[(Prom[2][ii] & 0x03) | ((Prom[2][ii] & 0x08) >> 1) ^
A10inv];
sopL = SopVal[Prom[2][ii] & 0x07];
sopH = SopVal[(Prom[2][ii] & 0x03) | ((Prom[2][ii] & 0x08) >> 1) ^
A10inv];
func = Prom[3][ii] & 0x07;
dest = Prom[4][ii] & 0x07;
notf = (func == NOTRS);
/* check if sources reversed */
if (func == SUBR)
{ regH1 = sopH;
regH2 = ropH;
regL1 = sopL;
regL2 = ropL;
}
else
{ regH1 = ropH;
regH2 = sopH;
regL1 = ropL;
regL2 = sopL;
}
/* convert to values */
regH1 = cnvReg( regH1, ii);
regH2 = cnvReg( regH2, ii);
regL1 = cnvReg( regL1, ii);
regL2 = cnvReg( regL2, ii);
/* Print mnemonics */
if (A10inv)
fputc( '*', stdout);
else
fputc( ' ', stdout);
fprintf( stdout, "%s(%c%s, %s)",
FuncName[func][Prom[5][ii] & Cb], (notf) ? '~' : ' ', RegName[regH1],
RegName[regH2]);
if ((((Prom[2][ii] >> 1) ^ Prom[2][ii]) & 0x04) && A10inv)
{ fprintf( stdout, "\nError: Different sources from A14 and A10.\n");
exit( 0);
}
/* Check if High and Low sources differ, if so, print low */
if ((((Prom[2][ii] >> 1) ^ Prom[2][ii]) & 0x04) || A10inv)
fprintf( stdout, " %s( %s, %s)",
FuncName[func][Prom[5][ii] & Cb], RegName[regL1],
RegName[regL2]);
else
fputs( " ", stdout);
/* print destination */
fputc( ' ', stdout);
switch (dest)
{
case 0: // QREG
fprintf( stdout, " Qre=ALU OUT=ALU");
break;
case 1: // NOP
fprintf( stdout, " OUT=ALU");
break;
case 2: // RAMA
fprintf( stdout, "%3s=ALU OUT=%3s",
RegName[cnvReg( 2, ii)], RegName[cnvReg( 1, ii)]);
break;
case 3: // RAMF
fprintf( stdout, "%3s=ALU OUT=ALU", RegName[cnvReg( 2, ii)]);
break;
case 4: // RAMQD
/* normal shift with zero */
if (!(Prom[5][ii] & Sb))
fprintf( stdout, "%3s=SRA Qre=RRQ OUT=ALU", RegName[cnvReg( 2,
ii)]);
/* modified shift with overflow */
else
fprintf( stdout, "%3s=OSR Qre=RRQ OUT=ALU", RegName[cnvReg( 2,
ii)]);
break;
case 5: // RAMD
/* normal shift with zero */
if (!(Prom[5][ii] & Sb))
fprintf( stdout, "%3s=SRA OUT=ALU", RegName[cnvReg( 2,
ii)]);
/* modified shift with overflow */
else
fprintf( stdout, "%3s=OSR OUT=ALU", RegName[cnvReg( 2,
ii)]);
break;
case 6: // RAMQU
fprintf( stdout, "%3s=RLA Qre=SLQ OUT=ALU", RegName[cnvReg( 2, ii)]);
break;
case 7: // RAMU
fprintf( stdout, "%3s=RLA OUT=ALU", RegName[cnvReg( 2, ii)]);
break;
}
fputc( ' ', stdout);
/* Print PC control information */
jmpf = 0;
/* check for jumps */
if (Prom[5][ii] & Jb) // if J high, check for jumps
{
if (Prom[5][ii] & Sb) // is S high, JNO
fputs( "JNO ", stdout);
else // if S low, always jmp
{ fputs( "JMP ", stdout);
jmpf = 1;
}
}
else
fputs( " ", stdout);
/* check if latch loaded */
if (Prom[4][ii] & LDAB)
fprintf( stdout, "L%1X%1X ", Prom[0][ii], Prom[1][ii]);
else
fputs( " ", stdout);
/* check for STOP instruction */
if (Prom[3][ii] & STOP)
{ fputs( "HLT", stdout);
jmpf = 1;
}
/* else */
/* fputs( " ", stdout); */
if (jmpf)
putchar( '\n');
}
}
int cnvReg( int reg, int index)
{
int newReg;
switch (reg)
{
case 0:
newReg = r_ZERO; // abs zero
break;
case 1:
newReg = Prom[0][index]; // 0-15 = register numbers
break;
case 2:
newReg = Prom[1][index]; // 0-15 = register numbers
break;
case 3:
newReg = r_DATA; // data port
break;
case 4:
newReg = r_QREG; // Q register
break;
}
return (newReg);
}