/* i51adr.c */ /* * (C) Copyright 1989,1990 * All Rights Reserved * * Alan R. Baldwin * 721 Berkeley St. * Kent, Ohio 44240 * * Ported from 8085 to 8051 by John Hartman 30-Apr-1995 * Continued, 29-May-95 */ #include #include #include "asm.h" #include "i8051.h" extern int admode (struct adsym *); struct adsym reg51[] = { /* R0 thru R7 registers */ { "R0", R0}, { "R1", R1}, { "R2", R2}, { "R3", R3}, { "R4", R4}, { "R5", R5}, { "R6", R6}, { "R7", R7}, { "A", A}, { "DPTR", DPTR}, { "PC", PC}, { "C", C}, { "AB", AB}, { "r0", R0}, { "r1", R1}, { "r2", R2}, { "r3", R3}, { "r4", R4}, { "r5", R5}, { "r6", R6}, { "r7", R7}, { "a", A}, { "dptr", DPTR}, { "pc", PC}, { "c", C}, { "ab", AB}, { "", 0x00} }; /* Classify argument as to address mode */ int addr(esp) register struct expr *esp; { register int c; register unsigned rd; if ((c = getnb()) == '#') { /* Immediate mode */ expr(esp, 0); esp->e_mode = S_IMMED; } else if (c == '@') { /* choices are @R0, @R1, @DPTR, @A+PC, @A+DPTR */ switch (reg()) { case R0: esp->e_mode = S_AT_R; esp->e_addr = R0; break; case R1: esp->e_mode = S_AT_R; esp->e_addr = R1; break; case DPTR: esp->e_mode = S_AT_DP; esp->e_addr = DPTR; break; case A: if (getnb() == '+') { rd = reg(); if (rd == PC) { esp->e_mode = S_AT_APC; esp->e_addr = 0; } else if (rd == DPTR) { esp->e_mode = S_AT_ADP; esp->e_addr = 0; } else { aerr(); } } else aerr(); break; } esp->e_flag = 0; esp->e_base.e_ap = NULL; } else if (c == '*') { /* Force direct page */ expr(esp, 0); esp->e_mode = S_DIR; if (esp->e_addr & ~0xFF) err('d'); } else if (c == '/') { /* Force inverted bit */ expr(esp, 0); esp->e_mode = S_NOT_BIT; if (esp->e_addr & ~0xFF) err('d'); } else { unget(c); /* try for register: A, AB, R0-R7, DPTR, PC, Cy */ if ((esp->e_addr = admode(reg51)) != -1) { switch (esp->e_addr) { case A: esp->e_mode = S_A; break; case AB: esp->e_mode = S_RAB; break; case DPTR: esp->e_mode = S_DPTR; break; case PC: esp->e_mode = S_PC; break; case C: esp->e_mode = S_C; break; default: /* R0-R7 */ esp->e_mode = S_REG; } } else { /* Must be an expression */ expr(esp, 0); if ((!esp->e_flag) && (esp->e_base.e_ap==NULL) && !(esp->e_addr & ~0xFF)) { esp->e_mode = S_DIR; } else { esp->e_mode = S_EXT; } } } return (esp->e_mode); } /* * any --- does str contain c? */ int any(c,str) char c, *str; { while (*str) if(*str++ == c) return(1); return(0); } int srch(str) register char *str; { register char *ptr; ptr = ip; #if CASE_SENSITIVE while (*ptr && *str) { if(*ptr != *str) break; ptr++; str++; } if (*ptr == *str) { ip = ptr; return(1); } #else while (*ptr && *str) { if(ccase[*ptr] != ccase[*str]) break; ptr++; str++; } if (ccase[*ptr] == ccase[*str]) { ip = ptr; return(1); } #endif if (!*str) if (any(*ptr," \t\n,];")) { ip = ptr; return(1); } return(0); } /* * Enter admode() to search a specific addressing mode table * for a match. Return the addressing value on a match or * -1 for no match. */ int admode(sp) register struct adsym *sp; { register char *ptr; register int i; unget(getnb()); i = 0; while ( *(ptr = (char *) &sp[i]) ) { if (srch(ptr)) { return(sp[i].a_val); } i++; } return(-1); } /* * srch --- does string match ? */ /* * Read a register name. Return register value, -1 if no register found */ int reg() { register struct mne *mp; char id[NCPS]; getid(id, -1); if ((mp = mlookup(id))==NULL) { aerr(); return (-1); } switch (mp->m_type) { case S_A: case S_AB: case S_DPTR: case S_PC: case S_REG: return (mp->m_valu); default: return (-1); } }