Ejemplo n.º 1
0
/*
 * generates branch opcodes
 *
 * opcode : opcode of the branch (for instance 0x8f for BR7)
 * str    : operand string
 */
static void generate_branch(unsigned char opcode, char *str) {

    unsigned long target_adr;
    long disp;

    programlabel();

    /* get target address */
    if (parse_value(str, &target_adr)) {
        /* unresolved target address, reserve space */
        emit_opcode2(0, 0);
        return;
    }

    /* calculate displacement */
    if (isPCKnown()) {
        disp = target_adr - getPC() - 1;
        if (disp > 127 || disp < -128) {
            char buf[64];
            sprintf(buf, "%d", (int)disp);
            asmerr(ERROR_BRANCH_OUT_OF_RANGE, false, buf);
        }
    } else {
        /* unknown pc, will be (hopefully) resolved in future passes */
        disp = 0;
    }

    emit_opcode2(opcode, disp & 255);
}
Ejemplo n.º 2
0
/*
 * handles opcodes with a scratchpad register operand:
 * as, asd, ds, ns, xs
 */
static void v_sreg_op(char *str, MNEMONIC *mne) {

    unsigned char reg;

    programlabel();
    parse_scratchpad_register(str, &reg);
    emit_opcode1(mne->opcode[0] | reg);
}
Ejemplo n.º 3
0
/*
 * handles instructions that take a byte operand:
 * ai, ci, in, li, ni, oi, out, xi
 */
static void v_byteop(char *str, MNEMONIC *mne) {

    unsigned long value;

    programlabel();
    parse_value(str, &value);
    if (value > 0xff) {
        f8err(ERROR_ADDRESS_MUST_BE_LT_100, mne->name, str, false);
    }
    emit_opcode2(mne->opcode[0], value & 0xff);
}
Ejemplo n.º 4
0
/*
 * handles instructions that take a word operand:
 * dci, jmp, pi
 */
static void v_wordop(char *str, MNEMONIC *mne) {

    unsigned long value;

    programlabel();
    parse_value(str, &value);
    if (value > 0xffff) {
        f8err(ERROR_VALUE_MUST_BE_LT_10000, mne->name, str, false);
    }
    emit_opcode3(mne->opcode[0], (value >> 8) & 0xff, value & 0xff);
}
Ejemplo n.º 5
0
static void v_lisu_lisl(char *str, MNEMONIC *mne) {

    unsigned long operand;

    programlabel();
    parse_value(str, &operand);
    if (operand > 7) {
        f8err(ERROR_VALUE_MUST_BE_LT_8, mne->name, str, false);
    }
    emit_opcode1(mne->opcode[0] | (operand & 7));
}
Ejemplo n.º 6
0
static void v_lis(char *str, MNEMONIC *mne) {

    unsigned long operand;

    programlabel();
    parse_value(str, &operand);
    if (operand > 15) {
        f8err(ERROR_VALUE_MUST_BE_LT_10, mne->name, str, false);
    }
    emit_opcode1(0x70 | (operand & 15));
}
Ejemplo n.º 7
0
static void v_sl_sr(char *str, MNEMONIC *mne) {

    unsigned long operand;

    programlabel();

    if (parse_value(str, &operand)) {
        /* unresolved expression, reserve space */
        emit_opcode1(0);
    } else {
        switch (operand) {
            case 1:
                emit_opcode1(mne->opcode[0]);
                break;
            case 4:
                emit_opcode1(mne->opcode[0] + 2);
                break;
            default:
                f8err(ERROR_VALUE_MUST_BE_1_OR_4, mne->name, str, false);
                emit_opcode1(0);
                break;
        }
    }
}
Ejemplo n.º 8
0
void v_mnemonic(char *str, MNEMONIC *mne)
{
    int addrmode;
    SYMBOL *sym;
    unsigned int opcode;
    short opidx;
    SYMBOL *symbase;
    int     opsize;
    
    Csegment->flags |= SF_REF;
    programlabel();
    symbase = eval(str, 1);
    
    if ( bTrace )
        printf("PC: %04lx  MNEMONIC: %s  addrmode: %d  ", Csegment->org, mne->name, symbase->addrmode);

    for (sym = symbase; sym; sym = sym->next)
    {
        if (sym->flags & SYM_UNKNOWN)
        {
            ++Redo;
            Redo_why |= REASON_MNEMONIC_NOT_RESOLVED;
        }
    }
    sym = symbase;
    
    if (mne->flags & MF_IMOD)
    {
        if (sym->next)
        {
            sym->addrmode = AM_BITMOD;
            if ((mne->flags & MF_REL) && sym->next)
                sym->addrmode = AM_BITBRAMOD;
        }
    }
    addrmode = sym->addrmode;
    if ((sym->flags & SYM_UNKNOWN) || sym->value >= 0x100)
        opsize = 2;
    else
        opsize = (sym->value) ? 1 : 0;
    
    while (badcode(mne,addrmode) && Cvt[addrmode])
        addrmode = Cvt[addrmode];
    
    if ( bTrace )
        printf("mnemask: %08lx adrmode: %d  Cvt[am]: %d\n", mne->okmask, addrmode, Cvt[addrmode]);
    
    if (badcode(mne,addrmode))
    {
        char sBuffer[128];
        sprintf( sBuffer, "%s %s", mne->name, str );
        asmerr( ERROR_ILLEGAL_ADDRESSING_MODE, false, sBuffer );
        FreeSymbolList(symbase);
        return;
    }
    
    if (Mnext >= 0 && Mnext < NUMOC)            /*	Force	*/
    {
        addrmode = Mnext;
        
        if (badcode(mne,addrmode))
        {
            asmerr( ERROR_ILLEGAL_FORCED_ADDRESSING_MODE, false, mne->name );
            FreeSymbolList(symbase);
            return;
        }
    }
    
    if ( bTrace )
        printf("final addrmode = %d\n", addrmode);
    
    while (opsize > Opsize[addrmode])
    {
        if (Cvt[addrmode] == 0 || badcode(mne,Cvt[addrmode]))
        {
            char sBuffer[128];
            
            if (sym->flags & SYM_UNKNOWN)
                break;
            
            sprintf( sBuffer, "%s %s", mne->name, str );
            asmerr( ERROR_ADDRESS_MUST_BE_LT_100, false, sBuffer );
            break;
        }
        addrmode = Cvt[addrmode];
    }
    opcode = mne->opcode[addrmode];
    opidx = 1 + (opcode > 0xFF);
    if (opidx == 2)
    {
        Gen[0] = opcode >> 8;
        Gen[1] = opcode;
    }
Ejemplo n.º 9
0
static void v_lr(char *str, MNEMONIC *mne) {

    int i;
    int ncommas;
    int cindex;
    char *op1;
    char *op2;
    unsigned char reg_dst;
    unsigned char reg_src;
    int opcode;

    programlabel();

    /* a valid operand string must contain exactly one comma. find it. */
    ncommas = 0;
    cindex = 0;
    for (i=0; str[i]; i++) {
        if (',' == str[i]) {
        ncommas++;
        cindex = i;
        }
    }
    if (1 != ncommas) {
	f8err(ERROR_SYNTAX_ERROR, mne->name, str, false);
        return;
    }

    /* extract operand strings  */
    str[cindex] = 0;
    op1 = str;
    op2 = &str[cindex+1];
    if ( (0 != cindex) && (isspace(str[cindex-1])) ) {
        str[cindex-1] = 0;
    }
    if (isspace(*op2)) {
        op2++;
    }

    /* parse operand strings for register names */
    reg_dst = parse_special_register(op1);
    if (REG_NONE == reg_dst) {
        if (parse_scratchpad_register(op1, &reg_dst)) {
            /* unresolved expression, reserve space */
            emit_opcode1(0);
            return;
        }
    }
    reg_src = parse_special_register(op2);
    if (REG_NONE == reg_src) {
        if (parse_scratchpad_register(op2, &reg_src)) {
            /* unresolved expression, reserve space */
            emit_opcode1(0);
            return;
        }
    }

    /* restore operand string */
    str[cindex] = ',';
    if ( (0 != cindex) && (0 == str[cindex-1])) {
        str[cindex-1] = ' ';
    }

    /* generate opcode */
    opcode = -1;
    switch (reg_dst) {
        case REG_A:     /* lr a,xxx */
            switch (reg_src) {
                case REG_IS: opcode = 0x0a; break;
                case REG_KL: opcode = 0x01; break;
                case REG_KU: opcode = 0x00; break;
                case REG_QL: opcode = 0x03; break;
                case REG_QU: opcode = 0x02; break;
                default:
                    if (reg_src < 15) {
                        opcode = 0x40 | reg_src;
                    }
                    break;
                }
                break;
        case REG_DC0:
            switch (reg_src) {
                case REG_H: opcode = 0x10; break;
                case REG_Q: opcode = 0x0f; break;
            }
            break;
        case REG_H:
            if (REG_DC0 == reg_src) opcode = 0x11;
            break;
        case REG_IS:
            if (REG_A == reg_src) opcode = 0x0b;
            break;
        case REG_K:
            if (REG_PC1 == reg_src) opcode = 0x08;
            break;
        case REG_KL:
            if (REG_A == reg_src) opcode = 0x05;
            break;
        case REG_KU:
            if (REG_A == reg_src) opcode = 0x04;
            break;
        case REG_PC0:
            if (REG_Q == reg_src) opcode = 0x0d;
            break;
        case REG_PC1:
            if (REG_K == reg_src) opcode = 0x09;
            break;
        case REG_Q:
            if (REG_DC0 == reg_src) opcode = 0x0e;
            break;
        case REG_QL:
            if (REG_A == reg_src) opcode = 0x07;
            break;
        case REG_QU:
            if (REG_A == reg_src) opcode = 0x06;
            break;
        case REG_W:
            if (0x09 == reg_src) opcode = 0x1d;
            break;
        default:        /* lr sreg,xxx*/
            if ( (15 > reg_dst) && (REG_A == reg_src) ) {
                /* lr sreg,a */
                opcode = 0x50 | reg_dst;
            }
            else if ( (9 == reg_dst) && (REG_W == reg_src) ) {
                /* special case : lr j,w */
                opcode = 0x1e;
            }
            break;
    }
    if (opcode < 0) {
        f8err(ERROR_ILLEGAL_OPERAND_COMBINATION, mne->name, str, true);
    } else {
        emit_opcode1(opcode);
    }
}
Ejemplo n.º 10
0
static int MainShadow(int ac, char **av, bool *pbTableSort )
{
    
    
    
    int nError = ERROR_NONE;
    bool bDoAllPasses = false;
    int nMaxPasses = 10;
    
    char buf[MAXLINE];
    int i;
    MNEMONIC *mne;
    
    int oldredo = -1;
    unsigned long oldwhy = 0;
    int oldeval = 0;
    
    addhashtable(Ops);
    pass = 1;

    if (ac < 2)
    {

fail:
    puts(dasm_id);
    puts("Copyright (c) 1988-2008 by various authors (see file AUTHORS).");
    puts("License GPLv2+: GNU GPL version 2 or later (see file COPYING).");
    puts("DASM is free software: you are free to change and redistribute it.");
    puts("There is ABSOLUTELY NO WARRANTY, to the extent permitted by law.");
    puts("");
    puts("Usage: dasm sourcefile [options]");
    puts("");
    puts("-f#      output format 1-3 (default 1)");
    puts("-oname   output file name (else a.out)");
    puts("-lname   list file name (else none generated)");
    puts("-Lname   list file, containing all passes");
    puts("-sname   symbol dump file name (else none generated)");
    puts("-v#      verboseness 0-4 (default 0)");
    puts("-d       debug mode (for developers)");
    puts("-Dsymbol              define symbol, set to 0");
    puts("-Dsymbol=expression   define symbol, set to expression");
    puts("-Msymbol=expression   define symbol using EQM (same as -D)");
    puts("-Idir    search directory for INCLUDE and INCBIN");
    puts("-p#      maximum number of passes");
    puts("-P#      maximum number of passes, with fewer checks");
    puts("-T#      symbol table sorting (default 0 = alphabetical, 1 = address/value)");
    puts("-E#      error format (default 0 = MS, 1 = Dillon, 2 = GNU)");
    puts("");
    puts("Report bugs to [email protected] please!");

    return ERROR_COMMAND_LINE;
    }
    
    for (i = 2; i < ac; ++i)
    {
        if ( ( av[i][0] == '-' ) || ( av[i][0] == '/' ) )
        {
            char *str = av[i]+2;
            switch(av[i][1])
            {
            /* TODO: need to improve option parsing and errors for it */
            case 'E':
                F_errorformat = atoi(str);
                if (F_errorformat < ERRORFORMAT_DEFAULT
                   || F_errorformat >= ERRORFORMAT_MAX )
                {
                    panic("Invalid error format for -E, must be 0, 1, 2");
                }
                break;

            case 'T':
                F_sortmode = atoi(str);
                if (F_sortmode < SORTMODE_DEFAULT
                   || F_sortmode >= SORTMODE_MAX )
                {
                    panic("Invalid sorting mode for -T option, must be 0 or 1");
                }
                /* TODO: refactor into regular configuration [phf] */
                *pbTableSort = (F_sortmode != SORTMODE_DEFAULT);
                break;
                
            case 'd':
                Xdebug = atoi(str) != 0;
                printf( "Debug trace %s\n", Xdebug ? "ON" : "OFF" );
                break;
                
            case 'M':
            case 'D':
                while (*str && *str != '=')
                    ++str;
                if (*str == '=')
                {
                    *str = 0;
                    ++str;
                }
                else
                {
                    str = "0";
                }
                Av[0] = av[i]+2;
                
                if (av[i][1] == 'M')
                    v_eqm(str, NULL);
                else
                    v_set(str, NULL);
                break;
                
            case 'f':   /*  F_format    */
                F_format = atoi(str);
                if (F_format < FORMAT_DEFAULT || F_format >= FORMAT_MAX )
                    panic("Illegal format specification");
                break;
                
            case 'o':   /*  F_outfile   */
                F_outfile = str;
nofile:
                if (*str == 0)
                    panic("-o Switch requires file name.");
                break;

            case 'L':
                F_ListAllPasses = 1;
                /* fall through to 'l' */

            case 'l':   /*  F_listfile  */
                F_listfile = str;
                goto nofile;
                
            case 'P':   /*  F_Passes   */
                bDoAllPasses = true;
                
                /* fall through to 'p' */
            case 'p':   /*  F_passes   */
                nMaxPasses = atoi(str);
                break;
                
            case 's':   /*  F_symfile   */
                F_symfile = str;
                goto nofile;
            case 'v':   /*  F_verbose   */
                F_verbose = atoi(str);
                break;
                
            case 'I':
                v_incdir(str, NULL);
                break;
                
            default:
                goto fail;
            }
            continue;
        }
        goto fail;
    }
    
    /*    INITIAL SEGMENT */
    
    {
        SEGMENT *seg = (SEGMENT *)permalloc(sizeof(SEGMENT));
        seg->name = strcpy(permalloc(sizeof(ISEGNAME)), ISEGNAME);
        seg->flags= seg->rflags = seg->initflags = seg->initrflags = SF_UNKNOWN;
        Csegment = Seglist = seg;
    }
    /*    TOP LEVEL IF    */
    {
        IFSTACK *ifs = (IFSTACK *)zmalloc(sizeof(IFSTACK));
        ifs->file = NULL;
        ifs->flags = IFF_BASE;
        ifs->acctrue = 1;
        ifs->xtrue  = 1;
        Ifstack = ifs;
    }
    
    
nextpass:
    
    
    if ( F_verbose )
    {
        puts("");
        printf("START OF PASS: %d\n", pass);
    }
    
    Localindex = Lastlocalindex = 0;
    
    Localdollarindex = Lastlocaldollarindex = 0;
    
    /*_fmode = 0x8000;*/
    FI_temp = fopen(F_outfile, "wb");
    /*_fmode = 0;*/
    Fisclear = 1;
    CheckSum = 0;
    if (FI_temp == NULL) {
        printf("Warning: Unable to [re]open '%s'\n", F_outfile);
        return ERROR_FILE_ERROR;
    }
    if (F_listfile) {

        FI_listfile = fopen(F_listfile,
            F_ListAllPasses && (pass > 1)? "a" : "w");

        if (FI_listfile == NULL) {
            printf("Warning: Unable to [re]open '%s'\n", F_listfile);
            return ERROR_FILE_ERROR;
        }
    }
    pushinclude(av[1]);
    
    while ( pIncfile )
    {
        for (;;) {
            const char *comment;
            if ( pIncfile->flags & INF_MACRO) {
                if ( pIncfile->strlist == NULL) {
                    Av[0] = "";
                    v_mexit(NULL, NULL);
                    continue;
                }
                strcpy(buf, pIncfile->strlist->buf);
                pIncfile->strlist = pIncfile->strlist->next;
            }
            else
            {
                if (fgets(buf, MAXLINE, pIncfile->fi) == NULL)
                    break;
            }
            
            if (Xdebug)
                printf("%08lx %s\n", (unsigned long) pIncfile, buf);
            
            comment = cleanup(buf, false);
            ++pIncfile->lineno;
            mne = parse(buf);
            
            if (Av[1][0])
            {
                if (mne)
                {
                    if ((mne->flags & MF_IF) || (Ifstack->xtrue && Ifstack->acctrue))
                        (*mne->vect)(Av[2], mne);
                }
                else
                {
                    if (Ifstack->xtrue && Ifstack->acctrue)
                        asmerr( ERROR_UNKNOWN_MNEMONIC, false, Av[1] );
                }
                
            }
            else
            {
                if (Ifstack->xtrue && Ifstack->acctrue)
                    programlabel();
            }
            
            if (F_listfile && ListMode)
                outlistfile(comment);
        }
        
        while (Reploop && Reploop->file == pIncfile)
            rmnode((void **)&Reploop, sizeof(REPLOOP));
        
        while (Ifstack->file == pIncfile)
            rmnode((void **)&Ifstack, sizeof(IFSTACK));
        
        fclose( pIncfile->fi );
        free( pIncfile->name );
        --Inclevel;
        rmnode((void **)&pIncfile, sizeof(INCFILE));
        
        if ( pIncfile )
        {
        /*
        if (F_verbose > 1)
        printf("back to: %s\n", Incfile->name);
            */
            if (F_listfile)
                fprintf(FI_listfile, "------- FILE %s\n", pIncfile->name);
        }
    }
    
    
    
    if ( F_verbose >= 1 )
        ShowSegments();
    
    if ( F_verbose >= 3 )
    {
        if ( !Redo || ( F_verbose == 4 ) )
            ShowSymbols( stdout, *pbTableSort );
        
        ShowUnresolvedSymbols();
    }
    
    closegenerate();
    fclose(FI_temp);
    if (FI_listfile)
        fclose(FI_listfile);
    
    if (Redo)
    {
        if ( !bDoAllPasses )
            if (Redo == oldredo && Redo_why == oldwhy && Redo_eval == oldeval)
            {
                ShowUnresolvedSymbols();
                return ERROR_NOT_RESOLVABLE;
            }
            
            oldredo = Redo;
            oldwhy = Redo_why;
            oldeval = Redo_eval;
            Redo = 0;
            Redo_why = 0;
            Redo_eval = 0;

            Redo_if <<= 1;
            ++pass;
            
            if ( bStopAtEnd )
            {
                printf("Unrecoverable error(s) in pass, aborting assembly!\n");
            }
            else if ( pass > nMaxPasses )
            {
                char sBuffer[64];
                sprintf( sBuffer, "%d", pass );
                return asmerr( ERROR_TOO_MANY_PASSES, false, sBuffer );
                
            }
            else
            {
                clearrefs();
                clearsegs();
                goto nextpass;
            }
    }
    
    return nError;
}
Ejemplo n.º 11
0
void
v_mnemonic(char *str, MNE *mne)
{
    register int addrmode;
    register SYMBOL *sym;
    register uword opcode;
    short opidx;
    SYMBOL *symbase;
    int     opsize;

    Csegment->flags |= SF_REF;
    programlabel();
    symbase = eval(str, 1);

    if (Xtrace)
	printf("PC: %04lx  MNE: %s  addrmode: %d  ",
	       Csegment->org, mne->name, symbase->addrmode);
    for (sym = symbase; sym; sym = sym->next) {
	if (sym->flags & SYM_UNKNOWN) {
	    ++Redo;
	    Redo_why |= 1 << 0;
	}
    }
    sym = symbase;

    if (mne->flags & MF_IMOD) {
	if (sym->next) {
	    sym->addrmode = AM_BITMOD;
	    if ((mne->flags & MF_REL) && sym->next)
		sym->addrmode = AM_BITBRAMOD;
	}
    }
    addrmode = sym->addrmode;
    if ((sym->flags & SYM_UNKNOWN) || sym->value >= 0x100)
	opsize = 2;
    else
	opsize = (sym->value) ? 1 : 0;
    while (badcode(mne,addrmode) && Cvt[addrmode])
	addrmode = Cvt[addrmode];
    if (Xtrace)
	printf("mnemask: %08lx adrmode: %d  Cvt[am]: %d\n",
		mne->okmask, addrmode, Cvt[addrmode]);
    if (badcode(mne,addrmode)) {
	asmerr(5,0);
	freesymbollist(symbase);
	return;
    }
    if (Mnext >= 0 && Mnext < NUMOC) {		    /*	Force	*/
	addrmode = Mnext;
	if (badcode(mne,addrmode)) {
	    asmerr(19,0);
	    freesymbollist(symbase);
	    return;
	}
    }
    if (Xtrace)
	printf("final addrmode = %d\n", addrmode);

    while (opsize > Opsize[addrmode]) {
	if (Cvt[addrmode] == 0 || badcode(mne,Cvt[addrmode])) {
	    if (sym->flags & SYM_UNKNOWN)
		break;
	    asmerr(14,0);
	    break;
	}
	addrmode = Cvt[addrmode];
    }
    opcode = mne->opcode[addrmode];
    opidx = 1 + (opcode > 0xFF);
    if (opidx == 2) {
	Gen[0] = opcode >> 8;
	Gen[1] = opcode;
    } else {