home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 13
/
AACD13.ISO
/
AACD
/
Programming
/
Atmel
/
Asm
/
src
/
asm.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-08-22
|
32KB
|
1,832 lines
/************************************************************************/
/* Atmel assembler V1.01 */
/* (C)2000 LJS */
/* This should compile on anything! */
/* */
/* 1)Removed NULL at end of constant strings */
/* 2)Shift Left/Right (< >) is now as for C ( << >> ) */
/* 3)Removed temporary file, now done to a buffer. */
/* 4)No upper limit on number of labels (except for avail RAM). */
/* 5)'def' added to allow small text replacements. */
/* 6)Maths precedence is now /*+-&|<> */
/* 7)New line at end of file no longer needed. */
/* 8)Handling of undefined labels containing X,Y and Z */
/* 9)Corrected error on an undefined beginning with H ! */
/*10)Constant strings used to have spaces removed ! "Hell o" == "Hello" */
/*11)Text strings with commas processed wrong. */
/*12)Buffer cleans up correctly. */
/************************************************************************/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef unsigned long ULONG;
typedef unsigned char BYTE;
#include "buff.h"
#include "errors.h"
/* #define DUMP_BUFFER "tmp1.tmp" */
#define CODEFILE "Atmel.txt"
#define MAXOPCODES 256
#define OPLENGTH 8
#define MAX_SR_LINE 16 /*16 bytes max on one S Record line*/
char *Errors[]={"OK",
"Bad constant",
"File error",
"Unrecognised opcode",
"Operand error",
"Out of range",
"Bad code generated",
"Use registers >15",
"Use registers 24, 26, 28 and 30",
"Redeclared label",
"Relative address must be even",
"Code must be at an even address",
"Can't open file for inclusion",
"Out of memory",
"Missing quote's",
"Division by zero",
"Missing brackets",
"Formula to complex",
"Constant not defined",
"Source line too long"
};
#define D_ORG 0
#define D_END 1
#define D_EQU 2
#define D_INCL 3
#define D_NEWFILE 4
#define D_ENDNEW 5
#define D_CONSTB 6
#define D_CONSTW 7
#define D_DEFINE 8
char *Directives[]={"ORG",
"END",
"EQU",
"INCLUDE",
"FILE",
"ENDFILE",
"DB",
"DW",
"DEF",
NULL
};
#include "struct.h"
struct ACode *Codes[MAXOPCODES];
extern struct ACode InternCodes[];
int Error=0;
long LineNumber=0;
struct DStack *Files=NULL;
struct Labels *LabelStack = NULL;
BYTE SRBuffer[MAX_SR_LINE];
BYTE SROffset;
BYTE InternalTable = 0;
int SRIn=0;
#include "proto.h"
#include "str_p.h" /* String function prototypes */
char *FGets(char *Str, int Size, FILE *In);
void ConvertLine( char *Line, char *First, char *Second, char *Third );
int main(int argc, char *argv[])
{
MEMBUFF *Tempfile;
int Count;
char *Outfile, *Listfile=NULL;
printf(" Atmel cross assembler (C)2000 LJS By Lee Atkins.\n");
printf(" Version date "__DATE__"\n");
if(argc<2)
{
printf(" Asm <source file> <output file> <list file>\n");
return 1;
}
if (argc>2)
{
Outfile=argv[2];
}
else
{
Outfile="a.out";
}
if (argc==4)
{
Listfile=argv[3];
}
for(Count=0; Count<MAXOPCODES; Count++)
{
Codes[Count]=NULL;
}
printf(" Loading machine file..\r");
if(ParseCodes(CODEFILE))
{
if(InternalTable)
{
printf(" Using internal code table.\n");
}
else
{
printf(" Using machine file "CODEFILE"\n");
}
PushFiles(argv[1],NULL);
Tempfile=OpenBuffer();
if(Tempfile!=NULL)
{
printf(" Preprocessing.........\r");
if(PreProcess(argv[1],Tempfile))
{
printf(" Assembling :%s\n Output on :%s\n",argv[1],Outfile);
if(Listfile)
{
printf(" List on :%s\n",Listfile);
}
Assemble(Tempfile,Outfile,Listfile,argv[1]);
}
if(Error)
{
printf(" File : %s\n",Files->Data);
printf(" Error %d Line %ld %s.\n",Error,LineNumber,Errors[Error]);
}
else
{
printf(" Bytes used : %d\n",SRIn);
printf(" Assembled with no errors.\n");
}
#ifdef DUMP_BUFFER
BuffDump(DUMP_BUFFER,Tempfile);
#endif
KillBuffer(Tempfile);
}
else
{
printf(" Out of memory!\n");
}
}
else
{
printf(" Error parsing machine file!\n");
}
if(InternalTable != 1)
{
FreeCodes();
}
FreeLabelStack();
while(PopFiles());
return 1;
}
int ParseCodes(char *FileName)
{
FILE *Infile;
int Count=0, Part=0, OneOfFour=0;
char InText, InStr[36],Finished=0;
/*Gets code from code file FileName*/
Infile=fopen(FileName,"r");
if(Infile==NULL)
{
InternalTable = 1;
while(InternCodes[Part].Opcode != NULL)
{
Codes[Part]=&InternCodes[Part];
Part++;
}
return 1;
}
else
{
do
{
do
{
do
{
InText=fgetc(Infile);
}while( (InText<33) && (InText!=EOF) );
if(InText==EOF)
{
fclose(Infile);
return 1;
}
if(InText=='*')
{
do
{
InText=fgetc(Infile);
}while( (InText!='*') && (InText!=EOF) );
if(InText==EOF)
{
fclose(Infile);
return 0;
}
}
}while(InText=='*');
Count=0;
do
{
InStr[Count++]=InText;
if(Count==36)
{
Count--;
fclose(Infile);
return 0;
}
InText=fgetc(Infile);
if(InText=='*')
{
fclose(Infile);
return 0;
}
}while(InText>32);
InStr[Count]=0; /*terminate*/
switch(OneOfFour)
{
case 0:
Codes[Part]=(struct ACode*)malloc(sizeof(struct ACode));
if(Codes[Part]==NULL)
{
Finished=2;
}
else
{
Codes[Part]->Operand=NULL;
Codes[Part]->Code=NULL;
Codes[Part]->Flag=NULL;
Codes[Part]->Opcode=(char*)malloc(strlen(InStr)+1);
if(Codes[Part]->Opcode==NULL)
{
Finished=2;
}
else
{
strcpy(Codes[Part]->Opcode,InStr);
OneOfFour++;
}
}
break;
case 1:
Codes[Part]->Operand=(char*)malloc(strlen(InStr)+1);
if(Codes[Part]->Operand==NULL)
{
Finished=2;
}
else
{
strcpy(Codes[Part]->Operand,InStr);
OneOfFour++;
}
break;
case 2:
Codes[Part]->Code=(char*)malloc(strlen(InStr)+1);
if(Codes[Part]->Code==NULL)
{
Finished=2;
}
else
{
strcpy(Codes[Part]->Code,InStr);
OneOfFour++;
}
break;
case 3:
Codes[Part]->Flag=(char*)malloc(strlen(InStr)+1);
if(Codes[Part]->Flag==NULL)
{
Finished=2;
}
else
{
strcpy(Codes[Part]->Flag,InStr);
OneOfFour=0;
Part++;
if(Part==MAXOPCODES)
{
Finished=2;
}
}
break;
} /*end switch*/
}while(!Finished);
fclose(Infile);
if(Finished==1)
{
return 1;
}
else
{
return 0;
}
}
}
int FreeCodes(void)
{
/*Frees Codes array*/
int Count;
for(Count=0; Count<MAXOPCODES; Count++)
{
if(Codes[Count]!=NULL)
{
if(Codes[Count]->Opcode!=NULL)
{
free(Codes[Count]->Opcode);
Codes[Count]->Opcode=NULL;
}
if(Codes[Count]->Operand!=NULL)
{
free(Codes[Count]->Operand);
Codes[Count]->Operand=NULL;
}
if(Codes[Count]->Code!=NULL)
{
free(Codes[Count]->Code);
Codes[Count]->Code=NULL;
}
if(Codes[Count]->Flag!=NULL)
{
free(Codes[Count]->Flag);
Codes[Count]->Flag=NULL;
}
free(Codes[Count]);
Codes[Count]=NULL;
}
}
return 1;
}
char *FGets(char *Str, int Size, FILE *In)
{
char *p=Str, Some = 0;
int k;
do
{
k=fgetc(In);
if (k == -1)
{
if(Some) return (Str);
return (NULL);
}
Some = 1;
*p++=k;
}while( (--Size) && (k!='\n') );
*p++=0;
if(Size == 0)
{
Error = LONGLINE;
}
return(Str);
}
int PreProcess(char *Filename, MEMBUFF *Tempfile)
{
FILE *Infile;
char Line[128], First[128], Second[128], Third[128];
char TempStr[128], Flag;
int PC=0, Tmp, FileCount, WordPC=0, NewSz, Address;
struct Labels *Result;
LineNumber=0;
Infile=fopen(Filename,"r");
if(Infile==NULL)
{
printf("Can't open %s\n",Filename);
return 0;
}
FileCount=0;
do
{
/* Had to write my own fgets() cos some implementations are slightly */
/* different */
while( (FGets(Line,128,Infile)) && (Error==0))
{
LineNumber++;
StripComments(Line);
StripCrudd(Line);
StrUpr(Line);
/* Make us multi format compatible ! */
ConvertLine(Line, First, Second, Third);
RemoveSpace(First);
RemoveSpace(Second);
RemoveChar(Second,'.');
RemoveSpaceTSF(Third);
if(*First)
{ /*Add label in stack*/
if(strcmp(Second,Directives[D_EQU])==0)
{
Replace(Third);
Address=StrToInt(Third);
Flag='E';
}
else if(strcmp(Second,Directives[D_DEFINE])==0)
{
Replace(Third);
Flag='M';
}
else
{
Address=WordPC;
Flag='A';
}
if(Error==0)
{
if(IsInStack(First))
{
Error=REPEATLABEL;
fclose(Infile);
return 0;
}
if(Flag=='E')
{
Second[0]=0;
Third[0]=0;
}
if(Flag == 'M')
{
Result = AddLabel(First, Address, Flag, Third);
Second[0]=0;
Third[0]=0;
}
else
{
Result = AddLabel(First, Address, Flag, NULL);
}
if( Result == NULL)
{
Error=MEM;
fclose(Infile);
return 0;
}
First[0]=0;
}
else
{
Error=0;
}
}
if(*Second)
{
ProcessOperand(Third);
Error=0;
if( (Tmp=FindCode(Second)) !=MAXOPCODES )
{
NewSz=CodeLength(Tmp);
PC+=NewSz;
WordPC+=NewSz>>1;
}
else
{
/*could be a directive*/
Tmp=FindDirective(Second);
if(Directives[Tmp]!=NULL)
{
/*It is!*/
switch(Tmp)
{
case D_EQU:
break;
case D_DEFINE:
break;
case D_CONSTB:
NewSz=ConstantLength(Third,1);
PC+=NewSz;
WordPC+=NewSz>>1;
break;
case D_CONSTW:
NewSz=ConstantLength(Third,2);
PC+=NewSz;
WordPC+=NewSz>>1;
break;
case D_ORG:
PC=StrToInt(Third);
WordPC=PC;
break;
case D_NEWFILE:
PushFiles(Third,NULL);
LineNumber=0;
break;
case D_ENDNEW:
PopFiles();
break;
case D_INCL:
RemoveChar(Third,'"');
sprintf(TempStr," FILE \"%s\" \n",Third);
BuffPutS(TempStr,Tempfile);
PushFiles(Third,Infile); /*Save current file stuff*/
Infile=fopen(Third,"rb");
if(Infile==NULL)
{
Error=NOFILE;
Infile=PopFiles();
fclose(Infile);
return 0;
}
First[0]=0;
Second[0]=0;
Third[0]=0;
FileCount++;
LineNumber=0;
break;
case D_END:
First[0]=0;
Second[0]=0;
Third[0]=0;
break;
default:
Error=NOTOP;
break;
}/*end switch*/
}
else
{
Error=NOTOP;
}
}
}
sprintf(TempStr,"%s %s %s\n",First,Second,Third);
BuffPutS(TempStr,Tempfile);
}
fclose(Infile);
if( (FileCount) && (Error==0) )
{
BuffPutS(" ENDFILE",Tempfile);
Infile=PopFiles();
}
}while( (FileCount--) && (Error==0) );
if(Error==0) return 1;
return 0;
}
int FreeLabelStack(void)
{
struct Labels *Tmp;
while(LabelStack)
{
Tmp = LabelStack->Last;
if(LabelStack->Macro) free(LabelStack->Macro);
if(LabelStack->Label) free(LabelStack->Label);
free(LabelStack);
LabelStack = Tmp;
}
return 1;
}
struct Labels *AddLabel(char *Name, int Address, char Flag, char *Macro)
{
struct Labels *Tmp;
Tmp = (struct Labels*)malloc(sizeof(struct Labels));
if(Tmp != NULL)
{
Tmp->Last = LabelStack;
Tmp->Macro = NULL;
Tmp->Label = (char*)malloc(strlen(Name)+1);
if(Tmp->Label != NULL)
{
strcpy(Tmp->Label, Name);
Tmp->Address = Address;
Tmp->Flag = Flag;
if(Macro)
{
Tmp->Macro = (char*)malloc(strlen(Macro)+1);
if(Tmp->Macro != NULL)
{
strcpy(Tmp->Macro, Macro);
LabelStack = Tmp;
return Tmp;
}
}
else
{
LabelStack = Tmp;
return Tmp;
}
free(Tmp->Label);
}
free(Tmp);
}
return NULL;
}
int StripComments(char *Txt)
{
int Len=0;
while((*Txt!=';') && (Len<127) && (*Txt))
{
Txt++;
Len++;
if(*Txt=='"')
{
Txt++;
Len++;
while( (*Txt!='"') && (Len<127) && (*Txt) )
{
Txt++;
Len++;
}
if( (Len==127) || (*Txt!='"') )
{
Error=MISSINGQUOTE;
return 0;
}
}
}
*Txt=0;
return 1;
}
int CodeLength(int Code)
{
int Result;
if(Codes[Code]==NULL)
{
return 0;
}
Result=strlen(Codes[Code]->Code);
if(strchr(Codes[Code]->Code,'!'))
{
Result-=CountChar(Codes[Code]->Code,'!');
}
Result/=OPLENGTH;
return Result;
}
int IsInStack(char *Str)
{
struct Labels *Tmp;
Tmp = LabelStack;
while(Tmp)
{
if(strcmp(Str,Tmp->Label)==0)
{
return 1;
}
Tmp = Tmp->Last;
}
return 0;
}
int FindCode(char *Str)
{
int Count;
for (Count=0; Count<MAXOPCODES; Count++)
{
if(Codes[Count]!=NULL)
{
if(strcmp(Str,Codes[Count]->Opcode)==0)
{
return Count;
}
}
}
return Count;
}
int FindDirective(char *Str)
{
int Count=0;
while(Directives[Count])
{
if(strcmp(Str,Directives[Count])==0)
{
return Count;
}
Count++;
}
return Count;
}
int ProcessOperand(char *Str)
{
char *Ptr,Left[128],Right[128],Comma;
if(strlen(Str) == 0)
{
return 1;
}
Left[0]=0;
Right[0]=0;
Ptr=Str;
Comma=0;
while( (*Str!=',') && (*Str) )
{
Str++;
}
if(*Str==',')
{
*Str=0;
Str++;
Comma=1;
}
else
{
Str=Ptr;
}
strcpy(Left,Ptr);
strcpy(Right,Str);
Replace(Left);
strcpy(Ptr,Left);
if(Comma)
{
Replace(Right);
strcat(Ptr,",");
strcat(Ptr,Right);
}
return 0;
}
int Replace(char *Str)
{
int Ret, Result = 0;
char Work[128],Returned[128], *Sep="+-*/&|<>)",*Tmp;
char *Orig, *Op=" ", *StrIn, BitOfMath=0;
Work[0]=0;
Orig=Str;
StrIn=Str;
while(*Str)
{
if(*Str=='(')
{
*Op=*Str;
strcat(Work,Op);
Orig++;
}
else
{
Tmp=Sep;
while( (*Tmp) && (*Tmp!=*Str))
{
Tmp++;
}
if(*Tmp)
{
/*Found a maths operator*/
BitOfMath=1;
*Str=0;
Result += ReplaceLabels(Orig,Returned);
strcat(Work,Returned);
*Op=*Tmp;
strcat(Work,Op);
Orig=Str+1;
}
}
Str++;
}
Result += ReplaceLabels(Orig,Returned);
strcat(Work,Returned);
if(BitOfMath)
{
Ret=Math(Work);
if(!Error)
{
sprintf(StrIn,"$%X",Ret);
}
else
{
strcpy(StrIn,Work);
}
}
else
{
strcpy(StrIn,Work);
}
return (Result);
}
/*****************************************
* ReplaceLabels()
* Searches for a label in the label stack.
* Copies the labels value into Res.
*****************************************/
int ReplaceLabels(char *Str, char *Res)
{
struct Labels *Tmp;
Tmp = LabelStack;
while(Tmp)
{
if(Tmp->Label!=NULL)
{
if(strcmp(Str, Tmp->Label)==0)
{
if(Tmp->Macro)
{
strcpy(Res,Tmp->Macro);
}
else
{
sprintf(Res,"$%04X",Tmp->Address);
}
return 1;
}
}
Tmp = Tmp->Last;
}
strcpy(Res,Str);
return 0;
}
int StrToInt(char *Str)
{
/*Converts an asciiz number string into an int*/
/*Detects input type as being in hex,dec or bin*/
/*$aa, 0aaH is hex, %1001, 1001b is binary*/
int Result;
StrUpr(Str);
if(strchr(Str,'H')!=NULL)
{
Result=HexToInt(Str);
}
else if(strchr(Str,'$')!=NULL)
{
Result=HexToInt(Str);
}
else if(strchr(Str,'%')!=NULL)
{
Result=BinToInt(Str);
}
else if(strchr(Str,'B')!=NULL)
{
Result=BinToInt(Str);
}
else
{
if(!Validate(Str,"-+0123456789"))
{
Error=CONSTANT;
return 0;
}
Result=atoi(Str);
}
return Result;
}
int HexToInt(char *Str)
{
/* converts a hex string into an int*/
int Result=0,Weight=1,C=1;
char *Tmp;
Tmp=Str;
if(strchr(Str,'$')!=NULL)
{
Tmp=strchr(Str,'$');
Tmp++;
}
else
{
while(*Str)
{
Str++;
}
while(*Str!='H')
{
Str--;
}
*Str=0;
}
Str=Tmp+strlen(Tmp);
if( (!Validate(Tmp,"0123456789ABCDEF")) || (*Tmp == 0) )
{
Error=CONSTANT;
return 0;
}
while(Str!=Tmp)
{
Str--;
Result+=(*Str<'A' ? (*Str-'0'):(10+(*Str-'A')) ) * Weight;
Weight<<=4;
C++;
}
return Result;
}
int BinToInt(char *Str)
{
/*Converts a binary string into an int*/
int Result=0,Weight=1;
char *Tmp;
Tmp=Str;
if(strchr(Str,'%')!=NULL)
{
Tmp=strchr(Str,'%');
Tmp++;
}
else
{
while(*Str)
{
Str++;
}
while(*Str!='B')
{
Str--;
}
*Str=0;
}
Str=Tmp+strlen(Tmp);
if( (!Validate(Tmp,"01")) || (*Tmp == 0) )
{
Error=CONSTANT;
return 0;
}
while(Str!=Tmp)
{
Str--;
Result+=(*Str-'0') * Weight;
Weight<<=1;
}
return Result;
}
int Assemble(MEMBUFF *Tempfile, char *Out, char *List, char *Name)
{
FILE *Outfile=NULL, *SRecord=NULL;
int Count,Found,Replaced,Tmp,PC=0,OldPC=0,PrintPC=0, SRPC=0,CodePC=0;
char Line[128], First[128], Second[128], Repeat[128], *Ptr;
char OrigFirst[128], OrigSecond[128], Third[128];
char Code[33], Map[8],*Indirect,*Post,*Pre, *Temp, Flag;
ULONG CodeData;
int Address;
LineNumber=0;
BuffRewind(Tempfile);
if(List)
{
Outfile=fopen(List,"wb");
if(Outfile==NULL)
{
Error=FILE_ERROR;
return 0;
}
}
SRecord=fopen(Out,"w");
if(SRecord==NULL)
{
if(Outfile) fclose(Outfile);
Error=FILE_ERROR;
return 0;
}
StartSRecord(SRecord,Name);
do
{
do
{
Line[0] = 0;
BuffGetS(Line,128,Tempfile);
LineNumber++;
StripCrudd(Line);
/* StrUpr(Line); */
Ptr=StrCpyChar(First,Line,' ');
Ptr=StrCpyChar(Second,Ptr,' ');
StrCpyChar(Third,Ptr,0);
RemoveSpace(First);
RemoveSpace(Second);
RemoveSpaceTSF(Third);
}while((*Second==0) && (!BuffEOF(Tempfile)));
if(*Second == 0)
{
FinishSRecord(SRecord,SRPC-1);
if(Outfile)
{
DumpLabels(Outfile);
fclose(Outfile);
}
fclose(SRecord);
return 1;
}
strcpy(OrigFirst,Second); /*Save for output to list file*/
strcpy(OrigSecond,Third);
if(!strchr(Third,'"')) /*Test for a text string*/
{
ProcessOperand(Third);
/*Look for code*/
Indirect=strchr(Third,'X');
if(Indirect==NULL)
{
Indirect=strchr(Third,'Y');
}
if(Indirect==NULL)
{
Indirect=strchr(Third,'Z');
}
}
else
{
Indirect=NULL;
}
if(Indirect!=NULL)
{
Error=0; /*These will produce an error in the maths bits*/
Post=strchr(Third,'+');
Pre=strchr(Third,'-');
if(Post)
{
if(Post<Indirect)
{
Pre=Post;
Post=NULL;
}
else if(Post>Indirect)
{
Pre=NULL;
}
}
else if(Pre)
{
if(Pre>Indirect)
{
Post=Pre;
Pre=NULL;
}
else if(Pre<Indirect)
{
Post=NULL;
}
}
else
{
Indirect = NULL; /* Was a false alarm */
}
}
do
{
Count=0;
Found=0;
Replaced=0;
while((Count<MAXOPCODES) && (Codes[Count]) && (!Found))
{
if(strcmp(Codes[Count]->Opcode,Second)==0)
{
if(Indirect)
{
Temp=strchr(Codes[Count]->Operand,*Indirect);
if(Temp!=NULL)
{
if(Pre)
{
if(*(Temp-1)==*Pre)
{
Found=1;
}
}
else if(Post)
{
if(*(Temp+1)==*Post)
{
Found=1;
}
}
else if(strchr(Third,*Temp))
{
Found=1;
}
}
}
else
{
Found=1;
}
}
if(!Found)
{
Count++;
}
}
if(Found)
{
if(*Codes[Count]->Flag=='A')
{
strcpy(Second,Codes[Count]->Flag+1);
strcpy(Repeat,Third);
strcat(Third,",");
strcat(Third,Repeat);
Replaced=1;
}
}
}while(Replaced);
if(!Found)
{
if(!AsmDirective(Second))
{
Error=NOTOP;
fclose(Outfile);
fclose(SRecord);
return 0;
}
else
{
Tmp=FindDirective(Second);
if(Directives[Tmp]!=NULL)
{
/*It is!*/
switch(Tmp)
{
case D_CONSTB:
if(Outfile)
{
fprintf(Outfile,"%ld\t",LineNumber);
fprintf(Outfile,"%04X ",PrintPC);
}
PutConstants(Outfile,SRecord,Third,&SRPC,1);
if(Outfile)
{
fprintf(Outfile,"\t%s %s\n",OrigFirst,OrigSecond);
}
PC=SRPC;
PrintPC=SRPC>>1;
CodePC=PrintPC;
break;
case D_CONSTW:
if(Outfile)
{
fprintf(Outfile,"%ld\t",LineNumber);
fprintf(Outfile,"%04X ",PrintPC);
}
PutConstants(Outfile,SRecord,Third,&SRPC,2);
if(Outfile)
{
fprintf(Outfile,"\t%s %s\n",OrigFirst,OrigSecond);
}
PC=SRPC;
PrintPC=SRPC>>1;
CodePC=PrintPC;
break;
case D_ORG:
FlushSRBuffer(SRecord,SRPC-1);
PC=StrToInt(Third);
PrintPC=PC;
CodePC=PC;
SRPC=PC<<1;
break;
case D_NEWFILE:
PushFiles(Third,NULL);
LineNumber=0;
break;
case D_ENDNEW:
PopFiles();
LineNumber++;
break;
case D_EQU:
Replace(Third);
Address=StrToInt(Third);
Flag='E';
if(IsInStack(First))
{
Error=REPEATLABEL;
}
if(AddLabel(First, Address, Flag, NULL)==NULL)
{
Error=MEM;
}
break;
}
}
}
}
else
{
strcpy(Code,Codes[Count]->Code);
strcpy(Map,Codes[Count]->Operand);
OldPC=PC;
PC+=CodeLength(Count); /*Next address*/
CodePC+=(PC-OldPC)>>1;
CodeData=CreateCode(Code,Map,Third,Codes[Count]->Flag,CodePC);
if(Outfile)
{
fprintf(Outfile,"%ld\t",LineNumber);
fprintf(Outfile,"%04X %04lX ",PrintPC,CodeData);
PrintPC+=(PC-OldPC)>>1;
fprintf(Outfile,"\t%s %s\n",OrigFirst,OrigSecond);
}
if( (PC-OldPC)==4)
{
PutSRBuffer(SRecord,CodeData>>16,SRPC);
PutSRBuffer(SRecord,(CodeData>>24)&255,SRPC+1);
PutSRBuffer(SRecord,CodeData&255,SRPC+2);
PutSRBuffer(SRecord,CodeData>>8,SRPC+3);
}
else
{
PutSRBuffer(SRecord,CodeData&255,SRPC);
PutSRBuffer(SRecord,CodeData>>8,SRPC+1);
}
if(SRPC&1)
{
Error=ALLIGNMENT;
}
SRPC+=(PC-OldPC);
}
}while( Error==0 );
FinishSRecord(SRecord,SRPC);
if(Outfile)
{
DumpLabels(Outfile);
fclose(Outfile);
}
fclose(SRecord);
return 1;
}
ULONG CreateCode(char *Code, char *Map, char *Operand, char *Flag,int PC)
{
char Part[128], *Temp, MapPart[128], *MapTemp;
int Count, Work, Steps, Step,Len;
ULONG Result;
if(strcmp(Map,"-")==0)
{
Result=BinToULong(Code);
return Result;
}
memset(MapPart,0,128);
Temp=Code;
if(strchr(Map,',')!=NULL)
{
Steps=2;
}
else
{
Steps=1;
}
for(Step=0; Step<Steps; Step++)
{
Code=Temp;
if (Validate(Code,"01"))
{
break;
}
Len=strlen(Code);
Count=0;
MapTemp=Map;
while((*Operand) && (*Operand!=','))
{
Part[Count]=*Operand;
MapPart[Count]=*Map;
Count++;
Operand++;
Map++;
}
Part[Count]=0;
MapPart[Count]=0;
Map=MapTemp;
if(*Map=='R')
{
if(Part[0]=='R')
{
Work=StrToInt(&Part[1]);
if(*Flag=='S')
{
if(Work<16)
{
Error=REG16;
return 0;
}
Work-=16;
}
if(*Flag=='U')
{
if( (Work<24) || (Work&1) )
{
Error=UPPERREGS;
return 0;
}
Work=(Work>>1)&3;
}
Map++;
}
else
{
Error=WRONGOP;
return 0;
}
}
else if(*Map=='k')
{
if( (strchr(Operand,',')!=NULL) && (Steps==1) )
{
Error=WRONGOP;
return 0;
}
Work=StrToInt(Part);
if(*Flag=='R')
{
Work=(Work-PC);
if((Work>63) || (Work<-64))
{
Error=RANGE;
return 0;
}
Work&=127;
}
else if(*Flag=='L')
{
Work=(Work-PC);
Work&=4095;
}
else if(*Flag=='N')
{
Work&=0xFFFF;
}
}
else if(*Map=='K')
{
Work=StrToInt(Part);
}
else if(MapPart[2]=='q')
{
Work=StrToInt(&Part[2]);
Map+=2;
}
else
{
if(!Validate(MapPart,"XYZ,+-"))
{
Work=StrToInt(Part);
}
else
{
Work=0;
}
}
Code+=(Len-1);
while(Len)
{
if( (*Code=='!') && (*(Code+1)!='K') )
{
Code++;
if(*Code=='1')
{
*Code='0';
}
else
{
*Code='1';
}
Code--;
*Code=' ';
RemoveSpace(Code);
}
if(*Code==*Map)
{
if(Work&1)
{
*Code='1';
}
else
{
*Code='0';
}
Work>>=1;
}
if(*Code=='X') /*Don't care bit*/
{
*Code='0';
}
Code--;
Len--;
}
if(Work>0) /*-ve numbers are ok!*/
{
Error=RANGE;
return 0;
}
Operand++;
while( (*Map) && (*Map!=',') )
{
Map++;
}
Map++;
}
Code=Temp;
Result=BinToULong(Code);
return Result;
}
ULONG BinToULong(char *Str)
{
/*Converts binary to ulong!*/
int Len;
ULONG Weight=1,Result=0;
StripDontCare(Str);
Len=strlen(Str);
Str+=Len-1;
while(Len)
{
if(Weight==0)
{
Error=RANGE;
return 0;
}
if(*Str=='1')
{
Result|=Weight;
}
else if(*Str!='0')
{
Error=BADCODE;
return 0;
}
Weight<<=1;
Str--;
Len--;
}
return Result;
}
int AsmDirective(char *Str)
{
int Count=0;
while(Directives[Count]!=NULL)
{
if(strcmp(Str,Directives[Count])==0)
{
return 1;
}
Count++;
}
return 0;
}
int PushFiles(char *Str, FILE *H)
{
struct DStack *Temp;
if(Files==NULL)
{
Files=(struct DStack*)malloc(sizeof(struct DStack));
if(Files==NULL)
{
Error=MEM;
return 0;
}
Files->Last=NULL;
Files->Data=(char*)malloc(strlen(Str)+1);
if(Files->Data==NULL)
{
Error=MEM;
return 0;
}
Files->Line=LineNumber;
Files->Handle=H;
strcpy(Files->Data,Str);
}
else
{
Temp=Files;
Files=(struct DStack*)malloc(sizeof(struct DStack));
if(Files==NULL)
{
Error=MEM;
Files=Temp;
return 0;
}
Files->Last=Temp;
Files->Data=(char*)malloc(strlen(Str)+1);
if(Files->Data==NULL)
{
Error=MEM;
return 0;
}
strcpy(Files->Data,Str);
Files->Line=LineNumber;
Files->Handle=H;
}
return 1;
}
FILE *PopFiles(void)
{
struct DStack *Temp;
FILE *TempFile;
if(Files)
{
if(Files->Data!=NULL)
{
free(Files->Data);
Files->Data=NULL;
}
LineNumber=Files->Line;
TempFile=Files->Handle;
Temp=Files->Last;
free(Files);
Files=Temp;
return TempFile;
}
return NULL;
}
int StartSRecord(FILE *File, char *Name)
{
int Checksum, Temp;
char *Orig;
Orig=Name;
fprintf(File,"S0");
Temp=0;
while( (*Name) && (*Name!='.') )
{
Temp++;
Name++;
}
Name=Orig;
Temp+=3; /*+address +checksum*/
Checksum=Temp;
fprintf(File,"%02X",Temp);
fprintf(File,"0000");
while( (*Name) && (*Name!='.') )
{
fprintf(File,"%02X",*Name);
Checksum+=*Name;
Name++;
}
Checksum=~Checksum;
fprintf(File,"%02X\n",(Checksum&255));
SROffset=0;
return 1;
}
int PutSRBuffer(FILE *File, BYTE Data, int PC)
{
SRIn++;
SRBuffer[SROffset]=Data;
SROffset++;
if(SROffset==MAX_SR_LINE)
{
FlushSRBuffer(File,PC);
}
return 1;
}
int FlushSRBuffer(FILE *Outfile,int PC)
{
int C,Count;
int Checksum;
Count=SROffset;
if(Count==0)
{
return 1;
}
fprintf(Outfile,"S1");
fprintf(Outfile,"%02X",Count+3); /*+3 for checksum and address*/
Checksum=Count+3;
fprintf(Outfile,"%04X",PC-Count+1);
Checksum+=((PC-Count+1)>>8);
Checksum+=((PC-Count+1)&255);
for(C=0; C<Count; C++)
{
fprintf(Outfile,"%02X",SRBuffer[C]);
Checksum+=SRBuffer[C];
}
Checksum=~Checksum;
fprintf(Outfile,"%02X\n",(Checksum&255));
SROffset=0;
return 1;
}
int FinishSRecord(FILE *F,int PC)
{
FlushSRBuffer(F,PC);
fprintf(F,"S9030000FC\n");
return 1;
}
int ConstantLength(char *S, BYTE Size)
{
char Work[128];
int Os,Result=0;
do
{
Os=0;
while((*S) && (*S!=','))
{
Work[Os]=*S;
Os++;
if(Os==128)
{
Os--;
}
S++;
}
Work[Os]=0;
if(*S==',')
{
S++;
}
Os=0;
if(Work[Os]=='"')
{
Os++;
while((Work[Os]!='"') && (Work[Os]))
{
Result+=Size; /*Do we want word long chars? !!!!*/
Os++;
}
/* Result+=Size; */ /*For the NULL, Dont put a null*/
}
else
{
Result+=Size;
}
}while(*S);
return Result;
}
int PutConstants(FILE *List,FILE *Out,char *S,int *PC, BYTE Size)
{
char Work[128];
unsigned int Temp;
int Os, Width=0;
do
{
if(*S==',')
{
S++;
}
if( (*S=='"') && (Size==1) )
{
S++;
while( (*S!='"') && (*S) )
{
PutSRBuffer(Out,(BYTE)*S,*PC);
if(List)
{
fprintf(List,"%02X",*S);
Width++;
if(Width==2)
{
Width=0;
fprintf(List,"\n ");
}
}
*PC=*PC+1;
S++;
}
if(*S)
{
S++;
}
/* Dont stuff in a null !!! */
}
else if(*S)
{
Os=0;
while((*S) && (*S!=','))
{
Work[Os]=*S;
Os++;
if(Os==127)
{
Os--;
}
S++;
}
if(*S)
{
S++;
}
Work[Os]=0;
Temp=StrToInt(Work);
if(List)
{
fprintf(List,"%02X",Temp&255);
Width++;
if(Width==2)
{
Width=0;
fprintf(List,"\n ");
}
}
PutSRBuffer(Out,Temp&255,*PC);
*PC=*PC+1;
if(Size==2)
{
if(List)
{
fprintf(List,"%02X",Temp>>8);
Width++;
if(Width==2)
{
Width=0;
fprintf(List,"\n ");
}
}
PutSRBuffer(Out,Temp>>8,*PC);
*PC=*PC+1;
}
}
}while(*S);
return 1;
}
void DumpLabels(FILE *List)
{
struct Labels *Tmp;
fprintf(List,"\n\n");
Tmp = LabelStack;
while(Tmp)
{
if(Tmp->Label!=NULL)
{
if(Tmp->Flag=='E')
{
fprintf(List,"%s\t\t$%04X\tE\n",Tmp->Label,Tmp->Address);
}
else if(Tmp->Flag == 'M')
{
fprintf(List,"%s\t\t%s\tM\n",Tmp->Label,Tmp->Macro);
}
else
{
fprintf(List,"%s\t\t$%04X\tL\n",Tmp->Label,Tmp->Address);
}
}
Tmp = Tmp->Last;
}
}