Merge pull request #52 from kernigh/pr-relolis

PowerPC: more ha16/lo16 from ncg, new RELOLIS
This commit is contained in:
David Given 2017-02-15 21:04:14 +00:00 committed by GitHub
commit 8f79699ea8
11 changed files with 483 additions and 579 deletions

View file

@ -65,9 +65,9 @@ struct outname {
#define RELO1 1 /* 1 byte */ #define RELO1 1 /* 1 byte */
#define RELO2 2 /* 2 bytes */ #define RELO2 2 /* 2 bytes */
#define RELO4 3 /* 4 bytes */ #define RELO4 3 /* 4 bytes */
#define RELOPPC 4 /* PowerPC 26-bit address */ #define RELOPPC 4 /* PowerPC 26-bit address */
/* relo 5 is unused */ #define RELOLIS 5 /* PowerPC lis */
#define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */ #define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */
#define RELPC 0x2000 /* pc relative */ #define RELPC 0x2000 /* pc relative */
#define RELBR 0x4000 /* High order byte lowest address. */ #define RELBR 0x4000 /* High order byte lowest address. */

View file

@ -11,15 +11,13 @@
#define DEBUG 0 #define DEBUG 0
#undef valu_t #undef valu_t
#define valu_t long #define valu_t int32_t
#undef ADDR_T #undef ADDR_T
#define ADDR_T long #define ADDR_T uint32_t
#undef word_t #undef word_t
#define word_t long #define word_t uint32_t
typedef uint32_t quad;
#undef ALIGNWORD #undef ALIGNWORD
#define ALIGNWORD 4 #define ALIGNWORD 4

View file

@ -3,7 +3,10 @@
* $State$ * $State$
*/ */
#include <stdbool.h> /*
* Do not #include anything here. Do it in mach/proto/as/comm0.h
*/
extern quad emit_hi(struct expr_t* expr, bool is_signed); void no_hl(void);
extern quad emit_lo(struct expr_t* expr); word_t eval_hl(struct expr_t* expr, int token);
void emit_hl(word_t in);

View file

@ -51,6 +51,7 @@
%token <y_word> OP_LIA %token <y_word> OP_LIA
%token <y_word> OP_LIL %token <y_word> OP_LIL
%token <y_word> OP_LI32 %token <y_word> OP_LI32
%token <y_word> OP_RA_RS_C
%token <y_word> OP_RA_RS_RB_C %token <y_word> OP_RA_RS_RB_C
%token <y_word> OP_RA_RS_RB_MB5_ME5_C %token <y_word> OP_RA_RS_RB_MB5_ME5_C
%token <y_word> OP_RA_RS_RB_MB6_C %token <y_word> OP_RA_RS_RB_MB6_C
@ -58,17 +59,16 @@
%token <y_word> OP_RA_RS_SH5_MB5_ME5_C %token <y_word> OP_RA_RS_SH5_MB5_ME5_C
%token <y_word> OP_RA_RS_SH6_C %token <y_word> OP_RA_RS_SH6_C
%token <y_word> OP_RA_RS_SH6_MB6_C %token <y_word> OP_RA_RS_SH6_MB6_C
%token <y_word> OP_RA_RS_UI
%token <y_word> OP_RA_RS_UI_CC
%token <y_word> OP_RS_FXM %token <y_word> OP_RS_FXM
%token <y_word> OP_RS_RA %token <y_word> OP_RS_RA
%token <y_word> OP_RS_RA_C
%token <y_word> OP_RS_RA_D %token <y_word> OP_RS_RA_D
%token <y_word> OP_RS_RA_DS %token <y_word> OP_RS_RA_DS
%token <y_word> OP_RS_RA_NB %token <y_word> OP_RS_RA_NB
%token <y_word> OP_RS_RA_RB %token <y_word> OP_RS_RA_RB
%token <y_word> OP_RS_RA_RB_C %token <y_word> OP_RS_RA_RB_C
%token <y_word> OP_RS_RA_RA_C %token <y_word> OP_RS_RA_RA_C
%token <y_word> OP_RS_RA_UI
%token <y_word> OP_RS_RA_UI_CC
%token <y_word> OP_RS_RB %token <y_word> OP_RS_RB
%token <y_word> OP_RS_SPR %token <y_word> OP_RS_SPR
%token <y_word> OP_RS_SR %token <y_word> OP_RS_SR

View file

@ -498,25 +498,25 @@
0, OP_TOX_RA_SI, 3<<26 | 31<<21, "twui", 0, OP_TOX_RA_SI, 3<<26 | 31<<21, "twui",
/* page 62 */ /* page 62 */
0, OP_RS_RA_UI_CC, 28<<26, "andi", /* C compulsory */ 0, OP_RA_RS_UI_CC, 28<<26, "andi", /* C compulsory */
0, OP_RS_RA_UI_CC, 29<<26, "andis", /* C compulsory */ 0, OP_RA_RS_UI_CC, 29<<26, "andis", /* C compulsory */
0, OP_RS_RA_UI, 24<<26, "ori", 0, OP_RA_RS_UI, 24<<26, "ori",
0, OP_RS_RA_UI, 25<<26, "oris", 0, OP_RA_RS_UI, 25<<26, "oris",
0, OP_RS_RA_UI, 26<<26, "xori", 0, OP_RA_RS_UI, 26<<26, "xori",
0, OP_RS_RA_UI, 27<<26, "xoris", 0, OP_RA_RS_UI, 27<<26, "xoris",
0, OP_RS_RA_RB_C, 31<<26 | 28<<1, "and", 0, OP_RA_RS_RB_C, 31<<26 | 28<<1, "and",
0, OP_RS_RA_RB_C, 31<<26 | 444<<1, "or", 0, OP_RA_RS_RB_C, 31<<26 | 444<<1, "or",
0, OP_RS_RA_RB_C, 31<<26 | 316<<1, "xor", 0, OP_RA_RS_RB_C, 31<<26 | 316<<1, "xor",
0, OP_RS_RA_RB_C, 31<<26 | 476<<1, "nand", 0, OP_RA_RS_RB_C, 31<<26 | 476<<1, "nand",
0, OP_RS_RA_RB_C, 31<<26 | 124<<1, "nor", 0, OP_RA_RS_RB_C, 31<<26 | 124<<1, "nor",
0, OP_RS_RA_RB_C, 31<<26 | 284<<1, "eqv", 0, OP_RA_RS_RB_C, 31<<26 | 284<<1, "eqv",
0, OP_RS_RA_RB_C, 31<<26 | 60<<1, "andc", 0, OP_RA_RS_RB_C, 31<<26 | 60<<1, "andc",
0, OP_RS_RA_RB_C, 31<<26 | 412<<1, "orc", 0, OP_RA_RS_RB_C, 31<<26 | 412<<1, "orc",
0, OP_RS_RA_C, 31<<26 | 954<<1, "extsb", 0, OP_RA_RS_C, 31<<26 | 954<<1, "extsb",
0, OP_RS_RA_C, 31<<26 | 922<<1, "extsh", 0, OP_RA_RS_C, 31<<26 | 922<<1, "extsh",
0, OP_RS_RA_C, 31<<26 | 986<<1, "extsw", 0, OP_RA_RS_C, 31<<26 | 986<<1, "extsw",
0, OP_RS_RA_C, 31<<26 | 58<<1, "cntlzd", 0, OP_RA_RS_C, 31<<26 | 58<<1, "cntlzd",
0, OP_RS_RA_C, 31<<26 | 26<<1, "cntlzw", 0, OP_RA_RS_C, 31<<26 | 26<<1, "cntlzw",
/* extended m using logic */ /* extended m using logic */
0, OP_RS_RA_RA_C, 31<<26 | 444<<1, "mr", 0, OP_RS_RA_RA_C, 31<<26 | 444<<1, "mr",

View file

@ -10,11 +10,11 @@ operation
| OP_BF_BFA CR ',' CR { emit4($1 | ($2<<23) | ($4<<18)); } | 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_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_RB CR ',' u1 ',' GPR ',' GPR { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | ($8<<11)); }
| OP_BF_L_RA_SI CR ',' u1 ',' GPR ',' e16 { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); } | 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 { emit4($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_RB cr_opt GPR ',' GPR { emit4($1 | ($2<<23) | ($3<<16) | ($5<<11)); }
| OP_BF_RA_SI cr_opt GPR ',' e16 { emit4($1 | ($2<<23) | ($3<<16) | $5); } | OP_BF_RA_SI cr_opt GPR ',' e16 { emit_hl($1 | ($2<<23) | ($3<<16) | $5); }
| OP_BF_RA_UI cr_opt GPR ',' e16 { emit4($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_BF_U_C c CR ',' u4 { emit4($1 | $2 | ($3<<23) | ($5<<12)); }
| OP_BH { emit4($1); } | OP_BH { emit4($1); }
| OP_BH u2 { emit4($1 | ($2<<11)); } | OP_BH u2 { emit4($1 | ($2<<11)); }
@ -33,15 +33,16 @@ operation
| OP_BT_BT_BT u5 { emit4($1 | ($2<<21) | ($2<<16) | ($2<<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_BT_C c u5 { emit4($1 | $2 | ($3<<21)); }
| OP_FLM_FRB_C c u8 ',' FPR { emit4($1 | $2 | ($3<<17) | ($5<<11)); } | OP_FLM_FRB_C c u8 ',' FPR { emit4($1 | $2 | ($3<<17) | ($5<<11)); }
| OP_FRS_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | 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_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_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_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_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_FRB_C c FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<11)); }
| OP_FRT_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | 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_RA_RB FPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); }
| OP_FRT_C c FPR { emit4($1 | $2 | ($3<<21)); } | OP_FRT_C c FPR { emit4($1 | $2 | ($3<<21)); }
| OP_RA_RS_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16)); }
| OP_RA_RS_RB_C c GPR ',' GPR ',' GPR | OP_RA_RS_RB_C c GPR ',' GPR ',' GPR
{ emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); }
| OP_RA_RS_RB_MB5_ME5_C c GPR ',' GPR ',' GPR ',' u5 ',' u5 | OP_RA_RS_RB_MB5_ME5_C c GPR ',' GPR ',' GPR ',' u5 ',' u5
@ -58,35 +59,34 @@ operation
{ emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7)); } { emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7)); }
| OP_RA_RS_SH6_MB6_C c GPR ',' GPR ',' u6 ',' u6 | OP_RA_RS_SH6_MB6_C c GPR ',' GPR ',' u6 ',' u6
{ emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7) | MB6($9)); } { 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 GPR { emit4($1 | ($2<<21)); }
| OP_RT_RA_C c GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16)); } | OP_RT_RA_C c GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16)); }
| OP_RT_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | OP_RT_RA_D GPR ',' e16 '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); }
| OP_RT_RA_DS GPR ',' ds '(' GPR ')' { emit4($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_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 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_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); }
| OP_RT_RA_SI GPR ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } | OP_RT_RA_SI GPR ',' GPR ',' e16 { emit_hl($1 | ($2<<21) | ($4<<16) | $6); }
| OP_RT_RA_SI_addic c GPR ',' GPR ',' e16 { emit4($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); } | 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_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_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_RB_RA_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($7<<16) | ($5<<11)); }
| OP_RT_SI GPR ',' e16 { emit4($1 | ($2<<21) | $4); } | 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_SPR GPR ',' spr_num { emit4($1 | ($2<<21) | ($4<<11)); }
| OP_RS_FXM u7 ',' GPR { emit4($1 | ($4<<21) | ($2<<12)); } | OP_RS_FXM u7 ',' GPR { emit4($1 | ($4<<21) | ($2<<12)); }
| OP_RS_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16)); } | OP_RS_RA_D GPR ',' e16 '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); }
| OP_RS_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | OP_RS_RA_DS GPR ',' ds '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); }
| OP_RS_RA_DS GPR ',' ds '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); }
| OP_RS_RA_NB GPR ',' GPR ',' nb { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_RS_RA_NB GPR ',' GPR ',' nb { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); }
| OP_RS_RA_UI GPR ',' GPR ',' e16 { emit4($1 | ($4<<21) | ($2<<16) | $6); }
| OP_RS_RA_UI_CC C GPR ',' GPR ',' e16 { emit4($1 | ($5<<21) | ($3<<16) | $7); }
| OP_RS_RA_RB GPR ',' GPR ',' GPR { 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_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } | OP_RS_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); }
| OP_RS_RA_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($5<<11)); } | OP_RS_RA_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($5<<11)); }
| OP_RS_SPR spr_num ',' GPR { emit4($1 | ($4<<21) | ($2<<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_RB u5 ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); }
| OP_TO_RA_SI u5 ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } | 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_RB GPR ',' GPR { emit4($1 | ($2<<16) | ($4<<11)); }
| OP_TOX_RA_SI GPR ',' e16 { emit4($1 | ($2<<16) | $4); } | OP_TOX_RA_SI GPR ',' e16 { emit_hl($1 | ($2<<16) | $4); }
| OP_LEV { emit4($1); } | OP_LEV { emit4($1); }
| OP_LEV u7 { emit4($1 | ($2<<5)); } | OP_LEV u7 { emit4($1 | ($2<<5)); }
| OP_LIA lia { emit4($1 | $2); } | OP_LIA lia { emit4($1 | $2); }
@ -94,7 +94,7 @@ operation
| OP_LI32 li32 /* emitted in subrule */ | OP_LI32 li32 /* emitted in subrule */
| OP_clrlsldi c GPR ',' GPR ',' u6 ',' u6 | OP_clrlsldi c GPR ',' GPR ',' u6 ',' u6
{ {
quad mb = ($7 - $9) & 0x3f; word_t mb = ($7 - $9) & 0x3f;
fit($9 <= $7); fit($9 <= $7);
emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($9) | MB6(mb)); emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($9) | MB6(mb));
} }
@ -104,41 +104,41 @@ operation
} }
| OP_clrrdi c GPR ',' GPR ',' u6 | OP_clrrdi c GPR ',' GPR ',' u6
{ {
quad me = 63 - $7; word_t me = 63 - $7;
emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(0) | MB6(me)); emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(0) | MB6(me));
} }
| OP_extldi c GPR ',' GPR ',' u6 ',' u6 | OP_extldi c GPR ',' GPR ',' u6 ',' u6
{ {
quad me = ($7 - 1) & 0x3f; word_t me = ($7 - 1) & 0x3f;
fit($7 > 0); fit($7 > 0);
emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($9) | MB6(me)); emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($9) | MB6(me));
} }
| OP_extrdi c GPR ',' GPR ',' u6 ',' u6 | OP_extrdi c GPR ',' GPR ',' u6 ',' u6
{ {
quad sh = ($9 + $7) & 0x3f; word_t sh = ($9 + $7) & 0x3f;
quad mb = (64 - $7) & 0x3f; word_t mb = (64 - $7) & 0x3f;
fit($7 > 0); fit($7 > 0);
emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6(mb)); emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6(mb));
} }
| OP_rotrdi c GPR ',' GPR ',' u6 | OP_rotrdi c GPR ',' GPR ',' u6
{ {
quad sh = (64 - $7) & 0x3f; word_t sh = (64 - $7) & 0x3f;
emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6(0)); emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6(0));
} }
| OP_sldi c GPR ',' GPR ',' u6 | OP_sldi c GPR ',' GPR ',' u6
{ {
quad me = 63 - $7; word_t me = 63 - $7;
emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7) | MB6(me)); emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7) | MB6(me));
} }
| OP_srdi c GPR ',' GPR ',' u6 | OP_srdi c GPR ',' GPR ',' u6
{ {
quad sh = (64 - $7) & 0x3f; word_t sh = (64 - $7) & 0x3f;
emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6($7)); emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6($7));
} }
| OP_clrlslwi c GPR ',' GPR ',' u5 ',' u5 | OP_clrlslwi c GPR ',' GPR ',' u5 ',' u5
{ {
quad mb = ($7 - $9) & 0x1f; word_t mb = ($7 - $9) & 0x1f;
quad me = 31 - $9; word_t me = 31 - $9;
fit($9 <= $7); fit($9 <= $7);
emit4($1 | $2 | ($5<<21) | ($3<<16) | emit4($1 | $2 | ($5<<21) | ($3<<16) |
($9<<11) | (mb<<6) | (me<<1)); ($9<<11) | (mb<<6) | (me<<1));
@ -150,56 +150,56 @@ operation
} }
| OP_clrrwi c GPR ',' GPR ',' u5 | OP_clrrwi c GPR ',' GPR ',' u5
{ {
quad me = 31 - $7; word_t me = 31 - $7;
emit4($1 | $2 | ($5<<21) | ($3<<16) | emit4($1 | $2 | ($5<<21) | ($3<<16) |
(0<<11) | (0<<6) | (me<<1)); (0<<11) | (0<<6) | (me<<1));
} }
| OP_extlwi c GPR ',' GPR ',' u5 ',' u5 | OP_extlwi c GPR ',' GPR ',' u5 ',' u5
{ {
quad me = ($7 - 1) & 0x1f; word_t me = ($7 - 1) & 0x1f;
fit($7 > 0); fit($7 > 0);
emit4($1 | $2 | ($5<<21) | ($3<<16) | emit4($1 | $2 | ($5<<21) | ($3<<16) |
($9<<11) | (0<<6) | (me<<1)); ($9<<11) | (0<<6) | (me<<1));
} }
| OP_extrwi c GPR ',' GPR ',' u5 ',' u5 | OP_extrwi c GPR ',' GPR ',' u5 ',' u5
{ {
quad sh = ($9 + $7) & 0x1f; word_t sh = ($9 + $7) & 0x1f;
quad mb = (32 - $7) & 0x1f; word_t mb = (32 - $7) & 0x1f;
fit($7 > 0); fit($7 > 0);
emit4($1 | $2 | ($5<<21) | ($3<<16) | emit4($1 | $2 | ($5<<21) | ($3<<16) |
(sh<<11) | (mb<<6) | (31<<1)); (sh<<11) | (mb<<6) | (31<<1));
} }
| OP_inslwi c GPR ',' GPR ',' u5 ',' u5 | OP_inslwi c GPR ',' GPR ',' u5 ',' u5
{ {
quad sh = (32 - $9) & 0x1f; word_t sh = (32 - $9) & 0x1f;
quad me = ($9 + $7 - 1) & 0x1f; word_t me = ($9 + $7 - 1) & 0x1f;
fit($7 > 0); fit($7 > 0);
emit4($1 | $2 | ($5<<21) | ($3<<16) | emit4($1 | $2 | ($5<<21) | ($3<<16) |
(sh<<11) | ($9<<6) | (me<<1)); (sh<<11) | ($9<<6) | (me<<1));
} }
| OP_insrwi c GPR ',' GPR ',' u5 ',' u5 | OP_insrwi c GPR ',' GPR ',' u5 ',' u5
{ {
quad sh = (32 - $9 - $7) & 0x1f; word_t sh = (32 - $9 - $7) & 0x1f;
quad me = ($9 + $7 - 1) & 0x1f; word_t me = ($9 + $7 - 1) & 0x1f;
fit($7 > 0); fit($7 > 0);
emit4($1 | $2 | ($5<<21) | ($3<<16) | emit4($1 | $2 | ($5<<21) | ($3<<16) |
(sh<<11) | ($9<<6) | (me<<1)); (sh<<11) | ($9<<6) | (me<<1));
} }
| OP_rotrwi c GPR ',' GPR ',' u5 | OP_rotrwi c GPR ',' GPR ',' u5
{ {
quad sh = (32 - $7) & 0x1f; word_t sh = (32 - $7) & 0x1f;
emit4($1 | $2 | ($5<<21) | ($3<<16) | emit4($1 | $2 | ($5<<21) | ($3<<16) |
(sh<<11) | (0<<6) | (31<<1)); (sh<<11) | (0<<6) | (31<<1));
} }
| OP_slwi c GPR ',' GPR ',' u5 | OP_slwi c GPR ',' GPR ',' u5
{ {
quad me = 31 - $7; word_t me = 31 - $7;
emit4($1 | $2 | ($5<<21) | ($3<<16) | emit4($1 | $2 | ($5<<21) | ($3<<16) |
($7<<11) | (0<<6) | (me<<1)); ($7<<11) | (0<<6) | (me<<1));
} }
| OP_srwi c GPR ',' GPR ',' u5 | OP_srwi c GPR ',' GPR ',' u5
{ {
quad sh = (32 - $7) & 0x1f; word_t sh = (32 - $7) & 0x1f;
emit4($1 | $2 | ($5<<21) | ($3<<16) | emit4($1 | $2 | ($5<<21) | ($3<<16) |
(sh<<11) | ($7<<6) | (31<<1)); (sh<<11) | ($7<<6) | (31<<1));
} }
@ -217,10 +217,11 @@ e16
if (($1 < -0x8000) || ($1 > 0xffff)) if (($1 < -0x8000) || ($1 > 0xffff))
serror("16-bit value out of range"); serror("16-bit value out of range");
$$ = (uint16_t) $1; $$ = (uint16_t) $1;
no_hl();
} }
| OP_HI ASC_LPAR expr ASC_RPAR { $$ = emit_hi(&$3, false); } | OP_HI ASC_LPAR expr ASC_RPAR { $$ = eval_hl(&$3, OP_HI); }
| OP_HA ASC_LPAR expr ASC_RPAR { $$ = emit_hi(&$3, true); } | OP_HA ASC_LPAR expr ASC_RPAR { $$ = eval_hl(&$3, OP_HA); }
| OP_LO ASC_LPAR expr ASC_RPAR { $$ = emit_lo(&$3); } | OP_LO ASC_LPAR expr ASC_RPAR { $$ = eval_hl(&$3, OP_LO); }
; ;
negate16 negate16
@ -367,8 +368,8 @@ bda
li32 li32
: GPR ',' expr : GPR ',' expr
{ {
quad type = $3.typ & S_TYP; word_t type = $3.typ & S_TYP;
quad val = $3.val; word_t val = $3.val;
if ((type == S_ABS) && (val <= 0xffff)) if ((type == S_ABS) && (val <= 0xffff))
emit4((14<<26) | ($1<<21) | (0<<16) | val); /* addi */ emit4((14<<26) | ($1<<21) | (0<<16) | val); /* addi */
else else

View file

@ -1,38 +1,75 @@
static int hl_token;
static expr_t hl_expr;
quad emit_hi(struct expr_t* expr, bool is_signed) void no_hl(void) {
{ hl_token = 0;
/* If this is a symbol reference, discard the symbol and keep only the
* offset part. */
quad type = expr->typ & S_TYP;
quad val = expr->val;
uint16_t hi = val >> 16;
uint16_t lo = val & 0xffff;
if (type != S_ABS)
newrelo(expr->typ, RELOPPC | FIXUPFLAGS);
/* If the low half of this relocation is going to be a memory operation,
* then it'll be treated as a signed value. That means that values greater
* than 0x7fff will cause the high word to have 1 subtracted from it; so
* we apply an adjustment here.
*/
if (is_signed && (lo > 0x7fff))
hi++;
return hi;
} }
quad emit_lo(struct expr_t* expr) word_t eval_hl(expr_t* expr, int token)
{ {
quad type = expr->typ & S_TYP; word_t val = expr->val;
quad val = expr->val; uint16_t hi = val >> 16;
uint16_t lo = val & 0xffff;
/* If the assembler stored a symbol for relocation later, we need to hl_token = token;
* abandon it (because the relocation was generated by emit_ha). */ hl_expr = *expr;
if (type != S_ABS) switch (token) {
relonami = 0; case OP_HI: /* hi16[expr] */
return hi;
return val & 0xffff; case OP_HA: /* ha16[expr]*/
/*
* If the low half will be treated as a signed value,
* then values greater than 0x7fff will cause the high
* half to have 1 subtracted from it; so we apply an
* adjustment here.
*/
if (lo > 0x7fff)
hi++;
return hi;
case OP_LO: /* lo16[expr] */
return lo;
}
}
void emit_hl(word_t in)
{
word_t reg;
int type;
switch (hl_token) {
case OP_HI: /* hi16[expr] */
case OP_HA: /* ha16[expr] */
if (PASS_RELO && (hl_expr.typ & S_TYP) != S_ABS) {
/*
* RELOLIS only works with lis _, _ (same as
* addis _, r0, _). Check if instruction
* isn't addis or register RA isn't r0.
*/
if ((in & 0xfc1f0000) != (0x3c000000))
serror("relocation only works with lis");
/*
* High bit: ha16 flag
* Next 5 bits: register RT
* Low 26 bits: signed offset
*/
fit(fitx(hl_expr.val, 26));
newrelo(hl_expr.typ, RELOLIS | FIXUPFLAGS);
reg = (in >> 21) & 0x1f;
in = (hl_token == OP_HA) << 31;
in |= reg << 26;
in |= hl_expr.val & 0x03ffffff;
}
break;
case OP_LO: /* lo16[expr] */
if (PASS_RELO && (hl_expr.typ & S_TYP) != S_ABS) {
DOTVAL += 2;
newrelo(hl_expr.typ, RELO2 | FIXUPFLAGS);
DOTVAL -= 2;
}
break;
}
emit4(in);
} }

File diff suppressed because it is too large Load diff

View file

@ -140,6 +140,9 @@ showrelo()
case RELOPPC: case RELOPPC:
printf("\tPowerPC 26-bit address\n"); printf("\tPowerPC 26-bit address\n");
break; break;
case RELOLIS:
printf("\tPowerPC lis instruction\n");
break;
case RELOVC4: case RELOVC4:
printf("\tVideoCore IV address in 32-bit instruction\n"); printf("\tVideoCore IV address in 32-bit instruction\n");
break; break;

View file

@ -161,12 +161,13 @@ struct outrelo {
/* /*
* relocation type bits * relocation type bits
*/ */
#define RELSZ 0x0fff /* relocation length */ #define RELSZ 0x0fff /* relocation length */
#define RELO1 0x01 /* 1 byte */ #define RELO1 0x01 /* 1 byte */
#define RELO2 0x02 /* 2 bytes */ #define RELO2 0x02 /* 2 bytes */
#define RELO4 0x03 /* 4 bytes */ #define RELO4 0x03 /* 4 bytes */
#define RELOPPC 0x04 /* 26-bit PowerPC address */ #define RELOPPC 0x04 /* 26-bit PowerPC address */
#define RELOVC4 0x06 /* VideoCore IV address in 32-bit insruction */ #define RELOLIS 0x05 /* PowerPC lis */
#define RELOVC4 0x06 /* VideoCore IV address in 32-bit insruction */
#define RELPC 0x2000 /* pc relative */ #define RELPC 0x2000 /* pc relative */
#define RELBR 0x4000 /* High order byte lowest address. */ #define RELBR 0x4000 /* High order byte lowest address. */
#define RELWR 0x8000 /* High order word lowest address. */ #define RELWR 0x8000 /* High order word lowest address. */
@ -225,10 +226,23 @@ is an absolute number, and the datum is relocated pc relative.
The relocatable datum must then be relocated with respect to the The relocatable datum must then be relocated with respect to the
base address of its section. base address of its section.
.PP .PP
For RELOPPC and RELOVC4, the relocatable datum is a PowerPC or
VideoCore IV instruction.
The relocation depends on the instruction, and uses an offset encoded
in the instruction.
.PP
RELOLIS assembles a PowerPC \fBlis\fR instruction.
The relocatable datum is a 4-byte integer.
The high bit is set for ha16 or clear for hi16.
The next 5 bits are the register \fIRT\fR.
The low 26 bits are a signed offset.
The relocation replaces the datum with the PowerPC instruction
\(oq\fBlis\fR\ \fIRT\fR,\ ha16[\fIsymbol\fR\ +\ \fIoffset\fR]\(cq.
.PP
.B The symbol table. .B The symbol table.
.br .br
This table contains definitions of symbols. It is referred to by This table contains definitions of symbols.
outrelo-structures, and can be used by debuggers. It is referred to by outrelo-structures, and can be used by debuggers.
Entries in this table have the following structure: Entries in this table have the following structure:
.PP .PP
.nf .nf

View file

@ -165,8 +165,17 @@ static uint32_t get_powerpc_valu(char* addr, uint16_t type)
return ((hi << 16) | lo); return ((hi << 16) | lo);
} }
fatal("Don't know how to read from PowerPC fixup on instructions 0x%08x+0x%08x", fatal("Don't know how to read from PowerPC fixup on instructions 0x%08lx+0x%08lx",
opcode1, opcode2); (unsigned long)opcode1, (unsigned long)opcode2);
}
/* RELOLIS stores a signed 26-bit offset in the low bits. */
static uint32_t get_lis_valu(char *addr, uint16_t type)
{
uint32_t valu = read4(addr, type) & 0x03ffffff;
if (valu & 0x02000000)
valu |= 0xfc000000; /* sign extension */
return valu;
} }
/* /*
@ -184,6 +193,8 @@ static uint32_t getvalu(char* addr, uint16_t type)
return read4(addr, type); return read4(addr, type);
case RELOPPC: case RELOPPC:
return get_powerpc_valu(addr, type); return get_powerpc_valu(addr, type);
case RELOLIS:
return get_lis_valu(addr, type);
case RELOVC4: case RELOVC4:
return get_vc4_valu(addr); return get_vc4_valu(addr);
default: default:
@ -327,8 +338,34 @@ static void put_powerpc_valu(char* addr, uint32_t value, uint16_t type)
} }
else else
fatal("Don't know how to write a PowerPC fixup to instructions 0x%08x+0x%08x", fatal("Don't know how to write a PowerPC fixup to instructions 0x%08lx+0x%08lx",
opcode1, opcode2); (unsigned long)opcode1, (unsigned long)opcode2);
}
/* Writes a PowerPC lis instruction. */
static void put_lis_valu(char* addr, uint32_t value, uint16_t type)
{
uint32_t opcode, reg;
uint16_t hi, lo;
bool ha16;
/* ha16 flag in high bit, register in next 5 bits */
opcode = read4(addr, type);
ha16 = opcode >> 31;
reg = (opcode >> 26) & 0x1f;
/*
* Apply the sign adjustment if the ha16 flag is set and the
* low half is a negative signed 16-bit integer.
*/
hi = value >> 16;
lo = value & 0xffff;
if (ha16 && lo > 0x7fff)
hi++;
/* Assemble lis reg, hi == addis reg, r0, hi. */
opcode = (15 << 26) | (reg << 21) | (0 << 16) | hi;
write4(opcode, addr, type);
} }
/* /*
@ -352,6 +389,9 @@ static putvalu(uint32_t valu, char* addr, uint16_t type)
case RELOPPC: case RELOPPC:
put_powerpc_valu(addr, valu, type); put_powerpc_valu(addr, valu, type);
break; break;
case RELOLIS:
put_lis_valu(addr, valu, type);
break;
case RELOVC4: case RELOVC4:
put_vc4_valu(addr, valu); put_vc4_valu(addr, valu);
break; break;