📄 aicasm_gram.y
字号:
%{/* * Parser for the Aic7xxx SCSI Host adapter sequencer assembler. * * Copyright (c) 1997-1998 Justin T. Gibbs. * 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, immediately at the beginning of the file. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE. * * $Id: aicasm_gram.y,v 1.6 1998/12/10 04:14:50 gibbs Exp $ */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sysexits.h>#include <sys/types.h>#include <sys/queue.h>#include "aicasm.h"#include "aicasm_symbol.h"#include "sequencer.h"int yylineno;char *yyfilename;static symbol_t *cur_symbol;static symtype cur_symtype;static symbol_t *accumulator;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 sram_or_scb_offset;static int download_constant_count;static void process_bitmask __P((int mask_type, symbol_t *sym, int mask));static void initialize_symbol __P((symbol_t *symbol));static void process_register __P((symbol_t **p_symbol));static void format_1_instr __P((int opcode, symbol_ref_t *dest, expression_t *immed, symbol_ref_t *src, int ret));static void format_2_instr __P((int opcode, symbol_ref_t *dest, expression_t *places, symbol_ref_t *src, int ret));static void format_3_instr __P((int opcode, symbol_ref_t *src, expression_t *immed, symbol_ref_t *address));static void test_readable_symbol __P((symbol_t *symbol));static void test_writable_symbol __P((symbol_t *symbol));static void type_check __P((symbol_t *symbol, expression_t *expression, int and_op));static void make_expression __P((expression_t *immed, int value));static void add_conditional __P((symbol_t *symbol));static int is_download_const __P((expression_t *immed));#define YYDEBUG 1#define SRAM_SYMNAME "SRAM_BASE"#define SCB_SYMNAME "SCB_BASE"%}%union { int value; char *str; symbol_t *sym; symbol_ref_t sym_ref; expression_t expression;}%token T_REGISTER%token <value> T_CONST%token T_DOWNLOAD%token T_SCB%token T_SRAM%token T_ALIAS%token T_SIZE%token <value> T_ADDRESS%token T_ACCESS_MODE%token <value> T_MODE%token T_BIT%token T_MASK%token <value> T_NUMBER%token <str> T_PATH%token <sym> T_CEXPR%token T_EOF T_INCLUDE %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_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%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> ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne%type <value> numerical_value%left '|'%left '&'%left '+' '-'%right '~'%nonassoc UMINUS%%program: include| program include| register| program register| constant| program constant| scratch_ram| program scratch_ram| scb| program scb| label| program label| 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); };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| bit_defn| mask_defn| alias| accumulator| 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; };access_mode: T_ACCESS_MODE T_MODE { cur_symbol->info.rinfo->mode = $2; };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 != NULL) { stop("Only one accumulator definition allowed", EX_DATAERR); /* NOTREACHED */ } accumulator = 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 ')' { $$ = $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: { char buf[255]; snprintf(buf, sizeof(buf), "Undefined symbol %s referenced", symbol->name); stop(buf, EX_DATAERR); /* NOTREACHED */ break; } } SLIST_INIT(&$$.referenced_syms); symlist_add(&$$.referenced_syms, symbol, SYMLIST_INSERT_HEAD); };constant: T_CONST T_SYMBOL numerical_value { if ($2->type != UNINITIALIZED) { stop("Re-definition of symbol as a constant", EX_DATAERR); /* NOTREACHED */ } $2->type = CONST; initialize_symbol($2); $2->info.cinfo->value = $3; $2->info.cinfo->define = $1; }| T_CONST T_SYMBOL T_DOWNLOAD { if ($1) { stop("Invalid downloaded constant declaration", EX_DATAERR); /* NOTREACHED */ } if ($2->type != UNINITIALIZED) { stop("Re-definition of symbol as a downloaded constant", EX_DATAERR); /* NOTREACHED */ } $2->type = DOWNLOAD_CONST; initialize_symbol($2); $2->info.cinfo->value = download_constant_count++; $2->info.cinfo->define = FALSE; };numerical_value: T_NUMBER { $$ = $1; }| '-' T_NUMBER { $$ = -$2; };scratch_ram: T_SRAM '{' { 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); } reg_address { sram_or_scb_offset = cur_symbol->info.rinfo->address; } scb_or_sram_reg_list '}' { cur_symbol = NULL; };scb: T_SCB '{' { cur_symbol = symtable_get(SCB_SYMNAME); cur_symtype = SCBLOC; if (cur_symbol->type != UNINITIALIZED) { stop("Only one SRAM definition allowed", EX_SOFTWARE); /* NOTREACHED */ } cur_symbol->type = SCBLOC; initialize_symbol(cur_symbol); } reg_address { sram_or_scb_offset = cur_symbol->info.rinfo->address; } scb_or_sram_reg_list '}' { cur_symbol = NULL; };scb_or_sram_reg_list: reg_definition| scb_or_sram_reg_list reg_definition;reg_symbol: T_SYMBOL { process_register(&$1); $$.symbol = $1; $$.offset = 0; }| T_SYMBOL '[' T_NUMBER ']' { process_register(&$1); if (($3 + 1) > $1->info.rinfo->size) { stop("Accessing offset beyond range of register", EX_DATAERR); /* NOTREACHED */ } $$.symbol = $1; $$.offset = $3; }| T_A { if (accumulator == NULL) { stop("No accumulator has been defined", EX_DATAERR); /* NOTREACHED */ } $$.symbol = accumulator; $$.offset = 0; };destination: reg_symbol { test_writable_symbol($1.symbol); $$ = $1; };immediate: expression { $$ = $1; };immediate_or_a: expression { $$ = $1; }| T_A { SLIST_INIT(&$$.referenced_syms); $$.value = 0; };source: reg_symbol { test_readable_symbol($1.symbol); $$ = $1; };opt_source: { $$.symbol = NULL; $$.offset = 0; }| ',' source { $$ = $2; };ret: { $$ = 0; }| T_RET { $$ = 1; };label: T_SYMBOL ':' { if ($1->type != UNINITIALIZED) { stop("Program label multiply defined", EX_DATAERR); /* NOTREACHED */ } $1->type = LABEL; initialize_symbol($1); $1->info.linfo->address = instruction_ptr; };address: T_SYMBOL { $$.symbol = $1; $$.offset = 0; }| T_SYMBOL '+' T_NUMBER { $$.symbol = $1; $$.offset = $3; }| T_SYMBOL '-' T_NUMBER { $$.symbol = $1; $$.offset = -$3; }| '.' { $$.symbol = NULL; $$.offset = 0; }| '.' '+' T_NUMBER { $$.symbol = NULL; $$.offset = $3; }| '.' '-' T_NUMBER { $$.symbol = NULL; $$.offset = -$3; };conditional: T_IF T_CEXPR '{' { scope_t *new_scope; add_conditional($2); new_scope = scope_alloc(); new_scope->type = SCOPE_IF; new_scope->begin_addr = instruction_ptr; new_scope->func_num = $2->info.condinfo->func_num; }| T_ELSE T_IF T_CEXPR '{' { scope_t *new_scope; scope_t *scope_context; scope_t *last_scope; /* * Ensure that the previous scope is either an * if or and else if. */ scope_context = SLIST_FIRST(&scope_stack); last_scope = TAILQ_LAST(&scope_context->inner_scope, scope_tailq); if (last_scope == NULL || last_scope->type == T_ELSE) { stop("'else if' without leading 'if'", EX_DATAERR); /* NOTREACHED */ } add_conditional($3); new_scope = scope_alloc(); new_scope->type = SCOPE_ELSE_IF; new_scope->begin_addr = instruction_ptr; new_scope->func_num = $3->info.condinfo->func_num; }| T_ELSE '{'
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -