Rework relocations again: add RELO2HI and RELO2HISAD for the high two bytes of

a word.
This commit is contained in:
David Given 2018-09-09 14:11:11 +02:00
parent 95dd6f0141
commit 5dfef6f180
9 changed files with 49 additions and 31 deletions

View file

@ -69,8 +69,9 @@ struct outname {
#define RELOPPC_LIS 5 /* PowerPC lis */ #define RELOPPC_LIS 5 /* PowerPC lis */
#define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */ #define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */
#define RELOMIPS 7 /* MIPS */ #define RELOMIPS 7 /* MIPS */
#define RELO2HI 8 /* high 2 bytes of word */
#define RELO2HISAD 9 /* high 2 bytes of word, sign adjusted */
#define RELS2 0x1000 /* shift result right 16 bits before writing back */
#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. */

View file

@ -4,8 +4,6 @@
*/ */
#define THREE_PASS /* branch and offset optimization */ #define THREE_PASS /* branch and offset optimization */
#define BYTES_REVERSED /* high order byte has lowest address */
#define WORDS_REVERSED /* high order word has lowest address */
#define LISTING /* enable listing facilities */ #define LISTING /* enable listing facilities */
#define RELOCATION /* generate relocatable code */ #define RELOCATION /* generate relocatable code */
#define DEBUG 0 #define DEBUG 0
@ -28,4 +26,4 @@
#undef VALWIDTH #undef VALWIDTH
#define VALWIDTH 8 #define VALWIDTH 8
#define FIXUPFLAGS (RELBR | RELWR) #define FIXUPFLAGS 0

View file

@ -5,8 +5,9 @@
%token <y_word> OP_LI %token <y_word> OP_LI
%token <y_word> OP_LA %token <y_word> OP_LA
%token <y_word> HI %token <y_word> HI16
%token <y_word> LO %token <y_word> HA16
%token <y_word> LO16
%type <y_word> gpr fpr %type <y_word> gpr fpr
%type <y_word> e16 e9 %type <y_word> e16 e9
@ -17,7 +18,6 @@
%type <y_word> fcond %type <y_word> fcond
%type <y_word> extmsblsb insmsblsb %type <y_word> extmsblsb insmsblsb
%type <y_word> hilo
%type <y_valu> extabsexp %type <y_valu> extabsexp
#include "definitions.y" #include "definitions.y"

View file

@ -76,8 +76,9 @@
0, OP_LI, 0, "li", 0, OP_LI, 0, "li",
0, OP_LA, 0, "la", 0, OP_LA, 0, "la",
0, HI, RELO2|RELS2,"hi", 0, HI16, 0, "hi16",
0, LO, RELO2, "lo", 0, HA16, 0, "ha16",
0, LO16, 0, "lo16",
#include "tokens.y" #include "tokens.y"

View file

@ -24,7 +24,7 @@
word_t val = $4.val; word_t val = $4.val;
if (type != S_ABS) if (type != S_ABS)
newrelo($4.typ, RELO2 | RELS2 | FIXUPFLAGS); newrelo($4.typ, RELO2HI | FIXUPFLAGS);
emit4(0x3c000000 | (reg<<16) | (val>>16)); /* lui reg, value */ emit4(0x3c000000 | (reg<<16) | (val>>16)); /* lui reg, value */
if (type != S_ABS) if (type != S_ABS)
newrelo($4.typ, RELO2 | FIXUPFLAGS); newrelo($4.typ, RELO2 | FIXUPFLAGS);
@ -33,16 +33,25 @@
extabsexp extabsexp
: absexp : absexp
| hilo ASC_LPAR expr ASC_RPAR | LO16 ASC_LPAR expr ASC_RPAR
{ {
newrelo($3.typ, $1 | FIXUPFLAGS); newrelo($3.typ, RELO2 | FIXUPFLAGS);
$$ = $3.val;
}
| HI16 ASC_LPAR expr ASC_RPAR
{
newrelo($3.typ, RELO2HI | FIXUPFLAGS);
if ($3.val & 0xffff0000)
fatal("relocation offset in hi16[] too big");
$$ = $3.val;
}
| HA16 ASC_LPAR expr ASC_RPAR
{
newrelo($3.typ, RELO2HISAD | FIXUPFLAGS);
if ($3.val & 0xffff0000)
fatal("relocation offset in ha16[] too big");
$$ = $3.val; $$ = $3.val;
} }
;
hilo
: HI { $$ = $1; }
| LO { $$ = $1; }
; ;
gpr: GPR gpr: GPR
@ -147,7 +156,7 @@ u3
offset16 offset16
: expr : expr
{ {
int dist = $1.val - DOTVAL; int dist = $1.val - DOTVAL - 4;
fit(fitx(dist, 18)); fit(fitx(dist, 18));
if (dist & 0x3) if (dist & 0x3)

View file

@ -12,8 +12,8 @@
* Only at and f31 may be used. * Only at and f31 may be used.
*/ */
ori at, zero, hi[.fd_80000000] ori at, zero, hi16[.fd_80000000]
ldc1 f31, lo[.fd_80000000] (at) ldc1 f31, lo16[.fd_80000000] (at)
c.le.d 0, f31, f0 c.le.d 0, f31, f0
bc1t toobig bc1t toobig
nop nop

View file

@ -12,8 +12,8 @@
* Only at and f31 may be used. * Only at and f31 may be used.
*/ */
ori at, zero, hi[.ff_80000000] ori at, zero, hi16[.ff_80000000]
lwc1 f31, lo[.ff_80000000] (at) lwc1 f31, lo16[.ff_80000000] (at)
c.le.s 0, f31, f0 c.le.s 0, f31, f0
bc1t toobig bc1t toobig
nop nop

View file

@ -134,6 +134,12 @@ showrelo()
case RELO2: case RELO2:
printf("\t2 bytes\n"); printf("\t2 bytes\n");
break; break;
case RELO2HI:
printf("\ttop 2 bytes of result\n");
break;
case RELO2HISAD:
printf("\ttop 2 bytes of result, sign adjusted\n");
break;
case RELO4: case RELO4:
printf("\t4 bytes\n"); printf("\t4 bytes\n");
break; break;
@ -146,6 +152,9 @@ showrelo()
case RELOVC4: case RELOVC4:
printf("\tVideoCore IV address in 32-bit instruction\n"); printf("\tVideoCore IV address in 32-bit instruction\n");
break; break;
case RELOMIPS:
printf("\tMIPS b or j instruction\n");
break;
default: default:
printf("\tunknown relocation type %d\n", relrec.or_type & RELSZ); printf("\tunknown relocation type %d\n", relrec.or_type & RELSZ);
break; break;

View file

@ -213,6 +213,8 @@ static uint32_t getvalu(char* addr, uint16_t type)
case RELO1: case RELO1:
return UBYTE(addr[0]); return UBYTE(addr[0]);
case RELO2: case RELO2:
case RELO2HI:
case RELO2HISAD:
return read2(addr, type); return read2(addr, type);
case RELO4: case RELO4:
return read4(addr, type); return read4(addr, type);
@ -405,7 +407,7 @@ static void put_mips_valu(char* addr, uint32_t value)
fatal("invalid MIPS relocation value 0x%x", value); fatal("invalid MIPS relocation value 0x%x", value);
value >>= 2; value >>= 2;
switch (value >> 26) switch (opcode >> 26)
{ {
case 2: /* j */ case 2: /* j */
case 3: /* jal */ case 3: /* jal */
@ -440,6 +442,12 @@ static putvalu(uint32_t valu, char* addr, uint16_t type)
case RELO2: case RELO2:
write2(valu, addr, type); write2(valu, addr, type);
break; break;
case RELO2HI:
write2(valu>>16, addr, type);
break;
case RELO2HISAD:
write2((valu>>16) + !!(valu&0x8000), addr, type);
break;
case RELO4: case RELO4:
write4(valu, addr, type); write4(valu, addr, type);
break; break;
@ -565,14 +573,6 @@ relocate(head, emit, names, relo, off)
if (relo->or_type & RELPC) if (relo->or_type & RELPC)
valu -= relorig[sectindex].org_size+outsect[sectindex].os_base; valu -= relorig[sectindex].org_size+outsect[sectindex].os_base;
/*
* If RELS2 is set, right shift the value by sixteen bits; this
* allows 32-bit values to be fixed up as a high word and a low
* word.
*/
if (relo->or_type & RELS2)
valu >>= 16;
/* /*
* Now put the value back. * Now put the value back.
*/ */