📄 aicasm_gram.y
字号:
%{/* * Parser for the Aic7xxx SCSI Host adapter sequencer assembler. * * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. * Copyright (c) 2001 Adaptec Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * substantially similar to the "NO WARRANTY" disclaimer below * ("Disclaimer") and any redistribution must be conditioned upon * including a substantially similar Disclaimer requirement for further * binary redistribution. * 3. Neither the names of the above-listed copyright holders nor the names * of any contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * 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#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>#ifdef __linux__#include "../queue.h"#else#include <sys/queue.h>#endif#include "aicasm.h"#include "aicasm_symbol.h"#include "aicasm_insformat.h"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_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);static void format_2_instr(int opcode, symbol_ref_t *dest, expression_t *places, symbol_ref_t *src, int ret);static void format_3_instr(int opcode, symbol_ref_t *src, expression_t *immed, symbol_ref_t *address);static void test_readable_symbol(symbol_t *symbol);static void test_writable_symbol(symbol_t *symbol);static void type_check(symbol_t *symbol, expression_t *expression, int and_op);static void make_expression(expression_t *immed, int value);static void add_conditional(symbol_t *symbol);static void add_version(const char *verstring);static int is_download_const(expression_t *immed);#define SRAM_SYMNAME "SRAM_BASE"#define SCB_SYMNAME "SCB_BASE"%}%union { u_int value; char *str; symbol_t *sym; symbol_ref_t sym_ref; expression_t expression;}%token T_REGISTER%token <value> T_CONST%token T_EXPORT%token T_DOWNLOAD%token T_SCB%token T_SRAM%token T_ALIAS%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%token T_END_CS%token T_BIT%token T_MASK%token <value> T_NUMBER%token <str> T_PATH T_STRING T_ARG T_MACROBODY%token <sym> T_CEXPR%token T_EOF T_INCLUDE T_VERSION T_PATCH_ARG_LIST%token <value> T_SHR T_SHL T_ROR T_ROL%token <value> T_MVI T_MOV T_CLR T_BMOV%token <value> T_JMP T_JC T_JNC T_JE T_JNE T_JNZ T_JZ T_CALL%token <value> T_ADD T_ADC%token <value> T_INC T_DEC%token <value> T_STC T_CLC%token <value> T_CMP T_NOT T_XOR%token <value> T_TEST T_AND%token <value> T_OR%token T_RET%token T_NOP%token T_ACCUM T_ALLONES T_ALLZEROS T_NONE T_SINDEX T_MODE_PTR%token T_A%token <sym> T_SYMBOL%token T_NL%token T_IF T_ELSE T_ELSE_IF T_ENDIF%type <sym_ref> reg_symbol address destination source opt_source%type <expression> expression immediate immediate_or_a%type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne%type <value> numerical_value mode_value mode_list macro_arglist%left '|'%left '&'%left T_EXPR_LSHIFT T_EXPR_RSHIFT%left '+' '-'%left '*' '/'%right '~'%nonassoc UMINUS%%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| program critical_section_end| conditional| program conditional| code| program code;include: T_INCLUDE '<' T_PATH '>' { include_file($3, BRACKETED_INCLUDE); }| T_INCLUDE '"' T_PATH '"' { include_file($3, QUOTED_INCLUDE); };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); };register: T_REGISTER { cur_symtype = REGISTER; } reg_definition;reg_definition: T_SYMBOL '{' { if ($1->type != UNINITIALIZED) { stop("Register multiply defined", EX_DATAERR); /* NOTREACHED */ } cur_symbol = $1; cur_symbol->type = cur_symtype; initialize_symbol(cur_symbol); } reg_attribute_list '}' { /* * Default to allowing everything in for registers * with no bit or mask definitions. */ if (cur_symbol->info.rinfo->valid_bitmask == 0) cur_symbol->info.rinfo->valid_bitmask = 0xFF; if (cur_symbol->info.rinfo->size == 0) cur_symbol->info.rinfo->size = 1; /* * This might be useful for registers too. */ if (cur_symbol->type != REGISTER) { if (cur_symbol->info.rinfo->address == 0) cur_symbol->info.rinfo->address = sram_or_scb_offset; sram_or_scb_offset += cur_symbol->info.rinfo->size; } cur_symbol = NULL; };reg_attribute_list: reg_attribute| reg_attribute_list reg_attribute;reg_attribute: reg_address| size| access_mode| modes| bit_defn| mask_defn| alias| accumulator| mode_pointer| allones| allzeros| none| sindex;reg_address: T_ADDRESS T_NUMBER { cur_symbol->info.rinfo->address = $2; };size: 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); } };access_mode: T_ACCESS_MODE T_MODE { cur_symbol->info.rinfo->mode = $2; };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 { process_bitmask(BIT, $2, $3); };mask_defn: T_MASK T_SYMBOL expression { process_bitmask(MASK, $2, $3.value); };alias: T_ALIAS T_SYMBOL { if ($2->type != UNINITIALIZED) { stop("Re-definition of register alias", EX_DATAERR); /* NOTREACHED */ } $2->type = ALIAS; initialize_symbol($2); $2->info.ainfo->parent = cur_symbol; };accumulator: T_ACCUM { if (accumulator.symbol != NULL) { stop("Only one accumulator definition allowed", EX_DATAERR); /* NOTREACHED */ } 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; };allones: T_ALLONES { if (allones.symbol != NULL) { stop("Only one definition of allones allowed", EX_DATAERR); /* NOTREACHED */ } allones.symbol = cur_symbol; };allzeros: T_ALLZEROS { if (allzeros.symbol != NULL) { stop("Only one definition of allzeros allowed", EX_DATAERR); /* NOTREACHED */ } allzeros.symbol = cur_symbol; };none: T_NONE { if (none.symbol != NULL) { stop("Only one definition of none allowed", EX_DATAERR); /* NOTREACHED */ } none.symbol = cur_symbol; };sindex: T_SINDEX { if (sindex.symbol != NULL) { stop("Only one definition of sindex allowed", EX_DATAERR); /* NOTREACHED */ } sindex.symbol = cur_symbol; };expression: 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 '+' 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 '*' 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; }| '~' expression { $$ = $2; $$.value = (~$$.value) & 0xFF; }| '-' expression %prec UMINUS { $$ = $2; $$.value = -$$.value; }| T_NUMBER { $$.value = $1; SLIST_INIT(&$$.referenced_syms); }| T_SYMBOL { symbol_t *symbol; symbol = $1; switch (symbol->type) { case ALIAS: symbol = $1->info.ainfo->parent; case REGISTER: case SCBLOC: case SRAMLOC: $$.value = symbol->info.rinfo->address; break; case MASK: case BIT: $$.value = symbol->info.minfo->mask; break; case DOWNLOAD_CONST: case CONST: $$.value = symbol->info.cinfo->value; break; case UNINITIALIZED: default: {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -