#include #include #include #include "as.h" #include "arg_type.h" process_label() {} process_mnemonic( m) char *m; { for ( ; *m != '\0'; m++) if ( *m == '.') *m = '_'; } process_operand( str, op) register char *str; register struct t_operand *op; { char *glob_lbl(), *strchr(); op->type = 0; switch ( *str) { case '#' : op->type = IS_IMMEDIATE; op->expr = str+1; if ( *(op->expr) != '$') { /* #1 */ op->val = atoi( str+1); if ( 1 <= op->val && op->val <= 8 ) { op->type = IS_QUICK; op->lbl = NULL; } } else if ( arg_type( str+1) == STRING) { /* #$1+$2 */ op->lbl = op->expr; *(op->lbl+2) = '\0'; op->expr = op->lbl+3; } else /* #$1 */ op->lbl = NULL; break; case '(' : if ( strchr( str+1, ',') == NULL) if ( is_reg( str+1)) { op->reg = reg_val( str+1); if ( *(str+4) == '+') /* (sp)+ */ op->type = IS_INCR; else /* (a0) */ op->type = IS_IND_REG; } else { op->type = IS_IND_MEM; op->expr = str+1; for ( str++; *++str != ')';) ; *str = '\0'; if ( *(op->expr) == '$') if ( arg_type( op->expr) == STRING) { /* ($1+$2) */ op->lbl = op->expr; if ( strlen( op->lbl) == 2) op->expr = "0"; else { *(op->lbl+2) = '\0'; op->expr = op->lbl+3; } } else /* ($1) */ op->lbl = NULL; else if ( isdigit( *(op->expr))) /* (1) */ op->lbl = NULL; else { /* (.trppc) */ op->lbl = glob_lbl( op->expr); op->expr = "0"; } } else if ( *(str+1) == '[') { op->type = IS_IND_IND; op->expr = str+2; for ( str += 2; *++str != ',';) ; *str++ = '\0'; for ( ; *str == ' '; str++) ; op->reg = reg_val( str); for ( ; *str++ != ']';) ; if ( *str == ')') /* ([$1, a6]) */ op->expr2 = 0; else { /* ([8,a6],8) */ for ( ; *str++ != ',';) ; for ( ; *str == ' '; str++) ; op->expr2 = atoi( str); } } else { op->expr = str+1; for ( str++; *++str != ',';) ; *str++ = '\0'; for ( ; *str == ' '; str++) ; op->reg = reg_val( str); if ( *(str+2) == ')') /* (4, a0) */ op->type = IS_IND_REG_DISPL; else { /* (0, sp, d0.l*1) */ op->type = IS_3_OPS; for ( str++; *++str != ',';) ; for ( ; *str == ' '; str++) ; op->reg2 = reg_val( str); for ( ; *str++ != '*';) ; op->scale = atoi( str); } } break; case '-' : op->type = IS_DECR; /* -(sp) */ op->reg = reg_val( str+2); break; case '$' : op->type = IS_GLOB_LBL; /* $1 */ op->lbl = str; op->expr ="0"; break; default : if ( is_reg( str)) { op->reg = reg_val( str); if ( *(str+2) == ':') { /* d2:d1 */ op->type = IS_REG_PAIR; op->reg2 = reg_val( str+3); } else /* a6 */ op->type = ( *str == 'd' ? IS_D_REG : IS_A_REG); } else if ( isdigit( *str)) { /* 1f */ op->type = IS_LOC_LBL; op->lbl = str; op->expr = "0"; *(str+1) ='\0'; } else { /* .strhp */ op->type = IS_GLOB_LBL; op->lbl = glob_lbl( str); *(str+1) ='\0'; op->expr = "0"; } } } int reg_val( reg) char *reg; { return( *reg == 's' ? 7 : atoi( reg+1)); } int is_reg( str) register char *str; { switch ( *str) { case 'a' : case 'd' : return( isdigit( *(str+1))); case 's' : return( *(str+1) == 'p'); default : return( 0); } } char *glob_lbl( lbl) char *lbl; { char *gl, *Malloc(); gl = Malloc( strlen( lbl) + 3); sprintf( gl, "\"%s\"", lbl); return( gl); } /******************************************************************************/ int mode_reg( eaddr) register struct t_operand *eaddr; { switch ( eaddr->type) { case IS_A_REG : return( 0x08 | eaddr->reg); case IS_D_REG : return( 0x00 | eaddr->reg); case IS_IND_REG : return( 0x10 | eaddr->reg); case IS_INCR : return( 0x18 | eaddr->reg); case IS_DECR : return( 0x20 | eaddr->reg); case IS_IND_MEM : return( 0x39); case IS_IND_IND : return( 0x30 | eaddr->reg); case IS_IND_REG_DISPL : return( 0x28 | eaddr->reg); case IS_GLOB_LBL : return( 0x39); case IS_3_OPS : if ( isdigit( *(eaddr->expr)) && atoi( eaddr->expr) < 128) return( 0x30 | eaddr->reg); else fprintf( stderr, "FOUT in IS_3_OPS\n"); break; case IS_QUICK : case IS_IMMEDIATE : return( 0x3c); default : fprintf( stderr, "mode_reg(), verkeerde operand %d\n", eaddr->type); abort(); break; } } code_extension( eaddr) register struct t_operand *eaddr; { switch ( eaddr->type) { case IS_IND_MEM : if ( eaddr->lbl == NULL) @text4( %$( eaddr->expr)); else @reloc4( %$( eaddr->lbl), %$( eaddr->expr), ABSOLUTE); break; case IS_IND_IND : if ( eaddr->expr2 == 0) { @text2( 0x161); @text2( %$(eaddr->expr)); } else { @text2( 0x162); @text2( %$(eaddr->expr)); @text2( %d(eaddr->expr2)); } break; case IS_IND_REG_DISPL : @text2( %$( eaddr->expr)); break; case IS_GLOB_LBL : @reloc4( %$(eaddr->lbl), %$(eaddr->expr), ABSOLUTE); break; case IS_3_OPS : if ( isdigit( *(eaddr->expr)) && atoi( eaddr->expr) < 128) { @text2( %d( 0x0800 | ( eaddr->reg2 << 12) | ( two_log( eaddr->scale)<<9) | atoi( eaddr->expr))); } else fprintf( stderr, "FOUT in IS_3_OPS\n"); break; case IS_QUICK : case IS_IMMEDIATE : if ( eaddr->lbl != NULL) @reloc4( %$(eaddr->lbl), %$(eaddr->expr), ABSOLUTE); else @text4( %$(eaddr->expr)); } } int reg_mode( eaddr) struct t_operand *eaddr; { int mr; mr = mode_reg( eaddr); return( ((mr & 0x7) << 3) | ((mr & 0x38) >> 3)); } code_opcode( opcode, field1, field2, eaddr) int opcode, field1, field2; struct t_operand *eaddr; { @text2( %d(((opcode & 0xf) << 12) | ((field1 & 0x7) << 9) | ((field2 & 0x7) << 6) | (mode_reg(eaddr) & 0x3f))); } code_instr( opcode, field1, field2, eaddr) int opcode, field1, field2; struct t_operand *eaddr; { if (eaddr->type == IS_IND_REG_DISPL) { @__instr_code(%d(((opcode & 0xf) << 12) | ((field1 & 0x7) << 9) | ((field2 & 0x7) << 6)), %d(eaddr->reg), %$(eaddr->expr)); } else { code_opcode( opcode, field1, field2, eaddr); code_extension( eaddr); } } code_move( size, src, dst) int size; struct t_operand *src, *dst; { if (src->type == IS_IND_REG_DISPL) { if (dst->type == IS_IND_REG_DISPL) { @__moveXX(%d( ((size & 0x3) << 12)), %d(dst->reg), %$(dst->expr), %d(src->reg), %$(src->expr)); } else { @__instr_code(%d( ((size & 0x3) << 12)|((reg_mode( dst) & 0x3f) << 6)), %d(src->reg), %$(src->expr)); } } else if (dst->type == IS_IND_REG_DISPL) { @__move_X(%d( ((size & 0x3) << 12) | (mode_reg( src) & 0x3f)), %d(dst->reg), %$(dst->expr)); } else { @text2( %d( ((size & 0x3) << 12) | ((reg_mode( dst) & 0x3f) << 6) | (mode_reg( src) & 0x3f))); code_extension( src); code_extension( dst); } } code_dist4( dst) struct t_operand *dst; { @reloc4( %$(dst->lbl), %$(dst->expr) + 4, PC_REL); } int two_log( nr) register int nr; { register int log; for ( log = 0; nr >= 2; nr >>= 1) log++; return( log); }