1 1.1 fvdl %{ 2 1.9 ryo /* $NetBSD: aicasm_gram.y,v 1.9 2021/10/25 07:40:29 ryo Exp $ */ 3 1.1 fvdl 4 1.1 fvdl /* 5 1.1 fvdl * Parser for the Aic7xxx SCSI Host adapter sequencer assembler. 6 1.1 fvdl * 7 1.3 fvdl * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. 8 1.3 fvdl * Copyright (c) 2001, 2002 Adaptec Inc. 9 1.1 fvdl * All rights reserved. 10 1.1 fvdl * 11 1.1 fvdl * Redistribution and use in source and binary forms, with or without 12 1.1 fvdl * modification, are permitted provided that the following conditions 13 1.1 fvdl * are met: 14 1.1 fvdl * 1. Redistributions of source code must retain the above copyright 15 1.1 fvdl * notice, this list of conditions, and the following disclaimer, 16 1.1 fvdl * without modification. 17 1.3 fvdl * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 1.3 fvdl * substantially similar to the "NO WARRANTY" disclaimer below 19 1.3 fvdl * ("Disclaimer") and any redistribution must be conditioned upon 20 1.3 fvdl * including a substantially similar Disclaimer requirement for further 21 1.3 fvdl * binary redistribution. 22 1.3 fvdl * 3. Neither the names of the above-listed copyright holders nor the names 23 1.3 fvdl * of any contributors may be used to endorse or promote products derived 24 1.3 fvdl * from this software without specific prior written permission. 25 1.1 fvdl * 26 1.3 fvdl * Alternatively, this software may be distributed under the terms of the 27 1.3 fvdl * GNU General Public License ("GPL") version 2 as published by the Free 28 1.3 fvdl * Software Foundation. 29 1.3 fvdl * 30 1.3 fvdl * NO WARRANTY 31 1.3 fvdl * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 1.3 fvdl * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 1.3 fvdl * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 1.3 fvdl * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 1.3 fvdl * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 1.1 fvdl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 1.1 fvdl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 1.3 fvdl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 1.3 fvdl * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 1.3 fvdl * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 1.3 fvdl * POSSIBILITY OF SUCH DAMAGES. 42 1.1 fvdl * 43 1.3 fvdl * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_gram.y,v 1.23 2003/01/20 18:02:11 gibbs Exp $ 44 1.1 fvdl */ 45 1.1 fvdl 46 1.3 fvdl #include <sys/types.h> 47 1.3 fvdl 48 1.3 fvdl #include <inttypes.h> 49 1.3 fvdl #include <regex.h> 50 1.1 fvdl #include <stdio.h> 51 1.1 fvdl #include <stdlib.h> 52 1.1 fvdl #include <string.h> 53 1.1 fvdl #include <sysexits.h> 54 1.1 fvdl 55 1.3 fvdl #ifdef __linux__ 56 1.3 fvdl #include "../queue.h" 57 1.3 fvdl #else 58 1.1 fvdl #include <sys/queue.h> 59 1.3 fvdl #endif 60 1.1 fvdl 61 1.1 fvdl #include "aicasm.h" 62 1.1 fvdl #include "aicasm_symbol.h" 63 1.3 fvdl #include "aicasm_insformat.h" 64 1.1 fvdl 65 1.1 fvdl char *yyfilename; 66 1.3 fvdl char stock_prefix[] = "aic_"; 67 1.3 fvdl char *prefix = stock_prefix; 68 1.3 fvdl char *patch_arg_list; 69 1.3 fvdl char *versions; 70 1.3 fvdl static char errbuf[255]; 71 1.3 fvdl static char regex_pattern[255]; 72 1.1 fvdl static symbol_t *cur_symbol; 73 1.3 fvdl static symbol_t *field_symbol; 74 1.3 fvdl static symbol_t *scb_or_sram_symbol; 75 1.1 fvdl static symtype cur_symtype; 76 1.3 fvdl static symbol_ref_t accumulator; 77 1.3 fvdl static symbol_ref_t mode_ptr; 78 1.1 fvdl static symbol_ref_t allones; 79 1.1 fvdl static symbol_ref_t allzeros; 80 1.1 fvdl static symbol_ref_t none; 81 1.1 fvdl static symbol_ref_t sindex; 82 1.1 fvdl static int instruction_ptr; 83 1.3 fvdl static int num_srams; 84 1.1 fvdl static int sram_or_scb_offset; 85 1.1 fvdl static int download_constant_count; 86 1.3 fvdl static int in_critical_section; 87 1.3 fvdl static u_int enum_increment; 88 1.3 fvdl static u_int enum_next_value; 89 1.3 fvdl 90 1.3 fvdl static void process_field(int field_type, symbol_t *sym, int mask); 91 1.3 fvdl static void initialize_symbol(symbol_t *symbol); 92 1.3 fvdl static void add_macro_arg(const char *argtext, int position); 93 1.3 fvdl static void add_macro_body(const char *bodytext); 94 1.3 fvdl static void process_register(symbol_t **p_symbol); 95 1.3 fvdl static void format_1_instr(int opcode, symbol_ref_t *dest, 96 1.3 fvdl expression_t *immed, symbol_ref_t *src, int ret); 97 1.3 fvdl static void format_2_instr(int opcode, symbol_ref_t *dest, 98 1.3 fvdl expression_t *places, symbol_ref_t *src, int ret); 99 1.3 fvdl static void format_3_instr(int opcode, symbol_ref_t *src, 100 1.3 fvdl expression_t *immed, symbol_ref_t *address); 101 1.3 fvdl static void test_readable_symbol(symbol_t *symbol); 102 1.3 fvdl static void test_writable_symbol(symbol_t *symbol); 103 1.3 fvdl static void type_check(symbol_t *symbol, expression_t *expression, int and_op); 104 1.3 fvdl static void make_expression(expression_t *immed, int value); 105 1.3 fvdl static void add_conditional(symbol_t *symbol); 106 1.3 fvdl static void add_version(const char *verstring); 107 1.3 fvdl static int is_download_const(expression_t *immed); 108 1.1 fvdl 109 1.1 fvdl #define SRAM_SYMNAME "SRAM_BASE" 110 1.1 fvdl #define SCB_SYMNAME "SCB_BASE" 111 1.1 fvdl %} 112 1.1 fvdl 113 1.1 fvdl %union { 114 1.3 fvdl u_int value; 115 1.1 fvdl char *str; 116 1.1 fvdl symbol_t *sym; 117 1.1 fvdl symbol_ref_t sym_ref; 118 1.1 fvdl expression_t expression; 119 1.1 fvdl } 120 1.1 fvdl 121 1.1 fvdl %token T_REGISTER 122 1.1 fvdl 123 1.1 fvdl %token <value> T_CONST 124 1.1 fvdl 125 1.3 fvdl %token T_EXPORT 126 1.3 fvdl 127 1.1 fvdl %token T_DOWNLOAD 128 1.1 fvdl 129 1.1 fvdl %token T_SCB 130 1.1 fvdl 131 1.1 fvdl %token T_SRAM 132 1.1 fvdl 133 1.1 fvdl %token T_ALIAS 134 1.1 fvdl 135 1.1 fvdl %token T_SIZE 136 1.1 fvdl 137 1.3 fvdl %token T_EXPR_LSHIFT 138 1.3 fvdl 139 1.3 fvdl %token T_EXPR_RSHIFT 140 1.3 fvdl 141 1.1 fvdl %token <value> T_ADDRESS 142 1.1 fvdl 143 1.1 fvdl %token T_ACCESS_MODE 144 1.1 fvdl 145 1.3 fvdl %token T_MODES 146 1.3 fvdl 147 1.3 fvdl %token T_DEFINE 148 1.3 fvdl 149 1.3 fvdl %token T_SET_SRC_MODE 150 1.3 fvdl 151 1.3 fvdl %token T_SET_DST_MODE 152 1.3 fvdl 153 1.1 fvdl %token <value> T_MODE 154 1.1 fvdl 155 1.3 fvdl %token T_BEGIN_CS 156 1.3 fvdl 157 1.3 fvdl %token T_END_CS 158 1.3 fvdl 159 1.3 fvdl %token T_FIELD 160 1.3 fvdl 161 1.3 fvdl %token T_ENUM 162 1.1 fvdl 163 1.1 fvdl %token T_MASK 164 1.1 fvdl 165 1.1 fvdl %token <value> T_NUMBER 166 1.1 fvdl 167 1.3 fvdl %token <str> T_PATH T_STRING T_ARG T_MACROBODY 168 1.1 fvdl 169 1.1 fvdl %token <sym> T_CEXPR 170 1.1 fvdl 171 1.3 fvdl %token T_EOF T_INCLUDE T_VERSION T_PREFIX T_PATCH_ARG_LIST 172 1.1 fvdl 173 1.1 fvdl %token <value> T_SHR T_SHL T_ROR T_ROL 174 1.1 fvdl 175 1.1 fvdl %token <value> T_MVI T_MOV T_CLR T_BMOV 176 1.1 fvdl 177 1.1 fvdl %token <value> T_JMP T_JC T_JNC T_JE T_JNE T_JNZ T_JZ T_CALL 178 1.1 fvdl 179 1.1 fvdl %token <value> T_ADD T_ADC 180 1.1 fvdl 181 1.1 fvdl %token <value> T_INC T_DEC 182 1.1 fvdl 183 1.1 fvdl %token <value> T_STC T_CLC 184 1.1 fvdl 185 1.3 fvdl %token <value> T_CMP T_NOT T_XOR 186 1.1 fvdl 187 1.1 fvdl %token <value> T_TEST T_AND 188 1.1 fvdl 189 1.1 fvdl %token <value> T_OR 190 1.1 fvdl 191 1.1 fvdl %token T_RET 192 1.1 fvdl 193 1.1 fvdl %token T_NOP 194 1.1 fvdl 195 1.3 fvdl %token T_ACCUM T_ALLONES T_ALLZEROS T_NONE T_SINDEX T_MODE_PTR 196 1.1 fvdl 197 1.1 fvdl %token T_A 198 1.1 fvdl 199 1.1 fvdl %token <sym> T_SYMBOL 200 1.1 fvdl 201 1.1 fvdl %token T_NL 202 1.1 fvdl 203 1.1 fvdl %token T_IF T_ELSE T_ELSE_IF T_ENDIF 204 1.1 fvdl 205 1.1 fvdl %type <sym_ref> reg_symbol address destination source opt_source 206 1.1 fvdl 207 1.1 fvdl %type <expression> expression immediate immediate_or_a 208 1.1 fvdl 209 1.3 fvdl %type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne 210 1.1 fvdl 211 1.3 fvdl %type <value> mode_value mode_list macro_arglist 212 1.1 fvdl 213 1.1 fvdl %left '|' 214 1.1 fvdl %left '&' 215 1.3 fvdl %left T_EXPR_LSHIFT T_EXPR_RSHIFT 216 1.1 fvdl %left '+' '-' 217 1.3 fvdl %left '*' '/' 218 1.1 fvdl %right '~' 219 1.1 fvdl %nonassoc UMINUS 220 1.1 fvdl %% 221 1.1 fvdl 222 1.1 fvdl program: 223 1.1 fvdl include 224 1.1 fvdl | program include 225 1.3 fvdl | prefix 226 1.3 fvdl | program prefix 227 1.3 fvdl | patch_arg_list 228 1.3 fvdl | program patch_arg_list 229 1.3 fvdl | version 230 1.3 fvdl | program version 231 1.1 fvdl | register 232 1.1 fvdl | program register 233 1.1 fvdl | constant 234 1.1 fvdl | program constant 235 1.3 fvdl | macrodefn 236 1.3 fvdl | program macrodefn 237 1.1 fvdl | scratch_ram 238 1.1 fvdl | program scratch_ram 239 1.1 fvdl | scb 240 1.1 fvdl | program scb 241 1.1 fvdl | label 242 1.1 fvdl | program label 243 1.3 fvdl | set_src_mode 244 1.3 fvdl | program set_src_mode 245 1.3 fvdl | set_dst_mode 246 1.3 fvdl | program set_dst_mode 247 1.3 fvdl | critical_section_start 248 1.3 fvdl | program critical_section_start 249 1.3 fvdl | critical_section_end 250 1.3 fvdl | program critical_section_end 251 1.1 fvdl | conditional 252 1.1 fvdl | program conditional 253 1.1 fvdl | code 254 1.1 fvdl | program code 255 1.1 fvdl ; 256 1.1 fvdl 257 1.1 fvdl include: 258 1.1 fvdl T_INCLUDE '<' T_PATH '>' 259 1.3 fvdl { 260 1.3 fvdl include_file($3, BRACKETED_INCLUDE); 261 1.3 fvdl } 262 1.1 fvdl | T_INCLUDE '"' T_PATH '"' 263 1.3 fvdl { 264 1.3 fvdl include_file($3, QUOTED_INCLUDE); 265 1.3 fvdl } 266 1.3 fvdl ; 267 1.3 fvdl 268 1.3 fvdl prefix: 269 1.3 fvdl T_PREFIX '=' T_STRING 270 1.3 fvdl { 271 1.3 fvdl if (prefix != stock_prefix) 272 1.3 fvdl stop("Prefix multiply defined", 273 1.3 fvdl EX_DATAERR); 274 1.3 fvdl prefix = strdup($3); 275 1.3 fvdl if (prefix == NULL) 276 1.3 fvdl stop("Unable to record prefix", EX_SOFTWARE); 277 1.3 fvdl } 278 1.3 fvdl ; 279 1.3 fvdl 280 1.3 fvdl patch_arg_list: 281 1.3 fvdl T_PATCH_ARG_LIST '=' T_STRING 282 1.3 fvdl { 283 1.3 fvdl if (patch_arg_list != NULL) 284 1.3 fvdl stop("Patch argument list multiply defined", 285 1.3 fvdl EX_DATAERR); 286 1.3 fvdl patch_arg_list = strdup($3); 287 1.3 fvdl if (patch_arg_list == NULL) 288 1.3 fvdl stop("Unable to record patch arg list", EX_SOFTWARE); 289 1.3 fvdl } 290 1.3 fvdl ; 291 1.3 fvdl 292 1.3 fvdl version: 293 1.3 fvdl T_VERSION '=' T_STRING 294 1.3 fvdl { add_version($3); } 295 1.1 fvdl ; 296 1.1 fvdl 297 1.1 fvdl register: 298 1.1 fvdl T_REGISTER { cur_symtype = REGISTER; } reg_definition 299 1.1 fvdl ; 300 1.1 fvdl 301 1.1 fvdl reg_definition: 302 1.1 fvdl T_SYMBOL '{' 303 1.1 fvdl { 304 1.1 fvdl if ($1->type != UNINITIALIZED) { 305 1.1 fvdl stop("Register multiply defined", EX_DATAERR); 306 1.1 fvdl /* NOTREACHED */ 307 1.1 fvdl } 308 1.4 perry cur_symbol = $1; 309 1.1 fvdl cur_symbol->type = cur_symtype; 310 1.1 fvdl initialize_symbol(cur_symbol); 311 1.1 fvdl } 312 1.1 fvdl reg_attribute_list 313 1.1 fvdl '}' 314 1.4 perry { 315 1.1 fvdl /* 316 1.1 fvdl * Default to allowing everything in for registers 317 1.1 fvdl * with no bit or mask definitions. 318 1.1 fvdl */ 319 1.1 fvdl if (cur_symbol->info.rinfo->valid_bitmask == 0) 320 1.1 fvdl cur_symbol->info.rinfo->valid_bitmask = 0xFF; 321 1.1 fvdl 322 1.1 fvdl if (cur_symbol->info.rinfo->size == 0) 323 1.1 fvdl cur_symbol->info.rinfo->size = 1; 324 1.1 fvdl 325 1.1 fvdl /* 326 1.1 fvdl * This might be useful for registers too. 327 1.1 fvdl */ 328 1.1 fvdl if (cur_symbol->type != REGISTER) { 329 1.1 fvdl if (cur_symbol->info.rinfo->address == 0) 330 1.1 fvdl cur_symbol->info.rinfo->address = 331 1.1 fvdl sram_or_scb_offset; 332 1.1 fvdl sram_or_scb_offset += 333 1.1 fvdl cur_symbol->info.rinfo->size; 334 1.1 fvdl } 335 1.1 fvdl cur_symbol = NULL; 336 1.1 fvdl } 337 1.1 fvdl ; 338 1.1 fvdl 339 1.1 fvdl reg_attribute_list: 340 1.1 fvdl reg_attribute 341 1.1 fvdl | reg_attribute_list reg_attribute 342 1.1 fvdl ; 343 1.1 fvdl 344 1.4 perry reg_attribute: 345 1.1 fvdl reg_address 346 1.1 fvdl | size 347 1.1 fvdl | access_mode 348 1.3 fvdl | modes 349 1.3 fvdl | field_defn 350 1.3 fvdl | enum_defn 351 1.1 fvdl | mask_defn 352 1.1 fvdl | alias 353 1.1 fvdl | accumulator 354 1.3 fvdl | mode_pointer 355 1.1 fvdl | allones 356 1.1 fvdl | allzeros 357 1.1 fvdl | none 358 1.1 fvdl | sindex 359 1.1 fvdl ; 360 1.1 fvdl 361 1.1 fvdl reg_address: 362 1.1 fvdl T_ADDRESS T_NUMBER 363 1.1 fvdl { 364 1.1 fvdl cur_symbol->info.rinfo->address = $2; 365 1.1 fvdl } 366 1.1 fvdl ; 367 1.1 fvdl 368 1.1 fvdl size: 369 1.1 fvdl T_SIZE T_NUMBER 370 1.1 fvdl { 371 1.1 fvdl cur_symbol->info.rinfo->size = $2; 372 1.3 fvdl if (scb_or_sram_symbol != NULL) { 373 1.3 fvdl u_int max_addr; 374 1.3 fvdl u_int sym_max_addr; 375 1.3 fvdl 376 1.3 fvdl max_addr = scb_or_sram_symbol->info.rinfo->address 377 1.3 fvdl + scb_or_sram_symbol->info.rinfo->size; 378 1.3 fvdl sym_max_addr = cur_symbol->info.rinfo->address 379 1.3 fvdl + cur_symbol->info.rinfo->size; 380 1.3 fvdl 381 1.3 fvdl if (sym_max_addr > max_addr) 382 1.3 fvdl stop("SCB or SRAM space exhausted", EX_DATAERR); 383 1.3 fvdl } 384 1.1 fvdl } 385 1.1 fvdl ; 386 1.1 fvdl 387 1.1 fvdl access_mode: 388 1.1 fvdl T_ACCESS_MODE T_MODE 389 1.1 fvdl { 390 1.1 fvdl cur_symbol->info.rinfo->mode = $2; 391 1.1 fvdl } 392 1.1 fvdl ; 393 1.1 fvdl 394 1.3 fvdl modes: 395 1.3 fvdl T_MODES mode_list 396 1.3 fvdl { 397 1.3 fvdl cur_symbol->info.rinfo->modes = $2; 398 1.3 fvdl } 399 1.3 fvdl ; 400 1.3 fvdl 401 1.3 fvdl mode_list: 402 1.3 fvdl mode_value 403 1.3 fvdl { 404 1.3 fvdl $$ = $1; 405 1.3 fvdl } 406 1.3 fvdl | mode_list ',' mode_value 407 1.3 fvdl { 408 1.3 fvdl $$ = $1 | $3; 409 1.3 fvdl } 410 1.3 fvdl ; 411 1.3 fvdl 412 1.3 fvdl mode_value: 413 1.3 fvdl T_NUMBER 414 1.3 fvdl { 415 1.3 fvdl if ($1 > 4) { 416 1.3 fvdl stop("Valid register modes range between 0 and 4.", 417 1.3 fvdl EX_DATAERR); 418 1.3 fvdl /* NOTREACHED */ 419 1.3 fvdl } 420 1.3 fvdl 421 1.3 fvdl $$ = (0x1 << $1); 422 1.3 fvdl } 423 1.3 fvdl | T_SYMBOL 424 1.1 fvdl { 425 1.3 fvdl symbol_t *symbol; 426 1.3 fvdl 427 1.3 fvdl symbol = $1; 428 1.3 fvdl if (symbol->type != CONST) { 429 1.3 fvdl stop("Only \"const\" symbols allowed in " 430 1.3 fvdl "mode definitions.", EX_DATAERR); 431 1.3 fvdl /* NOTREACHED */ 432 1.3 fvdl } 433 1.3 fvdl if (symbol->info.cinfo->value > 4) { 434 1.3 fvdl stop("Valid register modes range between 0 and 4.", 435 1.3 fvdl EX_DATAERR); 436 1.3 fvdl /* NOTREACHED */ 437 1.3 fvdl } 438 1.3 fvdl $$ = (0x1 << symbol->info.cinfo->value); 439 1.3 fvdl } 440 1.3 fvdl ; 441 1.3 fvdl 442 1.3 fvdl field_defn: 443 1.3 fvdl T_FIELD 444 1.3 fvdl { 445 1.3 fvdl field_symbol = NULL; 446 1.3 fvdl enum_next_value = 0; 447 1.3 fvdl enum_increment = 1; 448 1.3 fvdl } 449 1.3 fvdl '{' enum_entry_list '}' 450 1.3 fvdl | T_FIELD T_SYMBOL expression 451 1.3 fvdl { 452 1.3 fvdl process_field(FIELD, $2, $3.value); 453 1.3 fvdl field_symbol = $2; 454 1.3 fvdl enum_next_value = 0; 455 1.3 fvdl enum_increment = 0x01 << (ffs($3.value) - 1); 456 1.3 fvdl } 457 1.3 fvdl '{' enum_entry_list '}' 458 1.3 fvdl | T_FIELD T_SYMBOL expression 459 1.3 fvdl { 460 1.3 fvdl process_field(FIELD, $2, $3.value); 461 1.3 fvdl } 462 1.3 fvdl ; 463 1.3 fvdl 464 1.3 fvdl enum_defn: 465 1.3 fvdl T_ENUM 466 1.3 fvdl { 467 1.3 fvdl field_symbol = NULL; 468 1.3 fvdl enum_next_value = 0; 469 1.3 fvdl enum_increment = 1; 470 1.3 fvdl } 471 1.3 fvdl '{' enum_entry_list '}' 472 1.3 fvdl | T_ENUM T_SYMBOL expression 473 1.3 fvdl { 474 1.3 fvdl process_field(ENUM, $2, $3.value); 475 1.3 fvdl field_symbol = $2; 476 1.3 fvdl enum_next_value = 0; 477 1.3 fvdl enum_increment = 0x01 << (ffs($3.value) - 1); 478 1.3 fvdl } 479 1.3 fvdl '{' enum_entry_list '}' 480 1.3 fvdl ; 481 1.3 fvdl 482 1.3 fvdl enum_entry_list: 483 1.3 fvdl enum_entry 484 1.3 fvdl | enum_entry_list ',' enum_entry 485 1.3 fvdl ; 486 1.3 fvdl 487 1.3 fvdl enum_entry: 488 1.3 fvdl T_SYMBOL 489 1.3 fvdl { 490 1.3 fvdl process_field(ENUM_ENTRY, $1, enum_next_value); 491 1.3 fvdl enum_next_value += enum_increment; 492 1.3 fvdl } 493 1.3 fvdl | T_SYMBOL expression 494 1.3 fvdl { 495 1.3 fvdl process_field(ENUM_ENTRY, $1, $2.value); 496 1.3 fvdl enum_next_value = $2.value + enum_increment; 497 1.1 fvdl } 498 1.1 fvdl ; 499 1.1 fvdl 500 1.1 fvdl mask_defn: 501 1.1 fvdl T_MASK T_SYMBOL expression 502 1.1 fvdl { 503 1.3 fvdl process_field(MASK, $2, $3.value); 504 1.1 fvdl } 505 1.1 fvdl ; 506 1.1 fvdl 507 1.1 fvdl alias: 508 1.1 fvdl T_ALIAS T_SYMBOL 509 1.1 fvdl { 510 1.1 fvdl if ($2->type != UNINITIALIZED) { 511 1.1 fvdl stop("Re-definition of register alias", 512 1.1 fvdl EX_DATAERR); 513 1.1 fvdl /* NOTREACHED */ 514 1.1 fvdl } 515 1.1 fvdl $2->type = ALIAS; 516 1.1 fvdl initialize_symbol($2); 517 1.1 fvdl $2->info.ainfo->parent = cur_symbol; 518 1.1 fvdl } 519 1.1 fvdl ; 520 1.1 fvdl 521 1.1 fvdl accumulator: 522 1.1 fvdl T_ACCUM 523 1.1 fvdl { 524 1.3 fvdl if (accumulator.symbol != NULL) { 525 1.1 fvdl stop("Only one accumulator definition allowed", 526 1.1 fvdl EX_DATAERR); 527 1.1 fvdl /* NOTREACHED */ 528 1.1 fvdl } 529 1.3 fvdl accumulator.symbol = cur_symbol; 530 1.3 fvdl } 531 1.3 fvdl ; 532 1.3 fvdl 533 1.3 fvdl mode_pointer: 534 1.3 fvdl T_MODE_PTR 535 1.3 fvdl { 536 1.3 fvdl if (mode_ptr.symbol != NULL) { 537 1.3 fvdl stop("Only one mode pointer definition allowed", 538 1.3 fvdl EX_DATAERR); 539 1.3 fvdl /* NOTREACHED */ 540 1.3 fvdl } 541 1.3 fvdl mode_ptr.symbol = cur_symbol; 542 1.1 fvdl } 543 1.1 fvdl ; 544 1.1 fvdl 545 1.1 fvdl allones: 546 1.1 fvdl T_ALLONES 547 1.1 fvdl { 548 1.1 fvdl if (allones.symbol != NULL) { 549 1.1 fvdl stop("Only one definition of allones allowed", 550 1.1 fvdl EX_DATAERR); 551 1.1 fvdl /* NOTREACHED */ 552 1.1 fvdl } 553 1.1 fvdl allones.symbol = cur_symbol; 554 1.1 fvdl } 555 1.1 fvdl ; 556 1.1 fvdl 557 1.1 fvdl allzeros: 558 1.1 fvdl T_ALLZEROS 559 1.1 fvdl { 560 1.1 fvdl if (allzeros.symbol != NULL) { 561 1.1 fvdl stop("Only one definition of allzeros allowed", 562 1.1 fvdl EX_DATAERR); 563 1.1 fvdl /* NOTREACHED */ 564 1.1 fvdl } 565 1.1 fvdl allzeros.symbol = cur_symbol; 566 1.1 fvdl } 567 1.1 fvdl ; 568 1.1 fvdl 569 1.1 fvdl none: 570 1.1 fvdl T_NONE 571 1.1 fvdl { 572 1.1 fvdl if (none.symbol != NULL) { 573 1.1 fvdl stop("Only one definition of none allowed", 574 1.1 fvdl EX_DATAERR); 575 1.1 fvdl /* NOTREACHED */ 576 1.1 fvdl } 577 1.1 fvdl none.symbol = cur_symbol; 578 1.1 fvdl } 579 1.1 fvdl ; 580 1.1 fvdl 581 1.1 fvdl sindex: 582 1.1 fvdl T_SINDEX 583 1.1 fvdl { 584 1.1 fvdl if (sindex.symbol != NULL) { 585 1.1 fvdl stop("Only one definition of sindex allowed", 586 1.1 fvdl EX_DATAERR); 587 1.1 fvdl /* NOTREACHED */ 588 1.1 fvdl } 589 1.1 fvdl sindex.symbol = cur_symbol; 590 1.1 fvdl } 591 1.1 fvdl ; 592 1.1 fvdl 593 1.1 fvdl expression: 594 1.1 fvdl expression '|' expression 595 1.1 fvdl { 596 1.1 fvdl $$.value = $1.value | $3.value; 597 1.1 fvdl symlist_merge(&$$.referenced_syms, 598 1.1 fvdl &$1.referenced_syms, 599 1.1 fvdl &$3.referenced_syms); 600 1.1 fvdl } 601 1.1 fvdl | expression '&' expression 602 1.1 fvdl { 603 1.1 fvdl $$.value = $1.value & $3.value; 604 1.1 fvdl symlist_merge(&$$.referenced_syms, 605 1.1 fvdl &$1.referenced_syms, 606 1.1 fvdl &$3.referenced_syms); 607 1.1 fvdl } 608 1.1 fvdl | expression '+' expression 609 1.1 fvdl { 610 1.1 fvdl $$.value = $1.value + $3.value; 611 1.1 fvdl symlist_merge(&$$.referenced_syms, 612 1.1 fvdl &$1.referenced_syms, 613 1.1 fvdl &$3.referenced_syms); 614 1.1 fvdl } 615 1.1 fvdl | expression '-' expression 616 1.1 fvdl { 617 1.1 fvdl $$.value = $1.value - $3.value; 618 1.1 fvdl symlist_merge(&($$.referenced_syms), 619 1.1 fvdl &($1.referenced_syms), 620 1.1 fvdl &($3.referenced_syms)); 621 1.1 fvdl } 622 1.3 fvdl | expression '*' expression 623 1.3 fvdl { 624 1.3 fvdl $$.value = $1.value * $3.value; 625 1.3 fvdl symlist_merge(&($$.referenced_syms), 626 1.3 fvdl &($1.referenced_syms), 627 1.3 fvdl &($3.referenced_syms)); 628 1.3 fvdl } 629 1.3 fvdl | expression '/' expression 630 1.3 fvdl { 631 1.3 fvdl $$.value = $1.value / $3.value; 632 1.3 fvdl symlist_merge(&($$.referenced_syms), 633 1.3 fvdl &($1.referenced_syms), 634 1.3 fvdl &($3.referenced_syms)); 635 1.3 fvdl } 636 1.3 fvdl | expression T_EXPR_LSHIFT expression 637 1.3 fvdl { 638 1.3 fvdl $$.value = $1.value << $3.value; 639 1.3 fvdl symlist_merge(&$$.referenced_syms, 640 1.3 fvdl &$1.referenced_syms, 641 1.3 fvdl &$3.referenced_syms); 642 1.3 fvdl } 643 1.3 fvdl | expression T_EXPR_RSHIFT expression 644 1.3 fvdl { 645 1.3 fvdl $$.value = $1.value >> $3.value; 646 1.3 fvdl symlist_merge(&$$.referenced_syms, 647 1.3 fvdl &$1.referenced_syms, 648 1.3 fvdl &$3.referenced_syms); 649 1.3 fvdl } 650 1.1 fvdl | '(' expression ')' 651 1.1 fvdl { 652 1.1 fvdl $$ = $2; 653 1.1 fvdl } 654 1.1 fvdl | '~' expression 655 1.1 fvdl { 656 1.1 fvdl $$ = $2; 657 1.1 fvdl $$.value = (~$$.value) & 0xFF; 658 1.1 fvdl } 659 1.1 fvdl | '-' expression %prec UMINUS 660 1.1 fvdl { 661 1.1 fvdl $$ = $2; 662 1.1 fvdl $$.value = -$$.value; 663 1.1 fvdl } 664 1.1 fvdl | T_NUMBER 665 1.1 fvdl { 666 1.1 fvdl $$.value = $1; 667 1.1 fvdl SLIST_INIT(&$$.referenced_syms); 668 1.1 fvdl } 669 1.1 fvdl | T_SYMBOL 670 1.1 fvdl { 671 1.1 fvdl symbol_t *symbol; 672 1.1 fvdl 673 1.1 fvdl symbol = $1; 674 1.1 fvdl switch (symbol->type) { 675 1.1 fvdl case ALIAS: 676 1.1 fvdl symbol = $1->info.ainfo->parent; 677 1.1 fvdl case REGISTER: 678 1.1 fvdl case SCBLOC: 679 1.1 fvdl case SRAMLOC: 680 1.1 fvdl $$.value = symbol->info.rinfo->address; 681 1.1 fvdl break; 682 1.1 fvdl case MASK: 683 1.3 fvdl case FIELD: 684 1.3 fvdl case ENUM: 685 1.3 fvdl case ENUM_ENTRY: 686 1.3 fvdl $$.value = symbol->info.finfo->value; 687 1.1 fvdl break; 688 1.1 fvdl case DOWNLOAD_CONST: 689 1.1 fvdl case CONST: 690 1.1 fvdl $$.value = symbol->info.cinfo->value; 691 1.1 fvdl break; 692 1.1 fvdl case UNINITIALIZED: 693 1.1 fvdl default: 694 1.1 fvdl { 695 1.3 fvdl snprintf(errbuf, sizeof(errbuf), 696 1.1 fvdl "Undefined symbol %s referenced", 697 1.1 fvdl symbol->name); 698 1.3 fvdl stop(errbuf, EX_DATAERR); 699 1.1 fvdl /* NOTREACHED */ 700 1.1 fvdl break; 701 1.1 fvdl } 702 1.1 fvdl } 703 1.1 fvdl SLIST_INIT(&$$.referenced_syms); 704 1.1 fvdl symlist_add(&$$.referenced_syms, symbol, SYMLIST_INSERT_HEAD); 705 1.1 fvdl } 706 1.1 fvdl ; 707 1.1 fvdl 708 1.1 fvdl constant: 709 1.4 perry T_CONST T_SYMBOL expression 710 1.1 fvdl { 711 1.1 fvdl if ($2->type != UNINITIALIZED) { 712 1.1 fvdl stop("Re-definition of symbol as a constant", 713 1.1 fvdl EX_DATAERR); 714 1.1 fvdl /* NOTREACHED */ 715 1.1 fvdl } 716 1.1 fvdl $2->type = CONST; 717 1.1 fvdl initialize_symbol($2); 718 1.3 fvdl $2->info.cinfo->value = $3.value; 719 1.1 fvdl } 720 1.1 fvdl | T_CONST T_SYMBOL T_DOWNLOAD 721 1.1 fvdl { 722 1.1 fvdl if ($1) { 723 1.1 fvdl stop("Invalid downloaded constant declaration", 724 1.1 fvdl EX_DATAERR); 725 1.1 fvdl /* NOTREACHED */ 726 1.1 fvdl } 727 1.1 fvdl if ($2->type != UNINITIALIZED) { 728 1.1 fvdl stop("Re-definition of symbol as a downloaded constant", 729 1.1 fvdl EX_DATAERR); 730 1.1 fvdl /* NOTREACHED */ 731 1.1 fvdl } 732 1.1 fvdl $2->type = DOWNLOAD_CONST; 733 1.1 fvdl initialize_symbol($2); 734 1.1 fvdl $2->info.cinfo->value = download_constant_count++; 735 1.1 fvdl } 736 1.1 fvdl ; 737 1.1 fvdl 738 1.3 fvdl macrodefn_prologue: 739 1.3 fvdl T_DEFINE T_SYMBOL 740 1.3 fvdl { 741 1.3 fvdl if ($2->type != UNINITIALIZED) { 742 1.3 fvdl stop("Re-definition of symbol as a macro", 743 1.3 fvdl EX_DATAERR); 744 1.3 fvdl /* NOTREACHED */ 745 1.3 fvdl } 746 1.3 fvdl cur_symbol = $2; 747 1.3 fvdl cur_symbol->type = MACRO; 748 1.3 fvdl initialize_symbol(cur_symbol); 749 1.3 fvdl } 750 1.3 fvdl ; 751 1.3 fvdl 752 1.3 fvdl macrodefn: 753 1.3 fvdl macrodefn_prologue T_MACROBODY 754 1.3 fvdl { 755 1.3 fvdl add_macro_body($2); 756 1.3 fvdl } 757 1.3 fvdl | macrodefn_prologue '(' macro_arglist ')' T_MACROBODY 758 1.3 fvdl { 759 1.3 fvdl add_macro_body($5); 760 1.3 fvdl cur_symbol->info.macroinfo->narg = $3; 761 1.3 fvdl } 762 1.3 fvdl ; 763 1.3 fvdl 764 1.3 fvdl macro_arglist: 765 1.3 fvdl { 766 1.3 fvdl /* Macros can take no arguments */ 767 1.3 fvdl $$ = 0; 768 1.3 fvdl } 769 1.3 fvdl | T_ARG 770 1.1 fvdl { 771 1.3 fvdl $$ = 1; 772 1.3 fvdl add_macro_arg($1, 0); 773 1.1 fvdl } 774 1.3 fvdl | macro_arglist ',' T_ARG 775 1.1 fvdl { 776 1.3 fvdl if ($1 == 0) { 777 1.6 christos stop("Comma without preceding argument in arg list", 778 1.3 fvdl EX_DATAERR); 779 1.3 fvdl /* NOTREACHED */ 780 1.3 fvdl } 781 1.3 fvdl $$ = $1 + 1; 782 1.3 fvdl add_macro_arg($3, $1); 783 1.1 fvdl } 784 1.1 fvdl ; 785 1.1 fvdl 786 1.1 fvdl scratch_ram: 787 1.1 fvdl T_SRAM '{' 788 1.1 fvdl { 789 1.3 fvdl snprintf(errbuf, sizeof(errbuf), "%s%d", SRAM_SYMNAME, 790 1.3 fvdl num_srams); 791 1.1 fvdl cur_symbol = symtable_get(SRAM_SYMNAME); 792 1.1 fvdl cur_symtype = SRAMLOC; 793 1.1 fvdl cur_symbol->type = SRAMLOC; 794 1.1 fvdl initialize_symbol(cur_symbol); 795 1.1 fvdl } 796 1.1 fvdl reg_address 797 1.1 fvdl { 798 1.1 fvdl sram_or_scb_offset = cur_symbol->info.rinfo->address; 799 1.1 fvdl } 800 1.3 fvdl size 801 1.3 fvdl { 802 1.3 fvdl scb_or_sram_symbol = cur_symbol; 803 1.3 fvdl } 804 1.3 fvdl scb_or_sram_attributes 805 1.1 fvdl '}' 806 1.1 fvdl { 807 1.1 fvdl cur_symbol = NULL; 808 1.3 fvdl scb_or_sram_symbol = NULL; 809 1.1 fvdl } 810 1.1 fvdl ; 811 1.1 fvdl 812 1.1 fvdl scb: 813 1.1 fvdl T_SCB '{' 814 1.1 fvdl { 815 1.1 fvdl cur_symbol = symtable_get(SCB_SYMNAME); 816 1.1 fvdl cur_symtype = SCBLOC; 817 1.1 fvdl if (cur_symbol->type != UNINITIALIZED) { 818 1.1 fvdl stop("Only one SRAM definition allowed", 819 1.1 fvdl EX_SOFTWARE); 820 1.1 fvdl /* NOTREACHED */ 821 1.1 fvdl } 822 1.1 fvdl cur_symbol->type = SCBLOC; 823 1.1 fvdl initialize_symbol(cur_symbol); 824 1.3 fvdl /* 64 bytes of SCB space */ 825 1.3 fvdl cur_symbol->info.rinfo->size = 64; 826 1.1 fvdl } 827 1.1 fvdl reg_address 828 1.1 fvdl { 829 1.1 fvdl sram_or_scb_offset = cur_symbol->info.rinfo->address; 830 1.1 fvdl } 831 1.3 fvdl size 832 1.3 fvdl { 833 1.3 fvdl scb_or_sram_symbol = cur_symbol; 834 1.3 fvdl } 835 1.3 fvdl scb_or_sram_attributes 836 1.1 fvdl '}' 837 1.1 fvdl { 838 1.1 fvdl cur_symbol = NULL; 839 1.3 fvdl scb_or_sram_symbol = NULL; 840 1.1 fvdl } 841 1.1 fvdl ; 842 1.1 fvdl 843 1.3 fvdl scb_or_sram_attributes: 844 1.3 fvdl /* NULL definition is okay */ 845 1.3 fvdl | modes 846 1.3 fvdl | scb_or_sram_reg_list 847 1.3 fvdl | modes scb_or_sram_reg_list 848 1.3 fvdl ; 849 1.3 fvdl 850 1.1 fvdl scb_or_sram_reg_list: 851 1.1 fvdl reg_definition 852 1.1 fvdl | scb_or_sram_reg_list reg_definition 853 1.1 fvdl ; 854 1.1 fvdl 855 1.1 fvdl reg_symbol: 856 1.1 fvdl T_SYMBOL 857 1.1 fvdl { 858 1.1 fvdl process_register(&$1); 859 1.1 fvdl $$.symbol = $1; 860 1.1 fvdl $$.offset = 0; 861 1.1 fvdl } 862 1.3 fvdl | T_SYMBOL '[' T_SYMBOL ']' 863 1.3 fvdl { 864 1.3 fvdl process_register(&$1); 865 1.3 fvdl if ($3->type != CONST) { 866 1.3 fvdl stop("register offset must be a constant", EX_DATAERR); 867 1.3 fvdl /* NOTREACHED */ 868 1.3 fvdl } 869 1.3 fvdl if (($3->info.cinfo->value + 1) > $1->info.rinfo->size) { 870 1.3 fvdl stop("Accessing offset beyond range of register", 871 1.3 fvdl EX_DATAERR); 872 1.3 fvdl /* NOTREACHED */ 873 1.3 fvdl } 874 1.3 fvdl $$.symbol = $1; 875 1.3 fvdl $$.offset = $3->info.cinfo->value; 876 1.3 fvdl } 877 1.1 fvdl | T_SYMBOL '[' T_NUMBER ']' 878 1.1 fvdl { 879 1.1 fvdl process_register(&$1); 880 1.1 fvdl if (($3 + 1) > $1->info.rinfo->size) { 881 1.1 fvdl stop("Accessing offset beyond range of register", 882 1.1 fvdl EX_DATAERR); 883 1.1 fvdl /* NOTREACHED */ 884 1.1 fvdl } 885 1.1 fvdl $$.symbol = $1; 886 1.1 fvdl $$.offset = $3; 887 1.1 fvdl } 888 1.1 fvdl | T_A 889 1.1 fvdl { 890 1.3 fvdl if (accumulator.symbol == NULL) { 891 1.1 fvdl stop("No accumulator has been defined", EX_DATAERR); 892 1.1 fvdl /* NOTREACHED */ 893 1.1 fvdl } 894 1.3 fvdl $$.symbol = accumulator.symbol; 895 1.1 fvdl $$.offset = 0; 896 1.1 fvdl } 897 1.1 fvdl ; 898 1.1 fvdl 899 1.1 fvdl destination: 900 1.1 fvdl reg_symbol 901 1.1 fvdl { 902 1.1 fvdl test_writable_symbol($1.symbol); 903 1.1 fvdl $$ = $1; 904 1.1 fvdl } 905 1.1 fvdl ; 906 1.1 fvdl 907 1.1 fvdl immediate: 908 1.1 fvdl expression 909 1.1 fvdl { $$ = $1; } 910 1.1 fvdl ; 911 1.1 fvdl 912 1.1 fvdl immediate_or_a: 913 1.1 fvdl expression 914 1.1 fvdl { 915 1.3 fvdl if ($1.value == 0 && is_download_const(&$1) == 0) { 916 1.3 fvdl snprintf(errbuf, sizeof(errbuf), 917 1.3 fvdl "\nExpression evaluates to 0 and thus " 918 1.3 fvdl "references the accumulator.\n " 919 1.3 fvdl "If this is the desired effect, use 'A' " 920 1.3 fvdl "instead.\n"); 921 1.3 fvdl stop(errbuf, EX_DATAERR); 922 1.3 fvdl } 923 1.1 fvdl $$ = $1; 924 1.1 fvdl } 925 1.1 fvdl | T_A 926 1.1 fvdl { 927 1.1 fvdl SLIST_INIT(&$$.referenced_syms); 928 1.3 fvdl symlist_add(&$$.referenced_syms, accumulator.symbol, 929 1.3 fvdl SYMLIST_INSERT_HEAD); 930 1.1 fvdl $$.value = 0; 931 1.1 fvdl } 932 1.1 fvdl ; 933 1.1 fvdl 934 1.1 fvdl source: 935 1.1 fvdl reg_symbol 936 1.1 fvdl { 937 1.1 fvdl test_readable_symbol($1.symbol); 938 1.1 fvdl $$ = $1; 939 1.1 fvdl } 940 1.1 fvdl ; 941 1.1 fvdl 942 1.1 fvdl opt_source: 943 1.1 fvdl { 944 1.1 fvdl $$.symbol = NULL; 945 1.1 fvdl $$.offset = 0; 946 1.1 fvdl } 947 1.1 fvdl | ',' source 948 1.1 fvdl { $$ = $2; } 949 1.1 fvdl ; 950 1.1 fvdl 951 1.1 fvdl ret: 952 1.1 fvdl { $$ = 0; } 953 1.1 fvdl | T_RET 954 1.1 fvdl { $$ = 1; } 955 1.1 fvdl ; 956 1.1 fvdl 957 1.3 fvdl set_src_mode: 958 1.3 fvdl T_SET_SRC_MODE T_NUMBER ';' 959 1.3 fvdl { 960 1.3 fvdl src_mode = $2; 961 1.3 fvdl } 962 1.3 fvdl ; 963 1.3 fvdl 964 1.3 fvdl set_dst_mode: 965 1.3 fvdl T_SET_DST_MODE T_NUMBER ';' 966 1.3 fvdl { 967 1.3 fvdl dst_mode = $2; 968 1.3 fvdl } 969 1.3 fvdl ; 970 1.3 fvdl 971 1.3 fvdl critical_section_start: 972 1.3 fvdl T_BEGIN_CS ';' 973 1.3 fvdl { 974 1.3 fvdl critical_section_t *cs; 975 1.3 fvdl 976 1.3 fvdl if (in_critical_section != FALSE) { 977 1.3 fvdl stop("Critical Section within Critical Section", 978 1.3 fvdl EX_DATAERR); 979 1.3 fvdl /* NOTREACHED */ 980 1.3 fvdl } 981 1.3 fvdl cs = cs_alloc(); 982 1.3 fvdl cs->begin_addr = instruction_ptr; 983 1.3 fvdl in_critical_section = TRUE; 984 1.3 fvdl } 985 1.3 fvdl ; 986 1.3 fvdl 987 1.3 fvdl critical_section_end: 988 1.3 fvdl T_END_CS ';' 989 1.3 fvdl { 990 1.3 fvdl critical_section_t *cs; 991 1.3 fvdl 992 1.3 fvdl if (in_critical_section == FALSE) { 993 1.3 fvdl stop("Unballanced 'end_cs'", EX_DATAERR); 994 1.3 fvdl /* NOTREACHED */ 995 1.3 fvdl } 996 1.3 fvdl cs = TAILQ_LAST(&cs_tailq, cs_tailq); 997 1.3 fvdl cs->end_addr = instruction_ptr; 998 1.3 fvdl in_critical_section = FALSE; 999 1.3 fvdl } 1000 1.3 fvdl ; 1001 1.3 fvdl 1002 1.3 fvdl export: 1003 1.3 fvdl { $$ = 0; } 1004 1.3 fvdl | T_EXPORT 1005 1.3 fvdl { $$ = 1; } 1006 1.3 fvdl ; 1007 1.3 fvdl 1008 1.1 fvdl label: 1009 1.3 fvdl export T_SYMBOL ':' 1010 1.1 fvdl { 1011 1.3 fvdl if ($2->type != UNINITIALIZED) { 1012 1.1 fvdl stop("Program label multiply defined", EX_DATAERR); 1013 1.1 fvdl /* NOTREACHED */ 1014 1.1 fvdl } 1015 1.3 fvdl $2->type = LABEL; 1016 1.3 fvdl initialize_symbol($2); 1017 1.3 fvdl $2->info.linfo->address = instruction_ptr; 1018 1.3 fvdl $2->info.linfo->exported = $1; 1019 1.1 fvdl } 1020 1.1 fvdl ; 1021 1.1 fvdl 1022 1.1 fvdl address: 1023 1.1 fvdl T_SYMBOL 1024 1.1 fvdl { 1025 1.1 fvdl $$.symbol = $1; 1026 1.1 fvdl $$.offset = 0; 1027 1.1 fvdl } 1028 1.1 fvdl | T_SYMBOL '+' T_NUMBER 1029 1.1 fvdl { 1030 1.1 fvdl $$.symbol = $1; 1031 1.1 fvdl $$.offset = $3; 1032 1.1 fvdl } 1033 1.1 fvdl | T_SYMBOL '-' T_NUMBER 1034 1.1 fvdl { 1035 1.1 fvdl $$.symbol = $1; 1036 1.1 fvdl $$.offset = -$3; 1037 1.1 fvdl } 1038 1.1 fvdl | '.' 1039 1.1 fvdl { 1040 1.1 fvdl $$.symbol = NULL; 1041 1.1 fvdl $$.offset = 0; 1042 1.1 fvdl } 1043 1.1 fvdl | '.' '+' T_NUMBER 1044 1.1 fvdl { 1045 1.1 fvdl $$.symbol = NULL; 1046 1.1 fvdl $$.offset = $3; 1047 1.1 fvdl } 1048 1.1 fvdl | '.' '-' T_NUMBER 1049 1.1 fvdl { 1050 1.1 fvdl $$.symbol = NULL; 1051 1.1 fvdl $$.offset = -$3; 1052 1.1 fvdl } 1053 1.1 fvdl ; 1054 1.1 fvdl 1055 1.1 fvdl conditional: 1056 1.1 fvdl T_IF T_CEXPR '{' 1057 1.1 fvdl { 1058 1.1 fvdl scope_t *new_scope; 1059 1.1 fvdl 1060 1.1 fvdl add_conditional($2); 1061 1.1 fvdl new_scope = scope_alloc(); 1062 1.1 fvdl new_scope->type = SCOPE_IF; 1063 1.1 fvdl new_scope->begin_addr = instruction_ptr; 1064 1.1 fvdl new_scope->func_num = $2->info.condinfo->func_num; 1065 1.1 fvdl } 1066 1.1 fvdl | T_ELSE T_IF T_CEXPR '{' 1067 1.1 fvdl { 1068 1.1 fvdl scope_t *new_scope; 1069 1.1 fvdl scope_t *scope_context; 1070 1.1 fvdl scope_t *last_scope; 1071 1.1 fvdl 1072 1.1 fvdl /* 1073 1.1 fvdl * Ensure that the previous scope is either an 1074 1.1 fvdl * if or and else if. 1075 1.1 fvdl */ 1076 1.1 fvdl scope_context = SLIST_FIRST(&scope_stack); 1077 1.1 fvdl last_scope = TAILQ_LAST(&scope_context->inner_scope, 1078 1.1 fvdl scope_tailq); 1079 1.1 fvdl if (last_scope == NULL 1080 1.1 fvdl || last_scope->type == T_ELSE) { 1081 1.1 fvdl 1082 1.1 fvdl stop("'else if' without leading 'if'", EX_DATAERR); 1083 1.1 fvdl /* NOTREACHED */ 1084 1.1 fvdl } 1085 1.1 fvdl add_conditional($3); 1086 1.1 fvdl new_scope = scope_alloc(); 1087 1.1 fvdl new_scope->type = SCOPE_ELSE_IF; 1088 1.1 fvdl new_scope->begin_addr = instruction_ptr; 1089 1.1 fvdl new_scope->func_num = $3->info.condinfo->func_num; 1090 1.1 fvdl } 1091 1.1 fvdl | T_ELSE '{' 1092 1.1 fvdl { 1093 1.1 fvdl scope_t *new_scope; 1094 1.1 fvdl scope_t *scope_context; 1095 1.1 fvdl scope_t *last_scope; 1096 1.1 fvdl 1097 1.1 fvdl /* 1098 1.1 fvdl * Ensure that the previous scope is either an 1099 1.1 fvdl * if or and else if. 1100 1.1 fvdl */ 1101 1.1 fvdl scope_context = SLIST_FIRST(&scope_stack); 1102 1.1 fvdl last_scope = TAILQ_LAST(&scope_context->inner_scope, 1103 1.1 fvdl scope_tailq); 1104 1.1 fvdl if (last_scope == NULL 1105 1.1 fvdl || last_scope->type == SCOPE_ELSE) { 1106 1.1 fvdl 1107 1.1 fvdl stop("'else' without leading 'if'", EX_DATAERR); 1108 1.1 fvdl /* NOTREACHED */ 1109 1.1 fvdl } 1110 1.1 fvdl new_scope = scope_alloc(); 1111 1.1 fvdl new_scope->type = SCOPE_ELSE; 1112 1.1 fvdl new_scope->begin_addr = instruction_ptr; 1113 1.1 fvdl } 1114 1.1 fvdl ; 1115 1.1 fvdl 1116 1.1 fvdl conditional: 1117 1.1 fvdl '}' 1118 1.1 fvdl { 1119 1.1 fvdl scope_t *scope_context; 1120 1.1 fvdl 1121 1.1 fvdl scope_context = SLIST_FIRST(&scope_stack); 1122 1.1 fvdl if (scope_context->type == SCOPE_ROOT) { 1123 1.1 fvdl stop("Unexpected '}' encountered", EX_DATAERR); 1124 1.1 fvdl /* NOTREACHED */ 1125 1.1 fvdl } 1126 1.1 fvdl 1127 1.1 fvdl scope_context->end_addr = instruction_ptr; 1128 1.1 fvdl 1129 1.1 fvdl /* Pop the scope */ 1130 1.1 fvdl SLIST_REMOVE_HEAD(&scope_stack, scope_stack_links); 1131 1.1 fvdl 1132 1.1 fvdl process_scope(scope_context); 1133 1.1 fvdl 1134 1.1 fvdl if (SLIST_FIRST(&scope_stack) == NULL) { 1135 1.1 fvdl stop("Unexpected '}' encountered", EX_DATAERR); 1136 1.1 fvdl /* NOTREACHED */ 1137 1.1 fvdl } 1138 1.1 fvdl } 1139 1.1 fvdl ; 1140 1.1 fvdl 1141 1.1 fvdl f1_opcode: 1142 1.1 fvdl T_AND { $$ = AIC_OP_AND; } 1143 1.1 fvdl | T_XOR { $$ = AIC_OP_XOR; } 1144 1.1 fvdl | T_ADD { $$ = AIC_OP_ADD; } 1145 1.1 fvdl | T_ADC { $$ = AIC_OP_ADC; } 1146 1.1 fvdl ; 1147 1.1 fvdl 1148 1.1 fvdl code: 1149 1.1 fvdl f1_opcode destination ',' immediate_or_a opt_source ret ';' 1150 1.1 fvdl { 1151 1.1 fvdl format_1_instr($1, &$2, &$4, &$5, $6); 1152 1.1 fvdl } 1153 1.1 fvdl ; 1154 1.1 fvdl 1155 1.1 fvdl code: 1156 1.1 fvdl T_OR reg_symbol ',' immediate_or_a opt_source ret ';' 1157 1.1 fvdl { 1158 1.1 fvdl format_1_instr(AIC_OP_OR, &$2, &$4, &$5, $6); 1159 1.1 fvdl } 1160 1.1 fvdl ; 1161 1.1 fvdl 1162 1.1 fvdl code: 1163 1.1 fvdl T_INC destination opt_source ret ';' 1164 1.1 fvdl { 1165 1.1 fvdl expression_t immed; 1166 1.1 fvdl 1167 1.1 fvdl make_expression(&immed, 1); 1168 1.1 fvdl format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); 1169 1.1 fvdl } 1170 1.1 fvdl ; 1171 1.1 fvdl 1172 1.1 fvdl code: 1173 1.1 fvdl T_DEC destination opt_source ret ';' 1174 1.1 fvdl { 1175 1.1 fvdl expression_t immed; 1176 1.1 fvdl 1177 1.1 fvdl make_expression(&immed, -1); 1178 1.1 fvdl format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); 1179 1.1 fvdl } 1180 1.1 fvdl ; 1181 1.1 fvdl 1182 1.1 fvdl code: 1183 1.1 fvdl T_CLC ret ';' 1184 1.1 fvdl { 1185 1.1 fvdl expression_t immed; 1186 1.1 fvdl 1187 1.1 fvdl make_expression(&immed, -1); 1188 1.1 fvdl format_1_instr(AIC_OP_ADD, &none, &immed, &allzeros, $2); 1189 1.1 fvdl } 1190 1.1 fvdl | T_CLC T_MVI destination ',' immediate_or_a ret ';' 1191 1.1 fvdl { 1192 1.1 fvdl format_1_instr(AIC_OP_ADD, &$3, &$5, &allzeros, $6); 1193 1.1 fvdl } 1194 1.1 fvdl ; 1195 1.1 fvdl 1196 1.1 fvdl code: 1197 1.1 fvdl T_STC ret ';' 1198 1.1 fvdl { 1199 1.1 fvdl expression_t immed; 1200 1.1 fvdl 1201 1.1 fvdl make_expression(&immed, 1); 1202 1.1 fvdl format_1_instr(AIC_OP_ADD, &none, &immed, &allones, $2); 1203 1.1 fvdl } 1204 1.1 fvdl | T_STC destination ret ';' 1205 1.1 fvdl { 1206 1.1 fvdl expression_t immed; 1207 1.1 fvdl 1208 1.1 fvdl make_expression(&immed, 1); 1209 1.1 fvdl format_1_instr(AIC_OP_ADD, &$2, &immed, &allones, $3); 1210 1.1 fvdl } 1211 1.1 fvdl ; 1212 1.1 fvdl 1213 1.1 fvdl code: 1214 1.1 fvdl T_BMOV destination ',' source ',' immediate ret ';' 1215 1.1 fvdl { 1216 1.1 fvdl format_1_instr(AIC_OP_BMOV, &$2, &$6, &$4, $7); 1217 1.1 fvdl } 1218 1.1 fvdl ; 1219 1.1 fvdl 1220 1.1 fvdl code: 1221 1.1 fvdl T_MOV destination ',' source ret ';' 1222 1.1 fvdl { 1223 1.1 fvdl expression_t immed; 1224 1.1 fvdl 1225 1.3 fvdl make_expression(&immed, 1); 1226 1.3 fvdl format_1_instr(AIC_OP_BMOV, &$2, &immed, &$4, $5); 1227 1.3 fvdl } 1228 1.3 fvdl ; 1229 1.3 fvdl 1230 1.3 fvdl code: 1231 1.3 fvdl T_MVI destination ',' immediate ret ';' 1232 1.3 fvdl { 1233 1.3 fvdl if ($4.value == 0 1234 1.3 fvdl && is_download_const(&$4) == 0) { 1235 1.3 fvdl expression_t immed; 1236 1.3 fvdl 1237 1.3 fvdl /* 1238 1.3 fvdl * Allow move immediates of 0 so that macros, 1239 1.3 fvdl * that can't know the immediate's value and 1240 1.3 fvdl * otherwise compensate, still work. 1241 1.3 fvdl */ 1242 1.3 fvdl make_expression(&immed, 1); 1243 1.3 fvdl format_1_instr(AIC_OP_BMOV, &$2, &immed, &allzeros, $5); 1244 1.3 fvdl } else { 1245 1.3 fvdl format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5); 1246 1.3 fvdl } 1247 1.1 fvdl } 1248 1.1 fvdl ; 1249 1.1 fvdl 1250 1.1 fvdl code: 1251 1.3 fvdl T_NOT destination opt_source ret ';' 1252 1.1 fvdl { 1253 1.3 fvdl expression_t immed; 1254 1.3 fvdl 1255 1.3 fvdl make_expression(&immed, 0xff); 1256 1.3 fvdl format_1_instr(AIC_OP_XOR, &$2, &immed, &$3, $4); 1257 1.1 fvdl } 1258 1.1 fvdl ; 1259 1.1 fvdl 1260 1.1 fvdl code: 1261 1.1 fvdl T_CLR destination ret ';' 1262 1.1 fvdl { 1263 1.1 fvdl expression_t immed; 1264 1.1 fvdl 1265 1.1 fvdl make_expression(&immed, 0xff); 1266 1.1 fvdl format_1_instr(AIC_OP_AND, &$2, &immed, &allzeros, $3); 1267 1.1 fvdl } 1268 1.1 fvdl ; 1269 1.1 fvdl 1270 1.1 fvdl code: 1271 1.1 fvdl T_NOP ret ';' 1272 1.1 fvdl { 1273 1.1 fvdl expression_t immed; 1274 1.1 fvdl 1275 1.1 fvdl make_expression(&immed, 0xff); 1276 1.1 fvdl format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, $2); 1277 1.1 fvdl } 1278 1.1 fvdl ; 1279 1.1 fvdl 1280 1.1 fvdl code: 1281 1.1 fvdl T_RET ';' 1282 1.1 fvdl { 1283 1.1 fvdl expression_t immed; 1284 1.1 fvdl 1285 1.1 fvdl make_expression(&immed, 0xff); 1286 1.1 fvdl format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, TRUE); 1287 1.1 fvdl } 1288 1.1 fvdl ; 1289 1.1 fvdl 1290 1.1 fvdl /* 1291 1.1 fvdl * This grammer differs from the one in the aic7xxx 1292 1.1 fvdl * reference manual since the grammer listed there is 1293 1.1 fvdl * ambiguous and causes a shift/reduce conflict. 1294 1.1 fvdl * It also seems more logical as the "immediate" 1295 1.1 fvdl * argument is listed as the second arg like the 1296 1.1 fvdl * other formats. 1297 1.1 fvdl */ 1298 1.1 fvdl 1299 1.1 fvdl f2_opcode: 1300 1.1 fvdl T_SHL { $$ = AIC_OP_SHL; } 1301 1.1 fvdl | T_SHR { $$ = AIC_OP_SHR; } 1302 1.1 fvdl | T_ROL { $$ = AIC_OP_ROL; } 1303 1.1 fvdl | T_ROR { $$ = AIC_OP_ROR; } 1304 1.1 fvdl ; 1305 1.1 fvdl 1306 1.1 fvdl code: 1307 1.1 fvdl f2_opcode destination ',' expression opt_source ret ';' 1308 1.1 fvdl { 1309 1.1 fvdl format_2_instr($1, &$2, &$4, &$5, $6); 1310 1.1 fvdl } 1311 1.1 fvdl ; 1312 1.1 fvdl 1313 1.1 fvdl jmp_jc_jnc_call: 1314 1.1 fvdl T_JMP { $$ = AIC_OP_JMP; } 1315 1.1 fvdl | T_JC { $$ = AIC_OP_JC; } 1316 1.1 fvdl | T_JNC { $$ = AIC_OP_JNC; } 1317 1.1 fvdl | T_CALL { $$ = AIC_OP_CALL; } 1318 1.1 fvdl ; 1319 1.1 fvdl 1320 1.1 fvdl jz_jnz: 1321 1.1 fvdl T_JZ { $$ = AIC_OP_JZ; } 1322 1.1 fvdl | T_JNZ { $$ = AIC_OP_JNZ; } 1323 1.1 fvdl ; 1324 1.1 fvdl 1325 1.1 fvdl je_jne: 1326 1.1 fvdl T_JE { $$ = AIC_OP_JE; } 1327 1.1 fvdl | T_JNE { $$ = AIC_OP_JNE; } 1328 1.1 fvdl ; 1329 1.1 fvdl 1330 1.1 fvdl code: 1331 1.1 fvdl jmp_jc_jnc_call address ';' 1332 1.1 fvdl { 1333 1.1 fvdl expression_t immed; 1334 1.1 fvdl 1335 1.1 fvdl make_expression(&immed, 0); 1336 1.1 fvdl format_3_instr($1, &sindex, &immed, &$2); 1337 1.1 fvdl } 1338 1.1 fvdl ; 1339 1.1 fvdl 1340 1.1 fvdl code: 1341 1.1 fvdl T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';' 1342 1.1 fvdl { 1343 1.1 fvdl format_3_instr($5, &$2, &$4, &$6); 1344 1.1 fvdl } 1345 1.1 fvdl ; 1346 1.1 fvdl 1347 1.1 fvdl code: 1348 1.1 fvdl T_TEST source ',' immediate_or_a jz_jnz address ';' 1349 1.1 fvdl { 1350 1.1 fvdl format_3_instr($5, &$2, &$4, &$6); 1351 1.1 fvdl } 1352 1.1 fvdl ; 1353 1.1 fvdl 1354 1.1 fvdl code: 1355 1.1 fvdl T_CMP source ',' immediate_or_a je_jne address ';' 1356 1.1 fvdl { 1357 1.1 fvdl format_3_instr($5, &$2, &$4, &$6); 1358 1.1 fvdl } 1359 1.1 fvdl ; 1360 1.1 fvdl 1361 1.1 fvdl code: 1362 1.1 fvdl T_MOV source jmp_jc_jnc_call address ';' 1363 1.1 fvdl { 1364 1.1 fvdl expression_t immed; 1365 1.1 fvdl 1366 1.1 fvdl make_expression(&immed, 0); 1367 1.1 fvdl format_3_instr($3, &$2, &immed, &$4); 1368 1.1 fvdl } 1369 1.1 fvdl ; 1370 1.1 fvdl 1371 1.1 fvdl code: 1372 1.1 fvdl T_MVI immediate jmp_jc_jnc_call address ';' 1373 1.1 fvdl { 1374 1.1 fvdl format_3_instr($3, &allzeros, &$2, &$4); 1375 1.1 fvdl } 1376 1.1 fvdl ; 1377 1.1 fvdl 1378 1.1 fvdl %% 1379 1.1 fvdl 1380 1.1 fvdl static void 1381 1.3 fvdl process_field(int field_type, symbol_t *sym, int value) 1382 1.1 fvdl { 1383 1.1 fvdl /* 1384 1.1 fvdl * Add the current register to its 1385 1.1 fvdl * symbol list, if it already exists, 1386 1.1 fvdl * warn if we are setting it to a 1387 1.1 fvdl * different value, or in the bit to 1388 1.1 fvdl * the "allowed bits" of this register. 1389 1.1 fvdl */ 1390 1.1 fvdl if (sym->type == UNINITIALIZED) { 1391 1.3 fvdl sym->type = field_type; 1392 1.1 fvdl initialize_symbol(sym); 1393 1.3 fvdl sym->info.finfo->value = value; 1394 1.3 fvdl if (field_type != ENUM_ENTRY) { 1395 1.3 fvdl if (field_type != MASK && value == 0) { 1396 1.3 fvdl stop("Empty Field, or Enum", EX_DATAERR); 1397 1.1 fvdl /* NOTREACHED */ 1398 1.1 fvdl } 1399 1.3 fvdl sym->info.finfo->value = value; 1400 1.3 fvdl sym->info.finfo->mask = value; 1401 1.3 fvdl } else if (field_symbol != NULL) { 1402 1.3 fvdl sym->info.finfo->mask = field_symbol->info.finfo->value; 1403 1.3 fvdl } else { 1404 1.3 fvdl sym->info.finfo->mask = 0xFF; 1405 1.1 fvdl } 1406 1.3 fvdl } else if (sym->type != field_type) { 1407 1.3 fvdl stop("Field definition mirrors a definition of the same " 1408 1.1 fvdl " name, but a different type", EX_DATAERR); 1409 1.1 fvdl /* NOTREACHED */ 1410 1.3 fvdl } else if (value != sym->info.finfo->value) { 1411 1.3 fvdl stop("Field redefined with a conflicting value", EX_DATAERR); 1412 1.1 fvdl /* NOTREACHED */ 1413 1.1 fvdl } 1414 1.1 fvdl /* Fail if this symbol is already listed */ 1415 1.3 fvdl if (symlist_search(&(sym->info.finfo->symrefs), 1416 1.1 fvdl cur_symbol->name) != NULL) { 1417 1.3 fvdl stop("Field defined multiple times for register", EX_DATAERR); 1418 1.1 fvdl /* NOTREACHED */ 1419 1.1 fvdl } 1420 1.3 fvdl symlist_add(&(sym->info.finfo->symrefs), cur_symbol, 1421 1.1 fvdl SYMLIST_INSERT_HEAD); 1422 1.3 fvdl cur_symbol->info.rinfo->valid_bitmask |= sym->info.finfo->mask; 1423 1.1 fvdl cur_symbol->info.rinfo->typecheck_masks = TRUE; 1424 1.3 fvdl symlist_add(&(cur_symbol->info.rinfo->fields), sym, SYMLIST_SORT); 1425 1.1 fvdl } 1426 1.1 fvdl 1427 1.1 fvdl static void 1428 1.3 fvdl initialize_symbol(symbol_t *symbol) 1429 1.1 fvdl { 1430 1.1 fvdl switch (symbol->type) { 1431 1.3 fvdl case UNINITIALIZED: 1432 1.1 fvdl stop("Call to initialize_symbol with type field unset", 1433 1.1 fvdl EX_SOFTWARE); 1434 1.1 fvdl /* NOTREACHED */ 1435 1.1 fvdl break; 1436 1.3 fvdl case REGISTER: 1437 1.3 fvdl case SRAMLOC: 1438 1.3 fvdl case SCBLOC: 1439 1.1 fvdl symbol->info.rinfo = 1440 1.1 fvdl (struct reg_info *)malloc(sizeof(struct reg_info)); 1441 1.1 fvdl if (symbol->info.rinfo == NULL) { 1442 1.1 fvdl stop("Can't create register info", EX_SOFTWARE); 1443 1.1 fvdl /* NOTREACHED */ 1444 1.1 fvdl } 1445 1.1 fvdl memset(symbol->info.rinfo, 0, 1446 1.1 fvdl sizeof(struct reg_info)); 1447 1.3 fvdl SLIST_INIT(&(symbol->info.rinfo->fields)); 1448 1.3 fvdl /* 1449 1.3 fvdl * Default to allowing access in all register modes 1450 1.3 fvdl * or to the mode specified by the SCB or SRAM space 1451 1.3 fvdl * we are in. 1452 1.3 fvdl */ 1453 1.3 fvdl if (scb_or_sram_symbol != NULL) 1454 1.3 fvdl symbol->info.rinfo->modes = 1455 1.3 fvdl scb_or_sram_symbol->info.rinfo->modes; 1456 1.3 fvdl else 1457 1.3 fvdl symbol->info.rinfo->modes = ~0; 1458 1.1 fvdl break; 1459 1.3 fvdl case ALIAS: 1460 1.1 fvdl symbol->info.ainfo = 1461 1.1 fvdl (struct alias_info *)malloc(sizeof(struct alias_info)); 1462 1.1 fvdl if (symbol->info.ainfo == NULL) { 1463 1.1 fvdl stop("Can't create alias info", EX_SOFTWARE); 1464 1.1 fvdl /* NOTREACHED */ 1465 1.1 fvdl } 1466 1.1 fvdl memset(symbol->info.ainfo, 0, 1467 1.1 fvdl sizeof(struct alias_info)); 1468 1.1 fvdl break; 1469 1.3 fvdl case MASK: 1470 1.3 fvdl case FIELD: 1471 1.3 fvdl case ENUM: 1472 1.3 fvdl case ENUM_ENTRY: 1473 1.3 fvdl symbol->info.finfo = 1474 1.3 fvdl (struct field_info *)malloc(sizeof(struct field_info)); 1475 1.3 fvdl if (symbol->info.finfo == NULL) { 1476 1.3 fvdl stop("Can't create field info", EX_SOFTWARE); 1477 1.1 fvdl /* NOTREACHED */ 1478 1.1 fvdl } 1479 1.3 fvdl memset(symbol->info.finfo, 0, sizeof(struct field_info)); 1480 1.3 fvdl SLIST_INIT(&(symbol->info.finfo->symrefs)); 1481 1.1 fvdl break; 1482 1.3 fvdl case CONST: 1483 1.3 fvdl case DOWNLOAD_CONST: 1484 1.1 fvdl symbol->info.cinfo = 1485 1.1 fvdl (struct const_info *)malloc(sizeof(struct const_info)); 1486 1.1 fvdl if (symbol->info.cinfo == NULL) { 1487 1.1 fvdl stop("Can't create alias info", EX_SOFTWARE); 1488 1.1 fvdl /* NOTREACHED */ 1489 1.1 fvdl } 1490 1.1 fvdl memset(symbol->info.cinfo, 0, 1491 1.1 fvdl sizeof(struct const_info)); 1492 1.1 fvdl break; 1493 1.1 fvdl case LABEL: 1494 1.1 fvdl symbol->info.linfo = 1495 1.1 fvdl (struct label_info *)malloc(sizeof(struct label_info)); 1496 1.1 fvdl if (symbol->info.linfo == NULL) { 1497 1.1 fvdl stop("Can't create label info", EX_SOFTWARE); 1498 1.1 fvdl /* NOTREACHED */ 1499 1.1 fvdl } 1500 1.1 fvdl memset(symbol->info.linfo, 0, 1501 1.1 fvdl sizeof(struct label_info)); 1502 1.1 fvdl break; 1503 1.1 fvdl case CONDITIONAL: 1504 1.1 fvdl symbol->info.condinfo = 1505 1.1 fvdl (struct cond_info *)malloc(sizeof(struct cond_info)); 1506 1.1 fvdl if (symbol->info.condinfo == NULL) { 1507 1.1 fvdl stop("Can't create conditional info", EX_SOFTWARE); 1508 1.1 fvdl /* NOTREACHED */ 1509 1.1 fvdl } 1510 1.1 fvdl memset(symbol->info.condinfo, 0, 1511 1.1 fvdl sizeof(struct cond_info)); 1512 1.1 fvdl break; 1513 1.3 fvdl case MACRO: 1514 1.4 perry symbol->info.macroinfo = 1515 1.3 fvdl (struct macro_info *)malloc(sizeof(struct macro_info)); 1516 1.3 fvdl if (symbol->info.macroinfo == NULL) { 1517 1.3 fvdl stop("Can't create macro info", EX_SOFTWARE); 1518 1.3 fvdl /* NOTREACHED */ 1519 1.3 fvdl } 1520 1.3 fvdl memset(symbol->info.macroinfo, 0, 1521 1.3 fvdl sizeof(struct macro_info)); 1522 1.3 fvdl STAILQ_INIT(&symbol->info.macroinfo->args); 1523 1.3 fvdl break; 1524 1.1 fvdl default: 1525 1.1 fvdl stop("Call to initialize_symbol with invalid symbol type", 1526 1.1 fvdl EX_SOFTWARE); 1527 1.1 fvdl /* NOTREACHED */ 1528 1.1 fvdl break; 1529 1.1 fvdl } 1530 1.1 fvdl } 1531 1.1 fvdl 1532 1.1 fvdl static void 1533 1.3 fvdl add_macro_arg(const char *argtext, int argnum) 1534 1.3 fvdl { 1535 1.3 fvdl struct macro_arg *marg; 1536 1.3 fvdl int i; 1537 1.3 fvdl int retval; 1538 1.4 perry 1539 1.3 fvdl 1540 1.3 fvdl if (cur_symbol == NULL || cur_symbol->type != MACRO) { 1541 1.3 fvdl stop("Invalid current symbol for adding macro arg", 1542 1.3 fvdl EX_SOFTWARE); 1543 1.3 fvdl /* NOTREACHED */ 1544 1.3 fvdl } 1545 1.3 fvdl 1546 1.3 fvdl marg = (struct macro_arg *)malloc(sizeof(*marg)); 1547 1.3 fvdl if (marg == NULL) { 1548 1.3 fvdl stop("Can't create macro_arg structure", EX_SOFTWARE); 1549 1.3 fvdl /* NOTREACHED */ 1550 1.3 fvdl } 1551 1.3 fvdl marg->replacement_text = NULL; 1552 1.3 fvdl retval = snprintf(regex_pattern, sizeof(regex_pattern), 1553 1.3 fvdl "[^-/A-Za-z0-9_](%s)([^-/A-Za-z0-9_]|$)", 1554 1.3 fvdl argtext); 1555 1.3 fvdl if (retval >= sizeof(regex_pattern)) { 1556 1.3 fvdl stop("Regex text buffer too small for arg", 1557 1.3 fvdl EX_SOFTWARE); 1558 1.3 fvdl /* NOTREACHED */ 1559 1.3 fvdl } 1560 1.3 fvdl retval = regcomp(&marg->arg_regex, regex_pattern, REG_EXTENDED); 1561 1.3 fvdl if (retval != 0) { 1562 1.3 fvdl stop("Regex compilation failed", EX_SOFTWARE); 1563 1.3 fvdl /* NOTREACHED */ 1564 1.3 fvdl } 1565 1.3 fvdl STAILQ_INSERT_TAIL(&cur_symbol->info.macroinfo->args, marg, links); 1566 1.3 fvdl } 1567 1.3 fvdl 1568 1.3 fvdl static void 1569 1.3 fvdl add_macro_body(const char *bodytext) 1570 1.3 fvdl { 1571 1.3 fvdl if (cur_symbol == NULL || cur_symbol->type != MACRO) { 1572 1.3 fvdl stop("Invalid current symbol for adding macro arg", 1573 1.3 fvdl EX_SOFTWARE); 1574 1.3 fvdl /* NOTREACHED */ 1575 1.3 fvdl } 1576 1.3 fvdl cur_symbol->info.macroinfo->body = strdup(bodytext); 1577 1.3 fvdl if (cur_symbol->info.macroinfo->body == NULL) { 1578 1.3 fvdl stop("Can't duplicate macro body text", EX_SOFTWARE); 1579 1.3 fvdl /* NOTREACHED */ 1580 1.3 fvdl } 1581 1.3 fvdl } 1582 1.3 fvdl 1583 1.3 fvdl static void 1584 1.3 fvdl process_register(symbol_t **p_symbol) 1585 1.1 fvdl { 1586 1.1 fvdl symbol_t *symbol = *p_symbol; 1587 1.1 fvdl 1588 1.1 fvdl if (symbol->type == UNINITIALIZED) { 1589 1.3 fvdl snprintf(errbuf, sizeof(errbuf), "Undefined register %s", 1590 1.1 fvdl symbol->name); 1591 1.3 fvdl stop(errbuf, EX_DATAERR); 1592 1.1 fvdl /* NOTREACHED */ 1593 1.1 fvdl } else if (symbol->type == ALIAS) { 1594 1.1 fvdl *p_symbol = symbol->info.ainfo->parent; 1595 1.1 fvdl } else if ((symbol->type != REGISTER) 1596 1.1 fvdl && (symbol->type != SCBLOC) 1597 1.1 fvdl && (symbol->type != SRAMLOC)) { 1598 1.3 fvdl snprintf(errbuf, sizeof(errbuf), 1599 1.1 fvdl "Specified symbol %s is not a register", 1600 1.1 fvdl symbol->name); 1601 1.3 fvdl stop(errbuf, EX_DATAERR); 1602 1.1 fvdl } 1603 1.1 fvdl } 1604 1.1 fvdl 1605 1.1 fvdl static void 1606 1.3 fvdl format_1_instr(int opcode, symbol_ref_t *dest, expression_t *immed, 1607 1.3 fvdl symbol_ref_t *src, int ret) 1608 1.1 fvdl { 1609 1.1 fvdl struct instruction *instr; 1610 1.1 fvdl struct ins_format1 *f1_instr; 1611 1.1 fvdl 1612 1.1 fvdl if (src->symbol == NULL) 1613 1.1 fvdl src = dest; 1614 1.1 fvdl 1615 1.1 fvdl /* Test register permissions */ 1616 1.1 fvdl test_writable_symbol(dest->symbol); 1617 1.1 fvdl test_readable_symbol(src->symbol); 1618 1.1 fvdl 1619 1.1 fvdl /* Ensure that immediate makes sense for this destination */ 1620 1.1 fvdl type_check(dest->symbol, immed, opcode); 1621 1.1 fvdl 1622 1.1 fvdl /* Allocate sequencer space for the instruction and fill it out */ 1623 1.1 fvdl instr = seq_alloc(); 1624 1.1 fvdl f1_instr = &instr->format.format1; 1625 1.1 fvdl f1_instr->ret = ret ? 1 : 0; 1626 1.1 fvdl f1_instr->opcode = opcode; 1627 1.1 fvdl f1_instr->destination = dest->symbol->info.rinfo->address 1628 1.1 fvdl + dest->offset; 1629 1.1 fvdl f1_instr->source = src->symbol->info.rinfo->address 1630 1.1 fvdl + src->offset; 1631 1.1 fvdl f1_instr->immediate = immed->value; 1632 1.1 fvdl 1633 1.1 fvdl if (is_download_const(immed)) 1634 1.1 fvdl f1_instr->parity = 1; 1635 1.3 fvdl else if (dest->symbol == mode_ptr.symbol) { 1636 1.3 fvdl u_int src_value; 1637 1.3 fvdl u_int dst_value; 1638 1.3 fvdl 1639 1.3 fvdl /* 1640 1.3 fvdl * Attempt to update mode information if 1641 1.3 fvdl * we are operating on the mode register. 1642 1.3 fvdl */ 1643 1.3 fvdl if (src->symbol == allones.symbol) 1644 1.3 fvdl src_value = 0xFF; 1645 1.3 fvdl else if (src->symbol == allzeros.symbol) 1646 1.3 fvdl src_value = 0; 1647 1.3 fvdl else if (src->symbol == mode_ptr.symbol) 1648 1.3 fvdl src_value = (dst_mode << 4) | src_mode; 1649 1.3 fvdl else 1650 1.3 fvdl goto cant_update; 1651 1.1 fvdl 1652 1.3 fvdl switch (opcode) { 1653 1.3 fvdl case AIC_OP_AND: 1654 1.3 fvdl dst_value = src_value & immed->value; 1655 1.3 fvdl break; 1656 1.3 fvdl case AIC_OP_XOR: 1657 1.3 fvdl dst_value = src_value ^ immed->value; 1658 1.3 fvdl break; 1659 1.3 fvdl case AIC_OP_ADD: 1660 1.3 fvdl dst_value = (src_value + immed->value) & 0xFF; 1661 1.3 fvdl break; 1662 1.3 fvdl case AIC_OP_OR: 1663 1.3 fvdl dst_value = src_value | immed->value; 1664 1.3 fvdl break; 1665 1.3 fvdl case AIC_OP_BMOV: 1666 1.3 fvdl dst_value = src_value; 1667 1.3 fvdl break; 1668 1.3 fvdl default: 1669 1.3 fvdl goto cant_update; 1670 1.3 fvdl } 1671 1.3 fvdl src_mode = dst_value & 0xF; 1672 1.3 fvdl dst_mode = (dst_value >> 4) & 0xF; 1673 1.3 fvdl } 1674 1.3 fvdl 1675 1.3 fvdl cant_update: 1676 1.1 fvdl symlist_free(&immed->referenced_syms); 1677 1.1 fvdl instruction_ptr++; 1678 1.1 fvdl } 1679 1.1 fvdl 1680 1.1 fvdl static void 1681 1.3 fvdl format_2_instr(int opcode, symbol_ref_t *dest, expression_t *places, 1682 1.3 fvdl symbol_ref_t *src, int ret) 1683 1.1 fvdl { 1684 1.1 fvdl struct instruction *instr; 1685 1.1 fvdl struct ins_format2 *f2_instr; 1686 1.3 fvdl uint8_t shift_control; 1687 1.1 fvdl 1688 1.1 fvdl if (src->symbol == NULL) 1689 1.1 fvdl src = dest; 1690 1.1 fvdl 1691 1.1 fvdl /* Test register permissions */ 1692 1.1 fvdl test_writable_symbol(dest->symbol); 1693 1.1 fvdl test_readable_symbol(src->symbol); 1694 1.1 fvdl 1695 1.1 fvdl /* Allocate sequencer space for the instruction and fill it out */ 1696 1.1 fvdl instr = seq_alloc(); 1697 1.1 fvdl f2_instr = &instr->format.format2; 1698 1.1 fvdl f2_instr->ret = ret ? 1 : 0; 1699 1.1 fvdl f2_instr->opcode = AIC_OP_ROL; 1700 1.1 fvdl f2_instr->destination = dest->symbol->info.rinfo->address 1701 1.1 fvdl + dest->offset; 1702 1.1 fvdl f2_instr->source = src->symbol->info.rinfo->address 1703 1.1 fvdl + src->offset; 1704 1.1 fvdl if (places->value > 8 || places->value <= 0) { 1705 1.1 fvdl stop("illegal shift value", EX_DATAERR); 1706 1.1 fvdl /* NOTREACHED */ 1707 1.1 fvdl } 1708 1.1 fvdl switch (opcode) { 1709 1.1 fvdl case AIC_OP_SHL: 1710 1.1 fvdl if (places->value == 8) 1711 1.1 fvdl shift_control = 0xf0; 1712 1.1 fvdl else 1713 1.1 fvdl shift_control = (places->value << 4) | places->value; 1714 1.1 fvdl break; 1715 1.1 fvdl case AIC_OP_SHR: 1716 1.1 fvdl if (places->value == 8) { 1717 1.1 fvdl shift_control = 0xf8; 1718 1.1 fvdl } else { 1719 1.1 fvdl shift_control = (places->value << 4) 1720 1.1 fvdl | (8 - places->value) 1721 1.1 fvdl | 0x08; 1722 1.1 fvdl } 1723 1.1 fvdl break; 1724 1.1 fvdl case AIC_OP_ROL: 1725 1.1 fvdl shift_control = places->value & 0x7; 1726 1.1 fvdl break; 1727 1.1 fvdl case AIC_OP_ROR: 1728 1.1 fvdl shift_control = (8 - places->value) | 0x08; 1729 1.1 fvdl break; 1730 1.1 fvdl default: 1731 1.1 fvdl shift_control = 0; /* Quiet Compiler */ 1732 1.1 fvdl stop("Invalid shift operation specified", EX_SOFTWARE); 1733 1.1 fvdl /* NOTREACHED */ 1734 1.1 fvdl break; 1735 1.1 fvdl }; 1736 1.1 fvdl f2_instr->shift_control = shift_control; 1737 1.1 fvdl symlist_free(&places->referenced_syms); 1738 1.1 fvdl instruction_ptr++; 1739 1.1 fvdl } 1740 1.1 fvdl 1741 1.1 fvdl static void 1742 1.3 fvdl format_3_instr(int opcode, symbol_ref_t *src, 1743 1.3 fvdl expression_t *immed, symbol_ref_t *address) 1744 1.1 fvdl { 1745 1.1 fvdl struct instruction *instr; 1746 1.1 fvdl struct ins_format3 *f3_instr; 1747 1.1 fvdl int addr; 1748 1.1 fvdl 1749 1.1 fvdl /* Test register permissions */ 1750 1.1 fvdl test_readable_symbol(src->symbol); 1751 1.1 fvdl 1752 1.1 fvdl /* Ensure that immediate makes sense for this source */ 1753 1.1 fvdl type_check(src->symbol, immed, opcode); 1754 1.1 fvdl 1755 1.1 fvdl /* Allocate sequencer space for the instruction and fill it out */ 1756 1.1 fvdl instr = seq_alloc(); 1757 1.1 fvdl f3_instr = &instr->format.format3; 1758 1.1 fvdl if (address->symbol == NULL) { 1759 1.8 andvar /* 'dot' reference. Use the current instruction pointer */ 1760 1.1 fvdl addr = instruction_ptr + address->offset; 1761 1.1 fvdl } else if (address->symbol->type == UNINITIALIZED) { 1762 1.1 fvdl /* forward reference */ 1763 1.1 fvdl addr = address->offset; 1764 1.1 fvdl instr->patch_label = address->symbol; 1765 1.1 fvdl } else 1766 1.1 fvdl addr = address->symbol->info.linfo->address + address->offset; 1767 1.1 fvdl f3_instr->opcode = opcode; 1768 1.1 fvdl f3_instr->address = addr; 1769 1.1 fvdl f3_instr->source = src->symbol->info.rinfo->address 1770 1.1 fvdl + src->offset; 1771 1.1 fvdl f3_instr->immediate = immed->value; 1772 1.1 fvdl 1773 1.1 fvdl if (is_download_const(immed)) 1774 1.1 fvdl f3_instr->parity = 1; 1775 1.1 fvdl 1776 1.1 fvdl symlist_free(&immed->referenced_syms); 1777 1.1 fvdl instruction_ptr++; 1778 1.1 fvdl } 1779 1.1 fvdl 1780 1.1 fvdl static void 1781 1.3 fvdl test_readable_symbol(symbol_t *symbol) 1782 1.1 fvdl { 1783 1.4 perry 1784 1.3 fvdl if ((symbol->info.rinfo->modes & (0x1 << src_mode)) == 0) { 1785 1.3 fvdl snprintf(errbuf, sizeof(errbuf), 1786 1.3 fvdl "Register %s unavailable in source reg mode %d", 1787 1.3 fvdl symbol->name, src_mode); 1788 1.3 fvdl stop(errbuf, EX_DATAERR); 1789 1.3 fvdl } 1790 1.3 fvdl 1791 1.1 fvdl if (symbol->info.rinfo->mode == WO) { 1792 1.1 fvdl stop("Write Only register specified as source", 1793 1.1 fvdl EX_DATAERR); 1794 1.1 fvdl /* NOTREACHED */ 1795 1.1 fvdl } 1796 1.1 fvdl } 1797 1.1 fvdl 1798 1.1 fvdl static void 1799 1.3 fvdl test_writable_symbol(symbol_t *symbol) 1800 1.1 fvdl { 1801 1.4 perry 1802 1.3 fvdl if ((symbol->info.rinfo->modes & (0x1 << dst_mode)) == 0) { 1803 1.3 fvdl snprintf(errbuf, sizeof(errbuf), 1804 1.3 fvdl "Register %s unavailable in destination reg mode %d", 1805 1.3 fvdl symbol->name, dst_mode); 1806 1.3 fvdl stop(errbuf, EX_DATAERR); 1807 1.3 fvdl } 1808 1.3 fvdl 1809 1.1 fvdl if (symbol->info.rinfo->mode == RO) { 1810 1.1 fvdl stop("Read Only register specified as destination", 1811 1.1 fvdl EX_DATAERR); 1812 1.1 fvdl /* NOTREACHED */ 1813 1.1 fvdl } 1814 1.1 fvdl } 1815 1.1 fvdl 1816 1.1 fvdl static void 1817 1.3 fvdl type_check(symbol_t *symbol, expression_t *expression, int opcode) 1818 1.1 fvdl { 1819 1.1 fvdl symbol_node_t *node; 1820 1.1 fvdl int and_op; 1821 1.1 fvdl 1822 1.1 fvdl and_op = FALSE; 1823 1.1 fvdl if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || AIC_OP_JZ) 1824 1.1 fvdl and_op = TRUE; 1825 1.1 fvdl 1826 1.1 fvdl /* 1827 1.1 fvdl * Make sure that we aren't attempting to write something 1828 1.1 fvdl * that hasn't been defined. If this is an and operation, 1829 1.1 fvdl * this is a mask, so "undefined" bits are okay. 1830 1.1 fvdl */ 1831 1.1 fvdl if (and_op == FALSE 1832 1.1 fvdl && (expression->value & ~symbol->info.rinfo->valid_bitmask) != 0) { 1833 1.3 fvdl snprintf(errbuf, sizeof(errbuf), 1834 1.1 fvdl "Invalid bit(s) 0x%x in immediate written to %s", 1835 1.1 fvdl expression->value & ~symbol->info.rinfo->valid_bitmask, 1836 1.1 fvdl symbol->name); 1837 1.3 fvdl stop(errbuf, EX_DATAERR); 1838 1.1 fvdl /* NOTREACHED */ 1839 1.1 fvdl } 1840 1.1 fvdl 1841 1.1 fvdl /* 1842 1.1 fvdl * Now make sure that all of the symbols referenced by the 1843 1.1 fvdl * expression are defined for this register. 1844 1.1 fvdl */ 1845 1.3 fvdl if (symbol->info.rinfo->typecheck_masks != FALSE) { 1846 1.3 fvdl for(node = expression->referenced_syms.slh_first; 1847 1.3 fvdl node != NULL; 1848 1.3 fvdl node = node->links.sle_next) { 1849 1.1 fvdl if ((node->symbol->type == MASK 1850 1.3 fvdl || node->symbol->type == FIELD 1851 1.3 fvdl || node->symbol->type == ENUM 1852 1.3 fvdl || node->symbol->type == ENUM_ENTRY) 1853 1.3 fvdl && symlist_search(&node->symbol->info.finfo->symrefs, 1854 1.1 fvdl symbol->name) == NULL) { 1855 1.3 fvdl snprintf(errbuf, sizeof(errbuf), 1856 1.3 fvdl "Invalid field or mask %s " 1857 1.1 fvdl "for register %s", 1858 1.1 fvdl node->symbol->name, symbol->name); 1859 1.3 fvdl stop(errbuf, EX_DATAERR); 1860 1.1 fvdl /* NOTREACHED */ 1861 1.1 fvdl } 1862 1.1 fvdl } 1863 1.1 fvdl } 1864 1.1 fvdl } 1865 1.1 fvdl 1866 1.1 fvdl static void 1867 1.3 fvdl make_expression(expression_t *immed, int value) 1868 1.1 fvdl { 1869 1.1 fvdl SLIST_INIT(&immed->referenced_syms); 1870 1.1 fvdl immed->value = value & 0xff; 1871 1.1 fvdl } 1872 1.1 fvdl 1873 1.1 fvdl static void 1874 1.3 fvdl add_conditional(symbol_t *symbol) 1875 1.1 fvdl { 1876 1.1 fvdl static int numfuncs; 1877 1.1 fvdl 1878 1.1 fvdl if (numfuncs == 0) { 1879 1.1 fvdl /* add a special conditional, "0" */ 1880 1.1 fvdl symbol_t *false_func; 1881 1.1 fvdl 1882 1.1 fvdl false_func = symtable_get("0"); 1883 1.1 fvdl if (false_func->type != UNINITIALIZED) { 1884 1.1 fvdl stop("Conditional expression '0' " 1885 1.1 fvdl "conflicts with a symbol", EX_DATAERR); 1886 1.1 fvdl /* NOTREACHED */ 1887 1.1 fvdl } 1888 1.1 fvdl false_func->type = CONDITIONAL; 1889 1.1 fvdl initialize_symbol(false_func); 1890 1.1 fvdl false_func->info.condinfo->func_num = numfuncs++; 1891 1.1 fvdl symlist_add(&patch_functions, false_func, SYMLIST_INSERT_HEAD); 1892 1.1 fvdl } 1893 1.1 fvdl 1894 1.1 fvdl /* This condition has occurred before */ 1895 1.1 fvdl if (symbol->type == CONDITIONAL) 1896 1.1 fvdl return; 1897 1.1 fvdl 1898 1.1 fvdl if (symbol->type != UNINITIALIZED) { 1899 1.1 fvdl stop("Conditional expression conflicts with a symbol", 1900 1.1 fvdl EX_DATAERR); 1901 1.1 fvdl /* NOTREACHED */ 1902 1.1 fvdl } 1903 1.1 fvdl 1904 1.1 fvdl symbol->type = CONDITIONAL; 1905 1.1 fvdl initialize_symbol(symbol); 1906 1.1 fvdl symbol->info.condinfo->func_num = numfuncs++; 1907 1.1 fvdl symlist_add(&patch_functions, symbol, SYMLIST_INSERT_HEAD); 1908 1.1 fvdl } 1909 1.1 fvdl 1910 1.3 fvdl static void 1911 1.3 fvdl add_version(const char *verstring) 1912 1.3 fvdl { 1913 1.3 fvdl const char prefix[] = " * "; 1914 1.3 fvdl int newlen; 1915 1.3 fvdl int oldlen; 1916 1.3 fvdl 1917 1.7 jdolecek if (verstring[0] == '$') 1918 1.7 jdolecek verstring++; 1919 1.7 jdolecek 1920 1.3 fvdl newlen = strlen(verstring) + strlen(prefix); 1921 1.3 fvdl oldlen = 0; 1922 1.3 fvdl if (versions != NULL) 1923 1.3 fvdl oldlen = strlen(versions); 1924 1.3 fvdl versions = realloc(versions, newlen + oldlen + 2); 1925 1.3 fvdl if (versions == NULL) 1926 1.3 fvdl stop("Can't allocate version string", EX_SOFTWARE); 1927 1.3 fvdl strcpy(&versions[oldlen], prefix); 1928 1.3 fvdl strcpy(&versions[oldlen + strlen(prefix)], verstring); 1929 1.3 fvdl versions[newlen + oldlen] = '\n'; 1930 1.3 fvdl versions[newlen + oldlen + 1] = '\0'; 1931 1.3 fvdl } 1932 1.3 fvdl 1933 1.1 fvdl void 1934 1.3 fvdl yyerror(const char *string) 1935 1.1 fvdl { 1936 1.1 fvdl stop(string, EX_DATAERR); 1937 1.1 fvdl } 1938 1.1 fvdl 1939 1.1 fvdl static int 1940 1.3 fvdl is_download_const(expression_t *immed) 1941 1.1 fvdl { 1942 1.3 fvdl if ((immed->referenced_syms.slh_first != NULL) 1943 1.3 fvdl && (immed->referenced_syms.slh_first->symbol->type == DOWNLOAD_CONST)) 1944 1.1 fvdl return (TRUE); 1945 1.1 fvdl 1946 1.1 fvdl return (FALSE); 1947 1.1 fvdl } 1948