OpenCores
URL https://opencores.org/ocsvn/zipcpu/zipcpu/trunk

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [sw/] [zasm/] [zparser.cpp] - Diff between revs 12 and 13

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 12 Rev 13
Line 2... Line 2...
//
//
// Filename:    zparser.cpp
// Filename:    zparser.cpp
//
//
// Project:     Zip CPU -- a small, lightweight, RISC CPU core
// Project:     Zip CPU -- a small, lightweight, RISC CPU core
//
//
// Purpose:     
// Purpose:     This file is really mis-named.  At one time it was going to
 
//              be the parser for the Zip Assembler, zasm.  Since then, I
 
//              discovered Flex and Bison and have written a parser using
 
//              those tools.  The true parser may therefore be found in zasm.y.
 
//              This file, however, still contains some very valuable tools.
 
//              In particular, all of the routines used to build instructions
 
//              from the appropriate fields are kept in this file.  For example,
 
//              op_noop() returns the instruction code for a NOOP  instruction.
//
//
// Creator:     Dan Gisselquist, Ph.D.
// Creator:     Dan Gisselquist, Ph.D.
//              Gisselquist Tecnology, LLC
//              Gisselquist Tecnology, LLC
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Line 43... Line 50...
#include "zparser.h"
#include "zparser.h"
#include "zopcodes.h"
#include "zopcodes.h"
 
 
typedef ZPARSER::ZIPI ZIPI;     // A Zip Instruction (i.e. uint32)
typedef ZPARSER::ZIPI ZIPI;     // A Zip Instruction (i.e. uint32)
 
 
bool    ZPARSER::iscomment(const char *line) const {
 
        const   char    *sp = line;
 
        do {
 
                if (*sp == '\0')
 
                        return true;
 
                else if (*sp == ';')
 
                        return true;
 
                else if (*sp == '#')
 
                        return true;
 
                else if (*sp == '\n')
 
                        return true;
 
                else if (*sp == '\r')
 
                        return true;
 
                else if ((*sp == '/')&&(sp[1] == '/'))
 
                        return true;
 
                else if (!isspace(*sp))
 
                        return false;
 
        } while(*sp++);
 
 
 
        return true;
 
}
 
 
 
bool    ZPARSER::islabel(const char *line) const {
 
        const   char *sp = line;
 
        if (isspace(*line))
 
                return false;
 
        if (!isalpha(*line))
 
                return  false;
 
        while((isalpha(*sp))||(isdigit(*sp))||(*sp=='_'))
 
                sp++;
 
        if (*sp != ':')
 
                return false;
 
        sp++;
 
        return iscomment(sp);
 
}
 
 
 
bool    ZPARSER::parse_op(const char *line, ZPARSER::ZIPA pc,
 
                ZPARSER::ZIPI &ins, const unsigned lineno) const {
 
        const char      *sp = line;
 
        char    cpy[128], *cp = cpy, *point, *dollar, *plus, *comma, *paren,
 
                        *opc, *opb, *opa;
 
        ZPARSER::ZIPREG ra = ZPARSER::ZIP_Rnone, rb = ZPARSER::ZIP_Rnone;
 
        ZIPCOND cnd = ZIPC_ALWAYS;
 
        ZIPIMM  imm = 0;
 
        bool    valid = true;
 
 
 
        if (!isspace(*sp))
 
                return false;
 
 
 
        while(isspace(*sp))
 
                sp++;
 
        // Remove comments from our local copy
 
        for(unsigned int i=0; i<sizeof(cpy); i++) {
 
                if (*sp == '\0')
 
                        break;
 
                else if (*sp == ';')
 
                        break;
 
                else if (*sp == '#')
 
                        break;
 
                else if (*sp == '\n')
 
                        break;
 
                else if (*sp == '\r')
 
                        break;
 
                else if ((*sp == '/')&&(sp[1] == '/'))
 
                        break;
 
                *cp++ = *sp++;
 
        } if (cp-cpy >= (int)sizeof(cpy))
 
                return false;
 
        *cp = '\0';
 
        point = strchr(cpy, '.');
 
        comma = strchr(cpy, ',');
 
        plus  = strchr(cpy, '+');
 
        dollar= strchr(cpy, '$');
 
        paren = strchr(cpy, '(');
 
        if (point)  *point++  = '\0';
 
        if (comma)  *comma++  = '\0';
 
        if (plus)   *plus++   = '\0';
 
        if (dollar) *dollar++ = '\0';
 
        // if (paren)  *paren++  = '\0';
 
        cp = cpy;
 
        while(isalpha(*cp))
 
                cp++;
 
        opc = cpy;
 
        if ((*cp == '\0')&&(point == NULL))
 
                cp[1] = '\0';
 
        *cp = '\0';
 
 
 
        if ((point)&&(strncasecmp("DAT",point,3)!=0)) {
 
                cp = point;
 
                while(isalpha(*cp))
 
                        cp++;
 
                if (*cp == '\0')
 
                        cp[1] = '\0';
 
                *cp = '\0';
 
 
 
                for(int i=1; i<8; i++) {
 
                        if (strcasecmp(&zop_ccstr[i][1], point)==0) {
 
                                cnd = (ZIPCOND)i;
 
                                break;
 
                        }
 
                } if (cnd == ZIPC_ALWAYS) {
 
                        printf("ERR: Unrecognized condition, %s\n", point);
 
                        valid = false;
 
                }
 
        }
 
 
 
        cp++;
 
        while(isspace(*cp))
 
                cp++;
 
        opb = cp;
 
        opa = comma;
 
 
 
        if (paren) {
 
                opb = paren+1;
 
                if ((comma)&&(opb > comma))
 
                        opa = cp;
 
        } else if (plus)
 
                opb = plus;
 
 
 
        if (dollar) {
 
                // Figure out the base
 
                {
 
                        char *ip = dollar, mxd = 0;
 
                        if ((*ip == '0')&&(toupper(ip[1])=='X'))
 
                                imm = strtoul(dollar, NULL, 16);
 
                        else {
 
                                bool neg = false;
 
                                if (*ip == '-') {
 
                                        neg = true;
 
                                        ip++;
 
                                        dollar++;
 
                                }
 
                                while(isdigit(*ip)||((toupper(*ip)>='A')&&(toupper(*ip)<='F'))) {
 
                                        if (isalpha(*ip))
 
                                                mxd = (*ip-'a')+10;
 
                                        else
 
                                                mxd = (*ip-'0');
 
                                        ip++;
 
                                }
 
 
 
                                if ((mxd <= 1)&&(*ip=='d'))
 
                                        imm = strtoul(dollar, NULL, 2);
 
                                else if ((mxd <= 7)&&((*dollar == '0')||(toupper(*ip)=='O')))
 
                                        imm = strtoul(dollar, NULL, 8);
 
                                else if ((mxd <= 15)&&(toupper(*ip)=='H'))
 
                                        imm = strtoul(dollar, NULL, 16);
 
                                else if ((toupper(*ip)=='D')||(*ip == '+')||(isspace(*ip))||(*ip == '(')||(*ip == '\0'))
 
                                        imm = atoi(dollar);
 
                                else {
 
                                        printf("Cannot parse immediate, %s\n", dollar);
 
                                        printf("Assuming you meant %d\n", atoi(dollar));
 
                                        imm = atoi(dollar);
 
                                }
 
 
 
                                if (neg)
 
                                        imm = -imm;
 
                        }
 
                }
 
        } else
 
                imm = 0;
 
 
 
        if (*opb) for(int i=31; i>=0; i--) {
 
                // printf("%s Checking for match to opB: \'%s\' to %s", opc, opb, zop_regstr[i]);
 
                if (NULL != strcasestr(opb, zop_regstr[i])) {
 
                        // printf(" --- Match\n");
 
                        rb = (ZIPREG)i;
 
                        break;
 
                } // else printf(" -- nope\n");
 
        } if (opa) for(int i=31; i>=0; i--) {
 
                // printf("%s Checking for match to opA: ,%s to %s", opc, opa, zop_regstr[i]);
 
                if (NULL != strcasestr(opa, zop_regstr[i])) {
 
                        ra = (ZIPREG)i;
 
                        // printf(" --- Match\n");
 
                        break;
 
                } // else printf(" -- nope\n");
 
        }
 
 
 
        if (strcasecmp("MOV",opc)!=0) {
 
                // Only move instructions can reference user regs
 
                if ((ra != ZIP_Rnone)&&(ra >= ZIP_uR0))
 
                        valid = false;
 
                if ((rb != ZIP_Rnone)&&(rb >= ZIP_uR0))
 
                        valid = false;
 
                if (!valid)
 
                        printf("ERR: Only Mov can specify user regs\n");
 
        }
 
 
 
        if ((!*opc)&&(strncasecmp("DAT",point,3)==0)) {
 
                ins = imm;
 
                valid = true;
 
        } else if (strcasecmp("CMP",opc)==0) {
 
                if (rb != ZIP_Rnone)
 
                        ins = op_cmp(cnd, imm, rb, ra);
 
                else    ins = op_cmp(cnd, imm, ra);
 
        } else if (strcasecmp("TST",opc)==0) {
 
                if (rb != ZIP_Rnone)
 
                        ins = op_tst(cnd, imm, rb, ra);
 
                else if (!dollar)
 
                        ins = op_tst(cnd, ra);
 
                else
 
                        ins = op_tst(cnd, imm, ra);
 
        } else if (strcasecmp("MOV",opc)==0) {
 
                if ((rb != ZIP_Rnone)&&(ra != ZIP_Rnone))
 
                        ins = op_mov(cnd, imm, rb, ra);
 
                else    { printf("ERR MOV, ra = %d, rb = %d, imm = %d, cnd = %d\nLine was: %s", (int)ra, (int)rb, (int)imm, (int)cnd, line); valid = false; }
 
        } else if (strcasecmp("LDI",opc)==0) {
 
                if ((rb == ZIP_Rnone)&&(cnd == ZIPC_ALWAYS))
 
                        ins = op_ldi(imm, ra);
 
                else    valid = false;
 
        } else if (strcasecmp("trap",opc)==0) {
 
                if ((rb == ZIP_Rnone)&&(rb == ZIP_Rnone))
 
                        ins = op_trap(cnd, imm);
 
                else
 
                        valid = false;
 
        } else if (strcasecmp("CLR",opc)==0) {
 
                if ((ra == ZIP_Rnone)&&(!dollar)&&(cnd == ZIPC_ALWAYS))
 
                        ins = op_clr(rb);       // Good
 
                else    valid = false;
 
        } else if ((strcasecmp("NOOP",opc)==0)||(strcasecmp("NOP",opc)==0)) {
 
                if ((rb == ZIP_Rnone)&&(ra == ZIP_Rnone)&&(!dollar)&&(cnd == ZIPC_ALWAYS))
 
                        ins = op_noop();
 
                else    { printf("ERR: NOP, ra=%d, rb=%d, dollar = %s\n",
 
                                (int)ra, (int)rb, (dollar)?"true":"false"); valid = false; }
 
        } else if ((strcasecmp("BREAK",opc)==0)||(strcasecmp("BRK",opc)==0)) {
 
                if ((rb == ZIP_Rnone)&&(ra == ZIP_Rnone)&&(!dollar)&&(cnd == ZIPC_ALWAYS))
 
                        ins = op_break();
 
                else    { printf("ERR: BRK, ra=%d, rb=%d, dollar = %s\n",
 
                                (int)ra, (int)rb, (dollar)?"true":"false"); valid = false; }
 
        } else if ((strcasecmp("LDIHI",opc)==0)||(strcasecmp("LODIHI",opc)==0)) {
 
                if ((dollar)&&(ra != ZIP_Rnone))
 
                        ins = op_ldihi(cnd, imm, ra);
 
                else    valid = false;
 
        } else if ((strcasecmp("LDILO",opc)==0)||(strcasecmp("LODILO",opc)==0)){
 
                if ((dollar)&&(ra != ZIP_Rnone))
 
                        ins = op_ldilo(cnd, imm, ra);
 
                else    valid = false;
 
        } else if ((strcasecmp("LOD",opc)==0)||(strcasecmp("LOAD",opc)==0)) {
 
                if (rb != ZIP_Rnone)
 
                        ins = op_lod(cnd,imm,rb,ra);
 
                else    ins = op_lod(cnd,imm,ra);
 
        } else if ((strcasecmp("STO",opc)==0)||(strcasecmp("STOR",opc)==0)) {
 
                // printf("STO: Imm = %d, RA = %d, RB = %d\n", imm, ra, rb);
 
                if (rb != ZIP_Rnone)
 
                        ins = op_sto(cnd,ra,imm,rb);
 
                else    ins = op_sto(cnd,ra,imm);
 
        } else if (strcasecmp("SUB",opc)==0) {
 
                if (rb != ZIP_Rnone)
 
                        ins = op_sub(cnd,imm,rb,ra);
 
                else    ins = op_sub(cnd,imm,ra);
 
        } else if (strcasecmp("AND",opc)==0) {
 
                if (rb != ZIP_Rnone)
 
                        ins = op_and(cnd,imm,rb,ra);
 
                else    ins = op_and(cnd,imm,ra);
 
        } else if (strcasecmp("ADD",opc)==0) {
 
                if (rb != ZIP_Rnone)
 
                        ins = op_add(cnd,imm,rb,ra);
 
                else    ins = op_add(cnd,imm,ra);
 
        } else if (strcasecmp("OR",opc)==0) {
 
                if (rb != ZIP_Rnone)
 
                        ins = op_or(cnd,imm,rb,ra);
 
                else    ins = op_or(cnd,imm,ra);
 
        } else if (strcasecmp("XOR",opc)==0) {
 
                if (rb != ZIP_Rnone)
 
                        ins = op_xor(cnd,imm,rb,ra);
 
                else    ins = op_xor(cnd,imm,ra);
 
        } else if ((strcasecmp("LSL",opc)==0)||(strcasecmp("ASL",opc)==0)) {
 
                if (rb != ZIP_Rnone)
 
                        ins = op_lsl(cnd,imm,rb,ra);
 
                else    ins = op_lsl(cnd,imm,ra);
 
        } else if (strcasecmp("ASR",opc)==0) {
 
                if (rb != ZIP_Rnone)
 
                        ins = op_asr(cnd,imm,rb,ra);
 
                else    ins = op_asr(cnd,imm,ra);
 
        } else if (strcasecmp("LSR",opc)==0) {
 
                if (rb != ZIP_Rnone)
 
                        ins = op_lsr(cnd,imm,rb,ra);
 
                else    ins = op_lsr(cnd,imm,ra);
 
        } else if (strcasecmp("BR",opc)==0) {
 
                if ((dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone))
 
                        valid = false;
 
                else ins = op_bra(cnd, imm);
 
        } else if (strcasecmp("BRA",opc)==0) {
 
                if ((!dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone)||(cnd != ZIPC_ALWAYS))
 
                        valid = false;
 
                else ins = op_bra(imm);
 
        } else if (strcasecmp("BRZ",opc)==0) {
 
                if ((!dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone)||(cnd != ZIPC_ALWAYS))
 
                        valid = false;
 
                else ins = op_brz(imm);
 
        } else if ((strcasecmp("BRNZ",opc)==0)||(strcasecmp("BNZ",opc)==0)) {
 
                if ((!dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone)||(cnd != ZIPC_ALWAYS))
 
                        valid = false;
 
                else ins = op_bnz(imm);
 
        } else if ((strcasecmp("BRGE",opc)==0)||(strcasecmp("BGE",opc)==0)) {
 
                if ((!dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone)||(cnd != ZIPC_ALWAYS))
 
                        valid = false;
 
                else ins = op_bge(imm);
 
        } else if ((strcasecmp("BRGT",opc)==0)||(strcasecmp("BGT",opc)==0)) {
 
                if ((!dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone)||(cnd != ZIPC_ALWAYS))
 
                        valid = false;
 
                else ins = op_bgt(imm);
 
        } else if (strcasecmp("BRZ",opc)==0) {
 
        } else if ((strcasecmp("BRLT",opc)==0)||(strcasecmp("BLT",opc)==0)) {
 
                if ((!dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone)||(cnd != ZIPC_ALWAYS))
 
                        valid = false;
 
                else ins = op_blt(imm);
 
        } else if ((strcasecmp("BRC",opc)==0)||(strcasecmp("BC",opc)==0)) {
 
                if ((!dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone)||(cnd != ZIPC_ALWAYS))
 
                        valid = false;
 
                else ins = op_brc(imm);
 
        } else if ((strcasecmp("BRV",opc)==0)||(strcasecmp("BV",opc)==0)) {
 
                if ((!dollar)||(ra != ZIP_Rnone)||(rb != ZIP_Rnone)||(cnd != ZIPC_ALWAYS))
 
                        valid = false;
 
                else ins = op_brv(imm);
 
        } else if (strcasecmp("CLRF",opc)==0) {
 
                if ((ra == ZIP_Rnone)&&(!dollar)&&(imm==0))
 
                        ins = op_clrf(cnd, rb);
 
                else    valid = false;
 
        } else if((strcasecmp("HALT",opc)==0)||(strcasecmp("WAIT",opc)==0)) {
 
                if ((rb == ZIP_Rnone)&&(ra==ZIP_Rnone)&&(!opa)&&(!dollar))
 
                        ins = op_halt(cnd);
 
                else    valid = false;
 
        } else if (strcasecmp("BUSY",opc)==0) {
 
                if ((rb == ZIP_Rnone)&&(ra==ZIP_Rnone)&&(!opa)&&(!dollar))
 
                        ins = op_busy(cnd);
 
                else    valid = false;
 
        } else if (strcasecmp("RTU",opc)==0) {
 
                if ((rb == ZIP_Rnone)&&(ra==ZIP_Rnone)&&(imm==0)&&(!opa)&&(!dollar))
 
                        ins = op_rtu(cnd);
 
                else    { printf("ERRR,RTU, ra=%d,rb=%d,imm=%08x,comma=%s,dollar=%s\n",
 
                                (int)ra, (int)rb, imm, (opa)?"true":"false",
 
                                (dollar)?"true":"false");
 
                        valid = false;
 
                }
 
        } else if (strcasecmp("JMP",opc)==0) {
 
                if ((rb != ZIP_Rnone)&&(!opa))
 
                        ins = op_not(cnd, rb);
 
                else    valid = false;
 
        } else if (strcasecmp("NOT",opc)==0) {
 
                if ((rb != ZIP_Rnone)&&(ra==ZIP_Rnone)&&(!opa)&&(!dollar))
 
                        ins = op_not(cnd, rb);
 
                else    valid = false;
 
        } else  valid = false;
 
 
 
        return valid;
 
}
 
 
 
bool    ZPARSER::parse(const char *line, ZPARSER::ZIPA &pc, ZPARSER::ZIPI &instruction, const unsigned int lineno) {
 
        bool    v = parse_op(line, pc, instruction, lineno);
 
        pc = pc + 1;
 
        return v;
 
}
 
 
 
#define IMMOP(OP,CND,IMM,A) (((OP&0x0f)<<28)|((A&0x0f)<<24)|((CND&0x07)<<21) \
#define IMMOP(OP,CND,IMM,A) (((OP&0x0f)<<28)|((A&0x0f)<<24)|((CND&0x07)<<21) \
                        | (IMM & 0x0fffff))
                        | (IMM & 0x0fffff))
 
 
#define DBLREGOP(OP,CND,IMM,B,A) (((OP&0x0f)<<28)|((A&0x0f)<<24)        \
#define DBLREGOP(OP,CND,IMM,B,A) (((OP&0x0f)<<28)|((A&0x0f)<<24)        \
                        |((CND&0x07)<<21)|(1<<20)|((B&0x0f)<<16)         \
                        |((CND&0x07)<<21)|(1<<20)|((B&0x0f)<<16)         \
Line 437... Line 91...
        return in;
        return in;
}
}
 
 
ZIPI    ZPARSER::op_trap(ZIPCOND cnd, ZIPIMM imm) const {
ZIPI    ZPARSER::op_trap(ZIPCOND cnd, ZIPIMM imm) const {
        ZIPI    in;
        ZIPI    in;
        in  = ((0x4f)<<24)|((cnd&0x07)<<21)|(1<<20)|((0x0e)<<16);
        if (cnd != ZIPC_ALWAYS)
        in |= (imm & 0x0ffff);
                return op_ldilo(cnd, imm, ZIP_CC);
 
        else
 
                return op_ldi(imm, ZIP_CC);
 
        // in  = ((0x4f)<<24)|((cnd&0x07)<<21)|(1<<20)|((0x0e)<<16);
 
        // in |= (imm & 0x0ffff);
        return in;
        return in;
}
}
 
 
ZIPI    ZPARSER::op_noop(void) const {
ZIPI    ZPARSER::op_noop(void) const {
        return 0x4e000000;
        return 0x4e000000;

powered by: WebSVN 2.1.0

© copyright 1999-2022 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.