573 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			573 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
						|
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
						|
 */
 | 
						|
#define RCSID4 "$Header$"
 | 
						|
 | 
						|
/*
 | 
						|
** Zilog z8000 yacc parsing rules
 | 
						|
*/
 | 
						|
operation
 | 
						|
	: f1
 | 
						|
	| f2
 | 
						|
	| f3
 | 
						|
	| f4
 | 
						|
	| f5
 | 
						|
	| f6
 | 
						|
	| f7
 | 
						|
	| f8
 | 
						|
	| f9
 | 
						|
	;
 | 
						|
 | 
						|
 | 
						|
f1	: F1_1F2_3  dst
 | 
						|
		{ switch( ($1 & 0x0F00)>>8 ) {
 | 
						|
		  case 9:   case 0xF: chtype( DST, TYPE_11a23 );  break;
 | 
						|
		  case 0xC: case 0xD: chtype( DST, TYPE_11b23 );  break;
 | 
						|
		  }
 | 
						|
		  emit2( mode | $1 | $2<<4 );
 | 
						|
		  if ( mode>>12 == 4 ) emit_ad( addr_inf );
 | 
						|
		}
 | 
						|
	| F1_1a  reg
 | 
						|
		{ chreg( $1, $2 );
 | 
						|
		  emit2( $1 | $2<<4 );
 | 
						|
		}
 | 
						|
	| F1_1b  reg  option
 | 
						|
		{ if ( $3 != 1 && $3 != 2 )  argerr();
 | 
						|
		  emit2( $1 | $2<<4 | ($3-1)<<1 );
 | 
						|
		}
 | 
						|
	| F1_2  dst  option
 | 
						|
		{ chtype( DST, TYPE_12 );
 | 
						|
		  fit(fit4($3-1));
 | 
						|
		  emit2( mode | $1 | $2<<4 | $3-1 );
 | 
						|
		  if ( mode>>12 == 4 ) emit_ad( addr_inf );
 | 
						|
		}
 | 
						|
	| LDK  reg  ','  imexpr
 | 
						|
		{ fit(fit4($4));
 | 
						|
		  emit2( $1 | $2<<4 | $4 );
 | 
						|
		}
 | 
						|
	| F1_2F6_3  dst  ','  src
 | 
						|
		{ if ( oprtype[ DST ] == REG && oprtype[ SRC ] == REG )
 | 
						|
		  {   emit2( $1 | $4 );
 | 
						|
		      emit2( $2<<8 );
 | 
						|
		  }
 | 
						|
		  else if ( oprtype[ SRC ] == IM )
 | 
						|
		  {   chtype( DST, TYPE_1263 );
 | 
						|
		      if ((immed.typ & ~S_EXT) != S_ABS) {
 | 
						|
			serror("must be absolute");
 | 
						|
	 	      }
 | 
						|
		      if ( bitset($1,8) ) /* word */  fit(fit4(immed.val));
 | 
						|
		      else /* byte */  fit(fit3(immed.val));
 | 
						|
		      emit2( mode | $1 | $2<<4 | (int)immed.val );
 | 
						|
		      if ( mode>>12 == 4 ) emit_ad( addr_inf );
 | 
						|
		  }
 | 
						|
		  else  argerr();
 | 
						|
		}
 | 
						|
	| JP  coco1  dst
 | 
						|
		{ chtype( DST, TYPE_jp );
 | 
						|
		  emit2( mode | $1 | $3<<4 | $2 );
 | 
						|
		  if ( mode>>12 == 4 ) emit_ad( addr_inf );
 | 
						|
		}
 | 
						|
	| TCC  coco1  reg
 | 
						|
		{ emit2( $1 | $3<<4 | $2 );	}
 | 
						|
	;
 | 
						|
 | 
						|
 | 
						|
f2	: F2_1  reg  ','  src
 | 
						|
		{ switch( ($1 & 0xF000)>>12 )
 | 
						|
		  {   case 2: chtype( SRC, TYPE_21a );  break;
 | 
						|
		      case 3: chtype( SRC, TYPE_21b );  break;
 | 
						|
		  }
 | 
						|
		  emit2( mode | $1 | $4<<4 | $2 );
 | 
						|
		  if ( mode>>12 == 4 ) emit_ad( addr_inf );
 | 
						|
		}
 | 
						|
	| F2_1F5_1  dst  ','  src
 | 
						|
		{ switch( oprtype[ DST ] )
 | 
						|
		  { case REG: chtype( SRC, TYPE_2151 );
 | 
						|
			      chreg( $1, $2 );
 | 
						|
			      emit2( mode | $1 | $4<<4 | $2 );
 | 
						|
			      break;
 | 
						|
		    case IR: case DA: case X:
 | 
						|
			      if ( oprtype[ SRC ] == IM
 | 
						|
				&& ( $1 == 0x0B00 || $1 == 0x0A00   ) )
 | 
						|
				    /* cp or cpb */
 | 
						|
			      {   setmode( DST );
 | 
						|
				  emit2( mode | $1 + 0x201 | $2<<4 );
 | 
						|
				  break;
 | 
						|
			      }
 | 
						|
		    default: argerr();
 | 
						|
		  }
 | 
						|
		  if ( mode>>12 == 4 ) emit_ad( addr_inf );
 | 
						|
		  if ( oprtype[ SRC ] == IM )
 | 
						|
		  {   if (bitset($1,8)) /* word */ {
 | 
						|
#ifdef RELOCATION
 | 
						|
			newrelo(immed.typ, RELO2|RELBR);
 | 
						|
#endif
 | 
						|
			emit2( (int)immed.val );
 | 
						|
		      }
 | 
						|
		      else if (bitset($1,12)) /* long */ {
 | 
						|
#ifdef RELOCATION
 | 
						|
			newrelo(immed.typ, RELO4|RELWR|RELBR);
 | 
						|
#endif
 | 
						|
			emit4( immed.val );
 | 
						|
		      }
 | 
						|
		      else /* byte */ {
 | 
						|
#ifdef RELOCATION
 | 
						|
			newrelo(immed.typ, RELO1);
 | 
						|
#endif
 | 
						|
			emit1((int) immed.val);
 | 
						|
			/* emit1((int) immed.val); ??? twice ??? */
 | 
						|
		      }
 | 
						|
		  }
 | 
						|
		}
 | 
						|
	| LDA  R32  ','  src
 | 
						|
		{ switch( oprtype[ SRC ] )
 | 
						|
		  {   case DA: case X: emit2( 0x7600 | $4<<4 | $2 );
 | 
						|
				       emit_ad( addr_inf );
 | 
						|
				       break;
 | 
						|
		      case BA:  emit2( 0x3400 | $4<<4 | $2 );
 | 
						|
#ifdef RELOCATION
 | 
						|
				newrelo(displ.typ,RELO2|RELBR);
 | 
						|
#endif
 | 
						|
				emit2( (int) displ.val );  break;
 | 
						|
		      case BX:  emit2( 0x7400 | $4<<4 | $2 );
 | 
						|
				emit2( index<<8 );  break;
 | 
						|
		      default:  argerr();
 | 
						|
		  }
 | 
						|
		}
 | 
						|
	| POP  dst  ','  ir
 | 
						|
		{ chtype( DST, TYPE_pop );
 | 
						|
		  emit2( mode | $1 | $4<<4 | $2 );
 | 
						|
		  if ( mode>>12 == 4 ) emit_ad( addr_inf );
 | 
						|
		}
 | 
						|
	| PUSH  ir  ','  src
 | 
						|
		{ chtype( SRC, TYPE_push );
 | 
						|
		  switch ( oprtype[ SRC ] )
 | 
						|
		  {   case IM: if ( $1 == 0x1100 ) /* pushl */ argerr();
 | 
						|
			    /* {   emit2( 0x9109 | $2<<4 );
 | 
						|
			    **	   emit4( immed );
 | 
						|
			    ** }
 | 
						|
			    */
 | 
						|
			       else
 | 
						|
			       {   emit2( 0x0D09 | $2<<4 );
 | 
						|
#ifdef RELOCATION
 | 
						|
				   newrelo(immed.typ, RELO2|RELBR);
 | 
						|
#endif
 | 
						|
				   emit2( (int)immed.val );
 | 
						|
			       }
 | 
						|
			       break;
 | 
						|
		      default: emit2( mode | $1 | $2<<4 | $4 );
 | 
						|
			       if ( mode>>12 == 4 ) emit_ad( addr_inf );
 | 
						|
		  }
 | 
						|
		}
 | 
						|
	| LD  dst  ','  src
 | 
						|
		{ if ( oprtype[ DST ] == REG )
 | 
						|
		  {   switch( oprtype[ SRC ] )
 | 
						|
		      {   case IM:
 | 
						|
			       if ( $1 == 0 )  /* ldb: F3.2 */
 | 
						|
			       {   /* fit(fits8(immed)); */
 | 
						|
				   emit1( 0xC000 | $2<<8);
 | 
						|
#ifdef RELOCATION
 | 
						|
				   newrelo(immed.typ, RELO1);
 | 
						|
#endif
 | 
						|
				   emit1((int) immed.val);
 | 
						|
			       }
 | 
						|
			       else
 | 
						|
			       {   /*fit(fits16(immed));*/
 | 
						|
			           emit2( 0x2100 | $2 );
 | 
						|
#ifdef RELOCATION
 | 
						|
				   newrelo(immed.typ, RELO2|RELBR);
 | 
						|
#endif
 | 
						|
				   emit2( (int)immed.val );
 | 
						|
			       }
 | 
						|
			       break;
 | 
						|
			  case REG: case IR: case DA: case X:
 | 
						|
			       setmode( SRC );
 | 
						|
			       emit2( mode | 0x2000 | $1 | $4<<4 | $2 );
 | 
						|
			       if ( mode>>12 == 4 ) emit_ad( addr_inf );
 | 
						|
			       break;
 | 
						|
			  case BA: emit2( 0x3000 | $1 | $4<<4 | $2 );
 | 
						|
#ifdef RELOCATION
 | 
						|
				   newrelo(displ.typ,RELO2|RELBR);
 | 
						|
#endif
 | 
						|
				   emit2( (int) displ.val );
 | 
						|
				   break;
 | 
						|
			  case BX: emit2( 0x7000 | $1 | $4<<4 | $2 );
 | 
						|
				   emit2( index<<8 );
 | 
						|
				   break;
 | 
						|
			  default: argerr();
 | 
						|
		      }
 | 
						|
		      break;
 | 
						|
		  }
 | 
						|
		  if ( oprtype[ SRC ] == REG )
 | 
						|
		  {   switch( oprtype[ DST ] )
 | 
						|
		      {   case IR: case DA: case X:
 | 
						|
			       setmode( DST );
 | 
						|
			       emit2( mode | 0x2E00 | $1 | $2<<4 | $4 );
 | 
						|
			       if ( mode>>12 == 4 ) emit_ad( addr_inf );
 | 
						|
			       break;
 | 
						|
			  case BA: emit2( 0x3200 | $1 | $2<<4 | $4 );
 | 
						|
#ifdef RELOCATION
 | 
						|
				   newrelo(displ.typ,RELO2|RELBR);
 | 
						|
#endif
 | 
						|
				   emit2( (int) displ.val );
 | 
						|
				   break;
 | 
						|
			  case BX: emit2( 0x7200 | $1 | $2<<4 | $4 );
 | 
						|
				   emit2( index<<8 );
 | 
						|
				   break;
 | 
						|
			  default: argerr();
 | 
						|
		      }
 | 
						|
		      break;
 | 
						|
		  }
 | 
						|
		  if ( oprtype[ SRC ] == IM )	/* F5.1	*/
 | 
						|
		  {   chtype( DST, TYPE_ld );
 | 
						|
		      emit2( mode | 0xC05 | $1 | $2<<4 );
 | 
						|
		      if ( mode>>12 == 4 ) emit_ad( addr_inf );
 | 
						|
		      if ( $1 == 0 ) /* ldb */
 | 
						|
		      {   /* fit(fits8(immed)); */
 | 
						|
#ifdef RELOCATION
 | 
						|
			  newrelo(immed.typ, RELO1);
 | 
						|
#endif
 | 
						|
			  emit1((int) immed.val);
 | 
						|
			  /* emit1((int) immed.val); ??? twice ??? */
 | 
						|
		      }
 | 
						|
		      else /* ld */
 | 
						|
		      {   /*fit(fits16(immed));*/
 | 
						|
#ifdef RELOCATION
 | 
						|
			  newrelo(immed.typ, RELO2 | RELBR);
 | 
						|
#endif
 | 
						|
			  emit2( (int)immed.val );
 | 
						|
		      }
 | 
						|
		      break;
 | 
						|
		  }
 | 
						|
		  argerr();
 | 
						|
		}
 | 
						|
	| LDL  dst  ','  src
 | 
						|
		{ if ( oprtype[ DST ] == REG )
 | 
						|
		  {   switch( oprtype[ SRC ] )
 | 
						|
		      {   case IM: emit2( 0x1400 | $2 );
 | 
						|
#ifdef RELOCATION
 | 
						|
			  	   newrelo(immed.typ, RELO4|RELBR|RELWR);
 | 
						|
#endif
 | 
						|
				   emit4( immed.val );
 | 
						|
				   break;
 | 
						|
			  case REG: case IR: case DA: case X:
 | 
						|
			       setmode( SRC );
 | 
						|
			       emit2( mode | 0x1400 | $4<<4 | $2 );
 | 
						|
			       if ( mode>>12 == 4 ) emit_ad( addr_inf );
 | 
						|
			       break;
 | 
						|
			  case BA: emit2( 0x3500 | $4<<4 | $2 );
 | 
						|
#ifdef RELOCATION
 | 
						|
				   newrelo(displ.typ,RELO2|RELBR);
 | 
						|
#endif
 | 
						|
				   emit2((int) displ.val );
 | 
						|
				   break;
 | 
						|
			  case BX: emit2( 0x7500 | $4<<4 | $2 );
 | 
						|
				   emit2( index<<8 );
 | 
						|
				   break;
 | 
						|
			  default: argerr();
 | 
						|
		      }
 | 
						|
		      break;
 | 
						|
		  }
 | 
						|
		  if ( oprtype[ SRC ] == REG )
 | 
						|
		  {   switch( oprtype[ DST ] )
 | 
						|
		      {   case IR: case DA: case X:
 | 
						|
			       setmode( DST );
 | 
						|
			       emit2( mode | 0x1D00 | $2<<4 | $4 );
 | 
						|
			       if ( mode>>12 == 4 ) emit_ad( addr_inf );
 | 
						|
			       break;
 | 
						|
			  case BA: emit2( 0x3700 | $2<<4 | $4 );
 | 
						|
#ifdef RELOCATION
 | 
						|
				   newrelo(displ.typ,RELO2|RELBR);
 | 
						|
#endif
 | 
						|
				   emit2( (int) displ.val );
 | 
						|
				   break;
 | 
						|
			  case BX: emit2( 0x7700 | $2<<4 | $4 );
 | 
						|
				   emit2( index<<8 );
 | 
						|
				   break;
 | 
						|
			  default: argerr();
 | 
						|
		      }
 | 
						|
		      break;
 | 
						|
		  }
 | 
						|
	    /*	  if ( oprtype[ SRC ] == IM )
 | 
						|
	    **	  {   chtype( DST, TYPE_ld );
 | 
						|
	    **	      emit2( mode | 0xD07 | $2<<4 );
 | 
						|
	    **	      if ( mode>>12 == 4 ) emit_ad( addr_inf );
 | 
						|
	    **	      emit4( immed );
 | 
						|
	    **	      break;
 | 
						|
	    **	  }
 | 
						|
	    */
 | 
						|
		  argerr();
 | 
						|
		}
 | 
						|
	;
 | 
						|
 | 
						|
 | 
						|
f3	: DJNZ  reg  ','  ra
 | 
						|
		{ branch( $1 | $2<<8, $4 );	}
 | 
						|
	| JR  coco1  ra
 | 
						|
		{ branch( $1 | $2<<8, $3 );	}
 | 
						|
	| CALR  ra
 | 
						|
		{ branch( $1, $2 );	}
 | 
						|
	;
 | 
						|
 | 
						|
 | 
						|
f4	: LDR  reg  ','  ra
 | 
						|
		{ ldrel( $1 | $2, $4 );		}
 | 
						|
	| LDR  ra  ','  reg
 | 
						|
		{ ldrel( $1 | 0x200 | $4, $2 );	}
 | 
						|
	| LDAR  R32  ','  ra
 | 
						|
		{ ldrel( $1 | $2, $4 );		}
 | 
						|
	;
 | 
						|
 | 
						|
 | 
						|
f5	: F5_1L  reg  option
 | 
						|
		{   if ( $3 < 0 )
 | 
						|
		    {	warning( "neg src results in a right shift!" );
 | 
						|
			warning( "warning only");
 | 
						|
		    }
 | 
						|
		    shiftcode( $1 | $2<<4, $3 );
 | 
						|
		}
 | 
						|
	| F5_1R  reg  option2
 | 
						|
		{   if ( $3 > 0 )
 | 
						|
		    {	warning( "pos src results in a left shift!" );
 | 
						|
			warning( "warning only");
 | 
						|
		    }
 | 
						|
		    shiftcode( $1 | $2<<4, $3 );
 | 
						|
		}
 | 
						|
	;
 | 
						|
 | 
						|
option2	: ',' imexpr
 | 
						|
		{ $$ = $2;	}
 | 
						|
	|  /* empty */
 | 
						|
		{ $$ = -1;	}
 | 
						|
	;
 | 
						|
 | 
						|
f6	: LDM  dst  ','  src  ','  imexpr
 | 
						|
		{ switch( oprtype[ DST ] )
 | 
						|
		  { case REG: chtype( SRC, TYPE_ldm );
 | 
						|
			      ldmcode( $1 | $4<<4, $2, $6 );
 | 
						|
			      break;
 | 
						|
		    default:  switch( oprtype[ SRC ] )
 | 
						|
			      { case REG: chtype( DST, TYPE_ldm );
 | 
						|
					  ldmcode($1+8 | $2<<4, $4, $6);
 | 
						|
					  break;
 | 
						|
				default:  argerr();
 | 
						|
			      }
 | 
						|
		  }
 | 
						|
		}
 | 
						|
	| F6_4  ir  ','  ir  ','  R16
 | 
						|
		{ /* For translate instructions the roles of $2 and $4
 | 
						|
		  ** are interchanged with respect to the other
 | 
						|
		  ** instructions of this group.
 | 
						|
		  */
 | 
						|
		  if ( ($1 & 0xB8FF) == $1 )
 | 
						|
		  {	/* translate instruction	*/
 | 
						|
			emit2( ($1 & ~0xF0) | $2<<4 );
 | 
						|
			emit2( ($1 & 0xF0)>>4 | $6<<8 | $4<<4 );
 | 
						|
		  }
 | 
						|
		  else
 | 
						|
		  {	emit2( ($1 & ~0xF0) | $4<<4 );
 | 
						|
			emit2( ($1 & 0xF0)>>4 | $6<<8 | $2<<4 );
 | 
						|
		  }
 | 
						|
		}
 | 
						|
	| F6_5  dst  ','  ir  ','  R16  coco2
 | 
						|
		{ switch( oprtype[ DST ] )
 | 
						|
		  {   case REG: if ( bitset($1,1) )  argerr();  break;
 | 
						|
		      case IR : if ( !bitset($1,1) )  argerr();  break;
 | 
						|
		      default : argerr();
 | 
						|
		  }
 | 
						|
		  emit2( $1 | $4<<4 );
 | 
						|
		  emit2( $6<<8 | $2<<4 | $7 );
 | 
						|
		}
 | 
						|
	| F6_6  reg  ','  R16
 | 
						|
		{ emit2( $1 | $2<<4 );
 | 
						|
		  emit2( $4<<8 );
 | 
						|
		}
 | 
						|
	;
 | 
						|
 | 
						|
 | 
						|
f7	: IN  reg  ','  da
 | 
						|
		{ emit2( $1 | 0xA04 | $2<<4 );
 | 
						|
#ifdef RELOCATION
 | 
						|
		  newrelo(adr_inf.typ, RELO2|RELBR);
 | 
						|
#endif
 | 
						|
		  emit2( (short)addr_inf.val );    /* i/o address */
 | 
						|
		}
 | 
						|
	| OUT  da  ','  reg
 | 
						|
		{ emit2( $1 | 0xA06 | $4<<4 );
 | 
						|
#ifdef RELOCATION
 | 
						|
		  newrelo(adr_inf.typ, RELO2|RELBR);
 | 
						|
#endif
 | 
						|
		  emit2( (short)addr_inf.val );    /* i/o address */
 | 
						|
		}
 | 
						|
	| IN  reg  ','  ir
 | 
						|
		{ if ( bitset($1,0) )	argerr();
 | 
						|
		  emit2( $1 | 0xC00 | $4<<4 | $2 );
 | 
						|
		}
 | 
						|
	| OUT  ir  ','  reg
 | 
						|
		{ if ( bitset($1,0) )	argerr();
 | 
						|
		  emit2( $1 | 0xE00 | $2<<4 | $4 );
 | 
						|
		}
 | 
						|
	;
 | 
						|
 | 
						|
 | 
						|
f8	: LDCTL  ctlargs
 | 
						|
		{ emit2( $1 | $2 );	}
 | 
						|
	| LDCTLB  ctlbargs
 | 
						|
		{ emit2( $1 | $2 );	}
 | 
						|
	| MREQ  reg
 | 
						|
		{ emit2( $1 | $2<<4 );	}
 | 
						|
	;
 | 
						|
ctlargs	: CTLR  ','  R16
 | 
						|
		{ $$ = $3<<4 | $1 | 8;	}
 | 
						|
	| R16  ','  CTLR
 | 
						|
		{ $$ = $1<<4 | $3;	}
 | 
						|
	;
 | 
						|
ctlbargs: CTLRFLAGS  ','  R8
 | 
						|
		{ $$ = $3<<4 | $1 | 8;}
 | 
						|
	| R8  ','  CTLRFLAGS
 | 
						|
		{ $$ = $1<<4 | $3;	}
 | 
						|
	;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
f9	: F9_1  flags
 | 
						|
		{ emit2( $1 | $2 );	}
 | 
						|
	| F9_2  ints
 | 
						|
		{ emit2( $1 | $2 );	}
 | 
						|
	| F9_3
 | 
						|
		{ emit2( $1 );	}
 | 
						|
	| RET
 | 
						|
		{ emit2( $1 | 8 );	}
 | 
						|
	| RET  CC
 | 
						|
		{ emit2( $1 | $2 );	}
 | 
						|
	| SC  imexpr
 | 
						|
		{ fit(fit8($2));
 | 
						|
		  emit2( $1 | $2 );
 | 
						|
		}
 | 
						|
	;
 | 
						|
flags	: flags  ','  FLAG
 | 
						|
		{ $$ = $1 | $3;	}
 | 
						|
	| FLAG
 | 
						|
		{ $$ = $1;	}
 | 
						|
	;
 | 
						|
ints	: ints  ','  INTCB
 | 
						|
		{ $$ = $1 | $3;	}
 | 
						|
	| INTCB
 | 
						|
		{ $$ = $1;	}
 | 
						|
	;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
coco1	: CC  ','
 | 
						|
		{ $$ = $1;	}
 | 
						|
	| /* empty */
 | 
						|
		{ $$ = 8;	}
 | 
						|
	;
 | 
						|
coco2	: ','  CC
 | 
						|
		{ $$ = $2;	}
 | 
						|
	| /* empty */
 | 
						|
		{ $$ = 8;	}
 | 
						|
	;
 | 
						|
option	: ','  imexpr
 | 
						|
		{ $$ = $2;	}
 | 
						|
	|  /* empty */
 | 
						|
		{ $$ = 1;	}
 | 
						|
	;
 | 
						|
/*    `imexpr', just as `im', is used to implement immediate data.
 | 
						|
** But `imexpr' is used in those cases where the  immediate  value
 | 
						|
** always  will fit into 16 bits, so (long) `immed' is not needed.
 | 
						|
** Those cases are in `option', `option2', f9-`SC',  f6-`LDM'  and
 | 
						|
** f1-`LDK'.
 | 
						|
*/
 | 
						|
imexpr	: '$'  absexp
 | 
						|
		{ $$ = $2;	}
 | 
						|
	;
 | 
						|
/*     Destination (dst) as well as source  (src)  operands  never
 | 
						|
** have RA as addressing mode, except for some instructions of the
 | 
						|
** F3 and F4 instruction format group.   In those cases RA is even
 | 
						|
** the  only  addressing mode which is allowed.   This is why `ra'
 | 
						|
** has a yacc-rule not being part of `opr'.
 | 
						|
*/
 | 
						|
ra	: expr
 | 
						|
		{ $$ = $1;	}
 | 
						|
	;
 | 
						|
dst	:	{ operand = DST;}
 | 
						|
	  opr
 | 
						|
		{ $$ = $2;	}
 | 
						|
	;
 | 
						|
src	:	{ operand = SRC;}
 | 
						|
	  opr
 | 
						|
		{ $$ = $2;	}
 | 
						|
	;
 | 
						|
opr	: reg
 | 
						|
		{ settype( REG );	}
 | 
						|
	| im
 | 
						|
		{ settype( IM );	}
 | 
						|
	| ir
 | 
						|
		{ settype( IR );	}
 | 
						|
	| da
 | 
						|
		{ settype( DA );	}
 | 
						|
	| x
 | 
						|
		{ settype( X );		}
 | 
						|
	| ba
 | 
						|
		{ settype( BA );	}
 | 
						|
	| bx
 | 
						|
		{ settype( BX );	}
 | 
						|
	;
 | 
						|
reg	: R8
 | 
						|
	| R16
 | 
						|
	| R32
 | 
						|
	| R64
 | 
						|
	;
 | 
						|
im	: '$'  expr
 | 
						|
		{ $$ = 0;
 | 
						|
		  immed = $2;
 | 
						|
		}
 | 
						|
	| '$' '<' '<' expr '>' '>' expr
 | 
						|
		{ $$ = 0;
 | 
						|
		  immed.typ = combine($4.typ, $7.typ, '+');
 | 
						|
		  immed.val = $4.val<<16 | $7.val;
 | 
						|
		}
 | 
						|
	;
 | 
						|
ir	: '*'  R32
 | 
						|
		{ if ( $2 == 0 ) regerr();
 | 
						|
		  $$ = $2;
 | 
						|
		}
 | 
						|
	;
 | 
						|
da	: expr
 | 
						|
		{ $$ = 0;
 | 
						|
		  addr_inf = $1;
 | 
						|
		}
 | 
						|
	| '<' '<' expr '>' '>' expr
 | 
						|
		{ $$ = 0;
 | 
						|
		  addr_inf.typ = combine( $3.typ, $6.typ, '+' );
 | 
						|
		  addr_inf.val = $3.val<<16 | $6.val;
 | 
						|
		}
 | 
						|
	;
 | 
						|
x	: expr  '('  R16  ')'
 | 
						|
		{ if ( $3 == 0 ) regerr();
 | 
						|
		  $$ = $3;
 | 
						|
		  addr_inf = $1;
 | 
						|
		}
 | 
						|
	| '<' '<'  expr  '>' '>'  expr  '('  R16  ')'
 | 
						|
		{ if ( $8 == 0 ) regerr();
 | 
						|
		  $$ = $8;
 | 
						|
		  addr_inf.typ = combine( $3.typ, $6.typ, '+' );
 | 
						|
		  addr_inf.val = $3.val<<16 | $6.val;
 | 
						|
		}
 | 
						|
	;
 | 
						|
ba	: R32  '('  '$'  expr  ')'
 | 
						|
		{ if ( $1 == 0 ) regerr();
 | 
						|
		  $$ = $1;
 | 
						|
		  displ = $4;
 | 
						|
		}
 | 
						|
	;
 | 
						|
bx	: R32  '('  R16  ')'
 | 
						|
		{ if ( $1 == 0 || $3 == 0 ) regerr();
 | 
						|
		  $$ = $1;
 | 
						|
		  index = $3;
 | 
						|
		}
 | 
						|
	;
 |