18c2ecf20Sopenharmony_ci%{ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Parser for the Aic7xxx SCSI Host adapter sequencer assembler. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. 68c2ecf20Sopenharmony_ci * Copyright (c) 2001, 2002 Adaptec Inc. 78c2ecf20Sopenharmony_ci * All rights reserved. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 108c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 118c2ecf20Sopenharmony_ci * are met: 128c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 138c2ecf20Sopenharmony_ci * notice, this list of conditions, and the following disclaimer, 148c2ecf20Sopenharmony_ci * without modification. 158c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce at minimum a disclaimer 168c2ecf20Sopenharmony_ci * substantially similar to the "NO WARRANTY" disclaimer below 178c2ecf20Sopenharmony_ci * ("Disclaimer") and any redistribution must be conditioned upon 188c2ecf20Sopenharmony_ci * including a substantially similar Disclaimer requirement for further 198c2ecf20Sopenharmony_ci * binary redistribution. 208c2ecf20Sopenharmony_ci * 3. Neither the names of the above-listed copyright holders nor the names 218c2ecf20Sopenharmony_ci * of any contributors may be used to endorse or promote products derived 228c2ecf20Sopenharmony_ci * from this software without specific prior written permission. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the 258c2ecf20Sopenharmony_ci * GNU General Public License ("GPL") version 2 as published by the Free 268c2ecf20Sopenharmony_ci * Software Foundation. 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * NO WARRANTY 298c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 308c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 318c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 328c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 338c2ecf20Sopenharmony_ci * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 348c2ecf20Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 358c2ecf20Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 368c2ecf20Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 378c2ecf20Sopenharmony_ci * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 388c2ecf20Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 398c2ecf20Sopenharmony_ci * POSSIBILITY OF SUCH DAMAGES. 408c2ecf20Sopenharmony_ci * 418c2ecf20Sopenharmony_ci * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#30 $ 428c2ecf20Sopenharmony_ci * 438c2ecf20Sopenharmony_ci * $FreeBSD$ 448c2ecf20Sopenharmony_ci */ 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#include <sys/types.h> 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#include <inttypes.h> 498c2ecf20Sopenharmony_ci#include <regex.h> 508c2ecf20Sopenharmony_ci#include <stdio.h> 518c2ecf20Sopenharmony_ci#include <stdlib.h> 528c2ecf20Sopenharmony_ci#include <string.h> 538c2ecf20Sopenharmony_ci#include <sysexits.h> 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci#include "../queue.h" 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci#include "aicasm.h" 588c2ecf20Sopenharmony_ci#include "aicasm_symbol.h" 598c2ecf20Sopenharmony_ci#include "aicasm_insformat.h" 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ciint yylineno; 628c2ecf20Sopenharmony_cichar *yyfilename; 638c2ecf20Sopenharmony_cichar stock_prefix[] = "aic_"; 648c2ecf20Sopenharmony_cichar *prefix = stock_prefix; 658c2ecf20Sopenharmony_cichar *patch_arg_list; 668c2ecf20Sopenharmony_cichar *versions; 678c2ecf20Sopenharmony_cistatic char errbuf[255]; 688c2ecf20Sopenharmony_cistatic char regex_pattern[255]; 698c2ecf20Sopenharmony_cistatic symbol_t *cur_symbol; 708c2ecf20Sopenharmony_cistatic symbol_t *field_symbol; 718c2ecf20Sopenharmony_cistatic symbol_t *scb_or_sram_symbol; 728c2ecf20Sopenharmony_cistatic symtype cur_symtype; 738c2ecf20Sopenharmony_cistatic symbol_ref_t accumulator; 748c2ecf20Sopenharmony_cistatic symbol_ref_t mode_ptr; 758c2ecf20Sopenharmony_cistatic symbol_ref_t allones; 768c2ecf20Sopenharmony_cistatic symbol_ref_t allzeros; 778c2ecf20Sopenharmony_cistatic symbol_ref_t none; 788c2ecf20Sopenharmony_cistatic symbol_ref_t sindex; 798c2ecf20Sopenharmony_cistatic int instruction_ptr; 808c2ecf20Sopenharmony_cistatic int num_srams; 818c2ecf20Sopenharmony_cistatic int sram_or_scb_offset; 828c2ecf20Sopenharmony_cistatic int download_constant_count; 838c2ecf20Sopenharmony_cistatic int in_critical_section; 848c2ecf20Sopenharmony_cistatic u_int enum_increment; 858c2ecf20Sopenharmony_cistatic u_int enum_next_value; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistatic void process_field(int field_type, symbol_t *sym, int mask); 888c2ecf20Sopenharmony_cistatic void initialize_symbol(symbol_t *symbol); 898c2ecf20Sopenharmony_cistatic void add_macro_arg(const char *argtext, int position); 908c2ecf20Sopenharmony_cistatic void add_macro_body(const char *bodytext); 918c2ecf20Sopenharmony_cistatic void process_register(symbol_t **p_symbol); 928c2ecf20Sopenharmony_cistatic void format_1_instr(int opcode, symbol_ref_t *dest, 938c2ecf20Sopenharmony_ci expression_t *immed, symbol_ref_t *src, int ret); 948c2ecf20Sopenharmony_cistatic void format_2_instr(int opcode, symbol_ref_t *dest, 958c2ecf20Sopenharmony_ci expression_t *places, symbol_ref_t *src, int ret); 968c2ecf20Sopenharmony_cistatic void format_3_instr(int opcode, symbol_ref_t *src, 978c2ecf20Sopenharmony_ci expression_t *immed, symbol_ref_t *address); 988c2ecf20Sopenharmony_cistatic void test_readable_symbol(symbol_t *symbol); 998c2ecf20Sopenharmony_cistatic void test_writable_symbol(symbol_t *symbol); 1008c2ecf20Sopenharmony_cistatic void type_check(symbol_ref_t *sym, expression_t *expression, int and_op); 1018c2ecf20Sopenharmony_cistatic void make_expression(expression_t *immed, int value); 1028c2ecf20Sopenharmony_cistatic void add_conditional(symbol_t *symbol); 1038c2ecf20Sopenharmony_cistatic void add_version(const char *verstring); 1048c2ecf20Sopenharmony_cistatic int is_download_const(expression_t *immed); 1058c2ecf20Sopenharmony_cistatic int is_location_address(symbol_t *symbol); 1068c2ecf20Sopenharmony_civoid yyerror(const char *string); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci#define SRAM_SYMNAME "SRAM_BASE" 1098c2ecf20Sopenharmony_ci#define SCB_SYMNAME "SCB_BASE" 1108c2ecf20Sopenharmony_ci%} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci%union { 1138c2ecf20Sopenharmony_ci u_int value; 1148c2ecf20Sopenharmony_ci char *str; 1158c2ecf20Sopenharmony_ci symbol_t *sym; 1168c2ecf20Sopenharmony_ci symbol_ref_t sym_ref; 1178c2ecf20Sopenharmony_ci expression_t expression; 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci%token T_REGISTER 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci%token <value> T_CONST 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci%token T_EXPORT 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci%token T_DOWNLOAD 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci%token T_SCB 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci%token T_SRAM 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci%token T_ALIAS 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci%token T_SIZE 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci%token T_EXPR_LSHIFT 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci%token T_EXPR_RSHIFT 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci%token <value> T_ADDRESS 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci%token T_COUNT 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci%token T_ACCESS_MODE 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci%token T_DONT_GENERATE_DEBUG_CODE 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci%token T_MODES 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci%token T_DEFINE 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci%token T_SET_SRC_MODE 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci%token T_SET_DST_MODE 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci%token <value> T_MODE 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci%token T_BEGIN_CS 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci%token T_END_CS 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci%token T_PAD_PAGE 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci%token T_FIELD 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci%token T_ENUM 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci%token T_MASK 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci%token <value> T_NUMBER 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci%token <str> T_PATH T_STRING T_ARG T_MACROBODY 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci%token <sym> T_CEXPR 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci%token T_EOF T_INCLUDE T_VERSION T_PREFIX T_PATCH_ARG_LIST 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci%token <value> T_SHR T_SHL T_ROR T_ROL 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci%token <value> T_MVI T_MOV T_CLR T_BMOV 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci%token <value> T_JMP T_JC T_JNC T_JE T_JNE T_JNZ T_JZ T_CALL 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci%token <value> T_ADD T_ADC 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci%token <value> T_INC T_DEC 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci%token <value> T_STC T_CLC 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci%token <value> T_CMP T_NOT T_XOR 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci%token <value> T_TEST T_AND 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci%token <value> T_OR 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci/* 16 bit extensions, not implemented 1978c2ecf20Sopenharmony_ci * %token <value> T_OR16 T_AND16 T_XOR16 T_ADD16 1988c2ecf20Sopenharmony_ci * %token <value> T_ADC16 T_MVI16 T_TEST16 T_CMP16 T_CMPXCHG 1998c2ecf20Sopenharmony_ci */ 2008c2ecf20Sopenharmony_ci%token T_RET 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci%token T_NOP 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci%token T_ACCUM T_ALLONES T_ALLZEROS T_NONE T_SINDEX T_MODE_PTR 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci%token T_A 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci%token <sym> T_SYMBOL 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci%token T_NL 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci%token T_IF T_ELSE T_ELSE_IF T_ENDIF 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci%type <sym_ref> reg_symbol address destination source opt_source 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci%type <expression> expression immediate immediate_or_a 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci%type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci%type <value> mode_value mode_list macro_arglist 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci%left '|' 2238c2ecf20Sopenharmony_ci%left '&' 2248c2ecf20Sopenharmony_ci%left T_EXPR_LSHIFT T_EXPR_RSHIFT 2258c2ecf20Sopenharmony_ci%left '+' '-' 2268c2ecf20Sopenharmony_ci%left '*' '/' 2278c2ecf20Sopenharmony_ci%right '~' 2288c2ecf20Sopenharmony_ci%nonassoc UMINUS 2298c2ecf20Sopenharmony_ci%% 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ciprogram: 2328c2ecf20Sopenharmony_ci include 2338c2ecf20Sopenharmony_ci| program include 2348c2ecf20Sopenharmony_ci| prefix 2358c2ecf20Sopenharmony_ci| program prefix 2368c2ecf20Sopenharmony_ci| patch_arg_list 2378c2ecf20Sopenharmony_ci| program patch_arg_list 2388c2ecf20Sopenharmony_ci| version 2398c2ecf20Sopenharmony_ci| program version 2408c2ecf20Sopenharmony_ci| register 2418c2ecf20Sopenharmony_ci| program register 2428c2ecf20Sopenharmony_ci| constant 2438c2ecf20Sopenharmony_ci| program constant 2448c2ecf20Sopenharmony_ci| macrodefn 2458c2ecf20Sopenharmony_ci| program macrodefn 2468c2ecf20Sopenharmony_ci| scratch_ram 2478c2ecf20Sopenharmony_ci| program scratch_ram 2488c2ecf20Sopenharmony_ci| scb 2498c2ecf20Sopenharmony_ci| program scb 2508c2ecf20Sopenharmony_ci| label 2518c2ecf20Sopenharmony_ci| program label 2528c2ecf20Sopenharmony_ci| set_src_mode 2538c2ecf20Sopenharmony_ci| program set_src_mode 2548c2ecf20Sopenharmony_ci| set_dst_mode 2558c2ecf20Sopenharmony_ci| program set_dst_mode 2568c2ecf20Sopenharmony_ci| critical_section_start 2578c2ecf20Sopenharmony_ci| program critical_section_start 2588c2ecf20Sopenharmony_ci| critical_section_end 2598c2ecf20Sopenharmony_ci| program critical_section_end 2608c2ecf20Sopenharmony_ci| conditional 2618c2ecf20Sopenharmony_ci| program conditional 2628c2ecf20Sopenharmony_ci| code 2638c2ecf20Sopenharmony_ci| program code 2648c2ecf20Sopenharmony_ci; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ciinclude: 2678c2ecf20Sopenharmony_ci T_INCLUDE '<' T_PATH '>' 2688c2ecf20Sopenharmony_ci { 2698c2ecf20Sopenharmony_ci include_file($3, BRACKETED_INCLUDE); 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci| T_INCLUDE '"' T_PATH '"' 2728c2ecf20Sopenharmony_ci { 2738c2ecf20Sopenharmony_ci include_file($3, QUOTED_INCLUDE); 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ciprefix: 2788c2ecf20Sopenharmony_ci T_PREFIX '=' T_STRING 2798c2ecf20Sopenharmony_ci { 2808c2ecf20Sopenharmony_ci if (prefix != stock_prefix) 2818c2ecf20Sopenharmony_ci stop("Prefix multiply defined", 2828c2ecf20Sopenharmony_ci EX_DATAERR); 2838c2ecf20Sopenharmony_ci prefix = strdup($3); 2848c2ecf20Sopenharmony_ci if (prefix == NULL) 2858c2ecf20Sopenharmony_ci stop("Unable to record prefix", EX_SOFTWARE); 2868c2ecf20Sopenharmony_ci } 2878c2ecf20Sopenharmony_ci; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_cipatch_arg_list: 2908c2ecf20Sopenharmony_ci T_PATCH_ARG_LIST '=' T_STRING 2918c2ecf20Sopenharmony_ci { 2928c2ecf20Sopenharmony_ci if (patch_arg_list != NULL) 2938c2ecf20Sopenharmony_ci stop("Patch argument list multiply defined", 2948c2ecf20Sopenharmony_ci EX_DATAERR); 2958c2ecf20Sopenharmony_ci patch_arg_list = strdup($3); 2968c2ecf20Sopenharmony_ci if (patch_arg_list == NULL) 2978c2ecf20Sopenharmony_ci stop("Unable to record patch arg list", EX_SOFTWARE); 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_civersion: 3028c2ecf20Sopenharmony_ci T_VERSION '=' T_STRING 3038c2ecf20Sopenharmony_ci { add_version($3); } 3048c2ecf20Sopenharmony_ci; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ciregister: 3078c2ecf20Sopenharmony_ci T_REGISTER { cur_symtype = REGISTER; } reg_definition 3088c2ecf20Sopenharmony_ci; 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_cireg_definition: 3118c2ecf20Sopenharmony_ci T_SYMBOL '{' 3128c2ecf20Sopenharmony_ci { 3138c2ecf20Sopenharmony_ci if ($1->type != UNINITIALIZED) { 3148c2ecf20Sopenharmony_ci stop("Register multiply defined", EX_DATAERR); 3158c2ecf20Sopenharmony_ci /* NOTREACHED */ 3168c2ecf20Sopenharmony_ci } 3178c2ecf20Sopenharmony_ci cur_symbol = $1; 3188c2ecf20Sopenharmony_ci cur_symbol->type = cur_symtype; 3198c2ecf20Sopenharmony_ci initialize_symbol(cur_symbol); 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci reg_attribute_list 3228c2ecf20Sopenharmony_ci '}' 3238c2ecf20Sopenharmony_ci { 3248c2ecf20Sopenharmony_ci /* 3258c2ecf20Sopenharmony_ci * Default to allowing everything in for registers 3268c2ecf20Sopenharmony_ci * with no bit or mask definitions. 3278c2ecf20Sopenharmony_ci */ 3288c2ecf20Sopenharmony_ci if (cur_symbol->info.rinfo->valid_bitmask == 0) 3298c2ecf20Sopenharmony_ci cur_symbol->info.rinfo->valid_bitmask = 0xFF; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci if (cur_symbol->info.rinfo->size == 0) 3328c2ecf20Sopenharmony_ci cur_symbol->info.rinfo->size = 1; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci /* 3358c2ecf20Sopenharmony_ci * This might be useful for registers too. 3368c2ecf20Sopenharmony_ci */ 3378c2ecf20Sopenharmony_ci if (cur_symbol->type != REGISTER) { 3388c2ecf20Sopenharmony_ci if (cur_symbol->info.rinfo->address == 0) 3398c2ecf20Sopenharmony_ci cur_symbol->info.rinfo->address = 3408c2ecf20Sopenharmony_ci sram_or_scb_offset; 3418c2ecf20Sopenharmony_ci sram_or_scb_offset += 3428c2ecf20Sopenharmony_ci cur_symbol->info.rinfo->size; 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci cur_symbol = NULL; 3458c2ecf20Sopenharmony_ci } 3468c2ecf20Sopenharmony_ci; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_cireg_attribute_list: 3498c2ecf20Sopenharmony_ci reg_attribute 3508c2ecf20Sopenharmony_ci| reg_attribute_list reg_attribute 3518c2ecf20Sopenharmony_ci; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_cireg_attribute: 3548c2ecf20Sopenharmony_ci reg_address 3558c2ecf20Sopenharmony_ci| size 3568c2ecf20Sopenharmony_ci| count 3578c2ecf20Sopenharmony_ci| access_mode 3588c2ecf20Sopenharmony_ci| dont_generate_debug_code 3598c2ecf20Sopenharmony_ci| modes 3608c2ecf20Sopenharmony_ci| field_defn 3618c2ecf20Sopenharmony_ci| enum_defn 3628c2ecf20Sopenharmony_ci| mask_defn 3638c2ecf20Sopenharmony_ci| alias 3648c2ecf20Sopenharmony_ci| accumulator 3658c2ecf20Sopenharmony_ci| mode_pointer 3668c2ecf20Sopenharmony_ci| allones 3678c2ecf20Sopenharmony_ci| allzeros 3688c2ecf20Sopenharmony_ci| none 3698c2ecf20Sopenharmony_ci| sindex 3708c2ecf20Sopenharmony_ci; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_cireg_address: 3738c2ecf20Sopenharmony_ci T_ADDRESS T_NUMBER 3748c2ecf20Sopenharmony_ci { 3758c2ecf20Sopenharmony_ci cur_symbol->info.rinfo->address = $2; 3768c2ecf20Sopenharmony_ci } 3778c2ecf20Sopenharmony_ci; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_cisize: 3808c2ecf20Sopenharmony_ci T_SIZE T_NUMBER 3818c2ecf20Sopenharmony_ci { 3828c2ecf20Sopenharmony_ci cur_symbol->info.rinfo->size = $2; 3838c2ecf20Sopenharmony_ci if (scb_or_sram_symbol != NULL) { 3848c2ecf20Sopenharmony_ci u_int max_addr; 3858c2ecf20Sopenharmony_ci u_int sym_max_addr; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci max_addr = scb_or_sram_symbol->info.rinfo->address 3888c2ecf20Sopenharmony_ci + scb_or_sram_symbol->info.rinfo->size; 3898c2ecf20Sopenharmony_ci sym_max_addr = cur_symbol->info.rinfo->address 3908c2ecf20Sopenharmony_ci + cur_symbol->info.rinfo->size; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci if (sym_max_addr > max_addr) 3938c2ecf20Sopenharmony_ci stop("SCB or SRAM space exhausted", EX_DATAERR); 3948c2ecf20Sopenharmony_ci } 3958c2ecf20Sopenharmony_ci } 3968c2ecf20Sopenharmony_ci; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_cicount: 3998c2ecf20Sopenharmony_ci T_COUNT T_NUMBER 4008c2ecf20Sopenharmony_ci { 4018c2ecf20Sopenharmony_ci cur_symbol->count += $2; 4028c2ecf20Sopenharmony_ci } 4038c2ecf20Sopenharmony_ci; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ciaccess_mode: 4068c2ecf20Sopenharmony_ci T_ACCESS_MODE T_MODE 4078c2ecf20Sopenharmony_ci { 4088c2ecf20Sopenharmony_ci cur_symbol->info.rinfo->mode = $2; 4098c2ecf20Sopenharmony_ci } 4108c2ecf20Sopenharmony_ci; 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_cidont_generate_debug_code: 4138c2ecf20Sopenharmony_ci T_DONT_GENERATE_DEBUG_CODE 4148c2ecf20Sopenharmony_ci { 4158c2ecf20Sopenharmony_ci cur_symbol->dont_generate_debug_code = 1; 4168c2ecf20Sopenharmony_ci } 4178c2ecf20Sopenharmony_ci; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_cimodes: 4208c2ecf20Sopenharmony_ci T_MODES mode_list 4218c2ecf20Sopenharmony_ci { 4228c2ecf20Sopenharmony_ci cur_symbol->info.rinfo->modes = $2; 4238c2ecf20Sopenharmony_ci } 4248c2ecf20Sopenharmony_ci; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_cimode_list: 4278c2ecf20Sopenharmony_ci mode_value 4288c2ecf20Sopenharmony_ci { 4298c2ecf20Sopenharmony_ci $$ = $1; 4308c2ecf20Sopenharmony_ci } 4318c2ecf20Sopenharmony_ci| mode_list ',' mode_value 4328c2ecf20Sopenharmony_ci { 4338c2ecf20Sopenharmony_ci $$ = $1 | $3; 4348c2ecf20Sopenharmony_ci } 4358c2ecf20Sopenharmony_ci; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_cimode_value: 4388c2ecf20Sopenharmony_ci T_NUMBER 4398c2ecf20Sopenharmony_ci { 4408c2ecf20Sopenharmony_ci if ($1 > 4) { 4418c2ecf20Sopenharmony_ci stop("Valid register modes range between 0 and 4.", 4428c2ecf20Sopenharmony_ci EX_DATAERR); 4438c2ecf20Sopenharmony_ci /* NOTREACHED */ 4448c2ecf20Sopenharmony_ci } 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci $$ = (0x1 << $1); 4478c2ecf20Sopenharmony_ci } 4488c2ecf20Sopenharmony_ci| T_SYMBOL 4498c2ecf20Sopenharmony_ci { 4508c2ecf20Sopenharmony_ci symbol_t *symbol; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci symbol = $1; 4538c2ecf20Sopenharmony_ci if (symbol->type != CONST) { 4548c2ecf20Sopenharmony_ci stop("Only \"const\" symbols allowed in " 4558c2ecf20Sopenharmony_ci "mode definitions.", EX_DATAERR); 4568c2ecf20Sopenharmony_ci /* NOTREACHED */ 4578c2ecf20Sopenharmony_ci } 4588c2ecf20Sopenharmony_ci if (symbol->info.cinfo->value > 4) { 4598c2ecf20Sopenharmony_ci stop("Valid register modes range between 0 and 4.", 4608c2ecf20Sopenharmony_ci EX_DATAERR); 4618c2ecf20Sopenharmony_ci /* NOTREACHED */ 4628c2ecf20Sopenharmony_ci } 4638c2ecf20Sopenharmony_ci $$ = (0x1 << symbol->info.cinfo->value); 4648c2ecf20Sopenharmony_ci } 4658c2ecf20Sopenharmony_ci; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_cifield_defn: 4688c2ecf20Sopenharmony_ci T_FIELD 4698c2ecf20Sopenharmony_ci { 4708c2ecf20Sopenharmony_ci field_symbol = NULL; 4718c2ecf20Sopenharmony_ci enum_next_value = 0; 4728c2ecf20Sopenharmony_ci enum_increment = 1; 4738c2ecf20Sopenharmony_ci } 4748c2ecf20Sopenharmony_ci '{' enum_entry_list '}' 4758c2ecf20Sopenharmony_ci| T_FIELD T_SYMBOL expression 4768c2ecf20Sopenharmony_ci { 4778c2ecf20Sopenharmony_ci process_field(FIELD, $2, $3.value); 4788c2ecf20Sopenharmony_ci field_symbol = $2; 4798c2ecf20Sopenharmony_ci enum_next_value = 0; 4808c2ecf20Sopenharmony_ci enum_increment = 0x01 << (ffs($3.value) - 1); 4818c2ecf20Sopenharmony_ci } 4828c2ecf20Sopenharmony_ci '{' enum_entry_list '}' 4838c2ecf20Sopenharmony_ci| T_FIELD T_SYMBOL expression 4848c2ecf20Sopenharmony_ci { 4858c2ecf20Sopenharmony_ci process_field(FIELD, $2, $3.value); 4868c2ecf20Sopenharmony_ci } 4878c2ecf20Sopenharmony_ci; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_cienum_defn: 4908c2ecf20Sopenharmony_ci T_ENUM 4918c2ecf20Sopenharmony_ci { 4928c2ecf20Sopenharmony_ci field_symbol = NULL; 4938c2ecf20Sopenharmony_ci enum_next_value = 0; 4948c2ecf20Sopenharmony_ci enum_increment = 1; 4958c2ecf20Sopenharmony_ci } 4968c2ecf20Sopenharmony_ci '{' enum_entry_list '}' 4978c2ecf20Sopenharmony_ci| T_ENUM T_SYMBOL expression 4988c2ecf20Sopenharmony_ci { 4998c2ecf20Sopenharmony_ci process_field(ENUM, $2, $3.value); 5008c2ecf20Sopenharmony_ci field_symbol = $2; 5018c2ecf20Sopenharmony_ci enum_next_value = 0; 5028c2ecf20Sopenharmony_ci enum_increment = 0x01 << (ffs($3.value) - 1); 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci '{' enum_entry_list '}' 5058c2ecf20Sopenharmony_ci; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_cienum_entry_list: 5088c2ecf20Sopenharmony_ci enum_entry 5098c2ecf20Sopenharmony_ci| enum_entry_list ',' enum_entry 5108c2ecf20Sopenharmony_ci; 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_cienum_entry: 5138c2ecf20Sopenharmony_ci T_SYMBOL 5148c2ecf20Sopenharmony_ci { 5158c2ecf20Sopenharmony_ci process_field(ENUM_ENTRY, $1, enum_next_value); 5168c2ecf20Sopenharmony_ci enum_next_value += enum_increment; 5178c2ecf20Sopenharmony_ci } 5188c2ecf20Sopenharmony_ci| T_SYMBOL expression 5198c2ecf20Sopenharmony_ci { 5208c2ecf20Sopenharmony_ci process_field(ENUM_ENTRY, $1, $2.value); 5218c2ecf20Sopenharmony_ci enum_next_value = $2.value + enum_increment; 5228c2ecf20Sopenharmony_ci } 5238c2ecf20Sopenharmony_ci; 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_cimask_defn: 5268c2ecf20Sopenharmony_ci T_MASK T_SYMBOL expression 5278c2ecf20Sopenharmony_ci { 5288c2ecf20Sopenharmony_ci process_field(MASK, $2, $3.value); 5298c2ecf20Sopenharmony_ci } 5308c2ecf20Sopenharmony_ci; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_cialias: 5338c2ecf20Sopenharmony_ci T_ALIAS T_SYMBOL 5348c2ecf20Sopenharmony_ci { 5358c2ecf20Sopenharmony_ci if ($2->type != UNINITIALIZED) { 5368c2ecf20Sopenharmony_ci stop("Re-definition of register alias", 5378c2ecf20Sopenharmony_ci EX_DATAERR); 5388c2ecf20Sopenharmony_ci /* NOTREACHED */ 5398c2ecf20Sopenharmony_ci } 5408c2ecf20Sopenharmony_ci $2->type = ALIAS; 5418c2ecf20Sopenharmony_ci initialize_symbol($2); 5428c2ecf20Sopenharmony_ci $2->info.ainfo->parent = cur_symbol; 5438c2ecf20Sopenharmony_ci } 5448c2ecf20Sopenharmony_ci; 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ciaccumulator: 5478c2ecf20Sopenharmony_ci T_ACCUM 5488c2ecf20Sopenharmony_ci { 5498c2ecf20Sopenharmony_ci if (accumulator.symbol != NULL) { 5508c2ecf20Sopenharmony_ci stop("Only one accumulator definition allowed", 5518c2ecf20Sopenharmony_ci EX_DATAERR); 5528c2ecf20Sopenharmony_ci /* NOTREACHED */ 5538c2ecf20Sopenharmony_ci } 5548c2ecf20Sopenharmony_ci accumulator.symbol = cur_symbol; 5558c2ecf20Sopenharmony_ci } 5568c2ecf20Sopenharmony_ci; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_cimode_pointer: 5598c2ecf20Sopenharmony_ci T_MODE_PTR 5608c2ecf20Sopenharmony_ci { 5618c2ecf20Sopenharmony_ci if (mode_ptr.symbol != NULL) { 5628c2ecf20Sopenharmony_ci stop("Only one mode pointer definition allowed", 5638c2ecf20Sopenharmony_ci EX_DATAERR); 5648c2ecf20Sopenharmony_ci /* NOTREACHED */ 5658c2ecf20Sopenharmony_ci } 5668c2ecf20Sopenharmony_ci mode_ptr.symbol = cur_symbol; 5678c2ecf20Sopenharmony_ci } 5688c2ecf20Sopenharmony_ci; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ciallones: 5718c2ecf20Sopenharmony_ci T_ALLONES 5728c2ecf20Sopenharmony_ci { 5738c2ecf20Sopenharmony_ci if (allones.symbol != NULL) { 5748c2ecf20Sopenharmony_ci stop("Only one definition of allones allowed", 5758c2ecf20Sopenharmony_ci EX_DATAERR); 5768c2ecf20Sopenharmony_ci /* NOTREACHED */ 5778c2ecf20Sopenharmony_ci } 5788c2ecf20Sopenharmony_ci allones.symbol = cur_symbol; 5798c2ecf20Sopenharmony_ci } 5808c2ecf20Sopenharmony_ci; 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ciallzeros: 5838c2ecf20Sopenharmony_ci T_ALLZEROS 5848c2ecf20Sopenharmony_ci { 5858c2ecf20Sopenharmony_ci if (allzeros.symbol != NULL) { 5868c2ecf20Sopenharmony_ci stop("Only one definition of allzeros allowed", 5878c2ecf20Sopenharmony_ci EX_DATAERR); 5888c2ecf20Sopenharmony_ci /* NOTREACHED */ 5898c2ecf20Sopenharmony_ci } 5908c2ecf20Sopenharmony_ci allzeros.symbol = cur_symbol; 5918c2ecf20Sopenharmony_ci } 5928c2ecf20Sopenharmony_ci; 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_cinone: 5958c2ecf20Sopenharmony_ci T_NONE 5968c2ecf20Sopenharmony_ci { 5978c2ecf20Sopenharmony_ci if (none.symbol != NULL) { 5988c2ecf20Sopenharmony_ci stop("Only one definition of none allowed", 5998c2ecf20Sopenharmony_ci EX_DATAERR); 6008c2ecf20Sopenharmony_ci /* NOTREACHED */ 6018c2ecf20Sopenharmony_ci } 6028c2ecf20Sopenharmony_ci none.symbol = cur_symbol; 6038c2ecf20Sopenharmony_ci } 6048c2ecf20Sopenharmony_ci; 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_cisindex: 6078c2ecf20Sopenharmony_ci T_SINDEX 6088c2ecf20Sopenharmony_ci { 6098c2ecf20Sopenharmony_ci if (sindex.symbol != NULL) { 6108c2ecf20Sopenharmony_ci stop("Only one definition of sindex allowed", 6118c2ecf20Sopenharmony_ci EX_DATAERR); 6128c2ecf20Sopenharmony_ci /* NOTREACHED */ 6138c2ecf20Sopenharmony_ci } 6148c2ecf20Sopenharmony_ci sindex.symbol = cur_symbol; 6158c2ecf20Sopenharmony_ci } 6168c2ecf20Sopenharmony_ci; 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ciexpression: 6198c2ecf20Sopenharmony_ci expression '|' expression 6208c2ecf20Sopenharmony_ci { 6218c2ecf20Sopenharmony_ci $$.value = $1.value | $3.value; 6228c2ecf20Sopenharmony_ci symlist_merge(&$$.referenced_syms, 6238c2ecf20Sopenharmony_ci &$1.referenced_syms, 6248c2ecf20Sopenharmony_ci &$3.referenced_syms); 6258c2ecf20Sopenharmony_ci } 6268c2ecf20Sopenharmony_ci| expression '&' expression 6278c2ecf20Sopenharmony_ci { 6288c2ecf20Sopenharmony_ci $$.value = $1.value & $3.value; 6298c2ecf20Sopenharmony_ci symlist_merge(&$$.referenced_syms, 6308c2ecf20Sopenharmony_ci &$1.referenced_syms, 6318c2ecf20Sopenharmony_ci &$3.referenced_syms); 6328c2ecf20Sopenharmony_ci } 6338c2ecf20Sopenharmony_ci| expression '+' expression 6348c2ecf20Sopenharmony_ci { 6358c2ecf20Sopenharmony_ci $$.value = $1.value + $3.value; 6368c2ecf20Sopenharmony_ci symlist_merge(&$$.referenced_syms, 6378c2ecf20Sopenharmony_ci &$1.referenced_syms, 6388c2ecf20Sopenharmony_ci &$3.referenced_syms); 6398c2ecf20Sopenharmony_ci } 6408c2ecf20Sopenharmony_ci| expression '-' expression 6418c2ecf20Sopenharmony_ci { 6428c2ecf20Sopenharmony_ci $$.value = $1.value - $3.value; 6438c2ecf20Sopenharmony_ci symlist_merge(&($$.referenced_syms), 6448c2ecf20Sopenharmony_ci &($1.referenced_syms), 6458c2ecf20Sopenharmony_ci &($3.referenced_syms)); 6468c2ecf20Sopenharmony_ci } 6478c2ecf20Sopenharmony_ci| expression '*' expression 6488c2ecf20Sopenharmony_ci { 6498c2ecf20Sopenharmony_ci $$.value = $1.value * $3.value; 6508c2ecf20Sopenharmony_ci symlist_merge(&($$.referenced_syms), 6518c2ecf20Sopenharmony_ci &($1.referenced_syms), 6528c2ecf20Sopenharmony_ci &($3.referenced_syms)); 6538c2ecf20Sopenharmony_ci } 6548c2ecf20Sopenharmony_ci| expression '/' expression 6558c2ecf20Sopenharmony_ci { 6568c2ecf20Sopenharmony_ci $$.value = $1.value / $3.value; 6578c2ecf20Sopenharmony_ci symlist_merge(&($$.referenced_syms), 6588c2ecf20Sopenharmony_ci &($1.referenced_syms), 6598c2ecf20Sopenharmony_ci &($3.referenced_syms)); 6608c2ecf20Sopenharmony_ci } 6618c2ecf20Sopenharmony_ci| expression T_EXPR_LSHIFT expression 6628c2ecf20Sopenharmony_ci { 6638c2ecf20Sopenharmony_ci $$.value = $1.value << $3.value; 6648c2ecf20Sopenharmony_ci symlist_merge(&$$.referenced_syms, 6658c2ecf20Sopenharmony_ci &$1.referenced_syms, 6668c2ecf20Sopenharmony_ci &$3.referenced_syms); 6678c2ecf20Sopenharmony_ci } 6688c2ecf20Sopenharmony_ci| expression T_EXPR_RSHIFT expression 6698c2ecf20Sopenharmony_ci { 6708c2ecf20Sopenharmony_ci $$.value = $1.value >> $3.value; 6718c2ecf20Sopenharmony_ci symlist_merge(&$$.referenced_syms, 6728c2ecf20Sopenharmony_ci &$1.referenced_syms, 6738c2ecf20Sopenharmony_ci &$3.referenced_syms); 6748c2ecf20Sopenharmony_ci } 6758c2ecf20Sopenharmony_ci| '(' expression ')' 6768c2ecf20Sopenharmony_ci { 6778c2ecf20Sopenharmony_ci $$ = $2; 6788c2ecf20Sopenharmony_ci } 6798c2ecf20Sopenharmony_ci| '~' expression 6808c2ecf20Sopenharmony_ci { 6818c2ecf20Sopenharmony_ci $$ = $2; 6828c2ecf20Sopenharmony_ci $$.value = (~$$.value) & 0xFF; 6838c2ecf20Sopenharmony_ci } 6848c2ecf20Sopenharmony_ci| '-' expression %prec UMINUS 6858c2ecf20Sopenharmony_ci { 6868c2ecf20Sopenharmony_ci $$ = $2; 6878c2ecf20Sopenharmony_ci $$.value = -$$.value; 6888c2ecf20Sopenharmony_ci } 6898c2ecf20Sopenharmony_ci| T_NUMBER 6908c2ecf20Sopenharmony_ci { 6918c2ecf20Sopenharmony_ci $$.value = $1; 6928c2ecf20Sopenharmony_ci SLIST_INIT(&$$.referenced_syms); 6938c2ecf20Sopenharmony_ci } 6948c2ecf20Sopenharmony_ci| T_SYMBOL 6958c2ecf20Sopenharmony_ci { 6968c2ecf20Sopenharmony_ci symbol_t *symbol; 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci symbol = $1; 6998c2ecf20Sopenharmony_ci switch (symbol->type) { 7008c2ecf20Sopenharmony_ci case ALIAS: 7018c2ecf20Sopenharmony_ci symbol = $1->info.ainfo->parent; 7028c2ecf20Sopenharmony_ci case REGISTER: 7038c2ecf20Sopenharmony_ci case SCBLOC: 7048c2ecf20Sopenharmony_ci case SRAMLOC: 7058c2ecf20Sopenharmony_ci $$.value = symbol->info.rinfo->address; 7068c2ecf20Sopenharmony_ci break; 7078c2ecf20Sopenharmony_ci case MASK: 7088c2ecf20Sopenharmony_ci case FIELD: 7098c2ecf20Sopenharmony_ci case ENUM: 7108c2ecf20Sopenharmony_ci case ENUM_ENTRY: 7118c2ecf20Sopenharmony_ci $$.value = symbol->info.finfo->value; 7128c2ecf20Sopenharmony_ci break; 7138c2ecf20Sopenharmony_ci case DOWNLOAD_CONST: 7148c2ecf20Sopenharmony_ci case CONST: 7158c2ecf20Sopenharmony_ci $$.value = symbol->info.cinfo->value; 7168c2ecf20Sopenharmony_ci break; 7178c2ecf20Sopenharmony_ci case UNINITIALIZED: 7188c2ecf20Sopenharmony_ci default: 7198c2ecf20Sopenharmony_ci { 7208c2ecf20Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), 7218c2ecf20Sopenharmony_ci "Undefined symbol %s referenced", 7228c2ecf20Sopenharmony_ci symbol->name); 7238c2ecf20Sopenharmony_ci stop(errbuf, EX_DATAERR); 7248c2ecf20Sopenharmony_ci /* NOTREACHED */ 7258c2ecf20Sopenharmony_ci break; 7268c2ecf20Sopenharmony_ci } 7278c2ecf20Sopenharmony_ci } 7288c2ecf20Sopenharmony_ci SLIST_INIT(&$$.referenced_syms); 7298c2ecf20Sopenharmony_ci symlist_add(&$$.referenced_syms, symbol, SYMLIST_INSERT_HEAD); 7308c2ecf20Sopenharmony_ci } 7318c2ecf20Sopenharmony_ci; 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ciconstant: 7348c2ecf20Sopenharmony_ci T_CONST T_SYMBOL expression 7358c2ecf20Sopenharmony_ci { 7368c2ecf20Sopenharmony_ci if ($2->type != UNINITIALIZED) { 7378c2ecf20Sopenharmony_ci stop("Re-definition of symbol as a constant", 7388c2ecf20Sopenharmony_ci EX_DATAERR); 7398c2ecf20Sopenharmony_ci /* NOTREACHED */ 7408c2ecf20Sopenharmony_ci } 7418c2ecf20Sopenharmony_ci $2->type = CONST; 7428c2ecf20Sopenharmony_ci initialize_symbol($2); 7438c2ecf20Sopenharmony_ci $2->info.cinfo->value = $3.value; 7448c2ecf20Sopenharmony_ci } 7458c2ecf20Sopenharmony_ci| T_CONST T_SYMBOL T_DOWNLOAD 7468c2ecf20Sopenharmony_ci { 7478c2ecf20Sopenharmony_ci if ($1) { 7488c2ecf20Sopenharmony_ci stop("Invalid downloaded constant declaration", 7498c2ecf20Sopenharmony_ci EX_DATAERR); 7508c2ecf20Sopenharmony_ci /* NOTREACHED */ 7518c2ecf20Sopenharmony_ci } 7528c2ecf20Sopenharmony_ci if ($2->type != UNINITIALIZED) { 7538c2ecf20Sopenharmony_ci stop("Re-definition of symbol as a downloaded constant", 7548c2ecf20Sopenharmony_ci EX_DATAERR); 7558c2ecf20Sopenharmony_ci /* NOTREACHED */ 7568c2ecf20Sopenharmony_ci } 7578c2ecf20Sopenharmony_ci $2->type = DOWNLOAD_CONST; 7588c2ecf20Sopenharmony_ci initialize_symbol($2); 7598c2ecf20Sopenharmony_ci $2->info.cinfo->value = download_constant_count++; 7608c2ecf20Sopenharmony_ci } 7618c2ecf20Sopenharmony_ci; 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_cimacrodefn_prologue: 7648c2ecf20Sopenharmony_ci T_DEFINE T_SYMBOL 7658c2ecf20Sopenharmony_ci { 7668c2ecf20Sopenharmony_ci if ($2->type != UNINITIALIZED) { 7678c2ecf20Sopenharmony_ci stop("Re-definition of symbol as a macro", 7688c2ecf20Sopenharmony_ci EX_DATAERR); 7698c2ecf20Sopenharmony_ci /* NOTREACHED */ 7708c2ecf20Sopenharmony_ci } 7718c2ecf20Sopenharmony_ci cur_symbol = $2; 7728c2ecf20Sopenharmony_ci cur_symbol->type = MACRO; 7738c2ecf20Sopenharmony_ci initialize_symbol(cur_symbol); 7748c2ecf20Sopenharmony_ci } 7758c2ecf20Sopenharmony_ci; 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_cimacrodefn: 7788c2ecf20Sopenharmony_ci macrodefn_prologue T_MACROBODY 7798c2ecf20Sopenharmony_ci { 7808c2ecf20Sopenharmony_ci add_macro_body($2); 7818c2ecf20Sopenharmony_ci } 7828c2ecf20Sopenharmony_ci| macrodefn_prologue '(' macro_arglist ')' T_MACROBODY 7838c2ecf20Sopenharmony_ci { 7848c2ecf20Sopenharmony_ci add_macro_body($5); 7858c2ecf20Sopenharmony_ci cur_symbol->info.macroinfo->narg = $3; 7868c2ecf20Sopenharmony_ci } 7878c2ecf20Sopenharmony_ci; 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_cimacro_arglist: 7908c2ecf20Sopenharmony_ci { 7918c2ecf20Sopenharmony_ci /* Macros can take no arguments */ 7928c2ecf20Sopenharmony_ci $$ = 0; 7938c2ecf20Sopenharmony_ci } 7948c2ecf20Sopenharmony_ci| T_ARG 7958c2ecf20Sopenharmony_ci { 7968c2ecf20Sopenharmony_ci $$ = 1; 7978c2ecf20Sopenharmony_ci add_macro_arg($1, 0); 7988c2ecf20Sopenharmony_ci } 7998c2ecf20Sopenharmony_ci| macro_arglist ',' T_ARG 8008c2ecf20Sopenharmony_ci { 8018c2ecf20Sopenharmony_ci if ($1 == 0) { 8028c2ecf20Sopenharmony_ci stop("Comma without preceding argument in arg list", 8038c2ecf20Sopenharmony_ci EX_DATAERR); 8048c2ecf20Sopenharmony_ci /* NOTREACHED */ 8058c2ecf20Sopenharmony_ci } 8068c2ecf20Sopenharmony_ci $$ = $1 + 1; 8078c2ecf20Sopenharmony_ci add_macro_arg($3, $1); 8088c2ecf20Sopenharmony_ci } 8098c2ecf20Sopenharmony_ci; 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ciscratch_ram: 8128c2ecf20Sopenharmony_ci T_SRAM '{' 8138c2ecf20Sopenharmony_ci { 8148c2ecf20Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), "%s%d", SRAM_SYMNAME, 8158c2ecf20Sopenharmony_ci num_srams); 8168c2ecf20Sopenharmony_ci cur_symbol = symtable_get(SRAM_SYMNAME); 8178c2ecf20Sopenharmony_ci cur_symtype = SRAMLOC; 8188c2ecf20Sopenharmony_ci cur_symbol->type = SRAMLOC; 8198c2ecf20Sopenharmony_ci initialize_symbol(cur_symbol); 8208c2ecf20Sopenharmony_ci cur_symbol->count += 1; 8218c2ecf20Sopenharmony_ci } 8228c2ecf20Sopenharmony_ci reg_address 8238c2ecf20Sopenharmony_ci { 8248c2ecf20Sopenharmony_ci sram_or_scb_offset = cur_symbol->info.rinfo->address; 8258c2ecf20Sopenharmony_ci } 8268c2ecf20Sopenharmony_ci size 8278c2ecf20Sopenharmony_ci { 8288c2ecf20Sopenharmony_ci scb_or_sram_symbol = cur_symbol; 8298c2ecf20Sopenharmony_ci } 8308c2ecf20Sopenharmony_ci scb_or_sram_attributes 8318c2ecf20Sopenharmony_ci '}' 8328c2ecf20Sopenharmony_ci { 8338c2ecf20Sopenharmony_ci cur_symbol = NULL; 8348c2ecf20Sopenharmony_ci scb_or_sram_symbol = NULL; 8358c2ecf20Sopenharmony_ci } 8368c2ecf20Sopenharmony_ci; 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ciscb: 8398c2ecf20Sopenharmony_ci T_SCB '{' 8408c2ecf20Sopenharmony_ci { 8418c2ecf20Sopenharmony_ci cur_symbol = symtable_get(SCB_SYMNAME); 8428c2ecf20Sopenharmony_ci cur_symtype = SCBLOC; 8438c2ecf20Sopenharmony_ci if (cur_symbol->type != UNINITIALIZED) { 8448c2ecf20Sopenharmony_ci stop("Only one SRAM definition allowed", 8458c2ecf20Sopenharmony_ci EX_SOFTWARE); 8468c2ecf20Sopenharmony_ci /* NOTREACHED */ 8478c2ecf20Sopenharmony_ci } 8488c2ecf20Sopenharmony_ci cur_symbol->type = SCBLOC; 8498c2ecf20Sopenharmony_ci initialize_symbol(cur_symbol); 8508c2ecf20Sopenharmony_ci /* 64 bytes of SCB space */ 8518c2ecf20Sopenharmony_ci cur_symbol->info.rinfo->size = 64; 8528c2ecf20Sopenharmony_ci cur_symbol->count += 1; 8538c2ecf20Sopenharmony_ci } 8548c2ecf20Sopenharmony_ci reg_address 8558c2ecf20Sopenharmony_ci { 8568c2ecf20Sopenharmony_ci sram_or_scb_offset = cur_symbol->info.rinfo->address; 8578c2ecf20Sopenharmony_ci } 8588c2ecf20Sopenharmony_ci size 8598c2ecf20Sopenharmony_ci { 8608c2ecf20Sopenharmony_ci scb_or_sram_symbol = cur_symbol; 8618c2ecf20Sopenharmony_ci } 8628c2ecf20Sopenharmony_ci scb_or_sram_attributes 8638c2ecf20Sopenharmony_ci '}' 8648c2ecf20Sopenharmony_ci { 8658c2ecf20Sopenharmony_ci cur_symbol = NULL; 8668c2ecf20Sopenharmony_ci scb_or_sram_symbol = NULL; 8678c2ecf20Sopenharmony_ci } 8688c2ecf20Sopenharmony_ci; 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ciscb_or_sram_attributes: 8718c2ecf20Sopenharmony_ci /* NULL definition is okay */ 8728c2ecf20Sopenharmony_ci| modes 8738c2ecf20Sopenharmony_ci| scb_or_sram_reg_list 8748c2ecf20Sopenharmony_ci| modes scb_or_sram_reg_list 8758c2ecf20Sopenharmony_ci; 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ciscb_or_sram_reg_list: 8788c2ecf20Sopenharmony_ci reg_definition 8798c2ecf20Sopenharmony_ci| scb_or_sram_reg_list reg_definition 8808c2ecf20Sopenharmony_ci; 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_cireg_symbol: 8838c2ecf20Sopenharmony_ci T_SYMBOL 8848c2ecf20Sopenharmony_ci { 8858c2ecf20Sopenharmony_ci process_register(&$1); 8868c2ecf20Sopenharmony_ci $$.symbol = $1; 8878c2ecf20Sopenharmony_ci $$.offset = 0; 8888c2ecf20Sopenharmony_ci } 8898c2ecf20Sopenharmony_ci| T_SYMBOL '[' T_SYMBOL ']' 8908c2ecf20Sopenharmony_ci { 8918c2ecf20Sopenharmony_ci process_register(&$1); 8928c2ecf20Sopenharmony_ci if ($3->type != CONST) { 8938c2ecf20Sopenharmony_ci stop("register offset must be a constant", EX_DATAERR); 8948c2ecf20Sopenharmony_ci /* NOTREACHED */ 8958c2ecf20Sopenharmony_ci } 8968c2ecf20Sopenharmony_ci if (($3->info.cinfo->value + 1) > $1->info.rinfo->size) { 8978c2ecf20Sopenharmony_ci stop("Accessing offset beyond range of register", 8988c2ecf20Sopenharmony_ci EX_DATAERR); 8998c2ecf20Sopenharmony_ci /* NOTREACHED */ 9008c2ecf20Sopenharmony_ci } 9018c2ecf20Sopenharmony_ci $$.symbol = $1; 9028c2ecf20Sopenharmony_ci $$.offset = $3->info.cinfo->value; 9038c2ecf20Sopenharmony_ci } 9048c2ecf20Sopenharmony_ci| T_SYMBOL '[' T_NUMBER ']' 9058c2ecf20Sopenharmony_ci { 9068c2ecf20Sopenharmony_ci process_register(&$1); 9078c2ecf20Sopenharmony_ci if (($3 + 1) > $1->info.rinfo->size) { 9088c2ecf20Sopenharmony_ci stop("Accessing offset beyond range of register", 9098c2ecf20Sopenharmony_ci EX_DATAERR); 9108c2ecf20Sopenharmony_ci /* NOTREACHED */ 9118c2ecf20Sopenharmony_ci } 9128c2ecf20Sopenharmony_ci $$.symbol = $1; 9138c2ecf20Sopenharmony_ci $$.offset = $3; 9148c2ecf20Sopenharmony_ci } 9158c2ecf20Sopenharmony_ci| T_A 9168c2ecf20Sopenharmony_ci { 9178c2ecf20Sopenharmony_ci if (accumulator.symbol == NULL) { 9188c2ecf20Sopenharmony_ci stop("No accumulator has been defined", EX_DATAERR); 9198c2ecf20Sopenharmony_ci /* NOTREACHED */ 9208c2ecf20Sopenharmony_ci } 9218c2ecf20Sopenharmony_ci $$.symbol = accumulator.symbol; 9228c2ecf20Sopenharmony_ci $$.offset = 0; 9238c2ecf20Sopenharmony_ci } 9248c2ecf20Sopenharmony_ci; 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_cidestination: 9278c2ecf20Sopenharmony_ci reg_symbol 9288c2ecf20Sopenharmony_ci { 9298c2ecf20Sopenharmony_ci test_writable_symbol($1.symbol); 9308c2ecf20Sopenharmony_ci $$ = $1; 9318c2ecf20Sopenharmony_ci } 9328c2ecf20Sopenharmony_ci; 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ciimmediate: 9358c2ecf20Sopenharmony_ci expression 9368c2ecf20Sopenharmony_ci { $$ = $1; } 9378c2ecf20Sopenharmony_ci; 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ciimmediate_or_a: 9408c2ecf20Sopenharmony_ci expression 9418c2ecf20Sopenharmony_ci { 9428c2ecf20Sopenharmony_ci if ($1.value == 0 && is_download_const(&$1) == 0) { 9438c2ecf20Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), 9448c2ecf20Sopenharmony_ci "\nExpression evaluates to 0 and thus " 9458c2ecf20Sopenharmony_ci "references the accumulator.\n " 9468c2ecf20Sopenharmony_ci "If this is the desired effect, use 'A' " 9478c2ecf20Sopenharmony_ci "instead.\n"); 9488c2ecf20Sopenharmony_ci stop(errbuf, EX_DATAERR); 9498c2ecf20Sopenharmony_ci } 9508c2ecf20Sopenharmony_ci $$ = $1; 9518c2ecf20Sopenharmony_ci } 9528c2ecf20Sopenharmony_ci| T_A 9538c2ecf20Sopenharmony_ci { 9548c2ecf20Sopenharmony_ci SLIST_INIT(&$$.referenced_syms); 9558c2ecf20Sopenharmony_ci symlist_add(&$$.referenced_syms, accumulator.symbol, 9568c2ecf20Sopenharmony_ci SYMLIST_INSERT_HEAD); 9578c2ecf20Sopenharmony_ci $$.value = 0; 9588c2ecf20Sopenharmony_ci } 9598c2ecf20Sopenharmony_ci; 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_cisource: 9628c2ecf20Sopenharmony_ci reg_symbol 9638c2ecf20Sopenharmony_ci { 9648c2ecf20Sopenharmony_ci test_readable_symbol($1.symbol); 9658c2ecf20Sopenharmony_ci $$ = $1; 9668c2ecf20Sopenharmony_ci } 9678c2ecf20Sopenharmony_ci; 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ciopt_source: 9708c2ecf20Sopenharmony_ci { 9718c2ecf20Sopenharmony_ci $$.symbol = NULL; 9728c2ecf20Sopenharmony_ci $$.offset = 0; 9738c2ecf20Sopenharmony_ci } 9748c2ecf20Sopenharmony_ci| ',' source 9758c2ecf20Sopenharmony_ci { $$ = $2; } 9768c2ecf20Sopenharmony_ci; 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ciret: 9798c2ecf20Sopenharmony_ci { $$ = 0; } 9808c2ecf20Sopenharmony_ci| T_RET 9818c2ecf20Sopenharmony_ci { $$ = 1; } 9828c2ecf20Sopenharmony_ci; 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ciset_src_mode: 9858c2ecf20Sopenharmony_ci T_SET_SRC_MODE T_NUMBER ';' 9868c2ecf20Sopenharmony_ci { 9878c2ecf20Sopenharmony_ci src_mode = $2; 9888c2ecf20Sopenharmony_ci } 9898c2ecf20Sopenharmony_ci; 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ciset_dst_mode: 9928c2ecf20Sopenharmony_ci T_SET_DST_MODE T_NUMBER ';' 9938c2ecf20Sopenharmony_ci { 9948c2ecf20Sopenharmony_ci dst_mode = $2; 9958c2ecf20Sopenharmony_ci } 9968c2ecf20Sopenharmony_ci; 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_cicritical_section_start: 9998c2ecf20Sopenharmony_ci T_BEGIN_CS ';' 10008c2ecf20Sopenharmony_ci { 10018c2ecf20Sopenharmony_ci critical_section_t *cs; 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci if (in_critical_section != FALSE) { 10048c2ecf20Sopenharmony_ci stop("Critical Section within Critical Section", 10058c2ecf20Sopenharmony_ci EX_DATAERR); 10068c2ecf20Sopenharmony_ci /* NOTREACHED */ 10078c2ecf20Sopenharmony_ci } 10088c2ecf20Sopenharmony_ci cs = cs_alloc(); 10098c2ecf20Sopenharmony_ci cs->begin_addr = instruction_ptr; 10108c2ecf20Sopenharmony_ci in_critical_section = TRUE; 10118c2ecf20Sopenharmony_ci } 10128c2ecf20Sopenharmony_ci; 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_cicritical_section_end: 10158c2ecf20Sopenharmony_ci T_END_CS ';' 10168c2ecf20Sopenharmony_ci { 10178c2ecf20Sopenharmony_ci critical_section_t *cs; 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci if (in_critical_section == FALSE) { 10208c2ecf20Sopenharmony_ci stop("Unballanced 'end_cs'", EX_DATAERR); 10218c2ecf20Sopenharmony_ci /* NOTREACHED */ 10228c2ecf20Sopenharmony_ci } 10238c2ecf20Sopenharmony_ci cs = TAILQ_LAST(&cs_tailq, cs_tailq); 10248c2ecf20Sopenharmony_ci cs->end_addr = instruction_ptr; 10258c2ecf20Sopenharmony_ci in_critical_section = FALSE; 10268c2ecf20Sopenharmony_ci } 10278c2ecf20Sopenharmony_ci; 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ciexport: 10308c2ecf20Sopenharmony_ci { $$ = 0; } 10318c2ecf20Sopenharmony_ci| T_EXPORT 10328c2ecf20Sopenharmony_ci { $$ = 1; } 10338c2ecf20Sopenharmony_ci; 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_cilabel: 10368c2ecf20Sopenharmony_ci export T_SYMBOL ':' 10378c2ecf20Sopenharmony_ci { 10388c2ecf20Sopenharmony_ci if ($2->type != UNINITIALIZED) { 10398c2ecf20Sopenharmony_ci stop("Program label multiply defined", EX_DATAERR); 10408c2ecf20Sopenharmony_ci /* NOTREACHED */ 10418c2ecf20Sopenharmony_ci } 10428c2ecf20Sopenharmony_ci $2->type = LABEL; 10438c2ecf20Sopenharmony_ci initialize_symbol($2); 10448c2ecf20Sopenharmony_ci $2->info.linfo->address = instruction_ptr; 10458c2ecf20Sopenharmony_ci $2->info.linfo->exported = $1; 10468c2ecf20Sopenharmony_ci } 10478c2ecf20Sopenharmony_ci; 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ciaddress: 10508c2ecf20Sopenharmony_ci T_SYMBOL 10518c2ecf20Sopenharmony_ci { 10528c2ecf20Sopenharmony_ci $$.symbol = $1; 10538c2ecf20Sopenharmony_ci $$.offset = 0; 10548c2ecf20Sopenharmony_ci } 10558c2ecf20Sopenharmony_ci| T_SYMBOL '+' T_NUMBER 10568c2ecf20Sopenharmony_ci { 10578c2ecf20Sopenharmony_ci $$.symbol = $1; 10588c2ecf20Sopenharmony_ci $$.offset = $3; 10598c2ecf20Sopenharmony_ci } 10608c2ecf20Sopenharmony_ci| T_SYMBOL '-' T_NUMBER 10618c2ecf20Sopenharmony_ci { 10628c2ecf20Sopenharmony_ci $$.symbol = $1; 10638c2ecf20Sopenharmony_ci $$.offset = -$3; 10648c2ecf20Sopenharmony_ci } 10658c2ecf20Sopenharmony_ci| '.' 10668c2ecf20Sopenharmony_ci { 10678c2ecf20Sopenharmony_ci $$.symbol = NULL; 10688c2ecf20Sopenharmony_ci $$.offset = 0; 10698c2ecf20Sopenharmony_ci } 10708c2ecf20Sopenharmony_ci| '.' '+' T_NUMBER 10718c2ecf20Sopenharmony_ci { 10728c2ecf20Sopenharmony_ci $$.symbol = NULL; 10738c2ecf20Sopenharmony_ci $$.offset = $3; 10748c2ecf20Sopenharmony_ci } 10758c2ecf20Sopenharmony_ci| '.' '-' T_NUMBER 10768c2ecf20Sopenharmony_ci { 10778c2ecf20Sopenharmony_ci $$.symbol = NULL; 10788c2ecf20Sopenharmony_ci $$.offset = -$3; 10798c2ecf20Sopenharmony_ci } 10808c2ecf20Sopenharmony_ci; 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ciconditional: 10838c2ecf20Sopenharmony_ci T_IF T_CEXPR '{' 10848c2ecf20Sopenharmony_ci { 10858c2ecf20Sopenharmony_ci scope_t *new_scope; 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci add_conditional($2); 10888c2ecf20Sopenharmony_ci new_scope = scope_alloc(); 10898c2ecf20Sopenharmony_ci new_scope->type = SCOPE_IF; 10908c2ecf20Sopenharmony_ci new_scope->begin_addr = instruction_ptr; 10918c2ecf20Sopenharmony_ci new_scope->func_num = $2->info.condinfo->func_num; 10928c2ecf20Sopenharmony_ci } 10938c2ecf20Sopenharmony_ci| T_ELSE T_IF T_CEXPR '{' 10948c2ecf20Sopenharmony_ci { 10958c2ecf20Sopenharmony_ci scope_t *new_scope; 10968c2ecf20Sopenharmony_ci scope_t *scope_context; 10978c2ecf20Sopenharmony_ci scope_t *last_scope; 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci /* 11008c2ecf20Sopenharmony_ci * Ensure that the previous scope is either an 11018c2ecf20Sopenharmony_ci * if or and else if. 11028c2ecf20Sopenharmony_ci */ 11038c2ecf20Sopenharmony_ci scope_context = SLIST_FIRST(&scope_stack); 11048c2ecf20Sopenharmony_ci last_scope = TAILQ_LAST(&scope_context->inner_scope, 11058c2ecf20Sopenharmony_ci scope_tailq); 11068c2ecf20Sopenharmony_ci if (last_scope == NULL 11078c2ecf20Sopenharmony_ci || last_scope->type == T_ELSE) { 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci stop("'else if' without leading 'if'", EX_DATAERR); 11108c2ecf20Sopenharmony_ci /* NOTREACHED */ 11118c2ecf20Sopenharmony_ci } 11128c2ecf20Sopenharmony_ci add_conditional($3); 11138c2ecf20Sopenharmony_ci new_scope = scope_alloc(); 11148c2ecf20Sopenharmony_ci new_scope->type = SCOPE_ELSE_IF; 11158c2ecf20Sopenharmony_ci new_scope->begin_addr = instruction_ptr; 11168c2ecf20Sopenharmony_ci new_scope->func_num = $3->info.condinfo->func_num; 11178c2ecf20Sopenharmony_ci } 11188c2ecf20Sopenharmony_ci| T_ELSE '{' 11198c2ecf20Sopenharmony_ci { 11208c2ecf20Sopenharmony_ci scope_t *new_scope; 11218c2ecf20Sopenharmony_ci scope_t *scope_context; 11228c2ecf20Sopenharmony_ci scope_t *last_scope; 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci /* 11258c2ecf20Sopenharmony_ci * Ensure that the previous scope is either an 11268c2ecf20Sopenharmony_ci * if or and else if. 11278c2ecf20Sopenharmony_ci */ 11288c2ecf20Sopenharmony_ci scope_context = SLIST_FIRST(&scope_stack); 11298c2ecf20Sopenharmony_ci last_scope = TAILQ_LAST(&scope_context->inner_scope, 11308c2ecf20Sopenharmony_ci scope_tailq); 11318c2ecf20Sopenharmony_ci if (last_scope == NULL 11328c2ecf20Sopenharmony_ci || last_scope->type == SCOPE_ELSE) { 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci stop("'else' without leading 'if'", EX_DATAERR); 11358c2ecf20Sopenharmony_ci /* NOTREACHED */ 11368c2ecf20Sopenharmony_ci } 11378c2ecf20Sopenharmony_ci new_scope = scope_alloc(); 11388c2ecf20Sopenharmony_ci new_scope->type = SCOPE_ELSE; 11398c2ecf20Sopenharmony_ci new_scope->begin_addr = instruction_ptr; 11408c2ecf20Sopenharmony_ci } 11418c2ecf20Sopenharmony_ci; 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ciconditional: 11448c2ecf20Sopenharmony_ci '}' 11458c2ecf20Sopenharmony_ci { 11468c2ecf20Sopenharmony_ci scope_t *scope_context; 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci scope_context = SLIST_FIRST(&scope_stack); 11498c2ecf20Sopenharmony_ci if (scope_context->type == SCOPE_ROOT) { 11508c2ecf20Sopenharmony_ci stop("Unexpected '}' encountered", EX_DATAERR); 11518c2ecf20Sopenharmony_ci /* NOTREACHED */ 11528c2ecf20Sopenharmony_ci } 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci scope_context->end_addr = instruction_ptr; 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci /* Pop the scope */ 11578c2ecf20Sopenharmony_ci SLIST_REMOVE_HEAD(&scope_stack, scope_stack_links); 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci process_scope(scope_context); 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci if (SLIST_FIRST(&scope_stack) == NULL) { 11628c2ecf20Sopenharmony_ci stop("Unexpected '}' encountered", EX_DATAERR); 11638c2ecf20Sopenharmony_ci /* NOTREACHED */ 11648c2ecf20Sopenharmony_ci } 11658c2ecf20Sopenharmony_ci } 11668c2ecf20Sopenharmony_ci; 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_cif1_opcode: 11698c2ecf20Sopenharmony_ci T_AND { $$ = AIC_OP_AND; } 11708c2ecf20Sopenharmony_ci| T_XOR { $$ = AIC_OP_XOR; } 11718c2ecf20Sopenharmony_ci| T_ADD { $$ = AIC_OP_ADD; } 11728c2ecf20Sopenharmony_ci| T_ADC { $$ = AIC_OP_ADC; } 11738c2ecf20Sopenharmony_ci; 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_cicode: 11768c2ecf20Sopenharmony_ci f1_opcode destination ',' immediate_or_a opt_source ret ';' 11778c2ecf20Sopenharmony_ci { 11788c2ecf20Sopenharmony_ci format_1_instr($1, &$2, &$4, &$5, $6); 11798c2ecf20Sopenharmony_ci } 11808c2ecf20Sopenharmony_ci; 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_cicode: 11838c2ecf20Sopenharmony_ci T_OR reg_symbol ',' immediate_or_a opt_source ret ';' 11848c2ecf20Sopenharmony_ci { 11858c2ecf20Sopenharmony_ci format_1_instr(AIC_OP_OR, &$2, &$4, &$5, $6); 11868c2ecf20Sopenharmony_ci } 11878c2ecf20Sopenharmony_ci; 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_cicode: 11908c2ecf20Sopenharmony_ci T_INC destination opt_source ret ';' 11918c2ecf20Sopenharmony_ci { 11928c2ecf20Sopenharmony_ci expression_t immed; 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci make_expression(&immed, 1); 11958c2ecf20Sopenharmony_ci format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); 11968c2ecf20Sopenharmony_ci } 11978c2ecf20Sopenharmony_ci; 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_cicode: 12008c2ecf20Sopenharmony_ci T_DEC destination opt_source ret ';' 12018c2ecf20Sopenharmony_ci { 12028c2ecf20Sopenharmony_ci expression_t immed; 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci make_expression(&immed, -1); 12058c2ecf20Sopenharmony_ci format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); 12068c2ecf20Sopenharmony_ci } 12078c2ecf20Sopenharmony_ci; 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_cicode: 12108c2ecf20Sopenharmony_ci T_CLC ret ';' 12118c2ecf20Sopenharmony_ci { 12128c2ecf20Sopenharmony_ci expression_t immed; 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci make_expression(&immed, -1); 12158c2ecf20Sopenharmony_ci format_1_instr(AIC_OP_ADD, &none, &immed, &allzeros, $2); 12168c2ecf20Sopenharmony_ci } 12178c2ecf20Sopenharmony_ci| T_CLC T_MVI destination ',' immediate_or_a ret ';' 12188c2ecf20Sopenharmony_ci { 12198c2ecf20Sopenharmony_ci format_1_instr(AIC_OP_ADD, &$3, &$5, &allzeros, $6); 12208c2ecf20Sopenharmony_ci } 12218c2ecf20Sopenharmony_ci; 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_cicode: 12248c2ecf20Sopenharmony_ci T_STC ret ';' 12258c2ecf20Sopenharmony_ci { 12268c2ecf20Sopenharmony_ci expression_t immed; 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci make_expression(&immed, 1); 12298c2ecf20Sopenharmony_ci format_1_instr(AIC_OP_ADD, &none, &immed, &allones, $2); 12308c2ecf20Sopenharmony_ci } 12318c2ecf20Sopenharmony_ci| T_STC destination ret ';' 12328c2ecf20Sopenharmony_ci { 12338c2ecf20Sopenharmony_ci expression_t immed; 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_ci make_expression(&immed, 1); 12368c2ecf20Sopenharmony_ci format_1_instr(AIC_OP_ADD, &$2, &immed, &allones, $3); 12378c2ecf20Sopenharmony_ci } 12388c2ecf20Sopenharmony_ci; 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_cicode: 12418c2ecf20Sopenharmony_ci T_BMOV destination ',' source ',' immediate ret ';' 12428c2ecf20Sopenharmony_ci { 12438c2ecf20Sopenharmony_ci format_1_instr(AIC_OP_BMOV, &$2, &$6, &$4, $7); 12448c2ecf20Sopenharmony_ci } 12458c2ecf20Sopenharmony_ci; 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_cicode: 12488c2ecf20Sopenharmony_ci T_MOV destination ',' source ret ';' 12498c2ecf20Sopenharmony_ci { 12508c2ecf20Sopenharmony_ci expression_t immed; 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci make_expression(&immed, 1); 12538c2ecf20Sopenharmony_ci format_1_instr(AIC_OP_BMOV, &$2, &immed, &$4, $5); 12548c2ecf20Sopenharmony_ci } 12558c2ecf20Sopenharmony_ci; 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_cicode: 12588c2ecf20Sopenharmony_ci T_MVI destination ',' immediate ret ';' 12598c2ecf20Sopenharmony_ci { 12608c2ecf20Sopenharmony_ci if ($4.value == 0 12618c2ecf20Sopenharmony_ci && is_download_const(&$4) == 0) { 12628c2ecf20Sopenharmony_ci expression_t immed; 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci /* 12658c2ecf20Sopenharmony_ci * Allow move immediates of 0 so that macros, 12668c2ecf20Sopenharmony_ci * that can't know the immediate's value and 12678c2ecf20Sopenharmony_ci * otherwise compensate, still work. 12688c2ecf20Sopenharmony_ci */ 12698c2ecf20Sopenharmony_ci make_expression(&immed, 1); 12708c2ecf20Sopenharmony_ci format_1_instr(AIC_OP_BMOV, &$2, &immed, &allzeros, $5); 12718c2ecf20Sopenharmony_ci } else { 12728c2ecf20Sopenharmony_ci format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5); 12738c2ecf20Sopenharmony_ci } 12748c2ecf20Sopenharmony_ci } 12758c2ecf20Sopenharmony_ci; 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_cicode: 12788c2ecf20Sopenharmony_ci T_NOT destination opt_source ret ';' 12798c2ecf20Sopenharmony_ci { 12808c2ecf20Sopenharmony_ci expression_t immed; 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_ci make_expression(&immed, 0xff); 12838c2ecf20Sopenharmony_ci format_1_instr(AIC_OP_XOR, &$2, &immed, &$3, $4); 12848c2ecf20Sopenharmony_ci } 12858c2ecf20Sopenharmony_ci; 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_cicode: 12888c2ecf20Sopenharmony_ci T_CLR destination ret ';' 12898c2ecf20Sopenharmony_ci { 12908c2ecf20Sopenharmony_ci expression_t immed; 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci make_expression(&immed, 0xff); 12938c2ecf20Sopenharmony_ci format_1_instr(AIC_OP_AND, &$2, &immed, &allzeros, $3); 12948c2ecf20Sopenharmony_ci } 12958c2ecf20Sopenharmony_ci; 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_cicode: 12988c2ecf20Sopenharmony_ci T_NOP ret ';' 12998c2ecf20Sopenharmony_ci { 13008c2ecf20Sopenharmony_ci expression_t immed; 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci make_expression(&immed, 0xff); 13038c2ecf20Sopenharmony_ci format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, $2); 13048c2ecf20Sopenharmony_ci } 13058c2ecf20Sopenharmony_ci; 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_cicode: 13088c2ecf20Sopenharmony_ci T_RET ';' 13098c2ecf20Sopenharmony_ci { 13108c2ecf20Sopenharmony_ci expression_t immed; 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci make_expression(&immed, 0xff); 13138c2ecf20Sopenharmony_ci format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, TRUE); 13148c2ecf20Sopenharmony_ci } 13158c2ecf20Sopenharmony_ci; 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci /* 13188c2ecf20Sopenharmony_ci * This grammar differs from the one in the aic7xxx 13198c2ecf20Sopenharmony_ci * reference manual since the grammar listed there is 13208c2ecf20Sopenharmony_ci * ambiguous and causes a shift/reduce conflict. 13218c2ecf20Sopenharmony_ci * It also seems more logical as the "immediate" 13228c2ecf20Sopenharmony_ci * argument is listed as the second arg like the 13238c2ecf20Sopenharmony_ci * other formats. 13248c2ecf20Sopenharmony_ci */ 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_cif2_opcode: 13278c2ecf20Sopenharmony_ci T_SHL { $$ = AIC_OP_SHL; } 13288c2ecf20Sopenharmony_ci| T_SHR { $$ = AIC_OP_SHR; } 13298c2ecf20Sopenharmony_ci| T_ROL { $$ = AIC_OP_ROL; } 13308c2ecf20Sopenharmony_ci| T_ROR { $$ = AIC_OP_ROR; } 13318c2ecf20Sopenharmony_ci; 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci/* 13348c2ecf20Sopenharmony_ci * 16bit opcodes, not used 13358c2ecf20Sopenharmony_ci * 13368c2ecf20Sopenharmony_ci *f4_opcode: 13378c2ecf20Sopenharmony_ci * T_OR16 { $$ = AIC_OP_OR16; } 13388c2ecf20Sopenharmony_ci *| T_AND16 { $$ = AIC_OP_AND16; } 13398c2ecf20Sopenharmony_ci *| T_XOR16 { $$ = AIC_OP_XOR16; } 13408c2ecf20Sopenharmony_ci *| T_ADD16 { $$ = AIC_OP_ADD16; } 13418c2ecf20Sopenharmony_ci *| T_ADC16 { $$ = AIC_OP_ADC16; } 13428c2ecf20Sopenharmony_ci *| T_MVI16 { $$ = AIC_OP_MVI16; } 13438c2ecf20Sopenharmony_ci *; 13448c2ecf20Sopenharmony_ci */ 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_cicode: 13478c2ecf20Sopenharmony_ci f2_opcode destination ',' expression opt_source ret ';' 13488c2ecf20Sopenharmony_ci { 13498c2ecf20Sopenharmony_ci format_2_instr($1, &$2, &$4, &$5, $6); 13508c2ecf20Sopenharmony_ci } 13518c2ecf20Sopenharmony_ci; 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_cijmp_jc_jnc_call: 13548c2ecf20Sopenharmony_ci T_JMP { $$ = AIC_OP_JMP; } 13558c2ecf20Sopenharmony_ci| T_JC { $$ = AIC_OP_JC; } 13568c2ecf20Sopenharmony_ci| T_JNC { $$ = AIC_OP_JNC; } 13578c2ecf20Sopenharmony_ci| T_CALL { $$ = AIC_OP_CALL; } 13588c2ecf20Sopenharmony_ci; 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_cijz_jnz: 13618c2ecf20Sopenharmony_ci T_JZ { $$ = AIC_OP_JZ; } 13628c2ecf20Sopenharmony_ci| T_JNZ { $$ = AIC_OP_JNZ; } 13638c2ecf20Sopenharmony_ci; 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_cije_jne: 13668c2ecf20Sopenharmony_ci T_JE { $$ = AIC_OP_JE; } 13678c2ecf20Sopenharmony_ci| T_JNE { $$ = AIC_OP_JNE; } 13688c2ecf20Sopenharmony_ci; 13698c2ecf20Sopenharmony_ci 13708c2ecf20Sopenharmony_cicode: 13718c2ecf20Sopenharmony_ci jmp_jc_jnc_call address ';' 13728c2ecf20Sopenharmony_ci { 13738c2ecf20Sopenharmony_ci expression_t immed; 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci make_expression(&immed, 0); 13768c2ecf20Sopenharmony_ci format_3_instr($1, &sindex, &immed, &$2); 13778c2ecf20Sopenharmony_ci } 13788c2ecf20Sopenharmony_ci; 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_cicode: 13818c2ecf20Sopenharmony_ci T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';' 13828c2ecf20Sopenharmony_ci { 13838c2ecf20Sopenharmony_ci type_check(&$2, &$4, AIC_OP_OR); 13848c2ecf20Sopenharmony_ci format_3_instr($5, &$2, &$4, &$6); 13858c2ecf20Sopenharmony_ci } 13868c2ecf20Sopenharmony_ci; 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_cicode: 13898c2ecf20Sopenharmony_ci T_TEST source ',' immediate_or_a jz_jnz address ';' 13908c2ecf20Sopenharmony_ci { 13918c2ecf20Sopenharmony_ci format_3_instr($5, &$2, &$4, &$6); 13928c2ecf20Sopenharmony_ci } 13938c2ecf20Sopenharmony_ci; 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_cicode: 13968c2ecf20Sopenharmony_ci T_CMP source ',' immediate_or_a je_jne address ';' 13978c2ecf20Sopenharmony_ci { 13988c2ecf20Sopenharmony_ci format_3_instr($5, &$2, &$4, &$6); 13998c2ecf20Sopenharmony_ci } 14008c2ecf20Sopenharmony_ci; 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_cicode: 14038c2ecf20Sopenharmony_ci T_MOV source jmp_jc_jnc_call address ';' 14048c2ecf20Sopenharmony_ci { 14058c2ecf20Sopenharmony_ci expression_t immed; 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci make_expression(&immed, 0); 14088c2ecf20Sopenharmony_ci format_3_instr($3, &$2, &immed, &$4); 14098c2ecf20Sopenharmony_ci } 14108c2ecf20Sopenharmony_ci; 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_cicode: 14138c2ecf20Sopenharmony_ci T_MVI immediate jmp_jc_jnc_call address ';' 14148c2ecf20Sopenharmony_ci { 14158c2ecf20Sopenharmony_ci format_3_instr($3, &allzeros, &$2, &$4); 14168c2ecf20Sopenharmony_ci } 14178c2ecf20Sopenharmony_ci; 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci%% 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_cistatic void 14228c2ecf20Sopenharmony_ciprocess_field(int field_type, symbol_t *sym, int value) 14238c2ecf20Sopenharmony_ci{ 14248c2ecf20Sopenharmony_ci /* 14258c2ecf20Sopenharmony_ci * Add the current register to its 14268c2ecf20Sopenharmony_ci * symbol list, if it already exists, 14278c2ecf20Sopenharmony_ci * warn if we are setting it to a 14288c2ecf20Sopenharmony_ci * different value, or in the bit to 14298c2ecf20Sopenharmony_ci * the "allowed bits" of this register. 14308c2ecf20Sopenharmony_ci */ 14318c2ecf20Sopenharmony_ci if (sym->type == UNINITIALIZED) { 14328c2ecf20Sopenharmony_ci sym->type = field_type; 14338c2ecf20Sopenharmony_ci initialize_symbol(sym); 14348c2ecf20Sopenharmony_ci sym->info.finfo->value = value; 14358c2ecf20Sopenharmony_ci if (field_type != ENUM_ENTRY) { 14368c2ecf20Sopenharmony_ci if (field_type != MASK && value == 0) { 14378c2ecf20Sopenharmony_ci stop("Empty Field, or Enum", EX_DATAERR); 14388c2ecf20Sopenharmony_ci /* NOTREACHED */ 14398c2ecf20Sopenharmony_ci } 14408c2ecf20Sopenharmony_ci sym->info.finfo->value = value; 14418c2ecf20Sopenharmony_ci sym->info.finfo->mask = value; 14428c2ecf20Sopenharmony_ci } else if (field_symbol != NULL) { 14438c2ecf20Sopenharmony_ci sym->info.finfo->mask = field_symbol->info.finfo->value; 14448c2ecf20Sopenharmony_ci } else { 14458c2ecf20Sopenharmony_ci sym->info.finfo->mask = 0xFF; 14468c2ecf20Sopenharmony_ci } 14478c2ecf20Sopenharmony_ci } else if (sym->type != field_type) { 14488c2ecf20Sopenharmony_ci stop("Field definition mirrors a definition of the same " 14498c2ecf20Sopenharmony_ci " name, but a different type", EX_DATAERR); 14508c2ecf20Sopenharmony_ci /* NOTREACHED */ 14518c2ecf20Sopenharmony_ci } else if (value != sym->info.finfo->value) { 14528c2ecf20Sopenharmony_ci stop("Field redefined with a conflicting value", EX_DATAERR); 14538c2ecf20Sopenharmony_ci /* NOTREACHED */ 14548c2ecf20Sopenharmony_ci } 14558c2ecf20Sopenharmony_ci /* Fail if this symbol is already listed */ 14568c2ecf20Sopenharmony_ci if (symlist_search(&(sym->info.finfo->symrefs), 14578c2ecf20Sopenharmony_ci cur_symbol->name) != NULL) { 14588c2ecf20Sopenharmony_ci stop("Field defined multiple times for register", EX_DATAERR); 14598c2ecf20Sopenharmony_ci /* NOTREACHED */ 14608c2ecf20Sopenharmony_ci } 14618c2ecf20Sopenharmony_ci symlist_add(&(sym->info.finfo->symrefs), cur_symbol, 14628c2ecf20Sopenharmony_ci SYMLIST_INSERT_HEAD); 14638c2ecf20Sopenharmony_ci cur_symbol->info.rinfo->valid_bitmask |= sym->info.finfo->mask; 14648c2ecf20Sopenharmony_ci cur_symbol->info.rinfo->typecheck_masks = TRUE; 14658c2ecf20Sopenharmony_ci symlist_add(&(cur_symbol->info.rinfo->fields), sym, SYMLIST_SORT); 14668c2ecf20Sopenharmony_ci} 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_cistatic void 14698c2ecf20Sopenharmony_ciinitialize_symbol(symbol_t *symbol) 14708c2ecf20Sopenharmony_ci{ 14718c2ecf20Sopenharmony_ci switch (symbol->type) { 14728c2ecf20Sopenharmony_ci case UNINITIALIZED: 14738c2ecf20Sopenharmony_ci stop("Call to initialize_symbol with type field unset", 14748c2ecf20Sopenharmony_ci EX_SOFTWARE); 14758c2ecf20Sopenharmony_ci /* NOTREACHED */ 14768c2ecf20Sopenharmony_ci break; 14778c2ecf20Sopenharmony_ci case REGISTER: 14788c2ecf20Sopenharmony_ci case SRAMLOC: 14798c2ecf20Sopenharmony_ci case SCBLOC: 14808c2ecf20Sopenharmony_ci symbol->info.rinfo = 14818c2ecf20Sopenharmony_ci (struct reg_info *)malloc(sizeof(struct reg_info)); 14828c2ecf20Sopenharmony_ci if (symbol->info.rinfo == NULL) { 14838c2ecf20Sopenharmony_ci stop("Can't create register info", EX_SOFTWARE); 14848c2ecf20Sopenharmony_ci /* NOTREACHED */ 14858c2ecf20Sopenharmony_ci } 14868c2ecf20Sopenharmony_ci memset(symbol->info.rinfo, 0, 14878c2ecf20Sopenharmony_ci sizeof(struct reg_info)); 14888c2ecf20Sopenharmony_ci SLIST_INIT(&(symbol->info.rinfo->fields)); 14898c2ecf20Sopenharmony_ci /* 14908c2ecf20Sopenharmony_ci * Default to allowing access in all register modes 14918c2ecf20Sopenharmony_ci * or to the mode specified by the SCB or SRAM space 14928c2ecf20Sopenharmony_ci * we are in. 14938c2ecf20Sopenharmony_ci */ 14948c2ecf20Sopenharmony_ci if (scb_or_sram_symbol != NULL) 14958c2ecf20Sopenharmony_ci symbol->info.rinfo->modes = 14968c2ecf20Sopenharmony_ci scb_or_sram_symbol->info.rinfo->modes; 14978c2ecf20Sopenharmony_ci else 14988c2ecf20Sopenharmony_ci symbol->info.rinfo->modes = ~0; 14998c2ecf20Sopenharmony_ci break; 15008c2ecf20Sopenharmony_ci case ALIAS: 15018c2ecf20Sopenharmony_ci symbol->info.ainfo = 15028c2ecf20Sopenharmony_ci (struct alias_info *)malloc(sizeof(struct alias_info)); 15038c2ecf20Sopenharmony_ci if (symbol->info.ainfo == NULL) { 15048c2ecf20Sopenharmony_ci stop("Can't create alias info", EX_SOFTWARE); 15058c2ecf20Sopenharmony_ci /* NOTREACHED */ 15068c2ecf20Sopenharmony_ci } 15078c2ecf20Sopenharmony_ci memset(symbol->info.ainfo, 0, 15088c2ecf20Sopenharmony_ci sizeof(struct alias_info)); 15098c2ecf20Sopenharmony_ci break; 15108c2ecf20Sopenharmony_ci case MASK: 15118c2ecf20Sopenharmony_ci case FIELD: 15128c2ecf20Sopenharmony_ci case ENUM: 15138c2ecf20Sopenharmony_ci case ENUM_ENTRY: 15148c2ecf20Sopenharmony_ci symbol->info.finfo = 15158c2ecf20Sopenharmony_ci (struct field_info *)malloc(sizeof(struct field_info)); 15168c2ecf20Sopenharmony_ci if (symbol->info.finfo == NULL) { 15178c2ecf20Sopenharmony_ci stop("Can't create field info", EX_SOFTWARE); 15188c2ecf20Sopenharmony_ci /* NOTREACHED */ 15198c2ecf20Sopenharmony_ci } 15208c2ecf20Sopenharmony_ci memset(symbol->info.finfo, 0, sizeof(struct field_info)); 15218c2ecf20Sopenharmony_ci SLIST_INIT(&(symbol->info.finfo->symrefs)); 15228c2ecf20Sopenharmony_ci break; 15238c2ecf20Sopenharmony_ci case CONST: 15248c2ecf20Sopenharmony_ci case DOWNLOAD_CONST: 15258c2ecf20Sopenharmony_ci symbol->info.cinfo = 15268c2ecf20Sopenharmony_ci (struct const_info *)malloc(sizeof(struct const_info)); 15278c2ecf20Sopenharmony_ci if (symbol->info.cinfo == NULL) { 15288c2ecf20Sopenharmony_ci stop("Can't create alias info", EX_SOFTWARE); 15298c2ecf20Sopenharmony_ci /* NOTREACHED */ 15308c2ecf20Sopenharmony_ci } 15318c2ecf20Sopenharmony_ci memset(symbol->info.cinfo, 0, 15328c2ecf20Sopenharmony_ci sizeof(struct const_info)); 15338c2ecf20Sopenharmony_ci break; 15348c2ecf20Sopenharmony_ci case LABEL: 15358c2ecf20Sopenharmony_ci symbol->info.linfo = 15368c2ecf20Sopenharmony_ci (struct label_info *)malloc(sizeof(struct label_info)); 15378c2ecf20Sopenharmony_ci if (symbol->info.linfo == NULL) { 15388c2ecf20Sopenharmony_ci stop("Can't create label info", EX_SOFTWARE); 15398c2ecf20Sopenharmony_ci /* NOTREACHED */ 15408c2ecf20Sopenharmony_ci } 15418c2ecf20Sopenharmony_ci memset(symbol->info.linfo, 0, 15428c2ecf20Sopenharmony_ci sizeof(struct label_info)); 15438c2ecf20Sopenharmony_ci break; 15448c2ecf20Sopenharmony_ci case CONDITIONAL: 15458c2ecf20Sopenharmony_ci symbol->info.condinfo = 15468c2ecf20Sopenharmony_ci (struct cond_info *)malloc(sizeof(struct cond_info)); 15478c2ecf20Sopenharmony_ci if (symbol->info.condinfo == NULL) { 15488c2ecf20Sopenharmony_ci stop("Can't create conditional info", EX_SOFTWARE); 15498c2ecf20Sopenharmony_ci /* NOTREACHED */ 15508c2ecf20Sopenharmony_ci } 15518c2ecf20Sopenharmony_ci memset(symbol->info.condinfo, 0, 15528c2ecf20Sopenharmony_ci sizeof(struct cond_info)); 15538c2ecf20Sopenharmony_ci break; 15548c2ecf20Sopenharmony_ci case MACRO: 15558c2ecf20Sopenharmony_ci symbol->info.macroinfo = 15568c2ecf20Sopenharmony_ci (struct macro_info *)malloc(sizeof(struct macro_info)); 15578c2ecf20Sopenharmony_ci if (symbol->info.macroinfo == NULL) { 15588c2ecf20Sopenharmony_ci stop("Can't create macro info", EX_SOFTWARE); 15598c2ecf20Sopenharmony_ci /* NOTREACHED */ 15608c2ecf20Sopenharmony_ci } 15618c2ecf20Sopenharmony_ci memset(symbol->info.macroinfo, 0, 15628c2ecf20Sopenharmony_ci sizeof(struct macro_info)); 15638c2ecf20Sopenharmony_ci STAILQ_INIT(&symbol->info.macroinfo->args); 15648c2ecf20Sopenharmony_ci break; 15658c2ecf20Sopenharmony_ci default: 15668c2ecf20Sopenharmony_ci stop("Call to initialize_symbol with invalid symbol type", 15678c2ecf20Sopenharmony_ci EX_SOFTWARE); 15688c2ecf20Sopenharmony_ci /* NOTREACHED */ 15698c2ecf20Sopenharmony_ci break; 15708c2ecf20Sopenharmony_ci } 15718c2ecf20Sopenharmony_ci} 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_cistatic void 15748c2ecf20Sopenharmony_ciadd_macro_arg(const char *argtext, int argnum) 15758c2ecf20Sopenharmony_ci{ 15768c2ecf20Sopenharmony_ci struct macro_arg *marg; 15778c2ecf20Sopenharmony_ci int i; 15788c2ecf20Sopenharmony_ci int retval; 15798c2ecf20Sopenharmony_ci 15808c2ecf20Sopenharmony_ci if (cur_symbol == NULL || cur_symbol->type != MACRO) { 15818c2ecf20Sopenharmony_ci stop("Invalid current symbol for adding macro arg", 15828c2ecf20Sopenharmony_ci EX_SOFTWARE); 15838c2ecf20Sopenharmony_ci /* NOTREACHED */ 15848c2ecf20Sopenharmony_ci } 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci marg = (struct macro_arg *)malloc(sizeof(*marg)); 15878c2ecf20Sopenharmony_ci if (marg == NULL) { 15888c2ecf20Sopenharmony_ci stop("Can't create macro_arg structure", EX_SOFTWARE); 15898c2ecf20Sopenharmony_ci /* NOTREACHED */ 15908c2ecf20Sopenharmony_ci } 15918c2ecf20Sopenharmony_ci marg->replacement_text = NULL; 15928c2ecf20Sopenharmony_ci retval = snprintf(regex_pattern, sizeof(regex_pattern), 15938c2ecf20Sopenharmony_ci "[^-/A-Za-z0-9_](%s)([^-/A-Za-z0-9_]|$)", 15948c2ecf20Sopenharmony_ci argtext); 15958c2ecf20Sopenharmony_ci if (retval >= sizeof(regex_pattern)) { 15968c2ecf20Sopenharmony_ci stop("Regex text buffer too small for arg", 15978c2ecf20Sopenharmony_ci EX_SOFTWARE); 15988c2ecf20Sopenharmony_ci /* NOTREACHED */ 15998c2ecf20Sopenharmony_ci } 16008c2ecf20Sopenharmony_ci retval = regcomp(&marg->arg_regex, regex_pattern, REG_EXTENDED); 16018c2ecf20Sopenharmony_ci if (retval != 0) { 16028c2ecf20Sopenharmony_ci stop("Regex compilation failed", EX_SOFTWARE); 16038c2ecf20Sopenharmony_ci /* NOTREACHED */ 16048c2ecf20Sopenharmony_ci } 16058c2ecf20Sopenharmony_ci STAILQ_INSERT_TAIL(&cur_symbol->info.macroinfo->args, marg, links); 16068c2ecf20Sopenharmony_ci} 16078c2ecf20Sopenharmony_ci 16088c2ecf20Sopenharmony_cistatic void 16098c2ecf20Sopenharmony_ciadd_macro_body(const char *bodytext) 16108c2ecf20Sopenharmony_ci{ 16118c2ecf20Sopenharmony_ci if (cur_symbol == NULL || cur_symbol->type != MACRO) { 16128c2ecf20Sopenharmony_ci stop("Invalid current symbol for adding macro arg", 16138c2ecf20Sopenharmony_ci EX_SOFTWARE); 16148c2ecf20Sopenharmony_ci /* NOTREACHED */ 16158c2ecf20Sopenharmony_ci } 16168c2ecf20Sopenharmony_ci cur_symbol->info.macroinfo->body = strdup(bodytext); 16178c2ecf20Sopenharmony_ci if (cur_symbol->info.macroinfo->body == NULL) { 16188c2ecf20Sopenharmony_ci stop("Can't duplicate macro body text", EX_SOFTWARE); 16198c2ecf20Sopenharmony_ci /* NOTREACHED */ 16208c2ecf20Sopenharmony_ci } 16218c2ecf20Sopenharmony_ci} 16228c2ecf20Sopenharmony_ci 16238c2ecf20Sopenharmony_cistatic void 16248c2ecf20Sopenharmony_ciprocess_register(symbol_t **p_symbol) 16258c2ecf20Sopenharmony_ci{ 16268c2ecf20Sopenharmony_ci symbol_t *symbol = *p_symbol; 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_ci if (symbol->type == UNINITIALIZED) { 16298c2ecf20Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), "Undefined register %s", 16308c2ecf20Sopenharmony_ci symbol->name); 16318c2ecf20Sopenharmony_ci stop(errbuf, EX_DATAERR); 16328c2ecf20Sopenharmony_ci /* NOTREACHED */ 16338c2ecf20Sopenharmony_ci } else if (symbol->type == ALIAS) { 16348c2ecf20Sopenharmony_ci *p_symbol = symbol->info.ainfo->parent; 16358c2ecf20Sopenharmony_ci } else if ((symbol->type != REGISTER) 16368c2ecf20Sopenharmony_ci && (symbol->type != SCBLOC) 16378c2ecf20Sopenharmony_ci && (symbol->type != SRAMLOC)) { 16388c2ecf20Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), 16398c2ecf20Sopenharmony_ci "Specified symbol %s is not a register", 16408c2ecf20Sopenharmony_ci symbol->name); 16418c2ecf20Sopenharmony_ci stop(errbuf, EX_DATAERR); 16428c2ecf20Sopenharmony_ci } 16438c2ecf20Sopenharmony_ci} 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_cistatic void 16468c2ecf20Sopenharmony_ciformat_1_instr(int opcode, symbol_ref_t *dest, expression_t *immed, 16478c2ecf20Sopenharmony_ci symbol_ref_t *src, int ret) 16488c2ecf20Sopenharmony_ci{ 16498c2ecf20Sopenharmony_ci struct instruction *instr; 16508c2ecf20Sopenharmony_ci struct ins_format1 *f1_instr; 16518c2ecf20Sopenharmony_ci 16528c2ecf20Sopenharmony_ci if (src->symbol == NULL) 16538c2ecf20Sopenharmony_ci src = dest; 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_ci /* Test register permissions */ 16568c2ecf20Sopenharmony_ci test_writable_symbol(dest->symbol); 16578c2ecf20Sopenharmony_ci test_readable_symbol(src->symbol); 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ci if (!is_location_address(dest->symbol)) { 16608c2ecf20Sopenharmony_ci /* Ensure that immediate makes sense for this destination */ 16618c2ecf20Sopenharmony_ci type_check(dest, immed, opcode); 16628c2ecf20Sopenharmony_ci } 16638c2ecf20Sopenharmony_ci 16648c2ecf20Sopenharmony_ci /* Allocate sequencer space for the instruction and fill it out */ 16658c2ecf20Sopenharmony_ci instr = seq_alloc(); 16668c2ecf20Sopenharmony_ci f1_instr = &instr->format.format1; 16678c2ecf20Sopenharmony_ci f1_instr->ret = ret ? 1 : 0; 16688c2ecf20Sopenharmony_ci f1_instr->opcode = opcode; 16698c2ecf20Sopenharmony_ci f1_instr->destination = dest->symbol->info.rinfo->address 16708c2ecf20Sopenharmony_ci + dest->offset; 16718c2ecf20Sopenharmony_ci f1_instr->source = src->symbol->info.rinfo->address 16728c2ecf20Sopenharmony_ci + src->offset; 16738c2ecf20Sopenharmony_ci f1_instr->immediate = immed->value; 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_ci if (is_download_const(immed)) 16768c2ecf20Sopenharmony_ci f1_instr->parity = 1; 16778c2ecf20Sopenharmony_ci else if (dest->symbol == mode_ptr.symbol) { 16788c2ecf20Sopenharmony_ci u_int src_value; 16798c2ecf20Sopenharmony_ci u_int dst_value; 16808c2ecf20Sopenharmony_ci 16818c2ecf20Sopenharmony_ci /* 16828c2ecf20Sopenharmony_ci * Attempt to update mode information if 16838c2ecf20Sopenharmony_ci * we are operating on the mode register. 16848c2ecf20Sopenharmony_ci */ 16858c2ecf20Sopenharmony_ci if (src->symbol == allones.symbol) 16868c2ecf20Sopenharmony_ci src_value = 0xFF; 16878c2ecf20Sopenharmony_ci else if (src->symbol == allzeros.symbol) 16888c2ecf20Sopenharmony_ci src_value = 0; 16898c2ecf20Sopenharmony_ci else if (src->symbol == mode_ptr.symbol) 16908c2ecf20Sopenharmony_ci src_value = (dst_mode << 4) | src_mode; 16918c2ecf20Sopenharmony_ci else 16928c2ecf20Sopenharmony_ci goto cant_update; 16938c2ecf20Sopenharmony_ci 16948c2ecf20Sopenharmony_ci switch (opcode) { 16958c2ecf20Sopenharmony_ci case AIC_OP_AND: 16968c2ecf20Sopenharmony_ci dst_value = src_value & immed->value; 16978c2ecf20Sopenharmony_ci break; 16988c2ecf20Sopenharmony_ci case AIC_OP_XOR: 16998c2ecf20Sopenharmony_ci dst_value = src_value ^ immed->value; 17008c2ecf20Sopenharmony_ci break; 17018c2ecf20Sopenharmony_ci case AIC_OP_ADD: 17028c2ecf20Sopenharmony_ci dst_value = (src_value + immed->value) & 0xFF; 17038c2ecf20Sopenharmony_ci break; 17048c2ecf20Sopenharmony_ci case AIC_OP_OR: 17058c2ecf20Sopenharmony_ci dst_value = src_value | immed->value; 17068c2ecf20Sopenharmony_ci break; 17078c2ecf20Sopenharmony_ci case AIC_OP_BMOV: 17088c2ecf20Sopenharmony_ci dst_value = src_value; 17098c2ecf20Sopenharmony_ci break; 17108c2ecf20Sopenharmony_ci default: 17118c2ecf20Sopenharmony_ci goto cant_update; 17128c2ecf20Sopenharmony_ci } 17138c2ecf20Sopenharmony_ci src_mode = dst_value & 0xF; 17148c2ecf20Sopenharmony_ci dst_mode = (dst_value >> 4) & 0xF; 17158c2ecf20Sopenharmony_ci } 17168c2ecf20Sopenharmony_ci 17178c2ecf20Sopenharmony_cicant_update: 17188c2ecf20Sopenharmony_ci symlist_free(&immed->referenced_syms); 17198c2ecf20Sopenharmony_ci instruction_ptr++; 17208c2ecf20Sopenharmony_ci} 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_cistatic void 17238c2ecf20Sopenharmony_ciformat_2_instr(int opcode, symbol_ref_t *dest, expression_t *places, 17248c2ecf20Sopenharmony_ci symbol_ref_t *src, int ret) 17258c2ecf20Sopenharmony_ci{ 17268c2ecf20Sopenharmony_ci struct instruction *instr; 17278c2ecf20Sopenharmony_ci struct ins_format2 *f2_instr; 17288c2ecf20Sopenharmony_ci uint8_t shift_control; 17298c2ecf20Sopenharmony_ci 17308c2ecf20Sopenharmony_ci if (src->symbol == NULL) 17318c2ecf20Sopenharmony_ci src = dest; 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_ci /* Test register permissions */ 17348c2ecf20Sopenharmony_ci test_writable_symbol(dest->symbol); 17358c2ecf20Sopenharmony_ci test_readable_symbol(src->symbol); 17368c2ecf20Sopenharmony_ci 17378c2ecf20Sopenharmony_ci /* Allocate sequencer space for the instruction and fill it out */ 17388c2ecf20Sopenharmony_ci instr = seq_alloc(); 17398c2ecf20Sopenharmony_ci f2_instr = &instr->format.format2; 17408c2ecf20Sopenharmony_ci f2_instr->ret = ret ? 1 : 0; 17418c2ecf20Sopenharmony_ci f2_instr->opcode = AIC_OP_ROL; 17428c2ecf20Sopenharmony_ci f2_instr->destination = dest->symbol->info.rinfo->address 17438c2ecf20Sopenharmony_ci + dest->offset; 17448c2ecf20Sopenharmony_ci f2_instr->source = src->symbol->info.rinfo->address 17458c2ecf20Sopenharmony_ci + src->offset; 17468c2ecf20Sopenharmony_ci if (places->value > 8 || places->value <= 0) { 17478c2ecf20Sopenharmony_ci stop("illegal shift value", EX_DATAERR); 17488c2ecf20Sopenharmony_ci /* NOTREACHED */ 17498c2ecf20Sopenharmony_ci } 17508c2ecf20Sopenharmony_ci switch (opcode) { 17518c2ecf20Sopenharmony_ci case AIC_OP_SHL: 17528c2ecf20Sopenharmony_ci if (places->value == 8) 17538c2ecf20Sopenharmony_ci shift_control = 0xf0; 17548c2ecf20Sopenharmony_ci else 17558c2ecf20Sopenharmony_ci shift_control = (places->value << 4) | places->value; 17568c2ecf20Sopenharmony_ci break; 17578c2ecf20Sopenharmony_ci case AIC_OP_SHR: 17588c2ecf20Sopenharmony_ci if (places->value == 8) { 17598c2ecf20Sopenharmony_ci shift_control = 0xf8; 17608c2ecf20Sopenharmony_ci } else { 17618c2ecf20Sopenharmony_ci shift_control = (places->value << 4) 17628c2ecf20Sopenharmony_ci | (8 - places->value) 17638c2ecf20Sopenharmony_ci | 0x08; 17648c2ecf20Sopenharmony_ci } 17658c2ecf20Sopenharmony_ci break; 17668c2ecf20Sopenharmony_ci case AIC_OP_ROL: 17678c2ecf20Sopenharmony_ci shift_control = places->value & 0x7; 17688c2ecf20Sopenharmony_ci break; 17698c2ecf20Sopenharmony_ci case AIC_OP_ROR: 17708c2ecf20Sopenharmony_ci shift_control = (8 - places->value) | 0x08; 17718c2ecf20Sopenharmony_ci break; 17728c2ecf20Sopenharmony_ci default: 17738c2ecf20Sopenharmony_ci shift_control = 0; /* Quiet Compiler */ 17748c2ecf20Sopenharmony_ci stop("Invalid shift operation specified", EX_SOFTWARE); 17758c2ecf20Sopenharmony_ci /* NOTREACHED */ 17768c2ecf20Sopenharmony_ci break; 17778c2ecf20Sopenharmony_ci }; 17788c2ecf20Sopenharmony_ci f2_instr->shift_control = shift_control; 17798c2ecf20Sopenharmony_ci symlist_free(&places->referenced_syms); 17808c2ecf20Sopenharmony_ci instruction_ptr++; 17818c2ecf20Sopenharmony_ci} 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_cistatic void 17848c2ecf20Sopenharmony_ciformat_3_instr(int opcode, symbol_ref_t *src, 17858c2ecf20Sopenharmony_ci expression_t *immed, symbol_ref_t *address) 17868c2ecf20Sopenharmony_ci{ 17878c2ecf20Sopenharmony_ci struct instruction *instr; 17888c2ecf20Sopenharmony_ci struct ins_format3 *f3_instr; 17898c2ecf20Sopenharmony_ci int addr; 17908c2ecf20Sopenharmony_ci 17918c2ecf20Sopenharmony_ci /* Test register permissions */ 17928c2ecf20Sopenharmony_ci test_readable_symbol(src->symbol); 17938c2ecf20Sopenharmony_ci 17948c2ecf20Sopenharmony_ci /* Allocate sequencer space for the instruction and fill it out */ 17958c2ecf20Sopenharmony_ci instr = seq_alloc(); 17968c2ecf20Sopenharmony_ci f3_instr = &instr->format.format3; 17978c2ecf20Sopenharmony_ci if (address->symbol == NULL) { 17988c2ecf20Sopenharmony_ci /* 'dot' reference. Use the current instruction pointer */ 17998c2ecf20Sopenharmony_ci addr = instruction_ptr + address->offset; 18008c2ecf20Sopenharmony_ci } else if (address->symbol->type == UNINITIALIZED) { 18018c2ecf20Sopenharmony_ci /* forward reference */ 18028c2ecf20Sopenharmony_ci addr = address->offset; 18038c2ecf20Sopenharmony_ci instr->patch_label = address->symbol; 18048c2ecf20Sopenharmony_ci } else 18058c2ecf20Sopenharmony_ci addr = address->symbol->info.linfo->address + address->offset; 18068c2ecf20Sopenharmony_ci f3_instr->opcode = opcode; 18078c2ecf20Sopenharmony_ci f3_instr->address = addr; 18088c2ecf20Sopenharmony_ci f3_instr->source = src->symbol->info.rinfo->address 18098c2ecf20Sopenharmony_ci + src->offset; 18108c2ecf20Sopenharmony_ci f3_instr->immediate = immed->value; 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_ci if (is_download_const(immed)) 18138c2ecf20Sopenharmony_ci f3_instr->parity = 1; 18148c2ecf20Sopenharmony_ci 18158c2ecf20Sopenharmony_ci symlist_free(&immed->referenced_syms); 18168c2ecf20Sopenharmony_ci instruction_ptr++; 18178c2ecf20Sopenharmony_ci} 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_cistatic void 18208c2ecf20Sopenharmony_citest_readable_symbol(symbol_t *symbol) 18218c2ecf20Sopenharmony_ci{ 18228c2ecf20Sopenharmony_ci if ((symbol->info.rinfo->modes & (0x1 << src_mode)) == 0) { 18238c2ecf20Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), 18248c2ecf20Sopenharmony_ci "Register %s unavailable in source reg mode %d", 18258c2ecf20Sopenharmony_ci symbol->name, src_mode); 18268c2ecf20Sopenharmony_ci stop(errbuf, EX_DATAERR); 18278c2ecf20Sopenharmony_ci } 18288c2ecf20Sopenharmony_ci 18298c2ecf20Sopenharmony_ci if (symbol->info.rinfo->mode == WO) { 18308c2ecf20Sopenharmony_ci stop("Write Only register specified as source", 18318c2ecf20Sopenharmony_ci EX_DATAERR); 18328c2ecf20Sopenharmony_ci /* NOTREACHED */ 18338c2ecf20Sopenharmony_ci } 18348c2ecf20Sopenharmony_ci} 18358c2ecf20Sopenharmony_ci 18368c2ecf20Sopenharmony_cistatic void 18378c2ecf20Sopenharmony_citest_writable_symbol(symbol_t *symbol) 18388c2ecf20Sopenharmony_ci{ 18398c2ecf20Sopenharmony_ci if ((symbol->info.rinfo->modes & (0x1 << dst_mode)) == 0) { 18408c2ecf20Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), 18418c2ecf20Sopenharmony_ci "Register %s unavailable in destination reg mode %d", 18428c2ecf20Sopenharmony_ci symbol->name, dst_mode); 18438c2ecf20Sopenharmony_ci stop(errbuf, EX_DATAERR); 18448c2ecf20Sopenharmony_ci } 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_ci if (symbol->info.rinfo->mode == RO) { 18478c2ecf20Sopenharmony_ci stop("Read Only register specified as destination", 18488c2ecf20Sopenharmony_ci EX_DATAERR); 18498c2ecf20Sopenharmony_ci /* NOTREACHED */ 18508c2ecf20Sopenharmony_ci } 18518c2ecf20Sopenharmony_ci} 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_cistatic void 18548c2ecf20Sopenharmony_citype_check(symbol_ref_t *sym, expression_t *expression, int opcode) 18558c2ecf20Sopenharmony_ci{ 18568c2ecf20Sopenharmony_ci symbol_t *symbol = sym->symbol; 18578c2ecf20Sopenharmony_ci symbol_node_t *node; 18588c2ecf20Sopenharmony_ci int and_op; 18598c2ecf20Sopenharmony_ci int8_t value, mask; 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci and_op = FALSE; 18628c2ecf20Sopenharmony_ci /* 18638c2ecf20Sopenharmony_ci * Make sure that we aren't attempting to write something 18648c2ecf20Sopenharmony_ci * that hasn't been defined. If this is an and operation, 18658c2ecf20Sopenharmony_ci * this is a mask, so "undefined" bits are okay. 18668c2ecf20Sopenharmony_ci */ 18678c2ecf20Sopenharmony_ci if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || 18688c2ecf20Sopenharmony_ci opcode == AIC_OP_JZ || opcode == AIC_OP_JNE || 18698c2ecf20Sopenharmony_ci opcode == AIC_OP_BMOV) 18708c2ecf20Sopenharmony_ci and_op = TRUE; 18718c2ecf20Sopenharmony_ci 18728c2ecf20Sopenharmony_ci /* 18738c2ecf20Sopenharmony_ci * Defaulting to 8 bit logic 18748c2ecf20Sopenharmony_ci */ 18758c2ecf20Sopenharmony_ci mask = (int8_t)~symbol->info.rinfo->valid_bitmask; 18768c2ecf20Sopenharmony_ci value = (int8_t)expression->value; 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_ci if (and_op == FALSE && (mask & value) != 0 ) { 18798c2ecf20Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), 18808c2ecf20Sopenharmony_ci "Invalid bit(s) 0x%x in immediate written to %s", 18818c2ecf20Sopenharmony_ci (mask & value), 18828c2ecf20Sopenharmony_ci symbol->name); 18838c2ecf20Sopenharmony_ci stop(errbuf, EX_DATAERR); 18848c2ecf20Sopenharmony_ci /* NOTREACHED */ 18858c2ecf20Sopenharmony_ci } 18868c2ecf20Sopenharmony_ci 18878c2ecf20Sopenharmony_ci /* 18888c2ecf20Sopenharmony_ci * Now make sure that all of the symbols referenced by the 18898c2ecf20Sopenharmony_ci * expression are defined for this register. 18908c2ecf20Sopenharmony_ci */ 18918c2ecf20Sopenharmony_ci if (symbol->info.rinfo->typecheck_masks != FALSE) { 18928c2ecf20Sopenharmony_ci for(node = expression->referenced_syms.slh_first; 18938c2ecf20Sopenharmony_ci node != NULL; 18948c2ecf20Sopenharmony_ci node = node->links.sle_next) { 18958c2ecf20Sopenharmony_ci if ((node->symbol->type == MASK 18968c2ecf20Sopenharmony_ci || node->symbol->type == FIELD 18978c2ecf20Sopenharmony_ci || node->symbol->type == ENUM 18988c2ecf20Sopenharmony_ci || node->symbol->type == ENUM_ENTRY) 18998c2ecf20Sopenharmony_ci && symlist_search(&node->symbol->info.finfo->symrefs, 19008c2ecf20Sopenharmony_ci symbol->name) == NULL) { 19018c2ecf20Sopenharmony_ci snprintf(errbuf, sizeof(errbuf), 19028c2ecf20Sopenharmony_ci "Invalid field or mask %s " 19038c2ecf20Sopenharmony_ci "for register %s", 19048c2ecf20Sopenharmony_ci node->symbol->name, symbol->name); 19058c2ecf20Sopenharmony_ci stop(errbuf, EX_DATAERR); 19068c2ecf20Sopenharmony_ci /* NOTREACHED */ 19078c2ecf20Sopenharmony_ci } 19088c2ecf20Sopenharmony_ci } 19098c2ecf20Sopenharmony_ci } 19108c2ecf20Sopenharmony_ci} 19118c2ecf20Sopenharmony_ci 19128c2ecf20Sopenharmony_cistatic void 19138c2ecf20Sopenharmony_cimake_expression(expression_t *immed, int value) 19148c2ecf20Sopenharmony_ci{ 19158c2ecf20Sopenharmony_ci SLIST_INIT(&immed->referenced_syms); 19168c2ecf20Sopenharmony_ci immed->value = value & 0xff; 19178c2ecf20Sopenharmony_ci} 19188c2ecf20Sopenharmony_ci 19198c2ecf20Sopenharmony_cistatic void 19208c2ecf20Sopenharmony_ciadd_conditional(symbol_t *symbol) 19218c2ecf20Sopenharmony_ci{ 19228c2ecf20Sopenharmony_ci static int numfuncs; 19238c2ecf20Sopenharmony_ci 19248c2ecf20Sopenharmony_ci if (numfuncs == 0) { 19258c2ecf20Sopenharmony_ci /* add a special conditional, "0" */ 19268c2ecf20Sopenharmony_ci symbol_t *false_func; 19278c2ecf20Sopenharmony_ci 19288c2ecf20Sopenharmony_ci false_func = symtable_get("0"); 19298c2ecf20Sopenharmony_ci if (false_func->type != UNINITIALIZED) { 19308c2ecf20Sopenharmony_ci stop("Conditional expression '0' " 19318c2ecf20Sopenharmony_ci "conflicts with a symbol", EX_DATAERR); 19328c2ecf20Sopenharmony_ci /* NOTREACHED */ 19338c2ecf20Sopenharmony_ci } 19348c2ecf20Sopenharmony_ci false_func->type = CONDITIONAL; 19358c2ecf20Sopenharmony_ci initialize_symbol(false_func); 19368c2ecf20Sopenharmony_ci false_func->info.condinfo->func_num = numfuncs++; 19378c2ecf20Sopenharmony_ci symlist_add(&patch_functions, false_func, SYMLIST_INSERT_HEAD); 19388c2ecf20Sopenharmony_ci } 19398c2ecf20Sopenharmony_ci 19408c2ecf20Sopenharmony_ci /* This condition has occurred before */ 19418c2ecf20Sopenharmony_ci if (symbol->type == CONDITIONAL) 19428c2ecf20Sopenharmony_ci return; 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_ci if (symbol->type != UNINITIALIZED) { 19458c2ecf20Sopenharmony_ci stop("Conditional expression conflicts with a symbol", 19468c2ecf20Sopenharmony_ci EX_DATAERR); 19478c2ecf20Sopenharmony_ci /* NOTREACHED */ 19488c2ecf20Sopenharmony_ci } 19498c2ecf20Sopenharmony_ci 19508c2ecf20Sopenharmony_ci symbol->type = CONDITIONAL; 19518c2ecf20Sopenharmony_ci initialize_symbol(symbol); 19528c2ecf20Sopenharmony_ci symbol->info.condinfo->func_num = numfuncs++; 19538c2ecf20Sopenharmony_ci symlist_add(&patch_functions, symbol, SYMLIST_INSERT_HEAD); 19548c2ecf20Sopenharmony_ci} 19558c2ecf20Sopenharmony_ci 19568c2ecf20Sopenharmony_cistatic void 19578c2ecf20Sopenharmony_ciadd_version(const char *verstring) 19588c2ecf20Sopenharmony_ci{ 19598c2ecf20Sopenharmony_ci const char prefix[] = " * "; 19608c2ecf20Sopenharmony_ci int newlen; 19618c2ecf20Sopenharmony_ci int oldlen; 19628c2ecf20Sopenharmony_ci 19638c2ecf20Sopenharmony_ci newlen = strlen(verstring) + strlen(prefix); 19648c2ecf20Sopenharmony_ci oldlen = 0; 19658c2ecf20Sopenharmony_ci if (versions != NULL) 19668c2ecf20Sopenharmony_ci oldlen = strlen(versions); 19678c2ecf20Sopenharmony_ci versions = realloc(versions, newlen + oldlen + 2); 19688c2ecf20Sopenharmony_ci if (versions == NULL) 19698c2ecf20Sopenharmony_ci stop("Can't allocate version string", EX_SOFTWARE); 19708c2ecf20Sopenharmony_ci strcpy(&versions[oldlen], prefix); 19718c2ecf20Sopenharmony_ci strcpy(&versions[oldlen + strlen(prefix)], verstring); 19728c2ecf20Sopenharmony_ci versions[newlen + oldlen] = '\n'; 19738c2ecf20Sopenharmony_ci versions[newlen + oldlen + 1] = '\0'; 19748c2ecf20Sopenharmony_ci} 19758c2ecf20Sopenharmony_ci 19768c2ecf20Sopenharmony_civoid 19778c2ecf20Sopenharmony_ciyyerror(const char *string) 19788c2ecf20Sopenharmony_ci{ 19798c2ecf20Sopenharmony_ci stop(string, EX_DATAERR); 19808c2ecf20Sopenharmony_ci} 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_cistatic int 19838c2ecf20Sopenharmony_ciis_download_const(expression_t *immed) 19848c2ecf20Sopenharmony_ci{ 19858c2ecf20Sopenharmony_ci if ((immed->referenced_syms.slh_first != NULL) 19868c2ecf20Sopenharmony_ci && (immed->referenced_syms.slh_first->symbol->type == DOWNLOAD_CONST)) 19878c2ecf20Sopenharmony_ci return (TRUE); 19888c2ecf20Sopenharmony_ci 19898c2ecf20Sopenharmony_ci return (FALSE); 19908c2ecf20Sopenharmony_ci} 19918c2ecf20Sopenharmony_ci 19928c2ecf20Sopenharmony_cistatic int 19938c2ecf20Sopenharmony_ciis_location_address(symbol_t *sym) 19948c2ecf20Sopenharmony_ci{ 19958c2ecf20Sopenharmony_ci if (sym->type == SCBLOC || 19968c2ecf20Sopenharmony_ci sym->type == SRAMLOC) 19978c2ecf20Sopenharmony_ci return (TRUE); 19988c2ecf20Sopenharmony_ci return (FALSE); 19998c2ecf20Sopenharmony_ci} 20008c2ecf20Sopenharmony_ci 2001