patch-2.4.19 linux-2.4.19/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
Next file: linux-2.4.19/drivers/scsi/aic7xxx/aicasm/aicasm_insformat.h
Previous file: linux-2.4.19/drivers/scsi/aic7xxx/aicasm/aicasm.h
Back to the patch index
Back to the overall index
- Lines: 806
- Date:
Fri Aug 2 17:39:44 2002
- Orig file:
linux-2.4.18/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
- Orig date:
Thu Oct 25 13:53:49 2001
diff -urN linux-2.4.18/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y linux-2.4.19/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
@@ -38,18 +38,20 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#9 $
+ * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#14 $
*
* $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_gram.y,v 1.12 2000/10/31 18:44:32 gibbs Exp $
*/
+#include <sys/types.h>
+
#include <inttypes.h>
+#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
-#include <sys/types.h>
#ifdef __linux__
#include "../queue.h"
#else
@@ -62,21 +64,29 @@
int yylineno;
char *yyfilename;
+char *patch_arg_list;
char *versions;
+static char errbuf[255];
+static char regex_pattern[255];
static symbol_t *cur_symbol;
+static symbol_t *scb_or_sram_symbol;
static symtype cur_symtype;
-static symbol_t *accumulator;
+static symbol_ref_t accumulator;
+static symbol_ref_t mode_ptr;
static symbol_ref_t allones;
static symbol_ref_t allzeros;
static symbol_ref_t none;
static symbol_ref_t sindex;
static int instruction_ptr;
+static int num_srams;
static int sram_or_scb_offset;
static int download_constant_count;
static int in_critical_section;
static void process_bitmask(int mask_type, symbol_t *sym, int mask);
static void initialize_symbol(symbol_t *symbol);
+static void add_macro_arg(const char *argtext, int position);
+static void add_macro_body(const char *bodytext);
static void process_register(symbol_t **p_symbol);
static void format_1_instr(int opcode, symbol_ref_t *dest,
expression_t *immed, symbol_ref_t *src, int ret);
@@ -92,13 +102,12 @@
static void add_version(const char *verstring);
static int is_download_const(expression_t *immed);
-#define YYDEBUG 1
#define SRAM_SYMNAME "SRAM_BASE"
#define SCB_SYMNAME "SCB_BASE"
%}
%union {
- int value;
+ u_int value;
char *str;
symbol_t *sym;
symbol_ref_t sym_ref;
@@ -109,6 +118,8 @@
%token <value> T_CONST
+%token T_EXPORT
+
%token T_DOWNLOAD
%token T_SCB
@@ -119,10 +130,22 @@
%token T_SIZE
+%token T_EXPR_LSHIFT
+
+%token T_EXPR_RSHIFT
+
%token <value> T_ADDRESS
%token T_ACCESS_MODE
+%token T_MODES
+
+%token T_DEFINE
+
+%token T_SET_SRC_MODE
+
+%token T_SET_DST_MODE
+
%token <value> T_MODE
%token T_BEGIN_CS
@@ -135,11 +158,11 @@
%token <value> T_NUMBER
-%token <str> T_PATH T_STRING
+%token <str> T_PATH T_STRING T_ARG T_MACROBODY
%token <sym> T_CEXPR
-%token T_EOF T_INCLUDE T_VERSION
+%token T_EOF T_INCLUDE T_VERSION T_PATCH_ARG_LIST
%token <value> T_SHR T_SHL T_ROR T_ROL
@@ -163,7 +186,7 @@
%token T_NOP
-%token T_ACCUM T_ALLONES T_ALLZEROS T_NONE T_SINDEX
+%token T_ACCUM T_ALLONES T_ALLZEROS T_NONE T_SINDEX T_MODE_PTR
%token T_A
@@ -177,13 +200,15 @@
%type <expression> expression immediate immediate_or_a
-%type <value> ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne
+%type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne
-%type <value> numerical_value
+%type <value> numerical_value mode_value mode_list macro_arglist
%left '|'
%left '&'
+%left T_EXPR_LSHIFT T_EXPR_RSHIFT
%left '+' '-'
+%left '*' '/'
%right '~'
%nonassoc UMINUS
%%
@@ -191,18 +216,26 @@
program:
include
| program include
+| patch_arg_list
+| program patch_arg_list
| version
| program version
| register
| program register
| constant
| program constant
+| macrodefn
+| program macrodefn
| scratch_ram
| program scratch_ram
| scb
| program scb
| label
| program label
+| set_src_mode
+| program set_src_mode
+| set_dst_mode
+| program set_dst_mode
| critical_section_start
| program critical_section_start
| critical_section_end
@@ -224,6 +257,18 @@
}
;
+patch_arg_list:
+ T_PATCH_ARG_LIST '=' T_STRING
+ {
+ if (patch_arg_list != NULL)
+ stop("Patch argument list multiply defined",
+ EX_DATAERR);
+ patch_arg_list = strdup($3);
+ if (patch_arg_list == NULL)
+ stop("Unable to record patch arg list", EX_SOFTWARE);
+ }
+;
+
version:
T_VERSION '=' T_STRING
{ add_version($3); }
@@ -280,10 +325,12 @@
reg_address
| size
| access_mode
+| modes
| bit_defn
| mask_defn
| alias
| accumulator
+| mode_pointer
| allones
| allzeros
| none
@@ -301,6 +348,18 @@
T_SIZE T_NUMBER
{
cur_symbol->info.rinfo->size = $2;
+ if (scb_or_sram_symbol != NULL) {
+ u_int max_addr;
+ u_int sym_max_addr;
+
+ max_addr = scb_or_sram_symbol->info.rinfo->address
+ + scb_or_sram_symbol->info.rinfo->size;
+ sym_max_addr = cur_symbol->info.rinfo->address
+ + cur_symbol->info.rinfo->size;
+
+ if (sym_max_addr > max_addr)
+ stop("SCB or SRAM space exhausted", EX_DATAERR);
+ }
}
;
@@ -311,6 +370,54 @@
}
;
+modes:
+ T_MODES mode_list
+ {
+ cur_symbol->info.rinfo->modes = $2;
+ }
+;
+
+mode_list:
+ mode_value
+ {
+ $$ = $1;
+ }
+| mode_list ',' mode_value
+ {
+ $$ = $1 | $3;
+ }
+;
+
+mode_value:
+ T_NUMBER
+ {
+ if ($1 > 4) {
+ stop("Valid register modes range between 0 and 4.",
+ EX_DATAERR);
+ /* NOTREACHED */
+ }
+
+ $$ = (0x1 << $1);
+ }
+| T_SYMBOL
+ {
+ symbol_t *symbol;
+
+ symbol = $1;
+ if (symbol->type != CONST) {
+ stop("Only \"const\" symbols allowed in "
+ "mode definitions.", EX_DATAERR);
+ /* NOTREACHED */
+ }
+ if (symbol->info.cinfo->value > 4) {
+ stop("Valid register modes range between 0 and 4.",
+ EX_DATAERR);
+ /* NOTREACHED */
+ }
+ $$ = (0x1 << symbol->info.cinfo->value);
+ }
+;
+
bit_defn:
T_BIT T_SYMBOL T_NUMBER
{
@@ -342,12 +449,24 @@
accumulator:
T_ACCUM
{
- if (accumulator != NULL) {
+ if (accumulator.symbol != NULL) {
stop("Only one accumulator definition allowed",
EX_DATAERR);
/* NOTREACHED */
}
- accumulator = cur_symbol;
+ accumulator.symbol = cur_symbol;
+ }
+;
+
+mode_pointer:
+ T_MODE_PTR
+ {
+ if (mode_ptr.symbol != NULL) {
+ stop("Only one mode pointer definition allowed",
+ EX_DATAERR);
+ /* NOTREACHED */
+ }
+ mode_ptr.symbol = cur_symbol;
}
;
@@ -428,6 +547,34 @@
&($1.referenced_syms),
&($3.referenced_syms));
}
+| expression '*' expression
+ {
+ $$.value = $1.value * $3.value;
+ symlist_merge(&($$.referenced_syms),
+ &($1.referenced_syms),
+ &($3.referenced_syms));
+ }
+| expression '/' expression
+ {
+ $$.value = $1.value / $3.value;
+ symlist_merge(&($$.referenced_syms),
+ &($1.referenced_syms),
+ &($3.referenced_syms));
+ }
+| expression T_EXPR_LSHIFT expression
+ {
+ $$.value = $1.value << $3.value;
+ symlist_merge(&$$.referenced_syms,
+ &$1.referenced_syms,
+ &$3.referenced_syms);
+ }
+| expression T_EXPR_RSHIFT expression
+ {
+ $$.value = $1.value >> $3.value;
+ symlist_merge(&$$.referenced_syms,
+ &$1.referenced_syms,
+ &$3.referenced_syms);
+ }
| '(' expression ')'
{
$$ = $2;
@@ -471,12 +618,10 @@
case UNINITIALIZED:
default:
{
- char buf[255];
-
- snprintf(buf, sizeof(buf),
+ snprintf(errbuf, sizeof(errbuf),
"Undefined symbol %s referenced",
symbol->name);
- stop(buf, EX_DATAERR);
+ stop(errbuf, EX_DATAERR);
/* NOTREACHED */
break;
}
@@ -497,7 +642,6 @@
$2->type = CONST;
initialize_symbol($2);
$2->info.cinfo->value = $3;
- $2->info.cinfo->define = $1;
}
| T_CONST T_SYMBOL T_DOWNLOAD
{
@@ -514,7 +658,54 @@
$2->type = DOWNLOAD_CONST;
initialize_symbol($2);
$2->info.cinfo->value = download_constant_count++;
- $2->info.cinfo->define = FALSE;
+ }
+;
+
+macrodefn_prologue:
+ T_DEFINE T_SYMBOL
+ {
+ if ($2->type != UNINITIALIZED) {
+ stop("Re-definition of symbol as a macro",
+ EX_DATAERR);
+ /* NOTREACHED */
+ }
+ cur_symbol = $2;
+ cur_symbol->type = MACRO;
+ initialize_symbol(cur_symbol);
+ }
+;
+
+macrodefn:
+ macrodefn_prologue T_MACROBODY
+ {
+ add_macro_body($2);
+ }
+| macrodefn_prologue '(' macro_arglist ')' T_MACROBODY
+ {
+ add_macro_body($5);
+ cur_symbol->info.macroinfo->narg = $3;
+ }
+;
+
+macro_arglist:
+ {
+ /* Macros can take no arguments */
+ $$ = 0;
+ }
+| T_ARG
+ {
+ $$ = 1;
+ add_macro_arg($1, 0);
+ }
+| macro_arglist ',' T_ARG
+ {
+ if ($1 == 0) {
+ stop("Comma without preceeding argument in arg list",
+ EX_DATAERR);
+ /* NOTREACHED */
+ }
+ $$ = $1 + 1;
+ add_macro_arg($3, $1);
}
;
@@ -532,13 +723,10 @@
scratch_ram:
T_SRAM '{'
{
+ snprintf(errbuf, sizeof(errbuf), "%s%d", SRAM_SYMNAME,
+ num_srams);
cur_symbol = symtable_get(SRAM_SYMNAME);
cur_symtype = SRAMLOC;
- if (cur_symbol->type != UNINITIALIZED) {
- stop("Only one SRAM definition allowed",
- EX_DATAERR);
- /* NOTREACHED */
- }
cur_symbol->type = SRAMLOC;
initialize_symbol(cur_symbol);
}
@@ -546,10 +734,15 @@
{
sram_or_scb_offset = cur_symbol->info.rinfo->address;
}
- scb_or_sram_reg_list
+ size
+ {
+ scb_or_sram_symbol = cur_symbol;
+ }
+ scb_or_sram_attributes
'}'
{
cur_symbol = NULL;
+ scb_or_sram_symbol = NULL;
}
;
@@ -572,13 +765,25 @@
{
sram_or_scb_offset = cur_symbol->info.rinfo->address;
}
- scb_or_sram_reg_list
+ size
+ {
+ scb_or_sram_symbol = cur_symbol;
+ }
+ scb_or_sram_attributes
'}'
{
cur_symbol = NULL;
+ scb_or_sram_symbol = NULL;
}
;
+scb_or_sram_attributes:
+ /* NULL definition is okay */
+| modes
+| scb_or_sram_reg_list
+| modes scb_or_sram_reg_list
+;
+
scb_or_sram_reg_list:
reg_definition
| scb_or_sram_reg_list reg_definition
@@ -619,11 +824,11 @@
}
| T_A
{
- if (accumulator == NULL) {
+ if (accumulator.symbol == NULL) {
stop("No accumulator has been defined", EX_DATAERR);
/* NOTREACHED */
}
- $$.symbol = accumulator;
+ $$.symbol = accumulator.symbol;
$$.offset = 0;
}
;
@@ -644,6 +849,14 @@
immediate_or_a:
expression
{
+ if ($1.value == 0 && is_download_const(&$1) == 0) {
+ snprintf(errbuf, sizeof(errbuf),
+ "\nExpression evaluates to 0 and thus "
+ "references the accumulator.\n "
+ "If this is the desired effect, use 'A' "
+ "instead.\n");
+ stop(errbuf, EX_DATAERR);
+ }
$$ = $1;
}
| T_A
@@ -676,8 +889,22 @@
{ $$ = 1; }
;
+set_src_mode:
+ T_SET_SRC_MODE T_NUMBER ';'
+ {
+ src_mode = $2;
+ }
+;
+
+set_dst_mode:
+ T_SET_DST_MODE T_NUMBER ';'
+ {
+ dst_mode = $2;
+ }
+;
+
critical_section_start:
- T_BEGIN_CS
+ T_BEGIN_CS ';'
{
critical_section_t *cs;
@@ -692,7 +919,7 @@
}
critical_section_end:
- T_END_CS
+ T_END_CS ';'
{
critical_section_t *cs;
@@ -705,16 +932,23 @@
in_critical_section = FALSE;
}
+export:
+ { $$ = 0; }
+| T_EXPORT
+ { $$ = 1; }
+;
+
label:
- T_SYMBOL ':'
+ export T_SYMBOL ':'
{
- if ($1->type != UNINITIALIZED) {
+ if ($2->type != UNINITIALIZED) {
stop("Program label multiply defined", EX_DATAERR);
/* NOTREACHED */
}
- $1->type = LABEL;
- initialize_symbol($1);
- $1->info.linfo->address = instruction_ptr;
+ $2->type = LABEL;
+ initialize_symbol($2);
+ $2->info.linfo->address = instruction_ptr;
+ $2->info.linfo->exported = $1;
}
;
@@ -1128,6 +1362,16 @@
}
memset(symbol->info.rinfo, 0,
sizeof(struct reg_info));
+ /*
+ * Default to allowing access in all register modes
+ * or to the mode specified by the SCB or SRAM space
+ * we are in.
+ */
+ if (scb_or_sram_symbol != NULL)
+ symbol->info.rinfo->modes =
+ scb_or_sram_symbol->info.rinfo->modes;
+ else
+ symbol->info.rinfo->modes = ~0;
break;
case ALIAS:
symbol->info.ainfo =
@@ -1181,6 +1425,17 @@
memset(symbol->info.condinfo, 0,
sizeof(struct cond_info));
break;
+ case MACRO:
+ symbol->info.macroinfo =
+ (struct macro_info *)malloc(sizeof(struct macro_info));
+ if (symbol->info.macroinfo == NULL) {
+ stop("Can't create macro info", EX_SOFTWARE);
+ /* NOTREACHED */
+ }
+ memset(symbol->info.macroinfo, 0,
+ sizeof(struct macro_info));
+ STAILQ_INIT(&symbol->info.macroinfo->args);
+ break;
default:
stop("Call to initialize_symbol with invalid symbol type",
EX_SOFTWARE);
@@ -1190,25 +1445,75 @@
}
static void
+add_macro_arg(const char *argtext, int argnum)
+{
+ struct macro_arg *marg;
+ int i;
+ int retval;
+
+
+ if (cur_symbol == NULL || cur_symbol->type != MACRO) {
+ stop("Invalid current symbol for adding macro arg",
+ EX_SOFTWARE);
+ /* NOTREACHED */
+ }
+
+ marg = (struct macro_arg *)malloc(sizeof(*marg));
+ if (marg == NULL) {
+ stop("Can't create macro_arg structure", EX_SOFTWARE);
+ /* NOTREACHED */
+ }
+ marg->replacement_text = NULL;
+ retval = snprintf(regex_pattern, sizeof(regex_pattern),
+ "[^-/A-Za-z0-9_](%s)([^-/A-Za-z0-9_]|$)",
+ argtext);
+ if (retval >= sizeof(regex_pattern)) {
+ stop("Regex text buffer too small for arg",
+ EX_SOFTWARE);
+ /* NOTREACHED */
+ }
+ retval = regcomp(&marg->arg_regex, regex_pattern, REG_EXTENDED);
+ if (retval != 0) {
+ stop("Regex compilation failed", EX_SOFTWARE);
+ /* NOTREACHED */
+ }
+ STAILQ_INSERT_TAIL(&cur_symbol->info.macroinfo->args, marg, links);
+}
+
+static void
+add_macro_body(const char *bodytext)
+{
+ if (cur_symbol == NULL || cur_symbol->type != MACRO) {
+ stop("Invalid current symbol for adding macro arg",
+ EX_SOFTWARE);
+ /* NOTREACHED */
+ }
+ cur_symbol->info.macroinfo->body = strdup(bodytext);
+ if (cur_symbol->info.macroinfo->body == NULL) {
+ stop("Can't duplicate macro body text", EX_SOFTWARE);
+ /* NOTREACHED */
+ }
+}
+
+static void
process_register(symbol_t **p_symbol)
{
- char buf[255];
symbol_t *symbol = *p_symbol;
if (symbol->type == UNINITIALIZED) {
- snprintf(buf, sizeof(buf), "Undefined register %s",
+ snprintf(errbuf, sizeof(errbuf), "Undefined register %s",
symbol->name);
- stop(buf, EX_DATAERR);
+ stop(errbuf, EX_DATAERR);
/* NOTREACHED */
} else if (symbol->type == ALIAS) {
*p_symbol = symbol->info.ainfo->parent;
} else if ((symbol->type != REGISTER)
&& (symbol->type != SCBLOC)
&& (symbol->type != SRAMLOC)) {
- snprintf(buf, sizeof(buf),
+ snprintf(errbuf, sizeof(errbuf),
"Specified symbol %s is not a register",
symbol->name);
- stop(buf, EX_DATAERR);
+ stop(errbuf, EX_DATAERR);
}
}
@@ -1242,6 +1547,47 @@
if (is_download_const(immed))
f1_instr->parity = 1;
+ else if (dest->symbol == mode_ptr.symbol) {
+ u_int src_value;
+ u_int dst_value;
+
+ /*
+ * Attempt to update mode information if
+ * we are operating on the mode register.
+ */
+ if (src->symbol == allones.symbol)
+ src_value = 0xFF;
+ else if (src->symbol == allzeros.symbol)
+ src_value = 0;
+ else if (src->symbol == mode_ptr.symbol)
+ src_value = (dst_mode << 4) | src_mode;
+ else
+ goto cant_update;
+
+ switch (opcode) {
+ case AIC_OP_AND:
+ dst_value = src_value & immed->value;
+ break;
+ case AIC_OP_XOR:
+ dst_value = src_value ^ immed->value;
+ break;
+ case AIC_OP_ADD:
+ dst_value = (src_value + immed->value) & 0xFF;
+ break;
+ case AIC_OP_OR:
+ dst_value = src_value | immed->value;
+ break;
+ break;
+ case AIC_OP_BMOV:
+ dst_value = src_value;
+ break;
+ default:
+ goto cant_update;
+ }
+ src_mode = dst_value & 0xF;
+ dst_mode = (dst_value >> 4) & 0xF;
+cant_update:
+ }
symlist_free(&immed->referenced_syms);
instruction_ptr++;
@@ -1350,6 +1696,14 @@
static void
test_readable_symbol(symbol_t *symbol)
{
+
+ if ((symbol->info.rinfo->modes & (0x1 << src_mode)) == 0) {
+ snprintf(errbuf, sizeof(errbuf),
+ "Register %s unavailable in source reg mode %d",
+ symbol->name, src_mode);
+ stop(errbuf, EX_DATAERR);
+ }
+
if (symbol->info.rinfo->mode == WO) {
stop("Write Only register specified as source",
EX_DATAERR);
@@ -1360,6 +1714,14 @@
static void
test_writable_symbol(symbol_t *symbol)
{
+
+ if ((symbol->info.rinfo->modes & (0x1 << dst_mode)) == 0) {
+ snprintf(errbuf, sizeof(errbuf),
+ "Register %s unavailable in destination reg mode %d",
+ symbol->name, dst_mode);
+ stop(errbuf, EX_DATAERR);
+ }
+
if (symbol->info.rinfo->mode == RO) {
stop("Read Only register specified as destination",
EX_DATAERR);
@@ -1372,7 +1734,6 @@
{
symbol_node_t *node;
int and_op;
- char buf[255];
and_op = FALSE;
if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || AIC_OP_JZ)
@@ -1385,11 +1746,11 @@
*/
if (and_op == FALSE
&& (expression->value & ~symbol->info.rinfo->valid_bitmask) != 0) {
- snprintf(buf, sizeof(buf),
+ snprintf(errbuf, sizeof(errbuf),
"Invalid bit(s) 0x%x in immediate written to %s",
expression->value & ~symbol->info.rinfo->valid_bitmask,
symbol->name);
- stop(buf, EX_DATAERR);
+ stop(errbuf, EX_DATAERR);
/* NOTREACHED */
}
@@ -1397,7 +1758,7 @@
* Now make sure that all of the symbols referenced by the
* expression are defined for this register.
*/
- if(symbol->info.rinfo->typecheck_masks != FALSE) {
+ if (symbol->info.rinfo->typecheck_masks != FALSE) {
for(node = expression->referenced_syms.slh_first;
node != NULL;
node = node->links.sle_next) {
@@ -1405,11 +1766,11 @@
|| node->symbol->type == BIT)
&& symlist_search(&node->symbol->info.minfo->symrefs,
symbol->name) == NULL) {
- snprintf(buf, sizeof(buf),
+ snprintf(errbuf, sizeof(errbuf),
"Invalid bit or mask %s "
"for register %s",
node->symbol->name, symbol->name);
- stop(buf, EX_DATAERR);
+ stop(errbuf, EX_DATAERR);
/* NOTREACHED */
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)