Add more page numbers from PowerPC version 2.01. Remove "xnop" not in 2.01, add "mtcr" from 2.01. Add "lwarx" and the other instructions from Book II. I did not try all the newly added instructions, but these seem to work: dcbt, dcbtst, icibi, isync, lwarx, stwcx., mftb, mftbu In man/powerpc_as.6 (not installed), add a summary of the registers and addressing modes (like in i386_as.6), describe short forms, update description of hi16/ha16, add CAVEATS about instructions that some processors can't run.
		
			
				
	
	
		
			451 lines
		
	
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			451 lines
		
	
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * $Source$
 | |
|  * $State$
 | |
|  */
 | |
| 
 | |
| operation
 | |
| 	: OP                                              { emit4($1); }
 | |
| 	| OP_BDA               bda                        { emit4($1 | $2); }
 | |
| 	| OP_BDL               bdl                        { emit4($1 | $2); }
 | |
| 	| OP_BF_BFA            CR ',' CR                  { emit4($1 | ($2<<23) | ($4<<18)); }
 | |
| 	| OP_BF_FRA_FRB        CR ',' FPR ',' FPR         { emit4($1 | ($2<<23) | ($4<<16) | ($6<<11)); }
 | |
| 	| OP_BF_L_RA_RB        CR ',' u1 ',' GPR ',' GPR  { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | ($8<<11)); }
 | |
| 	| OP_BF_L_RA_SI        CR ',' u1 ',' GPR ',' e16  { emit_hl($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); }
 | |
| 	| OP_BF_L_RA_UI        CR ',' u1 ',' GPR ',' e16  { emit_hl($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); }
 | |
| 	| OP_BF_RA_RB          cr_opt GPR ',' GPR         { emit4($1 | ($2<<23) | ($3<<16) | ($5<<11)); }
 | |
| 	| OP_BF_RA_SI          cr_opt GPR ',' e16         { emit_hl($1 | ($2<<23) | ($3<<16) | $5); }
 | |
| 	| OP_BF_RA_UI          cr_opt GPR ',' e16         { emit_hl($1 | ($2<<23) | ($3<<16) | $5); }
 | |
| 	| OP_BF_U_C            c CR ',' u4                { emit4($1 | $2 | ($3<<23) | ($5<<12)); }
 | |
| 	| OP_BH                                           { emit4($1); }
 | |
| 	| OP_BH                u2                         { emit4($1 | ($2<<11)); }
 | |
| 	| OP_BI_BDA            u5 ',' bda                 { emit4($1 | ($2<<16) | $4); }
 | |
| 	| OP_BI_BDL            u5 ',' bdl                 { emit4($1 | ($2<<16) | $4); }
 | |
| 	| OP_BI_BH             u5 opt_bh                  { emit4($1 | ($2<<16) | $3); }
 | |
| 	| OP_BICR_BDA          cr_opt bda                 { emit4($1 | ($2<<18) | $3); }
 | |
| 	| OP_BICR_BDL          cr_opt bdl                 { emit4($1 | ($2<<18) | $3); }
 | |
| 	| OP_BICR_BH                                      { emit4($1); }
 | |
| 	| OP_BICR_BH           CR opt_bh                  { emit4($1 | ($2<<18) | $3); }
 | |
| 	| OP_BO_BI_BDA         u5 ',' u5 ',' bda          { emit4($1 | ($2<<21) | ($4<<16) | $6); }
 | |
| 	| OP_BO_BI_BDL         u5 ',' u5 ',' bdl          { emit4($1 | ($2<<21) | ($4<<16) | $6); }
 | |
| 	| OP_BO_BI_BH          u5 ',' u5 opt_bh           { emit4($1 | ($2<<21) | ($4<<16) | $5); }
 | |
| 	| OP_BT_BA_BA          u5 ',' u5                  { emit4($1 | ($2<<21) | ($4<<16) | ($4<<11)); }
 | |
| 	| OP_BT_BA_BB          u5 ',' u5 ',' u5           { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); }
 | |
| 	| OP_BT_BT_BT          u5                         { emit4($1 | ($2<<21) | ($2<<16) | ($2<<11)); }
 | |
| 	| OP_BT_C              c u5                       { emit4($1 | $2 | ($3<<21)); }
 | |
| 	| OP_FLM_FRB_C         c u8 ',' FPR               { emit4($1 | $2 | ($3<<17) | ($5<<11)); }
 | |
| 	| OP_FRS_RA_D          FPR ',' e16 '(' GPR ')'    { emit_hl($1 | ($2<<21) | ($6<<16) | $4); }
 | |
| 	| OP_FRS_RA_RB         FPR ',' GPR ',' GPR        { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); }
 | |
| 	| OP_FRT_FRA_FRB_C     c FPR ',' FPR ',' FPR      { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); }
 | |
| 	| OP_FRT_FRA_FRC_FRB_C c FPR ',' FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($9<<11) | ($7<<6)); }
 | |
| 	| OP_FRT_FRA_FRC_C     c FPR ',' FPR ',' FPR      { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<6)); }
 | |
| 	| OP_FRT_FRB_C         c FPR ',' FPR              { emit4($1 | $2 | ($3<<21) | ($5<<11)); }
 | |
| 	| OP_FRT_RA_D          FPR ',' e16 '(' GPR ')'    { emit_hl($1 | ($2<<21) | ($6<<16) | $4); }
 | |
| 	| OP_FRT_RA_RB         FPR ',' GPR ',' GPR        { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); }
 | |
| 	| OP_FRT_C             c FPR                      { emit4($1 | $2 | ($3<<21)); }
 | |
| 	| OP_L                              { emit4($1); }
 | |
| 	| OP_L                 u2           { emit4($1 | ($2<<21)); }
 | |
| 	| OP_LEV                            { emit4($1); }
 | |
| 	| OP_LEV               u7           { emit4($1 | ($2<<5)); }
 | |
| 	| OP_RA_RB             GPR ',' GPR
 | |
| 	{ emit4($1 | ($2<<16) | ($4<<11)); }
 | |
| 	| OP_RA_RB_TH          GPR ',' GPR opt_bh
 | |
| 	{ emit4($1 | $5 | ($2<<16) | ($4<<11)); }
 | |
| 	/*
 | |
| 	 * For instructions with "mnemonic RS, RA, ..."
 | |
| 	 * OP_RA_RS_... swaps RS and RA to (RA<<21) || (RS<<16)
 | |
| 	 * OP_RS_RA_... keeps RS and RA as (RS<<21) || (RA<<16)
 | |
| 	 */
 | |
| 	| OP_RA_RS_C           c GPR ',' GPR
 | |
| 	{ emit4($1 | $2 | ($5<<21) | ($3<<16)); }
 | |
| 	| OP_RA_RS_RA_C        c GPR ',' GPR
 | |
| 	{ emit4($1 | $2 | ($5<<21) | ($3<<16) | ($5<<11)); }
 | |
| 	| OP_RA_RS_RB_C        c GPR ',' GPR ',' GPR
 | |
| 	{ emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); }
 | |
| 	| OP_RA_RS_RB_MB5_ME5_C c GPR ',' GPR ',' GPR ',' u5 ',' u5
 | |
| 	{ emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) |
 | |
| 		($9<<6) | ($11<<1)); }
 | |
| 	| OP_RA_RS_RB_MB6_C    c GPR ',' GPR ',' GPR ',' u6
 | |
| 	{ emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | MB6($9)); }
 | |
| 	| OP_RA_RS_SH5_C       c GPR ',' GPR ',' u5
 | |
| 	{ emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); }
 | |
| 	| OP_RA_RS_SH5_MB5_ME5_C c GPR ',' GPR ',' u5 ',' u5 ',' u5
 | |
| 	{ emit4($1 | $2 | ($5<<21) | ($3<<16) |
 | |
| 		($7<<11) | ($9<<6) | ($11<<1)); }
 | |
| 	| OP_RA_RS_SH6_C       c GPR ',' GPR ',' u6
 | |
| 	{ emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7)); }
 | |
| 	| OP_RA_RS_SH6_MB6_C   c GPR ',' GPR ',' u6 ',' u6
 | |
| 	{ emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7) | MB6($9)); }
 | |
| 	| OP_RA_RS_UI          GPR ',' GPR ',' e16        { emit_hl($1 | ($4<<21) | ($2<<16) | $6); }
 | |
| 	| OP_RA_RS_UI_CC       C GPR ',' GPR ',' e16      { emit_hl($1 | ($5<<21) | ($3<<16) | $7); }
 | |
| 	| OP_RT                GPR                        { emit4($1 | ($2<<21)); }
 | |
| 	| OP_RT_RA_C           c GPR ',' GPR              { emit4($1 | $2 | ($3<<21) | ($5<<16)); }
 | |
| 	| OP_RT_RA_D           GPR ',' e16 '(' GPR ')'    { emit_hl($1 | ($2<<21) | ($6<<16) | $4); }
 | |
| 	| OP_RT_RA_DS          GPR ',' ds '(' GPR ')'     { emit_hl($1 | ($2<<21) | ($6<<16) | $4); }
 | |
| 	| OP_RT_RA_NB          GPR ',' GPR ',' nb         { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); }
 | |
| 	| OP_RT_RA_RB          GPR ',' GPR ',' GPR        { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); }
 | |
| 	| OP_RT_RA_RB_C        c GPR ',' GPR ',' GPR      { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); }
 | |
| 	| OP_RT_RA_SI          GPR ',' GPR ',' e16        { emit_hl($1 | ($2<<21) | ($4<<16) | $6); }
 | |
| 	| OP_RT_RA_SI_addic    c GPR ',' GPR ',' e16      { emit_hl($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); }
 | |
| 	| OP_RT_RA_SI_subi     GPR ',' GPR ',' negate16   { emit4($1 | ($2<<21) | ($4<<16) | $6); }
 | |
| 	| OP_RT_RA_SI_subic    c GPR ',' GPR ',' negate16 { emit4($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); }
 | |
| 	| OP_RT_RB_RA_C        c GPR ',' GPR ',' GPR      { emit4($1 | $2 | ($3<<21) | ($7<<16) | ($5<<11)); }
 | |
| 	| OP_RT_SI             GPR ',' e16                { emit_hl($1 | ($2<<21) | $4); }
 | |
| 	| OP_RT_SPR            GPR ',' spr_num            { emit4($1 | ($2<<21) | ($4<<11)); }
 | |
| 	| OP_RT_TBR            GPR opt_tbr                { emit4($1 | ($2<<21) | ($3<<11)); }
 | |
| 	| OP_RS                GPR                        { emit4($1 | ($2<<21)); }
 | |
| 	| OP_RS_FXM            u7 ',' GPR                 { emit4($1 | ($4<<21) | ($2<<12)); }
 | |
| 	| OP_RS_RA_D           GPR ',' e16 '(' GPR ')'    { emit_hl($1 | ($2<<21) | ($6<<16) | $4); }
 | |
| 	| OP_RS_RA_DS          GPR ',' ds '(' GPR ')'     { emit_hl($1 | ($2<<21) | ($6<<16) | $4); }
 | |
| 	| OP_RS_RA_NB          GPR ',' GPR ',' nb         { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); }
 | |
| 	| OP_RS_RA_RB          GPR ',' GPR ',' GPR        { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); }
 | |
| 	| OP_RS_RA_RB_CC       C GPR ',' GPR ',' GPR      { emit4($1 | ($3<<21) | ($5<<16) | ($7<<11)); }
 | |
| 	| OP_RS_SPR            spr_num ',' GPR            { emit4($1 | ($4<<21) | ($2<<11)); }
 | |
| 	| OP_TO_RA_RB          u5 ',' GPR ',' GPR         { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); }
 | |
| 	| OP_TO_RA_SI          u5 ',' GPR ',' e16         { emit_hl($1 | ($2<<21) | ($4<<16) | $6); }
 | |
| 	| OP_TOX_RA_RB         GPR ',' GPR                { emit4($1 | ($2<<16) | ($4<<11)); }
 | |
| 	| OP_TOX_RA_SI         GPR ',' e16                { emit_hl($1 | ($2<<16) | $4); }
 | |
| 	| OP_LIA               lia                        { emit4($1 | $2); }
 | |
| 	| OP_LIL               lil                        { emit4($1 | $2); }
 | |
| 	| OP_LI32              li32                       /* emitted in subrule */
 | |
| 	| OP_clrlsldi          c GPR ',' GPR ',' u6 ',' u6
 | |
| 	{
 | |
| 		word_t mb = ($7 - $9) & 0x3f;
 | |
| 		fit($9 <= $7);
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($9) | MB6(mb));
 | |
| 	}
 | |
| 	| OP_clrldi            c GPR ',' GPR ',' u6
 | |
| 	{
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(0) | MB6($7));
 | |
| 	}
 | |
| 	| OP_clrrdi            c GPR ',' GPR ',' u6
 | |
| 	{
 | |
| 		word_t me = 63 - $7;
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(0) | MB6(me));
 | |
| 	}
 | |
| 	| OP_extldi            c GPR ',' GPR ',' u6 ',' u6
 | |
| 	{
 | |
| 		word_t me = ($7 - 1) & 0x3f;
 | |
| 		fit($7 > 0);
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($9) | MB6(me));
 | |
| 	}
 | |
| 	| OP_extrdi            c GPR ',' GPR ',' u6 ',' u6
 | |
| 	{
 | |
| 		word_t sh = ($9 + $7) & 0x3f;
 | |
| 		word_t mb = (64 - $7) & 0x3f;
 | |
| 		fit($7 > 0);
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6(mb));
 | |
| 	}
 | |
| 	| OP_rotrdi            c GPR ',' GPR ',' u6
 | |
| 	{
 | |
| 		word_t sh = (64 - $7) & 0x3f;
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6(0));
 | |
| 	}
 | |
| 	| OP_sldi              c GPR ',' GPR ',' u6
 | |
| 	{
 | |
| 		word_t me = 63 - $7;
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7) | MB6(me));
 | |
| 	}
 | |
| 	| OP_srdi              c GPR ',' GPR ',' u6
 | |
| 	{
 | |
| 		word_t sh = (64 - $7) & 0x3f;
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6($7));
 | |
| 	}
 | |
| 	| OP_clrlslwi          c GPR ',' GPR ',' u5 ',' u5
 | |
| 	{
 | |
| 		word_t mb = ($7 - $9) & 0x1f;
 | |
| 		word_t me = 31 - $9;
 | |
| 		fit($9 <= $7);
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) |
 | |
| 		      ($9<<11) | (mb<<6) | (me<<1));
 | |
| 	}
 | |
| 	| OP_clrlwi            c GPR ',' GPR ',' u5
 | |
| 	{
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) |
 | |
| 		      (0<<11) | ($7<<6) | (31<<1));
 | |
| 	}
 | |
| 	| OP_clrrwi            c GPR ',' GPR ',' u5
 | |
| 	{
 | |
| 		word_t me = 31 - $7;
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) |
 | |
| 		      (0<<11) | (0<<6) | (me<<1));
 | |
| 	}
 | |
| 	| OP_extlwi            c GPR ',' GPR ',' u5 ',' u5
 | |
| 	{
 | |
| 		word_t me = ($7 - 1) & 0x1f;
 | |
| 		fit($7 > 0);
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) |
 | |
| 		      ($9<<11) | (0<<6) | (me<<1));
 | |
| 	}
 | |
| 	| OP_extrwi            c GPR ',' GPR ',' u5 ',' u5
 | |
| 	{
 | |
| 		word_t sh = ($9 + $7) & 0x1f;
 | |
| 		word_t mb = (32 - $7) & 0x1f;
 | |
| 		fit($7 > 0);
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) |
 | |
| 		      (sh<<11) | (mb<<6) | (31<<1));
 | |
| 	}
 | |
| 	| OP_inslwi            c GPR ',' GPR ',' u5 ',' u5
 | |
| 	{
 | |
| 		word_t sh = (32 - $9) & 0x1f;
 | |
| 		word_t me = ($9 + $7 - 1) & 0x1f;
 | |
| 		fit($7 > 0);
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) |
 | |
| 		      (sh<<11) | ($9<<6) | (me<<1));
 | |
| 	}
 | |
| 	| OP_insrwi            c GPR ',' GPR ',' u5 ',' u5
 | |
| 	{
 | |
| 		word_t sh = (32 - $9 - $7) & 0x1f;
 | |
| 		word_t me = ($9 + $7 - 1) & 0x1f;
 | |
| 		fit($7 > 0);
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) |
 | |
| 		      (sh<<11) | ($9<<6) | (me<<1));
 | |
| 	}
 | |
| 	| OP_rotrwi      c GPR ',' GPR ',' u5
 | |
| 	{
 | |
| 		word_t sh = (32 - $7) & 0x1f;
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) |
 | |
| 		      (sh<<11) | (0<<6) | (31<<1));
 | |
| 	}
 | |
| 	| OP_slwi              c GPR ',' GPR ',' u5
 | |
| 	{
 | |
| 		word_t me = 31 - $7;
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) |
 | |
| 		      ($7<<11) | (0<<6) | (me<<1));
 | |
| 	}
 | |
| 	| OP_srwi              c GPR ',' GPR ',' u5
 | |
| 	{
 | |
| 		word_t sh = (32 - $7) & 0x1f;
 | |
| 		emit4($1 | $2 | ($5<<21) | ($3<<16) |
 | |
| 		      (sh<<11) | ($7<<6) | (31<<1));
 | |
| 	}
 | |
| 	;
 | |
| 
 | |
| c
 | |
| 	: /* nothing */                          { $$ = 0; }
 | |
| 	| C                                      { $$ = 1; }
 | |
| 	;
 | |
| 
 | |
| e16
 | |
| 	: absexp
 | |
| 	{
 | |
| 		/* Allow signed or unsigned 16-bit values. */
 | |
| 		if (($1 < -0x8000) || ($1 > 0xffff))
 | |
| 			serror("16-bit value out of range");
 | |
| 		$$ = (uint16_t) $1;
 | |
| 		no_hl();
 | |
| 	}
 | |
| 	| OP_HI ASC_LPAR expr ASC_RPAR           { $$ = eval_hl(&$3, OP_HI); }
 | |
| 	| OP_HA ASC_LPAR expr ASC_RPAR           { $$ = eval_hl(&$3, OP_HA); }
 | |
| 	| OP_LO ASC_LPAR expr ASC_RPAR           { $$ = eval_hl(&$3, OP_LO); }
 | |
| 	;
 | |
| 
 | |
| negate16
 | |
| 	: absexp
 | |
| 	{
 | |
| 		/* To encode subi, we negate the immediate value, then
 | |
| 		 * it must fit as signed 16-bit. */
 | |
| 		$$ = -$1;
 | |
| 		fit(fitx($$, 16));
 | |
| 		$$ = (uint16_t) $$;
 | |
| 	}
 | |
| 	;
 | |
| 
 | |
| u8
 | |
| 	: absexp
 | |
| 	{
 | |
| 		if (($1 < 0) || ($1 > 0xFF))
 | |
| 			serror("8-bit unsigned value out of range");
 | |
| 		$$ = $1;
 | |
| 	}
 | |
| 	;
 | |
| 
 | |
| u7
 | |
| 	: absexp
 | |
| 	{
 | |
| 		if (($1 < 0) || ($1 > 0x7F))
 | |
| 			serror("7-bit unsigned value out of range");
 | |
| 		$$ = $1;
 | |
| 	}
 | |
| 	;
 | |
| 
 | |
| u6
 | |
| 	: absexp
 | |
| 	{
 | |
| 		if (($1 < 0) || ($1 > 0x3F))
 | |
| 			serror("6-bit unsigned value out of range");
 | |
| 		$$ = $1;
 | |
| 	}
 | |
| 	;
 | |
| 
 | |
| u5
 | |
| 	: absexp
 | |
| 	{
 | |
| 		if (($1 < 0) || ($1 > 0x1F))
 | |
| 			serror("5-bit unsigned value out of range");
 | |
| 		$$ = $1;
 | |
| 	}
 | |
| 	;
 | |
| 
 | |
| u4
 | |
| 	: absexp
 | |
| 	{
 | |
| 		if (($1 < 0) || ($1 > 0xF))
 | |
| 			serror("4-bit unsigned value out of range");
 | |
| 		$$ = $1;
 | |
| 	}
 | |
| 	;
 | |
| 
 | |
| u1
 | |
| 	: absexp
 | |
| 	{
 | |
| 		if (($1 < 0) || ($1 > 1))
 | |
| 			serror("1-bit unsigned value out of range");
 | |
| 		$$ = $1;
 | |
| 	}
 | |
| 	;
 | |
| 
 | |
| u2
 | |
| 	: absexp
 | |
| 	{
 | |
| 		if (($1 < 0) || ($1 > 0x3))
 | |
| 			serror("2-bit unsigned value out of range");
 | |
| 		$$ = $1;
 | |
| 	}
 | |
| 	;
 | |
| 
 | |
| /* Optional comma, branch hint (or touch hint). */
 | |
| opt_bh
 | |
| 	: /* nothing */         { $$ = 0; }
 | |
| 	| ',' u2                { $$ = ($2<<11); }
 | |
| 
 | |
| /*
 | |
|  * Optional condition register, comma.  This checks if the token is a
 | |
|  * CR register name.  This wouldn't work if we allowed CR as a number.
 | |
|  */
 | |
| cr_opt
 | |
| 	: /* nothing */         { $$ = 0; }
 | |
| 	| CR ','                { $$ = $1; }
 | |
| 
 | |
| ds
 | |
| 	: e16
 | |
| 	{
 | |
| 		if ($1 & 3)
 | |
| 			serror("value must be 4-aligned");
 | |
| 		$$ = $1;
 | |
| 	}
 | |
| 	;
 | |
| 
 | |
| nb
 | |
| 	: absexp
 | |
| 	{
 | |
| 		if (($1 < 1) || ($1 > 32))
 | |
| 			serror("register count must be in the range 1..32");
 | |
| 
 | |
| 		if ($1 == 32)
 | |
| 			$$ = 0;
 | |
| 		else
 | |
| 			$$ = $1;
 | |
| 	}
 | |
| 	;
 | |
| 
 | |
| bdl
 | |
| 	: expr
 | |
| 	{
 | |
| 		int dist = $1.val - DOTVAL;
 | |
| 		fit(fitx(dist, 25));
 | |
| 
 | |
| 		if (dist & 0x3)
 | |
| 			serror("jump targets must be 4-aligned");
 | |
| 
 | |
| 		DOTVAL += 2;
 | |
| 		newrelo($1.typ, RELO2 | RELPC | FIXUPFLAGS);
 | |
| 		DOTVAL -= 2;
 | |
| 		$$ = dist & 0xFFFD;
 | |
| 	}
 | |
| 	;
 | |
| 
 | |
| bda
 | |
| 	: expr
 | |
| 	{
 | |
| 		int target = $1.val;
 | |
| 		fit(fitx(target, 16));
 | |
| 
 | |
| 		if (target & 0x3)
 | |
| 			serror("jump targets must be 4-aligned");
 | |
| 
 | |
| 		DOTVAL += 2;
 | |
| 		newrelo($1.typ, RELO2 | FIXUPFLAGS);
 | |
| 		DOTVAL -= 2;
 | |
| 		$$ = target & 0xFFFD;
 | |
| 	}
 | |
| 	;
 | |
| 
 | |
| li32
 | |
| 	: GPR ',' expr
 | |
| 	{
 | |
| 		word_t type = $3.typ & S_TYP;
 | |
| 		word_t val = $3.val;
 | |
| 		if ((type == S_ABS) && (val <= 0xffff))
 | |
| 			emit4((14<<26) | ($1<<21) | (0<<16)  | val); /* addi */
 | |
| 		else
 | |
| 		{
 | |
| 			newrelo($3.typ, RELOPPC | FIXUPFLAGS);
 | |
| 			emit4((15<<26) | ($1<<21) | (0<<16)  | (val >> 16)); /* addis */
 | |
| 			emit4((24<<26) | ($1<<21) | ($1<<16) | (val & 0xffff)); /* ori */
 | |
| 		}
 | |
| 	}
 | |
| 	;
 | |
| 
 | |
| lil
 | |
| 	: expr
 | |
| 	{
 | |
| 		int dist = $1.val - DOTVAL;
 | |
| 		fit(fitx(dist, 26));
 | |
| 
 | |
| 		if (dist & 0x3)
 | |
| 			serror("jump targets must be 4-aligned");
 | |
| 
 | |
| 		newrelo($1.typ, RELOPPC | RELPC | FIXUPFLAGS);
 | |
| 		$$ = dist & 0x03FFFFFD;
 | |
| 	}
 | |
| 	;
 | |
| 
 | |
| lia
 | |
| 	: expr
 | |
| 	{
 | |
| 		int target = $1.val;
 | |
| 		fit(fitx(target, 26));
 | |
| 
 | |
| 		if (target & 0x3)
 | |
| 			serror("jump targets must be 4-aligned");
 | |
| 
 | |
| 		newrelo($1.typ, RELOPPC | FIXUPFLAGS);
 | |
| 		$$ = target & 0x03FFFFFD;
 | |
| 	}
 | |
| 	;
 | |
| 
 | |
| /*
 | |
|  * Instructions "mfspr", "mtspr", and "mftb" encode the 10-bit special
 | |
|  * purpose register (spr) or time base register (tbr) by swapping the
 | |
|  * low 5 bits with the high 5 bits.  The value from an SPR token has
 | |
|  * already been swapped.
 | |
|  */
 | |
| 
 | |
| spr_num
 | |
| 	: SPR     { $$ = $1; }
 | |
| 	| tbr_num { $$ = $1; }
 | |
| 	;
 | |
| 
 | |
| opt_tbr
 | |
| 	: /* nothing */         { $$ = 8 | (12<<5); }
 | |
| 	| ',' tbr_num           { $$ = $2; }
 | |
| 	;
 | |
| 
 | |
| tbr_num
 | |
| 	: absexp
 | |
| 	{
 | |
| 		if (($1 < 0) || ($1 > 0x3ff))
 | |
| 			serror("10-bit unsigned value out of range");
 | |
| 		$$ = ($1 >> 5) | (($1 & 0x1f) << 5);
 | |
| 	}
 | |
| 	;
 |