123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- */
- #define RCSID5 "$Id$"
- settype( type )
- int type;
- { oprtype[ operand ] = type; }
- int twolog( s )
- int s;
- { int twopower = 0;
- while ( (s>>=1) != 0 ) twopower++;
- return( twopower );
- }
- setmode( opr )
- int opr;
- { mode = modetbl[ twolog( oprtype[opr] ) ] << 12; }
- chtype( opr, typerange )
- int opr,
- typerange;
- /* Check type of 'opr' with given 'typerange' and
- ** set the global var 'mode'.
- */
- { if ( (oprtype[opr] & typerange) != oprtype[opr] ) argerr();
- else /* We have a permitted type for 'opr'. */ setmode( opr );
- }
- chreg( opc, reg )
- int opc, reg;
- { switch( opc ) {
- case 0xB10A: case 0x1B00: case 0x1900:
- /* R32 expected */ if (reg & 1) regerr(); break;
- case 0xB107: case 0x1A00: case 0x1800:
- /* R64 expected */ if (reg & 3) regerr(); break;
- }
- }
- ATYPE checkaddr( addr )
- valu_t addr;
- /* Called by functions emit_ad() and branch(). */
- { ATYPE addr_struct;
- addr_struct.seg = addr >> 16;
- addr_struct.off = addr & 0xFFFF;
- if ( addr_struct.seg < 0 ) addr_struct.seg = 0;
- #ifdef ASLD
- else fit(fit7(addr_struct.seg));
- #endif
- return( addr_struct );
- }
- emit_ad( ad_inf )
- expr_t ad_inf;
- /* When the type of an operand is 'da' or 'x' this function
- ** emits the address.
- */
- { ATYPE addr;
- addr = checkaddr( ad_inf.val );
- /* Always the long format is emitted, because the binary
- ** will be downloaded into one z8000-segment with offset
- ** 0x0000 upto 0xFFFF,so the chance we can use the short
- ** format is very small.
- */
- emit2( 1<<15 | addr.seg<<8 );
- emit2( addr.off ); /* ??? relocation information ??? */
- }
- ldmcode( wrd1, wrd2, num )
- int wrd1, wrd2, num;
- { fit(fit4(num-1));
- emit2( mode | wrd1 );
- emit2( wrd2<<8 | num-1 );
- if ( mode>>12 == 4 ) emit_ad( addr_inf );
- }
- valu_t adjust( absval )
- valu_t absval;
- { valu_t val = absval - DOTVAL - 2;
- if ( pass == PASS_2 && val > 0 ) val -= DOTGAIN;
- return( val );
- }
- branch( opc, exp )
- int opc;
- expr_t exp;
- /* This routine determines for the F3 format instructions whether the
- ** relative address is small enough to fit in normal code; If this is
- ** so normal code is emitted otherwise 'long' code is emitted contai-
- ** ning the direct address.
- */
- { int longopc = 0, reladdr = 0, sm2, sm4;
- valu_t val;
- ATYPE addr;
- val = adjust(exp.val) >> 1;
- if ( (exp.typ & ~S_DOT) != DOTTYP ) sm2 = sm4 = 0;
- else
- { switch ( opc & 0xF000 )
- { case DJNZ_: sm2 = fit7( -val );
- reladdr = -val;
- break;
- case JR_: sm2 = fits8( val );
- reladdr = low8( val );
- longopc = 0x5E00 | (opc>>8 & 0xF);
- break;
- case CALR_: sm2 = fits12( -val );
- reladdr = low12( -val );
- longopc = 0x5F00;
- break;
- }
- sm4 = sm2 || fit8( (int)exp.val );
- }
- switch ( opc & 0xF000 )
- { case DJNZ_: fit( sm2 ); /* djnz must be short */
- emit2( opc | reladdr );
- break;
- case JR_: case CALR_:
- sm4 = small(sm4, 2);
- sm2 = small(sm2, 2);
- if ( sm2 ) emit2( opc | reladdr );
- else /* replace by jp/call da */
- { emit2( longopc );
- addr = checkaddr( exp.val );
- if ( sm4 ) /* short-offset */
- emit2( addr.seg<<8 | addr.off );
- else
- { emit2( 1<<15 | addr.seg<<8 );
- emit2( addr.off );
- }
- }
- }
- }
- ldrel( opc, exp )
- int opc;
- expr_t exp;
- /* This routine determines for the F4 format instructions whether the
- ** address is within the same segment (meaning a relative address of
- ** less than 16 bits); If this is so normal code is emitted otherwise
- ** an error message is given.
- */
- { if ( pass >= PASS_2 && (exp.typ & ~S_DOT) != DOTTYP )
- serror( "relative too far" );
- emit2( opc );
- emit2( (int)adjust(exp.val) );
- }
- shiftcode( w1, w2 )
- int w1, w2;
- { switch( w1 & 0x0F04 )
- { /* Remember: w2 negative means right shift ! */
- case 0x200: /*byte*/ fit( w2>=-8 && w2<=8 ); break;
- case 0x300: /*word*/ fit( w2>=-16 && w2<=16 ); break;
- case 0x304: /*long*/ fit( w2>=-32 && w2<=32 ); break;
- }
- emit2( w1 );
- emit2( w2 );
- }
- argerr()
- { serror( "illegal operand" ); }
|