mirror of
https://github.com/alsa-project/alsa-tools.git
synced 2026-02-21 01:40:16 -05:00
Added as10k1 tool (EMU10K1 FX8010 DSP assembler).
This commit is contained in:
parent
a4569af2bb
commit
f2d80b5b5d
28 changed files with 3523 additions and 0 deletions
463
as10k1/parse.c
Normal file
463
as10k1/parse.c
Normal file
|
|
@ -0,0 +1,463 @@
|
|||
/***************************************************************************
|
||||
parse.c - parses each line, stores in temp space
|
||||
-------------------
|
||||
Date : May 23 2000
|
||||
Copyright : (C) 2000 by Daniel Bertrand
|
||||
Email : d.bertrand@ieee.ca
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include<string.h>
|
||||
#include<stdio.h>
|
||||
#include"types.h"
|
||||
#include"parse.h"
|
||||
#include"proto.h"
|
||||
|
||||
/*
|
||||
This function parses the asm file calling appropriate functions to blow up macros, include files,
|
||||
define constants, keep track of equates, and handling assembler directives.
|
||||
|
||||
This function is called on a line by line basis.
|
||||
|
||||
normally returns value 0 except when "end" directive is encountered in which case it returns 1,
|
||||
the "endm" directive which return -1, or the "endfor" deirective which returns -2
|
||||
*/
|
||||
|
||||
extern char type_strings[GPR_TYPE_EQUATE+1][20];
|
||||
extern int dbg_opt;
|
||||
extern char *listing,listtemp[60];
|
||||
extern FILE *listfile;
|
||||
|
||||
int parse( char line_string[MAX_LINE_LENGTH], char *line)
|
||||
{
|
||||
int tmp,i,arg[4];
|
||||
static int defmacro=0; //set to 0 unless we're in a macro definition
|
||||
int op_num;
|
||||
char *leading_symbol=NULL, *op_name_ptr,*tmpc;
|
||||
extern char patch_name[PATCH_NAME_SIZE];
|
||||
extern int ds_addr,ip,tram_addr,tram_delay_count,tram_table_count;
|
||||
extern unsigned int macro_depth;
|
||||
|
||||
struct sym *sym;
|
||||
struct control *control;
|
||||
|
||||
extern struct delay tram_delay[MAX_TANK_ADDR];
|
||||
extern struct lookup tram_lookup[MAX_TANK_ADDR];
|
||||
|
||||
|
||||
if( line_string[0]=='\0' || line_string[0]==';'||line_string[0]=='%'||line_string[0]=='*')
|
||||
return(0);
|
||||
//remove anything after a ; if one exist
|
||||
tmpc=line_string;
|
||||
while( *tmpc != ';' &&*tmpc != '\0')
|
||||
tmpc++;
|
||||
*tmpc='\0';
|
||||
|
||||
//check for a leading symbol
|
||||
if( line_string[0] != ' ' && line_string[0] != '\t'){
|
||||
|
||||
if(strlen(leading_symbol=strtok(line_string,": \t\n"))>MAX_SYM_LEN ){
|
||||
printf("symbol \"%s\" is more than %d characters long\n",leading_symbol,MAX_SYM_LEN );
|
||||
as_exit("Parse error");
|
||||
}
|
||||
|
||||
//address ref for skip command:
|
||||
if(*leading_symbol=='.'){
|
||||
if( issymbol(leading_symbol,&sym)!=-1)
|
||||
(sym->data.value)+=ip-1;
|
||||
}
|
||||
op_name_ptr=strtok(NULL, " \t\n");
|
||||
}else{
|
||||
op_name_ptr=strtok(line_string, " \t\n");
|
||||
}
|
||||
|
||||
if(op_name_ptr==NULL)
|
||||
return(0);
|
||||
|
||||
|
||||
//check if it a macro:
|
||||
if((tmp=ismacro(op_name_ptr)) != -1 ){
|
||||
if(defmacro==0)
|
||||
macro_expand(tmp,strtok(NULL,""));
|
||||
return(0);
|
||||
}
|
||||
|
||||
if( (op_num=op_decode(op_name_ptr))==-1) {
|
||||
printf("**Parse Error with op code field \"%s\"\n",op_name_ptr);
|
||||
as_exit("Parse Error: Bad neumonic");
|
||||
}
|
||||
|
||||
//check to see if we're defining a macro
|
||||
if(leading_symbol!=NULL && defmacro!=0 && op_num!=CON && op_num!=CONSTANT)
|
||||
as_exit("Parse error: Cannot define symbols inside of a macro");
|
||||
|
||||
|
||||
switch(op_num){
|
||||
|
||||
case EQU:
|
||||
add_symbol(leading_symbol,GPR_TYPE_EQUATE,arg_decode(strtok(NULL, " \t\n"),0),0);
|
||||
return(0);
|
||||
|
||||
case DS:
|
||||
printf("**Assembler warning: \"DS\" will be obsoleted\n");
|
||||
case DYNAMIC:
|
||||
case DYN:
|
||||
add_symbol(leading_symbol,GPR_TYPE_DYNAMIC,ds_addr++,0);
|
||||
|
||||
if( (tmpc=strtok(NULL, " \t\n"))==NULL)
|
||||
tmp=0;
|
||||
else if((tmp=arg_decode(tmpc,0)) <=0)
|
||||
tmp=1;
|
||||
for(i=1;i<tmp;i++){
|
||||
add_symbol( (char *)NO_SYM ,GPR_TYPE_DYNAMIC,ds_addr++,0);
|
||||
|
||||
}
|
||||
return(0);
|
||||
case MACRO:
|
||||
new_macro(leading_symbol,line,strtok(NULL, "")-line_string+line);
|
||||
defmacro++;
|
||||
return(0);
|
||||
case DC:
|
||||
printf("**Assembler warning: \"DC\" will be obsoleted\n");
|
||||
case STA:
|
||||
case STATIC:
|
||||
tmpc = strtok(NULL, " ,\t\n") ;
|
||||
|
||||
if(tmpc == NULL)
|
||||
as_exit("Error DC directive must contain an initial value");
|
||||
while(tmpc!=NULL ){
|
||||
|
||||
if( tmpc[0] == '&' )
|
||||
tmp=arg2long(tmpc)*0x800; //account for 11 bit shift of addresses
|
||||
else
|
||||
tmp=arg2long(tmpc);
|
||||
|
||||
add_symbol(leading_symbol,GPR_TYPE_STATIC,ds_addr++,tmp);
|
||||
|
||||
leading_symbol=(char *)NO_SYM;
|
||||
|
||||
tmpc=strtok(NULL, " ,\t");
|
||||
}
|
||||
return(0);
|
||||
|
||||
case CONSTANT:
|
||||
case CON:
|
||||
//declaring constants inside of a macro is legal and needed for branch macros
|
||||
if(defmacro!=0)
|
||||
return (0);
|
||||
|
||||
|
||||
tmpc = strtok(NULL, " ,\t\n") ;
|
||||
|
||||
if(tmpc == NULL)
|
||||
as_exit("Error Constant directive must contain a value");
|
||||
while(tmpc!=NULL ){
|
||||
|
||||
if( tmpc[0] == '&' )
|
||||
tmp=arg2long(tmpc)*0x800; //account for 11 bit shift of addresses
|
||||
else
|
||||
tmp=arg2long(tmpc);
|
||||
|
||||
// add_constant(leading_symbol,tmp);
|
||||
|
||||
add_symbol(leading_symbol,GPR_TYPE_CONSTANT,ds_addr++,tmp);
|
||||
|
||||
leading_symbol=(char *)NO_SYM;
|
||||
|
||||
tmpc=strtok(NULL, " ,\t");
|
||||
}
|
||||
|
||||
return(0);
|
||||
case IO:
|
||||
add_symbol(leading_symbol,GPR_TYPE_INPUT,ds_addr++,0);
|
||||
add_symbol(strcat(leading_symbol,".o"),GPR_TYPE_OUTPUT,ds_addr++,0);
|
||||
return(0);
|
||||
case DIN:
|
||||
as_exit("DIN is obsoleted, use IO instead");
|
||||
add_symbol(leading_symbol,GPR_TYPE_INPUT,ds_addr++,0);
|
||||
return(0);
|
||||
case DOUT:
|
||||
as_exit("DOUT is obsoleted, use IO instead");
|
||||
add_symbol(leading_symbol,GPR_TYPE_OUTPUT,ds_addr++,0);
|
||||
return(0);
|
||||
case DD:
|
||||
add_symbol(leading_symbol,GPR_TYPE_EQUATE,0x100+tram_delay_count,0);
|
||||
(&tram_delay[tram_delay_count])->size = arg2long( strtok(NULL, " \t\n" ) ) +1;
|
||||
|
||||
INIT_LIST_HEAD( &(tram_delay[tram_delay_count].tram ) );
|
||||
strcpy((&tram_delay[tram_delay_count])->name,leading_symbol);
|
||||
if((dbg_opt&DBG_TRAM))
|
||||
printf("Delay Line: %-16s, length: 0x%05x samples,\n",(&tram_delay[tram_delay_count])->name, (&tram_delay[tram_delay_count])->size);
|
||||
tram_delay_count++;
|
||||
return(0);
|
||||
case DT:
|
||||
add_symbol(leading_symbol,GPR_TYPE_EQUATE,tram_table_count,0);
|
||||
(&tram_lookup[tram_table_count])->size = arg2long( strtok(NULL, " \t\n" ) );
|
||||
INIT_LIST_HEAD( &(tram_lookup[tram_table_count].tram) );
|
||||
strcpy((&tram_lookup[tram_table_count])->name,leading_symbol);
|
||||
|
||||
if((dbg_opt&DBG_TRAM))
|
||||
printf("Lookup table: %-16s, length: 0x%05x samples\n",leading_symbol, (&tram_delay[tram_delay_count])->size);
|
||||
tram_table_count++;
|
||||
return(0);
|
||||
case DW:
|
||||
//two symbols are created, "symbol" -> addr:0x2xx ; value: tram id #
|
||||
// "symbol.a" -> addr:0x3xx ; value: write offset
|
||||
|
||||
add_symbol(leading_symbol,TYPE_TRAM_DATA,tram_addr+0x200, arg_decode(tmpc=strtok(NULL, " \t," ),0) );
|
||||
add_symbol( strcat(leading_symbol,".a") ,TYPE_TRAM_ADDR_WRITE, (tram_addr++)+0x300 ,
|
||||
arg2long(strtok(NULL," \t\n")));
|
||||
if(dbg_opt&DBG_TRAM)
|
||||
printf(", in segment: \"%s\"\n",tmpc);
|
||||
|
||||
return(0);
|
||||
|
||||
case DR:
|
||||
add_symbol(leading_symbol,TYPE_TRAM_DATA,tram_addr+0x200,arg_decode(tmpc=strtok(NULL, " \t," ),0) );
|
||||
add_symbol(strcat(leading_symbol,".a"),TYPE_TRAM_ADDR_READ,(tram_addr++)+0x300,
|
||||
arg2long(strtok(NULL," \t\n")));
|
||||
if(dbg_opt&DBG_TRAM)
|
||||
printf(", in segment: \"%s\"\n",tmpc);
|
||||
return(0);
|
||||
case CONTROL:
|
||||
if( (tmpc = strtok(NULL, "\t ,\n")) ==NULL)
|
||||
as_exit("Parse Error: missing operand(s)");
|
||||
|
||||
if( tmpc[0] == '&' )
|
||||
tmp=arg2long(tmpc)<<11; //account for 11 bit shift of addresses
|
||||
else
|
||||
tmp=arg2long(tmpc);
|
||||
add_symbol(leading_symbol,GPR_TYPE_CONTROL,ds_addr++,tmp);
|
||||
issymbol(leading_symbol,(struct sym **)(&control));
|
||||
|
||||
|
||||
if( (tmpc = strtok(NULL, "\t ,\n") )==NULL)
|
||||
as_exit("Parse Error: missing operand(s)");
|
||||
|
||||
|
||||
if( tmpc[0] == '&' )
|
||||
control->min=arg2long(tmpc)<<11; //account for 11 bit shift of addresses
|
||||
else
|
||||
control->min=arg2long(tmpc);
|
||||
|
||||
if( (tmpc = strtok(NULL, "\t ,\n")) ==NULL)
|
||||
as_exit("Parse Error: missing operand(s)");
|
||||
|
||||
|
||||
if( tmpc[0] == '&' )
|
||||
control->max=arg2long(tmpc)<<11; //account for 11 bit shift of addresses
|
||||
else
|
||||
control->max=arg2long(tmpc);
|
||||
|
||||
return(0);
|
||||
case ENDM:
|
||||
if(defmacro==1) {
|
||||
defmacro--;
|
||||
return(0);
|
||||
}else if(macro_depth!=0)
|
||||
return(-1);
|
||||
else
|
||||
as_exit("Error, stray ENDM directive");
|
||||
case END:
|
||||
if(defmacro==1)
|
||||
as_exit("Error end directive in macro definition");
|
||||
return(1);
|
||||
case INCLUDE:
|
||||
if(defmacro==1)
|
||||
as_exit("Error, cannot include file from within macro definition");
|
||||
if(listing){
|
||||
sprintf(listtemp,"including file");
|
||||
fprintf(listfile,"%-50s || %s\n",listtemp,line);
|
||||
}
|
||||
asm_open(strtok(NULL, "\'\""));
|
||||
|
||||
return(-3);
|
||||
case NAME:
|
||||
advance_to_end(op_name_ptr);
|
||||
op_name_ptr++;
|
||||
advance_over_whites(op_name_ptr);
|
||||
if(dbg_opt)
|
||||
printf("Patch name:%s\n",op_name_ptr);
|
||||
|
||||
// printf("%s\n",op_name_ptr);
|
||||
tmpc=strtok(op_name_ptr,"\"");
|
||||
if(tmpc==NULL)
|
||||
as_exit("Bad name string, did you remember quotes\"\"");
|
||||
if(strlen(tmpc)>PATCH_NAME_SIZE)
|
||||
as_exit("Error Patch name exceeds maximum allowed amount (16)");
|
||||
memset(patch_name,0,PATCH_NAME_SIZE);
|
||||
strcpy(patch_name,tmpc);
|
||||
return(0);
|
||||
case FOR:
|
||||
if(listing){
|
||||
sprintf(listtemp,"FOR LOOP");
|
||||
fprintf(listfile,"%-50s || %s\n",listtemp,line);
|
||||
}
|
||||
for_handler(line,strtok(NULL,""));
|
||||
|
||||
return(-3);
|
||||
case ENDFOR:
|
||||
sprintf(listtemp,"FOR LOOP DONE");
|
||||
return(-2);
|
||||
default:
|
||||
|
||||
if(defmacro==0){
|
||||
|
||||
for(i=0;i<=3;i++)
|
||||
arg[i]=arg_decode(strtok(NULL,","),0);
|
||||
op(op_num,arg[0],arg[1],arg[2],arg[3]);
|
||||
return(0);
|
||||
|
||||
}else
|
||||
return(0);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
//assembly-time for loop handling:
|
||||
void for_handler(char *begin, char *operand )
|
||||
{
|
||||
char *ptr,*next,*line,string[MAX_LINE_LENGTH];
|
||||
int start,end,i,done;
|
||||
int diff, incr=1;
|
||||
struct sym *sym;
|
||||
|
||||
ptr=strtok(operand,"=");
|
||||
|
||||
start= arg_decode(strtok(NULL,":"),0);
|
||||
end = arg_decode(strtok(NULL," \t"),0);
|
||||
|
||||
|
||||
if(end>start)
|
||||
diff=end-start;
|
||||
else{
|
||||
diff=start-end;
|
||||
incr=-1;
|
||||
}
|
||||
|
||||
if( (issymbol(ptr,&sym))!=-1)
|
||||
sym->data.address=start;
|
||||
else
|
||||
add_symbol(ptr,GPR_TYPE_EQUATE, start,0);
|
||||
|
||||
issymbol(ptr,&sym);
|
||||
|
||||
|
||||
while(*begin!='\0')
|
||||
begin++;
|
||||
begin++;
|
||||
|
||||
for(i=0;i<diff;i++){
|
||||
next=begin;
|
||||
line=next;
|
||||
done=0;
|
||||
|
||||
while(done==0)
|
||||
{
|
||||
while((*next!= '\n') )
|
||||
next++;
|
||||
listtemp[0]='\0';
|
||||
*next='\0';
|
||||
if(strlen(line)>MAX_LINE_LENGTH)
|
||||
as_exit("Parse error: Line exceeds allowable limit");
|
||||
strcpy(&string[0],line);
|
||||
//printf("%s\n",string);
|
||||
done=parse(string, line);
|
||||
if(listing)
|
||||
if(done!=-2)
|
||||
fprintf(listfile,"%-50s || %s\n",listtemp,line);
|
||||
*next='\n';
|
||||
if(done==-2)
|
||||
break;
|
||||
next++;
|
||||
|
||||
|
||||
line=next;
|
||||
}
|
||||
sym->data.address = start+(incr*(i+1));
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int op_decode(char *op_name_ptr)
|
||||
{
|
||||
int op_num;
|
||||
|
||||
for(op_num=0;op_num<NUM_OPS;op_num++){
|
||||
if( strcasecmp(&op_codes[op_num][0],op_name_ptr) == 0 )
|
||||
return(op_num);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
//check if a symbol is used and returns it's pointer value in sym
|
||||
//normally returns 0, if symbol is non exitant, return -1
|
||||
|
||||
int issymbol(char *symbol,struct sym **sym)
|
||||
{
|
||||
extern unsigned int macro_depth;
|
||||
extern struct list_head sym_head;
|
||||
struct list_head *entry;
|
||||
|
||||
|
||||
list_for_each(entry,&sym_head){
|
||||
(*sym)=list_entry(entry,struct sym,list);
|
||||
if(symcmp((char *)&(*sym)->data.name,symbol)==0){
|
||||
if((*sym)->type!=TYPE_MACRO_ARG)
|
||||
return(0);
|
||||
else if( (*sym)->data.value==(macro_depth+1) )
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
//compares to words, the words can be terminated with a ' ', '\t', ',' or '\0'
|
||||
int symcmp (char *symbol1,char *symbol2)
|
||||
{
|
||||
|
||||
|
||||
while(1){
|
||||
if(*symbol1!=*symbol2)
|
||||
return(-1);
|
||||
symbol1++;
|
||||
symbol2++;
|
||||
|
||||
if(symend(symbol1) && symend(symbol2))
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//copies a symbol, symbols can be terminated with a ' ' , '\t' , ',' , '\n' , a '\0'
|
||||
void symcpy (char *dest, char *source)
|
||||
{ int i=0;
|
||||
for(i=0;i<=MAX_SYM_LEN;i++){
|
||||
if(source[i]== ' ' || source[i]=='\0' ||source[i]==',' ||source[i]=='\n' || source[i]=='\t' ) {
|
||||
dest[i]='\0';
|
||||
return;
|
||||
}
|
||||
dest[i]=source[i];
|
||||
}
|
||||
as_exit("Error, Maximum symbol length exceeded");
|
||||
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue