v10i060: An 8031/8051 Assembler

Kenneth Stauffer stauffer at cpsc.ucalgary.ca
Wed Feb 14 12:57:59 AEST 1990


Posting-number: Volume 10, Issue 60
Submitted-by: stauffer at cpsc.ucalgary.ca (Kenneth Stauffer)
Archive-name: asm.8051

This is an 8031/8051 Assembler, which generates
many different output formats including S-records.

Ken Stauffer.

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README as31.h as31.y as31.man emitter.c lexer.c main.c
#   makefile symbol.c new.asm
# Wrapped by stauffer at cpsc.UCalgary.CA on Tue Jan 30 18:35:17 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1528 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
X
X	as31 - An 8031/8051 assembler.
X
X		Written by:
X	K e n    S t a u f f e r
X
X
Xas31, is an 8031/8051 assembler. The program consists of the
Xfollowing files:
X
X	makefile	- Makefile.
X	as31.h		- Package header file.
X	as31.y		- Parser / code generator.
X	lexer.c		- Scanner.
X	symbol.c	- Symbol table / opcode table.
X	emitter.c	- Object code generation routines.
X	main.c		- Command line / calls yyparse().
X
X	as31.man	- Assembler manual.
X
X	new.asm		- Sample 8031 code. This is a working
X			  debugger written by Theo Deraadt.
X
XOVERVIEW OF AS31:
X	as31 is a full featured assembler but it does lack
X	facilities for linking several modules together.
X	as31 can be configured to produced a wide variety of
X	object output formats.
X	One of the supported output formats is S-records.
X		(Written by: Theo Deraadt)
X
X	Standard assembler syntax is accepted.
X
XMAKING AS31:
X	On most unix systems, running make should be sufficient
X	to produce a working assembler.
X
X	Also typing:
X
X		% make man
X
X	Will produces a text file from as31.man (called as31.cat).
X	This is the users manual.
X
X	This package does work on the following systems:
X		SUN 3 / SUN 4 (SunOS 4.0), Tandy 6000 (Xenix)
X
X	Non-unix systems may require some porting for the FILE I/O
X	stuff but most reasonable implementations of stdio.h
X	should work.
X
XSOURCE CODE:
X	This code is public domain.
X
XREPORTING BUGS:
X	If any bugs are detected in this program, I would
X	like to know about them so that I could fix them. I can
X	be reached via E-mail at:
X
X		stauffer at cpsc.ucalgary.ca
X
XJanuary 26, 1990
X
END_OF_FILE
if test 1528 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'as31.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'as31.h'\"
else
echo shar: Extracting \"'as31.h'\" \(3549 characters\)
sed "s/^X//" >'as31.h' <<'END_OF_FILE'
X/* ----------------------------------------------------------------------
X * FILE: as31.h
X * PACKAGE: as31 - 8031/8051 Assembler.
X *
X * DESCRIPTION:
X *	The sole header file for the 8031/8051 assembler package.
X *	It defines several structures used by the yacc stack.
X *	It defines several macros for testing the bitsize of numeric
X *	quantities.
X *
X *	Some macros to extract information from the mode structure.
X *
X * REVISION HISTORY:
X *	Jan. 19, 1990 - Created. (Ken Stauffer)
X *
X * AUTHOR:
X *	All code in this file written by Ken Stauffer (University of Calgary).
X *	January, 1990.
X *
X */
X
X/* ----------------------------------------------------------------------
X * user / keyword symbol structures:
X */
X
Xstruct opcode {
X	char *name;
X	int type;
X	unsigned char *bytes;
X};
X
Xstruct symbol {
X	char *name;
X	int type;
X	long value;
X	struct symbol *next;
X};
X
X#define UNDEF	0
X#define LABEL	1
X
X/* ----------------------------------------------------------------------
X * addressing mode stuff:
X */
X
Xstruct mode {
X	unsigned char mode;		/* value to index with */
X	unsigned char size;		/* # of bytes used */
X	unsigned char orval;		/* value OR'd to obcode */
X	unsigned char byte1;		/* extra byte 1 */
X	unsigned char byte2;		/* extra byte 2 */
X};
X
X#define set_md(m,a)	((m).mode=(a))
X#define set_sz(m,a)	((m).size=(a))
X#define set_ov(m,a)	((m).orval=(a))
X#define set_b1(m,a)	((m).byte1=(a))
X#define set_b2(m,a)	((m).byte2=(a))
X
X#define get_md(m)	((m).mode)
X#define get_sz(m)	((m).size)
X#define get_ov(m)	((m).orval)
X#define get_b1(m)	((m).byte1)
X#define get_b2(m)	((m).byte2)
X
X/* ----------------------------------------------------------------------
X * yacc stack stuff:
X */
X
Xstruct value {
X	long v;
X	unsigned char d;		/* expression defined flag */
X};
X
Xunion ystack {
X	long value;
X	struct value val;
X	struct opcode *op;
X	struct symbol *sym;
X	struct mode mode;
X	char *str;
X};
X
X/* ----------------------------------------------------------------------
X * IS_BIT_MAPPED_RAM:
X *	True is the byte 'a' is the byte address of a bit mapped
X *	RAM location.
X */
X#define isbmram(a)	(((a)&0xf0)==0x20)
X
X/* ----------------------------------------------------------------------
X * IS_BIT_MAPPED_SFR:
X *	True is the byte 'a' is the byte address of a bit mapped
X *	SPECIAL FUCTION REGISTER.
X */
X#define isbmsfr(a)	(((a)&0x80) && !((a) & 0x07))
X
X/* ----------------------------------------------------------------------
X * isbit8, ...
X *	Macros to check the sizes of values and to convert
X *	a value to a certain, size.
X *
X */
X#define size8		(~0x00ff)
X#define size11		(~0x07ff)
X#define size13		(~0x1fff)
X#define size16		(~0xffff)
X
X#define size10		(~0x03ff)
X#define size12		(~0x0fff)
X#define size15		(~0x7fff)
X
X#define isbit8(v)	( !( ((v)>=0) ? (v)&size8 : -(v)>=128) )
X#define isbit11(v)	( !( ((v)>=0) ? (v)&size11 : (-(v))&size10 ) )
X#define isbit13(v)	( !( ((v)>=0) ? (v)&size13 : (-(v))&size12 ) )
X#define isbit16(v)	( !( ((v)>=0) ? (v)&size16 : (-(v))&size15 ) )
X
X/* ----------------------------------------------------------------------
X * Size of user hash table.
X */
X#define HASHTABSIZE		1000
X
X/* ----------------------------------------------------------------------
X * Macros to nicely test which pass we are in.
X */
X#define pass1			(!pass)
X#define pass2			(pass)
X
X/* -------- TOKENS ------------------------------------------------------
X *
X * This includes the header file generated by yacc -d.
X * NOPE is defined inside of as31.y, which does not
X * need to re-include the tokens twice, thus NOPE prevents this.
X *
X */
X#ifdef NOPE
X#else
X#include "y.tab.h"
X#endif
X
END_OF_FILE
if test 3549 -ne `wc -c <'as31.h'`; then
    echo shar: \"'as31.h'\" unpacked with wrong size!
fi
# end of 'as31.h'
fi
if test -f 'as31.y' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'as31.y'\"
else
echo shar: Extracting \"'as31.y'\" \(22290 characters\)
sed "s/^X//" >'as31.y' <<'END_OF_FILE'
X/* ----------------------------------------------------------------------
X * FILE: as31.y
X * PACKAGE: as31 - 8031/8051 Assembler.
X *
X * DESCRIPTION:
X *	This file contains the yacc parser for the assembler.
X *	Related to this are the following:
X *		error(), warning(), yyerror()
X *		genbyte(), genword(), genstr(), makeop()
X *
X *
X * REVISION HISTORY:
X *	Jan. 19, 1990 - Created. (Ken Stauffer)
X *
X * AUTHOR:
X *	All code in this file written by Ken Stauffer (University of Calgary).
X *	January 1990.
X *
X */
X
X%{
X
X#include <setjmp.h>
X#include <stdio.h>
X#define NOPE
X#include "as31.h"
X#undef NOPE
X
X#define YYSTYPE union ystack
X
Xextern int lineno;
Xextern int dashl;
Xextern char *asmfile;
Xextern jmp_buf main_env;
Xextern FILE *listing;
X
Xint pass,fatal;
Xunsigned long lc;
X
Xstatic unsigned char bytebuf[1024];		/* used by dumplist() */
Xstatic int bytecount;
X
X/* ------------------------ G R A M M E R ----------------------------- */
X
X%}
X
X%token STRING
X%token D_ORG
X%token D_BYTE
X%token D_WORD
X%token D_SKIP
X%token D_EQU
X%token D_FLAG
X%token D_END
X%token ACALL
X%token ADD
X%token ADDC
X%token AJMP
X%token ANL
X%token CJNE
X%token CLR
X%token CPL
X%token DA
X%token DEC
X%token DIV
X%token DJNZ
X%token INC
X%token JB
X%token JBC
X%token JC
X%token JMP
X%token JNB
X%token JNC
X%token JNZ
X%token JZ
X%token LCALL
X%token LJMP
X%token MOV
X%token MOVC
X%token MOVX
X%token NOP
X%token MUL
X%token ORL
X%token POP
X%token PUSH
X%token RET
X%token RETI
X%token RL
X%token RLC
X%token RR
X%token RRC
X%token SETB
X%token SJMP
X%token SUBB
X%token SWAP
X%token XCH
X%token XCHD
X%token XRL
X%token AB
X%token A
X%token C
X%token PC
X%token DPTR
X%token BITPOS
X%token R0
X%token R1
X%token R2
X%token R3
X%token R4
X%token R5
X%token R6
X%token R7
X%token VALUE
X%token SYMBOL
X
X%left '+' '-'
X%left '*' '/' '%'
X%left '|' '&'
X
X%start program
X
X%%
Xprogram		:	linelist
X{
X}
X		;
X
Xlinelist	: linelist line
X		| line
X		;
X
Xline		: undefsym ':' linerest
X{
X	if( pass1 ) {
X		$1.sym->type = LABEL;
X		$1.sym->value = lc;
X	}
X	inclc($3.value);
X	bytecount = 0;
X}
X		| linerest		{ inclc($1.value); bytecount = 0; }
X		;
X
Xlinerest	: directive '\n'	{
X						$$.value = $1.value;
X						if( dashl && pass2 )
X							dumplist($2.str,1);
X					}
X		| instr '\n'		{
X						$$.value = $1.value;
X						if( dashl && pass2 )
X							dumplist($2.str,1);
X
X					}
X		| '\n'			{
X						$$.value = 0;
X						if( dashl && pass2 )
X							dumplist($1.str,0);
X					}
X		;
X
X
X
X
X
X/* --------------------
X * DIRECTIVES:
X *
X */
X
Xdirective	: '.' D_ORG defexpr
X{
X	lc = $3.val.v;
X	if( pass2 ) emitaddr(lc);
X	bytecount = 0;
X	$$.value = 0;
X}
X		| '.' D_BYTE blist	{ $$.value = $3.value; }
X		| '.' D_WORD wlist	{ $$.value = $3.value; }
X		| '.' D_SKIP defexpr	{ $$.value = $3.val.v;
X					  if( pass2 )
X						emitaddr(lc+$$.value); }
X		| '.' D_EQU undefsym ',' expr
X{
X	if( $5.val.d == 0 )
X		error("Expression is undefined in pass 1");
X	$3.sym->type = LABEL;
X	$3.sym->value = $5.val.v;
X	$$.value = 0;
X}
X	
X		| '.' D_FLAG SYMBOL ',' flag
X{
X	$3.sym->type = LABEL;
X	$3.sym->value = $5.value;
X	$$.value = 0;
X}
X		| '.' D_END			{ $$.value = 0; }
X		;
X
Xdefexpr		: expr
X{
X		if( $1.val.d == 0 )
X			error("Expression is undefined in pass 1");
X		if( !(isbit16($1.val.v)) )
X			error("Value greater than 16-bits");
X		$$.value = $1.val.v;
X}
X		;
X
Xflag		: flagv BITPOS
X{
X	if( !isbit8($1.value) )
X		warning("Bit address exceeds 8-bits");
X	if( isbmram($1.value) )
X		$$.value = ($1.value-0x20)*8+ $2.value;
X	else if( isbmsfr($1.value) )
X		$$.value = $1.value + $2.value;
X	else
X		warning("Invalid bit addressable RAM location");
X}
X		;
X
Xflagv		: SYMBOL
X{
X	if( $1.sym->type == UNDEF )
X		error("Symbol %s must be defined in pass 1",$1.sym->name);
X	$$.value = $1.sym->value;
X}
X		| VALUE			{ $$.value = $1.value; }
X		;
X
X
Xundefsym	: SYMBOL
X{
X	if( $1.sym->type != UNDEF && pass1)
X		error("Attempt to redefine symbol: %s",$1.sym->name);
X	$$.sym = $1.sym;
X}
X		;
X
Xblist		: blist ',' data8
X{
X	if( pass2 ) genbyte($3.value);
X	$$.value = $1.value + 1;
X}
X		| blist ',' STRING
X{
X	if( pass1 )
X		$$.value = $1.value + $3.value;
X	else {
X		$$.value = $1.value + strlen($3.str);
X		genstr($3.str);
X		
X		free($3.str);
X	}
X}
X		| data8
X{
X	if( pass2 ) genbyte($1.value);
X	$$.value = 1;
X}
X		| STRING
X{
X	if( pass1 )
X		$$.value = $1.value;
X	else {
X		$$.value = strlen($1.str);
X		genstr($1.str);
X		free($1.str);
X	}
X}
X		;
X
Xwlist		: wlist ',' data16
X{
X	if( pass2 ) genword($3.value);
X	$$.value = $1.value + 2;
X}
X		| data16
X{
X	if( pass2 ) genword($1.value);
X	$$.value = 2;
X}
X		;
X
X
X
X/* --------------------
X * EXPRESSIONS:
X *
X */
X
Xexpr		: '*'			{ $$.val.v = lc;
X					  $$.val.d = 1; }
X
X		| '(' expr ')'		{ $$.val.v = $2.val.v;
X					  $$.val.d = $2.val.d; }
X
X		| '-' expr %prec '*'	{ $$.val.v = -$2.val.v;
X					  $$.val.d = $2.val.d;  }
X
X		| expr '|' expr		{ $$.val.v = $1.val.v | $3.val.v;
X					  $$.val.d = $1.val.d && $3.val.d; }
X
X		| expr '&' expr		{ $$.val.v = $1.val.v & $3.val.v;
X					  $$.val.d = $1.val.d && $3.val.d; }
X
X		| expr '*' expr		{ $$.val.v = $1.val.v * $3.val.v;
X					  $$.val.d = $1.val.d && $3.val.d; }
X
X		| expr '/' expr		{ $$.val.v = $1.val.v / $3.val.v;
X					  $$.val.d = $1.val.d && $3.val.d; }
X
X		| expr '%' expr		{ $$.val.v = $1.val.v % $3.val.v;
X					  $$.val.d = $1.val.d && $3.val.d; }
X
X		| expr '-' expr		{ $$.val.v = $1.val.v - $3.val.v;
X					  $$.val.d = $1.val.d && $3.val.d; }
X
X		| expr '+' expr		{ $$.val.v = $1.val.v + $3.val.v;
X					  $$.val.d = $1.val.d && $3.val.d; }
X		| SYMBOL
X{
X	if( pass1 ) {
X		$$.val.v = $1.sym->value;
X		$$.val.d = ($1.sym->type != UNDEF);
X	}
X	else {
X		if( $1.sym->type == UNDEF )
X			error("Undefined symbol %s",$1.sym->name);
X		$$.val.v = $1.sym->value;
X		$$.val.d = 1;
X	}
X}
X		| VALUE		{ $$.val.v = $1.val.v; $$.val.d=1; }
X		;
X
X
X
X
X
X/* --------------------
X * INSTRUCTIONS:
X *
X */
X
Xinstr		: NOP
X				{ $$.value = makeop($1.op,NULL,0); }
X		| ACALL addr11
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| AJMP addr11
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| ADD two_op1
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| ADDC two_op1
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| SUBB two_op1
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| XRL two_op1
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| XRL two_op2
X				{ $$.value = makeop($1.op,&$2.mode,4); }
X		| ANL two_op1
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| ANL two_op2
X				{ $$.value = makeop($1.op,&$2.mode,4); }
X		| ANL two_op3
X				{ $$.value = makeop($1.op,&$2.mode,6); }
X		| ORL two_op1
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| ORL two_op2
X				{ $$.value = makeop($1.op,&$2.mode,4); }
X		| ORL two_op3
X				{ $$.value = makeop($1.op,&$2.mode,6); }
X		| XCH two_op1
X				{ if( get_md($2.mode) == 3 )
X					error("Immediate mode is illegal");
X				  $$.value = makeop($1.op,&$2.mode,0);
X				}
X		| INC single_op1
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| INC DPTR
X				{ $$.value = makeop($1.op,NULL,4); }
X		| DEC single_op1
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| DA A
X				{ $$.value = makeop($1.op,NULL,0); }
X		| DIV AB
X				{ $$.value = makeop($1.op,NULL,0); }
X		| JMP '@' A '+' DPTR
X				{ $$.value = makeop($1.op,NULL,0); }
X		| JMP '@' DPTR '+' A
X				{ $$.value = makeop($1.op,NULL,0); }
X		| MUL AB
X				{ $$.value = makeop($1.op,NULL,0); }
X		| RET
X				{ $$.value = makeop($1.op,NULL,0); }
X		| RETI
X				{ $$.value = makeop($1.op,NULL,0); }
X		| RL A
X				{ $$.value = makeop($1.op,NULL,0); }
X		| RLC A
X				{ $$.value = makeop($1.op,NULL,0); }
X		| RR A
X				{ $$.value = makeop($1.op,NULL,0); }
X		| RRC A
X				{ $$.value = makeop($1.op,NULL,0); }
X		| SWAP A
X				{ $$.value = makeop($1.op,NULL,0); }
X		| XCHD two_op1
X				{ if( get_md($2.mode) != 2 )
X					error("Invalid addressing mode");
X				  $$.value = makeop($1.op,&$2.mode,-2); }
X		| CLR single_op2
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| CPL single_op2
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| SETB single_op2
X				{ if( get_md($2.mode) == 0 )
X					error("Invalid addressing mode");
X				  $$.value = makeop($1.op,&$2.mode,-1); }
X		| PUSH data8
X				{
X				   struct mode tmp;
X					set_md(tmp,0);
X					set_ov(tmp,0);
X					set_sz(tmp,1);
X					set_b1(tmp,$2.value);
X					$$.value = makeop($1.op,&tmp,0);
X				}
X		| POP data8
X				{
X				   struct mode tmp;
X					set_md(tmp,0);
X					set_ov(tmp,0);
X					set_sz(tmp,1);
X					set_b1(tmp,$2.value);
X					$$.value = makeop($1.op,&tmp,0);
X				}
X		| LJMP addr16
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| LCALL addr16
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| JC relative
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| JNC relative
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| JNZ relative
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| JZ relative
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| SJMP relative
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| CJNE three_op1
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| JB two_op4
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| JNB two_op4
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| JBC two_op4
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| DJNZ two_op5
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| MOV two_op1
X				{ $$.value = makeop($1.op,&$2.mode,0); }
X		| MOV two_op2
X				{ $$.value = makeop($1.op,&$2.mode,4); }
X		| MOV two_op6
X				{ $$.value = makeop($1.op,&$2.mode,6); }
X
X
X		| MOVC A ',' '@' A '+' DPTR
X				{ $$.value = makeop($1.op,NULL,0); }
X		| MOVC A ',' '@' DPTR '+' A
X				{ $$.value = makeop($1.op,NULL,0); }
X		| MOVC A ',' '@' A '+' PC
X				{ $$.value = makeop($1.op,NULL,1); }
X		| MOVC A ',' '@' PC '+' A
X				{ $$.value = makeop($1.op,NULL,1); }
X
X		| MOVX A ',' '@' regi
X				{ $$.value = makeop($1.op,NULL,$5.value); }
X		| MOVX A ',' '@' DPTR
X				{ $$.value = makeop($1.op,NULL,2); }
X		| MOVX '@' regi ',' A
X				{ $$.value = makeop($1.op,NULL,$3.value+3); }
X		| MOVX '@' DPTR ',' A
X				{ $$.value = makeop($1.op,NULL,5); }
X		;
X
X
X
X
X/* --------------------
X * ADDRESSING MODES:
X *
X */
X
Xtwo_op1		: A ',' reg
X				{
X					set_md($$.mode,0);
X					set_ov($$.mode, $3.value);
X					set_sz($$.mode, 0);
X				}
X		| A ',' data8
X				{
X					set_md($$.mode,1);
X					set_ov($$.mode,0);
X					set_sz($$.mode,1);
X					set_b1($$.mode,$3.value);
X				}
X		| A ',' '@' regi
X				{
X					set_md($$.mode,2);
X					set_ov($$.mode,$4.value);
X					set_sz($$.mode,0);
X				}
X		| A ',' '#' data8
X				{
X					set_md($$.mode,3);
X					set_ov($$.mode,0);
X					set_sz($$.mode,1);
X					set_b1($$.mode,$4.value);
X				}
X		;
X
Xtwo_op2		: data8 ',' A
X				{
X					set_md($$.mode,0);
X					set_ov($$.mode,0);
X					set_sz($$.mode,1);
X					set_b1($$.mode,$1.value);
X				}
X		| data8 ',' '#' data8
X				{
X					set_md($$.mode,1);
X					set_ov($$.mode,0);
X					set_sz($$.mode,2);
X					set_b1($$.mode,$1.value);
X					set_b2($$.mode,$4.value);
X				}
X		;
X
Xtwo_op3		: C ',' bit
X				{
X					set_md($$.mode,0);
X					set_ov($$.mode,0);
X					set_sz($$.mode,1);
X					set_b1($$.mode,$3.value);
X				}
X		| C ',' '/' bit
X				{
X					set_md($$.mode,1);
X					set_ov($$.mode,0);
X					set_sz($$.mode,1);
X					set_b1($$.mode,$4.value);
X				}
X		| C ',' '!' bit
X				{
X					set_md($$.mode,1);
X					set_ov($$.mode,0);
X					set_sz($$.mode,1);
X					set_b1($$.mode,$4.value);
X				}
X		;
X
Xtwo_op4		: bit ',' rel
X				{
X					set_md($$.mode,0);
X					set_ov($$.mode,0);
X					set_sz($$.mode,2);
X					set_b1($$.mode,$1.value);
X					set_b2($$.mode,$3.value);
X				}
X		;
X
Xtwo_op5		: reg ',' rel2
X				{
X					set_md($$.mode,0);
X					set_ov($$.mode,$1.value);
X					set_sz($$.mode,1);
X					set_b1($$.mode,$3.value);
X				}
X		| data8 ',' rel
X				{
X					set_md($$.mode,1);
X					set_ov($$.mode,0);
X					set_sz($$.mode,2);
X					set_b1($$.mode,$1.value);
X					set_b2($$.mode,$3.value);
X				}
X		;
X
Xtwo_op6		: reg ',' A
X				{
X					set_md($$.mode,0);
X					set_ov($$.mode,$1.value);
X					set_sz($$.mode,0);
X				}
X		| reg ',' data8
X				{
X					set_md($$.mode,1);
X					set_ov($$.mode,$1.value);
X					set_sz($$.mode,1);
X					set_b1($$.mode,$3.value);
X				}
X		| reg ',' '#' data8
X				{
X					set_md($$.mode,2);
X					set_ov($$.mode,$1.value);
X					set_sz($$.mode,1);
X					set_b1($$.mode,$4.value);
X				}
X		| data8 ',' reg
X				{
X					set_md($$.mode,3);
X					set_ov($$.mode,$3.value);
X					set_sz($$.mode,1);
X					set_b1($$.mode,$1.value);
X				}
X		| data8 ',' data8
X				{
X					set_md($$.mode,4);
X					set_ov($$.mode,0);
X					set_sz($$.mode,2);
X					set_b1($$.mode,$3.value);
X					set_b2($$.mode,$1.value);
X				}
X		| data8 ',' '@' regi
X				{
X					set_md($$.mode,5);
X					set_ov($$.mode,$4.value);
X					set_sz($$.mode,1);
X					set_b1($$.mode,$1.value);
X				}
X		| '@' regi ',' A
X				{
X					set_md($$.mode,6);
X					set_ov($$.mode,$2.value);
X					set_sz($$.mode,0);
X				}
X		| '@' regi ',' data8
X				{
X					set_md($$.mode,7);
X					set_ov($$.mode,$2.value);
X					set_sz($$.mode,1);
X					set_b1($$.mode,$4.value);
X				}
X		| '@' regi ',' '#' data8
X				{
X					set_md($$.mode,8);
X					set_ov($$.mode,$2.value);
X					set_sz($$.mode,1);
X					set_b1($$.mode,$5.value);
X				}
X		| DPTR ',' '#' data16
X			{
X				set_md($$.mode,9);
X				set_ov($$.mode,0);
X				set_sz($$.mode,2);
X				set_b1($$.mode, ($4.value & 0xff00) >> 8 );
X				set_b2($$.mode, ($4.value & 0x00ff) );
X			}
X		| C ',' bit
X				{
X					set_md($$.mode,10);
X					set_ov($$.mode,0);
X					set_sz($$.mode,1);
X					set_b1($$.mode,$3.value);
X				}
X	/*
X	 * Following two productions cannot be represented by:
X	 *
X	 *	bit ',' C
X	 *
X	 * Because yacc gives tons of reduce/reduce errors if
X 	 * that is attempted.
X	 *
X	 */
X		| data8 ',' C
X				{
X					set_md($$.mode,11);
X					set_ov($$.mode,0);
X					set_sz($$.mode,1);
X					set_b1($$.mode,$1.value);
X				}
X		| data8 BITPOS ',' C
X{
X	if( pass2 ) {
X		if( !isbit8($1.value) )
X			warning("Bit address exceeds 8-bits");
X		if( isbmram($1.value) )
X			set_b1($$.mode, ($1.value-0x20)*8+ $2.value );
X		else if( isbmsfr($1.value) )
X			set_b1($$.mode, $1.value + $2.value );
X		else
X			warning("Invalid bit addressable RAM location");
X	}
X	set_md($$.mode,11);
X	set_ov($$.mode,0);
X	set_sz($$.mode,1);
X}
X		;
X
X
Xsingle_op1	: A
X				{
X					set_md($$.mode,0);
X					set_ov($$.mode,0);
X					set_sz($$.mode,0);
X				}
X
X		| reg
X				{
X					set_md($$.mode,1);
X					set_ov($$.mode,$1.value);
X					set_sz($$.mode,0);
X				}
X		| data8
X				{
X					set_md($$.mode,2);
X					set_ov($$.mode,0);
X					set_sz($$.mode,1);
X					set_b1($$.mode,$1.value);
X				}
X		| '@' regi
X				{
X					set_md($$.mode,3);
X					set_ov($$.mode,$2.value);
X					set_sz($$.mode,0);
X				}
X		;
X
Xsingle_op2	: A
X				{
X					set_md($$.mode,0);
X					set_ov($$.mode,0);
X					set_sz($$.mode,0);
X				}
X		| C
X				{
X					set_md($$.mode,1);
X					set_ov($$.mode,0);
X					set_sz($$.mode,0);
X				}
X		| bit
X				{
X					set_md($$.mode,2);
X					set_ov($$.mode,0);
X					set_sz($$.mode,1);
X					set_b1($$.mode,$1.value);
X				}
X		;
X
Xthree_op1	: A ',' data8 ',' rel
X				{
X					set_md($$.mode,0);
X					set_ov($$.mode,0);
X					set_sz($$.mode,2);
X					set_b1($$.mode,$3.value);
X					set_b2($$.mode,$5.value);
X				}
X		| A ',' '#' data8 ',' rel
X				{
X					set_md($$.mode,1);
X					set_ov($$.mode,0);
X					set_sz($$.mode,2);
X					set_b1($$.mode,$4.value);
X					set_b2($$.mode,$6.value);
X				}
X		| reg ',' '#' data8 ',' rel
X				{
X					set_md($$.mode,2);
X					set_ov($$.mode,$1.value);
X					set_sz($$.mode,2);
X					set_b1($$.mode,$4.value);
X					set_b2($$.mode,$6.value);
X				}
X		| '@' regi ',' '#' data8 ',' rel
X				{
X					set_md($$.mode,3);
X					set_ov($$.mode,$2.value);
X					set_sz($$.mode,2);
X					set_b1($$.mode,$5.value);
X					set_b2($$.mode,$7.value);
X				}
X		;
X
Xrel		: expr
X{
X		long offset;
X		if( pass2 ) {
X			offset = $1.val.v - (lc+3);
X			if( offset > 127 || offset < -128 )
X			   warning("Relative offset exceeds -128 / +127");
X			$$.value = offset;
X		}
X}
X		;
X
X/*
X * This production differs from the above, by 1 number!
X *
X */
X
Xrel2		: expr
X{
X		long offset;
X		if( pass2 ) {
X			offset = $1.val.v - (lc+2); /* different! */
X			if( offset > 127 || offset < -128 )
X			   warning("Relative offset exceeds -128 / +127");
X			$$.value = offset;
X		}
X}
X		;
X
X
Xbit		: bitv BITPOS
X{
X	if( pass2 ) {
X		if( !isbit8($1.value) )
X			warning("Bit address exceeds 8-bits");
X		if( isbmram($1.value) )
X			$$.value = ($1.value-0x20)*8+$2.value;
X		else if( isbmsfr($1.value) )
X			$$.value = $1.value + $2.value;
X		else
X			warning("Invalid bit addressable RAM location");
X	}
X}
X		| bitv
X{
X	if( pass2 ) {
X		if( !isbit8($1.value) )
X			warning("Bit address exceeds 8-bits");
X		$$.value = $1.value;
X	}
X}
X		;
X
Xbitv		: SYMBOL
X{
X	if( $1.sym->type == UNDEF && pass2 )
X		error("Symbol %s undefined",$1.sym->name);
X	$$.value = $1.sym->value;
X}
X		| VALUE		{ $$.value = $1.value; }
X		;
X
Xreg		: R0		{ $$.value = 0; }
X		| R1		{ $$.value = 1; }
X		| R2		{ $$.value = 2; }
X		| R3		{ $$.value = 3; }
X		| R4		{ $$.value = 4; }
X		| R5		{ $$.value = 5; }
X		| R6		{ $$.value = 6; }
X		| R7		{ $$.value = 7; }
X		;
X
Xregi		: R0		{ $$.value = 0; }
X		| R1		{ $$.value = 1; }
X		| R2
X				{ $$.value = 0;
X				  warning("Illegal indirect register: @r2"); }
X		| R3
X				{ $$.value = 0;
X				  warning("Illegal indirect register: @r3"); }
X		| R4
X				{ $$.value = 0;
X				  warning("Illegal indirect register: @r4"); }
X		| R5
X				{ $$.value = 0;
X				  warning("Illegal indirect register: @r5"); }
X		| R6
X				{ $$.value = 0;
X				  warning("Illegal indirect register: @r6"); }
X		| R7
X				{ $$.value = 0;
X				  warning("Illegal indirect register: @r7"); }
X		;
X
Xdata8		: expr
X{
X	if( pass2 ) {
X		if( !isbit8($1.val.v) )
X			warning("Expression greater than 8-bits");
X	}
X	$$.value = $1.val.v;
X}
X		;
X
Xdata16		: expr
X{
X	if( pass2 ) {
X		if( !isbit16($1.val.v) )
X			warning("Expression greater than 16-bits");
X	}
X	$$.value = $1.val.v;
X}
X		;
X
Xaddr11		: expr
X{
X		if( pass2 ) {
X			if( !isbit16($1.val.v)  )
X				warning("Address greater than 16-bits");
X			if( ($1.val.v & size11) != ((lc+2) & size11) )
X				warning("Address outside current 2K page");
X		}
X		set_md($$.mode,0);
X		set_ov($$.mode, ($1.val.v&0x0700)>>3 );
X		set_sz($$.mode,1);
X		set_b1($$.mode,$1.val.v&0x00ff);
X}
X		;
X
Xaddr16		: expr
X{
X		if( pass2 ) {
X			if( !isbit16($1.val.v)  )
X				warning("Address greater than 16-bits");
X		}
X		set_md($$.mode,0);
X		set_ov($$.mode, 0 );
X		set_sz($$.mode,2);
X		set_b1($$.mode, ($1.val.v & 0xff00 ) >> 8 );
X		set_b2($$.mode, ($1.val.v & 0x00ff ) );
X}
X		;
X
Xrelative	: expr
X{
X		long offset;
X		if( pass2 ) {
X			offset = $1.val.v - (lc+2);
X			if( offset>127 || offset<-128 )
X			   warning("Relative offset exceeds -128 / +127");
X		}
X		set_md($$.mode,0);
X		set_ov($$.mode,0);
X		set_sz($$.mode,1);
X		set_b1($$.mode,offset);
X
X}
X		;
X
X%%
X
X/* ---------------------------------------------------------------------- */
X
Xyyerror(s)
Xchar *s;
X{
X	error(s);
X}
X
X
X/* ----------------------------------------------------------------------
X * error:
X *	Uses semi-variable arguments. This causes immediate assembler
X *	termination.
X */
X
Xerror(cs,a1,a2,a3,a4,a5,a6)
Xchar *cs,*a1,*a2,*a3,*a4,*a5,*a6;
X{
X	fprintf(stderr,"File: %s, line: %d, ",asmfile,lineno);
X	fprintf(stderr,cs,a1,a2,a3,a4,a5,a6);
X	fprintf(stderr,".\n");
X	longjmp(main_env,1);
X}
X
X/* ----------------------------------------------------------------------
X * warning:
X *	Produce error message. This will abort assembly at
X *	the end of the current pass.
X *
X */
X
Xwarning(cs,a1,a2,a3,a4,a5,a6)
Xchar *cs,*a1,*a2,*a3,*a4,*a5,*a6;
X{
X	fatal++;
X	fprintf(stderr,"File: %s, line: %d, ",asmfile,lineno);
X	fprintf(stderr,cs,a1,a2,a3,a4,a5,a6);
X	fprintf(stderr,".\n");
X}
X
X
X/* ----------------------------------------------------------------------
X * makeop:
X *	This function makes an opcode based on the instruction symbol table
X *	entry, and an addressing mode structure.
X *	This function is called from both passes, but
X *	only generates code in pass 2.
X *
X *	Resultant opcode bytes are passed to genbyte().
X *
X *	Returns the nuumber of bytes that the instruction
X *	occupies.
X *
X */
X
Xmakeop(op,m,add)
Xstruct opcode *op;
Xstruct mode *m;
X{
X	register unsigned int newop;
X
X	if( m == NULL ) {
X		if(pass2) genbyte(op->bytes[0+add]);
X		return(1);
X	}
X
X	if( pass2 ) {
X		newop = op->bytes[ get_md(*m)+add ] | get_ov(*m);
X		genbyte(newop);
X		if( get_sz(*m) > 0 ) genbyte( get_b1(*m) );
X		if( get_sz(*m) > 1 ) genbyte( get_b2(*m) );
X	}
X	return( get_sz(*m)+1 );
X}
X
X
X/* ----------------------------------------------------------------------
X * inclc:
X *	Increments the Location Counter by 'i' amount.
X *	Check to see if 'i' overflows 64K.
X *	Checks to see if assembler is overlapping previous sections
X *	of code. (using a large bit field).
X *
X */
X
X#define indx(a) ( (a)/(sizeof(long)*8) )
X#define bit(a)	( 1 << ((a)%(sizeof(long)*8)) )
X
X#define getloc(a) (regions[indx(a)] & bit(a))
X#define setloc(a) (regions[indx(a)] |= bit(a))
X
Xinclc(i)
X{
X	static unsigned long regions[ 0x10000/(sizeof(long)*8) ];
X
X	while(i-- > 0) {
X		if( pass2 && getloc(lc) )
X			error("Location counter overlaps");
X		if( pass2 ) setloc(lc);
X		lc += 1;
X	}
X		
X	if( lc > 0xffff )
X		error("Location counter has exceeded 16-bits");
X}
X
X/* ----------------------------------------------------------------------
X * padline:
X *	This routine returns a new string, which is equivilant to
X *	'line' except that all tabs have been expanded to spaces, and
X *	the total length has been truncated to 60 chars.
X */
X
Xchar *padline(line)
Xchar *line;
X{
X	static char newline[61];
X	char *p1;
X	int pos=0,nxtpos;
X
X	for(p1=line; pos<sizeof(newline)-1 && *p1; p1++ ) {
X		if( *p1 == '\t' ) {
X			nxtpos = pos+8-pos%8;
X			while(pos<sizeof(newline)-1 && pos <= nxtpos)
X				newline[pos++] = ' ';
X		} else if( *p1 != '\n' )
X			newline[pos++]= *p1;
X	}
X	newline[pos] = '\0';
X	return(newline);
X}
X
X
X/* ----------------------------------------------------------------------
X * dumplist:
X *	Outputs the current location counter, bytebuf[] array, and
X *	the string 'txt' to the listing file.
X *	This routine is called for every source line encountered in the
X *	source file. (Only in pass 2, and if listing is turned on).
X *
X */
X
Xdumplist(txt,show)
Xchar *txt;
X{
X	int i,j;
X
X	fprintf(listing,show?"%04X: ":"      ",lc);
X
X	j=0;
X	for(i=0; i<bytecount; i++ ) {
X		fprintf(listing,"%02X ",bytebuf[i]);
X		if( ++j >= 4 ) {
X			j = 0;
X			fprintf(listing,"\n      ");
X		}
X	}
X	while(++j <= 4)
X		fprintf(listing,"   ");
X
X	fprintf(listing," %s\n",padline(txt));
X}
X
X/* ----------------------------------------------------------------------
X * gen* routines:
X *	Place information into the bytebuf[] array, and also
X *	call emitbyte with the byte.
X *
X */
X
Xgenbyte(b)
Xint b;
X{
X	if( bytecount < sizeof(bytebuf) )
X		bytebuf[bytecount++] = b;
X	emitbyte(b);
X}
X
Xgenstr(s)
Xchar *s;
X{
X	while( *s )
X		genbyte(*s++);
X}
X
Xgenword(w)
Xunsigned long w;
X{
X	genbyte( (w & 0xff00) >> 8 );
X	genbyte( (w & 0x00ff) );
X}
X
END_OF_FILE
if test 22290 -ne `wc -c <'as31.y'`; then
    echo shar: \"'as31.y'\" unpacked with wrong size!
fi
# end of 'as31.y'
fi
if test -f 'as31.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'as31.man'\"
else
echo shar: Extracting \"'as31.man'\" \(9374 characters\)
sed "s/^X//" >'as31.man' <<'END_OF_FILE'
X.TH AS31 1L
X.SH NAME
Xas31 - An Intel 8031/8051 assembler
X.SH SYNOPSIS
X.B as31
X[
X.B \-Fformat
X] [
X.B \-Aarg
X] [
X.B \-l
X]
X.BR infile.asm
X.SH DESCRIPTION
X.I As31
Xassembles
X.IR infile.asm
Xinto one of several different output formats. The output
Xwill be in a file called infile.obj. The .asm extenstion
Xis required.
X
X.SH OPTIONS
XThe options must appear before the input file name. Both
Xoptions are optional. The text of each flag must appear
Xon the same argument as the flag. For example, "-Fod" is a
Xvalid argument, but "-F od" is not.
X.TP
X.I \-Fformat
XThis options specifies the output format that is to be used.
X.IP
XCurrently the only options available for this are:
X.RS
X.IP "tdr"
XThis format generates an asci file of hex digits formatted in such a
Xway, so that they can be read by tdr's debugger. An argument can be
Xspecified (See -A option) which will pass a format specific string to
Xthe format generator. In this case, the argument string represents
Xan offset to add to the location counter. This offset is
Xspecified in decimal and defaults to 64*1024 (0x10000). To specify
Xand offset of 100, you would need "-Ftdr -A100" when invoking the
Xassembler.
X
X.IP "byte"
XThis format is simply an address and a byte on each line, in ascii.
XNo -A option is used.
X
X.IP "od"
XThis format is similar to the output from od(1). The format 
Xconsists of an address followed by sixteen hexadecimal bytes, followed
Xby the equivilant ASCII. No -A option is used.
X
X.IP "srec2, srec3, srec4"
XThe srecord generator is capable of generating output with any one
Xof 2, 3, or 4 byte addresses. The -A option can be used to set the
Xbase address offset, the default here is 0x0000 (unlike \fBtdr\fP).
X.RE
X.IP
XNOTE: This assembler allows for the output formats to be expanded to
Xinclude many different output formats.
X.IP \-Aarg
XThis option specifies a format specific string which is
Xpassed to the format generator. Both format "tdr" and the srecord
Xformats use this option.
X.IP \-l
XThis option tells the assembler to also generate a listing file.
XA listing will be placed in the file infile.lst. Where 'infile' is
Xthe file that is being assembled. This option may appear
Xanywhere before infile.asm. The option must occur isolated on
Xthe command line.
X.IP
XThe listing file shows the assembler generated code in hex, and up to
X60 characters are retained from the source file.
X.DE
X
X.SH "ASSEMBLER INSTRUCTIONS"
XThis assembler accepts standard 8031/8051 instruction formats.
XBelow is a list of instructions
Xand addressing modes.
X.IP
X.RS
X.nf
X.ta +1i +2i +1i +1i
XINSTRUCTION		BYTES	CYCLES
X-----------		-----	------
XACALL	addr11		2	24
XADD	A, #data8		2	12
XADD	A, @Ri		1	12
XADD	A, Rn		1	12
XADD	A, direct		2	12
XADDC	A, #data8		2	12
XADDC	A, @Ri		1	12
XADDC	A, Rn		1	12
XADDC	A, direct		2	12
XAJMP	addr11		2	24
XANL	A, #data8		2	12
XANL	A, @Ri		1	12
XANL	A, Rn		1	12
XANL	A, direct		2	12
XANL	C, /bit		2	24
XANL	C, !bit		2	24
XANL	C, bit		2	24
XANL	direct, #data8		3	24
XANL	direct, A		2	12
XCJNE	@Ri, #data8, rel		3	24
XCJNE	A, #data8, rel		3	24
XCJNE	A, direct, rel		3	24
XCJNE	Rn, #data8, rel		3	24
XCLR	A		1	12
XCLR	C		1	12
XCLR	bit		2	12
XCPL	A		1	12
XCPL	C		1	12
XCPL	bit		2	12
XDA	A		1	12
XDEC	@Ri		1	12
XDEC	A		1	12
XDEC	DPTR		1	12
XDEC	Rn		1	12
XDEC	direct		2	12
XDIV	AB		1	48
XDJNZ	Rn, rel		2	24
XDJNZ	direct, rel		3	24
XINC	@Ri		1	12
XINC	A		1	12
XINC	DPTR		1	24
XINC	Rn		1	12
XINC	direct		2	12
XJB	bit, rel		3	24
XJBC	bit, rel		3	24
XJC	relative		2	24
XJMP	@A + DPTR		1	24
XJMP	@DPTR + A		1	24
XJNB	bit, rel		3	24
XJNC	relative		2	24
XJNZ	relative		2	24
XJZ	relative		2	24
XLCALL	addr16		3	24
XLJMP	addr16		3	24
XMOV	@Ri, #data8		2	12
XMOV	@Ri, A		1	12
XMOV	@Ri, direct		2	24
XMOV	A, #data8		2	12
XMOV	A, @Ri		1	12
XMOV	A, Rn		1	12
XMOV	A, direct		2	12
XMOV	C, bit		2	12
XMOV	DPTR, #data16		3	24
XMOV	Rn, #data8		2	12
XMOV	Rn, A		1	12
XMOV	Rn, direct		2	24
XMOV	bit, C		2	24
XMOV	direct, #data8		3	24
XMOV	direct, @Ri		2	24
XMOV	direct, A		2	12
XMOV	direct, Rn		2	24
XMOV	direct, direct		3	24
XMOVC	A, @A + DPTR		1	24
XMOVC	A, @A + PC		1	24
XMOVC	A, @DPTR + A		1	24
XMOVC	A, @PC + A		1	24
XMOVX	@DPTR, A		1	12
XMOVX	@Ri, A		1	24
XMOVX	A, @DPTR		1	24
XMOVX	A, @Ri		1	24
XMUL	AB		1	48
XNOP			1	12
XORL	A, #data8		2	12
XORL	A, @Ri		1	12
XORL	A, Rn		1	12
XORL	A, direct		2	12
XORL	C, /bit		2	24
XORL	C, !bit		2	24
XORL	C, bit		2	24
XORL	direct, #data8		3	24
XORL	direct, A		2	12
XPOP	direct		2	24
XPUSH	direct		2	24
XRET			1	24
XRETI			1	24
XRL	A		1	12
XRLC	A		1	12
XRR	A		1	12
XRRC	A		1	12
XSETB	A		1	12
XSETB	bit		2	12
XSJMP	relative		2	24
XSUBB	A, #data8		2	12
XSUBB	A, @Ri		1	12
XSUBB	A, Rn		1	12
XSUBB	A, direct		2	12
XSWAP	A		1	12
XXCH	A, #data8		2	12
XXCH	A, @Ri		1	12
XXCH	A, Rn		1	12
XXCH	A, direct		2	12
XXCHD	A, #data8		2	12
XXCHD	A, @Ri		1	12
XXCHD	A, Rn		1	12
XXCHD	A, direct		2	12
XXRL	A, #data8		2	12
XXRL	A, @Ri		1	12
XXRL	A, Rn		1	12
XXRL	A, direct		2	12
XXRL	direct, #data8		3	12
XXRL	direct, A		2	12
X.fi
X.RE
X
X.SH "ASSEMBLER DIRECTIVES"
XAs31 includes the following assembler directives:
X.IP ".ORG expr"
XStart assembling at the address specified by the expression expr.
XAn error occurs if the assembler starts assembling over an address
Xspace that has previously been assembled into.
X
X.IP ".EQU symbol, expr"
XSet symbol to the value of expr. The value for expr must be
Xknown during the first pass, when the line containing the .EQU
Xis encountered.
X
X.IP ".BYTE expr, expr, ..."
XAssemble the bytes specified by the expression into memory. A
Xstring may also be specified with this directive.
X
X.IP ".WORD expr, expr, ..."
XAssemble the words specified by the expression into memory.
XThe byte ordering used, is that used by the 8031.
X
X.IP ".FLAG symbol1, symbol.[0-7]"
XSets symbol1 to the bit address specified by the symbol.[0-7]
Xexpression. Where [0-7] denotes a character between 0 and 7.
XThe resulting bit address is checked to see if it is a valid bit
Xaddress.
X
X.IP ".END"
XThis directive is ignored.
X
X.IP ".SKIP expr"
XAdds the value of expr to the location counter. Used
Xto reserve a block of uninitialized data. Expr should
Xbe in bytes.
X
X.SH "LEXICAL CONVENTIONS"
X.IP "-"
XAll characters following a semi-colon are ignored until a newline
Xis encountered.
X
X.IP "-"
XAll numbers default to decimal, unless the number starts with
Xone of the following:
X.RS
X.IP "0x or 0X"
XThis indicates a hexadecimal number. ie. 0x00ff
X.IP "0b or 0B"
XThis indicates a binary number. (1's and 0's). ie. 0b1100110010
X.IP "0"
XThis indicates an octal number. ie. 0377
X.RE
X.IP "-"
XAll numbers default to decimal, unless the number ends with
Xone of the following characters:
X.RS
X.IP "b or B"
XThis indicates a binary number. Unless 0x was used above.
Xie. 1010101b
X.IP "h or H"
XThis always indicates a hex number, However the if the first
Xcharacter is non-numerical, then either 0x or 0 must be specified.
XThis avoids confusing the assembler into thinking a hex number is
Xa symbol.
XFor example: 0ffh, 0xffh, 0XffH, 20h, 0x20 and 020h are means
Xto specify a valid hexdigit. But the following are not:
Xffh, 0ff.
X.IP "d or D"
XThis forces a number to decimal. Unless 0X was used. ie. 129d
X.IP "o or O"
XThis causes the number to be interpreted as octal. ie. 377o
X.RE
X
X.IP "-"
XA character constant can be entered as 'c' where c is some
Xcharacter. \\b, \\n, \\r, \\t, \\' \\0 are also valid. A character
Xconstant can be used anywhere that an integer value can.
X
X.IP "-"
XA string is entered as a set of characters enclosed in double quotes "".
XA string is only valid with the .BYTE directive. \\b, \\n, \\r, \\t, \\"
Xare also valid escapes. However \\0 is not.
X
X.IP "-"
XInstructions, directives, and the symbols: R0, R1, R2, R3, R4, R5,
XR6, R7, A, AB, and C can be entered in upper or lower case without
Xassembler confusion. These words however cannot be defined as a user symbol.
XAny user symbol may be used, and case will be preserved. So the
Xuser symbols "foo" and "Foo" are different, but "addc" is the same
Xas "aDdC".
X
X.IP "-"
XA symbol can be any alpha numerical character plus the underscore ('_').
X
X.IP "-"
XExpressions are accepted in most places where a value or a symbol is
Xneeded. An expression consists of the following operators. All
Xoperators evaulate to integer objects (higher precedence opertors listed
Xfirst):
X.RS
X.IP "-"
XUnary minus
X.IP "&"
XBit-wise AND.
X.IP "|"
XBit-Wise OR.
X.IP "*"
XInteger multiplication.
X.IP
X\\ Integer division
X.IP "%"
XIntieger modulus
X.IP "+"
XInteger addition.
X.IP "-"
XInteger subtraction.
X.RE
X.IP "-"
XIn addition to these operators, a special symbol '*' may be used
Xto represent the current location counter.
X
X.SH EXAMPLES
X.IP
XBelow is a sample assembly program.
X.RS
X.nf
X
X                .org    0
Xstart:          mov     P3, #0xff       ; use alternate fns on P3
X			                ; leds on P1 are inverted.
X                setb    F0              ; climbing up
X                mov     A, #0x01        ; initial bit
X
Xwrite:          cpl     A               ; write it
X                mov     P1, A
X                cpl     A
X                acall   delay
X                jb      F0, climbup     ; climbing which way?
X
Xclimbdn:        rr      A               ; down - shift right
X                jnb     ACC.0, write    ; back for more
X                setb    F0
X                ajmp    write
X
Xclimbup:        rl      A               ; up - shift left
X                jnb     ACC.7, write    ; back for more
X                clr     F0
X                ajmp    write
X                .end			; this directive ignored.
X.fi
X
X
X.SH AUTHOR
XKen Stauffer (University of Calgary)
X.br
Xstauffer at cpsc.ucalgary.ca
END_OF_FILE
if test 9374 -ne `wc -c <'as31.man'`; then
    echo shar: \"'as31.man'\" unpacked with wrong size!
fi
# end of 'as31.man'
fi
if test -f 'emitter.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'emitter.c'\"
else
echo shar: Extracting \"'emitter.c'\" \(8382 characters\)
sed "s/^X//" >'emitter.c' <<'END_OF_FILE'
X/* ----------------------------------------------------------------------
X * FILE: emitter.c
X * PACKAGE: as31 - 8031/8051 Assembler.
X *
X * DESCRIPTION:
X *	This file contains the code to generate various
X *	object code formats. Provisions exist to
X *	support many types of output formats within the
X *	same executable.
X *
X * REVISION HISTORY:
X *	Jan. 19, 1990 - Created. (Ken Stauffer)
X *	Jan. 29, 1990 - Added S-records (Theo Deraadt)
X *
X *
X * AUTHOR:
X *	All code in this file written by Ken Stauffer (University of Calgary).
X *	January, 1990.
X */
X
X#include <stdio.h>
X
X/* ----------------------------------------------------------------------
X * DECLARE your own open(), close(), addr(), and byte() routines here.
X *
X */
X
Xstatic int open1(), close1(), addr1(), byte1();
Xstatic int open2(), close2(), addr2(), byte2();
Xstatic int open3(), close3(), addr3(), byte3();
Xstatic int open4(), close4(), addr4(), byte4();
X
X/* ----------------------------------------------------------------------
X * ADD an entry to this table to register your
X * output format routines. Give your object format
X * a name to be specified with the -F option.
X *
X */
X
Xstatic int format;
Xstatic struct {
X	char *name;
X	int (*e_open)();
X	int (*e_close)();
X	int (*e_addr)();
X	int (*e_byte)();
X} formtab[] = {
X	{ "tdr",   open1, close1, addr1, byte1 },
X	{ "byte",  open2, close2, addr2, byte2 },
X	{ "od",    open3, close3, addr3, byte3 },
X	{ "srec2", open4, close4, addr4, byte4 },
X	{ "srec3", open4, close4, addr4, byte4 },
X	{ "srec4", open4, close4, addr4, byte4 }
X};
X
X#define FORMTABSIZE	(sizeof(formtab)/sizeof(formtab[0]))
X
Xemitusage()
X{
X	int i;
X	fprintf(stderr, "\tfmt is one of:");
X	for(i=0; i<FORMTABSIZE; ) {
X		fprintf(stderr, "%s", formtab[i].name);
X		if( ++i < FORMTABSIZE)
X			fprintf(stderr, ", ");
X	}
X	fprintf(stderr, ".\n");
X}
X
Xemitopen(file,ftype,arg)
Xchar *file,*ftype,*arg;
X{
X	int i;
X	if( ftype ) {
X		for(i=0; i<FORMTABSIZE; i++ ) {
X			if( !strcmp(formtab[i].name,ftype) ) {
X				format = i;
X				(*formtab[format].e_open)(file,ftype,arg);
X				return;
X			}
X		}
X		fprintf(stderr, "warning: no format \"%s\", using \"%s\"\n",
X			ftype, formtab[0].name);
X	}
X	/*
X	 * 0th entry is the default format type
X	 */
X	format = 0;
X	(*formtab[format].e_open)(file,ftype,arg);
X}
X
Xemitclose()
X{
X	(*formtab[format].e_close)();
X}
X
Xemitaddr(a)
Xunsigned long int a;
X{
X	(*formtab[format].e_addr)(a);
X}
X
Xemitbyte(b)
Xint b;
X{
X	(*formtab[format].e_byte)(b);
X}
X
X/* ----------------------------------------------------------------------
X * Individual file format routines appear here:
X *	Each file format must define the following routines:
X *		open()	- Called ONCE before any of the others.
X *			It is passed with a filename and a format
X *			specific argument.
X *
X *		close() - Called ONCE when no more emit_byte()
X *			function calls will be made.
X *
X *		addr() - Called when ever a new address has been set
X *			in the assembler (ie. .org, .skip).
X *			This routine is also called once when the
X *			location counter is set to 0 at the very start of
X *			assembling.
X * 
X *		byte() - Called with each byte to be outputed.
X *
X */
X
X/* ----------------------------------------------------------------------
X * "tdr" format. For tdr's 68008 system. Generates a
X * script file readable by a debugger.
X *	[addr] : [byte] [byte] ..
X *
X * arg: This is a number in decimal which specifies
X *	the offset, -Ftdr -A0000
X *
X *	These options specifies the tdr format, with an argument
X *	of 0. This becomes the offset used in generating the
X *	script file. The default if no A is present is 0x10000.
X * 
X */
X
Xstatic unsigned long addr;
Xstatic FILE *fout;
Xstatic long int offset;
Xstatic int newaddr;
Xstatic int pos=-666;
X
Xstatic open1(file,ftype,arg)
Xchar *file, *ftype, *arg;
X{
X	fout = fopen(file,"w");
X	if( fout == NULL ) {
X		fprintf(stderr,"Cannot open %s for writting.\n",file);
X		exit(1);
X	}
X	if( arg ) {
X		offset = atoi(arg);
X	} else
X		offset = 0x10000;
X}
X
Xstatic close1()
X{
X	if( pos != 15 ) fprintf(fout,"\n");
X	fclose(fout);
X}
X
Xstatic addr1(a)
Xunsigned long int a;
X{
X	addr = a;
X	newaddr = 1;
X}
X
Xstatic byte1(b)
Xunsigned char b;
X{
X	if( newaddr ) {
X		if( pos != -666 ) fprintf(fout,"\n");
X		newaddr = 0;
X		pos = 15;
X		fprintf(fout,"%06x: ",addr+offset);
X	} else if( pos == 15 ) {
X		fprintf(fout,"%06x: ",addr+offset);
X	}
X
X	fprintf(fout,"%02x ", b&0xff );
X
X	if( pos-- == 0 ) {
X		fprintf(fout,"\n");
X		pos = 15;
X	}
X	addr += 1;
X}
X
X
X/* ----------------------------------------------------------------------
X * "byte" format.
X *	Like "tdr" but each byte is on a line by itself.
X *	This is nice for debugging. No -A is used.
X */
X
Xstatic open2(file,ftype,arg)
Xchar *file, *ftype, *arg;
X{
X	fout = fopen(file,"w");
X	if( fout == NULL ) {
X		fprintf(stderr,"Cannot open %s for writting.\n",file);
X		exit(1);
X	}
X}
X
Xstatic close2()
X{
X	fclose(fout);
X}
X
Xstatic addr2(a)
Xunsigned long int a;
X{
X	addr = a;
X}
X
Xstatic byte2(b)
Xunsigned char b;
X{
X	fprintf(fout,"%04x: %02x\n", addr, b&0xff );
X	addr += 1;
X}
X
X
X/* ----------------------------------------------------------------------
X * "od", this format shows 16 bytes per line, with address.
X *	It also includes ascii on one side.
X *
X * The format is similar to the od(1) program under Unix.
X *
X */
X
Xstatic int pos3;
Xstatic unsigned char buf[16];
Xstatic unsigned long saveaddr;
X
Xstatic open3(file,ftype,arg)
Xchar *file, *arg;
X{
X	fout = fopen(file,"w");
X	if( fout == NULL ) {
X		fprintf(stderr,"Cannot open %s for writting.\n",file);
X		exit(1);
X	}
X}
X
Xstatic close3()
X{
X	dumpline(saveaddr,buf,pos3-1);
X	fclose(fout);
X}
X
Xstatic addr3(a)
Xunsigned long int a;
X{
X	newaddr = 1;
X	addr = a;
X}
X
Xstatic byte3(b)
Xunsigned char b;
X{
X	if( newaddr ) {
X		dumpline(saveaddr,buf,pos3-1);
X		pos3 = 0;
X		newaddr = 0;
X		saveaddr = addr;
X	} else if( pos3 == 16 ) {
X		dumpline(saveaddr,buf,pos3-1);
X		pos3 = 0;
X		saveaddr = addr;
X	}
X	buf[pos3++] = b & 0x00ff;
X
X	addr += 1;
X}
X
Xdumpline(a,b,len)
Xunsigned long a;
Xunsigned char *b;
Xint len;
X{
X	int i;
X
X	if(len <= 0 ) return;
X
X	fprintf(fout,"%04x: ",a);
X
X	for(i=0; i<8; i++ ) {
X		if( i <= len )
X			fprintf(fout,"%02x ",b[i]);
X		else
X			fprintf(fout,"   ");
X	}
X
X	fprintf(fout,"- ");
X
X	for(i=8; i<16; i++ ) {
X		if( i <= len )
X			fprintf(fout,"%02x ",b[i]);
X		else
X			fprintf(fout,"   ");
X	}
X	fprintf(fout,"   ");
X
X	for(i=0; i<16; i++ ) {
X		if( i <= len )
X			fprintf(fout,"%c",
X				(b[i]>=' ' && b[i]<='~') ? b[i] : '.' );
X		else
X			break;
X	}
X	fprintf(fout,"\n");
X}
X
X/* ----------------------------------------------------------------------
X * srecord format. This is called with "-Fsrec2", "-Fsrec3", or
X * "-Fsrec4"...
X *
X * arg: This is a number in decimal which specifies
X *	the offset, -Fsrec3 -A0000
X *
X *	These options specifies the tdr format, with an argument
X *	of 0. This becomes the offset used in generating the
X *	script file. The default if no A is present is 0x0000.
X * 
X */
X#define SREC_BYTESPERLINE 32
X
Xstatic char format4;
Xstatic int check4, index4;
Xstatic char buf4[SREC_BYTESPERLINE];
Xstatic long address4;
X
Xstatic open4(file,ftype,arg)
Xchar *file, *ftype, *arg;
X{
X	format4 = ftype[4];		/* will be '2' -- '4' */
X
X	fout = fopen(file,"w");
X	if( fout == NULL ) {
X		fprintf(stderr,"Cannot open %s for writing.\n",file);
X		exit(1);
X	}
X
X	if(arg)	offset = atoi(arg);
X	else	offset = 0;
X
X	fprintf(fout, "S0030000%02X\n", (~3 & 0xff) );
X
X}
X
Xstatic close4()
X{
X	if(index4)
X		finishline();
X	switch(format4) {
X	case '2':
X		fprintf(fout, "S9030000%02X\n", ~3 & 0xff);
X		break;
X	case '3':
X		fprintf(fout, "S804000000%02X\n", ~4 & 0xff);
X		break;
X	case '4':
X		fprintf(fout, "S70500000000%02X\n", ~5 & 0xff);
X		break;
X	}
X	fclose(fout);
X}
X
X
Xstatic addr4(a)
Xunsigned long int a;
X{
X	if(index4>0)
X		finishline();
X	address4 = a + offset;
X}
X
Xstatic byte4(b)
X{
X	buf4[index4++] = b;
X	if(index4==SREC_BYTESPERLINE) {
X		finishline();
X		address4 += SREC_BYTESPERLINE;
X	}
X}
X
Xfinishline()
X{
X	int i;
X
X	check4 = index4 + (address4 & 0xff) + ((address4>>8) & 0xff) + 4;
X
X	switch(format4) {
X	case '2':
X		fprintf(fout, "S1%02X%04X", index4 + 4,	address4 & 0xffff);
X		break;
X	case '3':
X		fprintf(fout, "S2%02X%06X", index4 + 6, address4 & 0xffffff);
X		check4 += ((address4>>16) & 0xff) + 2;
X		break;
X	case '4':
X		fprintf(fout, "S3%02X%08X", index4 + 8, address4);
X		check4 += ((address4>>16) & 0xff) +((address4>>24) & 0xff) + 4;
X		break;
X	}
X
X	for(i=0; i<index4; i++) {
X		fprintf(fout, "%02X", buf4[i] & 0xff);
X		check4 += buf4[i];
X	}
X
X	fprintf(fout, "%02X\n", (~check4 & 0xff) );
X	index4 = 0;
X}
X
END_OF_FILE
if test 8382 -ne `wc -c <'emitter.c'`; then
    echo shar: \"'emitter.c'\" unpacked with wrong size!
fi
# end of 'emitter.c'
fi
if test -f 'lexer.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'lexer.c'\"
else
echo shar: Extracting \"'lexer.c'\" \(6816 characters\)
sed "s/^X//" >'lexer.c' <<'END_OF_FILE'
X/* ----------------------------------------------------------------------
X * FILE: lexer.c
X * PACKAGE: as31 - 8031/8051 Assembler.
X *
X * DESCRIPTION:
X *	This file contains the lexical tokenizer for the assembler.
X *	Since yacc is being used the lexer is called yylex().
X *
X *	In order to produce a listing, some record of the users
X *	source line must be kept. This is done by adding
X *	get_ch(), and unget_ch() routine which returns/ungets a character
X *	but also places information into a secret array.
X *
X *	When a newline is encountered the text line is returned as
X *	an attribute on the '\n' character.
X *
X * REVISION HISTORY:
X *	Jan. 19, 1990 - Created. (Ken Stauffer)
X *
X * AUTHOR:
X *	All code in this file written by Ken Stauffer (University of Calgary).
X *	January, 1990.
X *
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include "as31.h"
X
Xextern union ystack yylval;
Xextern int pass;
X
Xstruct symbol *looksym();
Xstruct opcode *lookop();
Xchar *malloc();
Xint lineno;
X
Xstatic char line[100],*lineptr=line;
X
X/* ----------------------------------------------------------------------
X * get_ch:
X *	Get a character from stdin, place char in line[]
X */
X
Xget_ch()
X{
X	register int c;
X
X	c = getchar();
X	if( c != EOF && lineptr - line < sizeof(line) )
X		*lineptr++ = c;
X	return(c);
X}
X
X/* ----------------------------------------------------------------------
X * unget_ch:
X *	Unget a character and move lineptr back by one.
X */
X
Xunget_ch(c)
Xint c;
X{
X	ungetc(c,stdin);
X	if( lineptr > line )
X		lineptr--;
X}
X
X/* ----------------------------------------------------------------------
X * yylex:
X *	The tokens themselves are returned via return(token)
X *
X *	Some tokens have attributes. These attributes are returned
X *	by setting a global variable yylval:
X *
X *		yylval.value
X *			numbers (any base)
X *			strings (in pass 1).
X *			bit positions .0, .1, .2, ...
X *
X *		yylval.str
X *			strings (in pass 2).
X *			'\n' (both passes).
X *
X *		yylval.sym
X *			User defined symbols.
X *
X *		yylval.op
X *			Reserved keyword (opcode/directive/misc.)
X *
X *		No other fields in yylval are used by yylex().
X * 
X *		Characters that do not have an attribute do
X *		not set anything in the yylval variable.
X *
X */
X
Xyylex()
X{
X	static nl_flag=0;	/* sync. error messages and the cur. line */
X	register int c;
X	char buf[120];		/* temporary buffer */
X	char *p;		/* general pointer */
X	struct symbol *sym;
X	struct opcode *op;
X
X	int octal=0,hex=0,decimal=0,binary=0;
X	register long value = 0;
X
X	if( nl_flag ) {
X		nl_flag = 0;
X		lineno++;
X	}
X
Xfor(;;) {
X	c = get_ch();
X	switch(c) {
X	case EOF: return(EOF);
X	case ' ':
X	case '\t':
X		break;
X
X	case '\n':
X		nl_flag = 1;
X		yylval.str = line;
X		*lineptr = '\0';
X		lineptr = line;
X		return('\n');
X
X	case ';':
X		while((c=get_ch()) != EOF && c!='\n');
X		nl_flag= 1;
X		yylval.str = line;
X		*lineptr = '\0';
X		lineptr = line;
X		return(c);
X
X	case '"':
X		p = buf;
X		while((c=get_ch()) != EOF && c!='"' && c!='\n') {
X			if( c == '\\' ) {
X				switch(c=get_ch()) {
X				case 'n': c = '\n'; break;
X				case 'r': c = '\r'; break;
X				case 't': c = '\t'; break;
X				case 'b': c = '\b'; break;
X				case '"': c = '"'; break;
X				case '\\': c = '\\'; break;
X				default:
X				  error("Invalid escape character: \\%c",c);
X				  break;
X				}
X			}
X			if( p-buf<sizeof(buf)-1 ) 
X				*p++ = c;
X			else {
X			   error("String constant longer than %d bytes",
X					sizeof(buf));
X			}
X		}
X		*p = '\0';
X		if( c == '\n' || c == EOF ) {
X			error("String terminated improperly.");
X			unget_ch(c);
X		}
X
X		if(pass1)
X			yylval.value = strlen(buf);
X		else {
X			if( (p = malloc(strlen(buf)+1)) == NULL )
X			   error("Cannot allocate %d bytes",strlen(buf)+1);
X			strcpy(p,buf);
X			yylval.str = p;
X		}
X		return(STRING);
X
X	case '.':
X		if( (c=get_ch())>='0' && c<='7' ) {
X			yylval.value = c-'0';
X			return(BITPOS);
X		}
X		unget_ch(c);
X		return('.');
X
X	case '\'':
X		c = get_ch();
X		if( c=='\\' ) {
X			switch(c=get_ch()) {
X			case 'n': c = '\n'; break;
X			case 'r': c = '\r'; break;
X			case 't': c = '\t'; break;
X			case 'b': c = '\b'; break;
X			case '\\': c = '\\'; break;
X			case '\'': c = '\''; break;
X			default:
X				error("Invalid escape character: \\%c",c);
X			}
X		}
X		if( get_ch() != '\'' )
X			error("Missing quote in character constant");
X		yylval.value = c;
X		return(VALUE);
X
X	case '0':	/* parse a number			*/
X	case '1':	/* could be followed by a:		*/
X	case '2':	/*	'b','B' - Binary		*/
X	case '3':	/*	'h','H' - Hex			*/
X	case '4':	/*	'd','D' - Decimal		*/
X	case '5':	/*	'o','O' - Octal			*/
X	case '6':	/* *** Numbers must start with a digit	*/
X	case '7':	/* Numbers could be also preceeded by:  */
X	case '8':	/*	0x	- Hex,	0b     - binary */
X	case '9':	/*	0	- Octal			*/
X
X		p = buf;
X		do {
X			if( p-buf<sizeof(buf)-1 )
X				*p++ = c;
X			c = get_ch();
X		} while( c=='H' || c=='h' || c=='O' || c=='o' ||
X				c=='x' || c=='X' || isxdigit(c) );
X		unget_ch(c);
X		*p = '\0';
X
X
X		/* Check any preceeding chars */
X		if( buf[0]=='0' && (buf[1]=='x' || buf[1]=='X') ) {
X				hex++;
X				buf[1] = '0';
X		} else if( buf[0]=='0' &&
X			(buf[1]=='b' || buf[1]=='B') ) {
X				binary++;
X				buf[1] = '0';
X			}
X		else if( buf[0]=='0' ) octal++;
X
X		/* check any trailing chars */
X		c = *(p-1);
X		if( !hex && (c=='b' || c=='B') )
X			{ binary++; *(p-1) = '\0'; }
X		else if( c=='H' || c=='h' )
X			{ hex++; *(p-1) = '\0'; }
X		else if( !hex && (c=='D' || c=='d') )
X			{ decimal++; *(p-1) = '\0'; }
X		else if( c=='O' || c=='o' )
X			{ octal++; *(p-1) = '\0'; }
X		else if( !hex && !octal && !binary) decimal++;
X
X		if( binary ) {
X			for(p=buf; *p; p++ ) {
X				if( *p=='1' ) value = value<<1 + 1;
X				else if( *p=='0' ) value = value<<1;
X				else
X				  error("Invalid binary digit: %c",*p);
X			}
X			yylval.value = value;
X			return(VALUE);
X		}
X
X		if( hex ) {
X			for(p=buf; *p; p++ ) {
X				value <<= 4;
X				if( isdigit(*p) )
X					value += *p-'0';
X				else if( *p>='a' && *p<='f' )
X					value += *p-'a'+ 10;
X				else if( *p>='A' && *p<='F' )
X					value += *p-'A'+ 10;
X				else
X				  error("Invalid hex digit: %c",*p);
X			}
X			yylval.value = value;
X			return(VALUE);
X		}
X
X		if( decimal ) {
X			for(p=buf; *p; p++ ) {
X				if( isdigit(*p) )
X					value = value*10 + *p-'0';
X				else
X				   error("Invalid decimal digit: %c",*p);
X			}
X			yylval.value = value;
X			return(VALUE);
X		}
X
X		if( octal ) {
X			for(p=buf; *p; p++ ) {
X				if( *p>='0' && *p<='7' )
X					value = value<<3 + *p-'0';
X				else
X				   error("Invalid octal digit: %c",*p);
X			}
X			yylval.value = value;
X			return(VALUE);
X		}
X
X	default:
X		if( isalpha(c) || c=='_' ) {
X			p = buf;
X			do {
X				if( p-buf<sizeof(buf)-1 )
X					*p++ = c;
X				c = get_ch();
X			} while( isalnum(c) || c=='_' );
X			*p = '\0';
X			unget_ch(c);
X			if( op = lookop(buf) ) {
X				yylval.op = op;
X				return(op->type);
X			}
X			sym = looksym(buf);
X			yylval.sym = sym;
X			return(SYMBOL);
X		} else
X			return(c);
X	} /* switch */
X} /* for */
X
X} /* yylex */
END_OF_FILE
if test 6816 -ne `wc -c <'lexer.c'`; then
    echo shar: \"'lexer.c'\" unpacked with wrong size!
fi
# end of 'lexer.c'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(2745 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X/* ----------------------------------------------------------------------
X * FILE: main.c
X * PACKAGE: as31 - 8031/8051 Assembler.
X *
X * DESCRIPTION:
X *	The file contains main(). It handles the arguments and makes
X *	sure that pass 1 is done before pass 2 etc...
X *
X * REVISION HISTORY:
X *	Jan. 19, 1990 - Created. (Ken Stauffer)
X *
X * AUTHOR:
X *	All code in this file written by Ken Stauffer (University of Calgary).
X *	January, 1990. */ static char
X *	id_id= "Written by: Ken Stauffer";/*
X *
X */
X
X#include <stdio.h>
X#include <setjmp.h>
X
Xextern int lineno;
Xextern int pass,fatal;
Xextern unsigned long lc;
X
Xjmp_buf main_env;
Xchar *asmfile;
Xint dashl=0;
XFILE *listing;
X
X/* ----------------------------------------------------------------------
X * checkext:
X *	Check the string s, for the presence of an extenstion e.
X *	Return the position of the start of e in s.
X *	or return NULL.
X */
X
Xchar *checkext(s,e)
Xchar *s,*e;
X{
X	register char *ps = s, *pe = e;
X
X	while( *ps ) ps++;
X	while( *pe ) pe++;
X
X	for( ; ps>=s && pe>=e && *ps == *pe; ps--, pe-- )
X		if( pe == e ) return(ps);
X	return(NULL);
X}
X
Xmain(argc,argv)
Xchar *argv[];
X{
X	FILE *fin;
X	char *p,*dashF=NULL, *dashA=NULL;
X	char objfile[100];
X	char lstfile[100];
X	int i;
X
X	if( argc < 2 ) {
X		fprintf(stderr,"Usage: %s [-l] [-Ffmt] [-Aarg] infile.asm\n",
X						argv[0]);
X		emitusage();
X		exit(1);
X	}
X
X	for(i=1; i<argc; i++ ) {
X		if( argv[i][0] != '-' ) break;
X		if( argv[i][1] == 'l' ) dashl = 1;
X		else if( dashF == NULL && argv[i][1] == 'F' )
X			dashF = argv[i]+2;
X		else if( dashA == NULL && argv[i][1] == 'A' )
X			dashA = argv[i]+2;
X		else {
X			fprintf(stderr,"Duplicate or unknown flag.\n");
X			exit(1);
X		}
X	}
X	if( i == argc ) {
X		fprintf(stderr,"Missing input file.\n");
X		exit(1);
X	}
X
X	if( (p=checkext(argv[i],".asm")) == NULL ) {
X		fprintf(stderr,"Input file \"%s\" must end with .asm\n",
X				argv[i]);
X		exit(1);
X	}
X	asmfile = argv[i];
X
X	if( (fin = freopen(argv[i],"r",stdin)) == NULL ) {
X		fprintf(stderr,"Cannot open input file: %s\n",argv[i]);
X		exit(1);
X	}
X
X	if( dashl ) {
X		strcpy(lstfile,argv[i]);
X		strcpy(lstfile+(p-argv[i]),".lst");
X		listing = fopen(lstfile,"w");
X		if( listing == NULL ) {
X			fprintf(stderr,"Cannot open file: %s for writting.\n",
X				lstfile);
X			exit(1);
X		}
X	}
X	strcpy(objfile,argv[i]);
X	strcpy(objfile+(p-argv[i]),".obj");
X
X	emitopen(objfile,dashF,dashA);
X
X	syminit();
X	fatal = 0;
X	lineno = 1;
X	pass=0;
X	lc = 0x0000;
X
X	if( setjmp(main_env) ) {
X		fclose(fin);
X		emitclose();
X		unlink(objfile);
X		exit(1);
X	}
X
X	/*
X	** P A S S    1
X	*/
X	yyparse();
X	if( fatal ) longjmp(main_env,1);
X
X	rewind(fin);
X	lineno = 1;
X	pass++;
X	lc = 0x0000;
X	emitaddr(lc);
X
X	/*
X	** P A S S    2
X	*/
X	yyparse();
X
X	emitclose();
X	fclose(fin);
X	if( dashl )
X		fclose(listing);
X	exit(0);
X
X}
END_OF_FILE
if test 2745 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
if test -f 'makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makefile'\"
else
echo shar: Extracting \"'makefile'\" \(856 characters\)
sed "s/^X//" >'makefile' <<'END_OF_FILE'
X# FILE: makefile
X# PACKAGE: as31 - 8031/8051 Assembler.
X#
X# DESCRIPTION:
X#
X#
X# REVISION HISTORY:
X#		Jan. 19, 1990 - Created. (Ken Stauffer).
X#		Jan. 30, 1990 - Theo played here.
X
XCFLAGS=-O
XYACCFLAGS=-d
XOBJ=as31.o symbol.o lexer.o emitter.o main.o
XSHARFILES=README as31.h as31.y as31.man emitter.c lexer.c main.c makefile \
X		symbol.c new.asm
X
Xas31:		$(OBJ)
X		$(CC) $(CFLAGS) -o as31 $(OBJ)
X		chmod a+rx as31
X
Xmain.o:		main.c as31.h
Xemitter.o:	emitter.c as31.h
Xsymbol.o:	symbol.c as31.h
Xlexer.o:	lexer.c as31.h
Xas31.o:		as31.c
Xas31.c:		as31.y as31.h
X		yacc $(YACCFLAGS) as31.y
X		/bin/mv y.tab.c as31.c
X
Xman:		as31.cat
X
Xas31.cat:	as31.man
X		nroff -man as31.man > as31.cat
X		chmod a+r as31.cat as31.man
X		
Xasm:		new.obj ram.obj
X
Xnew.obj:	new.asm
X		./as31 -Ftdr -l new.asm
X
Xclean:
X		$(RM) *~ *.o as31.c y.tab.h as31.shar
X
Xshar:
X		shar $(SHARFILES) > as31.shar
END_OF_FILE
if test 856 -ne `wc -c <'makefile'`; then
    echo shar: \"'makefile'\" unpacked with wrong size!
fi
# end of 'makefile'
fi
if test -f 'symbol.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'symbol.c'\"
else
echo shar: Extracting \"'symbol.c'\" \(10609 characters\)
sed "s/^X//" >'symbol.c' <<'END_OF_FILE'
X/* ----------------------------------------------------------------------
X * FILE: symbol.c
X * PACKAGE: as31 - 8031/8051 Assembler.
X *
X * DESCRIPTION:
X *	This file contains the symbol table search/insertion routines
X *	associated with user defined symbols.
X *
X *	The reserved keyword (instructions/directives) look up routine
X *	is defined here.
X *
X *	The opcode table for all of the instructions is located in this
X *	file.
X *
X * REVISION HISTORY:
X *	Jan. 19, 1990 - Created. (Ken Stauffer)
X *
X * AUTHOR:
X *	All code in this file written by Ken Stauffer (University of Calgary)
X *	January, 1990.
X *
X */
X
X#include "as31.h"
X#define NULL		(0)
X
X#define B(a)		(0xF0+(a))
X#define ACC(a)		(0xE0+(a))
X#define PSW(a)		(0xD0+(a))
X#define T2CON(a)	(0xC8+(a))
X#define IP(a)		(0xB8+(a))
X#define P3(a)		(0xB0+(a))
X#define IE(a)		(0xA8+(a))
X#define P2(a)		(0xA0+(a))
X#define SCON(a)		(0x98+(a))
X#define P1(a)		(0x90+(a))
X#define TCON(a)		(0x88+(a))
X#define P0(a)		(0x80+(a))
X
X/* ---------------------------------------------------------------------- 
X * sinit[]
X *	These symbols are not reserved keywords.
X *	This array contains the initial symbol table entries
X *	for the user symbol table. The symbols are
X *	basically convienient names that make writting
X *	in 8031/8051 bearable.
X *
X *	The function syminit() inserts these entries into the
X *	symbol table.
X *
X */
X
Xstatic struct symbol sinit[] = {
X	{ "AC",		LABEL,		PSW(6),	NULL },
X	{ "ACC",	LABEL,		ACC(0),	NULL },
X	{ "B",		LABEL,		B(0),	NULL },
X	{ "CY",		LABEL,		PSW(7),	NULL },
X	{ "DPH",	LABEL,		0x83,	NULL },
X	{ "DPL",	LABEL,		0x82,	NULL },
X	{ "EA",		LABEL,		IE(7),	NULL },
X	{ "ES",		LABEL,		IE(4),	NULL },
X	{ "ET0",	LABEL,		IE(1),	NULL },
X	{ "ET1",	LABEL,		IE(3),	NULL },
X	{ "ET2",	LABEL,		IE(5),	NULL },
X	{ "EX0",	LABEL,		IE(0),	NULL },
X	{ "EX1",	LABEL,		IE(2),	NULL },
X	{ "EXEN2",	LABEL,		T2CON(3),NULL },
X	{ "EXF2",	LABEL,		T2CON(6),NULL },
X	{ "F0",		LABEL,		PSW(5),	NULL },
X	{ "IE",		LABEL,		IE(0),	NULL },
X	{ "IE0",	LABEL,		TCON(1),NULL },
X	{ "IE1",	LABEL,		TCON(3),NULL },
X	{ "IP",		LABEL,		IP(0),	NULL },
X	{ "IT0",	LABEL,		TCON(0),NULL },
X	{ "IT1",	LABEL,		TCON(2),NULL },
X	{ "OV",		LABEL,		PSW(2),	NULL },
X	{ "P",		LABEL,		PSW(0),	NULL },
X	{ "P0",		LABEL,		P0(0),	NULL },
X	{ "P1",		LABEL,		P1(0),	NULL },
X	{ "P2",		LABEL,		P2(0),	NULL },
X	{ "P3",		LABEL,		P3(0),	NULL },
X	{ "PCON",	LABEL,		0x87,	NULL },
X	{ "PS",		LABEL,		IP(4),	NULL },
X	{ "PSW",	LABEL,		PSW(0),	NULL },
X	{ "PT0",	LABEL,		IP(1),	NULL },
X	{ "PT1",	LABEL,		IP(3),	NULL },
X	{ "PT2",	LABEL,		IP(5),	NULL },
X	{ "PX0",	LABEL,		IP(0),	NULL },
X	{ "PX1",	LABEL,		IP(2),	NULL },
X	{ "RB8",	LABEL,		SCON(2),NULL },
X	{ "RCAP2H",	LABEL,		0xCB,	NULL },
X	{ "RCAP2L",	LABEL,		0xCA,	NULL },
X	{ "RCLK",	LABEL,		T2CON(5),NULL },
X	{ "REN",	LABEL,		SCON(4),NULL },
X	{ "RI",		LABEL,		SCON(0),NULL },
X	{ "RL2",	LABEL,		T2CON(0),NULL },
X	{ "RS0",	LABEL,		PSW(3),	NULL },
X	{ "RS1",	LABEL,		PSW(4),	NULL },
X	{ "SBUF",	LABEL,		0x99,	NULL },
X	{ "SCON",	LABEL,		SCON(0),NULL },
X	{ "SM0",	LABEL,		SCON(7),NULL },
X	{ "SM1",	LABEL,		SCON(6),NULL },
X	{ "SM2",	LABEL,		SCON(5),NULL },
X	{ "SP",		LABEL,		0x81,	NULL },
X	{ "T2CON",	LABEL,		T2CON(0),NULL },
X	{ "TB8",	LABEL,		SCON(3),NULL },
X	{ "TCLK",	LABEL,		T2CON(4),NULL },
X	{ "TCON",	LABEL,		TCON(0),NULL },
X	{ "TF0",	LABEL,		TCON(5),NULL },
X	{ "TF1",	LABEL,		TCON(7),NULL },
X	{ "TF2",	LABEL,		T2CON(7),NULL },
X	{ "TH0",	LABEL,		0x8C,	NULL },
X	{ "TH1",	LABEL,		0x8D,	NULL },
X	{ "TH2",	LABEL,		0xCD,	NULL },
X	{ "TI",		LABEL,		SCON(1),NULL },
X	{ "TL0",	LABEL,		0x8A,	NULL },
X	{ "TL1",	LABEL,		0x8B,	NULL },
X	{ "TL2",	LABEL,		0xCC,	NULL },
X	{ "TMOD",	LABEL,		0x89,	NULL },
X	{ "TR0",	LABEL,		TCON(4),NULL },
X	{ "TR1",	LABEL,		TCON(6),NULL },
X	{ "TR2",	LABEL,		T2CON(2),NULL }
X};
X
X#define SINITSIZE	(sizeof(sinit)/sizeof(sinit[0]))
X
X/* ----------------------------------------------------------------------
X * opcode vectors:
X *	These arrays contain the various opcodes for the
X *	various forms an instruction may take.
X *
X *	The ordering of these opcodes is very critical to the
X *	proper fuctioning of the assembler.
X *
X *	When a given form of an instruction is parsed, the parser
X *	indexes one of these arrays by the correct amount and thus
X *	obtains the correct opcode for the particular form.
X *
X */
X
Xstatic unsigned char acall[]=	{ 0x11 };
Xstatic unsigned char add[]=	{ 0x28, 0x25, 0x26, 0x24 };
Xstatic unsigned char addc[]=	{ 0x38, 0x35, 0x36, 0x34 };
Xstatic unsigned char ajmp[]=	{ 0x01 };
Xstatic unsigned char anl[]=	{ 0x58, 0x55, 0x56, 0x54, 0x52, 0x53, 0x82,
X				  0xb0 };
Xstatic unsigned char cjne[]=	{ 0xb5, 0xb4, 0xb8, 0xb6 };
Xstatic unsigned char clr[]=	{ 0xe4, 0xc3, 0xc2 };
Xstatic unsigned char cpl[]=	{ 0xf4, 0xb3, 0xb2 };
Xstatic unsigned char da[]=	{ 0xd4 };
Xstatic unsigned char dec[]=	{ 0x14, 0x18, 0x15, 0x16 };
Xstatic unsigned char div[]=	{ 0x84 };
Xstatic unsigned char djnz[]=	{ 0xd8, 0xd5 };
Xstatic unsigned char inc[]=	{ 0x04, 0x08, 0x05, 0x06, 0xa3 };
Xstatic unsigned char jb[]=	{ 0x20 };
Xstatic unsigned char jbc[]=	{ 0x10 };
Xstatic unsigned char jc[]=	{ 0x40 };
Xstatic unsigned char jmp[]=	{ 0x73 };
Xstatic unsigned char jnb[]=	{ 0x30 };
Xstatic unsigned char jnc[]=	{ 0x50 };
Xstatic unsigned char jnz[]=	{ 0x70 };
Xstatic unsigned char jz[]=	{ 0x60 };
Xstatic unsigned char lcall[]=	{ 0x12 };
Xstatic unsigned char ljmp[]=	{ 0x02 };
Xstatic unsigned char mov[]=	{ 0xe8, 0xe5, 0xe6, 0x74, 0xf5, 0x75, 0xf8,
X				  0xa8, 0x78, 0x88, 0x85, 0x86, 0xf6, 0xa6,
X				  0x76, 0x90, 0xa2, 0x92 };
Xstatic unsigned char movc[]=	{ 0x93, 0x83 };
Xstatic unsigned char movx[]=	{ 0xe2, 0xe3, 0xe0, 0xf2, 0xf3, 0xf0 };
Xstatic unsigned char mul[]=	{ 0xa4 };
Xstatic unsigned char nop[]=	{ 0x00 };
Xstatic unsigned char orl[]=	{ 0x48, 0x45, 0x46, 0x44, 0x42, 0x43, 0x72,
X				  0xa0 };
Xstatic unsigned char pop[]=	{ 0xd0 };
Xstatic unsigned char push[]=	{ 0xc0 };
Xstatic unsigned char ret[]=	{ 0x22 };
Xstatic unsigned char reti[]=	{ 0x32 };
Xstatic unsigned char rl[]=	{ 0x23 };
Xstatic unsigned char rlc[]=	{ 0x33 };
Xstatic unsigned char rr[]=	{ 0x03 };
Xstatic unsigned char rrc[]=	{ 0x13 };
Xstatic unsigned char setb[]=	{ 0xd3, 0xd2 };
Xstatic unsigned char sjmp[]=	{ 0x80 };
Xstatic unsigned char subb[]=	{ 0x98, 0x95, 0x96, 0x94 };
Xstatic unsigned char swap[]=	{ 0xc4 };
Xstatic unsigned char xch[]=	{ 0xc8, 0xc5, 0xc6 };
Xstatic unsigned char xchd[]=	{ 0xd6 };
Xstatic unsigned char xrl[]=	{ 0x68, 0x65, 0x66, 0x64, 0x62, 0x63 };
X
X/* ----------------------------------------------------------------------
X * optable[]
X *	This table contains opcodes, directives and a few reserved
X *	symbols.
X *
X *	The second field is the keywords token value.
X *
X *	Unless the symbol is an opcode, the third field will
X *	be NULL.
X * 
X *	The third field is a pointer to an array of opcode bytes.
X *
X */
X
Xstatic struct opcode optable[] = {
X	{"a",		A,	NULL		},
X	{"ab",		AB,	NULL		},
X	{"acall",	ACALL,	acall		},
X	{"add",		ADD,	add		},
X	{"addc",	ADDC,	addc		},
X	{"ajmp",	AJMP,	ajmp		},
X	{"anl",		ANL,	anl		},
X	{"byte",	D_BYTE,	NULL		},
X	{"c",		C,	NULL		},
X	{"cjne",	CJNE,	cjne		},
X	{"clr",		CLR,	clr		},
X	{"cpl",		CPL,	cpl		},
X	{"da",		DA,	da		},
X	{"dec",		DEC,	dec		},
X	{"div",		DIV,	div		},
X	{"djnz",	DJNZ,	djnz		},
X	{"dptr",	DPTR,	NULL		},
X	{"end",		D_END,	NULL		},
X	{"equ",		D_EQU,	NULL		},
X	{"flag",	D_FLAG,	NULL		},
X	{"inc",		INC,	inc		},
X	{"jb",		JB,	jb		},
X	{"jbc",		JBC,	jbc		},
X	{"jc",		JC,	jc		},
X	{"jmp",		JMP,	jmp		},
X	{"jnb",		JNB,	jnb		},
X	{"jnc",		JNC,	jnc		},
X	{"jnz",		JNZ,	jnz		},
X	{"jz",		JZ,	jz		},
X	{"lcall",	LCALL,	lcall		},
X	{"ljmp",	LJMP,	ljmp		},
X	{"mov",		MOV,	mov		},
X	{"movc",	MOVC,	movc		},
X	{"movx",	MOVX,	movx		},
X	{"mul",		MUL,	mul		},
X	{"nop",		NOP,	nop		},
X	{"org",		D_ORG,	NULL		},
X	{"orl",		ORL,	orl		},
X	{"pc",		PC,	NULL		},
X	{"pop",		POP,	pop		},
X	{"push",	PUSH,	push		},
X	{"r0",		R0,	NULL		},
X	{"r1",		R1,	NULL		},
X	{"r2",		R2,	NULL		},
X	{"r3",		R3,	NULL		},
X	{"r4",		R4,	NULL		},
X	{"r5",		R5,	NULL		},
X	{"r6",		R6,	NULL		},
X	{"r7",		R7,	NULL		},
X	{"ret",		RET,	ret		},
X	{"reti",	RETI,	reti		},
X	{"rl",		RL,	rl		},
X	{"rlc",		RLC,	rlc		},
X	{"rr",		RR,	rr		},
X	{"rrc",		RRC,	rrc		},
X	{"setb",	SETB,	setb		},
X	{"sjmp",	SJMP,	sjmp		},
X	{"skip",	D_SKIP,	NULL		},
X	{"subb",	SUBB,	subb		},
X	{"swap",	SWAP,	swap		},
X	{"word",	D_WORD,	NULL		},
X	{"xch",		XCH,	xch		},
X	{"xchd",	XCHD,	xchd		},
X	{"xrl",		XRL,	xrl		}
X};
X
X#define OPTABSIZE	(sizeof(optable)/sizeof(struct opcode))
X
X/* ----------------------------------------------------------------------
X * strcase:
X *	A case IN-sensitive string compare.
X *
X */
X
Xstrcase(s,t)
Xchar *s,*t;
X{
X	for( ; (*s|040) == (*t|040); s++, t++)
X		if( *s == '\0') return(0);
X	return( (*s|040) - (*t|040) );
X}
X
X/* ----------------------------------------------------------------------
X * lookop:
X *	Do a binary search through optable[], for a matching
X *	symbol. Return the symbol found or NULL.
X *
X */
X
Xstruct opcode *lookop(s)
Xchar *s;
X{
X	register int low,high,mid,cond;
X
X	low = 0;
X	high = OPTABSIZE-1;
X	while( low<=high ) {
X		mid = (low+high)/2;
X		if( (cond = strcase(s,optable[mid].name)) < 0 )
X			high = mid-1;
X		else if(cond > 0 )
X			low = mid+1;
X		else
X			return(&optable[mid]);
X	}
X	return(NULL);
X}
X
X/* ----------------------------------------------------------------------
X * symtab, hash, looksym:
X *	User symbol table routines.
X *	symtab is the hash table for the user symbols.
X *	(chaining is used for collision resolution).
X *
X */
X
Xstatic struct symbol *symtab[HASHTABSIZE];
X
Xstatic hash(s)
Xchar *s;
X{
X	register char *p;
X	register unsigned h=0,g;
X	for(p=s; *p; p++) {
X		h = (h<<4) + *p;
X		if( g = h&0xf0000000 ) {
X			h = h ^ (g >> 24);
X			h = h ^ g;
X		}
X	}
X	return( h % HASHTABSIZE );
X}
X
Xstruct symbol *looksym(s)
Xchar *s;
X{
X	register struct symbol *ptr,*prev;
X	char *malloc(),*p;
X	register int hv;
X
X	hv = hash(s);
X
X	prev = NULL;
X	for(ptr=symtab[hv]; ptr; ptr = ptr->next) {
X		if( !strcmp(ptr->name,s) ) {
X			if( prev != NULL ) {
X				prev->next = ptr->next;
X				ptr->next = symtab[hv];
X				symtab[hv] = ptr;
X			}
X			return(ptr);
X		}
X		prev = ptr;
X	}
X
X	if( p = malloc(strlen(s)+1) )
X		strcpy(p,s);
X	else
X		error("Cannot allocate %d bytes",strlen(s)+1);
X
X	ptr = (struct symbol *) malloc( sizeof(struct symbol) );
X	if( ptr == NULL )
X		error("Cannot allocate %d bytes",sizeof(struct symbol));
X	ptr->name = p;
X	ptr->type = UNDEF;
X	ptr->next = symtab[hv];
X	symtab[hv] = ptr;
X	return(ptr);
X}
X
X/* ----------------------------------------------------------------------
X * syminit:
X *	Initializes the hash table, with the initial symbols from
X *	sinit[]
X *
X */
X
Xsyminit()
X{
X	register int i,hv;
X
X	for(i=0; i<SINITSIZE; i++ ) {
X		hv = hash(sinit[i].name);
X		if( symtab[hv] )
X			sinit[i].next = symtab[hv];
X		symtab[hv] = &sinit[i];
X	}
X}
END_OF_FILE
if test 10609 -ne `wc -c <'symbol.c'`; then
    echo shar: \"'symbol.c'\" unpacked with wrong size!
fi
# end of 'symbol.c'
fi
if test -f 'new.asm' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'new.asm'\"
else
echo shar: Extracting \"'new.asm'\" \(10618 characters\)
sed "s/^X//" >'new.asm' <<'END_OF_FILE'
X; -----------------------------------------------------------------------
X; -		debugger v2.0 theo de raadt 21/1/90			-
X; NOTE: Hardware has to be specially built to handle this monitor.
X; The CODE address space and the DATA address space have to be mapped
X; on top of each other. ie. CHIP_READ* = 8031RD* AND 8031PSEN* and
X; CHIP_WRITE* = 8031WR*.
X; Within this (combined) address space, you can now use either MOVX
X; or MOVC for the same effect.
X; In this address space, I have placed the rom this debugger is in
X; at 0x0000 and ram at 0x8000. (additional IO would go in between.)
X; (actually, I used a battery backed up static ram at 0x000.)
X; Some of the commands in the help are actually unimplimented. It
X; suited my purposes. The 'g' command could be much improved, to have
X; a seperate register set for the called routine.
X; -----------------------------------------------------------------------
X
X		.org	0
Xstart:		nop			; for accidental overwrite if ram
X					; at 0 -- bug in my decode logic?
X		mov	P3, #0xff	; use alternate fns on P3
X		ajmp	main
X
X; -----------------------------------------------------------------------
X; SERINIT() nothing hurt
Xserinit:	mov	TMOD, #0x20	; timer 1 mode 2
X	;	mov	TH1, #230	; 1200 baud
X		mov	TH1,#243	; 4800 baud
X		mov	TCON, #0x40	; turn timer 1 on
X		mov	SCON, #0x52	; serial mode 1 rx, fake tx done
X
X		mov	A, PCON		; for 4800 baud
X		setb	ACC.7
X		mov	PCON, A
X		ret
X
X; -----------------------------------------------------------------------
X; PUTC( A=char )
Xputc:		jnb	TI, putc	; wait for tx free
X		clr	TI
X		mov	SBUF, A		; send it
X		ret
X
X; -----------------------------------------------------------------------
X; GETC() A=char
Xgetc:		jnb	RI, getc
X		clr	RI
X		mov	A, SBUF
X		ret
X
X; -----------------------------------------------------------------------
X; GETS( DPTR=start of string ) A not hurt, DPTR at start of string
Xgets:		push	ACC
X		push	DPL
X		push	DPH
X		mov	A, R3
X		push	ACC
X
X		clr	A
X		mov	R3, A
Xgets_nxt:	lcall	getc
X		cjne	A, #8, gets_notbs
X		ajmp	gets_bs
Xgets_notbs:	cjne	A, #'\r', gets_good
X		clr	A
X		movx	@DPTR, A
X
X		pop	ACC
X		mov	R3, A
X		pop	DPH
X		pop	DPL
X		pop	ACC
X		ret
X
Xgets_bs:	mov	A, R3		; backspaced too far
X		jz	gets_nxt
X		dec	A
X		mov	R3, A
X
X		mov	A, #8		; "\b \b"
X		lcall	putc
X		mov	A, #' '
X		lcall	putc
X		mov	A, #8
X		lcall	putc
X
X		setb	C		; this is "dec DPTR"
X		mov	A, DPL
X		subb	A, #0
X		mov	DPL, A
X		mov	A, DPH
X		subb	A, #0
X		mov	DPH, A
X		ajmp	gets_nxt
X
Xgets_good:	movx	@DPTR, A
X		lcall	putc
X		inc	DPTR
X		inc	R3
X		ajmp	gets_nxt
X
X; ----------------------------------------------------------------------
X; HEXPARSE( DPTR=string ) A not hurt, DPTR advanced, R0/R1 [H/L] return
Xhexparse:	push	ACC
X
Xhp_char:	movx	A, @DPTR	; get char
X
X		clr	C
X		subb	A, #'a'
X		jc	hp_notalpha	; < 'a' not hex alpha char
X		subb	A, #5+1
X		jnc	hp_notalpha	; > 'f' not hex aplha char
X		movx	A, @DPTR
X		clr	C
X		subb	A, #'a'-10
X		sjmp	hp_nybble
X
Xhp_notalpha:	movx	A, @DPTR
X		clr	C
X		subb	A, #'0'
X		jc	hp_notdigit	; < '0' not hex digit
X		subb	A, #9+1
X		jnc	hp_notdigit	; > '9' not hex digit
X		movx	A, @DPTR
X		clr	C
X		subb	A, #'0'
X
Xhp_nybble:	inc	DPTR
X
X		anl	A, #0x0f
X		push	ACC		;     R0       R1
X		mov	A, R0		;  HHHH LLLL hhhh llll
X		swap	A
X		anl	A, #0xf0
X		mov	R0, A
X		mov	A, R1
X		swap	A		; shift left by nybble
X		anl	A, #0x0f
X		orl	A, R0
X		mov	R0, A
X		mov	A, R1
X		swap	A
X		anl	A, #0xf0
X		mov	R1, A
X		pop	ACC
X		orl	A, R1
X		mov	R1, A		;  LLLL hhhh llll aaaa
X
X	;	debugging
X	;	push	ACC
X	;	push	DPL
X	;	push	DPH
X	;	mov	DPH, R0
X	;	mov	DPL, R1
X	;	lcall	putword
X	;	lcall	putnl
X	;	pop	DPH
X	;	pop	DPL
X	;	pop	ACC
X
X		sjmp	hp_char
X
Xhp_notdigit:	pop	ACC
X		ret
X
X; ----------------------------------------------------------------------
X; EATSPACE( DPTR=string ) A not hurt, DPTR advanced
Xeatspace:	push	ACC
Xeatspace_loop:	movx	A, @DPTR
X		cjne	A, #' ', eatspace_done
X		inc	DPTR
X		sjmp	eatspace_loop
Xeatspace_done:	pop	ACC
X		ret
X
X; -----------------------------------------------------------------------
X; PUTS( DPTR=string ) A not hurt, DPTR at end of string
Xputs:		push	ACC
Xputs_ch:	movx	A, @DPTR	; get ch
X		jz	puts_q		; null - finished str
X		lcall	putc
X		inc	DPTR
X		sjmp	puts_ch		; go for next
Xputs_q:		pop	ACC
X		ret
X
X; -----------------------------------------------------------------------
X; PUTNL() nothing hurt
Xputnl:		push	ACC
X		mov	A, #0x0d
X		lcall	putc
X		mov	A, #0x0a
X		lcall	putc
X		pop	ACC
X		ret
X
X; -----------------------------------------------------------------------
X; putword( DPTR=word) nothing hurt
Xputword:	push	ACC
X		mov	A, DPH
X		lcall	putbyte
X		mov	A, DPL
X		lcall	putbyte
X		pop	ACC
X		ret
X
X; -----------------------------------------------------------------------
X; putbyte( A=byte) nothing hurt
Xputbyte:	push	ACC
X		push	ACC
X		swap	A
X		lcall	putnyb
X		pop	ACC
X		lcall	putnyb
X		pop	ACC
X		ret
X
X; -----------------------------------------------------------------------
X; putnyb( A=nybble ) A hurt
Xputnyb:		anl	A, #0x0f
X		push	ACC
X		clr	C
X		subb	A, #10
X		jc	pn_digit	; <= 9, then it's a digit
X		add	A, #'a'		; alphabetic
X		lcall	putc
X		pop	ACC
X		ret
X
Xpn_digit:	pop	ACC		; it's a digit
X		add	A, #'0'
X		lcall	putc
X		ret
X
X; -----------------------------------------------------------------------
Xmain:		lcall	serinit
X		mov	DPTR, #run_regs_psw	; initialize psw at least!
X		clr	A
X		movx	@DPTR, A
X		mov	DPTR, #title_msg
X		lcall	puts
X
Xnext_line:	mov	A, #'>'		; prompt
X		lcall	putc
X
X		mov	DPTR, #linebuf	; get cmd
X		lcall	gets
X		lcall	putnl
X
Xnext_cmd:	lcall	eatspace
X		movx	A, @DPTR
X		jz	next_line
X
X		; --------------------------------------------------
X		cjne	A, #'g', cmd_notgo	; g --> lcall addr..
X		push	DPL
X		push	DPH
X		push	ACC
X		push	PSW
X
X		mov	DPTR, #go_return	; come back to here..
X		push	DPL
X		push	DPH
X
X		mov	A, R1			; return on top of function
X		push	ACC
X		mov	A, R0
X		push	ACC
X		mov	DPTR, #run_regs
X		movx	A, @DPTR		; DPH
X		push	ACC
X		inc	DPTR
X		movx	A, @DPTR		; DPL
X		push	ACC
X		inc	DPTR
X		movx	A, @DPTR		; PSW
X		push	ACC
X		inc	DPTR
X		movx	A, @DPTR		; ACC
X		pop	PSW
X		pop	DPL
X		pop	DPH
X		ret				; enter it
X
Xgo_return:	pop	PSW
X		pop	ACC
X		pop	DPH
X		pop	DPL
X		inc	DPTR
X		sjmp	next_cmd
X
X		; --------------------------------------------------
Xcmd_notgo:	cjne	A, #'R', cmd_notregs
X		inc	DPTR
X		push	DPH
X		push	DPL
X		mov	DPTR, #regs_msg		; "DPTR ACC PSW"
X		lcall	puts
X		mov	DPTR, #run_regs
X		movx	A, @DPTR
X		acall	putbyte			;  xx
X		inc	DPTR
X		movx	A, @DPTR
X		acall	putbyte			;    xx
X		mov	A, #' '
X		acall	putc
X		inc	DPTR
X		movx	A, @DPTR
X		acall	putbyte			;       xx
X		inc	DPTR
X		mov	A, #' '
X		acall	putc
X		acall	putc
X		movx	A, @DPTR
X		acall	putbyte			;           xx
X		acall	putnl
X		pop	DPL
X		pop	DPH
X		sjmp	next_cmd
X
X		; --------------------------------------------------
Xcmd_notregs:	cjne	A, #':', cmd_notenter	; : --> eat bytes..
X		inc	DPTR
X		mov	A, R2
X		push	ACC
X		mov	A, R3
X		push	ACC
X		mov	A, R0
X		mov	R2, A
X		mov	A, R1
X		mov	R3, A		; R2/R3 = mem ptr
X
Xenter_next:	lcall	eatspace
X		movx	A, @DPTR
X		jz	enter_done
X
X		push	DPL
X		clr	A
X		mov	R0, A
X		mov	R1, A
X		lcall	hexparse
X		pop	ACC
X		cjne	A, DPL, enter_number
X		sjmp	enter_next
X
Xenter_number:	push	DPL
X		push	DPH
X		mov	DPH, R2		; put low byte only
X		mov	DPL, R3
X		mov	A, R1
X		movx	@DPTR, A
X		inc	DPTR
X		mov	R2, DPH
X		mov	R3, DPL
X		pop	DPH
X		pop	DPL
X		sjmp	enter_next
X
Xenter_done:	pop	ACC
X		mov	R3, A
X		pop	ACC
X		mov	R2, A
X		ajmp	next_cmd
X
X		; --------------------------------------------------
Xcmd_notenter:	cjne	A, #'?', cmd_nothelp
X		push	DPL
X		push	DPH
X		mov	DPTR, #help_msg
X		lcall	puts
X		pop	DPH
X		pop	DPL
X		inc	DPTR
X		ajmp	next_cmd
X
X		; --------------------------------------------------
Xcmd_nothelp:	cjne	A, #'l', cmd_notlist
X		push	DPL
X		push	DPH
X		push	B
X		clr	A
X		mov	B, ACC
X		mov	DPH, R0
X		mov	DPL, R1
X		lcall	putword		; addr: [16 bytes]
X		mov	A, #':'
X		lcall	putc
X		mov	A, #' '
X		lcall	putc
Xcl_nextbyte:	movx	A, @DPTR
X		lcall	putbyte
X		mov	A, #' '
X		lcall	putc
X		inc	DPTR
X		inc	B
X		mov	A, B
X		cjne	A, #16, cl_nextbyte
X		lcall	putnl
X		mov	R0, DPH
X		mov	R1, DPL
X		pop	B
X		pop	DPH
X		pop	DPL
X		inc	DPTR
X		ajmp	next_cmd
X
X		; --------------------------------------------------
Xcmd_notlist:	cjne	A, #'r', cmd_notread
X		mov	A, R3		; counter
X		push	ACC
X		mov	A, R1		; base addr
X		push	ACC
X
X		inc	DPTR		; get arg
X		lcall	eatspace
X		push	DPL
X		lcall	hexparse
X		pop	ACC
X		cjne	A, DPL, nl_loop
X		mov	A, #1
X		mov	R3, A
X		sjmp	nl_start
Xnl_loop:	mov	A, R1
X		mov	R3, A
X		
Xnl_start:	pop	ACC
X		mov	R1, A
X		mov	A, R1		; put address
X		lcall	putbyte
X		mov	A, #':'
X		lcall	putc
X
Xnl_nextloop:	mov	A, R3		; eat one loop
X		jz	nl_endloop
X		dec	A
X		mov	R3, A
X
X		mov	A, #' '
X		lcall	putc
X		mov	A, @R1		; put byte
X		lcall	putbyte
X		inc	R1		; inc address
X
X		sjmp	nl_nextloop
X
Xnl_endloop:	lcall	putnl
X		pop	ACC
X		mov	R3, A
X		ajmp	next_cmd
X
X		; --------------------------------------------------
Xcmd_notread:	cjne	A, #'w', cmd_notwrite
X		mov	A, R3
X		push	ACC
X		mov	A, R1
X		mov	R3, A		; save addr
X		inc	DPTR
X
Xnr_nextbyte:	lcall	eatspace
X		movx	A, @DPTR
X		jz	nr_earlyeol	; [addr] w [EOL]
X		push	DPL
X		lcall	hexparse	; [addr] w [NONHEX]
X		pop	ACC
X		cjne	A, DPL, nr_good
X		sjmp	nr_earlyeol
X
Xnr_good:	mov	A, R3		; R1 = value, R3 = addr
X		mov	R0, A
X		mov	A, R1
X		mov	@R0, A
X		ajmp	nr_nextbyte
X
Xnr_earlyeol:	pop	ACC
X		mov	R3, A
X		ajmp	next_cmd
X
X		; --------------------------------------------------
Xcmd_notwrite:	cjne	A, #';', cmd_notcomment
X		ajmp	next_line
X
Xcmd_notcomment:	push	DPL
X		clr	A
X		mov	R0, A
X		mov	R1, A
X		lcall	hexparse		; probably addr, see if ptr
X		pop	ACC			; moved, else error
X		cjne	A, DPL, cmd_more
X		sjmp	cmd_error
X
X		; --------------------------------------------------
Xcmd_more:
X	;	debugging
X	;	push	DPL
X	;	push	DPH
X	;	mov	DPTR, #number_msg
X	;	lcall	puts
X	;	mov	DPH, R0
X	;	mov	DPL, R1
X	;	lcall	putword
X	;	lcall	putnl
X	;	pop	DPH
X	;	pop	DPL
X		ajmp	next_cmd
X
Xcmd_error:	mov	DPTR, #error_msg
X		lcall	puts
X		ajmp	next_line
X
X; -----------------------------------------------------------------------
Xtitle_msg:	.byte	"\r\n8031 mon v3.0\r\n", 0
Xerror_msg:	.byte	"syntax error\r\n", 0
Xregs_msg:	.byte	"DPTR ACC PSW\r\n", 0
Xhelp_msg:	.byte	"8031 mon v3.0\r\n"
X		.byte	"[addr] : [bytes]\tstore bytes\t"
X		.byte	"[addr] g\t\tcall address\r\n"
X		.byte	"[addr] l\t\tlist memory\t"
X		.byte	"[addr] r [count]\tlist onchip\r\n"
X		.byte	"[addr] w [bytes]\tstore onchip\t"
X		.byte	"; [comment]\t\tcomment\r\n"
X		.byte	"[value] D\t\tstore in DPTR\t"
X		.byte	"[value] A\t\tstore in ACC\r\n"
X		.byte	"[value] P\t\tstore in PSW\t"
X		.byte	"R\t\t\tprint registers\r\n", 0
X
X; -----------------------------------------------------------------------
X; sort of a bss segment
X; -----------------------------------------------------------------------
X		.org	0x8000
Xrun_regs:	.skip	2		; DPTR [H/L]
Xrun_regs_psw:	.skip	1		; PSW
X		.skip	1		; ACC
Xlinebuf:	.skip	256
X
X		.end
END_OF_FILE
if test 10618 -ne `wc -c <'new.asm'`; then
    echo shar: \"'new.asm'\" unpacked with wrong size!
fi
# end of 'new.asm'
fi
echo shar: End of shell archive.
exit 0



More information about the Comp.sources.misc mailing list