On Fri, Jul 31, 2009 at 7:38 PM, Kyle McMartin<kyle@xxxxxxxxxxx> wrote: > Is it as simple as: > > diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c > index ef5caf2..0502fab 100644 > --- a/arch/parisc/kernel/module.c > +++ b/arch/parisc/kernel/module.c > @@ -82,13 +82,6 @@ > return -ENOEXEC; \ > } > > -/* Maximum number of GOT entries. We use a long displacement ldd from > - * the bottom of the table, which has a maximum signed displacement of > - * 0x3fff; however, since we're only going forward, this becomes > - * 0x1fff, and thus, since each GOT entry is 8 bytes long we can have > - * at most 1023 entries */ > -#define MAX_GOTS 1023 > - > /* three functions to determine where in the module core > * or init pieces the location is */ > static inline int in_init(struct module *me, void *loc) > @@ -126,6 +119,14 @@ struct stub_entry { > }; > #endif > > +/* Maximum number of GOT entries. We use a long displacement ldd from > + * the bottom of the table, which has 16-bit signed displacement from > + * %dp. Because we only use the forward direction, we're limited to > + * 15-bits - 1, and because each GOT entry is 8-bytes wide, we're limited > + * to 4095 entries. > + */ > +#define MAX_GOTS (((1 << 15) - 1) / sizeof(struct got_entry)) > + OK > /* Field selection types defined by hppa */ > #define rnd(x) (((x)+0x1000)&~0x1fff) > /* fsel: full 32 bits */ > @@ -151,6 +152,15 @@ static inline int reassemble_14(int as14) > ((as14 & 0x2000) >> 13)); > } > > +/* Unusual 16-bit encoding, for wide mode only. */ > +static inline int reassemble_16a(int as16) > +{ > + int s, t; > + t = (as16 << 1) & 0xffff; > + s = (as16 & 0x8000); > + return (t ^ s ^ (s >> 1)) | (s >> 15); > +} > + OK > static inline int reassemble_17(int as17) > { > return (((as17 & 0x10000) >> 16) | > @@ -460,12 +470,16 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, > */ > switch (stub_type) { > case ELF_STUB_GOT: > + unsigned int d = get_got(me, value, addend) & 0x7fff; > + > stub->insns[0] = 0x537b0000; /* ldd 0(%dp),%dp */ > stub->insns[1] = 0x53610020; /* ldd 10(%dp),%r1 */ > stub->insns[2] = 0xe820d000; /* bve (%r1) */ > stub->insns[3] = 0x537b0030; /* ldd 18(%dp),%dp */ > > - stub->insns[0] |= reassemble_14(get_got(me, value, addend) & 0x3fff); > + if (d > 15) > + stub->insns[0] |= reassemble_16a(d); > + You need to rewrite stub->insn[0[, the long format 3 ldd is a different opcode, see the PA 2.0 manual, it will no longer be 0x537b0000. You also still need a <= 15 byte case which uses the old short format 5 ldd with a 14-bit immediate. > break; > case ELF_STUB_MILLI: > stub->insns[0] = 0x20200000; /* ldil 0,%r1 */ > > I don't think we need to worry about the initial 15-bytes displacement, > since they're all within the first got_entry? (The resulting assembly > looks alright from a 64-bit toolchain: No, we still have to worry about the initial 15-bytes. Within the first 15-bytes you have one GOT entry (%dp + 0) and thus you need to add the case for the short format 3 ldd. Thanks for hacking this up! Cheers, Carlos. -- To unsubscribe from this list: send the line "unsubscribe linux-parisc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html