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.");
- }
- /* Fixed up to this */
- int relocFix(Symbol *area)
- {
- char *image = area->area.info->image;
- Reloc *relocs = area->area.info->relocs;
- int offset,size;
- WORD w;
- Value value;
- int norelocs = 0;
- LateInfo *late;
- int this;
-
- while(relocs) {
- if(relocs->value.Tag != ValueCode) {
- errorLine(relocs->lineno,ErrorSerious,TRUE,"Not a code value in relocFix.");
- goto ForgetThisReloc;
- } else {
- codeInit();
- value = codeEvalLow(ValueAll,relocs->value.ValueCode.len,relocs->value.ValueCode.c);
- switch(value.Tag) {
- case ValueIllegal:
- errorLine(relocs->lineno,ErrorError,TRUE,"Can not evaluate expression (illegal).");
- goto ForgetThisReloc;
- case ValueCode:
- errorLine(relocs->lineno,ErrorError,TRUE,"Can not evaluate expression (code).");
- goto ForgetThisReloc;
- case ValueLateLabel:
- switch(relocs->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(relocs->lineno,ErrorError,TRUE,"Only positive relocation allowed.");
- late->factor = 1;
- }
- if(this)
- errorLine(relocs->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(relocs->extra != 4) {
- errorLine(relocs->lineno,ErrorError,TRUE,
- "8/16 bits field can not be allocated with area (%s).",
- late->symbol->str);
- }
- } else
- if(late->factor < 0) {
- errorLine(relocs->lineno,ErrorError,TRUE,"Only positive relocation allowed.");
- late->factor = 1;
- }
- }
- break;
- case ValueInt:
- break;
- default:
- errorLine(relocs->lineno,ErrorError,TRUE,"Linker can not handle %s.",reloc2String(relocs->Tag));
- goto ForgetThisReloc;
- }
- size = 0;
- 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) {
- relocs->value.ValueCode.c[size ].Tag = CodeValue;
- relocs->value.ValueCode.c[size ].CodeValue.value.Tag = ValueInt;
- relocs->value.ValueCode.c[size++].CodeValue.value.ValueInt.i = late->factor;
- }
- relocs->value.ValueCode.c[size ].Tag = CodeSymbol;
- relocs->value.ValueCode.c[size++].CodeSymbol.symbol = late->symbol;
- }
- }
- if(size>relocs->value.ValueCode.len)
- errorLine(relocs->lineno,ErrorSerious,FALSE,"Overflow in relocation data.");
- relocs->value.ValueCode.len = size;
- case ValueInt:
- /************** Start writing the value *****************/
- offset = relocs->offset;
- switch(relocs->Tag) { /* Write out the value */
- case RelocBranch:
- w = fixBranch(relocs->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(relocs->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(relocs->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(relocs->lineno,relocs->extra,value.ValueInt.i);
- switch(relocs->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(relocs->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(relocs->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(relocs->lineno,ErrorError,TRUE,"Can not handle %s when value is int.",reloc2String(relocs->Tag));
- goto ForgetThisReloc;
- }
- if(value.Tag == ValueInt || relocs->value.ValueCode.len == 0) /* Value is known */
- relocs->Tag = RelocNone;
- break;
- case ValueFloat:
- offset = relocs->offset;
- switch(relocs->Tag) { /* Write out the value */
- case RelocFloat: {
- int i;
- union { double d;
- float f;
- struct { char c[8]; } u;
- } translate;
- if(relocs->extra==4)
- translate.f = (float)value.ValueFloat.f;
- else
- translate.d = (double)value.ValueFloat.f;
- for(i=0; i<relocs->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(relocs->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(relocs->lineno,ErrorError,TRUE,"Can not handle %s when value is float.",reloc2String(relocs->Tag));
- goto ForgetThisReloc;
- }
- relocs->Tag = RelocNone;
- break;
- default:
- errorLine(relocs->lineno,ErrorError,TRUE,"Can not handle %s.",reloc2String(relocs->Tag));
- ForgetThisReloc:
- relocs->Tag = RelocNone;
- }
- }
- 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);
- }
- }
- }
-