dynld-power.c 983 B

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