2864 lines
89 KiB
C
2864 lines
89 KiB
C
|
|
//-------------------------------------------------------------------
|
|
// Copyright (C) 2012 David Welch
|
|
//-------------------------------------------------------------------
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
|
|
FILE *fpin;
|
|
FILE *fpout;
|
|
|
|
unsigned int rd,rm,rn,rx;
|
|
unsigned int bl_upper;
|
|
unsigned int is_const,is_label;
|
|
|
|
#define ADDMASK 0xFFFF
|
|
unsigned short mem[ADDMASK+1];
|
|
unsigned short mark[ADDMASK+1];
|
|
|
|
unsigned int curradd;
|
|
unsigned int line;
|
|
|
|
char cstring[1024];
|
|
char newline[1024];
|
|
|
|
|
|
#define LABLEN 64
|
|
|
|
#define MAX_LABS 65536
|
|
struct
|
|
{
|
|
char name[LABLEN];
|
|
unsigned int addr;
|
|
unsigned int line;
|
|
unsigned int type;
|
|
} lab_struct[MAX_LABS];
|
|
unsigned int nlabs;
|
|
unsigned int lab;
|
|
|
|
|
|
#define NREGNAMES (19)
|
|
struct
|
|
{
|
|
char name[4];
|
|
unsigned char num;
|
|
} reg_names[NREGNAMES]=
|
|
{
|
|
{"r0",0},{"r1",1},{"r2",2},{"r3",3},{"r4",4},{"r5",5},{"r6",6},{"r7",7},
|
|
{"r8",8},{"r9",9},{"r10",10},{"r11",11},{"r12",12},{"r13",13},{"r14",14},{"r15",15},
|
|
{"sp",13},{"lr",14},{"pc",15}
|
|
};
|
|
|
|
|
|
unsigned char hexchar[256]=
|
|
{
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
|
|
0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
};
|
|
|
|
unsigned char numchar[256]=
|
|
{
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
};
|
|
|
|
//-------------------------------------------------------------------
|
|
//-------------------------------------------------------------------
|
|
//-------------------------------------------------------------------
|
|
int rest_of_line ( unsigned int ra )
|
|
{
|
|
for(;newline[ra];ra++) if(newline[ra]!=0x20) break;
|
|
if(newline[ra])
|
|
{
|
|
printf("<%u> Error: garbage at end of line\n",line);
|
|
return(1);
|
|
}
|
|
return(0);
|
|
}
|
|
//-------------------------------------------------------------------
|
|
int get_reg_number ( char *s, unsigned int *rx )
|
|
{
|
|
unsigned int ra;
|
|
|
|
for(ra=0;ra<NREGNAMES;ra++)
|
|
{
|
|
if(strcmp(s,reg_names[ra].name)==0)
|
|
{
|
|
*rx=reg_names[ra].num;
|
|
return(0);
|
|
}
|
|
}
|
|
return(1);
|
|
}
|
|
//-------------------------------------------------------------------
|
|
unsigned int parse_immed ( unsigned int ra )
|
|
{
|
|
unsigned int rb;
|
|
|
|
for(;newline[ra];ra++) if(newline[ra]!=0x20) break;
|
|
if((newline[ra]==0x30)&&((newline[ra+1]=='x')||(newline[ra+1]=='X')))
|
|
{
|
|
ra+=2;
|
|
rb=0;
|
|
for(;newline[ra];ra++)
|
|
{
|
|
if(newline[ra]==',') break;
|
|
if(newline[ra]==']') break;
|
|
if(newline[ra]==0x20) break;
|
|
if(!hexchar[newline[ra]])
|
|
{
|
|
printf("<%u> Error: invalid number\n",line);
|
|
return(0);
|
|
}
|
|
cstring[rb++]=newline[ra];
|
|
}
|
|
cstring[rb]=0;
|
|
if(rb==0)
|
|
{
|
|
printf("<%u> Error: invalid number\n",line);
|
|
return(0);
|
|
}
|
|
rx=strtoul(cstring,NULL,16);
|
|
}
|
|
else
|
|
{
|
|
rb=0;
|
|
for(;newline[ra];ra++)
|
|
{
|
|
if(newline[ra]==',') break;
|
|
if(newline[ra]==']') break;
|
|
if(newline[ra]==0x20) break;
|
|
if(!numchar[newline[ra]])
|
|
{
|
|
printf("<%u> Error: invalid number\n",line);
|
|
return(0);
|
|
}
|
|
cstring[rb++]=newline[ra];
|
|
}
|
|
cstring[rb]=0;
|
|
if(rb==0)
|
|
{
|
|
printf("<%u> Error: invalid number\n",line);
|
|
return(0);
|
|
}
|
|
rx=strtoul(cstring,NULL,10);
|
|
}
|
|
for(;newline[ra];ra++) if(newline[ra]!=0x20) break;
|
|
return(ra);
|
|
}
|
|
//-------------------------------------------------------------------
|
|
unsigned int parse_reg ( unsigned int ra )
|
|
{
|
|
unsigned int rb;
|
|
|
|
for(;newline[ra];ra++) if(newline[ra]!=0x20) break;
|
|
rb=0;
|
|
for(;newline[ra];ra++)
|
|
{
|
|
if(newline[ra]==',') break;
|
|
if(newline[ra]==']') break;
|
|
if(newline[ra]=='}') break;
|
|
if(newline[ra]==0x20) break;
|
|
cstring[rb++]=newline[ra];
|
|
}
|
|
cstring[rb]=0;
|
|
if(get_reg_number(cstring,&rx))
|
|
{
|
|
printf("<%u> Error: not a register\n",line);
|
|
return(0);
|
|
}
|
|
for(;newline[ra];ra++) if(newline[ra]!=0x20) break;
|
|
return(ra);
|
|
}
|
|
//-------------------------------------------------------------------
|
|
unsigned int parse_low_reg ( unsigned int ra )
|
|
{
|
|
unsigned int rb;
|
|
|
|
for(;newline[ra];ra++) if(newline[ra]!=0x20) break;
|
|
rb=0;
|
|
for(;newline[ra];ra++)
|
|
{
|
|
if(newline[ra]==',') break;
|
|
if(newline[ra]=='!') break;
|
|
if(newline[ra]=='}') break;
|
|
if(newline[ra]==']') break;
|
|
if(newline[ra]==0x20) break;
|
|
cstring[rb++]=newline[ra];
|
|
}
|
|
cstring[rb]=0;
|
|
if(get_reg_number(cstring,&rx))
|
|
{
|
|
printf("<%u> Error: not a register\n",line);
|
|
return(0);
|
|
}
|
|
if(rx>7)
|
|
{
|
|
printf("<%u> Error: invalid (high) register\n",line);
|
|
return(0);
|
|
}
|
|
for(;newline[ra];ra++) if(newline[ra]!=0x20) break;
|
|
return(ra);
|
|
}
|
|
//-------------------------------------------------------------------
|
|
unsigned int parse_comma ( unsigned int ra )
|
|
{
|
|
for(;newline[ra];ra++) if(newline[ra]!=0x20) break;
|
|
if(newline[ra]!=',')
|
|
{
|
|
printf("<%u> Error: syntax error\n",line);
|
|
return(0);
|
|
}
|
|
ra++;
|
|
for(;newline[ra];ra++) if(newline[ra]!=0x20) break;
|
|
return(ra);
|
|
}
|
|
//-------------------------------------------------------------------
|
|
unsigned int parse_character ( unsigned int ra, unsigned char ch )
|
|
{
|
|
for(;newline[ra];ra++) if(newline[ra]!=0x20) break;
|
|
if(newline[ra]!=ch)
|
|
{
|
|
printf("<%u> Error: syntax error\n",line);
|
|
return(0);
|
|
}
|
|
ra++;
|
|
for(;newline[ra];ra++) if(newline[ra]!=0x20) break;
|
|
return(ra);
|
|
}
|
|
//-------------------------------------------------------------------
|
|
unsigned int no_spaces ( unsigned int ra )
|
|
{
|
|
for(;newline[ra];ra++) if(newline[ra]!=0x20) break;
|
|
return(ra);
|
|
}
|
|
//-------------------------------------------------------------------
|
|
unsigned int parse_two_regs ( unsigned int ra )
|
|
{
|
|
ra=parse_low_reg(ra); if(ra==0) return(0);
|
|
rd=rx;
|
|
ra=parse_comma(ra); if(ra==0) return(0);
|
|
ra=parse_low_reg(ra); if(ra==0) return(0);
|
|
rm=rx;
|
|
return(ra);
|
|
}
|
|
//-------------------------------------------------------------------
|
|
unsigned int parse_branch_label ( unsigned int ra )
|
|
{
|
|
unsigned int rb;
|
|
unsigned int rc;
|
|
|
|
is_const=0;
|
|
is_label=0;
|
|
for(;newline[ra];ra++) if(newline[ra]!=0x20) break;
|
|
if(numchar[newline[ra]])
|
|
{
|
|
ra=parse_immed(ra); if(ra==0) return(0);
|
|
is_const=1;
|
|
}
|
|
else
|
|
{
|
|
//assume label, find space or eol.
|
|
for(rb=ra;newline[rb];rb++)
|
|
{
|
|
if(newline[rb]==0x20) break; //no spaces in labels
|
|
}
|
|
//got a label
|
|
rc=rb-ra;
|
|
if(rc==0)
|
|
{
|
|
printf("<%u> Error: Invalid label\n",line);
|
|
return(0);
|
|
}
|
|
rc--;
|
|
if(rc>=LABLEN)
|
|
{
|
|
printf("<%u> Error: Label too long\n",line);
|
|
return(0);
|
|
}
|
|
for(rb=0;rb<=rc;rb++)
|
|
{
|
|
lab_struct[nlabs].name[rb]=newline[ra++];
|
|
}
|
|
lab_struct[nlabs].name[rb]=0;
|
|
lab_struct[nlabs].addr=curradd;
|
|
lab_struct[nlabs].line=line;
|
|
lab_struct[nlabs].type=1;
|
|
nlabs++;
|
|
rx=0;
|
|
is_label=1;
|
|
}
|
|
return(ra);
|
|
}//-------------------------------------------------------------------
|
|
//-------------------------------------------------------------------
|
|
int assemble ( void )
|
|
{
|
|
unsigned int ra;
|
|
unsigned int rb;
|
|
unsigned int rc;
|
|
|
|
|
|
curradd=0;
|
|
nlabs=0;
|
|
memset(mem,0x00,sizeof(mem));
|
|
memset(mark,0x00,sizeof(mark));
|
|
|
|
//.word 0xEAFFFFFF
|
|
//.word 0xE59FD004
|
|
//.word 0xE59F0004
|
|
//.word 0xE12FFF10
|
|
//.word 0x00100000
|
|
//.word 0x00000021
|
|
//.word 0x00000000
|
|
//.word 0x00000000
|
|
|
|
mem[curradd]=0xFFFF; mark[curradd]=0x9000; curradd++; mem[curradd]=0xEAFF; mark[curradd]=0x9000; curradd++;
|
|
mem[curradd]=0xD004; mark[curradd]=0x9000; curradd++; mem[curradd]=0xE59F; mark[curradd]=0x9000; curradd++;
|
|
mem[curradd]=0x0004; mark[curradd]=0x9000; curradd++; mem[curradd]=0xE59F; mark[curradd]=0x9000; curradd++;
|
|
mem[curradd]=0xFF10; mark[curradd]=0x9000; curradd++; mem[curradd]=0xE12F; mark[curradd]=0x9000; curradd++;
|
|
mem[curradd]=0x0000; mark[curradd]=0x9000; curradd++; mem[curradd]=0x0010; mark[curradd]=0x9000; curradd++;
|
|
mem[curradd]=0x0021; mark[curradd]=0x9000; curradd++; mem[curradd]=0x0000; mark[curradd]=0x9000; curradd++;
|
|
mem[curradd]=0x0000; mark[curradd]=0x9000; curradd++; mem[curradd]=0x0000; mark[curradd]=0x9000; curradd++;
|
|
mem[curradd]=0x0000; mark[curradd]=0x9000; curradd++; mem[curradd]=0x0000; mark[curradd]=0x9000; curradd++;
|
|
|
|
line=0;
|
|
while(fgets(newline,sizeof(newline)-1,fpin))
|
|
{
|
|
line++;
|
|
//tabs to spaces and other things
|
|
for(ra=0;newline[ra];ra++)
|
|
{
|
|
if(newline[ra]<0x20) newline[ra]=0x20;
|
|
if(newline[ra]>=0x7F) newline[ra]=0;
|
|
}
|
|
|
|
//various ways to comment lines
|
|
for(ra=0;newline[ra];ra++)
|
|
{
|
|
if(newline[ra]==';') newline[ra]=0;
|
|
if(newline[ra]=='@') newline[ra]=0;
|
|
if((newline[ra]=='/')&&(newline[ra+1]=='/')) newline[ra]=0;
|
|
if(newline[ra]==0) break;
|
|
}
|
|
|
|
//skip spaces
|
|
for(ra=0;newline[ra];ra++) if(newline[ra]!=0x20) break;
|
|
if(newline[ra]==0) continue;
|
|
|
|
//look for a label?
|
|
for(rb=ra;newline[rb];rb++)
|
|
{
|
|
if(newline[rb]==0x20) break; //no spaces in labels
|
|
if(newline[rb]==':') break;
|
|
}
|
|
if(newline[rb]==':')
|
|
{
|
|
//got a label
|
|
rc=rb-ra;
|
|
if(rc==0)
|
|
{
|
|
printf("<%u> Error: Invalid label\n",line);
|
|
return(1);
|
|
}
|
|
rc--;
|
|
if(rc>=LABLEN)
|
|
{
|
|
printf("<%u> Error: Label too long\n",line);
|
|
return(1);
|
|
}
|
|
for(rb=0;rb<=rc;rb++)
|
|
{
|
|
lab_struct[nlabs].name[rb]=newline[ra++];
|
|
}
|
|
lab_struct[nlabs].name[rb]=0;
|
|
lab_struct[nlabs].addr=curradd<<1;
|
|
lab_struct[nlabs].line=line;
|
|
lab_struct[nlabs].type=0;
|
|
ra++;
|
|
for(lab=0;lab<nlabs;lab++)
|
|
{
|
|
if(lab_struct[lab].type) continue;
|
|
if(strcmp(lab_struct[lab].name,lab_struct[nlabs].name)==0) break;
|
|
}
|
|
if(lab<nlabs)
|
|
{
|
|
printf("<%u> Error: label [%s] already defined on line %u\n",line,lab_struct[lab].name,lab_struct[lab].line);
|
|
return(1);
|
|
}
|
|
nlabs++;
|
|
//skip spaces
|
|
for(;newline[ra];ra++) if(newline[ra]!=0x20) break;
|
|
if(newline[ra]==0) continue;
|
|
}
|
|
// .align -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],".align",6)==0)
|
|
{
|
|
ra+=6;
|
|
if(rest_of_line(ra)) return(1);
|
|
if(curradd&1)
|
|
{
|
|
printf("<%u> Adding halfword to align on a word boundary\n",line);
|
|
mem[curradd]=0x0000;
|
|
mark[curradd]|=0x9000;
|
|
curradd++;
|
|
}
|
|
continue;
|
|
}
|
|
// .word -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],".word ",6)==0)
|
|
{
|
|
ra+=6;
|
|
if(curradd&1)
|
|
{
|
|
printf("<%u> Error: not word aligned\n",line,lab_struct[lab].name,lab_struct[lab].line);
|
|
return(1);
|
|
}
|
|
for(;newline[ra];ra++) if(newline[ra]!=0x20) break;
|
|
if(newline[ra]=='=')
|
|
{
|
|
ra=parse_character(ra,'='); if(ra==0) return(1);
|
|
ra=parse_branch_label(ra); if(ra==0) return(1);
|
|
if((is_const)||(!is_label))
|
|
{
|
|
printf("<%u> Error: expecting a label\n",line);
|
|
return(1);
|
|
}
|
|
mem[curradd]=0x0000;
|
|
mark[curradd]|=0x9000;
|
|
curradd++;
|
|
mem[curradd]=0x0000;
|
|
mark[curradd]|=0x9000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
while(1)
|
|
{
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
mem[curradd]=rx&0xFFFF;
|
|
mark[curradd]|=0x9000;
|
|
curradd++;
|
|
mem[curradd]=(rx>>16)&0xFFFF;
|
|
mark[curradd]|=0x9000;
|
|
curradd++;
|
|
if(newline[ra]!=',') break;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
}
|
|
}
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// .hword -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],".hword ",7)==0)
|
|
{
|
|
ra+=7;
|
|
while(1)
|
|
{
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0xFFFF)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
mem[curradd]=rx;
|
|
mark[curradd]|=0x9000;
|
|
curradd++;
|
|
if(newline[ra]!=',') break;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
}
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// adc -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"adc ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//adc rd,rm
|
|
ra=parse_two_regs(ra); if(ra==0) return(1);
|
|
mem[curradd]=0x4140|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// add -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"add ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//add rd,rm,#immed_3
|
|
//add rd,#immed_8
|
|
//add rd,rn,rm
|
|
//add rd,rm one or both high
|
|
//add rd,pc,#immed_8*4
|
|
//add rd,sp,#immed_8*4
|
|
//add sp,#immed_7*4
|
|
ra=parse_reg(ra); if(ra==0) return(1);
|
|
rd=rx;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
if(rd>7)
|
|
{
|
|
//add rdhi,
|
|
if((rd==13)&&(newline[ra]=='#'))
|
|
{
|
|
ra++;
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0x1FC)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
//add sp,#immed_7*4
|
|
mem[curradd]=0xB000|(rx>>2);
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
ra=parse_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
//add rd,rm one or both high
|
|
mem[curradd]=0x4400|((rd&8)<<4)|(rm<<3)|(rd&7);
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//add rdlo,
|
|
if(newline[ra]=='#')
|
|
{
|
|
ra++;
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0xFF)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
//add rd,#immed_8
|
|
mem[curradd]=0x3000|(rd<<8)|rx;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
//add rdlo,r?
|
|
ra=parse_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
if(rm>7)
|
|
{
|
|
//add rdlo,rhi
|
|
if(newline[ra]==',')
|
|
{
|
|
//add rdlo,rhi,
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
if(newline[ra]!='#')
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
if(rm==15)
|
|
{
|
|
ra++;
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0x3FC)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
//add rd,pc,#immed_8*4
|
|
mem[curradd]=0xA000|(rd<<8)|(rx>>2);
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
if(rm==13)
|
|
{
|
|
ra++;
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0x3FC)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
//add rd,pc,#immed_8*4
|
|
mem[curradd]=0xA800|(rd<<8)|(rx>>2);
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
printf("<%u> Error: Invalid second register\n",line);
|
|
return(1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//add rdlo,rdhi
|
|
//add rd,rm one or both high
|
|
mem[curradd]=0x4400|((rd&8)<<4)|(rm<<3)|(rd&7);
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//add rlo,rlo
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
if(newline[ra]=='#')
|
|
{
|
|
rn=rm;
|
|
ra++;
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0x7)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
//add rd,rm,#immed_3
|
|
mem[curradd]=0x1C00|(rx<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
rn=rm;
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
mem[curradd]=0x1800|(rm<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// and -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"and ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//and rd,rm
|
|
ra=parse_two_regs(ra); if(ra==0) return(1);
|
|
mem[curradd]=0x4000|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// asr -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"asr ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//asr rd,rm,#immed_5
|
|
//asr rd,rs
|
|
ra=parse_two_regs(ra); if(ra==0) return(1);
|
|
if(newline[ra]==',')
|
|
{
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
if(newline[ra]=='#')
|
|
{
|
|
ra++;
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx<1)||(rx>32))
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
rx&=0x1F;
|
|
//asr rd,rm,#immed_5
|
|
mem[curradd]=0x1000|(rx<<6)|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//asr rd,rs
|
|
mem[curradd]=0x4100|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// b -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"b ",2)==0)
|
|
{
|
|
ra+=2;
|
|
//b label
|
|
//b immed
|
|
ra=parse_branch_label(ra); if(ra==0) return(1);
|
|
if(rest_of_line(ra)) return(1);
|
|
if(is_label)
|
|
{
|
|
mem[curradd]=0xE000;
|
|
mark[curradd]=0x8002;
|
|
curradd++;
|
|
continue;
|
|
}
|
|
if(is_const)
|
|
{
|
|
rd=rx-((curradd<<1)+4);
|
|
rm=0xFFFFFFFF<<11;
|
|
if(rd&rm)
|
|
{
|
|
if((rd&rm)!=rm)
|
|
{
|
|
printf("<%u> Error: Branch destination too far\n",line);
|
|
return(1);
|
|
}
|
|
}
|
|
//ignore even/odd address?
|
|
rm=(rd>>1)&0x7FF;
|
|
mem[curradd]=0xE000|rm;
|
|
mark[curradd]=0x8002;
|
|
curradd++;
|
|
continue;
|
|
}
|
|
}
|
|
// bcond -----------------------------------------------------------
|
|
rn=0;
|
|
if(strncmp(&newline[ra],"beq ",4)==0) rn=0x10;
|
|
if(strncmp(&newline[ra],"bne ",4)==0) rn=0x11;
|
|
if(strncmp(&newline[ra],"bcs ",4)==0) rn=0x12;
|
|
if(strncmp(&newline[ra],"bcc ",4)==0) rn=0x13;
|
|
if(strncmp(&newline[ra],"bmi ",4)==0) rn=0x14;
|
|
if(strncmp(&newline[ra],"bpl ",4)==0) rn=0x15;
|
|
if(strncmp(&newline[ra],"bvs ",4)==0) rn=0x16;
|
|
if(strncmp(&newline[ra],"bvc ",4)==0) rn=0x17;
|
|
if(strncmp(&newline[ra],"bhi ",4)==0) rn=0x18;
|
|
if(strncmp(&newline[ra],"bls ",4)==0) rn=0x19;
|
|
if(strncmp(&newline[ra],"bge ",4)==0) rn=0x1A;
|
|
if(strncmp(&newline[ra],"blt ",4)==0) rn=0x1B;
|
|
if(strncmp(&newline[ra],"bgt ",4)==0) rn=0x1C;
|
|
if(strncmp(&newline[ra],"ble ",4)==0) rn=0x1D;
|
|
if(strncmp(&newline[ra],"bal ",4)==0) rn=0x1E;
|
|
if(rn)
|
|
{
|
|
ra+=3;
|
|
ra=parse_branch_label(ra); if(ra==0) return(1);
|
|
if(rest_of_line(ra)) return(1);
|
|
if(is_label)
|
|
{
|
|
mem[curradd]=0xD000|(rn<<8);
|
|
mark[curradd]=0x8002;
|
|
curradd++;
|
|
continue;
|
|
}
|
|
if(is_const)
|
|
{
|
|
rd=rx-((curradd<<1)+4);
|
|
rm=0xFFFFFFFF<<8;
|
|
if(rd&rm)
|
|
{
|
|
if((rd&rm)!=rm)
|
|
{
|
|
printf("<%u> Error: Branch destination too far\n",line);
|
|
return(1);
|
|
}
|
|
}
|
|
//ignore even/odd address?
|
|
rm=(rd>>1)&0xFF;
|
|
rn&=0xF;
|
|
mem[curradd]=0xD000|(rn<<8)|rm;
|
|
mark[curradd]=0x8002;
|
|
curradd++;
|
|
continue;
|
|
}
|
|
}
|
|
// bic -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"bic ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//bic rd,rm
|
|
ra=parse_two_regs(ra); if(ra==0) return(1);
|
|
mem[curradd]=0x4380|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// bkpt -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"bkpt ",5)==0)
|
|
{
|
|
ra+=5;
|
|
//bkpt immed_8
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0xFF)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
mem[curradd]=0xBE00|rx;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// bl -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"bl ",3)==0)
|
|
{
|
|
ra+=3;
|
|
//bl label
|
|
//bl immed
|
|
ra=parse_branch_label(ra); if(ra==0) return(1);
|
|
if(rest_of_line(ra)) return(1);
|
|
if(is_label)
|
|
{
|
|
mem[curradd]=0xF000;
|
|
mark[curradd]=0x8002;
|
|
curradd++;
|
|
mem[curradd]=0xF800;
|
|
mark[curradd]=0x8002;
|
|
curradd++;
|
|
continue;
|
|
}
|
|
if(is_const)
|
|
{
|
|
rd=rx-((curradd<<1)+4);
|
|
rm=0xFFFFFFFF<<22;
|
|
if(rd&rm)
|
|
{
|
|
if((rd&rm)!=rm)
|
|
{
|
|
printf("<%u> Error: Branch destination too far\n",line);
|
|
return(1);
|
|
}
|
|
}
|
|
//ignore even/odd address?
|
|
rn=(rd>>12)&0x7FF;
|
|
rm=(rd>>1)&0x7FF;
|
|
mem[curradd]=0xF000|rn;
|
|
mark[curradd]=0x8002;
|
|
curradd++;
|
|
mem[curradd]=0xF800|rm;
|
|
mark[curradd]=0x8002;
|
|
curradd++;
|
|
continue;
|
|
}
|
|
}
|
|
// bx -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"bx ",3)==0)
|
|
{
|
|
ra+=3;
|
|
//bx rm
|
|
ra=parse_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
mem[curradd]=0x4700|(rm<<3);
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// cmn -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"cmn ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//cmn rn,rm
|
|
ra=parse_two_regs(ra); if(ra==0) return(1);
|
|
mem[curradd]=0x42C0|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// cmp -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"cmp ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//cmp rn,#immed_8
|
|
//cmp rn,rm both low
|
|
//cmp rn,rm one or the other high
|
|
ra=parse_reg(ra); if(ra==0) return(1);
|
|
rn=rx;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
if(rn>7)
|
|
{
|
|
ra=parse_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
if(rm>7)
|
|
{
|
|
if(rm==15)
|
|
{
|
|
printf("<%u> Error: Not wise to use r15 in this way\n",line);
|
|
return(1);
|
|
}
|
|
//cmp rn,rm one or the other high
|
|
mem[curradd]=0x4500|((rn&8)<<4)|(rm<<3)|rn;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
//cmp rn,rm both low
|
|
mem[curradd]=0x4280|(rm<<3)|rn;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(newline[ra]=='#')
|
|
{
|
|
ra=parse_character(ra,'#'); if(ra==0) return(1);
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0xFF)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
//cmp rn,#immed_8
|
|
mem[curradd]=0x2800|(rn<<8)|rx;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
ra=parse_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
if(rm>7)
|
|
{
|
|
if(rm==15)
|
|
{
|
|
printf("<%u> Error: Not wise to use r15 in this way\n",line);
|
|
return(1);
|
|
}
|
|
//cmp rn,rm one or the other high
|
|
mem[curradd]=0x4500|((rn&8)<<4)|(rm<<3)|rn;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
//cmp rn,rm both low
|
|
mem[curradd]=0x4280|(rm<<3)|rn;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
|
|
}
|
|
}
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// eor -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"eor ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//eor rd,rm
|
|
ra=parse_two_regs(ra); if(ra==0) return(1);
|
|
mem[curradd]=0x4040|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// ldmia -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"ldmia ",6)==0)
|
|
{
|
|
ra+=6;
|
|
//ldmia rn!,{r0,r1,...,r7}
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rn=rx;
|
|
ra=parse_character(ra,'!'); if(ra==0) return(1);
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
ra=parse_character(ra,'{'); if(ra==0) return(1);
|
|
rm=0;
|
|
while(1)
|
|
{
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
if(rm&(1<<rx))
|
|
{
|
|
printf("<%u> Warning: You already specified r%u\n",line,rx);
|
|
}
|
|
rm|=(1<<rx);
|
|
if(newline[ra]=='}')
|
|
{
|
|
ra++;
|
|
break;
|
|
}
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
}
|
|
mem[curradd]=0xC800|(rn<<8)|rm;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// ldr -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"ldr ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//ldr rd,[rn,#immed_5*4]
|
|
//ldr rd,[rn,rm]
|
|
//ldr rd,[pc,#immed_8*4]
|
|
//ldr rd,[sp,#immed_8*4]
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rd=rx;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
if(newline[ra]=='[')
|
|
{
|
|
ra=parse_character(ra,'['); if(ra==0) return(1);
|
|
ra=parse_reg(ra); if(ra==0) return(1);
|
|
rn=rx;
|
|
if(rx>7)
|
|
{
|
|
if(rn==15)
|
|
{
|
|
}
|
|
else
|
|
if(rn==13)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
printf("<%u> Error: Invalid base register\n",line);
|
|
return(1);
|
|
}
|
|
if(newline[ra]==']')
|
|
{
|
|
rx=0;
|
|
}
|
|
else
|
|
{
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
ra=parse_character(ra,'#'); if(ra==0) return(1);
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0x3FC)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
}
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
//ldr rd,[pc,#immed_8*4]
|
|
//ldr rd,[sp,#immed_8*4]
|
|
mem[curradd]=0x0000|(rd<<8)|(rx>>2);
|
|
if(rn==15) mem[curradd]|=0x4800;
|
|
if(rn==13) mem[curradd]|=0x9800;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
if(newline[ra]==',')
|
|
{
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
if(newline[ra]=='#')
|
|
{
|
|
//ldr rd,[rn,#immed_5*4]
|
|
ra=parse_character(ra,'#'); if(ra==0) return(1);
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0x7C)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x6800|((rx>>2)<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
//ldr rd,[rn,rm]
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x5800|(rm<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//ldr rd,[rn] immed_5 = 0
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x6800|(0<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ra=parse_branch_label(ra); if(ra==0) return(1);
|
|
if(is_const)
|
|
{
|
|
printf("<%u> Error: not a label",line);
|
|
return(1);
|
|
}
|
|
mem[curradd]=0x4800|(rd<<8)|0;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// ldrb -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"ldrb ",5)==0)
|
|
{
|
|
ra+=5;
|
|
//ldrb rd,[rn,#immed_5]
|
|
//ldrb rd,[rn,rm]
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rd=rx;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
ra=parse_character(ra,'['); if(ra==0) return(1);
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rn=rx;
|
|
if(newline[ra]==',')
|
|
{
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
if(newline[ra]=='#')
|
|
{
|
|
//ldrb rd,[rn,#immed_5]
|
|
ra=parse_character(ra,'#'); if(ra==0) return(1);
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0x1F)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x7800|((rx>>0)<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
//ldrb rd,[rn,rm]
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x5C00|(rm<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//ldrb rd,[rn] immed_5 = 0
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x7800|(0<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// ldrh -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"ldrh ",5)==0)
|
|
{
|
|
ra+=5;
|
|
//ldrh rd,[rn,#immed_5]
|
|
//ldrh rd,[rn,rm]
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rd=rx;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
ra=parse_character(ra,'['); if(ra==0) return(1);
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rn=rx;
|
|
if(newline[ra]==',')
|
|
{
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
if(newline[ra]=='#')
|
|
{
|
|
//ldrh rd,[rn,#immed_5]
|
|
ra=parse_character(ra,'#'); if(ra==0) return(1);
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&(0x1F<<1))!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x8800|((rx>>1)<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
//ldrb rd,[rn,rm]
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x5A00|(rm<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//ldrh rd,[rn] immed_5 = 0
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x8800|(0<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// ldrsb -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"ldrsb ",6)==0)
|
|
{
|
|
ra+=6;
|
|
//ldrsb rd,[rn,rm]
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rd=rx;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
ra=parse_character(ra,'['); if(ra==0) return(1);
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rn=rx;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x5600|(rm<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// ldrsh -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"ldrsh ",6)==0)
|
|
{
|
|
ra+=6;
|
|
//ldrsh rd,[rn,rm]
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rd=rx;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
ra=parse_character(ra,'['); if(ra==0) return(1);
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rn=rx;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x5E00|(rm<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// lsl -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"lsl ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//lsl rd,rm,#immed_5
|
|
//lsl rd,rs
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rd=rx;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
if(newline[ra]==',')
|
|
{
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
ra=parse_character(ra,'#'); if(ra==0) return(1);
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx<1)||(rx>32))
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
rx&=0x1F;
|
|
//lsl rd,rm,#immed_5
|
|
mem[curradd]=0x0000|(rx<<6)|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
//lsl rd,rs
|
|
mem[curradd]=0x4080|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// lsr -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"lsr ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//lsr rd,rm,#immed_5
|
|
//lsr rd,rs
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rd=rx;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
if(newline[ra]==',')
|
|
{
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
ra=parse_character(ra,'#'); if(ra==0) return(1);
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx<1)||(rx>32))
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
rx&=0x1F;
|
|
//lsr rd,rm,#immed_5
|
|
mem[curradd]=0x0800|(rx<<6)|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
//lsr rd,rs
|
|
mem[curradd]=0x40C0|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// mov -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"mov ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//mov rd,#immed_8
|
|
//mov rd,rn low
|
|
//mov rd,rm one or both high
|
|
ra=parse_reg(ra); if(ra==0) return(1);
|
|
rd=rx;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
if(rd>7)
|
|
{
|
|
ra=parse_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
//mov rd,rm
|
|
mem[curradd]=0x4600|((rd&8)<<4)|(rm<<3)|(rd&7);
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
if(newline[ra]=='#')
|
|
{
|
|
ra=parse_character(ra,'#'); if(ra==0) return(1);
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0xFF)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
//mov rd,#immed_8
|
|
mem[curradd]=0x2000|(rd<<8)|rx;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
ra=parse_reg(ra); if(ra==0) return(1);
|
|
if(rx>7)
|
|
{
|
|
rm=rx;
|
|
//mov rd,rm
|
|
mem[curradd]=0x4600|((rd&8)<<4)|(rm<<3)|(rd&7);
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
rn=rx;
|
|
//mov rd,rn both low
|
|
mem[curradd]=0x1C00|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
}
|
|
}
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// mul -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"mul ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//mul rd,rm
|
|
ra=parse_two_regs(ra); if(ra==0) return(1);
|
|
if(rd==rm)
|
|
{
|
|
printf("<%u> Warning: using the same register might not work\n",line);
|
|
}
|
|
mem[curradd]=0x4340|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// mvn -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"mvn ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//mvn rd,rm
|
|
ra=parse_two_regs(ra); if(ra==0) return(1);
|
|
mem[curradd]=0x43C0|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// neg -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"neg ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//neg rd,rm
|
|
ra=parse_two_regs(ra); if(ra==0) return(1);
|
|
mem[curradd]=0x4240|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// orr -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"orr ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//orr rd,rm
|
|
ra=parse_two_regs(ra); if(ra==0) return(1);
|
|
mem[curradd]=0x4300|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// pop -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"pop ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//pop {r0,r1,...,r7}
|
|
ra=parse_character(ra,'{'); if(ra==0) return(1);
|
|
rm=0;
|
|
while(1)
|
|
{
|
|
ra=parse_reg(ra); if(ra==0) return(1);
|
|
if(rx>7)
|
|
{
|
|
if(rx!=15)
|
|
{
|
|
printf("<%u> Error: Invalid Register\n",line);
|
|
return(1);
|
|
}
|
|
rx=8;
|
|
}
|
|
rm|=(1<<rx);
|
|
if(newline[ra]=='}')
|
|
{
|
|
ra=parse_character(ra,'}'); if(ra==0) return(1);
|
|
break;
|
|
}
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
}
|
|
mem[curradd]=0xBC00|rm;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// push -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"push ",5)==0)
|
|
{
|
|
ra+=5;
|
|
//push {r0,r1,...,r7}
|
|
ra=parse_character(ra,'{'); if(ra==0) return(1);
|
|
rm=0;
|
|
while(1)
|
|
{
|
|
ra=parse_reg(ra); if(ra==0) return(1);
|
|
if(rx>7)
|
|
{
|
|
if(rx!=14)
|
|
{
|
|
printf("<%u> Error: Invalid Register\n",line);
|
|
return(1);
|
|
}
|
|
rx=8;
|
|
}
|
|
rm|=(1<<rx);
|
|
if(newline[ra]=='}')
|
|
{
|
|
ra=parse_character(ra,'}'); if(ra==0) return(1);
|
|
break;
|
|
}
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
}
|
|
mem[curradd]=0xB400|rm;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// ror -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"ror ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//ror rd,rm
|
|
ra=parse_two_regs(ra); if(ra==0) return(1);
|
|
mem[curradd]=0x41C0|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// sbc -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"sbc ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//ror rd,rm
|
|
ra=parse_two_regs(ra); if(ra==0) return(1);
|
|
mem[curradd]=0x4180|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// stmia -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"stmia ",6)==0)
|
|
{
|
|
ra+=6;
|
|
//stmia rn!,{r0,r1,...,r7}
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rn=rx;
|
|
ra=parse_character(ra,'!'); if(ra==0) return(1);
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
ra=parse_character(ra,'{'); if(ra==0) return(1);
|
|
rm=0;
|
|
while(1)
|
|
{
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
if(rm&(1<<rx))
|
|
{
|
|
printf("<%u> Warning: You already specified r%u\n",line,rx);
|
|
}
|
|
rm|=(1<<rx);
|
|
if(newline[ra]=='}')
|
|
{
|
|
ra++;
|
|
break;
|
|
}
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
}
|
|
mem[curradd]=0xC000|(rn<<8)|rm;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// str -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"str ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//str rd,[rn,#immed_5*4]
|
|
//str rd,[rn,rm]
|
|
//str rd,[sp,#immed_8*4]
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rd=rx;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
ra=parse_character(ra,'['); if(ra==0) return(1);
|
|
ra=parse_reg(ra); if(ra==0) return(1);
|
|
rn=rx;
|
|
if(rx>7)
|
|
{
|
|
if(rn!=13)
|
|
{
|
|
printf("<%u> Error: Invalid base register\n",line);
|
|
return(1);
|
|
}
|
|
if(newline[ra]==']')
|
|
{
|
|
rx=0;
|
|
}
|
|
else
|
|
{
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
ra=parse_character(ra,'#'); if(ra==0) return(1);
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0x3FC)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
}
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
//str rd,[sp,#immed_8*4]
|
|
mem[curradd]=0x9000|(rd<<8)|(rx>>2);
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
if(newline[ra]==',')
|
|
{
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
if(newline[ra]=='#')
|
|
{
|
|
//str rd,[rn,#immed_5*4]
|
|
ra=parse_character(ra,'#'); if(ra==0) return(1);
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0x7C)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x6000|((rx>>2)<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
//str rd,[rn,rm]
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x5000|(rm<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//str rd,[rn] immed_5 = 0
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x6000|(0<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
}
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// strb -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"strb ",5)==0)
|
|
{
|
|
ra+=5;
|
|
//strb rd,[rn,#immed_5]
|
|
//strb rd,[rn,rm]
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rd=rx;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
ra=parse_character(ra,'['); if(ra==0) return(1);
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rn=rx;
|
|
if(newline[ra]==',')
|
|
{
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
if(newline[ra]=='#')
|
|
{
|
|
//strb rd,[rn,#immed_5]
|
|
ra=parse_character(ra,'#'); if(ra==0) return(1);
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0x1F)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x7000|((rx>>0)<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
//strb rd,[rn,rm]
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x5400|(rm<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//strb rd,[rn] immed_5 = 0
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x7000|(0<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// strh -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"strh ",5)==0)
|
|
{
|
|
ra+=5;
|
|
//strh rd,[rn,#immed_5*2]
|
|
//strh rd,[rn,rm]
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rd=rx;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
ra=parse_character(ra,'['); if(ra==0) return(1);
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rn=rx;
|
|
if(newline[ra]==',')
|
|
{
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
if(newline[ra]=='#')
|
|
{
|
|
//strh rd,[rn,#immed_5*2]
|
|
ra=parse_character(ra,'#'); if(ra==0) return(1);
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&(0x1F<<1))!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x8000|((rx>>1)<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
//strh rd,[rn,rm]
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x5200|(rm<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//strh rd,[rn] immed_5 = 0
|
|
ra=parse_character(ra,']'); if(ra==0) return(1);
|
|
mem[curradd]=0x8000|(0<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// sub -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"sub ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//sub rd,rm,#immed_3
|
|
//sub rd,#immed_8
|
|
//sub rd,rn,rm
|
|
//sub sp,#immed_7*4
|
|
ra=parse_reg(ra); if(ra==0) return(1);
|
|
rd=rx;
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
if(rd>7)
|
|
{
|
|
//sub rdhi,
|
|
if((rd==13)&&(newline[ra]=='#'))
|
|
{
|
|
ra=parse_character(ra,'#'); if(ra==0) return(1);
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0x1FC)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
//sub sp,#immed_7*4
|
|
mem[curradd]=0xB080|(rx>>2);
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
printf("<%u> Error: Invalid rd register\n",line);
|
|
return(1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//sub rdlo,
|
|
if(newline[ra]=='#')
|
|
{
|
|
ra=parse_character(ra,'#'); if(ra==0) return(1);
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0xFF)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
//sub rd,#immed_8
|
|
mem[curradd]=0x3800|(rd<<8)|rx;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
//sub rdlo,r?
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
{
|
|
//sub rlo,rlo
|
|
ra=parse_comma(ra); if(ra==0) return(1);
|
|
if(newline[ra]=='#')
|
|
{
|
|
rn=rm;
|
|
ra=parse_character(ra,'#'); if(ra==0) return(1);
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0x7)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
//sub rd,rm,#immed_3
|
|
mem[curradd]=0x1E00|(rx<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
else
|
|
{
|
|
//sub rd,rn,rm
|
|
rn=rm;
|
|
ra=parse_low_reg(ra); if(ra==0) return(1);
|
|
rm=rx;
|
|
mem[curradd]=0x1A00|(rm<<6)|(rn<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// swi -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"swi ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//swi immed_8
|
|
ra=parse_immed(ra); if(ra==0) return(1);
|
|
if((rx&0xFF)!=rx)
|
|
{
|
|
printf("<%u> Error: Invalid immediate\n",line);
|
|
return(1);
|
|
}
|
|
mem[curradd]=0xDF00|rx;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
// tst -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"tst ",4)==0)
|
|
{
|
|
ra+=4;
|
|
//tst rn,rm
|
|
ra=parse_two_regs(ra); if(ra==0) return(1);
|
|
mem[curradd]=0x4200|(rm<<3)|rd;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
if(rest_of_line(ra)) return(1);
|
|
continue;
|
|
}
|
|
//-------------------------------------------------------------------
|
|
// pseudo instructions
|
|
//-------------------------------------------------------------------
|
|
// nop -----------------------------------------------------------
|
|
if(strncmp(&newline[ra],"nop",3)==0)
|
|
{
|
|
ra+=3;
|
|
if(rest_of_line(ra)) return(1);
|
|
//nop, encode mov r8,r8
|
|
mem[curradd]=0x46C0;
|
|
mark[curradd]=0x8000;
|
|
curradd++;
|
|
continue;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------
|
|
printf("<%u> Error: syntax error\n",line);
|
|
return(1);
|
|
}
|
|
|
|
mem[curradd]=0xE7FE; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0xE7FE; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0xE7FE; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0xE7FE; mark[curradd]=0x8000; curradd++;
|
|
|
|
return(0);
|
|
}
|
|
//-------------------------------------------------------------------
|
|
void dissassemble ( FILE *fp, unsigned int addr, unsigned short inst )
|
|
{
|
|
if((inst&0xFFC0)==0x4140)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
fprintf(fp,"adc r%u,r%u",rd,rm);
|
|
return;
|
|
}
|
|
if((inst&0xFE00)==0x1C00)
|
|
{
|
|
rd=inst&7;
|
|
rn=(inst>>3)&7;
|
|
rx=(inst>>6)&7;
|
|
fprintf(fp,"add r%u,r%u,#%u",rd,rn,rx);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0x3000)
|
|
{
|
|
rd=(inst>>8)&7;
|
|
rx=inst&0xFF;
|
|
fprintf(fp,"add r%u,#0x%02X ; %u",rd,rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xFE00)==0x1800)
|
|
{
|
|
rd=inst&7;
|
|
rn=(inst>>3)&7;
|
|
rm=(inst>>6)&7;
|
|
fprintf(fp,"add r%u,r%u,r%u",rd,rn,rm);
|
|
return;
|
|
}
|
|
if((inst&0xFF00)==0x4400)
|
|
{
|
|
rd=inst&7;
|
|
rd|=(inst>>4)&8;
|
|
rm=(inst>>3)&0xF;
|
|
fprintf(fp,"add r%u,r%u",rd,rm);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0xA000)
|
|
{
|
|
rd=(inst>>8)&7;
|
|
rx=inst&0xFF;
|
|
rx<<=2;
|
|
fprintf(fp,"add r%u,pc,#0x%03X ; %u",rd,rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0xA800)
|
|
{
|
|
rd=(inst>>8)&7;
|
|
rx=inst&0xFF;
|
|
rx<<=2;
|
|
fprintf(fp,"add r%u,sp,#0x%03X ; %u",rd,rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xFF80)==0xB000)
|
|
{
|
|
rx=inst&0x7F;
|
|
rx<<=2;
|
|
fprintf(fp,"add sp,#0x%03X ; %u",rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xFFC0)==0x4000)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
fprintf(fp,"and r%u,r%u",rd,rm);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0x1000)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
rx=(inst>>6)&0x1F;
|
|
if(rx==0) rx=32;
|
|
fprintf(fp,"asr r%u,r%u,#%u",rd,rm,rx);
|
|
return;
|
|
}
|
|
if((inst&0xFFC0)==0x4100)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
fprintf(fp,"asr r%u,r%u",rd,rm);
|
|
return;
|
|
}
|
|
if((inst&0xF000)==0xD000)
|
|
{
|
|
rx=inst&0xFF;
|
|
rm=(inst>>8)&0xF;
|
|
if(rx&0x80) rd=0xFFFFFFFF;
|
|
else rd=0x00000000;
|
|
rd<<=9;
|
|
rd|=rx<<1;
|
|
rd+=addr+4;
|
|
switch(rm)
|
|
{
|
|
case 0x0: fprintf(fp,"beq 0x%08X",rd); return;
|
|
case 0x1: fprintf(fp,"bne 0x%08X",rd); return;
|
|
case 0x2: fprintf(fp,"bcs 0x%08X",rd); return;
|
|
case 0x3: fprintf(fp,"bcc 0x%08X",rd); return;
|
|
case 0x4: fprintf(fp,"bmi 0x%08X",rd); return;
|
|
case 0x5: fprintf(fp,"bpl 0x%08X",rd); return;
|
|
case 0x6: fprintf(fp,"bvs 0x%08X",rd); return;
|
|
case 0x7: fprintf(fp,"bvc 0x%08X",rd); return;
|
|
case 0x8: fprintf(fp,"bhi 0x%08X",rd); return;
|
|
case 0x9: fprintf(fp,"bls 0x%08X",rd); return;
|
|
case 0xA: fprintf(fp,"bge 0x%08X",rd); return;
|
|
case 0xB: fprintf(fp,"blt 0x%08X",rd); return;
|
|
case 0xC: fprintf(fp,"bgt 0x%08X",rd); return;
|
|
case 0xD: fprintf(fp,"ble 0x%08X",rd); return;
|
|
case 0xE: fprintf(fp,"bal 0x%08X",rd); return;
|
|
//case 0xF:
|
|
}
|
|
}
|
|
if((inst&0xFFC0)==0x4380)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
fprintf(fp,"bic r%u,r%u",rd,rm);
|
|
return;
|
|
}
|
|
if((inst&0xFF00)==0xBE00)
|
|
{
|
|
rx=inst&0xFF;
|
|
fprintf(fp,"bkpt 0x%02X ; %u",rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xE000)==0xE000)
|
|
{
|
|
rx=inst&0x07FF;
|
|
rm=(inst>>11)&0x3;
|
|
switch(rm)
|
|
{
|
|
case 0:
|
|
{
|
|
if(rx&(1<<10)) rd=0xFFFFFFFF;
|
|
else rd=0x00000000;
|
|
rd<<=12;
|
|
rd|=rx<<1;
|
|
rd+=addr+4;
|
|
fprintf(fp,"b 0x%08X",rd);
|
|
return;
|
|
}
|
|
case 2:
|
|
{
|
|
fprintf(fp,";bl upper");
|
|
bl_upper=rx;
|
|
return;
|
|
}
|
|
case 3:
|
|
{
|
|
if(bl_upper&(1<<10)) rd=0xFFFFFFFF;
|
|
else rd=0x00000000;
|
|
rd<<=11;
|
|
rd|=bl_upper;
|
|
rd<<=12;
|
|
rd|=rx<<1;
|
|
rd+=addr+(4-2);
|
|
fprintf(fp,"bl 0x%08X",rd);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
if((inst&0xFF87)==0x4700)
|
|
{
|
|
rm=(inst>>3)&0xF;
|
|
fprintf(fp,"bx r%u",rm);
|
|
return;
|
|
}
|
|
if((inst&0xFFC0)==0x42C0)
|
|
{
|
|
rn=inst&7;
|
|
rm=(inst>>3)&7;
|
|
fprintf(fp,"cmn r%u,r%u",rn,rm);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0x2800)
|
|
{
|
|
rx=inst&0xFF;
|
|
rn=(inst>>8)&7;
|
|
fprintf(fp,"cmp r%u,#0x%02X ; %u",rn,rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xFFC0)==0x4280)
|
|
{
|
|
rn=inst&7;
|
|
rm=(inst>>3)&7;
|
|
fprintf(fp,"cmp r%u,r%u",rn,rm);
|
|
return;
|
|
}
|
|
if((inst&0xFF00)==0x4500)
|
|
{
|
|
rn=inst&7;
|
|
rn|=(inst>>4)&8;
|
|
rm=(inst>>3)&0xF;
|
|
fprintf(fp,"cmp r%u,r%u",rn,rm);
|
|
return;
|
|
}
|
|
if((inst&0xFFC0)==0x4040)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
fprintf(fp,"eor r%u,r%u",rd,rm);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0xC800)
|
|
{
|
|
rm=inst&0xFF;
|
|
rn=(inst>>8)&7;
|
|
fprintf(fp,"ldmia r%u!,{",rn);
|
|
for(rx=0;rx<8;rx++)
|
|
{
|
|
if(rm&(1<<rx))
|
|
{
|
|
fprintf(fp,"r%u",rx);
|
|
break;
|
|
}
|
|
}
|
|
for(rx++;rx<8;rx++)
|
|
{
|
|
if(rm&(1<<rx))
|
|
{
|
|
fprintf(fp,",r%u",rx);
|
|
}
|
|
}
|
|
fprintf(fp,"}");
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0x6800)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
rx=(inst>>6)&0x1F; rx<<=2;
|
|
if(rx==0) fprintf(fp,"ldr r%u,[r%u]",rd,rm);
|
|
else fprintf(fp,"ldr r%u,[r%u,#0x%02X] ; %u",rd,rm,rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xFE00)==0x5800)
|
|
{
|
|
rd=inst&7;
|
|
rn=(inst>>3)&7;
|
|
rm=(inst>>6)&7;
|
|
fprintf(fp,"ldr r%u,[r%u,r%u]",rd,rn,rm);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0x4800)
|
|
{
|
|
rx=inst&0xFF; rx<<=2;
|
|
rd=(inst>>8)&7;
|
|
if(rx&0x200) rm=0xFFFFFFFF<<10; else rm=0;
|
|
rm=addr+4+rx;
|
|
if(rx==0) fprintf(fp,"ldr r%u,[pc] ; [0x%04X]",rd,rm);
|
|
else fprintf(fp,"ldr r%u,[pc,#0x%03X] ; %u [0x%04X]",rd,rx,rx,rm);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0x9800)
|
|
{
|
|
rx=inst&0xFF; rx<<=2;
|
|
rd=(inst>>8)&7;
|
|
if(rx==0) fprintf(fp,"ldr r%u,[sp]",rd);
|
|
else fprintf(fp,"ldr r%u,[sp,#0x%03X] ; %u",rd,rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0x7800)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
rx=(inst>>6)&0x1F; rx<<=0;
|
|
if(rx==0) fprintf(fp,"ldrb r%u,[r%u]",rd,rm);
|
|
else fprintf(fp,"ldrb r%u,[r%u,#0x%02X] ; %u",rd,rm,rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xFE00)==0x5C00)
|
|
{
|
|
rd=inst&7;
|
|
rn=(inst>>3)&7;
|
|
rm=(inst>>6)&7;
|
|
fprintf(fp,"ldrb r%u,[r%u,r%u]",rd,rn,rm);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0x8800)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
rx=(inst>>6)&0x1F; rx<<=1;
|
|
if(rx==0) fprintf(fp,"ldrh r%u,[r%u]",rd,rm);
|
|
else fprintf(fp,"ldrh r%u,[r%u,#0x%02X] ; %u",rd,rm,rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xFE00)==0x5A00)
|
|
{
|
|
rd=inst&7;
|
|
rn=(inst>>3)&7;
|
|
rm=(inst>>6)&7;
|
|
fprintf(fp,"ldrh r%u,[r%u,r%u]",rd,rn,rm);
|
|
return;
|
|
}
|
|
if((inst&0xFE00)==0x5600)
|
|
{
|
|
rd=inst&7;
|
|
rn=(inst>>3)&7;
|
|
rm=(inst>>6)&7;
|
|
fprintf(fp,"ldrsb r%u,[r%u,r%u]",rd,rn,rm);
|
|
return;
|
|
}
|
|
if((inst&0xFE00)==0x5E00)
|
|
{
|
|
rd=inst&7;
|
|
rn=(inst>>3)&7;
|
|
rm=(inst>>6)&7;
|
|
fprintf(fp,"ldrsh r%u,[r%u,r%u]",rd,rn,rm);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0x0000)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
rx=(inst>>6)&0x1F; if(rx==0) rx=32;
|
|
fprintf(fp,"lsl r%u,r%u,#%u",rd,rm,rx);
|
|
return;
|
|
}
|
|
if((inst&0xFFC0)==0x4080)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
fprintf(fp,"lsl r%u,r%u",rd,rm);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0x0800)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
rx=(inst>>6)&0x1F; if(rx==0) rx=32;
|
|
fprintf(fp,"lsr r%u,r%u,#%u",rd,rm,rx);
|
|
return;
|
|
}
|
|
if((inst&0xFFC0)==0x40C0)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
fprintf(fp,"lsr r%u,r%u",rd,rm);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0x2000)
|
|
{
|
|
rx=inst&0xFF;
|
|
rd=(inst>>8)&7;
|
|
fprintf(fp,"mov r%u,#0x%02X ; %u",rd,rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xFFC0)==0x1C00)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
fprintf(fp,"mov r%u,r%u",rd,rm);
|
|
return;
|
|
}
|
|
if((inst&0xFF00)==0x4600)
|
|
{
|
|
rd=inst&7;
|
|
rd|=(inst>>4)&8;
|
|
rm=(inst>>3)&0xF;
|
|
fprintf(fp,"mov r%u,r%u",rd,rm);
|
|
return;
|
|
}
|
|
if((inst&0xFFC0)==0x4340)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
fprintf(fp,"mul r%u,r%u",rd,rm);
|
|
return;
|
|
}
|
|
if((inst&0xFFC0)==0x43C0)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
fprintf(fp,"mvn r%u,r%u",rd,rm);
|
|
return;
|
|
}
|
|
if((inst&0xFFC0)==0x4240)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
fprintf(fp,"neg r%u,r%u",rd,rm);
|
|
return;
|
|
}
|
|
if((inst&0xFFC0)==0x4300)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
fprintf(fp,"orr r%u,r%u",rd,rm);
|
|
return;
|
|
}
|
|
if((inst&0xFE00)==0xBC00)
|
|
{
|
|
rm=inst&0xFF;
|
|
rn=inst&0x100;
|
|
fprintf(fp,"pop {");
|
|
for(rx=0;rx<8;rx++)
|
|
{
|
|
if(rm&(1<<rx))
|
|
{
|
|
fprintf(fp,"r%u",rx);
|
|
break;
|
|
}
|
|
}
|
|
for(rx++;rx<8;rx++)
|
|
{
|
|
if(rm&(1<<rx))
|
|
{
|
|
fprintf(fp,",r%u",rx);
|
|
}
|
|
}
|
|
if(rn)
|
|
{
|
|
if(rm==0) fprintf(fp,"pc");
|
|
else fprintf(fp,",pc");
|
|
}
|
|
fprintf(fp,"}");
|
|
return;
|
|
}
|
|
if((inst&0xFE00)==0xB400)
|
|
{
|
|
rm=inst&0xFF;
|
|
rn=inst&0x100;
|
|
fprintf(fp,"push {");
|
|
for(rx=0;rx<8;rx++)
|
|
{
|
|
if(rm&(1<<rx))
|
|
{
|
|
fprintf(fp,"r%u",rx);
|
|
break;
|
|
}
|
|
}
|
|
for(rx++;rx<8;rx++)
|
|
{
|
|
if(rm&(1<<rx))
|
|
{
|
|
fprintf(fp,",r%u",rx);
|
|
}
|
|
}
|
|
if(rn)
|
|
{
|
|
if(rm==0) fprintf(fp,"lr");
|
|
else fprintf(fp,",lr");
|
|
}
|
|
fprintf(fp,"}");
|
|
return;
|
|
}
|
|
if((inst&0xFFC0)==0x41C0)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
fprintf(fp,"ror r%u,r%u",rd,rm);
|
|
return;
|
|
}
|
|
if((inst&0xFFC0)==0x4180)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
fprintf(fp,"sbc r%u,r%u",rd,rm);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0xC000)
|
|
{
|
|
rm=inst&0xFF;
|
|
rn=(inst>>8)&7;
|
|
fprintf(fp,"stmia r%u!,{",rn);
|
|
for(rx=0;rx<8;rx++)
|
|
{
|
|
if(rm&(1<<rx))
|
|
{
|
|
fprintf(fp,"r%u",rx);
|
|
break;
|
|
}
|
|
}
|
|
for(rx++;rx<8;rx++)
|
|
{
|
|
if(rm&(1<<rx))
|
|
{
|
|
fprintf(fp,",r%u",rx);
|
|
}
|
|
}
|
|
fprintf(fp,"}");
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0x6000)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
rx=(inst>>6)&0x1F; rx<<=2;
|
|
if(rx==0) fprintf(fp,"str r%u,[r%u]",rd,rm);
|
|
else fprintf(fp,"str r%u,[r%u,#0x%02X] ; %u",rd,rm,rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xFE00)==0x5000)
|
|
{
|
|
rd=inst&7;
|
|
rn=(inst>>3)&7;
|
|
rm=(inst>>6)&7;
|
|
fprintf(fp,"str r%u,[r%u,r%u]",rd,rn,rm);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0x9000)
|
|
{
|
|
rx=inst&0xFF; rx<<=2;
|
|
rd=(inst>>8)&7;
|
|
if(rx==0) fprintf(fp,"str r%u,[sp]",rd);
|
|
else fprintf(fp,"str r%u,[sp,#0x%03X] ; %u",rd,rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0x7000)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
rx=(inst>>6)&0x1F; rx<<=0;
|
|
if(rx==0) fprintf(fp,"strb r%u,[r%u]",rd,rm);
|
|
else fprintf(fp,"strb r%u,[r%u,#0x%02X] ; %u",rd,rm,rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xFE00)==0x5400)
|
|
{
|
|
rd=inst&7;
|
|
rn=(inst>>3)&7;
|
|
rm=(inst>>6)&7;
|
|
fprintf(fp,"strb r%u,[r%u,r%u]",rd,rn,rm);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0x8000)
|
|
{
|
|
rd=inst&7;
|
|
rm=(inst>>3)&7;
|
|
rx=(inst>>6)&0x1F; rx<<=1;
|
|
if(rx==0) fprintf(fp,"strh r%u,[r%u]",rd,rm);
|
|
else fprintf(fp,"strh r%u,[r%u,#0x%02X] ; %u",rd,rm,rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xFE00)==0x5200)
|
|
{
|
|
rd=inst&7;
|
|
rn=(inst>>3)&7;
|
|
rm=(inst>>6)&7;
|
|
fprintf(fp,"strh r%u,[r%u,r%u]",rd,rn,rm);
|
|
return;
|
|
}
|
|
if((inst&0xFE00)==0x1E00)
|
|
{
|
|
rd=inst&7;
|
|
rn=(inst>>3)&7;
|
|
rx=(inst>>6)&7;
|
|
fprintf(fp,"sub r%u,r%u,#%u",rd,rn,rx);
|
|
return;
|
|
}
|
|
if((inst&0xF800)==0x3800)
|
|
{
|
|
rd=(inst>>8)&7;
|
|
rx=inst&0xFF;
|
|
fprintf(fp,"sub r%u,#0x%02X ; %u",rd,rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xFE00)==0x1A00)
|
|
{
|
|
rd=inst&7;
|
|
rn=(inst>>3)&7;
|
|
rm=(inst>>6)&7;
|
|
fprintf(fp,"sub r%u,r%u,r%u",rd,rn,rm);
|
|
return;
|
|
}
|
|
if((inst&0xFF80)==0xB080)
|
|
{
|
|
rx=inst&0x7F;
|
|
rx<<=2;
|
|
fprintf(fp,"sub sp,#0x%03X ; %u",rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xFF00)==0xDF00)
|
|
{
|
|
rx=inst&0x7F;
|
|
fprintf(fp,"swi 0x%02X ; %u",rx,rx);
|
|
return;
|
|
}
|
|
if((inst&0xFFC0)==0x4200)
|
|
{
|
|
rn=inst&7;
|
|
rm=(inst>>3)&7;
|
|
fprintf(fp,"tst r%u,r%u",rn,rm);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fprintf(fp,"UNKNOWN");
|
|
}
|
|
//-------------------------------------------------------------------
|
|
int main ( int argc, char *argv[] )
|
|
{
|
|
int ret;
|
|
unsigned int ra;
|
|
unsigned int rb;
|
|
unsigned int inst;
|
|
unsigned int inst2;
|
|
unsigned int found_hexstring;
|
|
|
|
if(argc!=2)
|
|
{
|
|
printf("mas filename\n");
|
|
return(1);
|
|
}
|
|
|
|
fpin=fopen(argv[1],"rt");
|
|
if(fpin==NULL)
|
|
{
|
|
printf("Error opening file [%s]\n",argv[1]);
|
|
return(1);
|
|
}
|
|
ret=assemble();
|
|
fclose(fpin);
|
|
if(ret)
|
|
{
|
|
printf("failed %u\n",line);
|
|
return(1);
|
|
}
|
|
|
|
found_hexstring=0;
|
|
for(ra=0;ra<nlabs;ra++)
|
|
{
|
|
printf("label%04u: [0x%08X] [%s] %u\n",ra,lab_struct[ra].addr,lab_struct[ra].name,lab_struct[ra].type);
|
|
if(lab_struct[ra].type==1)
|
|
{
|
|
if(strcmp(lab_struct[ra].name,"hexstring")==0)
|
|
{
|
|
found_hexstring=1;
|
|
}
|
|
}
|
|
if(found_hexstring) break;
|
|
}
|
|
if(found_hexstring)
|
|
{
|
|
if(curradd&1)
|
|
{
|
|
mem[curradd]=0x0000;
|
|
mark[curradd]|=0x9000;
|
|
curradd++;
|
|
}
|
|
strcpy(lab_struct[nlabs].name,"hexstring");
|
|
lab_struct[nlabs].addr=curradd<<1;
|
|
lab_struct[nlabs].line=0;
|
|
lab_struct[nlabs].type=0;
|
|
nlabs++;
|
|
mem[curradd]=0xB5FE; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x4913; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x4e13; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x2420; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x270f; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x2220; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x3c04; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x1c03; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x40e3; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x403b; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x1c1d; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x3530; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x2b09; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0xd900; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x3507; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x680b; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x421a; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0xd0fc; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x6035; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x2c00; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0xd1f0; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x4909; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x2220; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x680b; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x421a; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0xd0fc; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x4b07; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x220d; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x4905; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x601a; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x2220; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x680b; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x421a; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0xd0fc; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x4b03; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x220a; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x601a; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0xbcfe; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0xbc01; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x4700; mark[curradd]=0x8000; curradd++;
|
|
mem[curradd]=0x5054; mark[curradd]=0x9000; curradd++;
|
|
mem[curradd]=0x2021; mark[curradd]=0x9000; curradd++;
|
|
mem[curradd]=0x5040; mark[curradd]=0x9000; curradd++;
|
|
mem[curradd]=0x2021; mark[curradd]=0x9000; curradd++;
|
|
}
|
|
|
|
|
|
for(ra=0;ra<nlabs;ra++)
|
|
{
|
|
printf("label%04u: [0x%08X] [%s] %u\n",ra,lab_struct[ra].addr,lab_struct[ra].name,lab_struct[ra].type);
|
|
if(lab_struct[ra].type==1)
|
|
{
|
|
for(rb=0;rb<nlabs;rb++)
|
|
{
|
|
if(lab_struct[rb].type) continue;
|
|
if(strcmp(lab_struct[ra].name,lab_struct[rb].name)==0)
|
|
{
|
|
rx=lab_struct[rb].addr;
|
|
inst=mem[lab_struct[ra].addr];
|
|
line=lab_struct[ra].line;
|
|
if((inst&0xF800)==0x0000)
|
|
{
|
|
//no this really isnt an lsl, using this to
|
|
//mark an address
|
|
inst2=mem[lab_struct[ra].addr+1];
|
|
if((inst2&0xF800)!=0x0000)
|
|
{
|
|
printf("<%u> Error: expecting a .word\n",line);
|
|
return(1);
|
|
}
|
|
inst=rx&0xFFFF;
|
|
inst2=(rx>>16)&0xFFFF;
|
|
mem[lab_struct[ra].addr+1]=inst2;
|
|
lab_struct[ra].type++;
|
|
}
|
|
if((inst&0xF800)==0x4800)
|
|
{
|
|
//ldr rd,[pc,#immed_8]
|
|
if(lab_struct[ra].addr&1)
|
|
{
|
|
rd=rx-((lab_struct[ra].addr<<1)+2);
|
|
}
|
|
else
|
|
{
|
|
rd=rx-((lab_struct[ra].addr<<1)+4);
|
|
}
|
|
rm=0xFFFFFFFF;
|
|
rm<<=8; //I think this is wrong by two or four
|
|
if(rd&rm)
|
|
{
|
|
if((rd&rm)!=rm)
|
|
{
|
|
printf("<%u> Error: Load destination too far\n",line);
|
|
return(1);
|
|
}
|
|
}
|
|
inst|=(rd>>2)&0x7FF;
|
|
lab_struct[ra].type++;
|
|
}
|
|
if((inst&0xF000)==0xD000)
|
|
{
|
|
//bcond signed_immed_8
|
|
rd=rx-((lab_struct[ra].addr<<1)+4);
|
|
rm=0xFFFFFFFF;
|
|
rm<<=8;
|
|
if(rd&rm)
|
|
{
|
|
if((rd&rm)!=rm)
|
|
{
|
|
printf("<%u> Error: Branch destination too far\n",line);
|
|
return(1);
|
|
}
|
|
}
|
|
inst|=(rd>>1)&0xFF;
|
|
lab_struct[ra].type++;
|
|
}
|
|
if((inst&0xF000)==0xE000)
|
|
{
|
|
//b signed_immed_11
|
|
rd=rx-((lab_struct[ra].addr<<1)+4);
|
|
rm=0xFFFFFFFF;
|
|
rm<<=11;
|
|
if(rd&rm)
|
|
{
|
|
if((rd&rm)!=rm)
|
|
{
|
|
printf("<%u> Error: Branch destination too far\n",line);
|
|
return(1);
|
|
}
|
|
}
|
|
inst|=(rd>>1)&0x7FF;
|
|
lab_struct[ra].type++;
|
|
}
|
|
if((inst&0xF800)==0xF000)
|
|
{
|
|
inst2=mem[lab_struct[ra].addr+1];
|
|
if((inst2&0xF800)!=0xF800)
|
|
{
|
|
printf("<%u> Error: bl should be a pair of instructions (internal error)\n",line);
|
|
return(1);
|
|
}
|
|
rd=rx-((lab_struct[ra].addr<<1)+4);
|
|
rm=0xFFFFFFFF;
|
|
rm<<=22;
|
|
if(rd&rm)
|
|
{
|
|
if((rd&rm)!=rm)
|
|
{
|
|
printf("<%u> Error: Branch destination too far\n",line);
|
|
}
|
|
}
|
|
inst|=(rd>>12)&0x7FF;
|
|
inst2|=(rd>>1)&0x7FF;
|
|
mem[lab_struct[ra].addr+1]=inst2;
|
|
lab_struct[ra].type++;
|
|
}
|
|
if(lab_struct[ra].type==1)
|
|
{
|
|
printf("<%u> Error: internal error, unknown instruction 0x%08X\n",lab_struct[ra].line,inst);
|
|
return(1);
|
|
}
|
|
mem[lab_struct[ra].addr]=inst;
|
|
break;
|
|
}
|
|
}
|
|
if(rb<nlabs) ; else
|
|
{
|
|
printf("<%u> Error: unresolved label\n",lab_struct[ra].line);
|
|
return(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
sprintf(newline,"%s.hex",argv[1]);
|
|
fpout=fopen(newline,"wt");
|
|
if(fpout==NULL)
|
|
{
|
|
printf("Error creating file [%s]\n",newline);
|
|
return(1);
|
|
}
|
|
|
|
for(ra=0;ra<=ADDMASK;ra++)
|
|
{
|
|
curradd=(ra<<1);
|
|
if(mark[ra]&0x8000)
|
|
{
|
|
printf("0x%08X: 0x%04X ",curradd,mem[ra]);
|
|
if(mark[ra]&0x1000)
|
|
{
|
|
fprintf(stdout,"data");
|
|
}
|
|
else
|
|
{
|
|
dissassemble(stdout,curradd,mem[ra]);
|
|
}
|
|
printf("\n");
|
|
|
|
//rb=0x04;
|
|
//rb+=(curradd>>8)&0xFF;
|
|
//rb+=(curradd>>0)&0xFF;
|
|
//rb+=0x00;
|
|
//rb+=(mem[ra]>>24)&0xFF;
|
|
//rb+=(mem[ra]>>16)&0xFF;
|
|
//rb+=(mem[ra]>> 8)&0xFF;
|
|
//rb+=(mem[ra]>> 0)&0xFF;
|
|
//rb=(-rb)&0xFF;
|
|
//fprintf(fpout,":%02X%04X%02X%08X%02X\n",0x04,curradd&0xFFFF,0x00,mem[ra],rb);
|
|
}
|
|
}
|
|
|
|
fclose(fpout);
|
|
|
|
|
|
sprintf(newline,"%s.s",argv[1]);
|
|
fpout=fopen(newline,"wt");
|
|
if(fpout==NULL)
|
|
{
|
|
printf("Error creating file [%s]\n",newline);
|
|
return(1);
|
|
}
|
|
for(ra=0;ra<=ADDMASK;ra++)
|
|
{
|
|
curradd=(ra<<1);
|
|
if(mark[ra]&0x8000)
|
|
{
|
|
//fprintf(fpout,"0x%08X: 0x%04X ",curradd,mem[ra]);
|
|
if(mark[ra]&0x1000)
|
|
{
|
|
fprintf(fpout,"data");
|
|
}
|
|
else
|
|
{
|
|
dissassemble(fpout,curradd,mem[ra]);
|
|
}
|
|
fprintf(fpout,"\n");
|
|
}
|
|
}
|
|
fclose(fpout);
|
|
|
|
sprintf(newline,"%s.diss",argv[1]);
|
|
fpout=fopen(newline,"wt");
|
|
if(fpout==NULL)
|
|
{
|
|
printf("Error creating file [%s]\n",newline);
|
|
return(1);
|
|
}
|
|
for(ra=0;ra<=ADDMASK;ra++)
|
|
{
|
|
curradd=(ra<<1);
|
|
if(mark[ra]&0x8000)
|
|
{
|
|
fprintf(fpout,"0x%08X: 0x%04X ",curradd,mem[ra]);
|
|
if(mark[ra]&0x1000)
|
|
{
|
|
fprintf(fpout,"data");
|
|
}
|
|
else
|
|
{
|
|
dissassemble(fpout,curradd,mem[ra]);
|
|
}
|
|
fprintf(fpout,"\n");
|
|
}
|
|
}
|
|
fclose(fpout);
|
|
|
|
rb=0;
|
|
for(ra=0;ra<=ADDMASK;ra++)
|
|
{
|
|
if(mark[ra]&0x8000) rb=ra;
|
|
}
|
|
sprintf(newline,"%s.bin",argv[1]);
|
|
fpout=fopen(newline,"wb");
|
|
if(fpout==NULL)
|
|
{
|
|
printf("Error creating file [%s]\n",newline);
|
|
return(1);
|
|
}
|
|
fwrite(mem,2,rb+1,fpout);
|
|
fclose(fpout);
|
|
|
|
return(0);
|
|
}
|
|
//-------------------------------------------------------------------
|
|
//-------------------------------------------------------------------
|
|
//-------------------------------------------------------------------
|
|
|
|
|