home *** CD-ROM | disk | FTP | other *** search
- #include "a:printf.h"
- #include "a:stdio.h"
- #include "as.h"
-
-
- ldmstm(opskel)
- unsigned opskel;
- {
-
- /*
- process MOVEM, STM, and LDM instructions
- STM <RLIST>,<ADR> LDM <ADR>,<RLIST>
- */
- int i;
-
- if (imode == 1)
- return 3;
-
- if (imode == 3)
- opskel |= 0x40;
-
- /* try picking up a register operand */
-
- op = opnptr;
- rlstdc(&op,&dlist,&alist);
-
- if (dlist == 0 && alist == 0)
- return ldm(opskel);
-
- /* check if destination EA is legal for a STM instruction */
- /* -(An) and CTL alterable addressing modes are legal */
-
- if (op2ea != 3 && op2ea != 5 && op2ea != 0)
- return 3;
-
- /* reformat data and address bitmaps for STM instruction */
-
- if (op2ea == 5) {
-
- /* -(An) requires registers to be backwards in the bitmap */
-
- dlsti = alsti = 0;
- for (i = 0; i < 8; ++i) {
- if (dlist & (1 << i))
- dlsti |= (0x80 >> i);
-
- if (alist & (1 << i))
- alsti |= (0x80 >> i);
- }
-
- alist = dlsti;
- dlist = alsti;
- }
-
- /* build bitmap */
-
- objbuf[2] = ((alist & 0xff) << 8) | (dlist & 0xff);
-
- /* process destination operand */
-
- objwc = 2;
-
- if (op2ea != 0) {
-
- /* simple destination operand */
-
- objbuf[1] = opskel | op2da | ((op2ea - 1) * 8);
- return 1;
- }
-
- /* process complex destination operand */
-
- procop(&opnpt2);
- objbuf[1] = opskel | opnwrd[1];
- objbuf[3] = opnwrd[2];
-
- if (opnwc == 2) {
- objbuf[3] = opnwrd[3];
- objbuf[4] = opnwrd[2];
- }
-
- objwc += opnwc;
- return 1;
- }
-
-
- ldm(opskel)
- unsigned opskel;
- {
- opskel |= 0x400;
-
- /* check if source is legal for LDM instruction */
- /* (An)+ and CTL adrressing modes are legal */
-
- if ((op1ea != 3) && (op1ea != 4) && op1ea != 0)
- return 3;
-
- /* process source operand */
-
- if (op1ea != 0)
- objbuf[1] = opskel | op1da | ((op1ea - 1) * 8);
- else {
- procop(&opnptr);
- objbuf[1] = opskel | opnwrd[1];
- objbuf[2] = opnwrd[2];
-
- if (opnwc == 2) {
- objbuf[2] = opnwrd[3];
- objbuf[3] = opnwrd[2];
- }
-
- objwc += opnwc;
- }
-
- /* process register list */
-
- op = opnpt2;
- rlstdc(&op,&dlist,&alist);
-
- if (dlist == 0 && alist == 0)
- return 3;
-
- /* reformat data and address bitmaps for LDM instruction */
-
- objbuf[++objwc] = ((alist & 0xff) << 8) | (dlist & 0xff);
- return 1;
- }
-
-
- rlstdc(op,dlist,alist)
- unsigned *op,*dlist,*alist;
- {
-
- /*
- this subroutine will attempt to process a register
- list in the source line pointed to by 'op' into
- a pair of words which can be converted into a register
- bitmap for the 'MOVEM' instruction
- */
- unsigned i,streg,grpflg,stregt,regtyp,regnum;
-
- /* initialize default output values */
-
- *alist = *dlist = 0;
- grpflg = FALSE;
-
- /* try to find a register to decode */
-
- while (regtyp = rdecod(op,®num)) {
-
- if (grpflg) {
- if ((streg >= regnum) || (stregt != regtyp))
- break;
-
- /* set bits in register list bitmap */
-
- if (regtyp == 1)
- for (i = streg; i <= regnum; ++i)
- *dlist |= (1 << i);
- else
- for (i = streg; i <= regnum; ++i)
- *alist |= (1 << i);
-
- streg = regnum = 0;
- grpflg = FALSE;
- }
- else {
- /* add an individual register to list */
-
- if (regtyp == 1)
- *dlist |= (1 << regnum);
- else
- if (regtyp == 2)
- *alist |= (1 << regnum);
- }
-
- /* check for '/' */
-
- if (srclne[*op] == '/') {
- if (grpflg)
- break;
-
- ++(*op);
- }
-
- /* check for '-' or end of register list */
-
- else
- if (srclne[*op] == '-') {
- streg = regnum;
- stregt = regtyp;
- grpflg = TRUE;
- ++(*op);
- }
- else
- break;
- }
-
- /* error processing */
-
- if (grpflg) {
- *alist = *dlist = 0;
- return 0;
- }
- else
- return 1;
- }
-
-
- rdecod(op,regnum)
- unsigned *op,*regnum;
- {
-
- /*
- This subroutine returns the register type and number
- if the next two characters in a source line specify registers
-
- regtyp = 0 next two characters don't specify a register
- 1 Data register
- 2 Address register
-
- regnum = register number (0-7)
-
- op = op + 2 unless a register wasn't found
- */
-
- unsigned regtyp;
-
- regtyp = 0;
-
- if (srclne[*op] == 'A' || srclne[*op] == 'S')
- regtyp = 2;
- else
- if (srclne[*op] == 'D')
- regtyp = 1;
- else
- return 0;
-
- ++(*op);
-
- if (srclne[*op] == 'P') {
- *regnum = 7;
- return 2;
- }
-
- if ((srclne[*op] < '0') || (srclne[*op] > '7'))
- return 0;
-
- *regnum = srclne[*op] & 7;
- ++(*op);
-
- return regtyp;
- }
-
-
- procop(op)
- unsigned *op;
- {
-
- /*
- EVALUATE COMPLEX EFFECTIVE ADDRESSES
-
- OUTPUT WORDS:
-
- opnflg 0 IF OPERAND CAN BE USED IN 'QUicK' INSTRUCTioNS
- 1 IF OPERAND CONTAINED A FWD REF SYMBOL
-
- opnwc NUMBER OF BYTES GENERATED (6 MAX)
-
- OPNWRD OPERAND WORDS GENERATED
- FIRST WORD - ADR typE
- NEXT WORD - OPN DATA <LOW WORD>
- NEXT WORD - OPN DATA <HIGH WORD>
- */
-
- long symval,tmpval;
- int imd,amd,nochrs,nval,i,n,isindex,issym;
- unsigned ah,al;
-
- /* ZERO OPERAND RESULT BUFFER */
-
- opnwrd[1] = opnwrd[2] = opnwrd[3] = 0;
-
- /* SET PARSE POINTER TO START OF OPN FOR error PROCESSOR */
-
- scanpt = *op;
-
- /* DEFAULT IS NON-IMMEDIATE MODE */
- /* WITH SUBOPNS ADDED TO ORIG OPN */
-
- imd = opnwc = 0;
- amd = 1;
- opnflg = isindex = issym = FALSE;
- symval = 0l;
-
- /* CHECK FOR '#' <IMMEDIATE MODE> */
-
- if (srclne[*op] == '#') {
- imd = 1;
- ++(*op);
- }
-
- while (srclne[*op] != ',' && srclne[*op] != ' ' &&
- srclne[*op] != '\t' && srclne[*op] != EOS) {
-
- tmpval = 0l;
-
- /* CHECK FOR ASCII LITERAL ' */
-
- if (srclne[*op] == '\'') {
- imd = 1;
- nochrs = 0;
- while (srclne[++(*op)] != '\'') {
- if (++nochrs > 4)
- break;
-
- tmpval = (tmpval << 8) | (long)(srclne[*op]);
- }
-
- if (srclne[*op] == '\'')
- ++(*op);
- }
-
- /* CHECK FOR '*' <PC> */
-
- else if (srclne[*op] == '*') {
- if (amd == 1) {
- symval += pc;
- ++(*op);
- }
- else if (amd == 2) {
- symval -= pc;
- ++(*op);
- }
- else {
- opnwc = 7;
- scanpt = *op;
- return opnwc;
- }
- }
-
- /* CHECK FOR '$' <HEXADECIMAL> */
-
- else if (srclne[*op] == '$') {
-
- /* HEXADECIMAL LITERAL */
-
- while ((srclne[++(*op)] >= '0' &&
- srclne[*op] <= '9') ||
- (srclne[*op] >= 'A' &&
- srclne[*op] <= 'F')) {
- if (srclne[*op] >= '0' &&
- srclne[*op] <= '9')
- nval = srclne[*op] - '0';
- else
- nval = srclne[*op] - '7';
-
- tmpval <<= 4;
- tmpval |= (long)nval;
- }
- }
-
- /* CHECK FOR 0-9 <DECIMAL> */
-
- else if (srclne[*op] >= '0' && srclne[*op] <= '9') {
-
- /* DECIMAL LITERAL */
-
- while (srclne[*op] >= '0' && srclne[*op] <= '9') {
- nval = srclne[*op] - '0';
- tmpval *= 10l;
- tmpval += (long)nval;
- ++(*op);
- }
- }
-
- /* CHECK FOR A-Z <SYMBOLic> */
-
- else if ((srclne[*op] >= 'A' && srclne[*op] <= 'Z') ||
- (srclne[*op] == '@' || srclne[*op] == '_')) {
- opnflg = chksym(imd,op,&tmpval);
- issym = TRUE;
- }
- else if (srclne[*op] != '-' && srclne[*op] != '+') {
- /* not unary + or - */
- scanpt = *op;
- error(406);
- ++(*op);
- }
-
- /* PROCESS +,-,*,/,!,<<,>> */
-
- switch (amd) {
- case 1: symval += tmpval;
- break;
- case 2: symval -= tmpval;
- break;
- case 3: symval *= tmpval;
- break;
- case 4: /* dividing by zero is bad news */
- if (tmpval == 0l) {
- opnwc = 7;
- scanpt = *op;
- return opnwc;
- }
- symval /= tmpval;
- break;
- case 5: symval &= tmpval;
- break;
- case 6: symval |= tmpval;
- break;
- case 7: symval <<= tmpval;
- break;
- case 8: symval >>= tmpval;
- break;
- }
- amd = 1;
-
- /* CHECK FOR +,-,*,/ */
-
- switch (srclne[*op]) {
- case ' ':
- case ',':
- case '\t':
- case EOS: break;
- case '+': amd = 1;
- ++(*op);
- break;
- case '-': amd = 2;
- ++(*op);
- break;
- case '*': amd = 3;
- ++(*op);
- break;
- case '/': amd = 4;
- ++(*op);
- break;
- case '&': amd = 5;
- ++(*op);
- break;
- case '!': amd = 6;
- ++(*op);
- break;
- case '<': ++(*op);
- if (srclne[*op] != '<') {
- opnwc = 7;
- scanpt = *op;
- return opnwc;
- }
-
- amd = 7;
- ++(*op);
- break;
- case '>': ++(*op);
- if (srclne[*op] != '>') {
- opnwc = 7;
- scanpt = *op;
- return opnwc;
- }
- amd = 8;
- ++(*op);
- break;
- case '(': if (chkreg(imd,op,symval) == 7)
- return opnwc;
-
- isindex = TRUE;
- break;
- default: opnwc = 7;
- scanpt = *op;
- return opnwc;
- }
-
- /* go back and CHECK FOR END OF OPERAND */
- }
-
- /* IF BRANCH INSTRUCTION PROC VAL AS PC REL OFFSET */
-
- if (dbflg == 1 ) {
-
- /* GENERATE PC RELATIVE OFFSET */
-
- opnwrd[1] = 0x3a;
- symval = symval - 2l - pc;
- opnwrd[2] = (unsigned)(symval & (long)0xffff);
- opnwrd[3] = (unsigned)((symval >> 16) & (long)0xffff);
- opnwc = 1;
- return opnwc;
- }
-
- /* PROCESS VAL AS PC REL UNLESS ABS OR IMMEDIATE OR 2ND OP */
-
- if (rflg == 0 && imd != 1 && issym && op != &opnpt2 &&
-
- /* IF OPERAND HAD AN EQUATED SYMBOL PROC VAL AS IMMEDIATE */
-
- !(symflg[stind] & 0x10)) {
- tmpval = symval - 2l - pc;
- opnwrd[2] = (unsigned)(tmpval & (long)0xffff);
- opnwrd[3] = (unsigned)((tmpval >> 16) & (long)0xffff);
-
- if ((pass == 2) && (tmpval > (long)0x7fff || tmpval < 0xffff8000)) {
- opnwc = 7;
- error(404);
- return opnwc;
- }
-
- if (isindex) {
- if ((opnwrd[1] & 0x3f) != 0x3b) {
- if (tmpval > 127l || tmpval < -128l) {
- opnwc = 7;
- error(408);
- return opnwc;
- }
-
- opnwrd[2] = opnwrd[2] & 0xff |
- ((opnwrd[1] << 12) & 0x7000) | 0x8000;
- opnwrd[1] = opnwrd[1] & 0xffc0 | 0x3b;
- }
- opnwc = 1;
- return opnwc;
- }
-
- opnwrd[1] = 0x3a;
- opnwc = 1;
- return opnwc;
- }
-
- /* PROCESS IMMEDIATE DATA */
-
- opnwrd[2] = (unsigned)(symval & (long)0xffff);
- opnwrd[3] = (unsigned)((symval >> 16) & (long)0xffff);
-
- if (imd == 1) {
- opnwc = 1;
-
- if (imode == 3)
- opnwc = 2;
-
- opnwrd[1] = 0x3c;
- return opnwc;
- }
-
- /* PROCESS disp(AN) */
-
- if (isindex)
- return opnwc;
-
- /* PROCESS ABSOLUTE ADR */
- /* GENERATE LONG ADR FORM IF INSTR MODE LONG */
-
- if (opnflg != TRUE && opnwrd[3] == 0) {
- opnwc = 1;
- opnwrd[1] = 0x38;
- return opnwc;
- }
-
- opnwc = 2;
- opnwrd[1] = 0x39;
- return opnwc;
- }
-
-
- chksym(imd,op,tmpval)
- int imd,*op;
- long *tmpval;
- {
- char tmpsym[SYMSZ1];
- int n,iop;
-
- for (n = 0,iop = *op; iop < (*op)+SYMSIZ; ++n, ++iop) {
- if ((srclne[iop] >= '0' && srclne[iop] <= '9') ||
- (srclne[iop] >= 'A' && srclne[iop] <= 'Z') ||
- (srclne[iop] == '_' || srclne[iop] == '@'))
- tmpsym[n] = srclne[iop];
- else
- break;
- }
-
- tmpsym[n] = EOS;
- while ((srclne[iop] >= '0' && srclne[iop] <= '9') ||
- (srclne[iop] >= 'A' && srclne[iop] <= 'Z') ||
- (srclne[iop] == '_' || srclne[iop] == '@'))
- ++iop;
-
- *op = iop;
-
- /* SEARCH SYMBOL TBL */
-
- symtbl(1,0l,tmpsym);
-
- /* IF symlin LESS THAN CURRENT LINE AND NOT 0 */
- /* THEN SYMBOL IS DEFINED AND IS NOT A FWD REF*/
-
- if (symlin[stind] > nocard || symlin[stind] == 0)
-
- /* CHECK FOR UNDEFINED SYMBOL */
-
- if (symlin[stind] != 0)
-
- /* WE GET TO HERE IF THE */
- /* SYMBOL IS DEFINED */
- /* BUT WASNT AS OF THIS LINE IN THE */
- /* ASSEMBLY DURING pass ONE */
-
- opnflg = TRUE;
-
- if (symlin[stind] != 0)
-
- /* LABEL HAS BEEN DEFINED */
- /* GET VALUE OF LABEL AND PUT IN tmpval */
-
- *tmpval = symadr[stind];
- else {
-
- /* GO HERE ON UNDEFINED FIRST */
- /* AND SECOND pass SYMBOLS */
-
- if (pass == 2)
- error(407);
-
- /*
- IF THIS IS THE FIRST pass, THEN THE LENGTH
- OF ALL OPERANDS OTHER THAN
- IMMEDIATE BYTE AND WORD
- ARE FORCED TO TWO WORDS
- */
-
- opnflg = TRUE;
-
- if ((imd == 1) && (imode != 3))
- opnwc = 1;
- else
- opnwc = 2;
- }
-
- return opnflg;
- }
-
-
- chkreg(imd,op,symval)
- int imd,*op;
- long symval;
- {
- if (imd == 1) {
- opnwc = 7;
- scanpt = *op;
- return opnwc;
- }
-
- if (srclne[(*op) + 3] == ')') {
-
- /* disp(AN) or disp(DN) */
-
- if ((srclne[(*op)+1] != 'A' && srclne[(*op)+1] != 'D') ||
- srclne[(*op)+2] < '0' ||
- srclne[(*op)+2] > '7') {
- opnwc = 7;
- scanpt = *op;
- return opnwc;
- }
-
- opnwc = 1;
- if (srclne[(*op)+1] == 'D')
- opnwrd[1] = ((srclne[(*op) + 2] - '0') << 12) | 0x3b;
- else
- opnwrd[1] = (srclne[(*op) + 2] - '0') | 0x28;
-
- opnwrd[2] = (unsigned)(symval & (long)0xffff);
- opnwrd[3] = (unsigned)((symval >> 16) & (long)0xffff);
- *op += 4;
- return opnwc;
- }
-
- /* disp(AN,RN.L) or disp(RN.L) */
-
- opnwrd[2] = (unsigned)(symval & (long)0xffff);
- opnwrd[3] = (unsigned)((symval >> 16) & (long)0xffff);
-
- if (symval < -128l || symval > 127l) {
- error(408);
- return opnwc;
- }
-
- opnwrd[2] &= 0xff;
-
- /* imdEX OK..DO THE REST */
-
- if (srclne[(*op) + 3] == '.' && srclne[(*op) + 4] == 'L') {
- opnwc = 1;
- if (srclne[(*op) + 2] != 'A' && srclne[(*op) + 2] != 'D') {
- opnwc = 7;
- scanpt = *op;
- return opnwc;
- }
-
- if (srclne[(*op) + 2] == 'A')
- opnwrd[2] |= 0x8000;
-
- if (srclne[(*op) + 3] < '0' || srclne[(*op) + 3] > '7') {
- opnwc = 7;
- scanpt = *op;
- return opnwc;
- }
-
- opnwrd[2] |= ((srclne[(*op) + 3] - '0') << 12);
- opnwrd[2] |= 0x800;
- *op += 6;
- return opnwc;
- }
-
- opnwc = 1;
-
- if (srclne[(*op)+1] != 'A' || srclne[(*op)+2] < '0' || srclne[(*op)+2] > '7') {
- opnwc = 7;
- scanpt = *op;
- return opnwc;
- }
-
- opnwrd[1] = (srclne[(*op) + 2] - '0') | 0x30;
-
- /* CHECK FOR DATA OR ADR reg */
-
- if (srclne[(*op) + 4] != 'A' && srclne[(*op) + 4] != 'D') {
- opnwc = 7;
- scanpt = *op;
- return opnwc;
- }
-
- if (srclne[(*op) + 4] == 'A')
- opnwrd[2] |= 0x8000;
-
- if (srclne[(*op) + 5] < '0' || srclne[(*op) + 5] > '7') {
- opnwc = 7;
- scanpt = *op;
- return opnwc;
- }
-
- opnwrd[2] = opnwrd[2] + (srclne[(*op) + 5] - '0') * 0x1000;
- *op += 6;
-
- if (srclne[(*op) + 6] == '.' && srclne[(*op) + 7] == 'L') {
- *op += 2;
- opnwrd[2] |= 0x800;
- }
- ++(*op);
- return opnwc;
- }
-
-
- eatyp(op,reg)
- unsigned op,*reg;
- {
-
- /*
- DETERMINE GENERAL typE OF OPERAND
- IN:
- op = POINTER TO START OF OPERAND
-
- OUT:
- returns:
- 0 = NOT regISTER OR IMMEDIATE EA
- 1 = DN
- 2 = AN
- 3 = (AN)
- 4 = (AN)+
- 5 = -(AN)
- 6 = DATA
- 7 = SR
- 8 = CCR
- 9 = USP
- 10 = error DETECTED
-
- reg REG 0-7
- */
- char io;
- unsigned typ;
-
- typ = 0;
- switch (srclne[op]) {
- case '#':
- return 6;
- case '(':
- if (srclne[op + 1] == 'A' && (srclne[op + 2] >= '0' &&
- srclne[op + 2] <= '7') && srclne[op + 3] == ')') {
- *reg = srclne[op + 2] - '0';
-
- if (srclne[op + 4] == '+') {
- typ = 4;
- io = srclne[op + 5];
- }
- else {
- typ = 3;
- io = srclne[op + 4];
- }
- break;
-
- }
- else
- if (srclne[op + 1] == 'S' && srclne[op + 2] == 'P' &&
- srclne[op + 3] == ')') {
- *reg = 7;
-
- if (srclne[op + 4] == '+') {
- typ = 4;
- io = srclne[op + 5];
- }
- else {
- typ = 3;
- io = srclne[op + 4];
- }
- break;
- }
- else
- return 0;
- case '-':
- if (srclne[op + 1] == '(' && srclne[op + 2] == 'A' &&
- srclne[op + 3] >= '0' && srclne[op + 3] <= '7' &&
- srclne[op + 4] == ')') {
- typ = 5;
- *reg = srclne[op + 3] - '0';
- io = srclne[op + 5];
- break;
- }
- else
- if (srclne[op + 1] == '(' && srclne[op + 2] == 'S' &&
- srclne[op + 3] == 'P' && srclne[op + 4] == ')') {
- typ = 5;
- *reg = 7;
- io = srclne[op + 5];
- break;
- }
- else
- return 0;
- case 'D':
- case 'A':
- if (srclne[op + 1] < '0' || srclne[op + 1] > '7')
- return 0;
-
- *reg = srclne[op + 1] - '0';
- io = srclne[op + 2];
-
- if (srclne[op] == 'D')
- typ = 1;
- else
- typ = 2;
- break;
- case 'S':
- if (srclne[op + 1] == 'R') {
- typ = 7;
- io = srclne[op + 2];
- break;
- }
- else
- if (srclne[op + 1] == 'P') {
- typ = 2;
- io = srclne[op + 2];
- break;
- }
- else
- return 0;
- case 'C':
- if (srclne[op + 1] == 'C' && srclne[op + 2] == 'R') {
- typ = 8;
- io = srclne[op + 3];
- break;
- }
- else
- return 0;
- case 'U':
- if (srclne[op + 1] == 'S' && srclne[op + 2] == 'P') {
- typ = 9;
- io = srclne[op + 3];
- break;
- }
- default:
- return 0;
- }
-
- if (io == 0 || io == ' ' || io == '\t' || io == ',')
- return typ;
-
- if (typ <= 5 && typ >= 3)
- return 10;
- else
- return 0;
- }