Category : Files from Magazines
Archive   : DDJ8612.ZIP
Filename : RODMAN.DEC

 
Output of file : RODMAN.DEC contained in archive : DDJ8612.ZIP
/* A32000.C - Series 32000 assembler
850903 rr fix addr ext, scaled index, acp, cxp 0.10
850902 rr add scaled index logic 0.09
850828 rr fix enter, setcfg, lpr/spr, index 0.08
850809 rr add equate logic 0.07
850730 rr add binary search in lookup 0.06
850729 rr symbol table mods, reglist 0.05

Still need:
--- register names for lpr/spr
--- linkable modules

Note: While 68000 is hilo (high-bytes at lower memory
addresses), 32000 is lohi (low-bytes at lower memory
addresses, like the Z80).

This is a 3-pass assembler; 3 passes to make
sure that relative branches are computed correctly. */

#define EOF -1

#define SYMSIZ 1024 /* symbol table size */

char inpbuf[ 256 ]; /* input buffer */
int inpcnt, inpptr; /* input counter, pointer */

char word_buffer[ 128 ]; /* buff for current word */
char ambig_buffer[ 128 ]; /* ambiguous refs here */

char listline[ 81 ]; /* line of listing output */
int listop, listcp; /* pointers for list output */

int paren = 0; /* used in gchar() */
int brack = 0;
int quote = 0;

int iwparen = 0; /* used in inword() */

int errors = 0; /* count of errors */

char *word; /* pointer to current word */
char *ambig[ 10 ]; /* filled in by match */
int ambcnt = 0; /* count of pointers in ambig[] */

int pass; /* pass = 1, 2 or 3 */
long int asmadr, codadr; /* assembly addr, code addr */
char filename[ 30 ];

int fasm, fobj; /* file numbers */

char objbuf[ 64 ]; /* object byte buffer */
long int objadr; /* addr of first byte of buf */
int objcnt = 0; /* count of bytes in buffer */

struct { /* Symbol table */
char *snam; /* symbol name */
long int sval; /* value */
} symbol[ SYMSIZ ];

int symcnt; /* count of symbols */

char hexchr[ 17 ] = "0123456789abcdef";

/* --- 32000 opcodes --- */

/* Note: Shortest form of opcode must be listed first. */

#define MAXOP 149

/* the opcode binary value should be a string of bits,
e.g. 0111xxxxx000b the opcode opopt character is used
to specify special operands, etc. */

/* opopts used here for the 32000 are:
blank nothing special
a gen
b gen short
c gen gen
d 00000 short
e gen gen reg
f reglist save/enter
g reglist restore/exit
h 00000 gen (sfsr)
i inss/exts
j movs/skps/cmps
k setcfg
l procreg, gen for lpr/spr
m index (operand order)
n ret/rett - postbyte
o movm
p cxp (disp after instruction) */

struct {
char *onam; /* opcode name */
int ocnt; /* operand count, negative if PC-rel */
char *obin; /* opcode binary value */
char oopt; /* opcode opopt char */
} opcode[ MAXOP ] = {

/* Format 1 ops (16) */

"bsr", -1, "02h", ' ',
"ret", 1, "12h", 'n',
"cxp", 1, "22h", 'p',
"rxp", 1, "32h", 'n',
"rett", 1, "42h", 'n',
"reti", 0, "52h", ' ',
"save", 1, "62h", 'f',
"restore", 1, "72h", 'g',
"enter", 2, "82h", 'f',
"exit", 1, "92h", 'g',
"nop", 0, "0a2h", ' ',
"wait", 0, "0b2h", ' ',
"dia", 0, "0c2h", ' ',
"flag", 0, "0d2h", ' ',
"svc", 0, "0e2h", ' ',
"bpt", 0, "0f2h", ' ',

/* Conditional branches (15) */

"beq", -1, "0ah", 'b',
"bne", -1, "1ah", 'b',
"bcs", -1, "2ah", 'b',
"bcc", -1, "3ah", 'b',
"bhi", -1, "4ah", 'b',
"bls", -1, "5ah", 'b',
"bgt", -1, "6ah", 'b',
"ble", -1, "7ah", 'b',
"bfs", -1, "8ah", 'b',
"bfc", -1, "9ah", 'b',
"blo", -1, "0aah", 'b',
"bhs", -1, "0bah", 'b',
"blt", -1, "0cah", 'b',
"bge", -1, "0dah", 'b',
"br", -1, "0eah", 'b',

/* Format 2 ops (7) */

"addq?", 2, "xxxxxxxxx00011iib", 'e',
"cmpq?", 2, "xxxxxxxxx00111iib", 'e',
"spr?", 2, "xxxxxxxxx01011iib", 'l',
"lpr?", 2, "xxxxxxxxx11011iib", 'l',

"seq?", 1, "xxxxx000001111iib", 'a',
"sne?", 1, "xxxxx000101111iib", 'a',
"scs?", 1, "xxxxx001001111iib", 'a',
"scc?", 1, "xxxxx001101111iib", 'a',
"shi?", 1, "xxxxx010001111iib", 'a',
"sls?", 1, "xxxxx010101111iib", 'a',
"sgt?", 1, "xxxxx011001111iib", 'a',
"sle?", 1, "xxxxx011101111iib", 'a',
"sfs?", 1, "xxxxx100001111iib", 'a',
"sfc?", 1, "xxxxx100101111iib", 'a',
"slo?", 1, "xxxxx101001111iib", 'a',
"shs?", 1, "xxxxx101101111iib", 'a',
"slt?", 1, "xxxxx110001111iib", 'a',
"sge?", 1, "xxxxx110101111iib", 'a',
"st?", 1, "xxxxx111001111iib", 'a',
"sf?", 1, "xxxxx111101111iib", 'a',

/* The acb instruction 3rd operand is a relative jump */

"acb?", -3, "xxxxxxxxx10011iib", 'e',
"movq?", 2, "xxxxxxxxx10111iib", 'e',

/* Format 3 instructions (7) */

"cxpd", 1, "xxxxx00001111111b", 'a',
"bicpsr?", 1, "xxxxx001011111iib", 'a',
"jump", 1, "xxxxx01001111111b", 'a',
"bispsr?", 1, "xxxxx011011111iib", 'a',
"adjsp?", 1, "xxxxx101011111iib", 'a',
"jsr", 1, "xxxxx11001111111b", 'a',
"case?", 1, "xxxxx111011111iib", 'a',

/* Format 11 ops (16) -
moved here so wildcards won't interfere */

"addf", 2, "xxxxxxxxxx00000110111110b", 'c',
"addl", 2, "xxxxxxxxxx00000010111110b", 'c',
"movf", 2, "xxxxxxxxxx00010110111110b", 'c',
"movl", 2, "xxxxxxxxxx00010010111110b", 'c',
"cmpf", 2, "xxxxxxxxxx00100110111110b", 'c',
"cmpl", 2, "xxxxxxxxxx00100010111110b", 'c',
"subf", 2, "xxxxxxxxxx01000110111110b", 'c',
"subl", 2, "xxxxxxxxxx01000010111110b", 'c',
"negf", 2, "xxxxxxxxxx01010110111110b", 'c',
"negl", 2, "xxxxxxxxxx01010010111110b", 'c',
"divf", 2, "xxxxxxxxxx10000110111110b", 'c',
"divl", 2, "xxxxxxxxxx10000010111110b", 'c',
"mulf", 2, "xxxxxxxxxx11000110111110b", 'c',
"mull", 2, "xxxxxxxxxx11000010111110b", 'c',
"absf", 2, "xxxxxxxxxx11010110111110b", 'c',
"absl", 2, "xxxxxxxxxx11010010111110b", 'c',

/* Format 4 instructions (12) */

"add?", 2, "xxxxxxxxxx0000iib", 'c',
"cmp?", 2, "xxxxxxxxxx0001iib", 'c',
"bic?", 2, "xxxxxxxxxx0010iib", 'c',
"addc?", 2, "xxxxxxxxxx0100iib", 'c',
"mov?", 2, "xxxxxxxxxx0101iib", 'c',
"or?", 2, "xxxxxxxxxx0110iib", 'c',
"sub?", 2, "xxxxxxxxxx1000iib", 'c',
"addr", 2, "xxxxxxxxxx100111b", 'c',
"lxpd", 2, "xxxxxxxxxx100111b", 'c',
"and?", 2, "xxxxxxxxxx1010iib", 'c',
"subc?", 2, "xxxxxxxxxx1100iib", 'c',
"tbit?", 2, "xxxxxxxxxx1101iib", 'c',
"xor?", 2, "xxxxxxxxxx1110iib", 'c',

/* Format 5 instructions (4) */

"movst", 1, "00000xxx100000ii00001110b", 'j',
"movs?", 1, "00000xxx000000ii00001110b", 'j',
"cmpst", 1, "00000xxx100001ii00001110b", 'j',
"cmps?", 1, "00000xxx000001ii00001110b", 'j',
"skpst", 1, "00000xxx100011ii00001110b", 'j',
"skps?", 1, "00000xxx000011ii00001110b", 'j',

"setcfg", 1, "00000xxxx000101100001110b", 'k',

/* Format 6 ops (14) */

"rot?", 2, "xxxxxxxxxx0000ii01001110b", 'c',
"ash?", 2, "xxxxxxxxxx0001ii01001110b", 'c',
"cbit?", 2, "xxxxxxxxxx0010ii01001110b", 'c',
"cbiti?", 2, "xxxxxxxxxx0011ii01001110b", 'c',
"lsh?", 2, "xxxxxxxxxx0101ii01001110b", 'c',
"sbit?", 2, "xxxxxxxxxx0110ii01001110b", 'c',
"sbiti?", 2, "xxxxxxxxxx0111ii01001110b", 'c',
"neg?", 2, "xxxxxxxxxx1000ii01001110b", 'c',
"not?", 2, "xxxxxxxxxx1001ii01001110b", 'c',
"subp?", 2, "xxxxxxxxxx1011ii01001110b", 'c',
"abs?", 2, "xxxxxxxxxx1100ii01001110b", 'c',
"com?", 2, "xxxxxxxxxx1101ii01001110b", 'c',
"ibit?", 2, "xxxxxxxxxx1110ii01001110b", 'c',
"addp?", 2, "xxxxxxxxxx1111ii01001110b", 'c',

/* Format 7 ops (15) */

"movm?", 3, "xxxxxxxxxx0000ii11001110b", 'o',
"cmpm?", 2, "xxxxxxxxxx0001ii11001110b", 'c',
"inss?", 4, "xxxxxxxxxx0010ii11001110b", 'i',
"exts?", 4, "xxxxxxxxxx0011ii11001110b", 'i',
"movxbw?", 2, "xxxxxxxxxx0100ii11001110b", 'c',
"movzbw?", 2, "xxxxxxxxxx0101ii11001110b", 'c',
"movz?d", 2, "xxxxxxxxxx0110ii11001110b", 'c',
"movx?d", 2, "xxxxxxxxxx0111ii11001110b", 'c',
"mul?", 2, "xxxxxxxxxx1000ii11001110b", 'c',
"mei?", 2, "xxxxxxxxxx1001ii11001110b", 'c',
"dei?", 2, "xxxxxxxxxx1011ii11001110b", 'c',
"quo?", 2, "xxxxxxxxxx1100ii11001110b", 'c',
"rem?", 2, "xxxxxxxxxx1101ii11001110b", 'c',
"mod?", 2, "xxxxxxxxxx1110ii11001110b", 'c',
"div?", 2, "xxxxxxxxxx1111ii11001110b", 'c',

/* Format 8 ops (8) */

"ext?", 4, "xxxxxxxxxxxxx0ii00101110b", 'm',
"cvtp", 3, "xxxxxxxxxxxxx01101101110b", 'm',
"ins?", 4, "xxxxxxxxxxxxx0ii10101110b", 'm',
"check?", 3, "xxxxxxxxxxxxx0ii11101110b", 'm',
"index?", 3, "xxxxxxxxxxxxx1ii00101110b", 'm',
"ffs?", 2, "xxxxxxxxxx0001ii01101110b", 'c',
"movsu?", 2, "xxxxxxxxxx0011ii10101110b", 'c',
"movus?", 2, "xxxxxxxxxx0111ii10101110b", 'c',

/* Format 9 ops (12) */

"movlf", 2, "xxxxxxxxxx0101ii00111110b", 'c',
"movfl", 2, "xxxxxxxxxx0111ii00111110b", 'c',
"mov?f", 2, "xxxxxxxxxx0001ii00111110b", 'c',
"mov?l", 2, "xxxxxxxxxx0000ii00111110b", 'c',
"lfsr", 1, "xxxxx0000000111100111110b", 'a',
"sfsr", 1, "00000xxxxx11011100111110b", 'h',
"roundf?", 2, "xxxxxxxxxx1001ii00111110b", 'c',
"roundl?", 2, "xxxxxxxxxx1000ii00111110b", 'c',
"truncf?", 2, "xxxxxxxxxx1011ii00111110b", 'c',
"truncl?", 2, "xxxxxxxxxx1010ii00111110b", 'c',
"floorf?", 2, "xxxxxxxxxx1111ii00111110b", 'c',
"floorl?", 2, "xxxxxxxxxx1110ii00111110b", 'c',

/* Format 14 instructions (4) */

"rdval", 1, "xxxxxxxxx000001100011110b", 'a',
"wrval", 1, "xxxxxxxxx000011100011110b", 'a',
"lmr", 2, "xxxxxxxxx000101100011110b", 'e',
"smr", 2, "xxxxxxxxx000111100011110b", 'e'
};

/* Address Mode Table */

#define MAXAM 42

struct {
char *mstr; /* mode match string */
char *gstr; /* output string to insert (gen) */
int mcnt; /* count of ambigs to be put into
extension bytes */

char mopt; /* mode option */
} admode[ MAXAM ] = {

/* Scaled index modes */

"*[r?:b]", "11100", 1, 's',
"*[r?:w]", "11101", 1, 's',
"*[r?:d]", "11110", 1, 's',
"*[r?:q]", "11111", 1, 's',

/* Simple register modes */

"r0", "00000", 0, ' ', /* main registers */
"r1", "00001", 0, ' ',
"r2", "00010", 0, ' ',
"r3", "00011", 0, ' ',
"r4", "00100", 0, ' ',
"r5", "00101", 0, ' ',
"r6", "00110", 0, ' ',
"r7", "00111", 0, ' ',

"f0", "00000", 0, ' ', /* floating point */
"f1", "00001", 0, ' ',
"f2", "00010", 0, ' ',
"f3", "00011", 0, ' ',
"f4", "00100", 0, ' ',
"f5", "00101", 0, ' ',
"f6", "00110", 0, ' ',
"f7", "00111", 0, ' ',

/* Indexed addressing modes */

"*(r0)", "01000", 1, ' ', /* indexed */
"*(r1)", "01001", 1, ' ',
"*(r2)", "01010", 1, ' ',
"*(r3)", "01011", 1, ' ',
"*(r4)", "01100", 1, ' ',
"*(r5)", "01101", 1, ' ',
"*(r6)", "01110", 1, ' ',
"*(r7)", "01111", 1, ' ',

"*(*(fp))", "10000", 2, 'r', /* frame ptr */
"*(*(sp))", "10001", 2, 'r', /* stack mem */
"*(*(sb))", "10010", 2, 'r', /* static mem */

"#*", "10100", 1, ' ', /* immediate */
"@*", "10101", 1, ' ', /* absolute */
"ext(*)+*", "10110", 2, ' ', /* external */
"tos", "10111", 0, ' ', /* top of stack */

"*(fp)", "11000", 1, ' ', /* frame mem */
"*(sp)", "11001", 1, ' ', /* stack mem */
"*(sb)", "11010", 1, ' ', /* static mem */

".+*", "11011", 1, ' ', /* program mem */

"[*]", "", 0, 'l', /* register list */

/* catch-all */

"*", "", 1, 'w' /* fits no pattern */
};

/*---MAIN PROGRAM---*/

main( argc, argv )
int argc;
char *argv[];
{
int i;

puts( "\nA32000 v0.10" );

if( argc < 2 ) {
puts( "\n?No file name specified" );
exit( 1 );
}

symcnt = 0;

for( pass = 1; pass <= 3; ++pass ) {

makename( argv[ 1 ], ".s" );
fasm = fopen( filename, "r" );

if( fasm == 0 ) {
puts( "\n?Unable to open source file" );
exit( 1 );
}

if( pass == 3 ) {
makename( argv[ 1 ], ".hex" );
fobj = fopen( filename, "w" );
if( ! fobj ) {
puts( "\n?No directory space" );
exit( 1 );
}
}

puts( "\nPass " );
putchar( pass + '0' );

asmadr = 0;
codadr = 0;

if( pass == 3 ) {
objflush();
listnl();
}
inpload();

while( gword() ) {

if( match( word, "end" )) break;

/* Each word is processed by the following nested if
statement, which attempts to identify what it is.
Note that any successful identification stops the
process of the statement. */

if( ! islabel( word ))
if( ! ispseudo( word ))
if( ! isopcode( word ))
if( ! isequate( word ))
error( '?', word );
}

fclose( fasm );

/* Sort symbols after pass 1. */

if( pass == 1 ) sortsyms();

if( pass == 3 ) {
objflush();

putc( ':', fobj ); /* write eof record */
for( i = 0; i < 10; ++i ) putc( '0', fobj );
putc( '\n', fobj );

fclose( fobj );
}
}

listpr();
puts( "\n\n" );
dumpsyms();

if( errors )
puts( "\n---Fix errors and reassemble---" );
}

/* Construct a filename from two strings. */

makename( p, q )
char *p, *q;
{
char *r;
r = &filename[ 0 ];
while( *p ) *r++ = *p++;
while( *q ) *r++ = *q++;
*r = '\0';
}

/* Check to see if the word is a label, and if it is, add
its value to the symbol table */

int islabel( w )
char *w;
{
while( *w ) ++w;
if( *--w != ':' ) return 0;
*w = '\0'; /* take off the colon */

addsymbol( word, codadr );
return 1;
}

/* Check the word to see if it is a pseudo-op. */

int ispseudo( w )
char *w;
{
long int getarg(), temp;

if( match( w, "org" )) {
asmadr = getarg();
codadr = asmadr;
if( pass == 3 ) objflush();
return 1;
}

if( match( w, "db" )) { /* Note: Allow msgs? */
temp = getarg(); /* get argument */
objout( temp & 0xFF ); /* output byte */
return 1;
}

if( match( w, "dw" )) {
temp = getarg(); /* get argument */
objout( temp & 0xFF ); /* output lsb */
objout(( temp >> 8 ) & 0xFF ); /* output msb */
return 1;
}

if( match( w, "dd" )) {
temp = getarg(); /* get argument */
objout( temp & 0xFF ); /* output lsb */
objout(( temp >> 8 ) & 0xFF );
objout(( temp >> 16 ) & 0xFF );
objout(( temp >> 24 ) & 0xFF ); /* output msb */
return 1;
}

if( match( w, "even" ) && ( codadr & 1 )) {
objout( 0 ); /* send 1 byte to go to word bndry */
return 1;
}

return 0;
}

/* Check to see if the word is an opcode, and if it is,
get any operands required and generate code. */

int isopcode( w )
char *w;
{
long int value(), bitbin(), decbin(), o, ocodadr;
char opbuf[ 33 ], bytbuf[ 33 ], extbuf[ 128 ];
char opopt, modopt, opsiz, opcnt;
int i, j, k, l;
char *p, *q, *cpystr(), *regbits();

/* postbytes & scaled indexes */
int opexbt[ 4 ], opexct;

int adexct, adexln[ 8 ];
char *adexpt[ 8 ], *eoadex; /* addressing extensions */

ocodadr = codadr; /* save addr of begin of instr */

opexct = 0; /* no postbytes as yet */
adexct = 0; /* no extensions as yet */
eoadex = &extbuf[ 0 ]; /* point to begin of extbuf */

for( i = 0; i < MAXOP; ++i )
if( match( w, opcode[ i ].onam )) {

opopt = opcode[ i ].oopt;

if( opopt == 'x' ) {
error( 'x', w ); /* unimplemented instruction */
return 1;
}

p = cpystr( opcode[ i ].obin, &opbuf[ 0 ] );

/* see if length modifier */

if( ambcnt > 0 ) {
p = &opbuf[ 0 ];
opsiz = *ambig[ 0 ];

while( *p && *p != 'i' ) ++p;

if( ! *p ) error( 'l', w );
else {
switch( opsiz ) {

case 'b' : *p++ = '0';
*p++ = '0';
break;

case 'w' : *p++ = '0';
*p++ = '1';
break;

case 'd' : *p++ = '1';
*p++ = '1';
}
}
}

/* now parse operands */

/* get count of operands.
Take abs value (neg = PC-relative) */

opcnt = opcode[ i ].ocnt;
if( opcnt < 0 ) opcnt = 0 - opcnt;

p = &opbuf[ 0 ]; /* modified parts start at beg. */

for( j = 0; j < opcnt; ++j ) {
gword(); /* get operand */

/* find addr mode */

k = 0;
while(( k < MAXAM )
&& ! match( word, admode[ k ].mstr )) ++k;

modopt = admode[ k ].mopt;

/* move bit string into place */

q = admode[ k ].gstr;

/* if opopt h, sfsr, skip 5 bits */

if( opopt == 'h' ) p += 5;

/* for most opopts, move the bits in */

if(( opopt == ' ' )
|| ( opopt == 'a' )
|| ( opopt == 'c' )
|| ( opopt == 'e' && j == 1 )
|| ( opopt == 'h' )
|| ( opopt == 'i' && j < 2 )
|| ( opopt == 'l' && j == 1 )
|| ( opopt == 'm' && j > 0 && j < 3 )
|| ( opopt == 'o' && j < 2 ))
while( *q ) *p++ = *q++;

/* Double the effort for scaled index mode. create an
extension postbyte opexbt[] with basemode as upper
5 bits, reg as lower 3 bits. */

if( admode[ k ].mopt == 's' ) {
l = ( *ambig[ 1 ] ) & 7;
q = cpystr( ambig[ 0 ], &bytbuf[ 0 ] );

/* find basemode */

k = 0;
while(( k < MAXAM )
&& ! match( &bytbuf[ 0 ],
admode[ k ].mstr )) ++k;

modopt = admode[ k ].mopt;

/* move bit string into postbyte. use bitbin, because
value() destroys ambig[] array which we still need. */

q = cpystr( admode[ k ].gstr,
&bytbuf[ 0 ] );
--q; /* back up to null */
*q++ = '0' + (( l >> 2 ) & 1 );
*q++ = '0' + (( l >> 1 ) & 1 );
*q++ = '0' + ( l & 1 );
*q = '\0';

opexbt[ opexct++ ] = bitbin( &bytbuf[ 0 ] );
q = admode[ k ].gstr;
}

/* funny handling of reg: index operation (opopt 'm') */

if( opopt == 'm' && j == 0 ) {
p = &opbuf[ 10 ]; /* off to reg */
q += 2; /* skip 0 bits */
while( *q ) *p++ = *q++;
p = &opbuf[ 0 ]; /* reset */
}

/* move ambigs into extension bytes. set length to
variable (0). For some addressing modes, the
extensions go in in reverse order */

if( modopt == 'r' )
for( l = admode[ k ].mcnt - 1; l >= 0;
--l ) {
adexpt[ adexct ] = eoadex;
adexln[ adexct ] = 0;
++adexct;
eoadex = cpystr( ambig[ l ], \
eoadex );
} else for( l = 0; l < admode[ k ].mcnt; ++l ) {
adexpt[ adexct ] = eoadex;
adexln[ adexct ] = 0;
++adexct;
eoadex = cpystr( ambig[ l ], \
eoadex );
}

/* special logic for register list for "enter", "save",
"restore", "exit" */

if(( j == 0 && opopt == 'f' ) || opopt == 'g' ) {
adexpt[ adexct ] = eoadex;
adexln[ adexct ] = 1;
++adexct;
eoadex = regbits( word, eoadex, opopt );
}

/* shorten extension to 1 byte for enter, return */

if(( j == 1 && opopt == 'f' ) || opopt == 'n' ) {
if( adexct > 0 ) adexln[ adexct - 1 ] = 1;
else error( 'e', w );
}

/* opopts 'e' or 'd': immed data becomes 4 bit value */

if(( j == 0 && opopt == 'e' ) || opopt == 'd' ) {
if( ! adexct ) error( 'e', w );
else {
l = value( adexpt[ --adexct ] );
p = &opbuf[ 5 ];
*p++ = '0' + (( l >> 3 ) & 1 );
*p++ = '0' + (( l >> 2 ) & 1 );
*p++ = '0' + (( l >> 1 ) & 1 );
*p = '0' + ( l & 1 );
p = &opbuf[ 0 ];
}
}

/* opopt 'i': combine last two ambigs into one postbyte.
Put it in bytbuf and set length to 1 */

if( opopt == 'i' && j == 3 ) {
if( adexct < 2 ) error( 'e', w );
else {
l = ( value( adexpt[ --adexct ] ) - 1 )
& 31;
l += ( value( adexpt[ --adexct ] )
& 7 ) << 5;
bytbuf[ 0 ] = '0' +
(( l / 100 ) % 10 );
bytbuf[ 1 ] = '0' +
(( l / 10 ) % 10 );
bytbuf[ 2 ] = '0' + ( l % 10 );
bytbuf[ 3 ] = '\0';
adexpt[ adexct ] = &bytbuf[ 0 ];
adexln[ adexct++ ] = 1;
}
}

/* opopt 'j': uwb bits for movs, cmps, skps */

if( opopt == 'j' ) {
p += 5;
uwbbits( word, p );
adexct = 0; /* in case no paren */
}

/* opopt 'k': config bits for setcfg */

if( opopt == 'k' ) {
p += 5;
cfgbits( word, p );
}

/* opopt 'l': operand 1 becomes 4 bit value */

if( opopt == 'l' && j == 0 ) {
adexct = 0; /* unjunk extensions */
l = -1;
if( strcmp( word, "upsr" ) == 0 ) l = 0;
if( strcmp( word, "fp" ) == 0 ) l = 8;
if( strcmp( word, "sp" ) == 0 ) l = 9;
if( strcmp( word, "sb" ) == 0 ) l = 10;
if( strcmp( word, "psr" ) == 0 ) l = 13;
if( strcmp( word, "intbase" ) == 0 ) l = 14;
if( strcmp( word, "mod" ) == 0 ) l = 15;
if( l == -1 ) error( 'p', word );
else {
p = &opbuf[ 5 ];
*p++ = '0' + (( l >> 3 ) & 1 );
*p++ = '0' + (( l >> 2 ) & 1 );
*p++ = '0' + (( l >> 1 ) & 1 );
*p = '0' + ( l & 1 );
p = &opbuf[ 0 ];
}
}

/* odd length extension for movm, opopt 'o' */

if( j == 2 && opopt == 'o' ) {
if( adexct > 0 ) adexln[ --adexct ] = 1;
else error( 'e', w );
l = value( adexpt[ adexct ] ) - 1;
switch( opsiz ) {
case 'd' : l *= 4; break;
case 'w' : l *= 2; break;
}
bytbuf[ 0 ] = '0' + (( l / 100 ) % 10 );
bytbuf[ 1 ] = '0' + (( l / 10 ) % 10 );
bytbuf[ 2 ] = '0' + ( l % 10 );
bytbuf[ 3 ] = '\0';
adexpt[ adexct++ ] = &bytbuf[ 0 ];
}

} /* done operands */

o = value( &opbuf[ 0 ] );

l = strlen( opbuf );

/* Send as many opcode bytes as necessary */

objout( o % 256 );
if( l > 9 ) objout(( o / 256 ) % 256 );
if( l > 17 ) objout( o / 65536 );

/* Send postbytes for scaled index mode */

for( l = 0; l < opexct; ++l )
objout( opexbt[ l ] );

/* Send addressing extensions.
adexln = length of extension word in bytes if +.
If 0, it is a variable-length signed displacement.
If -1, indicates code-relative */

/* If opcode ocnt was negative, last address extension is
code relative. */

if( opcode[ i ].ocnt < 0 )
adexln[ adexct - 1 ] = -1;

/* send extension words */

for( j = 0; j < adexct; ++j ) {


o = value( adexpt[ j ] );

/* if adexln[] negative, operand(s) code-relative.
Note: on the 32000 you don't correct by adding 2 to
codadr first */

if( adexln[ j ] < 0 ) o -= ocodadr;

/* Compute variable-length signed displacement */

if( adexln[ j ] <= 0 ) {
if( o < 63 && o > -64 ) {
o = ( o & 0x7F );
l = 1; /* one-byte */
} else if( o < 8191 && o > -8192 ) {
o = ( o & 0x3FFF ) + 0x8000;
l = 2;
} else {
o = ( o & 0x3FFFFFFF )
+ 0xC0000000;
l = 4;
}
} else l = adexln[ j ];

/* address extensions are sent in lohi order */

if( l > 3 ) objout(( o >> 24 ) & 0xFF );
if( l > 2 ) objout(( o >> 16 ) & 0xFF );
if( l > 1 ) objout(( o >> 8 ) & 0xFF );
objout( o % 256 );
}
return 1;
}
return 0;
}

/* Special to create extension word for register list */

/* Regbits may look like "r0" or may look like "[r0,r2]"
or like "[r0-r7]". */

char *regbits( src, dst, flg )
char *src, *dst, flg;
{
int bits, reg, loreg, hireg;

bits = 0;

if( *src == '[' ) ++src; /* strip parens */
else error( '[', src );

while( *src ) {
if( *src++ != 'r' ) error( 'r', src );
reg = ( *src++ ) - '0';
bits = bits | ( 1 << reg );
if( *src++ == '-' ) {
loreg = reg;
if( *src++ != 'r' ) error( 'r', src );
hireg = ( *src++ ) - '0';
if( hireg < loreg ) {
reg = hireg;
hireg = loreg;
loreg = reg;
} /* swap if out of order */
for( reg = loreg; reg <= hireg; ++reg )
bits = bits | ( 1 << reg );
++src; /* skip over the comma */
}
if( *src == ']' ) break;
}

/* if flg = 'f', save/enter, need to swap bit
significance. The routine above constructed it in
reversed order in the first place, because of the
routine below */

if( flg == 'f' ) {
hireg = 0;
for( reg = 0; reg < 8; ++reg ) {
hireg = ( hireg << 1 ) + ( bits & 1 );
bits = ( bits >> 1 );
}
bits = hireg;
}

/* now create a binary string for the extension.
Note that bit significance becomes reversed again */

for( reg = 0; reg < 8; ++reg ) {
*dst++ = '0' + ( bits & 1 );
bits = ( bits >> 1 );
}

*dst++ = 'b'; /* add b for binary */
*dst++ = '\0'; /* terminate */

return dst;
}

/* put config bits into instruction */

cfgbits( src, dst )
char *src, *dst;
{
char b[ 4 ];

b[ 0 ] = '0';
b[ 1 ] = '0';
b[ 2 ] = '0';
b[ 3 ] = '0';

if( *src == '[' ) ++src; /* strip parens */
else error( '[', src );

while( *src ) {
switch( *src++ ) {

case 'c' : b[ 0 ] = '1';
break;

case 'm' : b[ 1 ] = '1';
break;

case 'f' : b[ 2 ] = '1';
break;

case 'i' : b[ 3 ] = '1';
}

if( *src++ == ']' ) break;
}
*dst++ = b[ 0 ];
*dst++ = b[ 1 ];
*dst++ = b[ 2 ];
*dst = b[ 3 ];
}

/* put uwb bits into instruction */

uwbbits( src, dst )
char *src, *dst;
{
char b[ 3 ];

b[ 0 ] = '0'; /* default = forward */
b[ 1 ] = '0'; /* default = neither */
b[ 2 ] = '0';

while( *src ) {
switch( *src++ ) {

case 'b' : b[ 2 ] = '1'; /* backward */
break;

case 'u' : b[ 0 ] = '1'; /* until match */
b[ 1 ] = '1';
break;

case 'w' : b[ 0 ] = '0'; /* while match */
b[ 1 ] = '1';
}
}
*dst++ = b[ 0 ];
*dst++ = b[ 1 ];
*dst = b[ 2 ];
}

/* Check to see if the word begins an equate, and if it
does, add the symbol to the symbol table. */

int isequate( w )
char *w;
{
char tempword[ 128 ];
char *q, *cpystr();

long int l, getarg();

q = cpystr( w, &tempword[ 0 ] );

gword(); /* get next word */

if( strcmp( word, "equ" ) == 0 ||
strcmp( word, "=" ) == 0 ) {
l = getarg(); /* get argument */

addsymbol( &tempword[ 0 ], l );

return 1; /* it was an equate */
}

return 0; /* we lost a word */
}

/* Get an argument value (for use above). */

long int getarg()
{
long int value();

gword(); /* get next word */
return value( word );
}

/* copy string and return new ending address */

char *cpystr( src, dst )
char *src, *dst;
{
while( *src ) *dst++ = *src++;
*dst++ = '\0'; /* terminate copied string */
return dst; /* return next address */
}

/* Calculate the value of a word. It may be a symbol, a
constant, or a computed value (must be enclosed in
parentheses.) */

long int value( w )
char *w;
{
long int hexbin(), octbin(), bitbin(), decbin(), v;
int lookup(), i, negate;

char *q;

char *wp[ 16 ];
int wpcnt;

negate = 0;

if( *w == '-' ) { /* Unary negation */
negate = 1;
++w;
}

if( strcmp( w, "." ) == 0 )
return codadr; /* . = code address */
if( strcmp( w, ".." ) == 0 )
return asmadr; /* .. = assembly address */

if( isdigit( *w )) {
if( match( w, "*h" )) v = hexbin( w );
else if( match( w, "*q" )) v = octbin( w );
else if( match( w, "*b" ))
v = bitbin( w );
else v = decbin( w );
} else {

if( *w == '(' ) { /* --- FORMULA --- */
++w; /* skip ( */
q = w;
while( *q ) ++q; /* find end of string */
--q;
if( *q != ')' ) error( ')', q );
else *q = '\0'; /* zap ) */

iwparen = 0; /* no parens now */

wpcnt = 0;

while( 1 ) { /* find beg of word */
while( inword( *w )) ++w;

if( ! *w ) break;

wp[ wpcnt++ ] = w; /* ptr to value */

iwparen = 0; /* find end of word */
while( *w && ! inword( *w )) ++w;
if( ! *w ) break;
*w++ = '\0'; /* terminate it */

if( wpcnt == 16 ) {
error( 'l', w ); /* too long */
break;
}
}

if(( wpcnt % 2 ) == 0 ) {
error( 'v', w ); /* must be odd */
--wpcnt;
}

v = value( wp[ 0 ] );

for( i = 1; i < wpcnt; i += 2 ) {
if( strcmp( wp[ i ], "+" ) == 0 ) {
v += value( wp[ i + 1 ] );
goto opdone;
}
if( strcmp( wp[ i ], "-" ) == 0 ) {
v -= value( wp[ i + 1 ] );
goto opdone;
}
if( strcmp( wp[ i ], "*" ) == 0 ) {
v *= value( wp[ i + 1 ] );
goto opdone;
}
if( strcmp( wp[ i ], "/" ) == 0 ) {
v /= value( wp[ i + 1 ] );
goto opdone;
}
error( 'o', wp[ i ] ); /* unknown op */
opdone:
i = i; /* get around c/80 bug */
}

} else { /* --- PLAIN VALUE --- */

i = lookup( w ); /* look up symbol */
if( i < 0 ) return 0; /* unknown symbol */
v = symbol[ i ].sval; /* return sym value */
}
}

if( negate ) v = 0 - v;

return v;
}

/* function for value() */

int inword( c )
char c;
{
if( c == '(' ) ++iwparen; /* special var for this */
if( c == ')' ) --iwparen; /* function */

if( iwparen ) return 0;

if( c == ' ' ) return 1; /* is space */

return 0;
}

/* --- SYMBOL TABLE LOGIC --- */

/* add new symbol to symbol table */

addsymbol( p, v )
char *p;
long int v;
{
char *w, *cpystr(), *alloc();
int i, lookup();

i = lookup( p ); /* see if already known */

if( i < 0 ) { /* new symbol */
i = symcnt;
++symcnt; /* count a new symbol */

symbol[ i ].snam = alloc( strlen( p ) + 1 );
w = cpystr( p, symbol[ i ].snam );
}

symbol[ i ].sval = v; /* update value in table */
}

/* lookup - returns symbol number or -1 if not found */

int lookup( p )
char *p;
{
char *w;
int i, j, k, found;

found = 0; /* not found yet */

/* pass 1 - use linear search */

if( pass == 1 ) {
for( i = 0; i < symcnt && ! found; ++i ) {
w = symbol[ i ].snam;
found = ( strcmp( p, w ) == 0 );
}
} else {

/* passes 2 and 3 - use binary search */

j = ( symcnt + 1 ) / 4; /* step to use */
i = symcnt / 2; /* starting point */
k = j + 1; /* one-step count */

while( 1 ) {
w = symbol[ i ].snam;
found = strcmp( p, w );
if( found == 0 ) {
found = 1;
break;
} else if( found < 0 ) i -= j;
else i += j;

if( i < 0 ) i = 0;
if( i >= symcnt ) i = symcnt - 1;

j /= 2; /* halve step */

if( j == 0 ) {
if( k-- == 0 ) {
found = 0; /* not found */
break;
}
j = 1;
}
}
}

if( ! found ) {
if( pass != 1 ) error( 'u', w );
return -1;
}

return i;
}

/* display error code */

error( c, p )
char c;
char *p;
{
puts( "\n>>---> Error " );
putchar( c );
puts( " at " );
puts( p );

++errors;
}

/* sort symbols by shell sort */

sortsyms()
{
int jump, done, k, l;
char *n;
long int v;

jump = symcnt; /* set jmp to cnt of elements */

while( jump > 0 ) {
jump = jump / 2;

while( 1 ) {
done = 1;
for( k = 0; k < ( symcnt - jump ); ++k ) {
l = k + jump;
if( strcmp( symbol[ k ].snam,
symbol[ l ].snam ) > 0 ) {
n = symbol[ k ].snam;
v = symbol[ k ].sval;
symbol[ k ].snam = symbol[ l ].snam;
symbol[ k ].sval = symbol[ l ].sval;
symbol[ l ].snam = n;
symbol[ l ].sval = v;
done = 0;
}
}
if( done ) break;
}
}
}

/* dump symbol table */

dumpsyms()
{
char *w;
int i;
long int v;

puts( "\nSymbol and Value\n" );

for( i = 0; i < symcnt; ++i ) {
puts( symbol[ i ].snam );
puts( " = " );
v = symbol[ i ].sval;
puthex( v >> 24, 0 );
puthex(( v >> 16 ) & 0xFF, 0 );
puthex(( v >> 8 ) & 0xFF, 0 );
puthex( v & 0xFF, 0 ); /* print value */
putchar( '\n' );
}
}

/* Match string. If match, returns 1; else returns 0.
Ambiguous values from the matches are saved and
pointed to by the array of char pointers ambig[], so
they can be checked later. */

int match( w1, w2 )
char *w1, *w2;
{
char c;
char *next_ambig;

next_ambig = &ambig_buffer[ 0 ]; /* init ambig buff */
ambcnt = 0; /* ambigs so far */

while( *w1 ) {
c = *w2++;
if( c == '*' ) {
ambig[ ambcnt++ ] = next_ambig;
while( *w1 && *w1 != *w2 )
*next_ambig++ = *w1++;
if( ! *w1 && *w2 ) return 0;
*next_ambig++ = '\0'; /* terminate this ambig */
} else if( c == '?' ) {
ambig[ ambcnt++ ] = next_ambig;
*next_ambig++ = *w1++; /* 1-char ambig */
*next_ambig++ = '\0'; /* terminate it */
} else if( c != *w1++ ) return 0;
}
return 1;
}

int gword()
{
char *p, *q;
char c, gchar();

p = &word_buffer[ 0 ];

c = ' ';

while( isdelim( c )) c = gchar();

while( ! isdelim( c )) {
*p++ = tolower( c );
c = gchar();
}

*p = '\0'; /* terminate word */

word = &word_buffer[ 0 ];

return 1;
}

/* is the character a delimeter? */

isdelim( c )
char c;
{
if( paren || quote || brack )
return 0; /* not a delim */

if( c == ' ' || c == ',' || c == ';' || c == '\n' \
|| c == '\r' || c == '\t' )
return 1;
return 0;
}

/* get next char from source file */

char gchar()
{
char c, getch();

c = getch(); /* get char from file */

if( c == '\'' ) quote = ! quote;
if( c == '"' ) quote = ! quote;
if( c == '(' ) ++paren;
if( c == ')' ) --paren;
if( c == '[' ) ++brack;
if( c == ']' ) --brack;

if( ! quote && ! paren && ! brack ) {

while( c == ';' ) { /* ;comment\n */
while( getch() != '\n' ) ;
c = getch();
}
}

return c;
}

puts( p )
char *p;
{
while( *p ) putchar( *p++ );
}

/* --- source file routines --- */

char getch()
{
while( inpcnt == 0 ) { /* if input buf empty, */
listpr(); /* print listing line */
inpload(); /* reload input buffer */
}

--inpcnt;
return( inpbuf[ inpptr++ ] );
}

inpload()
{
char c, getc();

inpcnt = 0;
inpptr = 0;

while((( c = getc( fasm )) != '\n' ) && ( c != EOF )) {
inpbuf[ inpcnt++ ] = c;
if( listcp < 81 ) listline[ listcp++ ] = c;
}

inpbuf[ inpcnt++ ] = '\n';
}

/* --- listing file routines --- */

listnl() /* list new line */
{
int i;

if( pass != 3 ) return;

for( i = 0; i < 26; ++i ) listline[ i ] = ' ';
for( i = 26; i < 81; ++i ) listline[ i ] = '\0';

listop = 0; /* flag to cause addr output */
listcp = 26;
}

lbyt( b ) /* put object byte in list file */
unsigned int b;
{
char c;

if( pass != 3 ) return;

c = (( b / 16 ) % 16 ) + '0';
if( c > '9' ) c += ( 'a' - ':' );
listline[ listop++ ] = c;

c = ( b % 16 ) + '0';
if( c > '9' ) c += ( 'a' - ':' );
listline[ listop++ ] = c;

if( listop > 24 ) listpr(); /* print list line */
}

listpr() /* print list line */
{
if( pass != 3 ) return;

putchar( '\n' );
puts( listline );
listnl();
}

/* --- object file routines --- */

objout( c )
char c;
{
asmadr++; /* incr asmadr, codadr. DON'T incr*/
codadr++; /* objadr, it is addr of 1st byte */
if( pass != 3 ) return; /* skip if not last pass */
objbuf[ objcnt++ ] = c; /* put new byte in buffer */
if( objcnt == 32 ) objflush();

if( listop == 0 ) { /* print address? */
lbyt( asmadr / 16777216 );
lbyt(( asmadr / 65536 ) % 256 );
lbyt(( asmadr / 256 ) % 256 );
lbyt( asmadr % 256 );
listop = 9;
}
lbyt( c ); /* send byte to listing too */
}

objflush()
{
int i, cksum;

if( pass != 3 ) return; /* just in case we get here */

cksum = 0;

if( objcnt > 0 ) {
putc( ':', fobj );
puthex( objcnt, fobj );
puthex( objadr / 256, fobj );
puthex( objadr % 256, fobj );
puthex( 0, fobj );
cksum =
objcnt + ( objadr / 256 ) + ( objadr % 256 );
for( i = 0; i < objcnt; ++i ) {
puthex( objbuf[ i ], fobj );
cksum += objbuf[ i ];
}
puthex( 0 - cksum, fobj );
putc( '\n', fobj );
}

objadr = asmadr;
objcnt = 0;}

puthex( b, c )
int b, c;
{
int v;

v = ( b & 0x00F0 ) >> 4;
if( v > 9 ) v += 'A' - 10; else v += '0';
putc( v, c );
v = ( b & 0x000F );
if( v > 9 ) v += 'A' - 10; else v += '0';
putc( v, c );
}

long int hexbin( p )
char *p;
{
long int v;

v = 0;

while( *p ) {
if( isdigit( *p )) v = ( 16 * v ) + *p++ - '0';
else if( *p >= 'a' && *p <= 'f' )
v = ( 16 * v ) + *p++ - 'a' + 10;
else ++p;
}

return v;
}

long int octbin( p )
char *p;
{
long int v;

v = 0;

while( *p ) {
if( *p >= '0' && *p <= '7' )
v = ( 8 * v ) + *p++ - '0';
else ++p;
}
return v;
}

long int bitbin( p )
char *p;
{
long int v;

v = 0;

while( *p ) {
if( *p == '0' || *p == '1' )
v = ( 2 * v ) + *p++ - '0';
else ++p;
}
return v;
}

long int decbin( p )
char *p;
{
long int v;

v = 0;

while( *p ) {
if( isdigit( *p )) v = ( 10 * v ) + *p++ - '0';
else ++p;
}
return v;
}

#include "stdlib.c"



  3 Responses to “Category : Files from Magazines
Archive   : DDJ8612.ZIP
Filename : RODMAN.DEC

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/