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 RELO2 2 /* 2 bytes */
#define RELO4 3 /* 4 bytes */
#define RELOPPC 4 /* PowerPC 26-bit address */
/* relo 5 is unused */
#define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */
#define RELOPPC 4 /* PowerPC 26-bit address */
#define RELOLIS 5 /* PowerPC lis */
#define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */
#define RELPC 0x2000 /* pc relative */
#define RELBR 0x4000 /* High order byte lowest address. */

View file

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

View file

@ -3,7 +3,10 @@
* $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);
extern quad emit_lo(struct expr_t* expr);
void no_hl(void);
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_LIL
%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_MB5_ME5_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_SH6_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_RA
%token <y_word> OP_RS_RA_C
%token <y_word> OP_RS_RA_D
%token <y_word> OP_RS_RA_DS
%token <y_word> OP_RS_RA_NB
%token <y_word> OP_RS_RA_RB
%token <y_word> OP_RS_RA_RB_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_SPR
%token <y_word> OP_RS_SR

View file

@ -498,25 +498,25 @@
0, OP_TOX_RA_SI, 3<<26 | 31<<21, "twui",
/* page 62 */
0, OP_RS_RA_UI_CC, 28<<26, "andi", /* C compulsory */
0, OP_RS_RA_UI_CC, 29<<26, "andis", /* C compulsory */
0, OP_RS_RA_UI, 24<<26, "ori",
0, OP_RS_RA_UI, 25<<26, "oris",
0, OP_RS_RA_UI, 26<<26, "xori",
0, OP_RS_RA_UI, 27<<26, "xoris",
0, OP_RS_RA_RB_C, 31<<26 | 28<<1, "and",
0, OP_RS_RA_RB_C, 31<<26 | 444<<1, "or",
0, OP_RS_RA_RB_C, 31<<26 | 316<<1, "xor",
0, OP_RS_RA_RB_C, 31<<26 | 476<<1, "nand",
0, OP_RS_RA_RB_C, 31<<26 | 124<<1, "nor",
0, OP_RS_RA_RB_C, 31<<26 | 284<<1, "eqv",
0, OP_RS_RA_RB_C, 31<<26 | 60<<1, "andc",
0, OP_RS_RA_RB_C, 31<<26 | 412<<1, "orc",
0, OP_RS_RA_C, 31<<26 | 954<<1, "extsb",
0, OP_RS_RA_C, 31<<26 | 922<<1, "extsh",
0, OP_RS_RA_C, 31<<26 | 986<<1, "extsw",
0, OP_RS_RA_C, 31<<26 | 58<<1, "cntlzd",
0, OP_RS_RA_C, 31<<26 | 26<<1, "cntlzw",
0, OP_RA_RS_UI_CC, 28<<26, "andi", /* C compulsory */
0, OP_RA_RS_UI_CC, 29<<26, "andis", /* C compulsory */
0, OP_RA_RS_UI, 24<<26, "ori",
0, OP_RA_RS_UI, 25<<26, "oris",
0, OP_RA_RS_UI, 26<<26, "xori",
0, OP_RA_RS_UI, 27<<26, "xoris",
0, OP_RA_RS_RB_C, 31<<26 | 28<<1, "and",
0, OP_RA_RS_RB_C, 31<<26 | 444<<1, "or",
0, OP_RA_RS_RB_C, 31<<26 | 316<<1, "xor",
0, OP_RA_RS_RB_C, 31<<26 | 476<<1, "nand",
0, OP_RA_RS_RB_C, 31<<26 | 124<<1, "nor",
0, OP_RA_RS_RB_C, 31<<26 | 284<<1, "eqv",
0, OP_RA_RS_RB_C, 31<<26 | 60<<1, "andc",
0, OP_RA_RS_RB_C, 31<<26 | 412<<1, "orc",
0, OP_RA_RS_C, 31<<26 | 954<<1, "extsb",
0, OP_RA_RS_C, 31<<26 | 922<<1, "extsh",
0, OP_RA_RS_C, 31<<26 | 986<<1, "extsw",
0, OP_RA_RS_C, 31<<26 | 58<<1, "cntlzd",
0, OP_RA_RS_C, 31<<26 | 26<<1, "cntlzw",
/* extended m using logic */
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_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 { emit4($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_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 { emit4($1 | ($2<<23) | ($3<<16) | $5); }
| OP_BF_RA_UI 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 { 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)); }
@ -33,15 +33,16 @@ operation
| 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 ')' { 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_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 ')' { 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_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
{ emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); }
| 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)); }
| 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 ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); }
| OP_RT_RA_DS GPR ',' ds '(' 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 ')' { 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 { emit4($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 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 { 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_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 ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); }
| OP_RS_RA_DS GPR ',' ds '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); }
| 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_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_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_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 { 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_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 u7 { emit4($1 | ($2<<5)); }
| OP_LIA lia { emit4($1 | $2); }
@ -94,7 +94,7 @@ operation
| OP_LI32 li32 /* emitted in subrule */
| OP_clrlsldi c GPR ',' GPR ',' u6 ',' u6
{
quad mb = ($7 - $9) & 0x3f;
word_t mb = ($7 - $9) & 0x3f;
fit($9 <= $7);
emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($9) | MB6(mb));
}
@ -104,41 +104,41 @@ operation
}
| 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));
}
| OP_extldi c GPR ',' GPR ',' u6 ',' u6
{
quad me = ($7 - 1) & 0x3f;
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
{
quad sh = ($9 + $7) & 0x3f;
quad mb = (64 - $7) & 0x3f;
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
{
quad sh = (64 - $7) & 0x3f;
word_t sh = (64 - $7) & 0x3f;
emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6(0));
}
| 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));
}
| 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));
}
| OP_clrlslwi c GPR ',' GPR ',' u5 ',' u5
{
quad mb = ($7 - $9) & 0x1f;
quad me = 31 - $9;
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));
@ -150,56 +150,56 @@ operation
}
| OP_clrrwi c GPR ',' GPR ',' u5
{
quad me = 31 - $7;
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
{
quad me = ($7 - 1) & 0x1f;
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
{
quad sh = ($9 + $7) & 0x1f;
quad mb = (32 - $7) & 0x1f;
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
{
quad sh = (32 - $9) & 0x1f;
quad me = ($9 + $7 - 1) & 0x1f;
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
{
quad sh = (32 - $9 - $7) & 0x1f;
quad me = ($9 + $7 - 1) & 0x1f;
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
{
quad sh = (32 - $7) & 0x1f;
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
{
quad me = 31 - $7;
word_t me = 31 - $7;
emit4($1 | $2 | ($5<<21) | ($3<<16) |
($7<<11) | (0<<6) | (me<<1));
}
| OP_srwi c GPR ',' GPR ',' u5
{
quad sh = (32 - $7) & 0x1f;
word_t sh = (32 - $7) & 0x1f;
emit4($1 | $2 | ($5<<21) | ($3<<16) |
(sh<<11) | ($7<<6) | (31<<1));
}
@ -217,10 +217,11 @@ e16
if (($1 < -0x8000) || ($1 > 0xffff))
serror("16-bit value out of range");
$$ = (uint16_t) $1;
no_hl();
}
| OP_HI ASC_LPAR expr ASC_RPAR { $$ = emit_hi(&$3, false); }
| OP_HA ASC_LPAR expr ASC_RPAR { $$ = emit_hi(&$3, true); }
| OP_LO ASC_LPAR expr ASC_RPAR { $$ = emit_lo(&$3); }
| 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
@ -367,8 +368,8 @@ bda
li32
: GPR ',' expr
{
quad type = $3.typ & S_TYP;
quad val = $3.val;
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

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)
{
/* 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;
void no_hl(void) {
hl_token = 0;
}
quad emit_lo(struct expr_t* expr)
word_t eval_hl(expr_t* expr, int token)
{
quad type = expr->typ & S_TYP;
quad val = expr->val;
word_t 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
* abandon it (because the relocation was generated by emit_ha). */
hl_token = token;
hl_expr = *expr;
if (type != S_ABS)
relonami = 0;
return val & 0xffff;
switch (token) {
case OP_HI: /* hi16[expr] */
return hi;
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:
printf("\tPowerPC 26-bit address\n");
break;
case RELOLIS:
printf("\tPowerPC lis instruction\n");
break;
case RELOVC4:
printf("\tVideoCore IV address in 32-bit instruction\n");
break;

View file

@ -161,12 +161,13 @@ struct outrelo {
/*
* relocation type bits
*/
#define RELSZ 0x0fff /* relocation length */
#define RELSZ 0x0fff /* relocation length */
#define RELO1 0x01 /* 1 byte */
#define RELO2 0x02 /* 2 bytes */
#define RELO4 0x03 /* 4 bytes */
#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 RELBR 0x4000 /* High order byte 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
base address of its section.
.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.
.br
This table contains definitions of symbols. It is referred to by
outrelo-structures, and can be used by debuggers.
This table contains definitions of symbols.
It is referred to by outrelo-structures, and can be used by debuggers.
Entries in this table have the following structure:
.PP
.nf

View file

@ -165,8 +165,17 @@ static uint32_t get_powerpc_valu(char* addr, uint16_t type)
return ((hi << 16) | lo);
}
fatal("Don't know how to read from PowerPC fixup on instructions 0x%08x+0x%08x",
opcode1, opcode2);
fatal("Don't know how to read from PowerPC fixup on instructions 0x%08lx+0x%08lx",
(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);
case RELOPPC:
return get_powerpc_valu(addr, type);
case RELOLIS:
return get_lis_valu(addr, type);
case RELOVC4:
return get_vc4_valu(addr);
default:
@ -327,8 +338,34 @@ static void put_powerpc_valu(char* addr, uint32_t value, uint16_t type)
}
else
fatal("Don't know how to write a PowerPC fixup to instructions 0x%08x+0x%08x",
opcode1, opcode2);
fatal("Don't know how to write a PowerPC fixup to instructions 0x%08lx+0x%08lx",
(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:
put_powerpc_valu(addr, valu, type);
break;
case RELOLIS:
put_lis_valu(addr, valu, type);
break;
case RELOVC4:
put_vc4_valu(addr, valu);
break;