321 lines
5.1 KiB
C
321 lines
5.1 KiB
C
#include "varargs.h"
|
|
#include "decl.h"
|
|
|
|
/* All the functions in this file will be called by the parser.
|
|
*/
|
|
|
|
extern char *strindex();
|
|
|
|
static struct Op_info { char *name, *type}
|
|
op_info[ MAX_OPERANDS] = { { 0, 0}};
|
|
|
|
static int n_ops = 0; /* Number of opertands of current
|
|
* assembly instruction.
|
|
*/
|
|
static char *assem_instr = 0; /* Name of the current assembly instr */
|
|
static Bool restriction = FALSE; /* Is there a restriction on the
|
|
* current operand?
|
|
*/
|
|
File *outfile;
|
|
|
|
save_instr( instr, len)
|
|
char *instr;
|
|
int len;
|
|
{
|
|
assem_instr = Salloc( instr, len + 1);
|
|
}
|
|
|
|
save_name( name, len)
|
|
char *name;
|
|
int len;
|
|
{
|
|
op_info[ n_ops].name = Salloc( name, len + 1);
|
|
}
|
|
|
|
save_type( type, len)
|
|
char *type;
|
|
int len;
|
|
{
|
|
op_info[ n_ops].type = Salloc( type, len + 1);
|
|
restriction = TRUE;
|
|
}
|
|
|
|
pr_header()
|
|
{
|
|
out( "%s_instr", assem_instr);
|
|
param_list();
|
|
out( "{\n");
|
|
save_mnem( assem_instr);
|
|
}
|
|
|
|
param_list()
|
|
{
|
|
int i;
|
|
|
|
out( "(");
|
|
if ( n_ops > 0) {
|
|
out( " %s", op_info[0].name);
|
|
for ( i = 1; i < n_ops; i++)
|
|
out( ", %s", op_info[i].name);
|
|
}
|
|
|
|
out( ")\n");
|
|
if ( n_ops > 0) {
|
|
out( "struct t_operand *%s", op_info[0].name);
|
|
for ( i = 1; i < n_ops; i++)
|
|
out( ", *%s", op_info[i].name);
|
|
out( ";\n");
|
|
}
|
|
}
|
|
|
|
|
|
pr_restriction()
|
|
{
|
|
int i;
|
|
Bool more = FALSE;
|
|
|
|
if ( !restriction)
|
|
return;
|
|
|
|
out( "if ( ");
|
|
for ( i = 0; i < n_ops; i++)
|
|
if ( op_info[i].type != 0) {
|
|
if ( more)
|
|
out( " &&");
|
|
out( " %s( %s)", op_info[i].type, op_info[i].name);
|
|
more = TRUE;
|
|
}
|
|
out( ") ");
|
|
}
|
|
|
|
pr_warning()
|
|
{
|
|
if ( restriction)
|
|
out( "else\nerror( \"No match for %s\");\n", assem_instr);
|
|
restriction = FALSE;
|
|
}
|
|
|
|
clear_restriction()
|
|
{
|
|
restriction = FALSE;
|
|
}
|
|
|
|
char *skip_string( str)
|
|
char *str;
|
|
|
|
/* returns position after the first '"'-charcter, look out for '\' escape
|
|
* sequence
|
|
*/
|
|
{
|
|
for ( str++; *str != '"' || *(str-1) == '\\'; str++);
|
|
return( str + 1);
|
|
}
|
|
|
|
pr_subroutine( str)
|
|
char *str;
|
|
{
|
|
out( "%s;\n", str);
|
|
}
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
pr_call( str)
|
|
char *str;
|
|
|
|
/* Ouput 'str', but keep track of the number of bytes and take care of
|
|
* conversions like %$.
|
|
*/
|
|
{
|
|
if ( strncmp( "text", str, 4) == 0 && isdigit( *(str+4)))
|
|
out( "cur_pos += %d;\n", *(str+4) - '0');
|
|
else if ( strncmp( "reloc", str, 5) == 0 && isdigit( *(str+5)))
|
|
out( "cur_pos += %d;\n", *(str+5) - '0');
|
|
|
|
pr_text_with_conversions( str);
|
|
out( "fprint( outfile, \";\");");
|
|
}
|
|
|
|
pr_end()
|
|
{
|
|
out( "fprint( outfile, \"}\\n\");");
|
|
}
|
|
|
|
pr_els()
|
|
{
|
|
out( "fprint( outfile, \"else\\n\");");
|
|
}
|
|
|
|
pr_else()
|
|
{
|
|
out( "fprint( outfile, \"else {\\n\");");
|
|
}
|
|
|
|
pr_question( quest)
|
|
char *quest;
|
|
{
|
|
out( "fprint( outfile, \"if\");");
|
|
pr_text_with_conversions( quest);
|
|
out( "fprint( outfile, \"{\\n\");");
|
|
}
|
|
|
|
|
|
init_table()
|
|
{
|
|
outfile = STDOUT;
|
|
out( "#include \"as.h\"\n");
|
|
out( "#include \"as_parser.h\"\n");
|
|
}
|
|
|
|
clean()
|
|
|
|
/* Free space, allocated during the parsing of an entry in 'as_table'.
|
|
*/
|
|
{
|
|
int i;
|
|
|
|
if ( assem_instr != 0) {
|
|
free( assem_instr);
|
|
assem_instr = 0;
|
|
}
|
|
|
|
for ( i = 0; i < n_ops; i++) {
|
|
free( op_info[i].name);
|
|
op_info[i].name = 0;
|
|
if ( op_info[i].type != 0) {
|
|
free( op_info[i].type);
|
|
op_info[i].type = 0;
|
|
}
|
|
}
|
|
n_ops = 0;
|
|
}
|
|
|
|
operand_clean()
|
|
|
|
/* Free space for the operands */
|
|
|
|
{
|
|
int i;
|
|
|
|
for ( i = 0; i < n_ops; i++) {
|
|
free( op_info[i].name);
|
|
op_info[i].name = 0;
|
|
if ( op_info[i].type != 0) {
|
|
free( op_info[i].type);
|
|
op_info[i].type = 0;
|
|
}
|
|
}
|
|
n_ops = 0;
|
|
}
|
|
|
|
/*VARARGS*/
|
|
out(va_alist)
|
|
va_dcl
|
|
{
|
|
va_list pvar;
|
|
char *fmt;
|
|
|
|
va_start(pvar);
|
|
fmt = va_arg(pvar, char *);
|
|
doprnt( outfile, fmt, pvar);
|
|
va_end(pvar);
|
|
}
|
|
|
|
/*VARARGS*/
|
|
error(va_alist)
|
|
va_dcl
|
|
{
|
|
char *fmt;
|
|
va_list pvar;
|
|
|
|
va_start(pvar);
|
|
fmt = va_arg(pvar, char *);
|
|
fprint( STDERR, "!! ERROR : ");
|
|
doprnt( STDERR, fmt, pvar);
|
|
fprint( STDERR, " !!\n");
|
|
va_end(pvar);
|
|
}
|
|
|
|
inc_ops()
|
|
{
|
|
n_ops++;
|
|
}
|
|
|
|
|
|
/**********************************/
|
|
|
|
char *mnemonic[ MAX_MNEMONICS];
|
|
int n_mnems = 0;
|
|
|
|
save_mnem( mnem)
|
|
char *mnem;
|
|
{
|
|
if ( n_mnems == MAX_MNEMONICS)
|
|
error( "too many assembler instructions!! MAX_MNEMONICS = %d",
|
|
MAX_MNEMONICS);
|
|
else
|
|
mnemonic[ n_mnems++] = Salloc( mnem, strlen( mnem) + 1);
|
|
}
|
|
|
|
|
|
end_table()
|
|
|
|
/* Flush information in the array 'mnemonic'
|
|
*/
|
|
{
|
|
int i;
|
|
|
|
quicksort( 0, n_mnems - 1);
|
|
|
|
out( "char *mnemonic[] = {\n");
|
|
for ( i = 0; i < n_mnems - 1; i++)
|
|
out( "\t\"%s\",\n", mnemonic[i]);
|
|
out( "\t\"%s\"};\n\n", mnemonic[ n_mnems-1]);
|
|
|
|
out( "int (*instruction[])() = {\n");
|
|
for ( i = 0; i < n_mnems - 1; i++)
|
|
out( "\t%s_instr,\n", mnemonic[i]);
|
|
out( "\t%s_instr};\n\n", mnemonic[ n_mnems-1]);
|
|
out( "int n_mnems = %d;\n", n_mnems);
|
|
}
|
|
|
|
quicksort( lower, upper)
|
|
int lower, upper;
|
|
|
|
/* Sort the array 'mnemonic'.
|
|
*/
|
|
{
|
|
char *key, *tmp;
|
|
int index1, index2;
|
|
|
|
if ( lower >= upper)
|
|
return;
|
|
|
|
key = mnemonic[lower];
|
|
index1 = lower;
|
|
index2 = upper+1;
|
|
|
|
while ( index1 < index2) {
|
|
|
|
do
|
|
index1++;
|
|
while (index1 <= upper && strcmp( mnemonic[index1], key) < 0 );
|
|
|
|
do
|
|
index2--;
|
|
while ( strcmp( mnemonic[index2], key) > 0);
|
|
|
|
if ( index1 < index2) {
|
|
tmp = mnemonic[index2];
|
|
mnemonic[index2] = mnemonic[index1];
|
|
mnemonic[index1] = tmp;
|
|
}
|
|
}
|
|
|
|
mnemonic[lower] = mnemonic[index2];
|
|
mnemonic[index2] = key;
|
|
|
|
quicksort( lower, index2-1);
|
|
quicksort( index2+1, upper);
|
|
}
|