Category : Assembly Language Source Code
Archive   : 68XASM.ZIP
Filename : OPPARSE.C
*
* OPPARSE.C
* Operand Parser for 68000 Assembler
*
* Function: opParse()
* Parses an operand of the 68000 assembly language
* instruction and attempts to recognize its addressing
* mode. The p argument points to the string to be
* evaluated, and the function returns a pointer to the
* first character beyond the end of the operand.
* The function returns a description of the operands that
* it parses in an opDescriptor structure. The fields of
* the operand descriptor are filled in as appropriate for
* the mode of the operand that was found:
*
* mode returns the address mode (symbolic values
* defined in ASM.H)
* reg returns the address or data register number
* data returns the displacement or address or
* immediate value
* backRef TRUE if data is the value of an expression
* that contains only constants and backwards
* references; FALSE otherwise.
* index returns the index register
* (0-7 = D0-D7, 8-15 = A0-A7)
* size returns the size to be used for the index
* register
*
* The argument errorPtr is used to return an error code
* via the standard mechanism.
*
* Usage: char *opParse(p, d, errorPtr)
* char *p;
* opDescriptor *d;
* int *errorPtr;
*
* Author: Paul McKee
* ECE492 North Carolina State University
*
* Date: 10/10/86
*
* Revision: 10/26/87
* Altered the immediate mode case to correctly flag
* constructs such as "#$1000(A5)" as syntax errors.
*
************************************************************************/
#include
#include
#include "asm.h"
extern char pass2;
#define isTerm(c) (isspace(c) || (c == ',') || c == '\0')
#define isRegNum(c) ((c >= '0') && (c <= '7'))
char *opParse(p, d, errorPtr)
char *p;
opDescriptor *d;
int *errorPtr;
{
/* Check for immediate mode */
if (p[0] == '#') {
p = eval(++p, &(d->data), &(d->backRef), errorPtr);
/* If expression evaluates OK, then return */
if (*errorPtr < SEVERE) {
if (isTerm(*p)) {
d->mode = Immediate;
return p;
}
else {
NEWERROR(*errorPtr, SYNTAX);
return NULL;
}
}
else
return NULL;
}
/* Check for address or data register direct */
if (isRegNum(p[1]) && isTerm(p[2])) {
if (p[0] == 'D') {
d->mode = DnDirect;
d->reg = p[1] - '0';
return (p + 2);
}
else if (p[0] == 'A') {
d->mode = AnDirect;
d->reg = p[1] - '0';
return (p + 2);
}
}
/* Check for Stack Pointer (i.e., A7) direct */
if (p[0] == 'S' && p[1] == 'P' && isTerm(p[2])) {
d->mode = AnDirect;
d->reg = 7;
return (p + 2);
}
/* Check for address register indirect */
if (p[0] == '(' &&
((p[1] == 'A' && isRegNum(p[2])) || (p[1] == 'S' && p[2] == 'P'))) {
if (p[1] == 'S')
d->reg = 7;
else
d->reg = p[2] - '0';
if (p[3] == ')') {
/* Check for plain address register indirect */
if (isTerm(p[4])) {
d->mode = AnInd;
return p+4;
}
/* Check for postincrement */
else if (p[4] == '+') {
d->mode = AnIndPost;
return p+5;
}
}
/* Check for address register indirect with index */
else if (p[3] == ',' && (p[4] == 'A' || p[4] == 'D')
&& isRegNum(p[5])) {
d->mode = AnIndIndex;
/* Displacement is zero */
d->data = 0;
d->backRef = TRUE;
d->index = p[5] - '0';
if (p[4] == 'A')
d->index += 8;
if (p[6] == '.')
/* Determine size of index register */
if (p[7] == 'W') {
d->size = WORD;
return p+9;
}
else if (p[7] == 'L') {
d->size = LONG;
return p+9;
}
else {
NEWERROR(*errorPtr, SYNTAX);
return NULL;
}
else if (p[6] == ')') {
/* Default index register size is Word */
d->size = WORD;
return p+7;
}
else {
NEWERROR(*errorPtr, SYNTAX);
return NULL;
}
}
}
/* Check for address register indirect with predecrement */
if (p[0] == '-' && p[1] == '(' && p[4] == ')' &&
((p[2] == 'A' && isRegNum(p[3])) || (p[2] == 'S' && p[3] == 'P'))) {
if (p[2] == 'S')
d->reg = 7;
else
d->reg = p[3] - '0';
d->mode = AnIndPre;
return p+5;
}
/* Check for PC relative */
if (p[0] == '(' && p[1] == 'P' && p[2] == 'C') {
/* Displacement is zero */
d->data = 0;
d->backRef = TRUE;
/* Check for plain PC relative */
if (p[3] == ')') {
d->mode = PCDisp;
return p+4;
}
/* Check for PC relative with index */
else if (p[3] == ',' && (p[4] == 'A' || p[4] == 'D')
&& isRegNum(p[5])) {
d->mode = PCIndex;
d->index = p[5] - '0';
if (p[4] == 'A')
d->index += 8;
if (p[6] == '.')
/* Determine size of index register */
if (p[7] == 'W') {
d->size = WORD;
return p+9;
}
else if (p[7] == 'L') {
d->size = LONG;
return p+9;
}
else {
NEWERROR(*errorPtr, SYNTAX);
return NULL;
}
else if (p[6] == ')') {
/* Default size of index register is Word */
d->size = WORD;
return p+7;
}
else {
NEWERROR(*errorPtr, SYNTAX);
return NULL;
}
}
}
/* Check for Status Register direct */
if (p[0] == 'S' && p[1] == 'R' && isTerm(p[2])) {
d->mode = SRDirect;
return p+2;
}
/* Check for Condition Code Register direct */
if (p[0] == 'C' && p[1] == 'C' && p[2] == 'R' && isTerm(p[3])) {
d->mode = CCRDirect;
return p+3;
}
/* Check for User Stack Pointer direct */
if (p[0] == 'U' && p[1] == 'S' && p[2] == 'P' && isTerm(p[3])) {
d->mode = USPDirect;
return p+3;
}
/* Check for Source Function Code register direct (68010) */
if (p[0] == 'S' && p[1] == 'F' && p[2] == 'C' && isTerm(p[3])) {
d->mode = SFCDirect;
return p+3;
}
/* Check for Destination Function Code register direct (68010) */
if (p[0] == 'D' && p[1] == 'F' && p[2] == 'C' && isTerm(p[3])) {
d->mode = DFCDirect;
return p+3;
}
/* Check for Vector Base Register direct (68010) */
if (p[0] == 'V' && p[1] == 'B' && p[2] == 'R' && isTerm(p[3])) {
d->mode = VBRDirect;
return p+3;
}
/* All other addressing modes start with a constant expression */
p = eval(p, &(d->data), &(d->backRef), errorPtr);
if (*errorPtr < SEVERE) {
/* Check for absolute */
if (isTerm(p[0])) {
/* Determine size of absolute address (must be long if
the symbol isn't defined or if the value is too big */
if (!d->backRef || d->data > 32767 || d->data < -32768)
d->mode = AbsLong;
else
d->mode = AbsShort;
return p;
}
/* Check for address register indirect with displacement */
if (p[0] == '(' &&
((p[1] == 'A' && isRegNum(p[2])) || (p[1] == 'S' && p[2] == 'P'))) {
if (p[1] == 'S')
d->reg = 7;
else
d->reg = p[2] - '0';
/* Check for plain address register indirect with displacement */
if (p[3] == ')') {
d->mode = AnIndDisp;
return p+4;
}
/* Check for address register indirect with index */
else if (p[3] == ',' && (p[4] == 'A' || p[4] == 'D')
&& isRegNum(p[5])) {
d->mode = AnIndIndex;
d->index = p[5] - '0';
if (p[4] == 'A')
d->index += 8;
if (p[6] == '.')
/* Determine size of index register */
if (p[7] == 'W') {
d->size = WORD;
return p+9;
}
else if (p[7] == 'L') {
d->size = LONG;
return p+9;
}
else {
NEWERROR(*errorPtr, SYNTAX);
return NULL;
}
else if (p[6] == ')') {
/* Default size of index register is Word */
d->size = WORD;
return p+7;
}
else {
NEWERROR(*errorPtr, SYNTAX);
return NULL;
}
}
}
/* Check for PC relative */
if (p[0] == '(' && p[1] == 'P' && p[2] == 'C') {
/* Check for plain PC relative */
if (p[3] == ')') {
d->mode = PCDisp;
return p+4;
}
/* Check for PC relative with index */
else if (p[3] == ',' && (p[4] == 'A' || p[4] == 'D')
&& isRegNum(p[5])) {
d->mode = PCIndex;
d->index = p[5] - '0';
if (p[4] == 'A')
d->index += 8;
if (p[6] == '.')
/* Determine size of index register */
if (p[7] == 'W') {
d->size = WORD;
return p+9;
}
else if (p[7] == 'L') {
d->size = LONG;
return p+9;
}
else {
NEWERROR(*errorPtr, SYNTAX);
return NULL;
}
else if (p[6] == ')') {
/* Default size of index register is Word */
d->size = WORD;
return p+7;
}
else {
NEWERROR(*errorPtr, SYNTAX);
return NULL;
}
}
}
}
/* If the operand doesn't match any pattern, return an error status */
NEWERROR(*errorPtr, SYNTAX);
return NULL;
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
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/