Xinu7/src/cmd/sub11/subASHC.c

Compare this file to the similar file:
Show the results in this format:

/*
 *      ARITHMETIC SHIFT COMBINED CONVERSION ROUTINE
 *
 * TO COMPILE RUN cc -O subASHC.c
 *
 *   Given an LSI-11 arithmetic shift combined instruction
 *      ashc A,R
 * this program will generate assembly code that will produce the equivalent
 * result. Condition codes are properly set.
 *   It replaces each "l:ashc A,r0" line (for example) with:
 *      mfps    -(sp)           / get psw
 *      mov     A,-(sp)         / push shift count onto the stack
 *      mov     r0,-(sp)        / push number to be shifted onto the stack
 *      mov     r1,-(sp)        / push number to be shifted onto the stack
 *      jsr     pc,cshft2       / call the simulation routine
 *      mov     (sp)+,r1        / save the result
 *      mov     (sp)+,r0        / save the result
 *      tst     (sp)+           / restore the stack
 *      mtps    (sp)+           / put in the new psw
 * In no case are comments provided. This follows the UNIX philosophy of
 * incomprehensibility above all else in assembly language.)
 *
 * Program by Matt Bishop, Purdue University (October 28, 1981)
 * for Doug Comer's 690d microcomputer seminar
 *
 */

/*
 * usual include crud
 */
#include <stdio.h>
#include <ctype.h>

#define LEN 30          /* max length of label, opcode, or operand */
#define ASHC "ashc"     /* instruction to be replaced */

char label[LEN];        /* label of current assembly code line */
char operator[LEN];     /* operator of current assembly code line */
char foperand[LEN];     /* first operand of current assembly code line */
char soperand[LEN];     /* second operand of current assembly code line */
int rn;                 /* number of destination register */
int flag;               /* 1 if any substitutions were made, 0 if not */
int linect;             /* current line number */
char *pgnm;             /* name of program */

main(argc, argv)
int argc;
char **argv;
{
        char line[BUFSIZ];      /* input line */

        /* Initialize everything */
        pgnm = argv[0];
        flag = 0;
        linect = 0;

        /* phase 1 - loop through the file, line by line */
        while (fgets(line, BUFSIZ, stdin) != NULL){
                /* new line number */
                linect++;

                /* is line is an "ashc" instruction */
                if (findashc(line)){

                        /* yes - be sure dest is a legal register */
                        if ((rn = isregis(soperand)) < 0 || rn > 6){
                                fprintf(stderr, "%s, line %d: second operand ", pgnm, linect);
                                fprintf(stderr, "of ashc must be r0 - r6\n");
                                printf("%s", line);
                                continue;
                        }

                        /* phase 1 substitution - see header comments */
                        flag = 1;
                        if (*label)
                                printf("%s:\t", label);
                        else
                                printf("\t");
                        printf("mfps\t-(sp)\n");
                        printf("\tmov\t%s,-(sp)\n", foperand);
                        printf("\tmov\t%s,-(sp)\n", soperand);
                        printf("\tmov\tr%d,-(sp)\n", rn+1);
                        printf("\tjsr\tpc,cshft2\n");
                        printf("\tmov\t(sp)+,r%d\n", rn+1);
                        printf("\tmov\t(sp)+,%s\n", soperand);
                        printf("\ttst\t(sp)+\n");
                        printf("\tmtps\t(sp)+\n");
                }
                else    /* not an "ashc" instruction - print whatever's there */
                        printf("%s", line);
        }

}

/*
 * returns -1 if its arg is not a register, number if it is
 */
int isregis(s)
char *s;
{
        if (s[0] != 'r' || s[2] != '\0')
                return(-1);
        return(s[1] - '0');
}

/*
 * This parses the input line
 */
int findashc(s)
char *s;
{
        /* get label and operator (if any) */
        getlabel(&s, label);
        getoper(&s, operator);

        /* if not ASHC, don't go on */
        if (strcmp(operator, ASHC) != 0)
                return(0);

        /* it's an ASHC -- get the operands */
        getand(&s, foperand);
        getand(&s, soperand);

        /* be sure they're really there */
        if (*foperand == '\0' || *soperand == '\0'){
                fprintf(stderr, "%s, line %d: ashc takes 2 operands\n", pgnm, linect);
                return(0);
        }

        /* success */
        return(1);
}

/*
 * This gets a label (if any) from the input line
 * Legal label chars are alphanumerics and _.~
 */
getlabel(s, l)
char **s, *l;
{
        char *p, *lp;

        /* grab first identifier on line */
        for(p = *s, lp = l; isalnum(*p) || *p == '_' || *p == '.' || *p == '~'; p++, lp++)
                *lp = *p;
        /* it's a label */
        if (*p == ':'){
                *lp = '\0';
                for(p++; isspace(*p); p++);  /* eat trailing spaces */
                *s = p;
        }
        else    /* bullfeathers */
                *l = '\0';
        return;
}

/*
 * This gets an operator (if any) from the input line
 * Legal operator chars are alphanumerics
 */
getoper(s, l)
char **s, *l;
{
        char *p;

        /* grap next identifier */
        for(p = *s; isalnum(*p); p++, l++)
                *l = *p;

        /* eat trailing spaces */
        for(; isspace(*p); p++);

        *l = '\0';
        *s = p;
        return;
}

/*
 * This gets an operand (if any) from the input line
 * Legal operand chars are alphanumerics and $()+-_.
 */
getand(s, l)
char **s, *l;
{
        char *p;

        /* grab the identifier */
        for(p = *s; isalnum(*p) || *p == '$' || *p == '(' || *p == ')' || *p == '-' || *p == '+' || *p == '.' || *p == '_'; p++, l++)
                *l = *p;

        /* eat trailing comma, spaces */
        if (*p == ',')
                p++;
        for(; isspace(*p); p++);

        *l = '\0';
        *s = p;
        return;
}