417 lines
10 KiB
C
417 lines
10 KiB
C
|
#define RCSID4 "$Header$"
|
||
|
|
||
|
/*
|
||
|
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||
|
*
|
||
|
* This product is part of the Amsterdam Compiler Kit.
|
||
|
*
|
||
|
* Permission to use, sell, duplicate or disclose this software must be
|
||
|
* obtained in writing. Requests for such permissions may be sent to
|
||
|
*
|
||
|
* Dr. Andrew S. Tanenbaum
|
||
|
* Wiskundig Seminarium
|
||
|
* Vrije Universiteit
|
||
|
* Postbox 7161
|
||
|
* 1007 MC Amsterdam
|
||
|
* The Netherlands
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
/* Author: Ed Keizer */
|
||
|
|
||
|
operation:
|
||
|
BR expr
|
||
|
/* format 0 */
|
||
|
{ dot_adjust(&$2) ; form0($1) ; disp(&$2, RELPC) ;}
|
||
|
| WAIT
|
||
|
/* format 1 */
|
||
|
{ form1($1) ;}
|
||
|
| BSR expr
|
||
|
/* format 1 */
|
||
|
{ dot_adjust(&$2) ; form1($1) ; disp(&$2, RELPC) ;}
|
||
|
| RET expr
|
||
|
/* format 1 */
|
||
|
{ form1($1) ; disp(&$2, 0) ;}
|
||
|
| SAVE reg_list
|
||
|
/* format 1 */
|
||
|
{ form1($1) ; emit1(reg_list($2,id_op($1)!=0x6)) ;}
|
||
|
| ENTER reg_list ',' expr
|
||
|
/* format 1 */
|
||
|
{ form1($1) ; emit1(reg_list($2,0)) ; disp(&$4, 0) ;}
|
||
|
| LPR AREG ',' gen1
|
||
|
/* format 2 */
|
||
|
{ if ( id_op($1)==0x2 ) not_imm(&mode1) ;
|
||
|
form2($1,$2) ; gen1($1) ;
|
||
|
}
|
||
|
| SEQ gen1
|
||
|
/* format 2 */
|
||
|
{ form2($1,id_cc($1)) ; gen1($1) ; not_imm(&mode1) ;}
|
||
|
| MOVQ absexp ',' gen1
|
||
|
/* format 2 */
|
||
|
{
|
||
|
if ( !fit4($2) ) {
|
||
|
serror("Constant too large") ;
|
||
|
}
|
||
|
form2($1,low4($2)) ; gen1($1) ;
|
||
|
if ( id_op($1)!=0x1 ) not_imm(&mode1) ; /* !cmp */
|
||
|
}
|
||
|
| ACB absexp ',' gen1 ',' expr
|
||
|
/* format 2 */
|
||
|
{
|
||
|
dot_adjust(&$6) ;
|
||
|
if (!fit4($2) ) {
|
||
|
serror("Constant too large") ;
|
||
|
}
|
||
|
form2($1,low4($2)) ; gen1($1) ; not_imm(&mode1) ;
|
||
|
disp(&$6, RELPC) ;
|
||
|
}
|
||
|
| ADJSP gen1
|
||
|
/* format 3 */
|
||
|
{
|
||
|
if ( id_op($1)==0 ) not_imm(&mode1) ; /* cxpd */
|
||
|
form3($1) ; gen1($1) ;}
|
||
|
| JSR gen1
|
||
|
/* format 3 */
|
||
|
{
|
||
|
#ifndef NO_OPTIM
|
||
|
if ( mode1.m_mode==0x15 ) { /* Absolute */
|
||
|
dot_adjust(&mode1.m_expr1) ;
|
||
|
RELOMOVE(relonami, mode1.m_rel1);
|
||
|
form1(0) ; disp(&mode1.m_expr1, RELPC) ; /* bsr */
|
||
|
} else
|
||
|
#endif
|
||
|
{ form3($1) ; gen1($1) ; }
|
||
|
not_imm(&mode1) ;
|
||
|
}
|
||
|
| JUMP gen1
|
||
|
/* format 3 */
|
||
|
{
|
||
|
#ifndef NO_OPTIM
|
||
|
if ( mode1.m_mode==0x15 ) { /* Absolute */
|
||
|
dot_adjust(&mode1.m_expr1) ;
|
||
|
RELOMOVE(relonami, mode1.m_rel1);
|
||
|
form0(B_TRUE) ; disp(&mode1.m_expr1, RELPC) ; /* br */
|
||
|
} else
|
||
|
#endif
|
||
|
{ form3($1) ; gen1($1) ; }
|
||
|
not_imm(&mode1) ;
|
||
|
}
|
||
|
| ADD_I gen1 ',' gen2
|
||
|
/* format 4 */
|
||
|
{
|
||
|
register opc ;
|
||
|
opc=id_op($1) ;
|
||
|
if ( opc==0x9 ) not_imm(&mode1) ; /* addr */
|
||
|
if ( opc!=0x1 ) not_imm(&mode2) ; /* !cmp */
|
||
|
#ifndef NO_OPTIM
|
||
|
if ( mode1.m_mode==0x14 && /* Immediate */
|
||
|
(mode1.m_expr1.typ & ~S_EXT) == S_ABS &&
|
||
|
(
|
||
|
(fit4(mode1.m_expr1.val) &&
|
||
|
(opc==0 || opc==1 || opc==5))
|
||
|
||
|
||
|
(fit4(-mode1.m_expr1.val) &&
|
||
|
(opc==8))
|
||
|
)
|
||
|
)
|
||
|
{
|
||
|
/* Warning, an absolute expression derived
|
||
|
from a symbol that is defined after
|
||
|
use might - if the value now suddenly fits -
|
||
|
cause failed assertions in newlabel
|
||
|
*/
|
||
|
/* add, cmp, mov */
|
||
|
/* added: the subtract of a signed
|
||
|
* short is the same as the add
|
||
|
* of the negation of that short
|
||
|
* so: subi short,x == addqi -short,x
|
||
|
* 19/04/85 h.m.kodden,m.j.a.leliveld
|
||
|
*/
|
||
|
if (opc==8) /* do the negate */
|
||
|
mode1.m_expr1.val =
|
||
|
(~mode1.m_expr1.val+1)&0xF;
|
||
|
opc=low4(mode1.m_expr1.val) ;
|
||
|
mode1= mode2 ;
|
||
|
form2($1,opc) ; gen1($1) ;
|
||
|
} else
|
||
|
#endif
|
||
|
{ form4($1) ; gengen($1) ; }
|
||
|
}
|
||
|
| SETCFG cpu_opts
|
||
|
/* format 5 */
|
||
|
{ form5($1,$2) ;}
|
||
|
| MOVS string_opts
|
||
|
/* format 5 */
|
||
|
{ form5($1,($2)|id_cc($1)) ;}
|
||
|
| COM gen1 ',' gen2
|
||
|
/* format 6 */
|
||
|
{ form6($1) ; gengen($1) ; not_imm(&mode2) ;}
|
||
|
| MUL_I gen1 ',' gen2
|
||
|
/* format 7 */
|
||
|
{
|
||
|
if ( id_op($1)==0x9 || id_op($1)==0xB ) {
|
||
|
/* mei or dei */
|
||
|
switch ( mode2.m_mode ) {
|
||
|
case 1 : case 3 : case 5 : case 7 :
|
||
|
serror("register must be even") ;
|
||
|
}
|
||
|
}
|
||
|
form7($1) ; gengen($1) ; not_imm(&mode2) ;
|
||
|
}
|
||
|
| MOVID gen1 ',' gen2
|
||
|
/* format 7 */
|
||
|
{ form7x($1,id_g1($1)) ; gengen($1) ; not_imm(&mode2) ;}
|
||
|
| MOVM gen1 ',' gen2 ',' expr
|
||
|
/* format 7 */
|
||
|
{
|
||
|
register s_size ;
|
||
|
s_size= id_g1($1)+1 ;
|
||
|
/* $6.val= $6.val*s_size - s_size ; */
|
||
|
$6.val= $6.val -1 ;
|
||
|
form7($1) ; gengen($1) ; disp(&$6, 0) ;
|
||
|
not_imm(&mode1) ; not_imm(&mode2) ;
|
||
|
}
|
||
|
| INSS gen1 ',' gen2 ',' absexp ',' absexp
|
||
|
/* format 7 */
|
||
|
{
|
||
|
if ( ( $6<0 || $6>7 || $8<1 || $8>32 )
|
||
|
) { serror("Constant out of bounds") ; }
|
||
|
form7($1) ; gengen($1) ;
|
||
|
if ( id_op($1)==0x3 ) not_imm(&mode1) ; /* exts */
|
||
|
not_imm(&mode2) ;
|
||
|
emit1((((int)$6)<<5)+(int)$8-1) ;
|
||
|
}
|
||
|
| FFS gen1 ',' gen2
|
||
|
/* format 8 */
|
||
|
{ form8($1,id_cc($1)) ; gengen($1) ; not_imm(&mode2) ;}
|
||
|
| CHECK REG ',' gen1 ',' gen2
|
||
|
/* format 8 */
|
||
|
{
|
||
|
form8($1,$2) ; gengen($1) ;
|
||
|
if ( id_op($1)!=0x4 ) {
|
||
|
not_imm(&mode1) ; /* check, cvtp */
|
||
|
if ( id_op($1)==0x1 ) not_imm(&mode2) ;/*cvtp */
|
||
|
}
|
||
|
}
|
||
|
| INS REG ',' gen1 ',' gen2 ',' expr
|
||
|
/* format 8 */
|
||
|
{
|
||
|
form8($1,$2) ; gengen($1) ; disp(&$8, 0) ;
|
||
|
if ( id_op($1)==0x0 ) not_imm(&mode1) ;
|
||
|
not_imm(&mode2) ;
|
||
|
}
|
||
|
| MOVIF gen1 ',' fgen2
|
||
|
/* format 9 */
|
||
|
{
|
||
|
assert( id_t1($1)==T_INT && id_t2($1)==T_FL ) ;
|
||
|
form9($1,id_g1($1),id_g2($1)) ; gengen($1) ;
|
||
|
not_imm(&mode2) ;
|
||
|
}
|
||
|
| MOVFL fgen1 ',' fgen2
|
||
|
/* format 9 */
|
||
|
{
|
||
|
assert( id_t1($1)==T_FL && id_t2($1)==T_FL ) ;
|
||
|
form9($1,id_g1($1),( id_g2($1)==F_LONG?3:2 )) ;
|
||
|
gengen($1) ; not_imm(&mode2) ;
|
||
|
}
|
||
|
| TRUNC fgen1 ',' gen2
|
||
|
/* format 9 */
|
||
|
{
|
||
|
assert( id_t1($1)==T_FL && id_t2($1)==T_INT ) ;
|
||
|
form9($1,id_g2($1),id_g1($1)) ; gengen($1) ;
|
||
|
not_imm(&mode2) ;
|
||
|
}
|
||
|
| LFSR gen1
|
||
|
/* format 9 */
|
||
|
{
|
||
|
if ( id_op($1)==6 ) { /* SFSR */
|
||
|
not_imm(&mode1) ;
|
||
|
mode2.m_mode=mode1.m_mode ;
|
||
|
mode1.m_mode=0 ;
|
||
|
} else {
|
||
|
mode2.m_mode=0 ;
|
||
|
}
|
||
|
form9($1,0,0) ;
|
||
|
if ( id_op($1)==6 ) {
|
||
|
mode1.m_mode=mode2.m_mode ;
|
||
|
}
|
||
|
gen1($1) ;
|
||
|
}
|
||
|
| ADD_F fgen1 ',' fgen2
|
||
|
/* format 11 */
|
||
|
{ if ( id_op($1)!=0x2 ) not_imm(&mode2) ; /* !CMPF */
|
||
|
form11($1) ; gengen($1) ;
|
||
|
}
|
||
|
| RDVAL gen1
|
||
|
/* format 14 */
|
||
|
{ form14($1,0) ; gen1($1) ; not_imm(&mode1) ;}
|
||
|
| LMR MREG ',' gen1
|
||
|
/* format 14 */
|
||
|
{
|
||
|
form14($1,$2) ; gen1($1) ;
|
||
|
if ( id_op($1)==0x3 ) not_imm(&mode1) ;
|
||
|
}
|
||
|
/* All remaining categories are not checked for
|
||
|
illegal immediates */
|
||
|
| LCR CREG ',' gen1
|
||
|
/* format 15.0 */
|
||
|
{ frm15_0($1,$2) ; gen1($1) ;}
|
||
|
| CATST gen1
|
||
|
/* format 15.0 */
|
||
|
{ frm15_0($1,0) ; gen1($1) ;}
|
||
|
| LCSR gen1
|
||
|
/* format 15.1 */ /* Sure? */
|
||
|
{ mode2.m_mode=0 ; frm15_1($1,0,0) ; gen1($1) ;}
|
||
|
| CCVIS gen1 ',' gen2
|
||
|
/* format 15.1 */
|
||
|
{
|
||
|
assert( id_t1($1)==T_INT && id_t2($1)==T_SLAVE ) ;
|
||
|
frm15_1($1,id_g1($1),id_g2($1)) ; gengen($1) ;
|
||
|
}
|
||
|
| CCVSI gen1 ',' gen2
|
||
|
/* format 15.1 */
|
||
|
{
|
||
|
assert( id_t1($1)==T_SLAVE && id_t2($1)==T_INT ) ;
|
||
|
frm15_1($1,id_g2($1),id_g1($1)) ; gengen($1) ;
|
||
|
}
|
||
|
| CCVSS gen1 ',' gen2
|
||
|
/* format 15.1 */
|
||
|
{
|
||
|
assert( id_t1($1)==T_SLAVE && id_t2($1)==T_SLAVE ) ;
|
||
|
frm15_1($1,0,0) ; gengen($1) ; /* Sure? */
|
||
|
}
|
||
|
| CMOV gen1 ',' gen2
|
||
|
/* format 15.5 */
|
||
|
{ frm15_5($1) ; gengen($1) ;}
|
||
|
;
|
||
|
|
||
|
gen1 : { mode_ptr= &mode1 ; clrmode() ; } gen
|
||
|
;
|
||
|
gen2 : { mode_ptr= &mode2 ; clrmode() ; } gen
|
||
|
;
|
||
|
fgen1 : { mode_ptr= &mode1 ; clrmode() ; } fgen
|
||
|
;
|
||
|
fgen2 : { mode_ptr= &mode2 ; clrmode() ; } fgen
|
||
|
;
|
||
|
|
||
|
gen : gen_not_reg /* Every mode except register */
|
||
|
| REG
|
||
|
{ mode_ptr->m_mode= $1 ; }
|
||
|
;
|
||
|
fgen : gen_not_reg /* Every mode except register */
|
||
|
| FREG
|
||
|
{ mode_ptr->m_mode= $1 ; }
|
||
|
;
|
||
|
|
||
|
gen_not_reg: gen_a /* general mode with eff. address */
|
||
|
| REG { mode_ptr->m_mode=$1 ;} index
|
||
|
/* The register is supposed to contain the
|
||
|
address
|
||
|
*/
|
||
|
| gen_a index /* As above, but indexed */
|
||
|
| expr /* Immediate */
|
||
|
{ mode_ptr->m_mode= 0x14 ;
|
||
|
mode_ptr->m_expr1= $1 ;
|
||
|
RELOMOVE(mode_ptr->m_rel1, relonami);
|
||
|
}
|
||
|
;
|
||
|
|
||
|
gen_a : expr '(' REG ')' /* Register relative */
|
||
|
{ mode_ptr->m_mode= 0x8 + $3 ;
|
||
|
mode_ptr->m_ndisp= 1 ;
|
||
|
mode_ptr->m_expr1= $1 ;
|
||
|
RELOMOVE(mode_ptr->m_rel1, relonami);
|
||
|
}
|
||
|
| expr '(' AREG ')' /* Memory space */
|
||
|
{ if ( $3<0x8 || $3>0xA ) badsyntax() ;
|
||
|
mode_ptr->m_mode= 0x18 + ($3&3) ;
|
||
|
mode_ptr->m_ndisp= 1 ;
|
||
|
mode_ptr->m_expr1= $1 ;
|
||
|
RELOMOVE(mode_ptr->m_rel1, relonami);
|
||
|
}
|
||
|
| expr '(' PC ')' /* Memory space */
|
||
|
{ mode_ptr->m_mode= 0x1B ;
|
||
|
mode_ptr->m_ndisp= 1 ;
|
||
|
mode_ptr->m_expr1= $1 ;
|
||
|
RELOMOVE(mode_ptr->m_rel1, relonami);
|
||
|
dot_adjust(&mode_ptr->m_expr1) ;
|
||
|
}
|
||
|
| expr '('
|
||
|
{ mode_ptr->m_expr2 = $1;
|
||
|
RELOMOVE(mode_ptr->m_rel2, relonami);
|
||
|
}
|
||
|
expr '(' AREG ')' ')' /* Memory relative */
|
||
|
{ if ( $6<0x8 || $6>0xA ) badsyntax() ;
|
||
|
mode_ptr->m_mode= 0x10 + ($6&3) ;
|
||
|
mode_ptr->m_ndisp= 2 ;
|
||
|
mode_ptr->m_expr1= $4 ;
|
||
|
RELOMOVE(mode_ptr->m_rel1, relonami);
|
||
|
}
|
||
|
| '@' expr /* Absolute */
|
||
|
{ mode_ptr->m_mode= 0x15 ;
|
||
|
mode_ptr->m_ndisp= 1 ;
|
||
|
mode_ptr->m_expr1= $2 ;
|
||
|
RELOMOVE(mode_ptr->m_rel1, relonami);
|
||
|
}
|
||
|
| EXTERNAL '(' expr ')'
|
||
|
{ mode_ptr->m_mode= 0x16 ;
|
||
|
mode_ptr->m_ndisp= 2 ;
|
||
|
mode_ptr->m_expr1= $3 ;
|
||
|
RELOMOVE(mode_ptr->m_rel1, relonami);
|
||
|
}
|
||
|
'+' expr /* External */
|
||
|
{
|
||
|
mode_ptr->m_expr2= $7 ;
|
||
|
RELOMOVE(mode_ptr->m_rel2, relonami);
|
||
|
}
|
||
|
| TOS /* Top Of Stack */
|
||
|
{ mode_ptr->m_mode= 0x17 ; }
|
||
|
;
|
||
|
|
||
|
index : '[' REG ':' INDICATOR ']' /* Indexed postfix */
|
||
|
{ mode_ptr->m_index= (mode_ptr->m_mode<<3) | $2 ;
|
||
|
mode_ptr->m_mode= ind_mode( $4 ) ;
|
||
|
}
|
||
|
;
|
||
|
|
||
|
cpu_opts:
|
||
|
'[' ']'
|
||
|
{ $$=0 ;}
|
||
|
| '[' cpu_list ']'
|
||
|
{ $$= $2 ;}
|
||
|
;
|
||
|
|
||
|
cpu_list:
|
||
|
INDICATOR
|
||
|
{ $$=cpu_opt($1) ; }
|
||
|
| cpu_list ',' INDICATOR
|
||
|
{ $$= ($1) | cpu_opt($3) ;}
|
||
|
;
|
||
|
|
||
|
string_opts:
|
||
|
{ $$=0 ;}
|
||
|
| INDICATOR
|
||
|
{ $$= string_opt($1) ; }
|
||
|
| INDICATOR ',' INDICATOR
|
||
|
{ if ( $1 != 'b' ||
|
||
|
( $3 != 'u' && $3 != 'w' ) ) {
|
||
|
serror("illegal string options") ;
|
||
|
}
|
||
|
$$ = string_opt($1)|string_opt($3) ;
|
||
|
}
|
||
|
;
|
||
|
|
||
|
reg_list:
|
||
|
'[' ']'
|
||
|
{ $$=0 ;}
|
||
|
| '[' reg_items ']'
|
||
|
{ $$= $2 ;}
|
||
|
;
|
||
|
|
||
|
reg_items:
|
||
|
REG
|
||
|
{ $$= 1<<($1) ; }
|
||
|
| reg_items ',' REG
|
||
|
{ $$= ($1) | ( 1<<($3) ) ;}
|
||
|
;
|