home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * Copyright (c) 1988 by Sozobon, Limited. Author: Joseph M Treat
- *
- * Permission is granted to anyone to use this software for any purpose
- * on any computer system, and to redistribute it freely, with the
- * following restrictions:
- * 1) No charge may be made other than reasonable charges for reproduction.
- * 2) Modified versions must be clearly marked as such.
- * 3) The authors are not responsible for any harmful consequences
- * of using this software, even if they result from defects in it.
- */
-
- #include "jas.h"
-
- geninst( sp )
- STMT *sp;
- {
- register OPERAND *op;
- register char *cp;
- register short nbits = 0;
- register long fill = 0L;
- register short emode, ereg;
- OPERAND *eff[2];
- int which, do_immediate = 0;
- CBUF *cbp;
- extern int line;
- extern long newdot;
- extern Optimize;
- extern CBUF *generate();
-
- findinst( sp );
- eff[0] = eff[1] = (OPERAND *) NULL;
-
- if ( sp->op0 && sp->op0->mode == O_IMM )
- do_immediate = 1;
-
- for ( cp = sp->inst->format; *cp; cp++ ) {
- if ( *cp == 'o' ) {
- do {
- cp++;
- fill = ( fill << 3 ) | ( *cp - '0' );
- nbits += 3;
- } while ( cp[1] >= '0' && cp[1] <= '7' );
- } else if ( *cp == 'x' ) {
- do {
- cp++;
- if ( *cp <= '9' )
- fill = ( fill << 4 ) | ( *cp - '0' );
- else
- fill = ( fill << 4 ) | (*cp - 'a' + 10);
- nbits += 4;
- } while ( (cp[1] >= '0' && cp[1] <= '9') ||
- (cp[1] >= 'a' && cp[1] <= 'f'));
-
- } else if ( *cp == '0' ) {
- fill = ( fill << 1 );
- nbits++;
- } else if ( *cp == '1' ) {
- fill = ( fill << 1 ) | 1;
- nbits++;
- } else if ( *cp == '$' ) {
- switch ( *++cp ) {
- case 's':
- fill = ( fill << 2 ) |
- ( ( sp->misc & (S_BWL) ) >> 1 );
- nbits += 2;
- break;
- case 'c':
- fill = ( fill << 4 ) | ( sp->misc >> 4 );
- nbits += 4;
- break;
- case 'd':
- fill = ( fill << 1 ) |
- ( ( sp->misc & 0x8 ) >> 3 );
- nbits++;
- break;
- }
- } else if ( *cp == '%' ) {
- OPERAND *mp;
-
- cp++;
- if ( *cp == '0' ) {
- which = 0;
- op = sp->op0;
- cp++;
- } else if ( *cp == '1' ) {
- which = 1;
- op = sp->op1;
- cp++;
- } else if ( *cp >= 'A' && *cp <= 'Z' ) {
- which = 1;
- op = sp->op1;
- } else /* if ( *cp >= 'a' && *cp <= 'z' ) */ {
- which = 0;
- op = sp->op0;
- }
-
- switch ( *cp ) {
- case 'r':
- fill = ( fill << 3 ) | (op->reg & 0x7 );
- nbits += 3;
- break;
- case 'q':
- fill = ( fill << 3 ) | (op->expr.value & 0x7);
- nbits += 3;
- do_immediate = 0;
- break;
- case 'k':
- fill = ( fill << 8 ) | (op->expr.value & 0xff);
- nbits += 8;
- do_immediate = 0;
- break;
- case 'v':
- fill = ( fill << 4 ) | (op->expr.value & 0x0f);
- nbits += 4;
- do_immediate = 0;
- break;
- case 'm':
- if ( nbits % 8 )
- error( line, "internal alignment" );
- generate( nbits, GENSTMT, fill, (SYM *) NULL );
- nbits = 0;
- fill = 0L;
- if ( op->mode == O_DN || op->mode == O_AN )
- op->expr.value = 1L << op->reg;
- op->mode = O_REGS;
- mp = ( which == 0 ) ? sp->op1 : sp->op0;
- if ( mp->mode == O_PRE ) {
- /*
- * we must reverse the bits !GAG!
- */
- int i, k;
-
- k = op->expr.value;
- for ( i = 0; i < 16; i++ ) {
- fill <<= 1;
- if ( k & 1 )
- fill |= 1;
- k >>= 1;
- }
- generate( 16, GENVALUE, fill,
- (SYM *) NULL );
- fill = 0L;
- } else {
- generate( 16, GENVALUE, op->expr.value,
- (SYM *) NULL );
- }
- break;
- case 'd':
- if (! Optimize ) {
- fill <<= 8;
- nbits += 8;
- if ( nbits % 8 )
- error( line,
- "internal alignment" );
- generate( nbits, GENSTMT, fill,
- (SYM *) NULL);
- nbits = 0;
- fill = 0L;
- generate( 16, GENPCREL, op->expr.value,
- op->expr.psym);
- break;
- }
- if ( nbits != 8 )
- error( line, "internal alignment" );
- cbp = generate(8, GENBRNCH, fill, (SYM *) NULL);
- nbits = 0;
- fill = 0L;
-
- generate( 8, GENPCREL, op->expr.value,
- op->expr.psym);
- add_brnch( cbp, newdot );
- break;
- case 'D':
- if ( nbits % 8 )
- error( line, "internal alignment" );
- generate( nbits, GENSTMT, fill, (SYM *) NULL );
- nbits = 0;
- fill = 0L;
- generate( 16, GENPCREL, op->expr.value,
- op->expr.psym);
- break;
- case 'L':
- if ( nbits % 8 )
- error( line, "internal alignment" );
- generate( nbits, GENSTMT, fill, (SYM *) NULL );
- nbits = 0;
- fill = 0L;
- generate( 16, GENVALUE, op->expr.value,
- (SYM *) NULL );
- break;
- case 'f':
- case 'e':
- emode = ereg = 0;
- switch ( op->mode ) {
- case O_DN:
- emode = 0x0;
- ereg = op->reg & 0x7;
- break;
- case O_AN:
- emode = 0x1;
- ereg = op->reg & 0x7;
- break;
- case O_INDR:
- emode = 0x2;
- ereg = op->reg & 0x7;
- break;
- case O_POST:
- emode = 0x3;
- ereg = op->reg & 0x7;
- break;
- case O_PRE:
- emode = 0x4;
- ereg = op->reg & 0x7;
- break;
- case O_DISP:
- emode = 0x5;
- ereg = op->reg & 0x7;
- eff[which] = op;
- break;
- case O_INDX:
- emode = 0x6;
- ereg = op->reg & 0x7;
- eff[which] = op;
- break;
- case O_ABS:
- emode = 0x7;
- ereg = 0x1;
- eff[which] = op;
- break;
- case O_PCRL:
- emode = 0x7;
- ereg = 0x2;
- eff[which] = op;
- break;
- case O_PCIX:
- emode = 0x7;
- ereg = 0x3;
- eff[which] = op;
- break;
- case O_IMM:
- emode = 0x7;
- ereg = 0x4;
- break;
- }
- if ( *cp == 'e' ) {
- fill = ( fill << 3 ) | emode;
- fill = ( fill << 3 ) | ereg;
- } else {
- fill = ( fill << 3 ) | ereg;
- fill = ( fill << 3 ) | emode;
- }
- nbits += 6;
- break;
- }
- }
- }
- if ( nbits % 8 )
- error( line, "internal alignment" );
- if ( nbits ) {
- generate( nbits, GENSTMT, fill, (SYM *) NULL );
- nbits = 0;
- }
- fill = 0L;
- if ( do_immediate ) {
- int size;
- op = sp->op0;
-
- size = sp->misc & (S_BWL);
- if ( size == S_B ) {
- generate( 8, GENVALUE, 0L, (SYM *) NULL );
- }
- generate( size << 3, GENRELOC, op->expr.value, op->expr.psym );
- }
- for ( which = 0; which <= 1; which++ ) {
- if ( eff[which] == (OPERAND *) NULL )
- continue;
- op = eff[which];
- switch ( op->mode ) {
- case O_DISP:
- generate( 16, GENRELOC, op->expr.value, op->expr.psym );
- break;
- case O_INDX:
- fill = op->inx & 0x0f;
- fill = ( fill << 4 ) | ((op->inx & 0x10) >> 1);
- generate(8, GENVALUE, fill, (SYM *) NULL );
- generate( 8, GENRELOC, op->expr.value, op->expr.psym );
- break;
- case O_ABS:
- if ( sp->inst->flags & F_PC )
- generate( 16, GENPCREL, op->expr.value,
- op->expr.psym );
- else
- generate( 32, GENRELOC, op->expr.value,
- op->expr.psym );
- break;
- case O_PCRL:
- generate( 16, GENVALUE, op->expr.value, (SYM *) NULL );
- break;
- case O_PCIX:
- fill = op->inx & 0x0f;
- fill = ( fill << 4 ) | ((op->inx & 0x10) >> 1);
- generate(8, GENVALUE, fill, (SYM *) NULL );
- generate( 8, GENVALUE, op->expr.value, (SYM *) NULL );
- break;
- }
- }
- }
-
- findinst( sp )
- STMT *sp;
- {
- register INST *ip;
- register INST *jp;
-
- ip = sp->inst;
- for ( ; ; ) {
- if (! inst_ok( sp ) ) {
- return;
- }
- jp = ip+1;
- if (! strcmp( jp->mnemon, ip->mnemon ) ) {
- sp->inst = ip = jp;
- continue;
- }
- break;
- }
- Yerror( "illegal instruction" );
- }
-
- inst_ok( sp )
- register STMT *sp;
- {
- register INST *ip = sp->inst;
- register unsigned short size;
- extern Optimize;
-
- if (! Optimize ) {
- /*
- * if we're not optimizing, don't change jsr's to bsr's
- */
- if (! strncmp( ip->mnemon, "jsr", 3 ) )
- if (! strncmp( ip->format, "x61", 3 ) )
- return -18;
- }
-
- if ( ip->op0 != O_NONE && sp->op0 == (OPERAND *) NULL )
- return -1;
- if ( ip->op1 != O_NONE && sp->op1 == (OPERAND *) NULL )
- return -2;
- if ( sp->op1 && ip->op1 == O_NONE )
- return -3;
- if ( sp->op0 ) {
- if ( ip->op0 == O_NONE )
- return -4;
- if ( ( sp->op0->mode & ip->op0 ) != sp->op0->mode )
- return -5;
- }
- if ( sp->op1 ) {
- if ( ip->op1 == O_NONE )
- return -6;
- if ( ( sp->op1->mode & ip->op1 ) != sp->op1->mode )
- return -7;
- }
- size = sp->misc & (S_BWL);
- if ( ( size & ip->size ) != size )
- return -8;
- if ( ip->flags & F_Q ) {
- long val = sp->op0->expr.value;
-
- if ( sp->op0->expr.psym )
- return -9;
- if ( val < 1 || val > 8 )
- return -10;
- }
- if ( ip->flags & F_MQ ) {
- long val = sp->op0->expr.value;
-
- if ( sp->op0->expr.psym )
- return -11;
- if ( val < -128 || val > 127 )
- return -12;
- }
- if ( ip->flags & F_TV ) {
- long val = sp->op0->expr.value;
-
- if ( sp->op0->expr.psym )
- return -13;
- if ( val < 0 || val > 15 )
- return -14;
- }
- if ( ip->flags & F_TXT ) {
- OPERAND *op = sp->op0;
-
- if ( op->mode == O_DN ) /* the db$c instruction */
- op = sp->op1;
- switch ( op->mode ) {
- case O_DISP: case O_INDX:
- if ( op->expr.psym ) {
- switch ( op->expr.psym->flags & SEGMT ) {
- case 0: case TXT:
- break;
- default:
- return -15;
- }
- }
- break;
- case O_ABS:
- if ( op->expr.psym == (SYM *) NULL )
- return -16;
- switch ( op->expr.psym->flags & SEGMT ) {
- case 0: case TXT:
- break;
- default:
- return -17;
- }
- break;
- }
- }
-
- /*
- * set the default size, if none is specified
- */
- if ( size == 0 )
- sp->misc |= ( ip->flags & (S_BWL) );
-
- return 0;
- }
-