📄 pcasm5b.c
字号:
void find_mnemonic(FILE *fp_opcode, \
unsigned char *line_buffer, \
unsigned int length, \
unsigned int mnemonic_lines, \
unsigned int *result_buffer,
FILE *list_fp)
{
int i,j,k,t,p, reg, mnem_char, theword_len, qq;
int status;
char mnemonic[BL], mode, theword[BL];
unsigned char *ptr, c, label_found;
unsigned int opcode,match, immed;
unsigned char immed_result[3];
rewind(fp_opcode); // rewind opcode.dat file pointer to top
status=0;
// get next word from current line
ptr=0;
theword_len=find_word(line_buffer,&ptr,length,theword);
// if current sourece code line contains 'end', we've reached end of source
// code file, so exit out
if((theword[0]=='E'&&theword[1]=='N'&&theword[2]=='D') || \
(theword[0]=='e'&&theword[1]=='n'&&theword[2]=='d') )
return;
// does this word cotain ':' ?, if so, we're looking at a
// label and we want to skip over to next word
for(i=0,label_found=0;i<theword_len;i++)
if((c=theword[i])==':')
label_found=1;
if (label_found==1) // if label found, skip to next word
theword_len=find_word(line_buffer,&ptr,length,theword);
if(theword_len==0) // if this new word is empty, no opcode here, exit
{ result_buffer[0]=1 | (label_found<<7);
return;
}
for(j=0;j<mnemonic_lines;j++)
{
// clear mnemonic buffer
for(k=0;k<BL;k++) mnemonic[k]=NULL;
// load next mnemonic i.e. next line from opcode.dat
fscanf(fp_opcode,"%s %d %x %c",mnemonic,&mnem_char,&opcode,&mode);
// if mnemonic I read from opcode.dat is 'END' then entire table
// has been search, so exit
if ( (mnemonic[0]=="E")&&(mnemonic[1]=="N")&(mnemonic[2]=="D") )
return;
// scan through the line_buffer looking for matches
for(i=0,t=0,match=0;i<BL;i++)
{ if((theword[t]==mnemonic[i]) || ((theword[t]-0x20)==mnemonic[i]))
t++;
else t=0;
}
// *** Matching opcode found ***
if (t!=0)
{ match=1;
break; // break out of the for loop
}
}
if(match==1)
{
/*
** UNARY OPCODE
*/
if( (match==1) && (mode=='U') )
{
result_buffer[0] = 0 | (label_found<<7); // opcode found and no error
result_buffer[1] = 1;
result_buffer[2] = opcode;
fprintf(list_fp,"** unary opcode found\n");
//rintf(list_fp,"\t %x\n",result_buffer[2]);
return;
}
/*
** REGISTER DIRECT OPCODE, search for valid register
*/
if( (match==1) && (mode=='R') )
{
fprintf(list_fp,"** register direct opcode found ");
// scan through the rest of line looking for valid reg name
// get next word.. hopeflly it is a valid reg name
theword_len=find_word(line_buffer,&ptr,length,theword);
reg=find_reg(fp_opcode,mnemonic_lines,theword);
#ifdef debug
if (reg==-1) fprintf(list_fp,"** error reg not found\n");
else fprintf(list_fp,"** reg found\n");
#endif
if(reg==-1) // valid opcode found, but there was error
result_buffer[0] = 2 | (label_found<<7);
else
{ result_buffer[0] = 0 | (label_found<<7);
result_buffer[1] = 1;
result_buffer[2] = (opcode & 0xf8) | (reg & 0x07);
i = (unsigned int) *(result_buffer+1); // debug purpose
}
//fprintf(list_fp,"\t %x\n",result_buffer[2]);
return;
}
/*
** (acc) IMMEDIATE OPCODE, search for valid data
*/
if( (match==1) && (mode=='I') )
{
fprintf(list_fp,"** (acc) immediate opcode found ");
// scan through the line seraching for valid immediate value
// get next word.. hopeflly it is a valid immediate
theword_len=find_word(line_buffer,&ptr,length,theword);
find_immed(theword,theword_len,MODE_BYTE,immed_result);
if(immed_result[0]==0)
{
fprintf(list_fp," immed found \n");
result_buffer[0] =0 | (label_found<<7);
result_buffer[1] =2;
result_buffer[2] =opcode;
result_buffer[3] =immed_result[1];
//fprintf(list_fp,"\t %x %x\n",result_buffer[2],result_buffer[3]);
return;
}
else
{
fprintf(list_fp," err with immed \n");
result_buffer[0] =2|(label_found<<7);
return;
}
}
/*
** (reg) IMMEDIATE OPCODE, search for valid reg
** search for valid data
**/
if( (match==1) && (mode=='A') )
{
fprintf(list_fp,"** (reg) immediate opcode found ");
// scan through the rest of the line to find valid reg
theword_len=find_word(line_buffer,&ptr,length,theword);
reg=find_reg(fp_opcode,mnemonic_lines,theword);
#ifdef debug
if (reg==-1) fprintf(list_fp,"** error reg not found\n");
else fprintf(list_fp,"** reg found ");
#endif
if(reg==-1)
{ result_buffer[0] = 2 | (label_found<<7); //opcode has invalid register
return;
}
// scan through the line seraching for valid immediate value
theword_len=find_word(line_buffer,&ptr,length,theword);
find_immed(theword,theword_len,MODE_BYTE,immed_result);
if(immed_result[0]==0)
{
fprintf(list_fp," immed found \n");
result_buffer[0] =0 | (label_found<<7);
result_buffer[1] =2;
result_buffer[2] =(opcode & 0xc7) | ( (reg & 0x07) <<3 );
result_buffer[3] =immed_result[1];
//fprintf(list_fp,"\t %x %x\n",result_buffer[2],result_buffer[3]);
return;
}
else
{
fprintf(list_fp," err with immed \n");
result_buffer[0] =2 | (label_found<<7); // error with immediate value
return;
}
}
/*
** (memory) DIRECT OPCODES, serach for valid reg
** , search for valid addx
**
*/
if( (match==1) && (mode=='D') )
{
fprintf(list_fp,"** (mem) direct opcode found ");
// scan through the rest of the line to find valid reg
theword_len=find_word(line_buffer,&ptr,length,theword);
reg=find_reg(fp_opcode,mnemonic_lines,theword);
#ifdef debug
if (reg==-1) fprintf(list_fp,"** error reg not found\n");
else fprintf(list_fp,"** reg found ");
#endif
if(reg==-1)
{ result_buffer[0] = 2 | (label_found<<7); //opcode has invalid register
return;
}
// scan through the line seraching for valid addx
theword_len=find_word(line_buffer,&ptr,length,theword);
find_immed(theword,theword_len,MODE_ADDX,immed_result);
if(immed_result[0]==0)
{
fprintf(list_fp," addx found \n");
result_buffer[0] =0 | (label_found<<7);
result_buffer[1] =3;
result_buffer[2] =(opcode & 0xF8) | (reg & 0x07);
result_buffer[3] =immed_result[1];
result_buffer[4] =immed_result[2];
//fprintf(list_fp,"\t %x %x %x\n",result_buffer[2],result_buffer[3], \
result_buffer[4]);
return;
}
else
{
fprintf(list_fp," err with addx \n");
result_buffer[0] =2|(label_found<<7); // error with addx value
return;
}
}
/*
** BRANCHING OPCODE, search for valid address
**
*/
if( (match==1) && (mode=='B') )
{
fprintf(list_fp,"** branching opcode found ");
// get next word
theword_len=find_word(line_buffer,&ptr,length,theword);
// if this word does not contain '#' then, it is considered
// as a label
for(i=0,qq=0;i<theword_len;i++)
if((c=theword[i])=='#')
qq=1;
if(qq==0)
{
fprintf(list_fp,"label found \n");
result_buffer[0] =3|(label_found<<7); //branching opcode w/ label found
result_buffer[1] =3;
result_buffer[2] =opcode;
result_buffer[3] =0;
result_buffer[4] =0;
result_buffer[5] =theword_len; // lenght of label
for(i=0;i<theword_len;i++) // on the rest of result_buffer
{ result_buffer[i+6] = theword[i]; // copy the label
c=(unsigned char)result_buffer[i+6]; // debug
}
}
else
{
find_immed(theword,theword_len,MODE_ADDX,immed_result);
if(immed_result[0]==0)
{
fprintf(list_fp," addx found \n");
result_buffer[0] =0|(label_found<<7);
result_buffer[1] =3;
result_buffer[2] =opcode;
result_buffer[3] =immed_result[1];
result_buffer[4] =immed_result[2];
}
}
//fprintf(list_fp,"\t %x %x %x\n",result_buffer[2],result_buffer[3], \
result_buffer[4]);
return;
}
// fprintf(list_fp,"\n");
}
else
{
fprintf(list_fp,"no match\n");
result_buffer[0]=1|(label_found<<7); // no opcode found, but no error
}
// clear mnemonic buffer
for(k=0;k<7;k++)
mnemonic[k]=NULL;
}
/*
** int find_reg( )
**
** search through the "line_buffer" looking for a
** valid register.
**
** input:
** FILE *fp_opcode file pointer to opcode.dat
** unsiigned int mnemonic_line line count from opcode.dat
** unsigned char *theword pointer to word buffer
**
** output:
** -1 : no match found
** 0 : found 'ACC' or 'acc'
** 1 : found 'AX' or 'ax'
** 2 : found 'BX' or 'bx'
** 4 : found 'FLAG' or 'flag'
** 5 : found 'PORT' or 'port'
**
**
**
*/
int find_reg(FILE *fp_opcode, \
unsigned int mnemonic_line, \
unsigned char *theword )
{
FILE *fp_opcode_save;
int t,i,j,k,match,opcode,mnem_char;
unsigned char mnemonic[BL],mode;
rewind(fp_opcode);
for(i=0,match=0;i<mnemonic_line;i++)
{
// clear mnemonic buffer
for(k=0;k<BL;k++) mnemonic[k]=NULL;
// load next mnemonic i.e. next line from opcode.dat
fscanf(fp_opcode,"%s %d %x %c",mnemonic,&mnem_char,&opcode,&mode);
// if mnemonic I read from opcode.dat is 'END' then entire table
// has been search, so break out of loop
if ( (mnemonic[0]=='E')&&(mnemonic[1]=='N')&&(mnemonic[2]=='D') )
break;
// scan through the line_buffer looking for matches
for(i=0,t=0,match=0;i<BL;i++)
{ if((theword[t]==mnemonic[i]) || ((theword[t]-0x20)==mnemonic[i]))
t++;
else t=0;
}
// if match found, immediately break out of the for loop
if(t!=0)
break;
}
if(t!=0) return(opcode);
else return(-1);
}
/*
** void find_immed
**
** see if the literal characters in 'theword' buffer is a valid
** number representation, if so convert it to binary and
** exit
**
** inputs: unsigned char *theword buffer containing literal chars
** unsigned int theword_len length of the literal chars
** unsigned int mode mode=0
** expecting 8 bit data
** expecting 12 bit addx
** unsigned char immed_result pointer to result array
**
**
** output: int *immed_result result array
**
** immed_result[0] status
** 0 succesful
** 1 out of range
** 2 not valid number,
** missing # or
** missing radix or
** has non-numerical chars
** immed_Result[1-2] data: lsb, msb
**
*/
void find_immed(unsigned char *theword, \
unsigned int theword_len, \
unsigned int mode, \
unsigned char *immed_result )
{
int i,j,k,found_radix,found_num;
unsigned char c;
unsigned int temp,x,y;
// See if the literal number is correct
// see if the number sign and radix are present
if( theword[0]!='#'|| \
(theword[theword_len-1]!='h' && theword[theword_len-1]!='H') )
{ immed_result[0] = 2;
return;
}
// see if there are bogus characters != (0-9, a-f)
for(i=1;i<(theword_len-1);i++)
{ c=theword[i];
if( (c<'0') || ((c>'9')&&(c<'A')) || ((c>'F')&&(c<'a')) || \
(c>'f') )
{ immed_result[0]=2;
return;
}
}
// convert the ASCII to numbers
for(i=1;i<(theword_len-1);i++)
{ c=theword[i];
if( (c>='0')&&(c<='9') )
theword[i]=(unsigned int)theword[i]-0x30;
else if( (c>='A')&&(c<='F') )
theword[i]=theword[i]-0x37;
else if( (c>='a')&&(c<='f') )
theword[i]=theword[i]-0x57;
x=theword[i];
}
// check for overrange
temp=0;
for(i=1;i<(theword_len-1);i++)
{// temp += theword[i] * pow(16,(theword_len-2-i)) ;
x=theword[i];
y=theword_len;
y=y-2;
y=y-i;
y=pow(16,y);
x=x * y;
temp=temp+x;
}
if( ((mode==0)&&(temp>(pow(2,8)-1)))||((mode==1)&&(temp>(pow(2,12)-1))) )
{ immed_result[0] = 1;
return;
}
// if no more errors let's do some work
if(mode==0)
{ immed_result[0] = 0;
immed_result[1] = temp;
return;
}
if(mode==1)
{ immed_result[0] = 0;
immed_result[1] = temp%256;
immed_result[2] = temp/256;
x=immed_result[1];
y=immed_result[2];
return;
}
}
/*
** void find_word( )
**
** given a buffer, extract a "word" surrounded by delimeters
** delimeters can be commas, space, tabs or newline
** 'theword' buffer is converted to all caps.
**
** input: unsigned char *buffer pointer to the buffer, must be
** null terminated
** unsigned int *buff_ptr starting location in the buffer
** unsigned int buffer_len length of the buffer
** unsigned char *word pointer to the word buffer where
** the found word will be dumped
**
** output: o *buff_ptr will be updated to where it last found the word
** delimiter
** o buffer 'word' will have the NULL terminated word
** the 'word' buffer will be empty if there was no delimeter
** in the buffer given to scan or if the given buffer has
** length of zero
**
**
*/
int find_word( unsigned char *buffer, \
unsigned int *buff_ptr, \
unsigned int buffer_len, \
unsigned char *theword )
{
int i,t,ena;
unsigned char c,c2;
// clear 'theword' buffer
for(i=0;i<BL;i++)
*(theword+i)=NULL;
// advance the buffer pointer until no delimiter is found
i=0; c=buffer[*buff_ptr+i];
while((c==' ')||(c=='\t')||(c==CR)||(c==','))
{ i++;
c=buffer[*buff_ptr+i];
}
*buff_ptr=*buff_ptr+i;
// go through the line_buffer and extract a word
// rules: start when beginning of buffer or blank or tab is found
// end when end of buffer or blank or tab is found
i=0;
while((c!=NULL)&&(c!=' ')&&(c!='\t')&&(c!=NL)&&(c!=',')&&((*buff_ptr+i)!=buffer_len))
{ c=buffer[*buff_ptr+i];
theword[i]=c;
i++;
}
if((*buff_ptr+i)==buffer_len)
{ *buff_ptr=*buff_ptr+i;
theword[i]=NULL;
return(i);
}
else
{ *buff_ptr=*buff_ptr+i-1;
theword[i-1]=NULL;
return(i-1);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -