328 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			328 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #define RCSID4 "$Header$"
 | |
| 
 | |
| /*
 | |
|  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | |
|  * See the copyright notice in the ACK home directory, in the file "Copyright".
 | |
|  *
 | |
|  */
 | |
| 
 | |
| /*
 | |
|  * Zilog Z80 parsing rules
 | |
|  */
 | |
| operation
 | |
| 	:	NOOPOP
 | |
| 			{	emit1($1);}
 | |
| 	|	LDOP ldargs
 | |
| 	|	PSHPOP R16
 | |
| 			{	switch ($2) {
 | |
| 				case BC: emit1($1); break;
 | |
| 				case DE: emit1($1 | 020); break;
 | |
| 				case AF: emit1($1 | 060); break;
 | |
| 				case HL:
 | |
| 				case IX:
 | |
| 				case IY: xyreg($2,$1 | 040); break;
 | |
| 				default: serror("register error");
 | |
| 				}
 | |
| 			}
 | |
| 	|	EXOP R16 ',' R16
 | |
| 			{	if ($2==DE && $4==HL)
 | |
| 					emit1(0353);
 | |
| 				else if ($2==AF && $4==AF2)
 | |
| 					emit1(010);
 | |
| 				else serror("register error");
 | |
| 			}
 | |
| 	|	EXOP '(' R16 ')' ',' R16
 | |
| 			{	if ($3!=SP) serror("register error");
 | |
| 				xyreg($6,$1);
 | |
| 			}
 | |
| 	|	E_ED
 | |
| 			{	emit1(0355); emit1($1);}
 | |
| 	|	ADDOP R16 ',' R16
 | |
| 			{	if ($4 == $2)
 | |
| 					xyreg($2,051);
 | |
| 				else {
 | |
| 					if ($4==HL || $4>SP)
 | |
| 						serror("register error");
 | |
| 					xyreg($2,011 | $4<<4);
 | |
| 				}
 | |
| 			}
 | |
| 	|	ADCSBC R16 ',' R16
 | |
| 			{	if ($2!=HL || $4>SP) serror("register error");
 | |
| 				emit1(0355);
 | |
| 				emit1(($1==0210 ? 0112 : 0102) | ($4<<4));
 | |
| 			}
 | |
| 	|	INCDEC R16
 | |
| 			{	switch ($2) {
 | |
| 				case BC: case DE: case SP:
 | |
| 					emit1(($1==04 ? 03 : 013) | $2<<4);
 | |
| 					break;
 | |
| 				case HL: case IX: case IY:
 | |
| 					xyreg($2,$1==04 ? 043 : 053);
 | |
| 					break;
 | |
| 				default: serror("register error");
 | |
| 				}
 | |
| 			}
 | |
| 	|	INCDEC r8
 | |
| 			{	emit1($1 | $2<<3);}
 | |
| 	|	INCDEC ind
 | |
| 			{	xymem($2,$1 | 060);}
 | |
| 	|	ari8 r8
 | |
| 			{	emit1($1 | $2);}
 | |
| 	|	ari8 expr
 | |
| 			{	emit1($1 | 0106); emit1($2.val);}
 | |
| 	|	ari8 ind
 | |
| 			{	xymem($2,$1 | 06);}
 | |
| 	|	IMOP absexp
 | |
| 			{	emit1(0355);
 | |
| 				switch ($2) {
 | |
| 				case 0: emit1(0106); break;
 | |
| 				case 1:	emit1(0126); break;
 | |
| 				case 2:	emit1(0136); break;
 | |
| 				default: serror("range 0..2");
 | |
| 				}
 | |
| 			}
 | |
| 	|	ROTATE r8
 | |
| 			{	emit1(0313); emit1($1 | $2);}
 | |
| 	|	ROTATE ind
 | |
| 			{	xymem($2,0313); emit1($1 | 06);}
 | |
| 	|	BITS absexp ',' r8
 | |
| 			{	fit(fit3($2));
 | |
| 				emit1(0313); emit1($1 | low3($2)<<3 | $4);
 | |
| 			}
 | |
| 	|	BITS absexp ',' ind
 | |
| 			{	fit(fit3($2));
 | |
| 				xymem($4,0313);
 | |
| 				emit1($1 | low3($2)<<3 | 06);
 | |
| 			}
 | |
| 	|	JP expr
 | |
| 			{	emit1($1);
 | |
| #ifdef RELOCATION
 | |
| 				newrelo($2.typ, RELO2);
 | |
| #endif
 | |
| 				emit2($2.val);
 | |
| 			}
 | |
| 	|	JP coco ',' expr
 | |
| 			{	emit1(0302 | $2<<3);
 | |
| #ifdef RELOCATION
 | |
| 				newrelo($4.typ, RELO2);
 | |
| #endif
 | |
| 				emit2($4.val);
 | |
| 			}
 | |
| 	|	JP indir
 | |
| 			{	xyreg($2,0351);}
 | |
| 	|	JR expr
 | |
| 			{	branch($1,$2);}
 | |
| 	|	JR coco ',' expr
 | |
| 			{	if ($2 > 3) serror("bad condition code");
 | |
| 				branch(040 | ($2<<3), $4);
 | |
| 			}
 | |
| 	|	DJNZ expr
 | |
| 			{	branch($1,$2);}
 | |
| 	|	CALL expr
 | |
| 			{	emit1($1);
 | |
| #ifdef RELOCATION
 | |
| 				newrelo($2.typ, RELO2);
 | |
| #endif
 | |
| 				emit2($2.val);
 | |
| 			}
 | |
| 	|	CALL coco ',' expr
 | |
| 			{	emit1(0304 | $2<<3);
 | |
| #ifdef RELOCATION
 | |
| 				newrelo($4.typ, RELO2);
 | |
| #endif
 | |
| 				emit2($4.val);
 | |
| 			}
 | |
| 	|	RET
 | |
| 			{	emit1($1);}
 | |
| 	|	RET coco
 | |
| 			{	emit1(0300 | $2<<3);}
 | |
| 	|	RST absexp
 | |
| 			{	if (($2&070)!=$2)
 | |
| 					serror("rst expression out of range");
 | |
| 				emit1($1 | $2);
 | |
| 			}
 | |
| 	|	IN R8 ',' expr
 | |
| 			{	if ($2 != A) serror("register error");
 | |
| 				emit1($1);
 | |
| #ifdef RELOCATION
 | |
| 				newrelo($4.typ, RELO1);
 | |
| #endif
 | |
| 				emit1($4.val);
 | |
| 			}
 | |
| 	|	IN R8 ',' R8
 | |
| 			{	if ($4 != C) serror("register error");
 | |
| 				emit1(0355); emit1(0100 | $2<<3);
 | |
| 			}
 | |
| 	|	OUT expr ',' R8
 | |
| 			{	if ($4 != A) serror("register error");
 | |
| 				emit1($1);
 | |
| #ifdef RELOCATION
 | |
| 				newrelo($2.typ, RELO1);
 | |
| #endif
 | |
| 				emit1($2.val);
 | |
| 			}
 | |
| 	|	OUT R8 ',' R8
 | |
| 			{	if ($2 != C) serror("register error");
 | |
| 				emit1(0355); emit1(0101 | $4<<3);
 | |
| 			}
 | |
| 	;
 | |
| ari8	:	ARI8
 | |
| 	|	ADDOP R8 ','
 | |
| 			{	if ($2 != A) serror("register error");}
 | |
| 	|	ADCSBC R8 ','
 | |
| 			{	if ($2 != A) serror("register error");}
 | |
| 	;
 | |
| ldargs	:	R8 ',' R8
 | |
| 			{	if ($1==F || $3==F) serror("register error");
 | |
| 				if ($1<=A && $3<=A)
 | |
| 					emit1(0100 | $1<<3 | $3);
 | |
| 				else {
 | |
| 					emit1(0355);
 | |
| 					if ((($1==A) ^ ($3==A)) == 0)
 | |
| 						serror("register error");
 | |
| 					emit1(	0107 |
 | |
| 						($1==R||$3==R)<<3 |
 | |
| 						($1==A)<<4
 | |
| 					);
 | |
| 				}
 | |
| 			}
 | |
| 	|	R8 ',' expr
 | |
| 			{	if ($1==F || $1==I || $1==R)
 | |
| 					serror("register error");
 | |
| 				emit1(06 | $1<<3);
 | |
| #ifdef RELOCATION
 | |
| 				newrelo($3.typ, RELO1);
 | |
| #endif
 | |
| 				emit1($3.val);
 | |
| 			}
 | |
| 	|	R8 ',' indir
 | |
| 			{	if ($1==F || $1==I || $1==R)
 | |
| 					serror("register error");
 | |
| 				if ($1==A && ($3==BC || $3==DE))
 | |
| 					emit1($3==BC ? 012 : 032);
 | |
| 				else
 | |
| 					xymem($3,0106 | $1<<3);
 | |
| 			}
 | |
| 	|	R8 ',' index
 | |
| 			{	if ($1==F || $1==I || $1==R)
 | |
| 					serror("register error");
 | |
| 				xymem($3,0106 | $1<<3);
 | |
| 			}
 | |
| 	|	R8 ',' '(' expr ')'
 | |
| 			{	if ($1!=A) serror("register error");
 | |
| 				emit1(072);
 | |
| #ifdef RELOCATION
 | |
| 				newrelo($4.typ, RELO2);
 | |
| #endif
 | |
| 				emit2($4.val);
 | |
| 			}
 | |
| 	|	indir ',' r8
 | |
| 			{	if ($3==A && ($1==BC || $1==DE))
 | |
| 					emit1($1==BC ? 02 : 022);
 | |
| 				else
 | |
| 					xymem($1,0160 | $3);
 | |
| 			}
 | |
| 	|	index ',' r8
 | |
| 			{	xymem($1,0160 | $3);}
 | |
| 	|	indir ',' expr
 | |
| 			{	xymem($1,066);
 | |
| #ifdef RELOCATION
 | |
| 				newrelo($3.typ, RELO1);
 | |
| #endif
 | |
| 				emit1($3.val);
 | |
| 			}
 | |
| 	|	index ',' expr
 | |
| 			{	xymem($1,066);
 | |
| #ifdef RELOCATION
 | |
| 				newrelo($3.typ, RELO1);
 | |
| #endif
 | |
| 				emit1($3.val);
 | |
| 			}
 | |
| 	|	R16 ',' expr
 | |
| 			{	switch ($1) {
 | |
| 				case BC: case DE: case HL: case SP:
 | |
| 					emit1(01 | $1<<4); break;
 | |
| 				case IX: case IY:
 | |
| 					xyreg($1,041); break;
 | |
| 				default: serror("register error");
 | |
| 				}
 | |
| #ifdef RELOCATION
 | |
| 				newrelo($3.typ, RELO2);
 | |
| #endif
 | |
| 				emit2($3.val);
 | |
| 			}
 | |
| 	|	R16 ',' R16
 | |
| 			{	if ($1!=SP) serror("register error");
 | |
| 				xyreg($3,0371);
 | |
| 			}
 | |
| 	|	R16 ',' '(' expr ')'
 | |
| 			{	switch ($1) {
 | |
| 				case BC: case DE: case SP:
 | |
| 					emit1(0355); emit1(0113 | $1<<4); break;
 | |
| 				case HL: case IX: case IY:
 | |
| 					xyreg($1,052); break;
 | |
| 				default: serror("register error");
 | |
| 				}
 | |
| #ifdef RELOCATION
 | |
| 				newrelo($4.typ, RELO2);
 | |
| #endif
 | |
| 				emit2($4.val);
 | |
| 			}
 | |
| 	|	'(' expr ')' ',' R8
 | |
| 			{	if ($5!=A) serror("register error");
 | |
| 				emit1(062);
 | |
| #ifdef RELOCATION
 | |
| 				newrelo($2.typ, RELO2);
 | |
| #endif
 | |
| 				emit2($2.val);
 | |
| 			}
 | |
| 	|	'(' expr ')' ',' R16
 | |
| 			{	switch ($5) {
 | |
| 				case BC: case DE: case SP:
 | |
| 					emit1(0355); emit1(0103 | $5<<4); break;
 | |
| 				case HL: case IX: case IY:
 | |
| 					xyreg($5,042); break;
 | |
| 				default: serror("register error");
 | |
| 				}
 | |
| #ifdef RELOCATION
 | |
| 				newrelo($2.typ, RELO2);
 | |
| #endif
 | |
| 				emit2($2.val);
 | |
| 			}
 | |
| 	;
 | |
| r8	:	R8
 | |
| 			{	if ($1==F || $1==I || $1==R)
 | |
| 					serror("register error");
 | |
| 			}
 | |
| 	;
 | |
| indir	:	'(' R16 ')'
 | |
| 			{	if ($2>=SP && $2!=IX && $2!=IY)
 | |
| 					serror("register error");
 | |
| 				exp_ind.typ = S_ABS; exp_ind.val = 0;
 | |
| 				$$ = $2;
 | |
| 			}
 | |
| 	;
 | |
| index	:	'(' R16 '+' expr ')'
 | |
| 			{	if ($2!=IX && $2!=IY) serror("register error");
 | |
| 				exp_ind = $4;
 | |
| 				RELOMOVE(rel_ind, relonami);
 | |
| 				$$ = $2;
 | |
| 			}
 | |
| 	|	'(' R16 '-' expr ')'
 | |
| 			{
 | |
| 				if ($2!=IX && $2!=IY) serror("register error");
 | |
| 				fit(fitb($4.val));
 | |
| 				exp_ind = $4;
 | |
| 				RELOMOVE(rel_ind, relonami);
 | |
| 				$$ = $2;
 | |
| 			}
 | |
| 	;
 | |
| ind	:	indir
 | |
| 	|	index
 | |
| 	;
 | |
| coco	:	CC
 | |
| 	|	R8
 | |
| 			{	if ($1 != C) serror("bad condition code");
 | |
| 				$$ = 3;
 | |
| 			}
 | |
| 	;
 |