diff --git a/h/out.h b/h/out.h index 122296f8e..2c97219e5 100644 --- a/h/out.h +++ b/h/out.h @@ -64,6 +64,7 @@ struct outname { #define RELO4 3 /* 4 bytes */ #define RELOPPC 4 /* PowerPC 26-bit address */ #define RELOH2 5 /* write top 2 bytes of 4 byte word */ +#define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */ #define RELPC 0x08 /* pc relative */ #define RELBR 0x10 /* High order byte lowest address. */ diff --git a/util/amisc/ashow.c b/util/amisc/ashow.c index 5f22827ee..67e785ecc 100644 --- a/util/amisc/ashow.c +++ b/util/amisc/ashow.c @@ -143,6 +143,9 @@ showrelo() case RELOH2: printf("\ttop 2 bytes of a 4 byte word\n"); break; + case RELOVC4: + printf("\tVideoCore IV address in 32-bit instruction\n"); + break; default: printf("\tunknown relocation type %d\n", relrec.or_type & RELSZ); break; diff --git a/util/led/ack.out.5 b/util/led/ack.out.5 index 8e85b3f92..d9e24bff6 100644 --- a/util/led/ack.out.5 +++ b/util/led/ack.out.5 @@ -164,6 +164,7 @@ struct outrelo { #define RELO4 0x03 /* 4 bytes */ #define RELOPPC 0x04 /* 26-bit PowerPC address */ #define RELOH2 0x05 /* write top 2 bytes of 4 byte word */ +#define RELOVC4 0x06 /* VideoCore IV address in 32-bit insruction */ #define RELPC 0x08 /* pc relative */ #define RELBR 0x10 /* High order byte lowest address. */ #define RELWR 0x20 /* High order word lowest address. */ diff --git a/util/led/relocate.c b/util/led/relocate.c index 93b1e9c05..f44a34b96 100644 --- a/util/led/relocate.c +++ b/util/led/relocate.c @@ -8,6 +8,7 @@ static char rcsid[] = "$Id$"; #include #include +#include #include "out.h" #include "const.h" #include "debug.h" @@ -63,6 +64,22 @@ getvalu(addr, type) return read4(addr, type) & 0x03FFFFFD; case RELOH2: return read2(addr, type) << 16; + case RELOVC4: + { + long i = read4(addr, type); + if (i & 0x00800000) + { + /* Branch instruction. */ + return (i<<9)>>9; + } + else + { + /* Branch-link instruction. */ + long hi = (i<<4)>>28; + long lo = (i & 0x007fffff); + return lo | (hi<<23); + } + } default: fatal("bad relocation size"); } @@ -138,6 +155,28 @@ putvalu(valu, addr, type) case RELOH2: write2(valu>>16, addr, type); break; + case RELOVC4: + { + long i = read4(addr, type); + if (i & 0x00800000) + { + /* Branch instruction. */ + unsigned v = (valu/2) & 0x007fffff; + i &= ~0x007fffff; + i |= v; + } + else + { + /* Branch-link instruction. */ + unsigned v = (valu/2) & 0x07ffffff; + unsigned hiv = v >> 23; + unsigned lov = v & 0x007fffff; + i &= ~0x0f7fffff; + i |= (lov>>16) | (hiv<<24); + } + write4(i, addr, type); + break; + } default: fatal("bad relocation size"); }