home *** CD-ROM | disk | FTP | other *** search
- /*
- * reloc.c
- * Copyright © 1992 Niklas Röjemo
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include "code.h"
- #include "lex.h"
- #include "symbol.h"
- #include "global.h"
- #include "error.h"
- #include "eval.h"
- #include "reloc.h"
- #include "area.h"
- #include "option.h"
- #include "input.h"
- #include "AofFile.h"
- #include "fix.h"
-
- char *reloc2String(RelocTag tag)
- {
- switch(tag) {
- case RelocShiftImm: return "RelocShiftImm";
- case RelocImm8s4: return "RelocImm8s4";
- case RelocImmFloat: return "RelocImmFloat";
- case RelocBranch: return "RelocBranch";
- case RelocSwi: return "RelocSwi";
- case RelocCpuOffset: return "RelocCpuOffset";
- case RelocCopOffset: return "RelocCopOffset";
- case RelocAdr: return "RelocAdr";
- case RelocImmN: return "RelocImmN";
- case RelocFloat: return "RelocFloat";
- case RelocNone: return "RelocNone";
- }
- return "reloc2String does not understand";
- }
-
- static Reloc *relocNew(Reloc *more, RelocTag tag, int offset, Value value)
- {
- Reloc *new = malloc(sizeof(Reloc));
- if(new) {
- new->more = more;
- new->Tag = tag;
- new->lineno = inputLineNo;
- new->offset = offset;
- new->value = valueCopy(value);
- } else
- error(ErrorSerious,FALSE,"Out of memory in relocNew2.");
- return new;
- }
-
- void relocShiftImm(WORD shiftop, Value shift)
- {
- Reloc *new;
- if(areaCurrent) {
- new = relocNew(areaCurrent->area.info->relocs,RelocShiftImm,
- areaCurrent->value.ValueInt.i,shift);
- new->extra = shiftop;
- areaCurrent->area.info->relocs = new;
- } else
- error(ErrorError,TRUE,"No area defined.");
- }
- void relocImm8s4(WORD ir,Value im8s4)
- {
- Reloc *new;
- if(areaCurrent) {
- new = relocNew(areaCurrent->area.info->relocs,RelocImm8s4,
- areaCurrent->value.ValueInt.i,im8s4);
- new->extra = ir;
- areaCurrent->area.info->relocs = new;
- } else
- error(ErrorError,TRUE,"No area defined.");
- }
- void relocImmFloat(WORD ir,Value value)
- {
- Reloc *new;
- if(areaCurrent) {
- new = relocNew(areaCurrent->area.info->relocs,RelocImmFloat,
- areaCurrent->value.ValueInt.i,value);
- new->extra = ir;
- areaCurrent->area.info->relocs = new;
- } else
- error(ErrorError,TRUE,"No area defined.");
- }
- void relocBranch(Value offset)
- {
- Reloc *new;
- if(areaCurrent) {
- new = relocNew(areaCurrent->area.info->relocs,RelocBranch,
- areaCurrent->value.ValueInt.i,offset);
- areaCurrent->area.info->relocs = new;
- } else
- error(ErrorError,TRUE,"No area defined.");
- }
- void relocSwi(Value code)
- {
- Reloc *new;
- if(areaCurrent) {
- new = relocNew(areaCurrent->area.info->relocs,RelocSwi,
- areaCurrent->value.ValueInt.i,code);
- areaCurrent->area.info->relocs = new;
- } else
- error(ErrorError,TRUE,"No area defined.");
- }
- void relocCpuOffset(WORD ir,Value offset)
- {
- Reloc *new;
- if(areaCurrent) {
- new = relocNew(areaCurrent->area.info->relocs,RelocCpuOffset,
- areaCurrent->value.ValueInt.i,offset);
- new->extra = ir;
- areaCurrent->area.info->relocs = new;
- } else
- error(ErrorError,TRUE,"No area defined.");
- }
- void relocCopOffset(WORD ir,Value offset)
- {
- Reloc *new;
- if(areaCurrent) {
- new = relocNew(areaCurrent->area.info->relocs,RelocCopOffset,
- areaCurrent->value.ValueInt.i,offset);
- new->extra = ir;
- areaCurrent->area.info->relocs = new;
- } else
- error(ErrorError,TRUE,"No area defined.");
- }
- void relocAdr(WORD ir,Value addr)
- {
- Reloc *new;
- if(areaCurrent) {
- new = relocNew(areaCurrent->area.info->relocs,RelocAdr,
- areaCurrent->value.ValueInt.i,addr);
- new->extra = ir;
- areaCurrent->area.info->relocs = new;
- } else
- error(ErrorError,TRUE,"No area defined.");
- }
- void relocMask(Value mask)
- {
- Reloc *new;
- if(areaCurrent) {
- new = relocNew(areaCurrent->area.info->relocs,RelocImmN,
- areaCurrent->value.ValueInt.i,mask);
- new->extra = 2;
- areaCurrent->area.info->relocs = new;
- } else
- error(ErrorError,TRUE,"No area defined.");
- }
- void relocInt(int size, Value value)
- {
- Reloc *new;
- if(areaCurrent) {
- new = relocNew(areaCurrent->area.info->relocs,RelocImmN,
- areaCurrent->value.ValueInt.i,value);
- new->extra = size;
- areaCurrent->area.info->relocs = new;
- } else
- error(ErrorError,TRUE,"No area defined.");
- }
-
- void relocFloat(int size, Value value)
- {
- Reloc *new;
- if(areaCurrent) {
- new = relocNew(areaCurrent->area.info->relocs,RelocFloat,
- areaCurrent->value.ValueInt.i,value);
- new->extra = size;
- areaCurrent->area.info->relocs = new;
- } else
- error(ErrorError,TRUE,"No area defined.");
- }
-
- void relocAdd(Reloc *new)
- {
- if(areaCurrent) {
- new->more = areaCurrent->area.info->relocs;
- areaCurrent->area.info->relocs = new;
- } else
- error(ErrorError,TRUE,"No area defined.");
- }
-
- int relocLate2Reloc(Reloc *r, Value *value)
- {
- int size = 0;
- int norelocs = 0;
- LateInfo *late;
-
- for(late = value->ValueLate.late; late; late = late->next) {
- if(late->factor) {
- norelocs += late->factor; /* late->factor can not be less that 0 here */
- if(late->factor>1) {
- r->value.ValueCode.c[size ].Tag = CodeValue;
- r->value.ValueCode.c[size ].CodeValue.value.Tag = ValueInt;
- r->value.ValueCode.c[size++].CodeValue.value.ValueInt.i = late->factor;
- }
- r->value.ValueCode.c[size ].Tag = CodeSymbol;
- r->value.ValueCode.c[size++].CodeSymbol.symbol = late->symbol;
- }
- }
- if(size>r->value.ValueCode.len)
- errorLine(r->lineno,ErrorSerious,FALSE,"Overflow in relocation data.");
- r->value.ValueCode.len = size;
- return norelocs;
- }
-
- int relocEval(Reloc *r, Value *value, Symbol *area)
- {
- int norelocs = 0;
- int this = 0;
- LateInfo *late;
-
- codeInit();
- *value = codeEvalLow(ValueAll,r->value.ValueCode.len,r->value.ValueCode.c);
- switch(value->Tag) {
- case ValueIllegal:
- errorLine(r->lineno,ErrorError,TRUE,"Can not evaluate expression (illegal).");
- r->Tag = RelocNone;
- return 0;
- case ValueCode:
- errorLine(r->lineno,ErrorError,TRUE,"Can not evaluate expression (code).");
- r->Tag = RelocNone;
- return 0;
- case ValueLateLabel:
- switch(r->Tag) {
- case RelocBranch:
- this = 0;
- for(late = value->ValueLate.late; late; late = late->next)
- if(late->symbol == area) {
- this = late->factor;
- late->factor = 0;
- break;
- }
- for(late = value->ValueLate.late; late; late = late->next)
- if(late->factor > 0) {
- if(late->symbol->type != SYMBOL_AREA)
- late->symbol->used ++;
- this += late->factor;
- } else if(late->factor < 0) {
- errorLine(r->lineno,ErrorError,TRUE,"Only positive relocation allowed.");
- late->factor = 1;
- }
- if(this)
- errorLine(r->lineno,ErrorError,TRUE,"Unbalanced relocation (%d).",this);
- break;
- case RelocImmN:
- for(late = value->ValueLate.late; late; late = late->next) {
- if(late->factor > 0) {
- if(late->symbol->type != SYMBOL_AREA) {
- late->symbol->used ++;
- } else if(r->extra != 4) {
- errorLine(r->lineno,ErrorError,TRUE,
- "8/16 bits field can not be allocated with area (%s).",
- late->symbol->str);
- }
- } else
- if(late->factor < 0) {
- errorLine(r->lineno,ErrorError,TRUE,"Only positive relocation allowed.");
- late->factor = 1;
- }
- }
- break;
- case ValueInt:
- break;
- default:
- errorLine(r->lineno,ErrorError,TRUE,"Linker can not handle %s.",reloc2String(r->Tag));
- r->Tag = RelocNone;
- return 0;
- } /* ValueLateLabel */
- norelocs = relocLate2Reloc(r,value);
- break;
- case ValueInt:
- break;
- default:
- errorLine(r->lineno,ErrorSerious,FALSE,"Illegal ValueTag in relocEval.");
- }
- return norelocs;
- }
-
-
-
- void relocWrite(Reloc *r, Value *value, char *image)
- {
- int offset = r->offset;
- WORD w;
-
- switch(value->Tag) {
- case ValueLateLabel:
- case ValueInt:
- switch(r->Tag) { /* Write out the value */
- case RelocBranch:
- w = fixBranch(r->lineno,value->ValueInt.i);
- image[offset+2] = (w>>16) & 0xff;
- image[offset+1] = (w>> 8) & 0xff;
- image[offset+0] = w & 0xff;
- break;
- case RelocCpuOffset:
- w = (image[offset+3]<<24)|(image[offset+2]<<16)|(image[offset+1]<<8)|image[offset+0];
- w = fixCpuOffset(r->lineno,w,value->ValueInt.i);
- image[offset+3] = (w>>24) & 0xff;
- image[offset+2] = (w>>16) & 0xff;
- image[offset+1] = (w>> 8) & 0xff;
- image[offset+0] = w & 0xff;
- break;
- case RelocCopOffset:
- w = (image[offset+3]<<24)|(image[offset+2]<<16)|(image[offset+1]<<8)|image[offset+0];
- w = fixCopOffset(r->lineno,w,value->ValueInt.i);
- image[offset+3] = (w>>24) & 0xff;
- image[offset+2] = (w>>16) & 0xff;
- image[offset+1] = (w>> 8) & 0xff;
- image[offset+0] = w & 0xff;
- break;
- case RelocImmN:
- w = fixInt(r->lineno,r->extra,value->ValueInt.i);
- switch(r->extra) {
- case 4: image[offset+3] = (w>>24) & 0xff;
- image[offset+2] = (w>>16) & 0xff;
- case 2: image[offset+1] = (w>> 8) & 0xff;
- case 1: image[offset+0] = w & 0xff;
- }
- break;
- case RelocAdr:
- w = (image[offset+3]<<24)|(image[offset+2]<<16)|(image[offset+1]<<8)|image[offset+0];
- w = fixAdr(r->lineno,w,value->ValueInt.i);
- image[offset+3] = (w>>24) & 0xff;
- image[offset+2] = (w>>16) & 0xff;
- image[offset+1] = (w>> 8) & 0xff;
- image[offset+0] = w & 0xff;
- break;
- case RelocImm8s4:
- w = (image[offset+3]<<24)|(image[offset+2]<<16)|(image[offset+1]<<8)|image[offset+0];
- w = fixImm8s4(r->lineno,w,value->ValueInt.i);
- image[offset+3] = (w>>24) & 0xff;
- image[offset+2] = (w>>16) & 0xff;
- image[offset+1] = (w>> 8) & 0xff;
- image[offset+0] = w & 0xff;
- break;
- default:
- errorLine(r->lineno,ErrorError,TRUE,"Can not handle %s when value is int.",reloc2String(r->Tag));
- r->Tag = RelocNone;
- return;
- }
- if(value->Tag == ValueInt || r->value.ValueCode.len == 0) /* Value is known */
- r->Tag = RelocNone;
- break;
-
- case ValueFloat:
- switch(r->Tag) { /* Write out the value */
- case RelocFloat: {
- int i;
- union { double d;
- float f;
- struct { char c[8]; } u;
- } translate;
- if(r->extra==4)
- translate.f = (float)value->ValueFloat.f;
- else
- translate.d = (double)value->ValueFloat.f;
- for(i=0; i<r->extra; i++)
- image[offset+i] = translate.u.c[i];
- } break;
- case RelocImmFloat:
- w = (image[offset+3]<<24)|(image[offset+2]<<16)|(image[offset+1]<<8)|image[offset+0];
- w = fixImmFloat(r->lineno,w,value->ValueFloat.f);
- image[offset+3] = (w>>24) & 0xff;
- image[offset+2] = (w>>16) & 0xff;
- image[offset+1] = (w>> 8) & 0xff;
- image[offset+0] = w & 0xff;
- break;
- default:
- errorLine(r->lineno,ErrorError,TRUE,"Can not handle %s when value is float.",reloc2String(r->Tag));
- }
- r->Tag = RelocNone;
- break;
- default:
- errorLine(r->lineno,ErrorError,TRUE,"Illegal value in relocWrite.");
- r->Tag = RelocNone;
- } /* value->Tag */
- }
-
- int relocFix(Symbol *area)
- {
- char *image = area->area.info->image;
- Reloc *relocs = area->area.info->relocs;
- int norelocs = 0;
- Value value;
-
- while(relocs) {
- switch(relocs->value.Tag) {
- case ValueInt:
- value = relocs->value;
- break;
- case ValueCode:
- norelocs += relocEval(relocs,&value,area);
- break;
- default:
- errorLine(relocs->lineno,ErrorSerious,TRUE,"Not a legal value in relocFix.");
- relocs->Tag = RelocNone;
- }
- if(relocs->Tag != RelocNone) /* We now have a Value */
- relocWrite(relocs,&value,image);
- relocs = relocs->more;
- }
- return norelocs;
- }
-
- void relocOutput(FILE *outfile,Symbol *area)
- {
- Reloc *relocs;
- AofReloc areloc;
- int How,loop,ip;
- for(relocs = area->area.info->relocs; relocs; relocs = relocs->more) {
- switch(relocs->Tag) {
- case RelocBranch:
- How = HOW2_INIT | HOW2_RELATIVE | HOW2_WORD;
- break;
- case RelocImmN:
- switch(relocs->extra) {
- case 4: How = HOW2_INIT | HOW2_WORD; break;
- case 2: How = HOW2_INIT | HOW2_HALF; break;
- case 1: How = HOW2_INIT | HOW2_BYTE; break;
- default: errorLine(relocs->lineno,ErrorSerious,TRUE,"Linker can not handle RelocImmN with size %d.",relocs->extra);
- continue;
- }
- break;
- case RelocNone:
- continue;
- default: errorLine(relocs->lineno,ErrorSerious,TRUE,"Linker can not handle this.");
- continue;
- }
- areloc.Offset = relocs->offset;
- for(ip = 0; ip < relocs->value.ValueCode.len; ip++) {
- if(relocs->value.ValueCode.c[ip].Tag == CodeValue) {
- if(relocs->value.ValueCode.c[ip].CodeValue.value.Tag != ValueInt)
- errorLine(relocs->lineno,ErrorSerious,TRUE,"Internal error in relocsOutput (Not an int).");
- else
- loop = relocs->value.ValueCode.c[ip++].CodeValue.value.ValueInt.i;
- } else
- loop = 1;
- if(relocs->value.ValueCode.c[ip].Tag != CodeSymbol)
- errorLine(relocs->lineno,ErrorSerious,TRUE,"Internal error in relocsOutput.");
- areloc.How = How | relocs->value.ValueCode.c[ip].CodeSymbol.symbol->used;
- if(relocs->value.ValueCode.c[ip].CodeSymbol.symbol->type != SYMBOL_AREA)
- areloc.How |= HOW2_SYMBOL;
- while(loop--)
- fwrite((void *)&areloc,1,8,outfile);
- }
- }
- }
-