162306a36Sopenharmony_ci%{ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Parser for the Aic7xxx SCSI Host adapter sequencer assembler. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. 662306a36Sopenharmony_ci * Copyright (c) 2001, 2002 Adaptec Inc. 762306a36Sopenharmony_ci * All rights reserved. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 1062306a36Sopenharmony_ci * modification, are permitted provided that the following conditions 1162306a36Sopenharmony_ci * are met: 1262306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 1362306a36Sopenharmony_ci * notice, this list of conditions, and the following disclaimer, 1462306a36Sopenharmony_ci * without modification. 1562306a36Sopenharmony_ci * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1662306a36Sopenharmony_ci * substantially similar to the "NO WARRANTY" disclaimer below 1762306a36Sopenharmony_ci * ("Disclaimer") and any redistribution must be conditioned upon 1862306a36Sopenharmony_ci * including a substantially similar Disclaimer requirement for further 1962306a36Sopenharmony_ci * binary redistribution. 2062306a36Sopenharmony_ci * 3. Neither the names of the above-listed copyright holders nor the names 2162306a36Sopenharmony_ci * of any contributors may be used to endorse or promote products derived 2262306a36Sopenharmony_ci * from this software without specific prior written permission. 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the 2562306a36Sopenharmony_ci * GNU General Public License ("GPL") version 2 as published by the Free 2662306a36Sopenharmony_ci * Software Foundation. 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * NO WARRANTY 2962306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3062306a36Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3162306a36Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3262306a36Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3362306a36Sopenharmony_ci * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3462306a36Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3562306a36Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3662306a36Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3762306a36Sopenharmony_ci * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 3862306a36Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3962306a36Sopenharmony_ci * POSSIBILITY OF SUCH DAMAGES. 4062306a36Sopenharmony_ci * 4162306a36Sopenharmony_ci * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#30 $ 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * $FreeBSD$ 4462306a36Sopenharmony_ci */ 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#include <sys/types.h> 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#include <inttypes.h> 4962306a36Sopenharmony_ci#include <regex.h> 5062306a36Sopenharmony_ci#include <stdio.h> 5162306a36Sopenharmony_ci#include <stdlib.h> 5262306a36Sopenharmony_ci#include <string.h> 5362306a36Sopenharmony_ci#include <sysexits.h> 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#include "../queue.h" 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#include "aicasm.h" 5862306a36Sopenharmony_ci#include "aicasm_symbol.h" 5962306a36Sopenharmony_ci#include "aicasm_insformat.h" 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cichar *yyfilename; 6262306a36Sopenharmony_cichar stock_prefix[] = "aic_"; 6362306a36Sopenharmony_cichar *prefix = stock_prefix; 6462306a36Sopenharmony_cichar *patch_arg_list; 6562306a36Sopenharmony_cichar *versions; 6662306a36Sopenharmony_cistatic char errbuf[255]; 6762306a36Sopenharmony_cistatic char regex_pattern[255]; 6862306a36Sopenharmony_cistatic symbol_t *cur_symbol; 6962306a36Sopenharmony_cistatic symbol_t *field_symbol; 7062306a36Sopenharmony_cistatic symbol_t *scb_or_sram_symbol; 7162306a36Sopenharmony_cistatic symtype cur_symtype; 7262306a36Sopenharmony_cistatic symbol_ref_t accumulator; 7362306a36Sopenharmony_cistatic symbol_ref_t mode_ptr; 7462306a36Sopenharmony_cistatic symbol_ref_t allones; 7562306a36Sopenharmony_cistatic symbol_ref_t allzeros; 7662306a36Sopenharmony_cistatic symbol_ref_t none; 7762306a36Sopenharmony_cistatic symbol_ref_t sindex; 7862306a36Sopenharmony_cistatic int instruction_ptr; 7962306a36Sopenharmony_cistatic int num_srams; 8062306a36Sopenharmony_cistatic int sram_or_scb_offset; 8162306a36Sopenharmony_cistatic int download_constant_count; 8262306a36Sopenharmony_cistatic int in_critical_section; 8362306a36Sopenharmony_cistatic u_int enum_increment; 8462306a36Sopenharmony_cistatic u_int enum_next_value; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic void process_field(int field_type, symbol_t *sym, int mask); 8762306a36Sopenharmony_cistatic void initialize_symbol(symbol_t *symbol); 8862306a36Sopenharmony_cistatic void add_macro_arg(const char *argtext, int position); 8962306a36Sopenharmony_cistatic void add_macro_body(const char *bodytext); 9062306a36Sopenharmony_cistatic void process_register(symbol_t **p_symbol); 9162306a36Sopenharmony_cistatic void format_1_instr(int opcode, symbol_ref_t *dest, 9262306a36Sopenharmony_ci expression_t *immed, symbol_ref_t *src, int ret); 9362306a36Sopenharmony_cistatic void format_2_instr(int opcode, symbol_ref_t *dest, 9462306a36Sopenharmony_ci expression_t *places, symbol_ref_t *src, int ret); 9562306a36Sopenharmony_cistatic void format_3_instr(int opcode, symbol_ref_t *src, 9662306a36Sopenharmony_ci expression_t *immed, symbol_ref_t *address); 9762306a36Sopenharmony_cistatic void test_readable_symbol(symbol_t *symbol); 9862306a36Sopenharmony_cistatic void test_writable_symbol(symbol_t *symbol); 9962306a36Sopenharmony_cistatic void type_check(symbol_ref_t *sym, expression_t *expression, int and_op); 10062306a36Sopenharmony_cistatic void make_expression(expression_t *immed, int value); 10162306a36Sopenharmony_cistatic void add_conditional(symbol_t *symbol); 10262306a36Sopenharmony_cistatic void add_version(const char *verstring); 10362306a36Sopenharmony_cistatic int is_download_const(expression_t *immed); 10462306a36Sopenharmony_cistatic int is_location_address(symbol_t *symbol); 10562306a36Sopenharmony_civoid yyerror(const char *string); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci#define SRAM_SYMNAME "SRAM_BASE" 10862306a36Sopenharmony_ci#define SCB_SYMNAME "SCB_BASE" 10962306a36Sopenharmony_ci%} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci%union { 11262306a36Sopenharmony_ci u_int value; 11362306a36Sopenharmony_ci char *str; 11462306a36Sopenharmony_ci symbol_t *sym; 11562306a36Sopenharmony_ci symbol_ref_t sym_ref; 11662306a36Sopenharmony_ci expression_t expression; 11762306a36Sopenharmony_ci} 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci%token T_REGISTER 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci%token <value> T_CONST 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci%token T_EXPORT 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci%token T_DOWNLOAD 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci%token T_SCB 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci%token T_SRAM 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci%token T_ALIAS 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci%token T_SIZE 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci%token T_EXPR_LSHIFT 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci%token T_EXPR_RSHIFT 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci%token <value> T_ADDRESS 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci%token T_COUNT 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci%token T_ACCESS_MODE 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci%token T_DONT_GENERATE_DEBUG_CODE 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci%token T_MODES 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci%token T_DEFINE 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci%token T_SET_SRC_MODE 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci%token T_SET_DST_MODE 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci%token <value> T_MODE 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci%token T_BEGIN_CS 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci%token T_END_CS 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci%token T_PAD_PAGE 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci%token T_FIELD 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci%token T_ENUM 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci%token T_MASK 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci%token <value> T_NUMBER 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci%token <str> T_PATH T_STRING T_ARG T_MACROBODY 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci%token <sym> T_CEXPR 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci%token T_EOF T_INCLUDE T_VERSION T_PREFIX T_PATCH_ARG_LIST 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci%token <value> T_SHR T_SHL T_ROR T_ROL 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci%token <value> T_MVI T_MOV T_CLR T_BMOV 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci%token <value> T_JMP T_JC T_JNC T_JE T_JNE T_JNZ T_JZ T_CALL 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci%token <value> T_ADD T_ADC 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci%token <value> T_INC T_DEC 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci%token <value> T_STC T_CLC 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci%token <value> T_CMP T_NOT T_XOR 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci%token <value> T_TEST T_AND 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci%token <value> T_OR 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci/* 16 bit extensions, not implemented 19662306a36Sopenharmony_ci * %token <value> T_OR16 T_AND16 T_XOR16 T_ADD16 19762306a36Sopenharmony_ci * %token <value> T_ADC16 T_MVI16 T_TEST16 T_CMP16 T_CMPXCHG 19862306a36Sopenharmony_ci */ 19962306a36Sopenharmony_ci%token T_RET 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci%token T_NOP 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci%token T_ACCUM T_ALLONES T_ALLZEROS T_NONE T_SINDEX T_MODE_PTR 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci%token T_A 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci%token <sym> T_SYMBOL 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci%token T_NL 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci%token T_IF T_ELSE T_ELSE_IF T_ENDIF 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci%type <sym_ref> reg_symbol address destination source opt_source 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci%type <expression> expression immediate immediate_or_a 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci%type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci%type <value> mode_value mode_list macro_arglist 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci%left '|' 22262306a36Sopenharmony_ci%left '&' 22362306a36Sopenharmony_ci%left T_EXPR_LSHIFT T_EXPR_RSHIFT 22462306a36Sopenharmony_ci%left '+' '-' 22562306a36Sopenharmony_ci%left '*' '/' 22662306a36Sopenharmony_ci%right '~' 22762306a36Sopenharmony_ci%nonassoc UMINUS 22862306a36Sopenharmony_ci%% 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ciprogram: 23162306a36Sopenharmony_ci include 23262306a36Sopenharmony_ci| program include 23362306a36Sopenharmony_ci| prefix 23462306a36Sopenharmony_ci| program prefix 23562306a36Sopenharmony_ci| patch_arg_list 23662306a36Sopenharmony_ci| program patch_arg_list 23762306a36Sopenharmony_ci| version 23862306a36Sopenharmony_ci| program version 23962306a36Sopenharmony_ci| register 24062306a36Sopenharmony_ci| program register 24162306a36Sopenharmony_ci| constant 24262306a36Sopenharmony_ci| program constant 24362306a36Sopenharmony_ci| macrodefn 24462306a36Sopenharmony_ci| program macrodefn 24562306a36Sopenharmony_ci| scratch_ram 24662306a36Sopenharmony_ci| program scratch_ram 24762306a36Sopenharmony_ci| scb 24862306a36Sopenharmony_ci| program scb 24962306a36Sopenharmony_ci| label 25062306a36Sopenharmony_ci| program label 25162306a36Sopenharmony_ci| set_src_mode 25262306a36Sopenharmony_ci| program set_src_mode 25362306a36Sopenharmony_ci| set_dst_mode 25462306a36Sopenharmony_ci| program set_dst_mode 25562306a36Sopenharmony_ci| critical_section_start 25662306a36Sopenharmony_ci| program critical_section_start 25762306a36Sopenharmony_ci| critical_section_end 25862306a36Sopenharmony_ci| program critical_section_end 25962306a36Sopenharmony_ci| conditional 26062306a36Sopenharmony_ci| program conditional 26162306a36Sopenharmony_ci| code 26262306a36Sopenharmony_ci| program code 26362306a36Sopenharmony_ci; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ciinclude: 26662306a36Sopenharmony_ci T_INCLUDE '<' T_PATH '>' 26762306a36Sopenharmony_ci { 26862306a36Sopenharmony_ci include_file($3, BRACKETED_INCLUDE); 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci| T_INCLUDE '"' T_PATH '"' 27162306a36Sopenharmony_ci { 27262306a36Sopenharmony_ci include_file($3, QUOTED_INCLUDE); 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ciprefix: 27762306a36Sopenharmony_ci T_PREFIX '=' T_STRING 27862306a36Sopenharmony_ci { 27962306a36Sopenharmony_ci if (prefix != stock_prefix) 28062306a36Sopenharmony_ci stop("Prefix multiply defined", 28162306a36Sopenharmony_ci EX_DATAERR); 28262306a36Sopenharmony_ci prefix = strdup($3); 28362306a36Sopenharmony_ci if (prefix == NULL) 28462306a36Sopenharmony_ci stop("Unable to record prefix", EX_SOFTWARE); 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_cipatch_arg_list: 28962306a36Sopenharmony_ci T_PATCH_ARG_LIST '=' T_STRING 29062306a36Sopenharmony_ci { 29162306a36Sopenharmony_ci if (patch_arg_list != NULL) 29262306a36Sopenharmony_ci stop("Patch argument list multiply defined", 29362306a36Sopenharmony_ci EX_DATAERR); 29462306a36Sopenharmony_ci patch_arg_list = strdup($3); 29562306a36Sopenharmony_ci if (patch_arg_list == NULL) 29662306a36Sopenharmony_ci stop("Unable to record patch arg list", EX_SOFTWARE); 29762306a36Sopenharmony_ci } 29862306a36Sopenharmony_ci; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_civersion: 30162306a36Sopenharmony_ci T_VERSION '=' T_STRING 30262306a36Sopenharmony_ci { add_version($3); } 30362306a36Sopenharmony_ci; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ciregister: 30662306a36Sopenharmony_ci T_REGISTER { cur_symtype = REGISTER; } reg_definition 30762306a36Sopenharmony_ci; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_cireg_definition: 31062306a36Sopenharmony_ci T_SYMBOL '{' 31162306a36Sopenharmony_ci { 31262306a36Sopenharmony_ci if ($1->type != UNINITIALIZED) { 31362306a36Sopenharmony_ci stop("Register multiply defined", EX_DATAERR); 31462306a36Sopenharmony_ci /* NOTREACHED */ 31562306a36Sopenharmony_ci } 31662306a36Sopenharmony_ci cur_symbol = $1; 31762306a36Sopenharmony_ci cur_symbol->type = cur_symtype; 31862306a36Sopenharmony_ci initialize_symbol(cur_symbol); 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci reg_attribute_list 32162306a36Sopenharmony_ci '}' 32262306a36Sopenharmony_ci { 32362306a36Sopenharmony_ci /* 32462306a36Sopenharmony_ci * Default to allowing everything in for registers 32562306a36Sopenharmony_ci * with no bit or mask definitions. 32662306a36Sopenharmony_ci */ 32762306a36Sopenharmony_ci if (cur_symbol->info.rinfo->valid_bitmask == 0) 32862306a36Sopenharmony_ci cur_symbol->info.rinfo->valid_bitmask = 0xFF; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci if (cur_symbol->info.rinfo->size == 0) 33162306a36Sopenharmony_ci cur_symbol->info.rinfo->size = 1; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci /* 33462306a36Sopenharmony_ci * This might be useful for registers too. 33562306a36Sopenharmony_ci */ 33662306a36Sopenharmony_ci if (cur_symbol->type != REGISTER) { 33762306a36Sopenharmony_ci if (cur_symbol->info.rinfo->address == 0) 33862306a36Sopenharmony_ci cur_symbol->info.rinfo->address = 33962306a36Sopenharmony_ci sram_or_scb_offset; 34062306a36Sopenharmony_ci sram_or_scb_offset += 34162306a36Sopenharmony_ci cur_symbol->info.rinfo->size; 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci cur_symbol = NULL; 34462306a36Sopenharmony_ci } 34562306a36Sopenharmony_ci; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_cireg_attribute_list: 34862306a36Sopenharmony_ci reg_attribute 34962306a36Sopenharmony_ci| reg_attribute_list reg_attribute 35062306a36Sopenharmony_ci; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cireg_attribute: 35362306a36Sopenharmony_ci reg_address 35462306a36Sopenharmony_ci| size 35562306a36Sopenharmony_ci| count 35662306a36Sopenharmony_ci| access_mode 35762306a36Sopenharmony_ci| dont_generate_debug_code 35862306a36Sopenharmony_ci| modes 35962306a36Sopenharmony_ci| field_defn 36062306a36Sopenharmony_ci| enum_defn 36162306a36Sopenharmony_ci| mask_defn 36262306a36Sopenharmony_ci| alias 36362306a36Sopenharmony_ci| accumulator 36462306a36Sopenharmony_ci| mode_pointer 36562306a36Sopenharmony_ci| allones 36662306a36Sopenharmony_ci| allzeros 36762306a36Sopenharmony_ci| none 36862306a36Sopenharmony_ci| sindex 36962306a36Sopenharmony_ci; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_cireg_address: 37262306a36Sopenharmony_ci T_ADDRESS T_NUMBER 37362306a36Sopenharmony_ci { 37462306a36Sopenharmony_ci cur_symbol->info.rinfo->address = $2; 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_cisize: 37962306a36Sopenharmony_ci T_SIZE T_NUMBER 38062306a36Sopenharmony_ci { 38162306a36Sopenharmony_ci cur_symbol->info.rinfo->size = $2; 38262306a36Sopenharmony_ci if (scb_or_sram_symbol != NULL) { 38362306a36Sopenharmony_ci u_int max_addr; 38462306a36Sopenharmony_ci u_int sym_max_addr; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci max_addr = scb_or_sram_symbol->info.rinfo->address 38762306a36Sopenharmony_ci + scb_or_sram_symbol->info.rinfo->size; 38862306a36Sopenharmony_ci sym_max_addr = cur_symbol->info.rinfo->address 38962306a36Sopenharmony_ci + cur_symbol->info.rinfo->size; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci if (sym_max_addr > max_addr) 39262306a36Sopenharmony_ci stop("SCB or SRAM space exhausted", EX_DATAERR); 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_cicount: 39862306a36Sopenharmony_ci T_COUNT T_NUMBER 39962306a36Sopenharmony_ci { 40062306a36Sopenharmony_ci cur_symbol->count += $2; 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ciaccess_mode: 40562306a36Sopenharmony_ci T_ACCESS_MODE T_MODE 40662306a36Sopenharmony_ci { 40762306a36Sopenharmony_ci cur_symbol->info.rinfo->mode = $2; 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_cidont_generate_debug_code: 41262306a36Sopenharmony_ci T_DONT_GENERATE_DEBUG_CODE 41362306a36Sopenharmony_ci { 41462306a36Sopenharmony_ci cur_symbol->dont_generate_debug_code = 1; 41562306a36Sopenharmony_ci } 41662306a36Sopenharmony_ci; 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_cimodes: 41962306a36Sopenharmony_ci T_MODES mode_list 42062306a36Sopenharmony_ci { 42162306a36Sopenharmony_ci cur_symbol->info.rinfo->modes = $2; 42262306a36Sopenharmony_ci } 42362306a36Sopenharmony_ci; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_cimode_list: 42662306a36Sopenharmony_ci mode_value 42762306a36Sopenharmony_ci { 42862306a36Sopenharmony_ci $$ = $1; 42962306a36Sopenharmony_ci } 43062306a36Sopenharmony_ci| mode_list ',' mode_value 43162306a36Sopenharmony_ci { 43262306a36Sopenharmony_ci $$ = $1 | $3; 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_cimode_value: 43762306a36Sopenharmony_ci T_NUMBER 43862306a36Sopenharmony_ci { 43962306a36Sopenharmony_ci if ($1 > 4) { 44062306a36Sopenharmony_ci stop("Valid register modes range between 0 and 4.", 44162306a36Sopenharmony_ci EX_DATAERR); 44262306a36Sopenharmony_ci /* NOTREACHED */ 44362306a36Sopenharmony_ci } 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci $$ = (0x1 << $1); 44662306a36Sopenharmony_ci } 44762306a36Sopenharmony_ci| T_SYMBOL 44862306a36Sopenharmony_ci { 44962306a36Sopenharmony_ci symbol_t *symbol; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci symbol = $1; 45262306a36Sopenharmony_ci if (symbol->type != CONST) { 45362306a36Sopenharmony_ci stop("Only \"const\" symbols allowed in " 45462306a36Sopenharmony_ci "mode definitions.", EX_DATAERR); 45562306a36Sopenharmony_ci /* NOTREACHED */ 45662306a36Sopenharmony_ci } 45762306a36Sopenharmony_ci if (symbol->info.cinfo->value > 4) { 45862306a36Sopenharmony_ci stop("Valid register modes range between 0 and 4.", 45962306a36Sopenharmony_ci EX_DATAERR); 46062306a36Sopenharmony_ci /* NOTREACHED */ 46162306a36Sopenharmony_ci } 46262306a36Sopenharmony_ci $$ = (0x1 << symbol->info.cinfo->value); 46362306a36Sopenharmony_ci } 46462306a36Sopenharmony_ci; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_cifield_defn: 46762306a36Sopenharmony_ci T_FIELD 46862306a36Sopenharmony_ci { 46962306a36Sopenharmony_ci field_symbol = NULL; 47062306a36Sopenharmony_ci enum_next_value = 0; 47162306a36Sopenharmony_ci enum_increment = 1; 47262306a36Sopenharmony_ci } 47362306a36Sopenharmony_ci '{' enum_entry_list '}' 47462306a36Sopenharmony_ci| T_FIELD T_SYMBOL expression 47562306a36Sopenharmony_ci { 47662306a36Sopenharmony_ci process_field(FIELD, $2, $3.value); 47762306a36Sopenharmony_ci field_symbol = $2; 47862306a36Sopenharmony_ci enum_next_value = 0; 47962306a36Sopenharmony_ci enum_increment = 0x01 << (ffs($3.value) - 1); 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci '{' enum_entry_list '}' 48262306a36Sopenharmony_ci| T_FIELD T_SYMBOL expression 48362306a36Sopenharmony_ci { 48462306a36Sopenharmony_ci process_field(FIELD, $2, $3.value); 48562306a36Sopenharmony_ci } 48662306a36Sopenharmony_ci; 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_cienum_defn: 48962306a36Sopenharmony_ci T_ENUM 49062306a36Sopenharmony_ci { 49162306a36Sopenharmony_ci field_symbol = NULL; 49262306a36Sopenharmony_ci enum_next_value = 0; 49362306a36Sopenharmony_ci enum_increment = 1; 49462306a36Sopenharmony_ci } 49562306a36Sopenharmony_ci '{' enum_entry_list '}' 49662306a36Sopenharmony_ci| T_ENUM T_SYMBOL expression 49762306a36Sopenharmony_ci { 49862306a36Sopenharmony_ci process_field(ENUM, $2, $3.value); 49962306a36Sopenharmony_ci field_symbol = $2; 50062306a36Sopenharmony_ci enum_next_value = 0; 50162306a36Sopenharmony_ci enum_increment = 0x01 << (ffs($3.value) - 1); 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci '{' enum_entry_list '}' 50462306a36Sopenharmony_ci; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_cienum_entry_list: 50762306a36Sopenharmony_ci enum_entry 50862306a36Sopenharmony_ci| enum_entry_list ',' enum_entry 50962306a36Sopenharmony_ci; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_cienum_entry: 51262306a36Sopenharmony_ci T_SYMBOL 51362306a36Sopenharmony_ci { 51462306a36Sopenharmony_ci process_field(ENUM_ENTRY, $1, enum_next_value); 51562306a36Sopenharmony_ci enum_next_value += enum_increment; 51662306a36Sopenharmony_ci } 51762306a36Sopenharmony_ci| T_SYMBOL expression 51862306a36Sopenharmony_ci { 51962306a36Sopenharmony_ci process_field(ENUM_ENTRY, $1, $2.value); 52062306a36Sopenharmony_ci enum_next_value = $2.value + enum_increment; 52162306a36Sopenharmony_ci } 52262306a36Sopenharmony_ci; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_cimask_defn: 52562306a36Sopenharmony_ci T_MASK T_SYMBOL expression 52662306a36Sopenharmony_ci { 52762306a36Sopenharmony_ci process_field(MASK, $2, $3.value); 52862306a36Sopenharmony_ci } 52962306a36Sopenharmony_ci; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_cialias: 53262306a36Sopenharmony_ci T_ALIAS T_SYMBOL 53362306a36Sopenharmony_ci { 53462306a36Sopenharmony_ci if ($2->type != UNINITIALIZED) { 53562306a36Sopenharmony_ci stop("Re-definition of register alias", 53662306a36Sopenharmony_ci EX_DATAERR); 53762306a36Sopenharmony_ci /* NOTREACHED */ 53862306a36Sopenharmony_ci } 53962306a36Sopenharmony_ci $2->type = ALIAS; 54062306a36Sopenharmony_ci initialize_symbol($2); 54162306a36Sopenharmony_ci $2->info.ainfo->parent = cur_symbol; 54262306a36Sopenharmony_ci } 54362306a36Sopenharmony_ci; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ciaccumulator: 54662306a36Sopenharmony_ci T_ACCUM 54762306a36Sopenharmony_ci { 54862306a36Sopenharmony_ci if (accumulator.symbol != NULL) { 54962306a36Sopenharmony_ci stop("Only one accumulator definition allowed", 55062306a36Sopenharmony_ci EX_DATAERR); 55162306a36Sopenharmony_ci /* NOTREACHED */ 55262306a36Sopenharmony_ci } 55362306a36Sopenharmony_ci accumulator.symbol = cur_symbol; 55462306a36Sopenharmony_ci } 55562306a36Sopenharmony_ci; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_cimode_pointer: 55862306a36Sopenharmony_ci T_MODE_PTR 55962306a36Sopenharmony_ci { 56062306a36Sopenharmony_ci if (mode_ptr.symbol != NULL) { 56162306a36Sopenharmony_ci stop("Only one mode pointer definition allowed", 56262306a36Sopenharmony_ci EX_DATAERR); 56362306a36Sopenharmony_ci /* NOTREACHED */ 56462306a36Sopenharmony_ci } 56562306a36Sopenharmony_ci mode_ptr.symbol = cur_symbol; 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ciallones: 57062306a36Sopenharmony_ci T_ALLONES 57162306a36Sopenharmony_ci { 57262306a36Sopenharmony_ci if (allones.symbol != NULL) { 57362306a36Sopenharmony_ci stop("Only one definition of allones allowed", 57462306a36Sopenharmony_ci EX_DATAERR); 57562306a36Sopenharmony_ci /* NOTREACHED */ 57662306a36Sopenharmony_ci } 57762306a36Sopenharmony_ci allones.symbol = cur_symbol; 57862306a36Sopenharmony_ci } 57962306a36Sopenharmony_ci; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ciallzeros: 58262306a36Sopenharmony_ci T_ALLZEROS 58362306a36Sopenharmony_ci { 58462306a36Sopenharmony_ci if (allzeros.symbol != NULL) { 58562306a36Sopenharmony_ci stop("Only one definition of allzeros allowed", 58662306a36Sopenharmony_ci EX_DATAERR); 58762306a36Sopenharmony_ci /* NOTREACHED */ 58862306a36Sopenharmony_ci } 58962306a36Sopenharmony_ci allzeros.symbol = cur_symbol; 59062306a36Sopenharmony_ci } 59162306a36Sopenharmony_ci; 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_cinone: 59462306a36Sopenharmony_ci T_NONE 59562306a36Sopenharmony_ci { 59662306a36Sopenharmony_ci if (none.symbol != NULL) { 59762306a36Sopenharmony_ci stop("Only one definition of none allowed", 59862306a36Sopenharmony_ci EX_DATAERR); 59962306a36Sopenharmony_ci /* NOTREACHED */ 60062306a36Sopenharmony_ci } 60162306a36Sopenharmony_ci none.symbol = cur_symbol; 60262306a36Sopenharmony_ci } 60362306a36Sopenharmony_ci; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_cisindex: 60662306a36Sopenharmony_ci T_SINDEX 60762306a36Sopenharmony_ci { 60862306a36Sopenharmony_ci if (sindex.symbol != NULL) { 60962306a36Sopenharmony_ci stop("Only one definition of sindex allowed", 61062306a36Sopenharmony_ci EX_DATAERR); 61162306a36Sopenharmony_ci /* NOTREACHED */ 61262306a36Sopenharmony_ci } 61362306a36Sopenharmony_ci sindex.symbol = cur_symbol; 61462306a36Sopenharmony_ci } 61562306a36Sopenharmony_ci; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ciexpression: 61862306a36Sopenharmony_ci expression '|' expression 61962306a36Sopenharmony_ci { 62062306a36Sopenharmony_ci $$.value = $1.value | $3.value; 62162306a36Sopenharmony_ci symlist_merge(&$$.referenced_syms, 62262306a36Sopenharmony_ci &$1.referenced_syms, 62362306a36Sopenharmony_ci &$3.referenced_syms); 62462306a36Sopenharmony_ci } 62562306a36Sopenharmony_ci| expression '&' expression 62662306a36Sopenharmony_ci { 62762306a36Sopenharmony_ci $$.value = $1.value & $3.value; 62862306a36Sopenharmony_ci symlist_merge(&$$.referenced_syms, 62962306a36Sopenharmony_ci &$1.referenced_syms, 63062306a36Sopenharmony_ci &$3.referenced_syms); 63162306a36Sopenharmony_ci } 63262306a36Sopenharmony_ci| expression '+' expression 63362306a36Sopenharmony_ci { 63462306a36Sopenharmony_ci $$.value = $1.value + $3.value; 63562306a36Sopenharmony_ci symlist_merge(&$$.referenced_syms, 63662306a36Sopenharmony_ci &$1.referenced_syms, 63762306a36Sopenharmony_ci &$3.referenced_syms); 63862306a36Sopenharmony_ci } 63962306a36Sopenharmony_ci| expression '-' expression 64062306a36Sopenharmony_ci { 64162306a36Sopenharmony_ci $$.value = $1.value - $3.value; 64262306a36Sopenharmony_ci symlist_merge(&($$.referenced_syms), 64362306a36Sopenharmony_ci &($1.referenced_syms), 64462306a36Sopenharmony_ci &($3.referenced_syms)); 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci| expression '*' expression 64762306a36Sopenharmony_ci { 64862306a36Sopenharmony_ci $$.value = $1.value * $3.value; 64962306a36Sopenharmony_ci symlist_merge(&($$.referenced_syms), 65062306a36Sopenharmony_ci &($1.referenced_syms), 65162306a36Sopenharmony_ci &($3.referenced_syms)); 65262306a36Sopenharmony_ci } 65362306a36Sopenharmony_ci| expression '/' expression 65462306a36Sopenharmony_ci { 65562306a36Sopenharmony_ci $$.value = $1.value / $3.value; 65662306a36Sopenharmony_ci symlist_merge(&($$.referenced_syms), 65762306a36Sopenharmony_ci &($1.referenced_syms), 65862306a36Sopenharmony_ci &($3.referenced_syms)); 65962306a36Sopenharmony_ci } 66062306a36Sopenharmony_ci| expression T_EXPR_LSHIFT expression 66162306a36Sopenharmony_ci { 66262306a36Sopenharmony_ci $$.value = $1.value << $3.value; 66362306a36Sopenharmony_ci symlist_merge(&$$.referenced_syms, 66462306a36Sopenharmony_ci &$1.referenced_syms, 66562306a36Sopenharmony_ci &$3.referenced_syms); 66662306a36Sopenharmony_ci } 66762306a36Sopenharmony_ci| expression T_EXPR_RSHIFT expression 66862306a36Sopenharmony_ci { 66962306a36Sopenharmony_ci $$.value = $1.value >> $3.value; 67062306a36Sopenharmony_ci symlist_merge(&$$.referenced_syms, 67162306a36Sopenharmony_ci &$1.referenced_syms, 67262306a36Sopenharmony_ci &$3.referenced_syms); 67362306a36Sopenharmony_ci } 67462306a36Sopenharmony_ci| '(' expression ')' 67562306a36Sopenharmony_ci { 67662306a36Sopenharmony_ci $$ = $2; 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci| '~' expression 67962306a36Sopenharmony_ci { 68062306a36Sopenharmony_ci $$ = $2; 68162306a36Sopenharmony_ci $$.value = (~$$.value) & 0xFF; 68262306a36Sopenharmony_ci } 68362306a36Sopenharmony_ci| '-' expression %prec UMINUS 68462306a36Sopenharmony_ci { 68562306a36Sopenharmony_ci $$ = $2; 68662306a36Sopenharmony_ci $$.value = -$$.value; 68762306a36Sopenharmony_ci } 68862306a36Sopenharmony_ci| T_NUMBER 68962306a36Sopenharmony_ci { 69062306a36Sopenharmony_ci $$.value = $1; 69162306a36Sopenharmony_ci SLIST_INIT(&$$.referenced_syms); 69262306a36Sopenharmony_ci } 69362306a36Sopenharmony_ci| T_SYMBOL 69462306a36Sopenharmony_ci { 69562306a36Sopenharmony_ci symbol_t *symbol; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci symbol = $1; 69862306a36Sopenharmony_ci switch (symbol->type) { 69962306a36Sopenharmony_ci case ALIAS: 70062306a36Sopenharmony_ci symbol = $1->info.ainfo->parent; 70162306a36Sopenharmony_ci case REGISTER: 70262306a36Sopenharmony_ci case SCBLOC: 70362306a36Sopenharmony_ci case SRAMLOC: 70462306a36Sopenharmony_ci $$.value = symbol->info.rinfo->address; 70562306a36Sopenharmony_ci break; 70662306a36Sopenharmony_ci case MASK: 70762306a36Sopenharmony_ci case FIELD: 70862306a36Sopenharmony_ci case ENUM: 70962306a36Sopenharmony_ci case ENUM_ENTRY: 71062306a36Sopenharmony_ci $$.value = symbol->info.finfo->value; 71162306a36Sopenharmony_ci break; 71262306a36Sopenharmony_ci case DOWNLOAD_CONST: 71362306a36Sopenharmony_ci case CONST: 71462306a36Sopenharmony_ci $$.value = symbol->info.cinfo->value; 71562306a36Sopenharmony_ci break; 71662306a36Sopenharmony_ci case UNINITIALIZED: 71762306a36Sopenharmony_ci default: 71862306a36Sopenharmony_ci { 71962306a36Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), 72062306a36Sopenharmony_ci "Undefined symbol %s referenced", 72162306a36Sopenharmony_ci symbol->name); 72262306a36Sopenharmony_ci stop(errbuf, EX_DATAERR); 72362306a36Sopenharmony_ci /* NOTREACHED */ 72462306a36Sopenharmony_ci break; 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci } 72762306a36Sopenharmony_ci SLIST_INIT(&$$.referenced_syms); 72862306a36Sopenharmony_ci symlist_add(&$$.referenced_syms, symbol, SYMLIST_INSERT_HEAD); 72962306a36Sopenharmony_ci } 73062306a36Sopenharmony_ci; 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ciconstant: 73362306a36Sopenharmony_ci T_CONST T_SYMBOL expression 73462306a36Sopenharmony_ci { 73562306a36Sopenharmony_ci if ($2->type != UNINITIALIZED) { 73662306a36Sopenharmony_ci stop("Re-definition of symbol as a constant", 73762306a36Sopenharmony_ci EX_DATAERR); 73862306a36Sopenharmony_ci /* NOTREACHED */ 73962306a36Sopenharmony_ci } 74062306a36Sopenharmony_ci $2->type = CONST; 74162306a36Sopenharmony_ci initialize_symbol($2); 74262306a36Sopenharmony_ci $2->info.cinfo->value = $3.value; 74362306a36Sopenharmony_ci } 74462306a36Sopenharmony_ci| T_CONST T_SYMBOL T_DOWNLOAD 74562306a36Sopenharmony_ci { 74662306a36Sopenharmony_ci if ($1) { 74762306a36Sopenharmony_ci stop("Invalid downloaded constant declaration", 74862306a36Sopenharmony_ci EX_DATAERR); 74962306a36Sopenharmony_ci /* NOTREACHED */ 75062306a36Sopenharmony_ci } 75162306a36Sopenharmony_ci if ($2->type != UNINITIALIZED) { 75262306a36Sopenharmony_ci stop("Re-definition of symbol as a downloaded constant", 75362306a36Sopenharmony_ci EX_DATAERR); 75462306a36Sopenharmony_ci /* NOTREACHED */ 75562306a36Sopenharmony_ci } 75662306a36Sopenharmony_ci $2->type = DOWNLOAD_CONST; 75762306a36Sopenharmony_ci initialize_symbol($2); 75862306a36Sopenharmony_ci $2->info.cinfo->value = download_constant_count++; 75962306a36Sopenharmony_ci } 76062306a36Sopenharmony_ci; 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_cimacrodefn_prologue: 76362306a36Sopenharmony_ci T_DEFINE T_SYMBOL 76462306a36Sopenharmony_ci { 76562306a36Sopenharmony_ci if ($2->type != UNINITIALIZED) { 76662306a36Sopenharmony_ci stop("Re-definition of symbol as a macro", 76762306a36Sopenharmony_ci EX_DATAERR); 76862306a36Sopenharmony_ci /* NOTREACHED */ 76962306a36Sopenharmony_ci } 77062306a36Sopenharmony_ci cur_symbol = $2; 77162306a36Sopenharmony_ci cur_symbol->type = MACRO; 77262306a36Sopenharmony_ci initialize_symbol(cur_symbol); 77362306a36Sopenharmony_ci } 77462306a36Sopenharmony_ci; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_cimacrodefn: 77762306a36Sopenharmony_ci macrodefn_prologue T_MACROBODY 77862306a36Sopenharmony_ci { 77962306a36Sopenharmony_ci add_macro_body($2); 78062306a36Sopenharmony_ci } 78162306a36Sopenharmony_ci| macrodefn_prologue '(' macro_arglist ')' T_MACROBODY 78262306a36Sopenharmony_ci { 78362306a36Sopenharmony_ci add_macro_body($5); 78462306a36Sopenharmony_ci cur_symbol->info.macroinfo->narg = $3; 78562306a36Sopenharmony_ci } 78662306a36Sopenharmony_ci; 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_cimacro_arglist: 78962306a36Sopenharmony_ci { 79062306a36Sopenharmony_ci /* Macros can take no arguments */ 79162306a36Sopenharmony_ci $$ = 0; 79262306a36Sopenharmony_ci } 79362306a36Sopenharmony_ci| T_ARG 79462306a36Sopenharmony_ci { 79562306a36Sopenharmony_ci $$ = 1; 79662306a36Sopenharmony_ci add_macro_arg($1, 0); 79762306a36Sopenharmony_ci } 79862306a36Sopenharmony_ci| macro_arglist ',' T_ARG 79962306a36Sopenharmony_ci { 80062306a36Sopenharmony_ci if ($1 == 0) { 80162306a36Sopenharmony_ci stop("Comma without preceding argument in arg list", 80262306a36Sopenharmony_ci EX_DATAERR); 80362306a36Sopenharmony_ci /* NOTREACHED */ 80462306a36Sopenharmony_ci } 80562306a36Sopenharmony_ci $$ = $1 + 1; 80662306a36Sopenharmony_ci add_macro_arg($3, $1); 80762306a36Sopenharmony_ci } 80862306a36Sopenharmony_ci; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ciscratch_ram: 81162306a36Sopenharmony_ci T_SRAM '{' 81262306a36Sopenharmony_ci { 81362306a36Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), "%s%d", SRAM_SYMNAME, 81462306a36Sopenharmony_ci num_srams); 81562306a36Sopenharmony_ci cur_symbol = symtable_get(SRAM_SYMNAME); 81662306a36Sopenharmony_ci cur_symtype = SRAMLOC; 81762306a36Sopenharmony_ci cur_symbol->type = SRAMLOC; 81862306a36Sopenharmony_ci initialize_symbol(cur_symbol); 81962306a36Sopenharmony_ci cur_symbol->count += 1; 82062306a36Sopenharmony_ci } 82162306a36Sopenharmony_ci reg_address 82262306a36Sopenharmony_ci { 82362306a36Sopenharmony_ci sram_or_scb_offset = cur_symbol->info.rinfo->address; 82462306a36Sopenharmony_ci } 82562306a36Sopenharmony_ci size 82662306a36Sopenharmony_ci { 82762306a36Sopenharmony_ci scb_or_sram_symbol = cur_symbol; 82862306a36Sopenharmony_ci } 82962306a36Sopenharmony_ci scb_or_sram_attributes 83062306a36Sopenharmony_ci '}' 83162306a36Sopenharmony_ci { 83262306a36Sopenharmony_ci cur_symbol = NULL; 83362306a36Sopenharmony_ci scb_or_sram_symbol = NULL; 83462306a36Sopenharmony_ci } 83562306a36Sopenharmony_ci; 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ciscb: 83862306a36Sopenharmony_ci T_SCB '{' 83962306a36Sopenharmony_ci { 84062306a36Sopenharmony_ci cur_symbol = symtable_get(SCB_SYMNAME); 84162306a36Sopenharmony_ci cur_symtype = SCBLOC; 84262306a36Sopenharmony_ci if (cur_symbol->type != UNINITIALIZED) { 84362306a36Sopenharmony_ci stop("Only one SRAM definition allowed", 84462306a36Sopenharmony_ci EX_SOFTWARE); 84562306a36Sopenharmony_ci /* NOTREACHED */ 84662306a36Sopenharmony_ci } 84762306a36Sopenharmony_ci cur_symbol->type = SCBLOC; 84862306a36Sopenharmony_ci initialize_symbol(cur_symbol); 84962306a36Sopenharmony_ci /* 64 bytes of SCB space */ 85062306a36Sopenharmony_ci cur_symbol->info.rinfo->size = 64; 85162306a36Sopenharmony_ci cur_symbol->count += 1; 85262306a36Sopenharmony_ci } 85362306a36Sopenharmony_ci reg_address 85462306a36Sopenharmony_ci { 85562306a36Sopenharmony_ci sram_or_scb_offset = cur_symbol->info.rinfo->address; 85662306a36Sopenharmony_ci } 85762306a36Sopenharmony_ci size 85862306a36Sopenharmony_ci { 85962306a36Sopenharmony_ci scb_or_sram_symbol = cur_symbol; 86062306a36Sopenharmony_ci } 86162306a36Sopenharmony_ci scb_or_sram_attributes 86262306a36Sopenharmony_ci '}' 86362306a36Sopenharmony_ci { 86462306a36Sopenharmony_ci cur_symbol = NULL; 86562306a36Sopenharmony_ci scb_or_sram_symbol = NULL; 86662306a36Sopenharmony_ci } 86762306a36Sopenharmony_ci; 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ciscb_or_sram_attributes: 87062306a36Sopenharmony_ci /* NULL definition is okay */ 87162306a36Sopenharmony_ci| modes 87262306a36Sopenharmony_ci| scb_or_sram_reg_list 87362306a36Sopenharmony_ci| modes scb_or_sram_reg_list 87462306a36Sopenharmony_ci; 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ciscb_or_sram_reg_list: 87762306a36Sopenharmony_ci reg_definition 87862306a36Sopenharmony_ci| scb_or_sram_reg_list reg_definition 87962306a36Sopenharmony_ci; 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_cireg_symbol: 88262306a36Sopenharmony_ci T_SYMBOL 88362306a36Sopenharmony_ci { 88462306a36Sopenharmony_ci process_register(&$1); 88562306a36Sopenharmony_ci $$.symbol = $1; 88662306a36Sopenharmony_ci $$.offset = 0; 88762306a36Sopenharmony_ci } 88862306a36Sopenharmony_ci| T_SYMBOL '[' T_SYMBOL ']' 88962306a36Sopenharmony_ci { 89062306a36Sopenharmony_ci process_register(&$1); 89162306a36Sopenharmony_ci if ($3->type != CONST) { 89262306a36Sopenharmony_ci stop("register offset must be a constant", EX_DATAERR); 89362306a36Sopenharmony_ci /* NOTREACHED */ 89462306a36Sopenharmony_ci } 89562306a36Sopenharmony_ci if (($3->info.cinfo->value + 1) > $1->info.rinfo->size) { 89662306a36Sopenharmony_ci stop("Accessing offset beyond range of register", 89762306a36Sopenharmony_ci EX_DATAERR); 89862306a36Sopenharmony_ci /* NOTREACHED */ 89962306a36Sopenharmony_ci } 90062306a36Sopenharmony_ci $$.symbol = $1; 90162306a36Sopenharmony_ci $$.offset = $3->info.cinfo->value; 90262306a36Sopenharmony_ci } 90362306a36Sopenharmony_ci| T_SYMBOL '[' T_NUMBER ']' 90462306a36Sopenharmony_ci { 90562306a36Sopenharmony_ci process_register(&$1); 90662306a36Sopenharmony_ci if (($3 + 1) > $1->info.rinfo->size) { 90762306a36Sopenharmony_ci stop("Accessing offset beyond range of register", 90862306a36Sopenharmony_ci EX_DATAERR); 90962306a36Sopenharmony_ci /* NOTREACHED */ 91062306a36Sopenharmony_ci } 91162306a36Sopenharmony_ci $$.symbol = $1; 91262306a36Sopenharmony_ci $$.offset = $3; 91362306a36Sopenharmony_ci } 91462306a36Sopenharmony_ci| T_A 91562306a36Sopenharmony_ci { 91662306a36Sopenharmony_ci if (accumulator.symbol == NULL) { 91762306a36Sopenharmony_ci stop("No accumulator has been defined", EX_DATAERR); 91862306a36Sopenharmony_ci /* NOTREACHED */ 91962306a36Sopenharmony_ci } 92062306a36Sopenharmony_ci $$.symbol = accumulator.symbol; 92162306a36Sopenharmony_ci $$.offset = 0; 92262306a36Sopenharmony_ci } 92362306a36Sopenharmony_ci; 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_cidestination: 92662306a36Sopenharmony_ci reg_symbol 92762306a36Sopenharmony_ci { 92862306a36Sopenharmony_ci test_writable_symbol($1.symbol); 92962306a36Sopenharmony_ci $$ = $1; 93062306a36Sopenharmony_ci } 93162306a36Sopenharmony_ci; 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ciimmediate: 93462306a36Sopenharmony_ci expression 93562306a36Sopenharmony_ci { $$ = $1; } 93662306a36Sopenharmony_ci; 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ciimmediate_or_a: 93962306a36Sopenharmony_ci expression 94062306a36Sopenharmony_ci { 94162306a36Sopenharmony_ci if ($1.value == 0 && is_download_const(&$1) == 0) { 94262306a36Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), 94362306a36Sopenharmony_ci "\nExpression evaluates to 0 and thus " 94462306a36Sopenharmony_ci "references the accumulator.\n " 94562306a36Sopenharmony_ci "If this is the desired effect, use 'A' " 94662306a36Sopenharmony_ci "instead.\n"); 94762306a36Sopenharmony_ci stop(errbuf, EX_DATAERR); 94862306a36Sopenharmony_ci } 94962306a36Sopenharmony_ci $$ = $1; 95062306a36Sopenharmony_ci } 95162306a36Sopenharmony_ci| T_A 95262306a36Sopenharmony_ci { 95362306a36Sopenharmony_ci SLIST_INIT(&$$.referenced_syms); 95462306a36Sopenharmony_ci symlist_add(&$$.referenced_syms, accumulator.symbol, 95562306a36Sopenharmony_ci SYMLIST_INSERT_HEAD); 95662306a36Sopenharmony_ci $$.value = 0; 95762306a36Sopenharmony_ci } 95862306a36Sopenharmony_ci; 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_cisource: 96162306a36Sopenharmony_ci reg_symbol 96262306a36Sopenharmony_ci { 96362306a36Sopenharmony_ci test_readable_symbol($1.symbol); 96462306a36Sopenharmony_ci $$ = $1; 96562306a36Sopenharmony_ci } 96662306a36Sopenharmony_ci; 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ciopt_source: 96962306a36Sopenharmony_ci { 97062306a36Sopenharmony_ci $$.symbol = NULL; 97162306a36Sopenharmony_ci $$.offset = 0; 97262306a36Sopenharmony_ci } 97362306a36Sopenharmony_ci| ',' source 97462306a36Sopenharmony_ci { $$ = $2; } 97562306a36Sopenharmony_ci; 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ciret: 97862306a36Sopenharmony_ci { $$ = 0; } 97962306a36Sopenharmony_ci| T_RET 98062306a36Sopenharmony_ci { $$ = 1; } 98162306a36Sopenharmony_ci; 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ciset_src_mode: 98462306a36Sopenharmony_ci T_SET_SRC_MODE T_NUMBER ';' 98562306a36Sopenharmony_ci { 98662306a36Sopenharmony_ci src_mode = $2; 98762306a36Sopenharmony_ci } 98862306a36Sopenharmony_ci; 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ciset_dst_mode: 99162306a36Sopenharmony_ci T_SET_DST_MODE T_NUMBER ';' 99262306a36Sopenharmony_ci { 99362306a36Sopenharmony_ci dst_mode = $2; 99462306a36Sopenharmony_ci } 99562306a36Sopenharmony_ci; 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_cicritical_section_start: 99862306a36Sopenharmony_ci T_BEGIN_CS ';' 99962306a36Sopenharmony_ci { 100062306a36Sopenharmony_ci critical_section_t *cs; 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci if (in_critical_section != FALSE) { 100362306a36Sopenharmony_ci stop("Critical Section within Critical Section", 100462306a36Sopenharmony_ci EX_DATAERR); 100562306a36Sopenharmony_ci /* NOTREACHED */ 100662306a36Sopenharmony_ci } 100762306a36Sopenharmony_ci cs = cs_alloc(); 100862306a36Sopenharmony_ci cs->begin_addr = instruction_ptr; 100962306a36Sopenharmony_ci in_critical_section = TRUE; 101062306a36Sopenharmony_ci } 101162306a36Sopenharmony_ci; 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_cicritical_section_end: 101462306a36Sopenharmony_ci T_END_CS ';' 101562306a36Sopenharmony_ci { 101662306a36Sopenharmony_ci critical_section_t *cs; 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci if (in_critical_section == FALSE) { 101962306a36Sopenharmony_ci stop("Unballanced 'end_cs'", EX_DATAERR); 102062306a36Sopenharmony_ci /* NOTREACHED */ 102162306a36Sopenharmony_ci } 102262306a36Sopenharmony_ci cs = TAILQ_LAST(&cs_tailq, cs_tailq); 102362306a36Sopenharmony_ci cs->end_addr = instruction_ptr; 102462306a36Sopenharmony_ci in_critical_section = FALSE; 102562306a36Sopenharmony_ci } 102662306a36Sopenharmony_ci; 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ciexport: 102962306a36Sopenharmony_ci { $$ = 0; } 103062306a36Sopenharmony_ci| T_EXPORT 103162306a36Sopenharmony_ci { $$ = 1; } 103262306a36Sopenharmony_ci; 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_cilabel: 103562306a36Sopenharmony_ci export T_SYMBOL ':' 103662306a36Sopenharmony_ci { 103762306a36Sopenharmony_ci if ($2->type != UNINITIALIZED) { 103862306a36Sopenharmony_ci stop("Program label multiply defined", EX_DATAERR); 103962306a36Sopenharmony_ci /* NOTREACHED */ 104062306a36Sopenharmony_ci } 104162306a36Sopenharmony_ci $2->type = LABEL; 104262306a36Sopenharmony_ci initialize_symbol($2); 104362306a36Sopenharmony_ci $2->info.linfo->address = instruction_ptr; 104462306a36Sopenharmony_ci $2->info.linfo->exported = $1; 104562306a36Sopenharmony_ci } 104662306a36Sopenharmony_ci; 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ciaddress: 104962306a36Sopenharmony_ci T_SYMBOL 105062306a36Sopenharmony_ci { 105162306a36Sopenharmony_ci $$.symbol = $1; 105262306a36Sopenharmony_ci $$.offset = 0; 105362306a36Sopenharmony_ci } 105462306a36Sopenharmony_ci| T_SYMBOL '+' T_NUMBER 105562306a36Sopenharmony_ci { 105662306a36Sopenharmony_ci $$.symbol = $1; 105762306a36Sopenharmony_ci $$.offset = $3; 105862306a36Sopenharmony_ci } 105962306a36Sopenharmony_ci| T_SYMBOL '-' T_NUMBER 106062306a36Sopenharmony_ci { 106162306a36Sopenharmony_ci $$.symbol = $1; 106262306a36Sopenharmony_ci $$.offset = -$3; 106362306a36Sopenharmony_ci } 106462306a36Sopenharmony_ci| '.' 106562306a36Sopenharmony_ci { 106662306a36Sopenharmony_ci $$.symbol = NULL; 106762306a36Sopenharmony_ci $$.offset = 0; 106862306a36Sopenharmony_ci } 106962306a36Sopenharmony_ci| '.' '+' T_NUMBER 107062306a36Sopenharmony_ci { 107162306a36Sopenharmony_ci $$.symbol = NULL; 107262306a36Sopenharmony_ci $$.offset = $3; 107362306a36Sopenharmony_ci } 107462306a36Sopenharmony_ci| '.' '-' T_NUMBER 107562306a36Sopenharmony_ci { 107662306a36Sopenharmony_ci $$.symbol = NULL; 107762306a36Sopenharmony_ci $$.offset = -$3; 107862306a36Sopenharmony_ci } 107962306a36Sopenharmony_ci; 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_ciconditional: 108262306a36Sopenharmony_ci T_IF T_CEXPR '{' 108362306a36Sopenharmony_ci { 108462306a36Sopenharmony_ci scope_t *new_scope; 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci add_conditional($2); 108762306a36Sopenharmony_ci new_scope = scope_alloc(); 108862306a36Sopenharmony_ci new_scope->type = SCOPE_IF; 108962306a36Sopenharmony_ci new_scope->begin_addr = instruction_ptr; 109062306a36Sopenharmony_ci new_scope->func_num = $2->info.condinfo->func_num; 109162306a36Sopenharmony_ci } 109262306a36Sopenharmony_ci| T_ELSE T_IF T_CEXPR '{' 109362306a36Sopenharmony_ci { 109462306a36Sopenharmony_ci scope_t *new_scope; 109562306a36Sopenharmony_ci scope_t *scope_context; 109662306a36Sopenharmony_ci scope_t *last_scope; 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci /* 109962306a36Sopenharmony_ci * Ensure that the previous scope is either an 110062306a36Sopenharmony_ci * if or and else if. 110162306a36Sopenharmony_ci */ 110262306a36Sopenharmony_ci scope_context = SLIST_FIRST(&scope_stack); 110362306a36Sopenharmony_ci last_scope = TAILQ_LAST(&scope_context->inner_scope, 110462306a36Sopenharmony_ci scope_tailq); 110562306a36Sopenharmony_ci if (last_scope == NULL 110662306a36Sopenharmony_ci || last_scope->type == T_ELSE) { 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci stop("'else if' without leading 'if'", EX_DATAERR); 110962306a36Sopenharmony_ci /* NOTREACHED */ 111062306a36Sopenharmony_ci } 111162306a36Sopenharmony_ci add_conditional($3); 111262306a36Sopenharmony_ci new_scope = scope_alloc(); 111362306a36Sopenharmony_ci new_scope->type = SCOPE_ELSE_IF; 111462306a36Sopenharmony_ci new_scope->begin_addr = instruction_ptr; 111562306a36Sopenharmony_ci new_scope->func_num = $3->info.condinfo->func_num; 111662306a36Sopenharmony_ci } 111762306a36Sopenharmony_ci| T_ELSE '{' 111862306a36Sopenharmony_ci { 111962306a36Sopenharmony_ci scope_t *new_scope; 112062306a36Sopenharmony_ci scope_t *scope_context; 112162306a36Sopenharmony_ci scope_t *last_scope; 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_ci /* 112462306a36Sopenharmony_ci * Ensure that the previous scope is either an 112562306a36Sopenharmony_ci * if or and else if. 112662306a36Sopenharmony_ci */ 112762306a36Sopenharmony_ci scope_context = SLIST_FIRST(&scope_stack); 112862306a36Sopenharmony_ci last_scope = TAILQ_LAST(&scope_context->inner_scope, 112962306a36Sopenharmony_ci scope_tailq); 113062306a36Sopenharmony_ci if (last_scope == NULL 113162306a36Sopenharmony_ci || last_scope->type == SCOPE_ELSE) { 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci stop("'else' without leading 'if'", EX_DATAERR); 113462306a36Sopenharmony_ci /* NOTREACHED */ 113562306a36Sopenharmony_ci } 113662306a36Sopenharmony_ci new_scope = scope_alloc(); 113762306a36Sopenharmony_ci new_scope->type = SCOPE_ELSE; 113862306a36Sopenharmony_ci new_scope->begin_addr = instruction_ptr; 113962306a36Sopenharmony_ci } 114062306a36Sopenharmony_ci; 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_ciconditional: 114362306a36Sopenharmony_ci '}' 114462306a36Sopenharmony_ci { 114562306a36Sopenharmony_ci scope_t *scope_context; 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci scope_context = SLIST_FIRST(&scope_stack); 114862306a36Sopenharmony_ci if (scope_context->type == SCOPE_ROOT) { 114962306a36Sopenharmony_ci stop("Unexpected '}' encountered", EX_DATAERR); 115062306a36Sopenharmony_ci /* NOTREACHED */ 115162306a36Sopenharmony_ci } 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_ci scope_context->end_addr = instruction_ptr; 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ci /* Pop the scope */ 115662306a36Sopenharmony_ci SLIST_REMOVE_HEAD(&scope_stack, scope_stack_links); 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci process_scope(scope_context); 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_ci if (SLIST_FIRST(&scope_stack) == NULL) { 116162306a36Sopenharmony_ci stop("Unexpected '}' encountered", EX_DATAERR); 116262306a36Sopenharmony_ci /* NOTREACHED */ 116362306a36Sopenharmony_ci } 116462306a36Sopenharmony_ci } 116562306a36Sopenharmony_ci; 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_cif1_opcode: 116862306a36Sopenharmony_ci T_AND { $$ = AIC_OP_AND; } 116962306a36Sopenharmony_ci| T_XOR { $$ = AIC_OP_XOR; } 117062306a36Sopenharmony_ci| T_ADD { $$ = AIC_OP_ADD; } 117162306a36Sopenharmony_ci| T_ADC { $$ = AIC_OP_ADC; } 117262306a36Sopenharmony_ci; 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_cicode: 117562306a36Sopenharmony_ci f1_opcode destination ',' immediate_or_a opt_source ret ';' 117662306a36Sopenharmony_ci { 117762306a36Sopenharmony_ci format_1_instr($1, &$2, &$4, &$5, $6); 117862306a36Sopenharmony_ci } 117962306a36Sopenharmony_ci; 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_cicode: 118262306a36Sopenharmony_ci T_OR reg_symbol ',' immediate_or_a opt_source ret ';' 118362306a36Sopenharmony_ci { 118462306a36Sopenharmony_ci format_1_instr(AIC_OP_OR, &$2, &$4, &$5, $6); 118562306a36Sopenharmony_ci } 118662306a36Sopenharmony_ci; 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_cicode: 118962306a36Sopenharmony_ci T_INC destination opt_source ret ';' 119062306a36Sopenharmony_ci { 119162306a36Sopenharmony_ci expression_t immed; 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_ci make_expression(&immed, 1); 119462306a36Sopenharmony_ci format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); 119562306a36Sopenharmony_ci } 119662306a36Sopenharmony_ci; 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_cicode: 119962306a36Sopenharmony_ci T_DEC destination opt_source ret ';' 120062306a36Sopenharmony_ci { 120162306a36Sopenharmony_ci expression_t immed; 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci make_expression(&immed, -1); 120462306a36Sopenharmony_ci format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); 120562306a36Sopenharmony_ci } 120662306a36Sopenharmony_ci; 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_cicode: 120962306a36Sopenharmony_ci T_CLC ret ';' 121062306a36Sopenharmony_ci { 121162306a36Sopenharmony_ci expression_t immed; 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_ci make_expression(&immed, -1); 121462306a36Sopenharmony_ci format_1_instr(AIC_OP_ADD, &none, &immed, &allzeros, $2); 121562306a36Sopenharmony_ci } 121662306a36Sopenharmony_ci| T_CLC T_MVI destination ',' immediate_or_a ret ';' 121762306a36Sopenharmony_ci { 121862306a36Sopenharmony_ci format_1_instr(AIC_OP_ADD, &$3, &$5, &allzeros, $6); 121962306a36Sopenharmony_ci } 122062306a36Sopenharmony_ci; 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_cicode: 122362306a36Sopenharmony_ci T_STC ret ';' 122462306a36Sopenharmony_ci { 122562306a36Sopenharmony_ci expression_t immed; 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci make_expression(&immed, 1); 122862306a36Sopenharmony_ci format_1_instr(AIC_OP_ADD, &none, &immed, &allones, $2); 122962306a36Sopenharmony_ci } 123062306a36Sopenharmony_ci| T_STC destination ret ';' 123162306a36Sopenharmony_ci { 123262306a36Sopenharmony_ci expression_t immed; 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci make_expression(&immed, 1); 123562306a36Sopenharmony_ci format_1_instr(AIC_OP_ADD, &$2, &immed, &allones, $3); 123662306a36Sopenharmony_ci } 123762306a36Sopenharmony_ci; 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_cicode: 124062306a36Sopenharmony_ci T_BMOV destination ',' source ',' immediate ret ';' 124162306a36Sopenharmony_ci { 124262306a36Sopenharmony_ci format_1_instr(AIC_OP_BMOV, &$2, &$6, &$4, $7); 124362306a36Sopenharmony_ci } 124462306a36Sopenharmony_ci; 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_cicode: 124762306a36Sopenharmony_ci T_MOV destination ',' source ret ';' 124862306a36Sopenharmony_ci { 124962306a36Sopenharmony_ci expression_t immed; 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci make_expression(&immed, 1); 125262306a36Sopenharmony_ci format_1_instr(AIC_OP_BMOV, &$2, &immed, &$4, $5); 125362306a36Sopenharmony_ci } 125462306a36Sopenharmony_ci; 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_cicode: 125762306a36Sopenharmony_ci T_MVI destination ',' immediate ret ';' 125862306a36Sopenharmony_ci { 125962306a36Sopenharmony_ci if ($4.value == 0 126062306a36Sopenharmony_ci && is_download_const(&$4) == 0) { 126162306a36Sopenharmony_ci expression_t immed; 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci /* 126462306a36Sopenharmony_ci * Allow move immediates of 0 so that macros, 126562306a36Sopenharmony_ci * that can't know the immediate's value and 126662306a36Sopenharmony_ci * otherwise compensate, still work. 126762306a36Sopenharmony_ci */ 126862306a36Sopenharmony_ci make_expression(&immed, 1); 126962306a36Sopenharmony_ci format_1_instr(AIC_OP_BMOV, &$2, &immed, &allzeros, $5); 127062306a36Sopenharmony_ci } else { 127162306a36Sopenharmony_ci format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5); 127262306a36Sopenharmony_ci } 127362306a36Sopenharmony_ci } 127462306a36Sopenharmony_ci; 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_cicode: 127762306a36Sopenharmony_ci T_NOT destination opt_source ret ';' 127862306a36Sopenharmony_ci { 127962306a36Sopenharmony_ci expression_t immed; 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ci make_expression(&immed, 0xff); 128262306a36Sopenharmony_ci format_1_instr(AIC_OP_XOR, &$2, &immed, &$3, $4); 128362306a36Sopenharmony_ci } 128462306a36Sopenharmony_ci; 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_cicode: 128762306a36Sopenharmony_ci T_CLR destination ret ';' 128862306a36Sopenharmony_ci { 128962306a36Sopenharmony_ci expression_t immed; 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci make_expression(&immed, 0xff); 129262306a36Sopenharmony_ci format_1_instr(AIC_OP_AND, &$2, &immed, &allzeros, $3); 129362306a36Sopenharmony_ci } 129462306a36Sopenharmony_ci; 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_cicode: 129762306a36Sopenharmony_ci T_NOP ret ';' 129862306a36Sopenharmony_ci { 129962306a36Sopenharmony_ci expression_t immed; 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci make_expression(&immed, 0xff); 130262306a36Sopenharmony_ci format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, $2); 130362306a36Sopenharmony_ci } 130462306a36Sopenharmony_ci; 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_cicode: 130762306a36Sopenharmony_ci T_RET ';' 130862306a36Sopenharmony_ci { 130962306a36Sopenharmony_ci expression_t immed; 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci make_expression(&immed, 0xff); 131262306a36Sopenharmony_ci format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, TRUE); 131362306a36Sopenharmony_ci } 131462306a36Sopenharmony_ci; 131562306a36Sopenharmony_ci 131662306a36Sopenharmony_ci /* 131762306a36Sopenharmony_ci * This grammar differs from the one in the aic7xxx 131862306a36Sopenharmony_ci * reference manual since the grammar listed there is 131962306a36Sopenharmony_ci * ambiguous and causes a shift/reduce conflict. 132062306a36Sopenharmony_ci * It also seems more logical as the "immediate" 132162306a36Sopenharmony_ci * argument is listed as the second arg like the 132262306a36Sopenharmony_ci * other formats. 132362306a36Sopenharmony_ci */ 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_cif2_opcode: 132662306a36Sopenharmony_ci T_SHL { $$ = AIC_OP_SHL; } 132762306a36Sopenharmony_ci| T_SHR { $$ = AIC_OP_SHR; } 132862306a36Sopenharmony_ci| T_ROL { $$ = AIC_OP_ROL; } 132962306a36Sopenharmony_ci| T_ROR { $$ = AIC_OP_ROR; } 133062306a36Sopenharmony_ci; 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_ci/* 133362306a36Sopenharmony_ci * 16bit opcodes, not used 133462306a36Sopenharmony_ci * 133562306a36Sopenharmony_ci *f4_opcode: 133662306a36Sopenharmony_ci * T_OR16 { $$ = AIC_OP_OR16; } 133762306a36Sopenharmony_ci *| T_AND16 { $$ = AIC_OP_AND16; } 133862306a36Sopenharmony_ci *| T_XOR16 { $$ = AIC_OP_XOR16; } 133962306a36Sopenharmony_ci *| T_ADD16 { $$ = AIC_OP_ADD16; } 134062306a36Sopenharmony_ci *| T_ADC16 { $$ = AIC_OP_ADC16; } 134162306a36Sopenharmony_ci *| T_MVI16 { $$ = AIC_OP_MVI16; } 134262306a36Sopenharmony_ci *; 134362306a36Sopenharmony_ci */ 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_cicode: 134662306a36Sopenharmony_ci f2_opcode destination ',' expression opt_source ret ';' 134762306a36Sopenharmony_ci { 134862306a36Sopenharmony_ci format_2_instr($1, &$2, &$4, &$5, $6); 134962306a36Sopenharmony_ci } 135062306a36Sopenharmony_ci; 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_cijmp_jc_jnc_call: 135362306a36Sopenharmony_ci T_JMP { $$ = AIC_OP_JMP; } 135462306a36Sopenharmony_ci| T_JC { $$ = AIC_OP_JC; } 135562306a36Sopenharmony_ci| T_JNC { $$ = AIC_OP_JNC; } 135662306a36Sopenharmony_ci| T_CALL { $$ = AIC_OP_CALL; } 135762306a36Sopenharmony_ci; 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_cijz_jnz: 136062306a36Sopenharmony_ci T_JZ { $$ = AIC_OP_JZ; } 136162306a36Sopenharmony_ci| T_JNZ { $$ = AIC_OP_JNZ; } 136262306a36Sopenharmony_ci; 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_cije_jne: 136562306a36Sopenharmony_ci T_JE { $$ = AIC_OP_JE; } 136662306a36Sopenharmony_ci| T_JNE { $$ = AIC_OP_JNE; } 136762306a36Sopenharmony_ci; 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_cicode: 137062306a36Sopenharmony_ci jmp_jc_jnc_call address ';' 137162306a36Sopenharmony_ci { 137262306a36Sopenharmony_ci expression_t immed; 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci make_expression(&immed, 0); 137562306a36Sopenharmony_ci format_3_instr($1, &sindex, &immed, &$2); 137662306a36Sopenharmony_ci } 137762306a36Sopenharmony_ci; 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_cicode: 138062306a36Sopenharmony_ci T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';' 138162306a36Sopenharmony_ci { 138262306a36Sopenharmony_ci type_check(&$2, &$4, AIC_OP_OR); 138362306a36Sopenharmony_ci format_3_instr($5, &$2, &$4, &$6); 138462306a36Sopenharmony_ci } 138562306a36Sopenharmony_ci; 138662306a36Sopenharmony_ci 138762306a36Sopenharmony_cicode: 138862306a36Sopenharmony_ci T_TEST source ',' immediate_or_a jz_jnz address ';' 138962306a36Sopenharmony_ci { 139062306a36Sopenharmony_ci format_3_instr($5, &$2, &$4, &$6); 139162306a36Sopenharmony_ci } 139262306a36Sopenharmony_ci; 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_cicode: 139562306a36Sopenharmony_ci T_CMP source ',' immediate_or_a je_jne address ';' 139662306a36Sopenharmony_ci { 139762306a36Sopenharmony_ci format_3_instr($5, &$2, &$4, &$6); 139862306a36Sopenharmony_ci } 139962306a36Sopenharmony_ci; 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_cicode: 140262306a36Sopenharmony_ci T_MOV source jmp_jc_jnc_call address ';' 140362306a36Sopenharmony_ci { 140462306a36Sopenharmony_ci expression_t immed; 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci make_expression(&immed, 0); 140762306a36Sopenharmony_ci format_3_instr($3, &$2, &immed, &$4); 140862306a36Sopenharmony_ci } 140962306a36Sopenharmony_ci; 141062306a36Sopenharmony_ci 141162306a36Sopenharmony_cicode: 141262306a36Sopenharmony_ci T_MVI immediate jmp_jc_jnc_call address ';' 141362306a36Sopenharmony_ci { 141462306a36Sopenharmony_ci format_3_instr($3, &allzeros, &$2, &$4); 141562306a36Sopenharmony_ci } 141662306a36Sopenharmony_ci; 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci%% 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_cistatic void 142162306a36Sopenharmony_ciprocess_field(int field_type, symbol_t *sym, int value) 142262306a36Sopenharmony_ci{ 142362306a36Sopenharmony_ci /* 142462306a36Sopenharmony_ci * Add the current register to its 142562306a36Sopenharmony_ci * symbol list, if it already exists, 142662306a36Sopenharmony_ci * warn if we are setting it to a 142762306a36Sopenharmony_ci * different value, or in the bit to 142862306a36Sopenharmony_ci * the "allowed bits" of this register. 142962306a36Sopenharmony_ci */ 143062306a36Sopenharmony_ci if (sym->type == UNINITIALIZED) { 143162306a36Sopenharmony_ci sym->type = field_type; 143262306a36Sopenharmony_ci initialize_symbol(sym); 143362306a36Sopenharmony_ci sym->info.finfo->value = value; 143462306a36Sopenharmony_ci if (field_type != ENUM_ENTRY) { 143562306a36Sopenharmony_ci if (field_type != MASK && value == 0) { 143662306a36Sopenharmony_ci stop("Empty Field, or Enum", EX_DATAERR); 143762306a36Sopenharmony_ci /* NOTREACHED */ 143862306a36Sopenharmony_ci } 143962306a36Sopenharmony_ci sym->info.finfo->value = value; 144062306a36Sopenharmony_ci sym->info.finfo->mask = value; 144162306a36Sopenharmony_ci } else if (field_symbol != NULL) { 144262306a36Sopenharmony_ci sym->info.finfo->mask = field_symbol->info.finfo->value; 144362306a36Sopenharmony_ci } else { 144462306a36Sopenharmony_ci sym->info.finfo->mask = 0xFF; 144562306a36Sopenharmony_ci } 144662306a36Sopenharmony_ci } else if (sym->type != field_type) { 144762306a36Sopenharmony_ci stop("Field definition mirrors a definition of the same " 144862306a36Sopenharmony_ci " name, but a different type", EX_DATAERR); 144962306a36Sopenharmony_ci /* NOTREACHED */ 145062306a36Sopenharmony_ci } else if (value != sym->info.finfo->value) { 145162306a36Sopenharmony_ci stop("Field redefined with a conflicting value", EX_DATAERR); 145262306a36Sopenharmony_ci /* NOTREACHED */ 145362306a36Sopenharmony_ci } 145462306a36Sopenharmony_ci /* Fail if this symbol is already listed */ 145562306a36Sopenharmony_ci if (symlist_search(&(sym->info.finfo->symrefs), 145662306a36Sopenharmony_ci cur_symbol->name) != NULL) { 145762306a36Sopenharmony_ci stop("Field defined multiple times for register", EX_DATAERR); 145862306a36Sopenharmony_ci /* NOTREACHED */ 145962306a36Sopenharmony_ci } 146062306a36Sopenharmony_ci symlist_add(&(sym->info.finfo->symrefs), cur_symbol, 146162306a36Sopenharmony_ci SYMLIST_INSERT_HEAD); 146262306a36Sopenharmony_ci cur_symbol->info.rinfo->valid_bitmask |= sym->info.finfo->mask; 146362306a36Sopenharmony_ci cur_symbol->info.rinfo->typecheck_masks = TRUE; 146462306a36Sopenharmony_ci symlist_add(&(cur_symbol->info.rinfo->fields), sym, SYMLIST_SORT); 146562306a36Sopenharmony_ci} 146662306a36Sopenharmony_ci 146762306a36Sopenharmony_cistatic void 146862306a36Sopenharmony_ciinitialize_symbol(symbol_t *symbol) 146962306a36Sopenharmony_ci{ 147062306a36Sopenharmony_ci switch (symbol->type) { 147162306a36Sopenharmony_ci case UNINITIALIZED: 147262306a36Sopenharmony_ci stop("Call to initialize_symbol with type field unset", 147362306a36Sopenharmony_ci EX_SOFTWARE); 147462306a36Sopenharmony_ci /* NOTREACHED */ 147562306a36Sopenharmony_ci break; 147662306a36Sopenharmony_ci case REGISTER: 147762306a36Sopenharmony_ci case SRAMLOC: 147862306a36Sopenharmony_ci case SCBLOC: 147962306a36Sopenharmony_ci symbol->info.rinfo = 148062306a36Sopenharmony_ci (struct reg_info *)malloc(sizeof(struct reg_info)); 148162306a36Sopenharmony_ci if (symbol->info.rinfo == NULL) { 148262306a36Sopenharmony_ci stop("Can't create register info", EX_SOFTWARE); 148362306a36Sopenharmony_ci /* NOTREACHED */ 148462306a36Sopenharmony_ci } 148562306a36Sopenharmony_ci memset(symbol->info.rinfo, 0, 148662306a36Sopenharmony_ci sizeof(struct reg_info)); 148762306a36Sopenharmony_ci SLIST_INIT(&(symbol->info.rinfo->fields)); 148862306a36Sopenharmony_ci /* 148962306a36Sopenharmony_ci * Default to allowing access in all register modes 149062306a36Sopenharmony_ci * or to the mode specified by the SCB or SRAM space 149162306a36Sopenharmony_ci * we are in. 149262306a36Sopenharmony_ci */ 149362306a36Sopenharmony_ci if (scb_or_sram_symbol != NULL) 149462306a36Sopenharmony_ci symbol->info.rinfo->modes = 149562306a36Sopenharmony_ci scb_or_sram_symbol->info.rinfo->modes; 149662306a36Sopenharmony_ci else 149762306a36Sopenharmony_ci symbol->info.rinfo->modes = ~0; 149862306a36Sopenharmony_ci break; 149962306a36Sopenharmony_ci case ALIAS: 150062306a36Sopenharmony_ci symbol->info.ainfo = 150162306a36Sopenharmony_ci (struct alias_info *)malloc(sizeof(struct alias_info)); 150262306a36Sopenharmony_ci if (symbol->info.ainfo == NULL) { 150362306a36Sopenharmony_ci stop("Can't create alias info", EX_SOFTWARE); 150462306a36Sopenharmony_ci /* NOTREACHED */ 150562306a36Sopenharmony_ci } 150662306a36Sopenharmony_ci memset(symbol->info.ainfo, 0, 150762306a36Sopenharmony_ci sizeof(struct alias_info)); 150862306a36Sopenharmony_ci break; 150962306a36Sopenharmony_ci case MASK: 151062306a36Sopenharmony_ci case FIELD: 151162306a36Sopenharmony_ci case ENUM: 151262306a36Sopenharmony_ci case ENUM_ENTRY: 151362306a36Sopenharmony_ci symbol->info.finfo = 151462306a36Sopenharmony_ci (struct field_info *)malloc(sizeof(struct field_info)); 151562306a36Sopenharmony_ci if (symbol->info.finfo == NULL) { 151662306a36Sopenharmony_ci stop("Can't create field info", EX_SOFTWARE); 151762306a36Sopenharmony_ci /* NOTREACHED */ 151862306a36Sopenharmony_ci } 151962306a36Sopenharmony_ci memset(symbol->info.finfo, 0, sizeof(struct field_info)); 152062306a36Sopenharmony_ci SLIST_INIT(&(symbol->info.finfo->symrefs)); 152162306a36Sopenharmony_ci break; 152262306a36Sopenharmony_ci case CONST: 152362306a36Sopenharmony_ci case DOWNLOAD_CONST: 152462306a36Sopenharmony_ci symbol->info.cinfo = 152562306a36Sopenharmony_ci (struct const_info *)malloc(sizeof(struct const_info)); 152662306a36Sopenharmony_ci if (symbol->info.cinfo == NULL) { 152762306a36Sopenharmony_ci stop("Can't create alias info", EX_SOFTWARE); 152862306a36Sopenharmony_ci /* NOTREACHED */ 152962306a36Sopenharmony_ci } 153062306a36Sopenharmony_ci memset(symbol->info.cinfo, 0, 153162306a36Sopenharmony_ci sizeof(struct const_info)); 153262306a36Sopenharmony_ci break; 153362306a36Sopenharmony_ci case LABEL: 153462306a36Sopenharmony_ci symbol->info.linfo = 153562306a36Sopenharmony_ci (struct label_info *)malloc(sizeof(struct label_info)); 153662306a36Sopenharmony_ci if (symbol->info.linfo == NULL) { 153762306a36Sopenharmony_ci stop("Can't create label info", EX_SOFTWARE); 153862306a36Sopenharmony_ci /* NOTREACHED */ 153962306a36Sopenharmony_ci } 154062306a36Sopenharmony_ci memset(symbol->info.linfo, 0, 154162306a36Sopenharmony_ci sizeof(struct label_info)); 154262306a36Sopenharmony_ci break; 154362306a36Sopenharmony_ci case CONDITIONAL: 154462306a36Sopenharmony_ci symbol->info.condinfo = 154562306a36Sopenharmony_ci (struct cond_info *)malloc(sizeof(struct cond_info)); 154662306a36Sopenharmony_ci if (symbol->info.condinfo == NULL) { 154762306a36Sopenharmony_ci stop("Can't create conditional info", EX_SOFTWARE); 154862306a36Sopenharmony_ci /* NOTREACHED */ 154962306a36Sopenharmony_ci } 155062306a36Sopenharmony_ci memset(symbol->info.condinfo, 0, 155162306a36Sopenharmony_ci sizeof(struct cond_info)); 155262306a36Sopenharmony_ci break; 155362306a36Sopenharmony_ci case MACRO: 155462306a36Sopenharmony_ci symbol->info.macroinfo = 155562306a36Sopenharmony_ci (struct macro_info *)malloc(sizeof(struct macro_info)); 155662306a36Sopenharmony_ci if (symbol->info.macroinfo == NULL) { 155762306a36Sopenharmony_ci stop("Can't create macro info", EX_SOFTWARE); 155862306a36Sopenharmony_ci /* NOTREACHED */ 155962306a36Sopenharmony_ci } 156062306a36Sopenharmony_ci memset(symbol->info.macroinfo, 0, 156162306a36Sopenharmony_ci sizeof(struct macro_info)); 156262306a36Sopenharmony_ci STAILQ_INIT(&symbol->info.macroinfo->args); 156362306a36Sopenharmony_ci break; 156462306a36Sopenharmony_ci default: 156562306a36Sopenharmony_ci stop("Call to initialize_symbol with invalid symbol type", 156662306a36Sopenharmony_ci EX_SOFTWARE); 156762306a36Sopenharmony_ci /* NOTREACHED */ 156862306a36Sopenharmony_ci break; 156962306a36Sopenharmony_ci } 157062306a36Sopenharmony_ci} 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_cistatic void 157362306a36Sopenharmony_ciadd_macro_arg(const char *argtext, int argnum) 157462306a36Sopenharmony_ci{ 157562306a36Sopenharmony_ci struct macro_arg *marg; 157662306a36Sopenharmony_ci int i; 157762306a36Sopenharmony_ci int retval; 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_ci if (cur_symbol == NULL || cur_symbol->type != MACRO) { 158062306a36Sopenharmony_ci stop("Invalid current symbol for adding macro arg", 158162306a36Sopenharmony_ci EX_SOFTWARE); 158262306a36Sopenharmony_ci /* NOTREACHED */ 158362306a36Sopenharmony_ci } 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_ci marg = (struct macro_arg *)malloc(sizeof(*marg)); 158662306a36Sopenharmony_ci if (marg == NULL) { 158762306a36Sopenharmony_ci stop("Can't create macro_arg structure", EX_SOFTWARE); 158862306a36Sopenharmony_ci /* NOTREACHED */ 158962306a36Sopenharmony_ci } 159062306a36Sopenharmony_ci marg->replacement_text = NULL; 159162306a36Sopenharmony_ci retval = snprintf(regex_pattern, sizeof(regex_pattern), 159262306a36Sopenharmony_ci "[^-/A-Za-z0-9_](%s)([^-/A-Za-z0-9_]|$)", 159362306a36Sopenharmony_ci argtext); 159462306a36Sopenharmony_ci if (retval >= sizeof(regex_pattern)) { 159562306a36Sopenharmony_ci stop("Regex text buffer too small for arg", 159662306a36Sopenharmony_ci EX_SOFTWARE); 159762306a36Sopenharmony_ci /* NOTREACHED */ 159862306a36Sopenharmony_ci } 159962306a36Sopenharmony_ci retval = regcomp(&marg->arg_regex, regex_pattern, REG_EXTENDED); 160062306a36Sopenharmony_ci if (retval != 0) { 160162306a36Sopenharmony_ci stop("Regex compilation failed", EX_SOFTWARE); 160262306a36Sopenharmony_ci /* NOTREACHED */ 160362306a36Sopenharmony_ci } 160462306a36Sopenharmony_ci STAILQ_INSERT_TAIL(&cur_symbol->info.macroinfo->args, marg, links); 160562306a36Sopenharmony_ci} 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_cistatic void 160862306a36Sopenharmony_ciadd_macro_body(const char *bodytext) 160962306a36Sopenharmony_ci{ 161062306a36Sopenharmony_ci if (cur_symbol == NULL || cur_symbol->type != MACRO) { 161162306a36Sopenharmony_ci stop("Invalid current symbol for adding macro arg", 161262306a36Sopenharmony_ci EX_SOFTWARE); 161362306a36Sopenharmony_ci /* NOTREACHED */ 161462306a36Sopenharmony_ci } 161562306a36Sopenharmony_ci cur_symbol->info.macroinfo->body = strdup(bodytext); 161662306a36Sopenharmony_ci if (cur_symbol->info.macroinfo->body == NULL) { 161762306a36Sopenharmony_ci stop("Can't duplicate macro body text", EX_SOFTWARE); 161862306a36Sopenharmony_ci /* NOTREACHED */ 161962306a36Sopenharmony_ci } 162062306a36Sopenharmony_ci} 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_cistatic void 162362306a36Sopenharmony_ciprocess_register(symbol_t **p_symbol) 162462306a36Sopenharmony_ci{ 162562306a36Sopenharmony_ci symbol_t *symbol = *p_symbol; 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_ci if (symbol->type == UNINITIALIZED) { 162862306a36Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), "Undefined register %s", 162962306a36Sopenharmony_ci symbol->name); 163062306a36Sopenharmony_ci stop(errbuf, EX_DATAERR); 163162306a36Sopenharmony_ci /* NOTREACHED */ 163262306a36Sopenharmony_ci } else if (symbol->type == ALIAS) { 163362306a36Sopenharmony_ci *p_symbol = symbol->info.ainfo->parent; 163462306a36Sopenharmony_ci } else if ((symbol->type != REGISTER) 163562306a36Sopenharmony_ci && (symbol->type != SCBLOC) 163662306a36Sopenharmony_ci && (symbol->type != SRAMLOC)) { 163762306a36Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), 163862306a36Sopenharmony_ci "Specified symbol %s is not a register", 163962306a36Sopenharmony_ci symbol->name); 164062306a36Sopenharmony_ci stop(errbuf, EX_DATAERR); 164162306a36Sopenharmony_ci } 164262306a36Sopenharmony_ci} 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_cistatic void 164562306a36Sopenharmony_ciformat_1_instr(int opcode, symbol_ref_t *dest, expression_t *immed, 164662306a36Sopenharmony_ci symbol_ref_t *src, int ret) 164762306a36Sopenharmony_ci{ 164862306a36Sopenharmony_ci struct instruction *instr; 164962306a36Sopenharmony_ci struct ins_format1 *f1_instr; 165062306a36Sopenharmony_ci 165162306a36Sopenharmony_ci if (src->symbol == NULL) 165262306a36Sopenharmony_ci src = dest; 165362306a36Sopenharmony_ci 165462306a36Sopenharmony_ci /* Test register permissions */ 165562306a36Sopenharmony_ci test_writable_symbol(dest->symbol); 165662306a36Sopenharmony_ci test_readable_symbol(src->symbol); 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci if (!is_location_address(dest->symbol)) { 165962306a36Sopenharmony_ci /* Ensure that immediate makes sense for this destination */ 166062306a36Sopenharmony_ci type_check(dest, immed, opcode); 166162306a36Sopenharmony_ci } 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_ci /* Allocate sequencer space for the instruction and fill it out */ 166462306a36Sopenharmony_ci instr = seq_alloc(); 166562306a36Sopenharmony_ci f1_instr = &instr->format.format1; 166662306a36Sopenharmony_ci f1_instr->ret = ret ? 1 : 0; 166762306a36Sopenharmony_ci f1_instr->opcode = opcode; 166862306a36Sopenharmony_ci f1_instr->destination = dest->symbol->info.rinfo->address 166962306a36Sopenharmony_ci + dest->offset; 167062306a36Sopenharmony_ci f1_instr->source = src->symbol->info.rinfo->address 167162306a36Sopenharmony_ci + src->offset; 167262306a36Sopenharmony_ci f1_instr->immediate = immed->value; 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci if (is_download_const(immed)) 167562306a36Sopenharmony_ci f1_instr->parity = 1; 167662306a36Sopenharmony_ci else if (dest->symbol == mode_ptr.symbol) { 167762306a36Sopenharmony_ci u_int src_value; 167862306a36Sopenharmony_ci u_int dst_value; 167962306a36Sopenharmony_ci 168062306a36Sopenharmony_ci /* 168162306a36Sopenharmony_ci * Attempt to update mode information if 168262306a36Sopenharmony_ci * we are operating on the mode register. 168362306a36Sopenharmony_ci */ 168462306a36Sopenharmony_ci if (src->symbol == allones.symbol) 168562306a36Sopenharmony_ci src_value = 0xFF; 168662306a36Sopenharmony_ci else if (src->symbol == allzeros.symbol) 168762306a36Sopenharmony_ci src_value = 0; 168862306a36Sopenharmony_ci else if (src->symbol == mode_ptr.symbol) 168962306a36Sopenharmony_ci src_value = (dst_mode << 4) | src_mode; 169062306a36Sopenharmony_ci else 169162306a36Sopenharmony_ci goto cant_update; 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_ci switch (opcode) { 169462306a36Sopenharmony_ci case AIC_OP_AND: 169562306a36Sopenharmony_ci dst_value = src_value & immed->value; 169662306a36Sopenharmony_ci break; 169762306a36Sopenharmony_ci case AIC_OP_XOR: 169862306a36Sopenharmony_ci dst_value = src_value ^ immed->value; 169962306a36Sopenharmony_ci break; 170062306a36Sopenharmony_ci case AIC_OP_ADD: 170162306a36Sopenharmony_ci dst_value = (src_value + immed->value) & 0xFF; 170262306a36Sopenharmony_ci break; 170362306a36Sopenharmony_ci case AIC_OP_OR: 170462306a36Sopenharmony_ci dst_value = src_value | immed->value; 170562306a36Sopenharmony_ci break; 170662306a36Sopenharmony_ci case AIC_OP_BMOV: 170762306a36Sopenharmony_ci dst_value = src_value; 170862306a36Sopenharmony_ci break; 170962306a36Sopenharmony_ci default: 171062306a36Sopenharmony_ci goto cant_update; 171162306a36Sopenharmony_ci } 171262306a36Sopenharmony_ci src_mode = dst_value & 0xF; 171362306a36Sopenharmony_ci dst_mode = (dst_value >> 4) & 0xF; 171462306a36Sopenharmony_ci } 171562306a36Sopenharmony_ci 171662306a36Sopenharmony_cicant_update: 171762306a36Sopenharmony_ci symlist_free(&immed->referenced_syms); 171862306a36Sopenharmony_ci instruction_ptr++; 171962306a36Sopenharmony_ci} 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_cistatic void 172262306a36Sopenharmony_ciformat_2_instr(int opcode, symbol_ref_t *dest, expression_t *places, 172362306a36Sopenharmony_ci symbol_ref_t *src, int ret) 172462306a36Sopenharmony_ci{ 172562306a36Sopenharmony_ci struct instruction *instr; 172662306a36Sopenharmony_ci struct ins_format2 *f2_instr; 172762306a36Sopenharmony_ci uint8_t shift_control; 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_ci if (src->symbol == NULL) 173062306a36Sopenharmony_ci src = dest; 173162306a36Sopenharmony_ci 173262306a36Sopenharmony_ci /* Test register permissions */ 173362306a36Sopenharmony_ci test_writable_symbol(dest->symbol); 173462306a36Sopenharmony_ci test_readable_symbol(src->symbol); 173562306a36Sopenharmony_ci 173662306a36Sopenharmony_ci /* Allocate sequencer space for the instruction and fill it out */ 173762306a36Sopenharmony_ci instr = seq_alloc(); 173862306a36Sopenharmony_ci f2_instr = &instr->format.format2; 173962306a36Sopenharmony_ci f2_instr->ret = ret ? 1 : 0; 174062306a36Sopenharmony_ci f2_instr->opcode = AIC_OP_ROL; 174162306a36Sopenharmony_ci f2_instr->destination = dest->symbol->info.rinfo->address 174262306a36Sopenharmony_ci + dest->offset; 174362306a36Sopenharmony_ci f2_instr->source = src->symbol->info.rinfo->address 174462306a36Sopenharmony_ci + src->offset; 174562306a36Sopenharmony_ci if (places->value > 8 || places->value <= 0) { 174662306a36Sopenharmony_ci stop("illegal shift value", EX_DATAERR); 174762306a36Sopenharmony_ci /* NOTREACHED */ 174862306a36Sopenharmony_ci } 174962306a36Sopenharmony_ci switch (opcode) { 175062306a36Sopenharmony_ci case AIC_OP_SHL: 175162306a36Sopenharmony_ci if (places->value == 8) 175262306a36Sopenharmony_ci shift_control = 0xf0; 175362306a36Sopenharmony_ci else 175462306a36Sopenharmony_ci shift_control = (places->value << 4) | places->value; 175562306a36Sopenharmony_ci break; 175662306a36Sopenharmony_ci case AIC_OP_SHR: 175762306a36Sopenharmony_ci if (places->value == 8) { 175862306a36Sopenharmony_ci shift_control = 0xf8; 175962306a36Sopenharmony_ci } else { 176062306a36Sopenharmony_ci shift_control = (places->value << 4) 176162306a36Sopenharmony_ci | (8 - places->value) 176262306a36Sopenharmony_ci | 0x08; 176362306a36Sopenharmony_ci } 176462306a36Sopenharmony_ci break; 176562306a36Sopenharmony_ci case AIC_OP_ROL: 176662306a36Sopenharmony_ci shift_control = places->value & 0x7; 176762306a36Sopenharmony_ci break; 176862306a36Sopenharmony_ci case AIC_OP_ROR: 176962306a36Sopenharmony_ci shift_control = (8 - places->value) | 0x08; 177062306a36Sopenharmony_ci break; 177162306a36Sopenharmony_ci default: 177262306a36Sopenharmony_ci shift_control = 0; /* Quiet Compiler */ 177362306a36Sopenharmony_ci stop("Invalid shift operation specified", EX_SOFTWARE); 177462306a36Sopenharmony_ci /* NOTREACHED */ 177562306a36Sopenharmony_ci break; 177662306a36Sopenharmony_ci }; 177762306a36Sopenharmony_ci f2_instr->shift_control = shift_control; 177862306a36Sopenharmony_ci symlist_free(&places->referenced_syms); 177962306a36Sopenharmony_ci instruction_ptr++; 178062306a36Sopenharmony_ci} 178162306a36Sopenharmony_ci 178262306a36Sopenharmony_cistatic void 178362306a36Sopenharmony_ciformat_3_instr(int opcode, symbol_ref_t *src, 178462306a36Sopenharmony_ci expression_t *immed, symbol_ref_t *address) 178562306a36Sopenharmony_ci{ 178662306a36Sopenharmony_ci struct instruction *instr; 178762306a36Sopenharmony_ci struct ins_format3 *f3_instr; 178862306a36Sopenharmony_ci int addr; 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci /* Test register permissions */ 179162306a36Sopenharmony_ci test_readable_symbol(src->symbol); 179262306a36Sopenharmony_ci 179362306a36Sopenharmony_ci /* Allocate sequencer space for the instruction and fill it out */ 179462306a36Sopenharmony_ci instr = seq_alloc(); 179562306a36Sopenharmony_ci f3_instr = &instr->format.format3; 179662306a36Sopenharmony_ci if (address->symbol == NULL) { 179762306a36Sopenharmony_ci /* 'dot' reference. Use the current instruction pointer */ 179862306a36Sopenharmony_ci addr = instruction_ptr + address->offset; 179962306a36Sopenharmony_ci } else if (address->symbol->type == UNINITIALIZED) { 180062306a36Sopenharmony_ci /* forward reference */ 180162306a36Sopenharmony_ci addr = address->offset; 180262306a36Sopenharmony_ci instr->patch_label = address->symbol; 180362306a36Sopenharmony_ci } else 180462306a36Sopenharmony_ci addr = address->symbol->info.linfo->address + address->offset; 180562306a36Sopenharmony_ci f3_instr->opcode = opcode; 180662306a36Sopenharmony_ci f3_instr->address = addr; 180762306a36Sopenharmony_ci f3_instr->source = src->symbol->info.rinfo->address 180862306a36Sopenharmony_ci + src->offset; 180962306a36Sopenharmony_ci f3_instr->immediate = immed->value; 181062306a36Sopenharmony_ci 181162306a36Sopenharmony_ci if (is_download_const(immed)) 181262306a36Sopenharmony_ci f3_instr->parity = 1; 181362306a36Sopenharmony_ci 181462306a36Sopenharmony_ci symlist_free(&immed->referenced_syms); 181562306a36Sopenharmony_ci instruction_ptr++; 181662306a36Sopenharmony_ci} 181762306a36Sopenharmony_ci 181862306a36Sopenharmony_cistatic void 181962306a36Sopenharmony_citest_readable_symbol(symbol_t *symbol) 182062306a36Sopenharmony_ci{ 182162306a36Sopenharmony_ci if ((symbol->info.rinfo->modes & (0x1 << src_mode)) == 0) { 182262306a36Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), 182362306a36Sopenharmony_ci "Register %s unavailable in source reg mode %d", 182462306a36Sopenharmony_ci symbol->name, src_mode); 182562306a36Sopenharmony_ci stop(errbuf, EX_DATAERR); 182662306a36Sopenharmony_ci } 182762306a36Sopenharmony_ci 182862306a36Sopenharmony_ci if (symbol->info.rinfo->mode == WO) { 182962306a36Sopenharmony_ci stop("Write Only register specified as source", 183062306a36Sopenharmony_ci EX_DATAERR); 183162306a36Sopenharmony_ci /* NOTREACHED */ 183262306a36Sopenharmony_ci } 183362306a36Sopenharmony_ci} 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_cistatic void 183662306a36Sopenharmony_citest_writable_symbol(symbol_t *symbol) 183762306a36Sopenharmony_ci{ 183862306a36Sopenharmony_ci if ((symbol->info.rinfo->modes & (0x1 << dst_mode)) == 0) { 183962306a36Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), 184062306a36Sopenharmony_ci "Register %s unavailable in destination reg mode %d", 184162306a36Sopenharmony_ci symbol->name, dst_mode); 184262306a36Sopenharmony_ci stop(errbuf, EX_DATAERR); 184362306a36Sopenharmony_ci } 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_ci if (symbol->info.rinfo->mode == RO) { 184662306a36Sopenharmony_ci stop("Read Only register specified as destination", 184762306a36Sopenharmony_ci EX_DATAERR); 184862306a36Sopenharmony_ci /* NOTREACHED */ 184962306a36Sopenharmony_ci } 185062306a36Sopenharmony_ci} 185162306a36Sopenharmony_ci 185262306a36Sopenharmony_cistatic void 185362306a36Sopenharmony_citype_check(symbol_ref_t *sym, expression_t *expression, int opcode) 185462306a36Sopenharmony_ci{ 185562306a36Sopenharmony_ci symbol_t *symbol = sym->symbol; 185662306a36Sopenharmony_ci symbol_node_t *node; 185762306a36Sopenharmony_ci int and_op; 185862306a36Sopenharmony_ci int8_t value, mask; 185962306a36Sopenharmony_ci 186062306a36Sopenharmony_ci and_op = FALSE; 186162306a36Sopenharmony_ci /* 186262306a36Sopenharmony_ci * Make sure that we aren't attempting to write something 186362306a36Sopenharmony_ci * that hasn't been defined. If this is an and operation, 186462306a36Sopenharmony_ci * this is a mask, so "undefined" bits are okay. 186562306a36Sopenharmony_ci */ 186662306a36Sopenharmony_ci if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || 186762306a36Sopenharmony_ci opcode == AIC_OP_JZ || opcode == AIC_OP_JNE || 186862306a36Sopenharmony_ci opcode == AIC_OP_BMOV) 186962306a36Sopenharmony_ci and_op = TRUE; 187062306a36Sopenharmony_ci 187162306a36Sopenharmony_ci /* 187262306a36Sopenharmony_ci * Defaulting to 8 bit logic 187362306a36Sopenharmony_ci */ 187462306a36Sopenharmony_ci mask = (int8_t)~symbol->info.rinfo->valid_bitmask; 187562306a36Sopenharmony_ci value = (int8_t)expression->value; 187662306a36Sopenharmony_ci 187762306a36Sopenharmony_ci if (and_op == FALSE && (mask & value) != 0 ) { 187862306a36Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), 187962306a36Sopenharmony_ci "Invalid bit(s) 0x%x in immediate written to %s", 188062306a36Sopenharmony_ci (mask & value), 188162306a36Sopenharmony_ci symbol->name); 188262306a36Sopenharmony_ci stop(errbuf, EX_DATAERR); 188362306a36Sopenharmony_ci /* NOTREACHED */ 188462306a36Sopenharmony_ci } 188562306a36Sopenharmony_ci 188662306a36Sopenharmony_ci /* 188762306a36Sopenharmony_ci * Now make sure that all of the symbols referenced by the 188862306a36Sopenharmony_ci * expression are defined for this register. 188962306a36Sopenharmony_ci */ 189062306a36Sopenharmony_ci if (symbol->info.rinfo->typecheck_masks != FALSE) { 189162306a36Sopenharmony_ci for(node = expression->referenced_syms.slh_first; 189262306a36Sopenharmony_ci node != NULL; 189362306a36Sopenharmony_ci node = node->links.sle_next) { 189462306a36Sopenharmony_ci if ((node->symbol->type == MASK 189562306a36Sopenharmony_ci || node->symbol->type == FIELD 189662306a36Sopenharmony_ci || node->symbol->type == ENUM 189762306a36Sopenharmony_ci || node->symbol->type == ENUM_ENTRY) 189862306a36Sopenharmony_ci && symlist_search(&node->symbol->info.finfo->symrefs, 189962306a36Sopenharmony_ci symbol->name) == NULL) { 190062306a36Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), 190162306a36Sopenharmony_ci "Invalid field or mask %s " 190262306a36Sopenharmony_ci "for register %s", 190362306a36Sopenharmony_ci node->symbol->name, symbol->name); 190462306a36Sopenharmony_ci stop(errbuf, EX_DATAERR); 190562306a36Sopenharmony_ci /* NOTREACHED */ 190662306a36Sopenharmony_ci } 190762306a36Sopenharmony_ci } 190862306a36Sopenharmony_ci } 190962306a36Sopenharmony_ci} 191062306a36Sopenharmony_ci 191162306a36Sopenharmony_cistatic void 191262306a36Sopenharmony_cimake_expression(expression_t *immed, int value) 191362306a36Sopenharmony_ci{ 191462306a36Sopenharmony_ci SLIST_INIT(&immed->referenced_syms); 191562306a36Sopenharmony_ci immed->value = value & 0xff; 191662306a36Sopenharmony_ci} 191762306a36Sopenharmony_ci 191862306a36Sopenharmony_cistatic void 191962306a36Sopenharmony_ciadd_conditional(symbol_t *symbol) 192062306a36Sopenharmony_ci{ 192162306a36Sopenharmony_ci static int numfuncs; 192262306a36Sopenharmony_ci 192362306a36Sopenharmony_ci if (numfuncs == 0) { 192462306a36Sopenharmony_ci /* add a special conditional, "0" */ 192562306a36Sopenharmony_ci symbol_t *false_func; 192662306a36Sopenharmony_ci 192762306a36Sopenharmony_ci false_func = symtable_get("0"); 192862306a36Sopenharmony_ci if (false_func->type != UNINITIALIZED) { 192962306a36Sopenharmony_ci stop("Conditional expression '0' " 193062306a36Sopenharmony_ci "conflicts with a symbol", EX_DATAERR); 193162306a36Sopenharmony_ci /* NOTREACHED */ 193262306a36Sopenharmony_ci } 193362306a36Sopenharmony_ci false_func->type = CONDITIONAL; 193462306a36Sopenharmony_ci initialize_symbol(false_func); 193562306a36Sopenharmony_ci false_func->info.condinfo->func_num = numfuncs++; 193662306a36Sopenharmony_ci symlist_add(&patch_functions, false_func, SYMLIST_INSERT_HEAD); 193762306a36Sopenharmony_ci } 193862306a36Sopenharmony_ci 193962306a36Sopenharmony_ci /* This condition has occurred before */ 194062306a36Sopenharmony_ci if (symbol->type == CONDITIONAL) 194162306a36Sopenharmony_ci return; 194262306a36Sopenharmony_ci 194362306a36Sopenharmony_ci if (symbol->type != UNINITIALIZED) { 194462306a36Sopenharmony_ci stop("Conditional expression conflicts with a symbol", 194562306a36Sopenharmony_ci EX_DATAERR); 194662306a36Sopenharmony_ci /* NOTREACHED */ 194762306a36Sopenharmony_ci } 194862306a36Sopenharmony_ci 194962306a36Sopenharmony_ci symbol->type = CONDITIONAL; 195062306a36Sopenharmony_ci initialize_symbol(symbol); 195162306a36Sopenharmony_ci symbol->info.condinfo->func_num = numfuncs++; 195262306a36Sopenharmony_ci symlist_add(&patch_functions, symbol, SYMLIST_INSERT_HEAD); 195362306a36Sopenharmony_ci} 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_cistatic void 195662306a36Sopenharmony_ciadd_version(const char *verstring) 195762306a36Sopenharmony_ci{ 195862306a36Sopenharmony_ci const char prefix[] = " * "; 195962306a36Sopenharmony_ci int newlen; 196062306a36Sopenharmony_ci int oldlen; 196162306a36Sopenharmony_ci 196262306a36Sopenharmony_ci newlen = strlen(verstring) + strlen(prefix); 196362306a36Sopenharmony_ci oldlen = 0; 196462306a36Sopenharmony_ci if (versions != NULL) 196562306a36Sopenharmony_ci oldlen = strlen(versions); 196662306a36Sopenharmony_ci versions = realloc(versions, newlen + oldlen + 2); 196762306a36Sopenharmony_ci if (versions == NULL) 196862306a36Sopenharmony_ci stop("Can't allocate version string", EX_SOFTWARE); 196962306a36Sopenharmony_ci strcpy(&versions[oldlen], prefix); 197062306a36Sopenharmony_ci strcpy(&versions[oldlen + strlen(prefix)], verstring); 197162306a36Sopenharmony_ci versions[newlen + oldlen] = '\n'; 197262306a36Sopenharmony_ci versions[newlen + oldlen + 1] = '\0'; 197362306a36Sopenharmony_ci} 197462306a36Sopenharmony_ci 197562306a36Sopenharmony_civoid 197662306a36Sopenharmony_ciyyerror(const char *string) 197762306a36Sopenharmony_ci{ 197862306a36Sopenharmony_ci stop(string, EX_DATAERR); 197962306a36Sopenharmony_ci} 198062306a36Sopenharmony_ci 198162306a36Sopenharmony_cistatic int 198262306a36Sopenharmony_ciis_download_const(expression_t *immed) 198362306a36Sopenharmony_ci{ 198462306a36Sopenharmony_ci if ((immed->referenced_syms.slh_first != NULL) 198562306a36Sopenharmony_ci && (immed->referenced_syms.slh_first->symbol->type == DOWNLOAD_CONST)) 198662306a36Sopenharmony_ci return (TRUE); 198762306a36Sopenharmony_ci 198862306a36Sopenharmony_ci return (FALSE); 198962306a36Sopenharmony_ci} 199062306a36Sopenharmony_ci 199162306a36Sopenharmony_cistatic int 199262306a36Sopenharmony_ciis_location_address(symbol_t *sym) 199362306a36Sopenharmony_ci{ 199462306a36Sopenharmony_ci if (sym->type == SCBLOC || 199562306a36Sopenharmony_ci sym->type == SRAMLOC) 199662306a36Sopenharmony_ci return (TRUE); 199762306a36Sopenharmony_ci return (FALSE); 199862306a36Sopenharmony_ci} 199962306a36Sopenharmony_ci 2000