home *** CD-ROM | disk | FTP | other *** search
/ APDL Public Domain 1 / APDL_PD1A.iso / program / assembler / as / src / c / relocO < prev    next >
Encoding:
Text File  |  1993-03-06  |  14.1 KB  |  402 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. /* Fixed up to this */
  174. int relocFix(Symbol *area)
  175. {
  176.   char *image = area->area.info->image;
  177.   Reloc *relocs = area->area.info->relocs;
  178.   int offset,size;
  179.   WORD w;
  180.   Value value;
  181.   int norelocs = 0;
  182.   LateInfo *late;
  183.   int this;
  184.  
  185.   while(relocs) { 
  186.     if(relocs->value.Tag != ValueCode) {
  187.       errorLine(relocs->lineno,ErrorSerious,TRUE,"Not a code value in relocFix.");
  188.       goto ForgetThisReloc;
  189.     } else {
  190.       codeInit();
  191.       value = codeEvalLow(ValueAll,relocs->value.ValueCode.len,relocs->value.ValueCode.c);
  192.       switch(value.Tag) {
  193.         case ValueIllegal:
  194.           errorLine(relocs->lineno,ErrorError,TRUE,"Can not evaluate expression (illegal).");
  195.           goto ForgetThisReloc;
  196.         case ValueCode:
  197.           errorLine(relocs->lineno,ErrorError,TRUE,"Can not evaluate expression (code).");
  198.           goto ForgetThisReloc;
  199.         case ValueLateLabel:
  200.           switch(relocs->Tag) {
  201.             case RelocBranch:
  202.               this = 0;
  203.               for(late = value.ValueLate.late; late; late = late->next)
  204.                 if(late->symbol == area) {
  205.                   this = late->factor;
  206.                   late->factor = 0;
  207.                   break;
  208.                 }
  209.               for(late = value.ValueLate.late; late; late = late->next)
  210.                 if(late->factor > 0) {
  211.                   if(late->symbol->type != SYMBOL_AREA)
  212.                     late->symbol->used ++;
  213.                   this += late->factor;
  214.                 } else if(late->factor < 0) {
  215.                   errorLine(relocs->lineno,ErrorError,TRUE,"Only positive relocation allowed.");
  216.                   late->factor = 1;
  217.                 }
  218.               if(this)
  219.                 errorLine(relocs->lineno,ErrorError,TRUE,"Unbalanced relocation (%d).",this);
  220.               break;
  221.             case RelocImmN:
  222.               for(late = value.ValueLate.late; late; late = late->next) {
  223.                 if(late->factor > 0) {
  224.                   if(late->symbol->type != SYMBOL_AREA) {
  225.                     late->symbol->used ++;
  226.                   } else if(relocs->extra != 4) {
  227.                     errorLine(relocs->lineno,ErrorError,TRUE,
  228.                           "8/16 bits field can not be allocated with area (%s).",
  229.                           late->symbol->str);
  230.                   }
  231.                 } else
  232.                   if(late->factor < 0) {
  233.                     errorLine(relocs->lineno,ErrorError,TRUE,"Only positive relocation allowed.");
  234.                     late->factor = 1;
  235.                   }
  236.               }
  237.               break;
  238.             case ValueInt:
  239.               break;
  240.             default:
  241.               errorLine(relocs->lineno,ErrorError,TRUE,"Linker can not handle %s.",reloc2String(relocs->Tag));
  242.               goto ForgetThisReloc;
  243.           }
  244.           size = 0;
  245.           for(late = value.ValueLate.late; late; late = late->next) {
  246.             if(late->factor) {
  247.               norelocs += late->factor;  /* late->factor can not be less that 0 here */
  248.               if(late->factor>1) {
  249.                 relocs->value.ValueCode.c[size  ].Tag = CodeValue;
  250.                 relocs->value.ValueCode.c[size  ].CodeValue.value.Tag = ValueInt;
  251.                 relocs->value.ValueCode.c[size++].CodeValue.value.ValueInt.i = late->factor;
  252.               }
  253.               relocs->value.ValueCode.c[size  ].Tag = CodeSymbol;
  254.               relocs->value.ValueCode.c[size++].CodeSymbol.symbol = late->symbol;
  255.             }
  256.           }
  257.           if(size>relocs->value.ValueCode.len)
  258.             errorLine(relocs->lineno,ErrorSerious,FALSE,"Overflow in relocation data.");
  259.           relocs->value.ValueCode.len = size;
  260.         case ValueInt:
  261.     /************** Start writing the value *****************/
  262.           offset = relocs->offset;
  263.           switch(relocs->Tag) {       /* Write out the value */
  264.             case RelocBranch:
  265.               w = fixBranch(relocs->lineno,value.ValueInt.i);
  266.               image[offset+2] = (w>>16) & 0xff;
  267.               image[offset+1] = (w>> 8) & 0xff;
  268.               image[offset+0] =  w      & 0xff;
  269.               break;
  270.             case RelocCpuOffset:
  271.               w = (image[offset+3]<<24)|(image[offset+2]<<16)|(image[offset+1]<<8)|image[offset+0];
  272.               w = fixCpuOffset(relocs->lineno,w,value.ValueInt.i);
  273.               image[offset+3] = (w>>24) & 0xff;
  274.               image[offset+2] = (w>>16) & 0xff;
  275.               image[offset+1] = (w>> 8) & 0xff;
  276.               image[offset+0] =  w      & 0xff;
  277.               break;
  278.             case RelocCopOffset:
  279.               w = (image[offset+3]<<24)|(image[offset+2]<<16)|(image[offset+1]<<8)|image[offset+0];
  280.               w = fixCopOffset(relocs->lineno,w,value.ValueInt.i);
  281.               image[offset+3] = (w>>24) & 0xff;
  282.               image[offset+2] = (w>>16) & 0xff;
  283.               image[offset+1] = (w>> 8) & 0xff;
  284.               image[offset+0] =  w      & 0xff;
  285.               break;
  286.             case RelocImmN:
  287.               w = fixInt(relocs->lineno,relocs->extra,value.ValueInt.i);
  288.               switch(relocs->extra) {
  289.                 case 4: image[offset+3] = (w>>24) & 0xff;
  290.                         image[offset+2] = (w>>16) & 0xff;
  291.                 case 2: image[offset+1] = (w>> 8) & 0xff;
  292.                 case 1: image[offset+0] =  w      & 0xff;
  293.               }
  294.               break;
  295.             case RelocAdr:
  296.               w = (image[offset+3]<<24)|(image[offset+2]<<16)|(image[offset+1]<<8)|image[offset+0];
  297.               w = fixAdr(relocs->lineno,w,value.ValueInt.i);
  298.               image[offset+3] = (w>>24) & 0xff;
  299.               image[offset+2] = (w>>16) & 0xff;
  300.               image[offset+1] = (w>> 8) & 0xff;
  301.               image[offset+0] =  w      & 0xff;
  302.               break;
  303.             case RelocImm8s4:
  304.               w = (image[offset+3]<<24)|(image[offset+2]<<16)|(image[offset+1]<<8)|image[offset+0];
  305.               w = fixImm8s4(relocs->lineno,w,value.ValueInt.i);
  306.               image[offset+3] = (w>>24) & 0xff;
  307.               image[offset+2] = (w>>16) & 0xff;
  308.               image[offset+1] = (w>> 8) & 0xff;
  309.               image[offset+0] =  w      & 0xff;
  310.               break;
  311.             default:
  312.               errorLine(relocs->lineno,ErrorError,TRUE,"Can not handle %s when value is int.",reloc2String(relocs->Tag));
  313.               goto ForgetThisReloc;
  314.           }
  315.           if(value.Tag == ValueInt || relocs->value.ValueCode.len == 0) /* Value is known */
  316.             relocs->Tag = RelocNone;
  317.           break;
  318.         case ValueFloat:
  319.           offset = relocs->offset;
  320.           switch(relocs->Tag) {       /* Write out the value */
  321.             case RelocFloat: {
  322.               int i;
  323.               union { double d;
  324.                       float f;
  325.                       struct { char c[8]; } u;
  326.                     } translate;
  327.               if(relocs->extra==4)
  328.                 translate.f = (float)value.ValueFloat.f;
  329.               else
  330.                 translate.d = (double)value.ValueFloat.f;
  331.               for(i=0; i<relocs->extra; i++)
  332.                 image[offset+i] = translate.u.c[i];
  333.               } break;
  334.             case RelocImmFloat:
  335.               w = (image[offset+3]<<24)|(image[offset+2]<<16)|(image[offset+1]<<8)|image[offset+0];
  336.               w = fixImmFloat(relocs->lineno,w,value.ValueFloat.f);
  337.               image[offset+3] = (w>>24) & 0xff;
  338.               image[offset+2] = (w>>16) & 0xff;
  339.               image[offset+1] = (w>> 8) & 0xff;
  340.               image[offset+0] =  w      & 0xff;
  341.               break;
  342.             default:
  343.               errorLine(relocs->lineno,ErrorError,TRUE,"Can not handle %s when value is float.",reloc2String(relocs->Tag));
  344.               goto ForgetThisReloc;
  345.           }
  346.           relocs->Tag = RelocNone;
  347.           break;
  348.         default:
  349.           errorLine(relocs->lineno,ErrorError,TRUE,"Can not handle %s.",reloc2String(relocs->Tag));
  350. ForgetThisReloc:
  351.           relocs->Tag = RelocNone;
  352.       }
  353.     }
  354.     relocs = relocs->more;
  355.   }
  356.   return norelocs; 
  357. }
  358.  
  359. void relocOutput(FILE *outfile,Symbol *area)
  360. {
  361.   Reloc *relocs;
  362.   AofReloc areloc;
  363.   int How,loop,ip;
  364.   for(relocs = area->area.info->relocs; relocs; relocs = relocs->more) {
  365.     switch(relocs->Tag) {
  366.       case RelocBranch:
  367.         How = HOW2_INIT | HOW2_RELATIVE | HOW2_WORD;
  368.         break; 
  369.       case RelocImmN:
  370.         switch(relocs->extra) {
  371.           case 4: How = HOW2_INIT | HOW2_WORD; break;
  372.           case 2: How = HOW2_INIT | HOW2_HALF; break;
  373.           case 1: How = HOW2_INIT | HOW2_BYTE; break;
  374.           default: errorLine(relocs->lineno,ErrorSerious,TRUE,"Linker can not handle RelocImmN with size %d.",relocs->extra);
  375.                    continue;
  376.         }
  377.         break; 
  378.       case RelocNone:
  379.         continue;
  380.       default: errorLine(relocs->lineno,ErrorSerious,TRUE,"Linker can not handle this.");
  381.                continue;
  382.     }
  383.     areloc.Offset = relocs->offset;
  384.     for(ip = 0; ip < relocs->value.ValueCode.len; ip++) {
  385.       if(relocs->value.ValueCode.c[ip].Tag == CodeValue) {
  386.         if(relocs->value.ValueCode.c[ip].CodeValue.value.Tag != ValueInt)
  387.           errorLine(relocs->lineno,ErrorSerious,TRUE,"Internal error in relocsOutput (Not an int).");
  388.         else
  389.           loop = relocs->value.ValueCode.c[ip++].CodeValue.value.ValueInt.i;
  390.       } else
  391.         loop = 1;
  392.       if(relocs->value.ValueCode.c[ip].Tag != CodeSymbol)
  393.         errorLine(relocs->lineno,ErrorSerious,TRUE,"Internal error in relocsOutput.");
  394.       areloc.How = How | relocs->value.ValueCode.c[ip].CodeSymbol.symbol->used;
  395.       if(relocs->value.ValueCode.c[ip].CodeSymbol.symbol->type != SYMBOL_AREA)
  396.         areloc.How |= HOW2_SYMBOL;
  397.       while(loop--)
  398.         fwrite((void *)&areloc,1,8,outfile);
  399.     }
  400.   }
  401. }
  402.