From 5dfef6f1800d5ce930a1644f1639c27faa7804e9 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 9 Sep 2018 14:11:11 +0200 Subject: [PATCH] Rework relocations again: add RELO2HI and RELO2HISAD for the high two bytes of a word. --- h/out.h | 3 ++- mach/mips/as/mach0.c | 4 +--- mach/mips/as/mach2.c | 6 +++--- mach/mips/as/mach3.c | 5 +++-- mach/mips/as/mach4.c | 27 ++++++++++++++++++--------- mach/mips/libem/c_ud_i.s | 4 ++-- mach/mips/libem/c_uf_i.s | 4 ++-- util/amisc/ashow.c | 9 +++++++++ util/led/relocate.c | 18 +++++++++--------- 9 files changed, 49 insertions(+), 31 deletions(-) diff --git a/h/out.h b/h/out.h index cb7995133..ac770738b 100644 --- a/h/out.h +++ b/h/out.h @@ -69,8 +69,9 @@ struct outname { #define RELOPPC_LIS 5 /* PowerPC lis */ #define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */ #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 RELBR 0x4000 /* High order byte lowest address. */ #define RELWR 0x8000 /* High order word lowest address. */ diff --git a/mach/mips/as/mach0.c b/mach/mips/as/mach0.c index f390bccf5..edce6640b 100644 --- a/mach/mips/as/mach0.c +++ b/mach/mips/as/mach0.c @@ -4,8 +4,6 @@ */ #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 RELOCATION /* generate relocatable code */ #define DEBUG 0 @@ -28,4 +26,4 @@ #undef VALWIDTH #define VALWIDTH 8 -#define FIXUPFLAGS (RELBR | RELWR) +#define FIXUPFLAGS 0 diff --git a/mach/mips/as/mach2.c b/mach/mips/as/mach2.c index 48fce7760..9b11f1f1c 100644 --- a/mach/mips/as/mach2.c +++ b/mach/mips/as/mach2.c @@ -5,8 +5,9 @@ %token OP_LI %token OP_LA -%token HI -%token LO +%token HI16 +%token HA16 +%token LO16 %type gpr fpr %type e16 e9 @@ -17,7 +18,6 @@ %type fcond %type extmsblsb insmsblsb -%type hilo %type extabsexp #include "definitions.y" diff --git a/mach/mips/as/mach3.c b/mach/mips/as/mach3.c index 98e62c044..008759d9d 100644 --- a/mach/mips/as/mach3.c +++ b/mach/mips/as/mach3.c @@ -76,8 +76,9 @@ 0, OP_LI, 0, "li", 0, OP_LA, 0, "la", -0, HI, RELO2|RELS2,"hi", -0, LO, RELO2, "lo", +0, HI16, 0, "hi16", +0, HA16, 0, "ha16", +0, LO16, 0, "lo16", #include "tokens.y" diff --git a/mach/mips/as/mach4.c b/mach/mips/as/mach4.c index 45c1bedc6..da7bc1bfb 100644 --- a/mach/mips/as/mach4.c +++ b/mach/mips/as/mach4.c @@ -24,7 +24,7 @@ word_t val = $4.val; if (type != S_ABS) - newrelo($4.typ, RELO2 | RELS2 | FIXUPFLAGS); + newrelo($4.typ, RELO2HI | FIXUPFLAGS); emit4(0x3c000000 | (reg<<16) | (val>>16)); /* lui reg, value */ if (type != S_ABS) newrelo($4.typ, RELO2 | FIXUPFLAGS); @@ -33,16 +33,25 @@ extabsexp : 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; } - ; - -hilo - : HI { $$ = $1; } - | LO { $$ = $1; } ; gpr: GPR @@ -147,7 +156,7 @@ u3 offset16 : expr { - int dist = $1.val - DOTVAL; + int dist = $1.val - DOTVAL - 4; fit(fitx(dist, 18)); if (dist & 0x3) diff --git a/mach/mips/libem/c_ud_i.s b/mach/mips/libem/c_ud_i.s index c0dc10b32..c43658b23 100644 --- a/mach/mips/libem/c_ud_i.s +++ b/mach/mips/libem/c_ud_i.s @@ -12,8 +12,8 @@ * Only at and f31 may be used. */ - ori at, zero, hi[.fd_80000000] - ldc1 f31, lo[.fd_80000000] (at) + ori at, zero, hi16[.fd_80000000] + ldc1 f31, lo16[.fd_80000000] (at) c.le.d 0, f31, f0 bc1t toobig nop diff --git a/mach/mips/libem/c_uf_i.s b/mach/mips/libem/c_uf_i.s index 6dd9f2360..0a4af443d 100644 --- a/mach/mips/libem/c_uf_i.s +++ b/mach/mips/libem/c_uf_i.s @@ -12,8 +12,8 @@ * Only at and f31 may be used. */ - ori at, zero, hi[.ff_80000000] - lwc1 f31, lo[.ff_80000000] (at) + ori at, zero, hi16[.ff_80000000] + lwc1 f31, lo16[.ff_80000000] (at) c.le.s 0, f31, f0 bc1t toobig nop diff --git a/util/amisc/ashow.c b/util/amisc/ashow.c index 6ead9db6c..107e5f8ed 100644 --- a/util/amisc/ashow.c +++ b/util/amisc/ashow.c @@ -134,6 +134,12 @@ showrelo() case RELO2: printf("\t2 bytes\n"); 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: printf("\t4 bytes\n"); break; @@ -146,6 +152,9 @@ showrelo() case RELOVC4: printf("\tVideoCore IV address in 32-bit instruction\n"); break; + case RELOMIPS: + printf("\tMIPS b or j instruction\n"); + break; default: printf("\tunknown relocation type %d\n", relrec.or_type & RELSZ); break; diff --git a/util/led/relocate.c b/util/led/relocate.c index 8b34e8ec2..1f1dc89e6 100644 --- a/util/led/relocate.c +++ b/util/led/relocate.c @@ -213,6 +213,8 @@ static uint32_t getvalu(char* addr, uint16_t type) case RELO1: return UBYTE(addr[0]); case RELO2: + case RELO2HI: + case RELO2HISAD: return read2(addr, type); case RELO4: 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); value >>= 2; - switch (value >> 26) + switch (opcode >> 26) { case 2: /* j */ case 3: /* jal */ @@ -440,6 +442,12 @@ static putvalu(uint32_t valu, char* addr, uint16_t type) case RELO2: write2(valu, addr, type); break; + case RELO2HI: + write2(valu>>16, addr, type); + break; + case RELO2HISAD: + write2((valu>>16) + !!(valu&0x8000), addr, type); + break; case RELO4: write4(valu, addr, type); break; @@ -565,14 +573,6 @@ relocate(head, emit, names, relo, off) if (relo->or_type & RELPC) 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. */