home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 2 / RISC_DISC_2.iso / pd_share / program / language / as / source / c / reloc < prev    next >
Encoding:
Text File  |  1993-05-19  |  14.1 KB  |  450 lines

  1. /*
  2.  * reloc.c
  3.  * Copyright © 1992 Niklas Röjemo
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include "code.h"
  9. #include "lex.h"
  10. #include "symbol.h"
  11. #include "global.h"
  12. #include "error.h"
  13. #include "eval.h"
  14. #include "reloc.h"
  15. #include "area.h"
  16. #include "option.h"
  17. #include "input.h"
  18. #include "AofFile.h"
  19. #include "fix.h"
  20.  
  21. char *reloc2String(RelocTag tag)
  22. {
  23.   switch(tag) {
  24.     case RelocShiftImm:  return "RelocShiftImm";
  25.     case RelocImm8s4:    return "RelocImm8s4";
  26.     case RelocImmFloat:  return "RelocImmFloat";
  27.     case RelocBranch:    return "RelocBranch";
  28.     case RelocSwi:       return "RelocSwi";
  29.     case RelocCpuOffset: return "RelocCpuOffset";
  30.     case RelocCopOffset: return "RelocCopOffset";
  31.     case RelocAdr:       return "RelocAdr";
  32.     case RelocImmN:      return "RelocImmN";
  33.     case RelocFloat:     return "RelocFloat";
  34.     case RelocNone:      return "RelocNone";
  35.   }
  36.   return "reloc2String does not understand";
  37. }
  38.  
  39. static Reloc *relocNew(Reloc *more, RelocTag tag, int offset, Value value)
  40. {
  41.   Reloc *new = malloc(sizeof(Reloc));
  42.   if(new) {
  43.     new->more = more;
  44.     new->Tag = tag;
  45.     new->lineno = inputLineNo;
  46.     new->offset = offset;
  47.     new->value = valueCopy(value);
  48.   } else 
  49.     error(ErrorSerious,FALSE,"Out of memory in relocNew2.");
  50.   return new;
  51. }
  52.  
  53. void relocShiftImm(WORD shiftop, Value shift)
  54. {
  55.   Reloc *new;
  56.   if(areaCurrent) {
  57.     new  = relocNew(areaCurrent->area.info->relocs,RelocShiftImm,
  58.                          areaCurrent->value.ValueInt.i,shift);
  59.     new->extra = shiftop;
  60.     areaCurrent->area.info->relocs = new;
  61.   } else
  62.     error(ErrorError,TRUE,"No area defined.");
  63. }
  64. void relocImm8s4(WORD ir,Value im8s4)
  65. {
  66.   Reloc *new;
  67.   if(areaCurrent) {
  68.     new  = relocNew(areaCurrent->area.info->relocs,RelocImm8s4,
  69.                           areaCurrent->value.ValueInt.i,im8s4);
  70.     new->extra = ir;
  71.     areaCurrent->area.info->relocs = new;
  72.   } else
  73.     error(ErrorError,TRUE,"No area defined.");
  74. }
  75. void relocImmFloat(WORD ir,Value value)
  76. {
  77.   Reloc *new;
  78.   if(areaCurrent) {
  79.     new  = relocNew(areaCurrent->area.info->relocs,RelocImmFloat,
  80.                           areaCurrent->value.ValueInt.i,value);
  81.     new->extra = ir;
  82.     areaCurrent->area.info->relocs = new;
  83.   } else
  84.     error(ErrorError,TRUE,"No area defined.");
  85. }
  86. void relocBranch(Value offset)
  87. {
  88.   Reloc *new;
  89.   if(areaCurrent) {
  90.     new  = relocNew(areaCurrent->area.info->relocs,RelocBranch,
  91.                          areaCurrent->value.ValueInt.i,offset);
  92.     areaCurrent->area.info->relocs = new;
  93.   } else
  94.     error(ErrorError,TRUE,"No area defined.");
  95. }
  96. void relocSwi(Value code)
  97. {
  98.   Reloc *new;
  99.   if(areaCurrent) {
  100.     new  = relocNew(areaCurrent->area.info->relocs,RelocSwi,
  101.                          areaCurrent->value.ValueInt.i,code);
  102.     areaCurrent->area.info->relocs = new;
  103.   } else
  104.     error(ErrorError,TRUE,"No area defined.");
  105. }
  106. void relocCpuOffset(WORD ir,Value offset)
  107. {
  108.   Reloc *new;
  109.   if(areaCurrent) {
  110.     new  = relocNew(areaCurrent->area.info->relocs,RelocCpuOffset,
  111.                          areaCurrent->value.ValueInt.i,offset);
  112.     new->extra = ir;
  113.     areaCurrent->area.info->relocs = new;
  114.   } else
  115.     error(ErrorError,TRUE,"No area defined.");
  116. }
  117. void relocCopOffset(WORD ir,Value offset)
  118. {
  119.   Reloc *new;
  120.   if(areaCurrent) {
  121.     new  = relocNew(areaCurrent->area.info->relocs,RelocCopOffset,
  122.                          areaCurrent->value.ValueInt.i,offset);
  123.     new->extra = ir;
  124.     areaCurrent->area.info->relocs = new;
  125.   } else
  126.     error(ErrorError,TRUE,"No area defined.");
  127. }
  128. void relocAdr(WORD ir,Value addr)
  129. {
  130.   Reloc *new;
  131.   if(areaCurrent) {
  132.     new  = relocNew(areaCurrent->area.info->relocs,RelocAdr,
  133.                          areaCurrent->value.ValueInt.i,addr);
  134.     new->extra = ir;
  135.     areaCurrent->area.info->relocs = new;
  136.   } else
  137.     error(ErrorError,TRUE,"No area defined.");
  138. }
  139. void relocMask(Value mask)
  140. {
  141.   Reloc *new;
  142.   if(areaCurrent) {
  143.     new  = relocNew(areaCurrent->area.info->relocs,RelocImmN,
  144.                          areaCurrent->value.ValueInt.i,mask);
  145.     new->extra = 2;
  146.     areaCurrent->area.info->relocs = new;
  147.   } else
  148.     error(ErrorError,TRUE,"No area defined.");
  149. }
  150. void relocInt(int size, Value value)
  151. {
  152.   Reloc *new;
  153.   if(areaCurrent) {
  154.     new  = relocNew(areaCurrent->area.info->relocs,RelocImmN,
  155.                          areaCurrent->value.ValueInt.i,value);
  156.     new->extra = size;
  157.     areaCurrent->area.info->relocs = new;
  158.   } else
  159.     error(ErrorError,TRUE,"No area defined.");
  160. }
  161.  
  162. void relocFloat(int size, Value value)
  163. {
  164.   Reloc *new;
  165.   if(areaCurrent) {
  166.     new  = relocNew(areaCurrent->area.info->relocs,RelocFloat,
  167.                          areaCurrent->value.ValueInt.i,value);
  168.     new->extra = size;
  169.     areaCurrent->area.info->relocs = new;
  170.   } else
  171.     error(ErrorError,TRUE,"No area defined.");
  172. }
  173.  
  174. void relocAdd(Reloc *new)
  175. {
  176.   if(areaCurrent) {
  177.     new->more = areaCurrent->area.info->relocs;
  178.     areaCurrent->area.info->relocs = new;
  179.   } else
  180.     error(ErrorError,TRUE,"No area defined.");
  181. }
  182.  
  183. int relocLate2Reloc(Reloc *r, Value *value)
  184. {
  185.   int size = 0;
  186.   int norelocs = 0;
  187.   LateInfo *late;
  188.  
  189.   for(late = value->ValueLate.late; late; late = late->next) {
  190.     if(late->factor) {
  191.       norelocs += late->factor;  /* late->factor can not be less that 0 here */
  192.       if(late->factor>1) {
  193.         r->value.ValueCode.c[size  ].Tag = CodeValue;
  194.         r->value.ValueCode.c[size  ].CodeValue.value.Tag = ValueInt;
  195.         r->value.ValueCode.c[size++].CodeValue.value.ValueInt.i = late->factor;
  196.       }
  197.       r->value.ValueCode.c[size  ].Tag = CodeSymbol;
  198.       r->value.ValueCode.c[size++].CodeSymbol.symbol = late->symbol;
  199.     }
  200.   }
  201.   if(size>r->value.ValueCode.len)
  202.     errorLine(r->lineno,ErrorSerious,FALSE,"Overflow in relocation data.");
  203.   r->value.ValueCode.len = size;
  204.   return norelocs;
  205. }
  206.  
  207. int relocEval(Reloc *r, Value *value, Symbol *area)
  208. {
  209.   int norelocs = 0;
  210.   int this = 0;
  211.   LateInfo *late;
  212.  
  213.   codeInit();
  214.   *value = codeEvalLow(ValueAll,r->value.ValueCode.len,r->value.ValueCode.c);
  215.   switch(value->Tag) {
  216.     case ValueIllegal:
  217.       errorLine(r->lineno,ErrorError,TRUE,"Can not evaluate expression (illegal).");
  218.       r->Tag = RelocNone;
  219.       return 0;
  220.     case ValueCode:
  221.       errorLine(r->lineno,ErrorError,TRUE,"Can not evaluate expression (code).");
  222.       r->Tag = RelocNone;
  223.       return 0;
  224.     case ValueLateLabel:
  225.       switch(r->Tag) {
  226.         case RelocBranch:
  227.           this = 0;
  228.           for(late = value->ValueLate.late; late; late = late->next)
  229.             if(late->symbol == area) {
  230.               this = late->factor;
  231.               late->factor = 0;
  232.               break;
  233.             }
  234.           for(late = value->ValueLate.late; late; late = late->next)
  235.             if(late->factor > 0) {
  236.               if(late->symbol->type != SYMBOL_AREA)
  237.                 late->symbol->used ++;
  238.               this += late->factor;
  239.             } else if(late->factor < 0) {
  240.               errorLine(r->lineno,ErrorError,TRUE,"Only positive relocation allowed.");
  241.               late->factor = 1;
  242.             }
  243.           if(this)
  244.             errorLine(r->lineno,ErrorError,TRUE,"Unbalanced relocation (%d).",this);
  245.           break;
  246.         case RelocImmN:
  247.           for(late = value->ValueLate.late; late; late = late->next) {
  248.             if(late->factor > 0) {
  249.               if(late->symbol->type != SYMBOL_AREA) {
  250.                 late->symbol->used ++;
  251.               } else if(r->extra != 4) {
  252.                 errorLine(r->lineno,ErrorError,TRUE,
  253.                       "8/16 bits field can not be allocated with area (%s).",
  254.                       late->symbol->str);
  255.               }
  256.             } else
  257.               if(late->factor < 0) {
  258.                 errorLine(r->lineno,ErrorError,TRUE,"Only positive relocation allowed.");
  259.                 late->factor = 1;
  260.               }
  261.           }
  262.           break;
  263.         case ValueInt:
  264.           break;
  265.         default:
  266.           errorLine(r->lineno,ErrorError,TRUE,"Linker can not handle %s.",reloc2String(r->Tag));
  267.           r->Tag = RelocNone;
  268.           return 0;
  269.       }   /* ValueLateLabel */
  270.       norelocs = relocLate2Reloc(r,value);
  271.       break;
  272.     case ValueInt:
  273.       break;
  274.     default:
  275.       errorLine(r->lineno,ErrorSerious,FALSE,"Illegal ValueTag in relocEval.");
  276.   }
  277.   return norelocs;
  278. }
  279.  
  280.  
  281.  
  282. void relocWrite(Reloc *r, Value *value, char *image)
  283. {
  284.   int offset = r->offset;
  285.   WORD w;
  286.  
  287.   switch(value->Tag) {
  288.     case ValueLateLabel:
  289.     case ValueInt:
  290.       switch(r->Tag) {       /* Write out the value */
  291.         case RelocBranch:
  292.           w = fixBranch(r->lineno,value->ValueInt.i);
  293.           image[offset+2] = (w>>16) & 0xff;
  294.           image[offset+1] = (w>> 8) & 0xff;
  295.           image[offset+0] =  w      & 0xff;
  296.           break;
  297.         case RelocCpuOffset:
  298.           w = (image[offset+3]<<24)|(image[offset+2]<<16)|(image[offset+1]<<8)|image[offset+0];
  299.           w = fixCpuOffset(r->lineno,w,value->ValueInt.i);
  300.           image[offset+3] = (w>>24) & 0xff;
  301.           image[offset+2] = (w>>16) & 0xff;
  302.           image[offset+1] = (w>> 8) & 0xff;
  303.           image[offset+0] =  w      & 0xff;
  304.           break;
  305.         case RelocCopOffset:
  306.           w = (image[offset+3]<<24)|(image[offset+2]<<16)|(image[offset+1]<<8)|image[offset+0];
  307.           w = fixCopOffset(r->lineno,w,value->ValueInt.i);
  308.           image[offset+3] = (w>>24) & 0xff;
  309.           image[offset+2] = (w>>16) & 0xff;
  310.           image[offset+1] = (w>> 8) & 0xff;
  311.           image[offset+0] =  w      & 0xff;
  312.           break;
  313.         case RelocImmN:
  314.           w = fixInt(r->lineno,r->extra,value->ValueInt.i);
  315.           switch(r->extra) {
  316.             case 4: image[offset+3] = (w>>24) & 0xff;
  317.                     image[offset+2] = (w>>16) & 0xff;
  318.             case 2: image[offset+1] = (w>> 8) & 0xff;
  319.             case 1: image[offset+0] =  w      & 0xff;
  320.           }
  321.           break;
  322.         case RelocAdr:
  323.           w = (image[offset+3]<<24)|(image[offset+2]<<16)|(image[offset+1]<<8)|image[offset+0];
  324.           w = fixAdr(r->lineno,w,value->ValueInt.i);
  325.           image[offset+3] = (w>>24) & 0xff;
  326.           image[offset+2] = (w>>16) & 0xff;
  327.           image[offset+1] = (w>> 8) & 0xff;
  328.           image[offset+0] =  w      & 0xff;
  329.           break;
  330.         case RelocImm8s4:
  331.           w = (image[offset+3]<<24)|(image[offset+2]<<16)|(image[offset+1]<<8)|image[offset+0];
  332.           w = fixImm8s4(r->lineno,w,value->ValueInt.i);
  333.           image[offset+3] = (w>>24) & 0xff;
  334.           image[offset+2] = (w>>16) & 0xff;
  335.           image[offset+1] = (w>> 8) & 0xff;
  336.           image[offset+0] =  w      & 0xff;
  337.           break;
  338.         default:
  339.           errorLine(r->lineno,ErrorError,TRUE,"Can not handle %s when value is int.",reloc2String(r->Tag));
  340.           r->Tag = RelocNone;
  341.           return;
  342.       }
  343.       if(value->Tag == ValueInt || r->value.ValueCode.len == 0) /* Value is known */
  344.         r->Tag = RelocNone;
  345.       break;
  346.  
  347.     case ValueFloat:
  348.       switch(r->Tag) {       /* Write out the value */
  349.         case RelocFloat: {
  350.           int i;
  351.           union { double d;
  352.                   float f;
  353.                   struct { char c[8]; } u;
  354.                 } translate;
  355.           if(r->extra==4)
  356.             translate.f = (float)value->ValueFloat.f;
  357.           else
  358.             translate.d = (double)value->ValueFloat.f;
  359.           for(i=0; i<r->extra; i++)
  360.             image[offset+i] = translate.u.c[i];
  361.           } break;
  362.         case RelocImmFloat:
  363.           w = (image[offset+3]<<24)|(image[offset+2]<<16)|(image[offset+1]<<8)|image[offset+0];
  364.           w = fixImmFloat(r->lineno,w,value->ValueFloat.f);
  365.           image[offset+3] = (w>>24) & 0xff;
  366.           image[offset+2] = (w>>16) & 0xff;
  367.           image[offset+1] = (w>> 8) & 0xff;
  368.           image[offset+0] =  w      & 0xff;
  369.           break;
  370.         default:
  371.           errorLine(r->lineno,ErrorError,TRUE,"Can not handle %s when value is float.",reloc2String(r->Tag));
  372.       }
  373.       r->Tag = RelocNone;
  374.       break;
  375.     default:
  376.       errorLine(r->lineno,ErrorError,TRUE,"Illegal value in relocWrite.");
  377.       r->Tag = RelocNone;
  378.   } /* value->Tag */
  379. }
  380.  
  381. int relocFix(Symbol *area)
  382. {
  383.   char *image = area->area.info->image;
  384.   Reloc *relocs = area->area.info->relocs;
  385.   int norelocs = 0;
  386.   Value value;
  387.  
  388.   while(relocs) {
  389.     switch(relocs->value.Tag) {
  390.       case ValueInt:
  391.         value = relocs->value;
  392.         break;
  393.       case ValueCode:
  394.         norelocs += relocEval(relocs,&value,area);
  395.         break;
  396.       default:
  397.         errorLine(relocs->lineno,ErrorSerious,TRUE,"Not a legal value in relocFix.");
  398.         relocs->Tag = RelocNone;
  399.     } 
  400.     if(relocs->Tag != RelocNone) /* We now have a Value */ 
  401.       relocWrite(relocs,&value,image);
  402.     relocs = relocs->more;
  403.   }
  404.   return norelocs; 
  405. }
  406.  
  407. void relocOutput(FILE *outfile,Symbol *area)
  408. {
  409.   Reloc *relocs;
  410.   AofReloc areloc;
  411.   int How,loop,ip;
  412.   for(relocs = area->area.info->relocs; relocs; relocs = relocs->more) {
  413.     switch(relocs->Tag) {
  414.       case RelocBranch:
  415.         How = HOW2_INIT | HOW2_RELATIVE | HOW2_WORD;
  416.         break; 
  417.       case RelocImmN:
  418.         switch(relocs->extra) {
  419.           case 4: How = HOW2_INIT | HOW2_WORD; break;
  420.           case 2: How = HOW2_INIT | HOW2_HALF; break;
  421.           case 1: How = HOW2_INIT | HOW2_BYTE; break;
  422.           default: errorLine(relocs->lineno,ErrorSerious,TRUE,"Linker can not handle RelocImmN with size %d.",relocs->extra);
  423.                    continue;
  424.         }
  425.         break; 
  426.       case RelocNone:
  427.         continue;
  428.       default: errorLine(relocs->lineno,ErrorSerious,TRUE,"Linker can not handle this.");
  429.                continue;
  430.     }
  431.     areloc.Offset = relocs->offset;
  432.     for(ip = 0; ip < relocs->value.ValueCode.len; ip++) {
  433.       if(relocs->value.ValueCode.c[ip].Tag == CodeValue) {
  434.         if(relocs->value.ValueCode.c[ip].CodeValue.value.Tag != ValueInt)
  435.           errorLine(relocs->lineno,ErrorSerious,TRUE,"Internal error in relocsOutput (Not an int).");
  436.         else
  437.           loop = relocs->value.ValueCode.c[ip++].CodeValue.value.ValueInt.i;
  438.       } else
  439.         loop = 1;
  440.       if(relocs->value.ValueCode.c[ip].Tag != CodeSymbol)
  441.         errorLine(relocs->lineno,ErrorSerious,TRUE,"Internal error in relocsOutput.");
  442.       areloc.How = How | relocs->value.ValueCode.c[ip].CodeSymbol.symbol->used;
  443.       if(relocs->value.ValueCode.c[ip].CodeSymbol.symbol->type != SYMBOL_AREA)
  444.         areloc.How |= HOW2_SYMBOL;
  445.       while(loop--)
  446.         fwrite((void *)&areloc,1,8,outfile);
  447.     }
  448.   }
  449. }
  450.