Add RELOLIS for PowerPC lis with ha16 or hi16.
The new relocation type RELOLIS handles these instructions: lis RT, ha16[expr] == addis RT, r0, ha16[expr] lis RT, hi16[expr] == addis RT, r0, hi16[expr] RELOLIS stores a 32-bit value in the program text. In this value, the high bit is a ha16 flag, the next 5 bits are the target register RT, and the low bits are a signed 26-bit offset. The linker replaces this value with the lis instruction. The old RELOPPC relocated a ha16/lo16 or hi16/lo16 pair. The new RELOLIS relocates only a ha16 or hi16, so it is no longer necessary to have a matching lo16 in the next instruction. The disadvantage is that RELOLIS has only a signed 26-bit offset, not a 32-bit offset. Switch the assembler to use RELOLIS for ha16 or hi16 and RELO2 for lo16. The li32 instruction still uses the old RELOPPC relocation. This is not the same as my RELOPPC change from my recent mail to tack-devel (https://sourceforge.net/p/tack/mailman/message/35651528/). This commit is on a different branch. Here I am throwing away my RELOPPC change and instead trying RELOLIS.
This commit is contained in:
parent
f4cfbedd5c
commit
1bf58cf51c
6
h/out.h
6
h/out.h
|
@ -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. */
|
||||||
|
|
|
@ -7,5 +7,6 @@
|
||||||
* Do not #include anything here. Do it in mach/proto/as/comm0.h
|
* Do not #include anything here. Do it in mach/proto/as/comm0.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern word_t emit_hi(struct expr_t* expr, int is_signed);
|
void no_hl(void);
|
||||||
extern word_t emit_lo(struct expr_t* expr);
|
word_t eval_hl(struct expr_t* expr, int token);
|
||||||
|
void emit_hl(word_t in);
|
||||||
|
|
|
@ -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,13 +33,13 @@ 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_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16)); }
|
||||||
|
@ -59,34 +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 { emit4($1 | ($4<<21) | ($2<<16) | $6); }
|
| OP_RA_RS_UI GPR ',' GPR ',' e16 { emit_hl($1 | ($4<<21) | ($2<<16) | $6); }
|
||||||
| OP_RA_RS_UI_CC C GPR ',' GPR ',' e16 { emit4($1 | ($5<<21) | ($3<<16) | $7); }
|
| 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_D GPR ',' e16 '(' 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 ')' { 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_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_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); }
|
||||||
|
@ -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, 0); }
|
| OP_HI ASC_LPAR expr ASC_RPAR { $$ = eval_hl(&$3, OP_HI); }
|
||||||
| OP_HA ASC_LPAR expr ASC_RPAR { $$ = emit_hi(&$3, 1); }
|
| 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
|
||||||
|
|
|
@ -1,38 +1,75 @@
|
||||||
|
static int hl_token;
|
||||||
|
static expr_t hl_expr;
|
||||||
|
|
||||||
word_t emit_hi(struct expr_t* expr, int is_signed)
|
void no_hl(void) {
|
||||||
{
|
hl_token = 0;
|
||||||
/* If this is a symbol reference, discard the symbol and keep only the
|
|
||||||
* offset part. */
|
|
||||||
word_t type = expr->typ & S_TYP;
|
|
||||||
word_t 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
word_t emit_lo(struct expr_t* expr)
|
word_t eval_hl(expr_t* expr, int token)
|
||||||
{
|
{
|
||||||
word_t type = expr->typ & S_TYP;
|
word_t 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
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue