xref: /inferno-os/libdynld/dynld-power.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth #include "lib9.h"
2*37da2899SCharles.Forsyth #include <a.out.h>
3*37da2899SCharles.Forsyth #include <dynld.h>
4*37da2899SCharles.Forsyth 
5*37da2899SCharles.Forsyth #define	CHK(i,ntab)	if((unsigned)(i)>=(ntab))return "bad relocation index"
6*37da2899SCharles.Forsyth 
7*37da2899SCharles.Forsyth long
dynmagic(void)8*37da2899SCharles.Forsyth dynmagic(void)
9*37da2899SCharles.Forsyth {
10*37da2899SCharles.Forsyth 	return DYN_MAGIC | Q_MAGIC;
11*37da2899SCharles.Forsyth }
12*37da2899SCharles.Forsyth 
13*37da2899SCharles.Forsyth char*
dynreloc(uchar * b,ulong p,int m,Dynsym ** tab,int ntab)14*37da2899SCharles.Forsyth dynreloc(uchar *b, ulong p, int m, Dynsym **tab, int ntab)
15*37da2899SCharles.Forsyth {
16*37da2899SCharles.Forsyth 	int i;
17*37da2899SCharles.Forsyth 	ulong v, *pp0, *pp1;
18*37da2899SCharles.Forsyth 
19*37da2899SCharles.Forsyth 	p <<= 2;
20*37da2899SCharles.Forsyth 	p += (ulong)b;
21*37da2899SCharles.Forsyth 	pp0 = (ulong*)p;
22*37da2899SCharles.Forsyth 	v = *pp0;
23*37da2899SCharles.Forsyth 	switch(m){
24*37da2899SCharles.Forsyth 	case 0:
25*37da2899SCharles.Forsyth 		v += (ulong)b;
26*37da2899SCharles.Forsyth 		break;
27*37da2899SCharles.Forsyth 	case 1:
28*37da2899SCharles.Forsyth 		i = v>>22;
29*37da2899SCharles.Forsyth 		v &= 0x3fffff;
30*37da2899SCharles.Forsyth 		CHK(i, ntab);
31*37da2899SCharles.Forsyth 		v += tab[i]->addr;
32*37da2899SCharles.Forsyth 		break;
33*37da2899SCharles.Forsyth 	case 2:
34*37da2899SCharles.Forsyth 		i = (v&0xffc)>>2;
35*37da2899SCharles.Forsyth 		v &= ~0xffc;
36*37da2899SCharles.Forsyth 		CHK(i, ntab);
37*37da2899SCharles.Forsyth 		v |= (tab[i]->addr-p)&0x3fffffc;
38*37da2899SCharles.Forsyth 		break;
39*37da2899SCharles.Forsyth 	case 3:
40*37da2899SCharles.Forsyth 	case 4:
41*37da2899SCharles.Forsyth 	case 5:
42*37da2899SCharles.Forsyth 	case 6:
43*37da2899SCharles.Forsyth 		pp1 = (ulong*)(p+4);
44*37da2899SCharles.Forsyth 		v = (v<<16)|(*pp1&0xffff);
45*37da2899SCharles.Forsyth 		if(m&1)
46*37da2899SCharles.Forsyth 			v += (ulong)b;
47*37da2899SCharles.Forsyth 		else{
48*37da2899SCharles.Forsyth 			i = v>>22;
49*37da2899SCharles.Forsyth 			v &= 0x3fffff;
50*37da2899SCharles.Forsyth 			CHK(i, ntab);
51*37da2899SCharles.Forsyth 			v += tab[i]->addr;
52*37da2899SCharles.Forsyth 		}
53*37da2899SCharles.Forsyth 		if(m >= 5 && (v&0x8000))
54*37da2899SCharles.Forsyth 			v += 0x10000;
55*37da2899SCharles.Forsyth 		*pp0 &= ~0xffff;
56*37da2899SCharles.Forsyth 		*pp0 |= v>>16;
57*37da2899SCharles.Forsyth 		*pp1 &= ~0xffff;
58*37da2899SCharles.Forsyth 		*pp1 |= v&0xffff;
59*37da2899SCharles.Forsyth 		return nil;
60*37da2899SCharles.Forsyth 	default:
61*37da2899SCharles.Forsyth 		return "invalid relocation mode";
62*37da2899SCharles.Forsyth 	}
63*37da2899SCharles.Forsyth 	*pp0 = v;
64*37da2899SCharles.Forsyth 	return nil;
65*37da2899SCharles.Forsyth }
66