/* * $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); } ;