aicasm_gram.y revision 102668
1103285Sikob%{ 2113584Ssimokawa/* 3103285Sikob * Parser for the Aic7xxx SCSI Host adapter sequencer assembler. 4103285Sikob * 5103285Sikob * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. 6103285Sikob * Copyright (c) 2001, 2002 Adaptec Inc. 7103285Sikob * All rights reserved. 8103285Sikob * 9103285Sikob * Redistribution and use in source and binary forms, with or without 10103285Sikob * modification, are permitted provided that the following conditions 11103285Sikob * are met: 12103285Sikob * 1. Redistributions of source code must retain the above copyright 13103285Sikob * notice, this list of conditions, and the following disclaimer, 14103285Sikob * without modification. 15103285Sikob * 2. Redistributions in binary form must reproduce at minimum a disclaimer 16103285Sikob * substantially similar to the "NO WARRANTY" disclaimer below 17106802Ssimokawa * ("Disclaimer") and any redistribution must be conditioned upon 18103285Sikob * including a substantially similar Disclaimer requirement for further 19103285Sikob * binary redistribution. 20103285Sikob * 3. Neither the names of the above-listed copyright holders nor the names 21103285Sikob * of any contributors may be used to endorse or promote products derived 22103285Sikob * from this software without specific prior written permission. 23103285Sikob * 24103285Sikob * Alternatively, this software may be distributed under the terms of the 25103285Sikob * GNU General Public License ("GPL") version 2 as published by the Free 26103285Sikob * Software Foundation. 27103285Sikob * 28103285Sikob * NO WARRANTY 29103285Sikob * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30103285Sikob * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31103285Sikob * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 32103285Sikob * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33103285Sikob * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34103285Sikob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35103285Sikob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36103285Sikob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 37106802Ssimokawa * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 38103285Sikob * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39103285Sikob * POSSIBILITY OF SUCH DAMAGES. 40103285Sikob * 41103285Sikob * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#21 $ 42103285Sikob * 43103285Sikob * $FreeBSD: head/sys/dev/aic7xxx/aicasm/aicasm_gram.y 102668 2002-08-31 06:39:41Z gibbs $ 44103285Sikob */ 45103285Sikob 46109890Ssimokawa#include <sys/types.h> 47103285Sikob 48103285Sikob#include <inttypes.h> 49103285Sikob#include <regex.h> 50103285Sikob#include <stdio.h> 51103285Sikob#include <stdlib.h> 52103285Sikob#include <string.h> 53103285Sikob#include <sysexits.h> 54103285Sikob 55103285Sikob#ifdef __linux__ 56103285Sikob#include "../queue.h" 57103285Sikob#else 58103285Sikob#include <sys/queue.h> 59113584Ssimokawa#endif 60103285Sikob 61103285Sikob#include "aicasm.h" 62103285Sikob#include "aicasm_symbol.h" 63103285Sikob#include "aicasm_insformat.h" 64103285Sikob 65103285Sikobint yylineno; 66103285Sikobchar *yyfilename; 67103285Sikobchar stock_prefix[] = "aic_"; 68103285Sikobchar *prefix = stock_prefix; 69103285Sikobchar *patch_arg_list; 70103285Sikobchar *versions; 71103285Sikobstatic char errbuf[255]; 72113584Ssimokawastatic char regex_pattern[255]; 73103285Sikobstatic symbol_t *cur_symbol; 74103285Sikobstatic symbol_t *field_symbol; 75103285Sikobstatic symbol_t *scb_or_sram_symbol; 76103285Sikobstatic symtype cur_symtype; 77109179Ssimokawastatic symbol_ref_t accumulator; 78109179Ssimokawastatic symbol_ref_t mode_ptr; 79103285Sikobstatic symbol_ref_t allones; 80106802Ssimokawastatic symbol_ref_t allzeros; 81103285Sikobstatic symbol_ref_t none; 82103285Sikobstatic symbol_ref_t sindex; 83113584Ssimokawastatic int instruction_ptr; 84103285Sikobstatic int num_srams; 85103285Sikobstatic int sram_or_scb_offset; 86113584Ssimokawastatic int download_constant_count; 87103285Sikobstatic int in_critical_section; 88103285Sikobstatic u_int enum_increment; 89103285Sikobstatic u_int enum_next_value; 90103285Sikob 91103285Sikobstatic void process_field(int field_type, symbol_t *sym, int mask); 92103285Sikobstatic void initialize_symbol(symbol_t *symbol); 93103285Sikobstatic void add_macro_arg(const char *argtext, int position); 94103285Sikobstatic void add_macro_body(const char *bodytext); 95103285Sikobstatic void process_register(symbol_t **p_symbol); 96113584Ssimokawastatic void format_1_instr(int opcode, symbol_ref_t *dest, 97116376Ssimokawa expression_t *immed, symbol_ref_t *src, int ret); 98116376Ssimokawastatic void format_2_instr(int opcode, symbol_ref_t *dest, 99103285Sikob expression_t *places, symbol_ref_t *src, int ret); 100103285Sikobstatic void format_3_instr(int opcode, symbol_ref_t *src, 101103285Sikob expression_t *immed, symbol_ref_t *address); 102103285Sikobstatic void test_readable_symbol(symbol_t *symbol); 103103285Sikobstatic void test_writable_symbol(symbol_t *symbol); 104103285Sikobstatic void type_check(symbol_t *symbol, expression_t *expression, int and_op); 105103285Sikobstatic void make_expression(expression_t *immed, int value); 106103285Sikobstatic void add_conditional(symbol_t *symbol); 107103285Sikobstatic void add_version(const char *verstring); 108103285Sikobstatic int is_download_const(expression_t *immed); 109103285Sikob 110103285Sikob#define SRAM_SYMNAME "SRAM_BASE" 111103285Sikob#define SCB_SYMNAME "SCB_BASE" 112103285Sikob%} 113103285Sikob 114103285Sikob%union { 115103285Sikob u_int value; 116103285Sikob char *str; 117103285Sikob symbol_t *sym; 118103285Sikob symbol_ref_t sym_ref; 119103285Sikob expression_t expression; 120103285Sikob} 121103285Sikob 122103285Sikob%token T_REGISTER 123103285Sikob 124103285Sikob%token <value> T_CONST 125103285Sikob 126103285Sikob%token T_EXPORT 127103285Sikob 128113584Ssimokawa%token T_DOWNLOAD 129103285Sikob 130106789Ssimokawa%token T_SCB 131103285Sikob 132103285Sikob%token T_SRAM 133103285Sikob 134103285Sikob%token T_ALIAS 135103285Sikob 136103285Sikob%token T_SIZE 137103285Sikob 138103285Sikob%token T_EXPR_LSHIFT 139103285Sikob 140103285Sikob%token T_EXPR_RSHIFT 141113584Ssimokawa 142103285Sikob%token <value> T_ADDRESS 143113584Ssimokawa 144103285Sikob%token T_ACCESS_MODE 145103285Sikob 146103285Sikob%token T_MODES 147103285Sikob 148113584Ssimokawa%token T_DEFINE 149113584Ssimokawa 150113584Ssimokawa%token T_SET_SRC_MODE 151103285Sikob 152113584Ssimokawa%token T_SET_DST_MODE 153103285Sikob 154103285Sikob%token <value> T_MODE 155103285Sikob 156103285Sikob%token T_BEGIN_CS 157103285Sikob 158113584Ssimokawa%token T_END_CS 159113584Ssimokawa 160113584Ssimokawa%token T_FIELD 161103285Sikob 162103285Sikob%token T_ENUM 163103285Sikob 164103285Sikob%token T_MASK 165103285Sikob 166103285Sikob%token <value> T_NUMBER 167103285Sikob 168103285Sikob%token <str> T_PATH T_STRING T_ARG T_MACROBODY 169103285Sikob 170103285Sikob%token <sym> T_CEXPR 171103285Sikob 172112523Ssimokawa%token T_EOF T_INCLUDE T_VERSION T_PREFIX T_PATCH_ARG_LIST 173103285Sikob 174103285Sikob%token <value> T_SHR T_SHL T_ROR T_ROL 175103285Sikob 176103285Sikob%token <value> T_MVI T_MOV T_CLR T_BMOV 177103285Sikob 178103285Sikob%token <value> T_JMP T_JC T_JNC T_JE T_JNE T_JNZ T_JZ T_CALL 179103285Sikob 180103285Sikob%token <value> T_ADD T_ADC 181103285Sikob 182103285Sikob%token <value> T_INC T_DEC 183103285Sikob 184103285Sikob%token <value> T_STC T_CLC 185103285Sikob 186103285Sikob%token <value> T_CMP T_NOT T_XOR 187103285Sikob 188103285Sikob%token <value> T_TEST T_AND 189103285Sikob 190103285Sikob%token <value> T_OR 191103285Sikob 192103285Sikob%token T_RET 193103285Sikob 194103285Sikob%token T_NOP 195103285Sikob 196103285Sikob%token T_ACCUM T_ALLONES T_ALLZEROS T_NONE T_SINDEX T_MODE_PTR 197103285Sikob 198103285Sikob%token T_A 199103285Sikob 200103285Sikob%token <sym> T_SYMBOL 201113584Ssimokawa 202103285Sikob%token T_NL 203103285Sikob 204103285Sikob%token T_IF T_ELSE T_ELSE_IF T_ENDIF 205103285Sikob 206103285Sikob%type <sym_ref> reg_symbol address destination source opt_source 207103285Sikob 208103285Sikob%type <expression> expression immediate immediate_or_a 209103285Sikob 210103285Sikob%type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne 211103285Sikob 212103285Sikob%type <value> numerical_value mode_value mode_list macro_arglist 213103285Sikob 214103285Sikob%left '|' 215103285Sikob%left '&' 216103285Sikob%left T_EXPR_LSHIFT T_EXPR_RSHIFT 217103285Sikob%left '+' '-' 218103285Sikob%left '*' '/' 219103285Sikob%right '~' 220103285Sikob%nonassoc UMINUS 221103285Sikob%% 222103285Sikob 223103285Sikobprogram: 224103285Sikob include 225103285Sikob| program include 226103285Sikob| prefix 227103285Sikob| program prefix 228103285Sikob| patch_arg_list 229103285Sikob| program patch_arg_list 230103285Sikob| version 231103285Sikob| program version 232103285Sikob| register 233103285Sikob| program register 234103285Sikob| constant 235103285Sikob| program constant 236103285Sikob| macrodefn 237103285Sikob| program macrodefn 238103285Sikob| scratch_ram 239103285Sikob| program scratch_ram 240103285Sikob| scb 241103285Sikob| program scb 242103285Sikob| label 243103285Sikob| program label 244103285Sikob| set_src_mode 245103285Sikob| program set_src_mode 246103285Sikob| set_dst_mode 247103285Sikob| program set_dst_mode 248103285Sikob| critical_section_start 249103285Sikob| program critical_section_start 250103285Sikob| critical_section_end 251103285Sikob| program critical_section_end 252103285Sikob| conditional 253103285Sikob| program conditional 254103285Sikob| code 255103285Sikob| program code 256103285Sikob; 257103285Sikob 258103285Sikobinclude: 259103285Sikob T_INCLUDE '<' T_PATH '>' 260103285Sikob { 261103285Sikob include_file($3, BRACKETED_INCLUDE); 262103285Sikob } 263103285Sikob| T_INCLUDE '"' T_PATH '"' 264103285Sikob { 265106790Ssimokawa include_file($3, QUOTED_INCLUDE); 266106790Ssimokawa } 267103285Sikob; 268103285Sikob 269103285Sikobprefix: 270103285Sikob T_PREFIX '=' T_STRING 271103285Sikob { 272103285Sikob if (prefix != stock_prefix) 273103285Sikob stop("Prefix multiply defined", 274103285Sikob EX_DATAERR); 275103285Sikob prefix = strdup($3); 276103285Sikob if (prefix == NULL) 277103285Sikob stop("Unable to record prefix", EX_SOFTWARE); 278103285Sikob } 279103285Sikob; 280103285Sikob 281103285Sikobpatch_arg_list: 282103285Sikob T_PATCH_ARG_LIST '=' T_STRING 283103285Sikob { 284103285Sikob if (patch_arg_list != NULL) 285103285Sikob stop("Patch argument list multiply defined", 286103285Sikob EX_DATAERR); 287103285Sikob patch_arg_list = strdup($3); 288103285Sikob if (patch_arg_list == NULL) 289103285Sikob stop("Unable to record patch arg list", EX_SOFTWARE); 290103285Sikob } 291103285Sikob; 292103285Sikob 293103285Sikobversion: 294103285Sikob T_VERSION '=' T_STRING 295103285Sikob { add_version($3); } 296109280Ssimokawa; 297103285Sikob 298107653Ssimokawaregister: 299103285Sikob T_REGISTER { cur_symtype = REGISTER; } reg_definition 300107653Ssimokawa; 301107653Ssimokawa 302107653Ssimokawareg_definition: 303103285Sikob T_SYMBOL '{' 304103285Sikob { 305103285Sikob if ($1->type != UNINITIALIZED) { 306103285Sikob stop("Register multiply defined", EX_DATAERR); 307106790Ssimokawa /* NOTREACHED */ 308106790Ssimokawa } 309103285Sikob cur_symbol = $1; 310108500Ssimokawa cur_symbol->type = cur_symtype; 311108500Ssimokawa initialize_symbol(cur_symbol); 312103285Sikob } 313103285Sikob reg_attribute_list 314108500Ssimokawa '}' 315108500Ssimokawa { 316108500Ssimokawa /* 317103285Sikob * Default to allowing everything in for registers 318103285Sikob * with no bit or mask definitions. 319108500Ssimokawa */ 320103285Sikob if (cur_symbol->info.rinfo->valid_bitmask == 0) 321103285Sikob cur_symbol->info.rinfo->valid_bitmask = 0xFF; 322103285Sikob 323109280Ssimokawa if (cur_symbol->info.rinfo->size == 0) 324103285Sikob cur_symbol->info.rinfo->size = 1; 325108500Ssimokawa 326109280Ssimokawa /* 327109280Ssimokawa * This might be useful for registers too. 328108527Ssimokawa */ 329109280Ssimokawa if (cur_symbol->type != REGISTER) { 330108527Ssimokawa if (cur_symbol->info.rinfo->address == 0) 331108527Ssimokawa cur_symbol->info.rinfo->address = 332108500Ssimokawa sram_or_scb_offset; 333108500Ssimokawa sram_or_scb_offset += 334108500Ssimokawa cur_symbol->info.rinfo->size; 335108500Ssimokawa } 336108500Ssimokawa cur_symbol = NULL; 337109280Ssimokawa } 338109280Ssimokawa; 339108500Ssimokawa 340109280Ssimokawareg_attribute_list: 341108500Ssimokawa reg_attribute 342108500Ssimokawa| reg_attribute_list reg_attribute 343108500Ssimokawa; 344108500Ssimokawa 345108500Ssimokawareg_attribute: 346108500Ssimokawa reg_address 347108500Ssimokawa| size 348103285Sikob| access_mode 349103285Sikob| modes 350103285Sikob| field_defn 351103285Sikob| enum_defn 352103285Sikob| mask_defn 353103285Sikob| alias 354103285Sikob| accumulator 355103285Sikob| mode_pointer 356103285Sikob| allones 357103285Sikob| allzeros 358103285Sikob| none 359103285Sikob| sindex 360103285Sikob; 361103285Sikob 362103285Sikobreg_address: 363103285Sikob T_ADDRESS T_NUMBER 364103285Sikob { 365103285Sikob cur_symbol->info.rinfo->address = $2; 366103285Sikob } 367103285Sikob; 368103285Sikob 369103285Sikobsize: 370103285Sikob T_SIZE T_NUMBER 371103285Sikob { 372103285Sikob cur_symbol->info.rinfo->size = $2; 373103285Sikob if (scb_or_sram_symbol != NULL) { 374103285Sikob u_int max_addr; 375103285Sikob u_int sym_max_addr; 376103285Sikob 377103285Sikob max_addr = scb_or_sram_symbol->info.rinfo->address 378103285Sikob + scb_or_sram_symbol->info.rinfo->size; 379103285Sikob sym_max_addr = cur_symbol->info.rinfo->address 380103285Sikob + cur_symbol->info.rinfo->size; 381103285Sikob 382103285Sikob if (sym_max_addr > max_addr) 383103285Sikob stop("SCB or SRAM space exhausted", EX_DATAERR); 384103285Sikob } 385103285Sikob } 386103285Sikob; 387103285Sikob 388103285Sikobaccess_mode: 389103285Sikob T_ACCESS_MODE T_MODE 390103285Sikob { 391103285Sikob cur_symbol->info.rinfo->mode = $2; 392103285Sikob } 393103285Sikob; 394103285Sikob 395103285Sikobmodes: 396103285Sikob T_MODES mode_list 397103285Sikob { 398103285Sikob cur_symbol->info.rinfo->modes = $2; 399103285Sikob } 400103285Sikob; 401106790Ssimokawa 402108530Ssimokawamode_list: 403108530Ssimokawa mode_value 404103285Sikob { 405108530Ssimokawa $$ = $1; 406108530Ssimokawa } 407108530Ssimokawa| mode_list ',' mode_value 408108530Ssimokawa { 409108530Ssimokawa $$ = $1 | $3; 410108530Ssimokawa } 411108530Ssimokawa; 412108530Ssimokawa 413108530Ssimokawamode_value: 414108530Ssimokawa T_NUMBER 415108530Ssimokawa { 416108530Ssimokawa if ($1 > 4) { 417108530Ssimokawa stop("Valid register modes range between 0 and 4.", 418108530Ssimokawa EX_DATAERR); 419108530Ssimokawa /* NOTREACHED */ 420108530Ssimokawa } 421108530Ssimokawa 422108530Ssimokawa $$ = (0x1 << $1); 423108530Ssimokawa } 424108530Ssimokawa| T_SYMBOL 425108530Ssimokawa { 426108530Ssimokawa symbol_t *symbol; 427108701Ssimokawa 428108701Ssimokawa symbol = $1; 429108530Ssimokawa if (symbol->type != CONST) { 430108530Ssimokawa stop("Only \"const\" symbols allowed in " 431108530Ssimokawa "mode definitions.", EX_DATAERR); 432108530Ssimokawa /* NOTREACHED */ 433108530Ssimokawa } 434108530Ssimokawa if (symbol->info.cinfo->value > 4) { 435108530Ssimokawa stop("Valid register modes range between 0 and 4.", 436108530Ssimokawa EX_DATAERR); 437108530Ssimokawa /* NOTREACHED */ 438108530Ssimokawa } 439108530Ssimokawa $$ = (0x1 << symbol->info.cinfo->value); 440108701Ssimokawa } 441108701Ssimokawa; 442108530Ssimokawa 443108530Ssimokawafield_defn: 444108530Ssimokawa T_FIELD 445108530Ssimokawa { 446108530Ssimokawa field_symbol = NULL; 447108530Ssimokawa enum_next_value = 0; 448108530Ssimokawa enum_increment = 1; 449108530Ssimokawa } 450108530Ssimokawa '{' enum_entry_list '}' 451108530Ssimokawa| T_FIELD T_SYMBOL expression 452108530Ssimokawa { 453108530Ssimokawa process_field(FIELD, $2, $3.value); 454108530Ssimokawa field_symbol = $2; 455108530Ssimokawa enum_next_value = 0; 456108530Ssimokawa enum_increment = 0x01 << (ffs($3.value) - 1); 457108530Ssimokawa } 458108530Ssimokawa '{' enum_entry_list '}' 459108530Ssimokawa| T_FIELD T_SYMBOL expression 460108530Ssimokawa { 461108530Ssimokawa process_field(FIELD, $2, $3.value); 462108530Ssimokawa } 463108530Ssimokawa; 464108530Ssimokawa 465108530Ssimokawaenum_defn: 466108530Ssimokawa T_ENUM 467108530Ssimokawa { 468108530Ssimokawa field_symbol = NULL; 469108530Ssimokawa enum_next_value = 0; 470108530Ssimokawa enum_increment = 1; 471108530Ssimokawa } 472108530Ssimokawa '{' enum_entry_list '}' 473108530Ssimokawa| T_ENUM T_SYMBOL expression 474108530Ssimokawa { 475108530Ssimokawa process_field(ENUM, $2, $3.value); 476108530Ssimokawa field_symbol = $2; 477108530Ssimokawa enum_next_value = 0; 478108530Ssimokawa enum_increment = 0x01 << (ffs($3.value) - 1); 479108701Ssimokawa } 480103285Sikob '{' enum_entry_list '}' 481103285Sikob; 482103285Sikob 483108701Ssimokawaenum_entry_list: 484108530Ssimokawa enum_entry 485108530Ssimokawa| enum_entry_list ',' enum_entry 486108701Ssimokawa; 487108530Ssimokawa 488108530Ssimokawaenum_entry: 489108530Ssimokawa T_SYMBOL 490108530Ssimokawa { 491108530Ssimokawa process_field(ENUM_ENTRY, $1, enum_next_value); 492108530Ssimokawa enum_next_value += enum_increment; 493108530Ssimokawa } 494108530Ssimokawa| T_SYMBOL expression 495108530Ssimokawa { 496108530Ssimokawa process_field(ENUM_ENTRY, $1, $2.value); 497108530Ssimokawa enum_next_value = $2.value + enum_increment; 498108701Ssimokawa } 499108530Ssimokawa; 500108530Ssimokawa 501108530Ssimokawamask_defn: 502108530Ssimokawa T_MASK T_SYMBOL expression 503108530Ssimokawa { 504108530Ssimokawa process_field(MASK, $2, $3.value); 505108530Ssimokawa } 506108530Ssimokawa; 507108530Ssimokawa 508108530Ssimokawaalias: 509108530Ssimokawa T_ALIAS T_SYMBOL 510108701Ssimokawa { 511108701Ssimokawa if ($2->type != UNINITIALIZED) { 512108701Ssimokawa stop("Re-definition of register alias", 513108701Ssimokawa EX_DATAERR); 514108530Ssimokawa /* NOTREACHED */ 515108530Ssimokawa } 516108701Ssimokawa $2->type = ALIAS; 517108701Ssimokawa initialize_symbol($2); 518108701Ssimokawa $2->info.ainfo->parent = cur_symbol; 519108701Ssimokawa } 520108701Ssimokawa; 521108701Ssimokawa 522108701Ssimokawaaccumulator: 523108701Ssimokawa T_ACCUM 524108701Ssimokawa { 525108701Ssimokawa if (accumulator.symbol != NULL) { 526108701Ssimokawa stop("Only one accumulator definition allowed", 527108530Ssimokawa EX_DATAERR); 528108530Ssimokawa /* NOTREACHED */ 529108530Ssimokawa } 530108530Ssimokawa accumulator.symbol = cur_symbol; 531108701Ssimokawa } 532108530Ssimokawa; 533113584Ssimokawa 534108530Ssimokawamode_pointer: 535108530Ssimokawa T_MODE_PTR 536113584Ssimokawa { 537108530Ssimokawa if (mode_ptr.symbol != NULL) { 538108701Ssimokawa stop("Only one mode pointer definition allowed", 539108530Ssimokawa EX_DATAERR); 540108701Ssimokawa /* NOTREACHED */ 541108530Ssimokawa } 542108642Ssimokawa mode_ptr.symbol = cur_symbol; 543108701Ssimokawa } 544108642Ssimokawa; 545108642Ssimokawa 546108530Ssimokawaallones: 547108530Ssimokawa T_ALLONES 548108530Ssimokawa { 549108701Ssimokawa if (allones.symbol != NULL) { 550108701Ssimokawa stop("Only one definition of allones allowed", 551108701Ssimokawa EX_DATAERR); 552108701Ssimokawa /* NOTREACHED */ 553108701Ssimokawa } 554108701Ssimokawa allones.symbol = cur_symbol; 555108701Ssimokawa } 556108530Ssimokawa; 557108530Ssimokawa 558108530Ssimokawaallzeros: 559108530Ssimokawa T_ALLZEROS 560108530Ssimokawa { 561108530Ssimokawa if (allzeros.symbol != NULL) { 562108530Ssimokawa stop("Only one definition of allzeros allowed", 563108530Ssimokawa EX_DATAERR); 564108530Ssimokawa /* NOTREACHED */ 565108701Ssimokawa } 566108701Ssimokawa allzeros.symbol = cur_symbol; 567108530Ssimokawa } 568108530Ssimokawa; 569108530Ssimokawa 570108530Ssimokawanone: 571108530Ssimokawa T_NONE 572108530Ssimokawa { 573108530Ssimokawa if (none.symbol != NULL) { 574108530Ssimokawa stop("Only one definition of none allowed", 575108530Ssimokawa EX_DATAERR); 576108530Ssimokawa /* NOTREACHED */ 577108530Ssimokawa } 578108530Ssimokawa none.symbol = cur_symbol; 579108530Ssimokawa } 580108530Ssimokawa; 581109814Ssimokawa 582108530Ssimokawasindex: 583113584Ssimokawa T_SINDEX 584113584Ssimokawa { 585113584Ssimokawa if (sindex.symbol != NULL) { 586113584Ssimokawa stop("Only one definition of sindex allowed", 587103285Sikob EX_DATAERR); 588103285Sikob /* NOTREACHED */ 589103285Sikob } 590103285Sikob sindex.symbol = cur_symbol; 591110045Ssimokawa } 592110045Ssimokawa; 593110045Ssimokawa 594110045Ssimokawaexpression: 595110045Ssimokawa expression '|' expression 596110045Ssimokawa { 597110045Ssimokawa $$.value = $1.value | $3.value; 598110045Ssimokawa symlist_merge(&$$.referenced_syms, 599110045Ssimokawa &$1.referenced_syms, 600103285Sikob &$3.referenced_syms); 601103285Sikob } 602103285Sikob| expression '&' expression 603103285Sikob { 604103285Sikob $$.value = $1.value & $3.value; 605103285Sikob symlist_merge(&$$.referenced_syms, 606103285Sikob &$1.referenced_syms, 607103285Sikob &$3.referenced_syms); 608113584Ssimokawa } 609113584Ssimokawa| expression '+' expression 610113584Ssimokawa { 611113584Ssimokawa $$.value = $1.value + $3.value; 612113584Ssimokawa symlist_merge(&$$.referenced_syms, 613103285Sikob &$1.referenced_syms, 614103285Sikob &$3.referenced_syms); 615103285Sikob } 616103285Sikob| expression '-' expression 617103285Sikob { 618113584Ssimokawa $$.value = $1.value - $3.value; 619113584Ssimokawa symlist_merge(&($$.referenced_syms), 620113584Ssimokawa &($1.referenced_syms), 621113584Ssimokawa &($3.referenced_syms)); 622103285Sikob } 623103285Sikob| expression '*' expression 624103285Sikob { 625110593Ssimokawa $$.value = $1.value * $3.value; 626110593Ssimokawa symlist_merge(&($$.referenced_syms), 627103285Sikob &($1.referenced_syms), 628103285Sikob &($3.referenced_syms)); 629103285Sikob } 630103285Sikob| expression '/' expression 631103285Sikob { 632103285Sikob $$.value = $1.value / $3.value; 633103285Sikob symlist_merge(&($$.referenced_syms), 634103285Sikob &($1.referenced_syms), 635103285Sikob &($3.referenced_syms)); 636103285Sikob } 637103285Sikob| expression T_EXPR_LSHIFT expression 638103285Sikob { 639103285Sikob $$.value = $1.value << $3.value; 640103285Sikob symlist_merge(&$$.referenced_syms, 641113584Ssimokawa &$1.referenced_syms, 642103285Sikob &$3.referenced_syms); 643113584Ssimokawa } 644113584Ssimokawa| expression T_EXPR_RSHIFT expression 645113584Ssimokawa { 646113584Ssimokawa $$.value = $1.value >> $3.value; 647103285Sikob symlist_merge(&$$.referenced_syms, 648103285Sikob &$1.referenced_syms, 649103285Sikob &$3.referenced_syms); 650116376Ssimokawa } 651116376Ssimokawa| '(' expression ')' 652103285Sikob { 653103285Sikob $$ = $2; 654103285Sikob } 655103285Sikob| '~' expression 656103285Sikob { 657103285Sikob $$ = $2; 658103285Sikob $$.value = (~$$.value) & 0xFF; 659103285Sikob } 660113584Ssimokawa| '-' expression %prec UMINUS 661103285Sikob { 662103285Sikob $$ = $2; 663103285Sikob $$.value = -$$.value; 664103285Sikob } 665113584Ssimokawa| T_NUMBER 666113584Ssimokawa { 667113584Ssimokawa $$.value = $1; 668113584Ssimokawa SLIST_INIT(&$$.referenced_syms); 669108527Ssimokawa } 670108527Ssimokawa| T_SYMBOL 671113584Ssimokawa { 672113584Ssimokawa symbol_t *symbol; 673113584Ssimokawa 674113584Ssimokawa symbol = $1; 675113584Ssimokawa switch (symbol->type) { 676113584Ssimokawa case ALIAS: 677109736Ssimokawa symbol = $1->info.ainfo->parent; 678109736Ssimokawa case REGISTER: 679113584Ssimokawa case SCBLOC: 680113584Ssimokawa case SRAMLOC: 681108527Ssimokawa $$.value = symbol->info.rinfo->address; 682108527Ssimokawa break; 683108527Ssimokawa case MASK: 684113584Ssimokawa case FIELD: 685108527Ssimokawa case ENUM: 686108527Ssimokawa case ENUM_ENTRY: 687103285Sikob $$.value = symbol->info.finfo->value; 688113584Ssimokawa break; 689108527Ssimokawa case DOWNLOAD_CONST: 690108527Ssimokawa case CONST: 691108527Ssimokawa $$.value = symbol->info.cinfo->value; 692113584Ssimokawa break; 693108527Ssimokawa case UNINITIALIZED: 694108527Ssimokawa default: 695103285Sikob { 696109814Ssimokawa snprintf(errbuf, sizeof(errbuf), 697109814Ssimokawa "Undefined symbol %s referenced", 698109814Ssimokawa symbol->name); 699109814Ssimokawa stop(errbuf, EX_DATAERR); 700103285Sikob /* NOTREACHED */ 701109814Ssimokawa break; 702109814Ssimokawa } 703103285Sikob } 704103285Sikob SLIST_INIT(&$$.referenced_syms); 705103285Sikob symlist_add(&$$.referenced_syms, symbol, SYMLIST_INSERT_HEAD); 706103285Sikob } 707103285Sikob; 708103285Sikob 709103285Sikobconstant: 710103285Sikob T_CONST T_SYMBOL numerical_value 711103285Sikob { 712113584Ssimokawa if ($2->type != UNINITIALIZED) { 713103285Sikob stop("Re-definition of symbol as a constant", 714113584Ssimokawa EX_DATAERR); 715113584Ssimokawa /* NOTREACHED */ 716113584Ssimokawa } 717103285Sikob $2->type = CONST; 718103285Sikob initialize_symbol($2); 719103285Sikob $2->info.cinfo->value = $3; 720103285Sikob } 721106790Ssimokawa| T_CONST T_SYMBOL T_DOWNLOAD 722113584Ssimokawa { 723113584Ssimokawa if ($1) { 724108530Ssimokawa stop("Invalid downloaded constant declaration", 725108530Ssimokawa EX_DATAERR); 726103285Sikob /* NOTREACHED */ 727108530Ssimokawa } 728103285Sikob if ($2->type != UNINITIALIZED) { 729106790Ssimokawa stop("Re-definition of symbol as a downloaded constant", 730106790Ssimokawa EX_DATAERR); 731106790Ssimokawa /* NOTREACHED */ 732103285Sikob } 733103285Sikob $2->type = DOWNLOAD_CONST; 734103285Sikob initialize_symbol($2); 735103285Sikob $2->info.cinfo->value = download_constant_count++; 736103285Sikob } 737106790Ssimokawa; 738106790Ssimokawa 739106790Ssimokawamacrodefn_prologue: 740103285Sikob T_DEFINE T_SYMBOL 741103285Sikob { 742103285Sikob if ($2->type != UNINITIALIZED) { 743103285Sikob stop("Re-definition of symbol as a macro", 744103285Sikob EX_DATAERR); 745108527Ssimokawa /* NOTREACHED */ 746108527Ssimokawa } 747108527Ssimokawa cur_symbol = $2; 748108527Ssimokawa cur_symbol->type = MACRO; 749108527Ssimokawa initialize_symbol(cur_symbol); 750113584Ssimokawa } 751113584Ssimokawa; 752113584Ssimokawa 753113584Ssimokawamacrodefn: 754108527Ssimokawa macrodefn_prologue T_MACROBODY 755108527Ssimokawa { 756108527Ssimokawa add_macro_body($2); 757108527Ssimokawa } 758108527Ssimokawa| macrodefn_prologue '(' macro_arglist ')' T_MACROBODY 759108527Ssimokawa { 760108527Ssimokawa add_macro_body($5); 761108527Ssimokawa cur_symbol->info.macroinfo->narg = $3; 762108527Ssimokawa } 763108527Ssimokawa; 764108527Ssimokawa 765108527Ssimokawamacro_arglist: 766108527Ssimokawa { 767108527Ssimokawa /* Macros can take no arguments */ 768108527Ssimokawa $$ = 0; 769108655Ssimokawa } 770108655Ssimokawa| T_ARG 771108655Ssimokawa { 772108655Ssimokawa $$ = 1; 773108655Ssimokawa add_macro_arg($1, 0); 774108655Ssimokawa } 775106790Ssimokawa| macro_arglist ',' T_ARG 776113584Ssimokawa { 777113584Ssimokawa if ($1 == 0) { 778113584Ssimokawa stop("Comma without preceeding argument in arg list", 779113584Ssimokawa EX_DATAERR); 780113584Ssimokawa /* NOTREACHED */ 781113584Ssimokawa } 782113584Ssimokawa $$ = $1 + 1; 783113584Ssimokawa add_macro_arg($3, $1); 784113584Ssimokawa } 785113584Ssimokawa; 786113584Ssimokawa 787113584Ssimokawanumerical_value: 788113584Ssimokawa T_NUMBER 789113584Ssimokawa { 790113584Ssimokawa $$ = $1; 791113584Ssimokawa } 792113584Ssimokawa| '-' T_NUMBER 793113584Ssimokawa { 794113584Ssimokawa $$ = -$2; 795113584Ssimokawa } 796113584Ssimokawa; 797113584Ssimokawa 798113584Ssimokawascratch_ram: 799113584Ssimokawa T_SRAM '{' 800113584Ssimokawa { 801113584Ssimokawa snprintf(errbuf, sizeof(errbuf), "%s%d", SRAM_SYMNAME, 802113584Ssimokawa num_srams); 803113584Ssimokawa cur_symbol = symtable_get(SRAM_SYMNAME); 804113584Ssimokawa cur_symtype = SRAMLOC; 805113584Ssimokawa cur_symbol->type = SRAMLOC; 806113584Ssimokawa initialize_symbol(cur_symbol); 807113584Ssimokawa } 808106790Ssimokawa reg_address 809103285Sikob { 810103285Sikob sram_or_scb_offset = cur_symbol->info.rinfo->address; 811113584Ssimokawa } 812103285Sikob size 813103285Sikob { 814103285Sikob scb_or_sram_symbol = cur_symbol; 815103285Sikob } 816103285Sikob scb_or_sram_attributes 817103285Sikob '}' 818103285Sikob { 819103285Sikob cur_symbol = NULL; 820108655Ssimokawa scb_or_sram_symbol = NULL; 821103285Sikob } 822103285Sikob; 823103285Sikob 824103285Sikobscb: 825103285Sikob T_SCB '{' 826103285Sikob { 827103285Sikob cur_symbol = symtable_get(SCB_SYMNAME); 828103285Sikob cur_symtype = SCBLOC; 829103285Sikob if (cur_symbol->type != UNINITIALIZED) { 830103285Sikob stop("Only one SRAM definition allowed", 831103285Sikob EX_SOFTWARE); 832103285Sikob /* NOTREACHED */ 833103285Sikob } 834103285Sikob cur_symbol->type = SCBLOC; 835103285Sikob initialize_symbol(cur_symbol); 836103285Sikob /* 64 bytes of SCB space */ 837103285Sikob cur_symbol->info.rinfo->size = 64; 838103285Sikob } 839103285Sikob reg_address 840103285Sikob { 841103285Sikob sram_or_scb_offset = cur_symbol->info.rinfo->address; 842103285Sikob } 843103285Sikob size 844103285Sikob { 845103285Sikob scb_or_sram_symbol = cur_symbol; 846103285Sikob } 847113584Ssimokawa scb_or_sram_attributes 848103285Sikob '}' 849103285Sikob { 850103285Sikob cur_symbol = NULL; 851103285Sikob scb_or_sram_symbol = NULL; 852113584Ssimokawa } 853113584Ssimokawa; 854113584Ssimokawa 855103285Sikobscb_or_sram_attributes: 856103285Sikob /* NULL definition is okay */ 857103285Sikob| modes 858103285Sikob| scb_or_sram_reg_list 859113584Ssimokawa| modes scb_or_sram_reg_list 860103285Sikob; 861103285Sikob 862113584Ssimokawascb_or_sram_reg_list: 863113584Ssimokawa reg_definition 864103285Sikob| scb_or_sram_reg_list reg_definition 865103285Sikob; 866103285Sikob 867113584Ssimokawareg_symbol: 868103285Sikob T_SYMBOL 869103285Sikob { 870103285Sikob process_register(&$1); 871103285Sikob $$.symbol = $1; 872113584Ssimokawa $$.offset = 0; 873113584Ssimokawa } 874113584Ssimokawa| T_SYMBOL '[' T_SYMBOL ']' 875103285Sikob { 876103285Sikob process_register(&$1); 877113584Ssimokawa if ($3->type != CONST) { 878113584Ssimokawa stop("register offset must be a constant", EX_DATAERR); 879103285Sikob /* NOTREACHED */ 880113584Ssimokawa } 881113584Ssimokawa if (($3->info.cinfo->value + 1) > $1->info.rinfo->size) { 882113584Ssimokawa stop("Accessing offset beyond range of register", 883113584Ssimokawa EX_DATAERR); 884113584Ssimokawa /* NOTREACHED */ 885113584Ssimokawa } 886103285Sikob $$.symbol = $1; 887111942Ssimokawa $$.offset = $3->info.cinfo->value; 888103285Sikob } 889103285Sikob| T_SYMBOL '[' T_NUMBER ']' 890113584Ssimokawa { 891113584Ssimokawa process_register(&$1); 892113584Ssimokawa if (($3 + 1) > $1->info.rinfo->size) { 893113584Ssimokawa stop("Accessing offset beyond range of register", 894103285Sikob EX_DATAERR); 895113584Ssimokawa /* NOTREACHED */ 896103285Sikob } 897113584Ssimokawa $$.symbol = $1; 898113584Ssimokawa $$.offset = $3; 899113584Ssimokawa } 900113584Ssimokawa| T_A 901113584Ssimokawa { 902103285Sikob if (accumulator.symbol == NULL) { 903111942Ssimokawa stop("No accumulator has been defined", EX_DATAERR); 904113584Ssimokawa /* NOTREACHED */ 905113584Ssimokawa } 906113584Ssimokawa $$.symbol = accumulator.symbol; 907113584Ssimokawa $$.offset = 0; 908113584Ssimokawa } 909113584Ssimokawa; 910113584Ssimokawa 911113584Ssimokawadestination: 912113584Ssimokawa reg_symbol 913113584Ssimokawa { 914113584Ssimokawa test_writable_symbol($1.symbol); 915111942Ssimokawa $$ = $1; 916111942Ssimokawa } 917113584Ssimokawa; 918113584Ssimokawa 919111942Ssimokawaimmediate: 920111942Ssimokawa expression 921113584Ssimokawa { $$ = $1; } 922111942Ssimokawa; 923111942Ssimokawa 924111942Ssimokawaimmediate_or_a: 925111942Ssimokawa expression 926103285Sikob { 927113584Ssimokawa if ($1.value == 0 && is_download_const(&$1) == 0) { 928113584Ssimokawa snprintf(errbuf, sizeof(errbuf), 929113584Ssimokawa "\nExpression evaluates to 0 and thus " 930113584Ssimokawa "references the accumulator.\n " 931113584Ssimokawa "If this is the desired effect, use 'A' " 932113584Ssimokawa "instead.\n"); 933113584Ssimokawa stop(errbuf, EX_DATAERR); 934113584Ssimokawa } 935113584Ssimokawa $$ = $1; 936103285Sikob } 937108655Ssimokawa| T_A 938108655Ssimokawa { 939108655Ssimokawa SLIST_INIT(&$$.referenced_syms); 940108655Ssimokawa $$.value = 0; 941108655Ssimokawa } 942103285Sikob; 943103285Sikob 944113584Ssimokawasource: 945113584Ssimokawa reg_symbol 946113584Ssimokawa { 947113584Ssimokawa test_readable_symbol($1.symbol); 948103285Sikob $$ = $1; 949103285Sikob } 950103285Sikob; 951103285Sikob 952103285Sikobopt_source: 953113584Ssimokawa { 954103285Sikob $$.symbol = NULL; 955103285Sikob $$.offset = 0; 956103285Sikob } 957103285Sikob| ',' source 958103285Sikob { $$ = $2; } 959103285Sikob; 960107653Ssimokawa 961103285Sikobret: 962103285Sikob { $$ = 0; } 963103285Sikob| T_RET 964103285Sikob { $$ = 1; } 965113584Ssimokawa; 966113584Ssimokawa 967103285Sikobset_src_mode: 968103285Sikob T_SET_SRC_MODE T_NUMBER ';' 969103285Sikob { 970103285Sikob src_mode = $2; 971107653Ssimokawa } 972107653Ssimokawa; 973103285Sikob 974113584Ssimokawaset_dst_mode: 975103285Sikob T_SET_DST_MODE T_NUMBER ';' 976103285Sikob { 977103285Sikob dst_mode = $2; 978106790Ssimokawa } 979103285Sikob; 980103285Sikob 981103285Sikobcritical_section_start: 982103285Sikob T_BEGIN_CS ';' 983106790Ssimokawa { 984106790Ssimokawa critical_section_t *cs; 985106790Ssimokawa 986103285Sikob if (in_critical_section != FALSE) { 987103285Sikob stop("Critical Section within Critical Section", 988103285Sikob EX_DATAERR); 989103285Sikob /* NOTREACHED */ 990103285Sikob } 991106790Ssimokawa cs = cs_alloc(); 992106790Ssimokawa cs->begin_addr = instruction_ptr; 993106790Ssimokawa in_critical_section = TRUE; 994103285Sikob } 995103285Sikob 996103285Sikobcritical_section_end: 997103285Sikob T_END_CS ';' 998103285Sikob { 999106790Ssimokawa critical_section_t *cs; 1000106790Ssimokawa 1001106790Ssimokawa if (in_critical_section == FALSE) { 1002103285Sikob stop("Unballanced 'end_cs'", EX_DATAERR); 1003113584Ssimokawa /* NOTREACHED */ 1004103285Sikob } 1005103285Sikob cs = TAILQ_LAST(&cs_tailq, cs_tailq); 1006103285Sikob cs->end_addr = instruction_ptr; 1007103285Sikob in_critical_section = FALSE; 1008113584Ssimokawa } 1009103285Sikob 1010103285Sikobexport: 1011113584Ssimokawa { $$ = 0; } 1012103285Sikob| T_EXPORT 1013103285Sikob { $$ = 1; } 1014113584Ssimokawa; 1015103285Sikob 1016103285Sikoblabel: 1017113584Ssimokawa export T_SYMBOL ':' 1018103285Sikob { 1019103285Sikob if ($2->type != UNINITIALIZED) { 1020103285Sikob stop("Program label multiply defined", EX_DATAERR); 1021103285Sikob /* NOTREACHED */ 1022103285Sikob } 1023103285Sikob $2->type = LABEL; 1024113584Ssimokawa initialize_symbol($2); 1025113584Ssimokawa $2->info.linfo->address = instruction_ptr; 1026103285Sikob $2->info.linfo->exported = $1; 1027103285Sikob } 1028113584Ssimokawa; 1029113584Ssimokawa 1030103285Sikobaddress: 1031103285Sikob T_SYMBOL 1032103285Sikob { 1033103285Sikob $$.symbol = $1; 1034113584Ssimokawa $$.offset = 0; 1035113584Ssimokawa } 1036113584Ssimokawa| T_SYMBOL '+' T_NUMBER 1037113584Ssimokawa { 1038113584Ssimokawa $$.symbol = $1; 1039103285Sikob $$.offset = $3; 1040113584Ssimokawa } 1041113584Ssimokawa| T_SYMBOL '-' T_NUMBER 1042103285Sikob { 1043103285Sikob $$.symbol = $1; 1044103285Sikob $$.offset = -$3; 1045103285Sikob } 1046103285Sikob| '.' 1047103285Sikob { 1048113584Ssimokawa $$.symbol = NULL; 1049103285Sikob $$.offset = 0; 1050110577Ssimokawa } 1051103285Sikob| '.' '+' T_NUMBER 1052103285Sikob { 1053103285Sikob $$.symbol = NULL; 1054103285Sikob $$.offset = $3; 1055103285Sikob } 1056110577Ssimokawa| '.' '-' T_NUMBER 1057103285Sikob { 1058103285Sikob $$.symbol = NULL; 1059103285Sikob $$.offset = -$3; 1060103285Sikob } 1061103285Sikob; 1062103285Sikob 1063103285Sikobconditional: 1064103285Sikob T_IF T_CEXPR '{' 1065103285Sikob { 1066103285Sikob scope_t *new_scope; 1067103285Sikob 1068103285Sikob add_conditional($2); 1069103285Sikob new_scope = scope_alloc(); 1070103285Sikob new_scope->type = SCOPE_IF; 1071103285Sikob new_scope->begin_addr = instruction_ptr; 1072103285Sikob new_scope->func_num = $2->info.condinfo->func_num; 1073103285Sikob } 1074103285Sikob| T_ELSE T_IF T_CEXPR '{' 1075103285Sikob { 1076103285Sikob scope_t *new_scope; 1077103285Sikob scope_t *scope_context; 1078103285Sikob scope_t *last_scope; 1079103285Sikob 1080103285Sikob /* 1081110577Ssimokawa * Ensure that the previous scope is either an 1082103285Sikob * if or and else if. 1083113584Ssimokawa */ 1084113584Ssimokawa scope_context = SLIST_FIRST(&scope_stack); 1085113584Ssimokawa last_scope = TAILQ_LAST(&scope_context->inner_scope, 1086113584Ssimokawa scope_tailq); 1087113584Ssimokawa if (last_scope == NULL 1088114218Ssimokawa || last_scope->type == T_ELSE) { 1089114218Ssimokawa 1090114218Ssimokawa stop("'else if' without leading 'if'", EX_DATAERR); 1091114218Ssimokawa /* NOTREACHED */ 1092114218Ssimokawa } 1093114218Ssimokawa add_conditional($3); 1094114224Ssimokawa new_scope = scope_alloc(); 1095114224Ssimokawa new_scope->type = SCOPE_ELSE_IF; 1096114218Ssimokawa new_scope->begin_addr = instruction_ptr; 1097114224Ssimokawa new_scope->func_num = $3->info.condinfo->func_num; 1098114218Ssimokawa } 1099114218Ssimokawa| T_ELSE '{' 1100114218Ssimokawa { 1101114218Ssimokawa scope_t *new_scope; 1102114224Ssimokawa scope_t *scope_context; 1103113584Ssimokawa scope_t *last_scope; 1104114218Ssimokawa 1105103285Sikob /* 1106110577Ssimokawa * Ensure that the previous scope is either an 1107110577Ssimokawa * if or and else if. 1108110577Ssimokawa */ 1109110577Ssimokawa scope_context = SLIST_FIRST(&scope_stack); 1110113584Ssimokawa last_scope = TAILQ_LAST(&scope_context->inner_scope, 1111113584Ssimokawa scope_tailq); 1112103285Sikob if (last_scope == NULL 1113110269Ssimokawa || last_scope->type == SCOPE_ELSE) { 1114103285Sikob 1115103285Sikob stop("'else' without leading 'if'", EX_DATAERR); 1116103285Sikob /* NOTREACHED */ 1117103285Sikob } 1118103285Sikob new_scope = scope_alloc(); 1119111956Ssimokawa new_scope->type = SCOPE_ELSE; 1120111956Ssimokawa new_scope->begin_addr = instruction_ptr; 1121111956Ssimokawa } 1122111956Ssimokawa; 1123111956Ssimokawa 1124111956Ssimokawaconditional: 1125103285Sikob '}' 1126103285Sikob { 1127103285Sikob scope_t *scope_context; 1128103285Sikob 1129103285Sikob scope_context = SLIST_FIRST(&scope_stack); 1130103285Sikob if (scope_context->type == SCOPE_ROOT) { 1131103285Sikob stop("Unexpected '}' encountered", EX_DATAERR); 1132103285Sikob /* NOTREACHED */ 1133103285Sikob } 1134106790Ssimokawa 1135106790Ssimokawa scope_context->end_addr = instruction_ptr; 1136106790Ssimokawa 1137103285Sikob /* Pop the scope */ 1138103285Sikob SLIST_REMOVE_HEAD(&scope_stack, scope_stack_links); 1139113584Ssimokawa 1140103285Sikob process_scope(scope_context); 1141108527Ssimokawa 1142108527Ssimokawa if (SLIST_FIRST(&scope_stack) == NULL) { 1143108527Ssimokawa stop("Unexpected '}' encountered", EX_DATAERR); 1144113584Ssimokawa /* NOTREACHED */ 1145103285Sikob } 1146113584Ssimokawa } 1147113584Ssimokawa; 1148113584Ssimokawa 1149113584Ssimokawaf1_opcode: 1150113584Ssimokawa T_AND { $$ = AIC_OP_AND; } 1151113584Ssimokawa| T_XOR { $$ = AIC_OP_XOR; } 1152113584Ssimokawa| T_ADD { $$ = AIC_OP_ADD; } 1153103285Sikob| T_ADC { $$ = AIC_OP_ADC; } 1154103285Sikob; 1155103285Sikob 1156113584Ssimokawacode: 1157110195Ssimokawa f1_opcode destination ',' immediate_or_a opt_source ret ';' 1158103285Sikob { 1159108527Ssimokawa format_1_instr($1, &$2, &$4, &$5, $6); 1160103285Sikob } 1161106790Ssimokawa; 1162106790Ssimokawa 1163113584Ssimokawacode: 1164103285Sikob T_OR reg_symbol ',' immediate_or_a opt_source ret ';' 1165103285Sikob { 1166103285Sikob format_1_instr(AIC_OP_OR, &$2, &$4, &$5, $6); 1167108642Ssimokawa } 1168108642Ssimokawa; 1169108642Ssimokawa 1170108642Ssimokawacode: 1171113584Ssimokawa T_INC destination opt_source ret ';' 1172113584Ssimokawa { 1173113584Ssimokawa expression_t immed; 1174113584Ssimokawa 1175113584Ssimokawa make_expression(&immed, 1); 1176113584Ssimokawa format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); 1177113584Ssimokawa } 1178113584Ssimokawa; 1179113584Ssimokawa 1180113584Ssimokawacode: 1181113584Ssimokawa T_DEC destination opt_source ret ';' 1182113584Ssimokawa { 1183113584Ssimokawa expression_t immed; 1184103285Sikob 1185103285Sikob make_expression(&immed, -1); 1186103285Sikob format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4); 1187103285Sikob } 1188103285Sikob; 1189113584Ssimokawa 1190103285Sikobcode: 1191109379Ssimokawa T_CLC ret ';' 1192103285Sikob { 1193103285Sikob expression_t immed; 1194109379Ssimokawa 1195113584Ssimokawa make_expression(&immed, -1); 1196113584Ssimokawa format_1_instr(AIC_OP_ADD, &none, &immed, &allzeros, $2); 1197113584Ssimokawa } 1198113584Ssimokawa| T_CLC T_MVI destination ',' immediate_or_a ret ';' 1199113584Ssimokawa { 1200103285Sikob format_1_instr(AIC_OP_ADD, &$3, &$5, &allzeros, $6); 1201103285Sikob } 1202103285Sikob; 1203103285Sikob 1204103285Sikobcode: 1205113584Ssimokawa T_STC ret ';' 1206113584Ssimokawa { 1207113584Ssimokawa expression_t immed; 1208113584Ssimokawa 1209113584Ssimokawa make_expression(&immed, 1); 1210113584Ssimokawa format_1_instr(AIC_OP_ADD, &none, &immed, &allones, $2); 1211113584Ssimokawa } 1212113584Ssimokawa| T_STC destination ret ';' 1213113584Ssimokawa { 1214113584Ssimokawa expression_t immed; 1215113584Ssimokawa 1216103285Sikob make_expression(&immed, 1); 1217113584Ssimokawa format_1_instr(AIC_OP_ADD, &$2, &immed, &allones, $3); 1218108530Ssimokawa } 1219108530Ssimokawa; 1220108530Ssimokawa 1221108530Ssimokawacode: 1222108530Ssimokawa T_BMOV destination ',' source ',' immediate ret ';' 1223108530Ssimokawa { 1224103285Sikob format_1_instr(AIC_OP_BMOV, &$2, &$6, &$4, $7); 1225103285Sikob } 1226103285Sikob; 1227103285Sikob 1228103285Sikobcode: 1229108642Ssimokawa T_MOV destination ',' source ret ';' 1230108642Ssimokawa { 1231108642Ssimokawa expression_t immed; 1232103285Sikob 1233103285Sikob make_expression(&immed, 1); 1234108527Ssimokawa format_1_instr(AIC_OP_BMOV, &$2, &immed, &$4, $5); 1235103285Sikob } 1236106790Ssimokawa; 1237106790Ssimokawa 1238106790Ssimokawacode: 1239103285Sikob T_MVI destination ',' immediate_or_a ret ';' 1240103285Sikob { 1241113584Ssimokawa format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5); 1242109890Ssimokawa } 1243113584Ssimokawa; 1244113584Ssimokawa 1245103285Sikobcode: 1246103285Sikob T_NOT destination opt_source ret ';' 1247109890Ssimokawa { 1248113584Ssimokawa expression_t immed; 1249103285Sikob 1250103285Sikob make_expression(&immed, 0xff); 1251103285Sikob format_1_instr(AIC_OP_XOR, &$2, &immed, &$3, $4); 1252103285Sikob } 1253106790Ssimokawa; 1254106790Ssimokawa 1255106790Ssimokawacode: 1256103285Sikob T_CLR destination ret ';' 1257103285Sikob { 1258113584Ssimokawa expression_t immed; 1259103285Sikob 1260103285Sikob make_expression(&immed, 0xff); 1261103285Sikob format_1_instr(AIC_OP_AND, &$2, &immed, &allzeros, $3); 1262103285Sikob } 1263109890Ssimokawa; 1264113584Ssimokawa 1265103285Sikobcode: 1266103285Sikob T_NOP ret ';' 1267103285Sikob { 1268103285Sikob expression_t immed; 1269106790Ssimokawa 1270113584Ssimokawa make_expression(&immed, 0xff); 1271106790Ssimokawa format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, $2); 1272106790Ssimokawa } 1273103285Sikob; 1274113584Ssimokawa 1275103285Sikobcode: 1276103285Sikob T_RET ';' 1277103285Sikob { 1278103285Sikob expression_t immed; 1279106790Ssimokawa 1280106790Ssimokawa make_expression(&immed, 0xff); 1281103285Sikob format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, TRUE); 1282103285Sikob } 1283113584Ssimokawa; 1284103285Sikob 1285103285Sikob /* 1286109892Ssimokawa * This grammer differs from the one in the aic7xxx 1287103285Sikob * reference manual since the grammer listed there is 1288103285Sikob * ambiguous and causes a shift/reduce conflict. 1289103285Sikob * It also seems more logical as the "immediate" 1290103285Sikob * argument is listed as the second arg like the 1291103285Sikob * other formats. 1292103285Sikob */ 1293103285Sikob 1294103285Sikobf2_opcode: 1295103285Sikob T_SHL { $$ = AIC_OP_SHL; } 1296103285Sikob| T_SHR { $$ = AIC_OP_SHR; } 1297103285Sikob| T_ROL { $$ = AIC_OP_ROL; } 1298103285Sikob| T_ROR { $$ = AIC_OP_ROR; } 1299103285Sikob; 1300103285Sikob 1301103285Sikobcode: 1302103285Sikob f2_opcode destination ',' expression opt_source ret ';' 1303103285Sikob { 1304103285Sikob format_2_instr($1, &$2, &$4, &$5, $6); 1305103285Sikob } 1306103285Sikob; 1307103285Sikob 1308103285Sikobjmp_jc_jnc_call: 1309103285Sikob T_JMP { $$ = AIC_OP_JMP; } 1310113584Ssimokawa| T_JC { $$ = AIC_OP_JC; } 1311113584Ssimokawa| T_JNC { $$ = AIC_OP_JNC; } 1312103285Sikob| T_CALL { $$ = AIC_OP_CALL; } 1313103285Sikob; 1314103285Sikob 1315109892Ssimokawajz_jnz: 1316113584Ssimokawa T_JZ { $$ = AIC_OP_JZ; } 1317113584Ssimokawa| T_JNZ { $$ = AIC_OP_JNZ; } 1318113584Ssimokawa; 1319113584Ssimokawa 1320103285Sikobje_jne: 1321103285Sikob T_JE { $$ = AIC_OP_JE; } 1322113584Ssimokawa| T_JNE { $$ = AIC_OP_JNE; } 1323113584Ssimokawa; 1324113584Ssimokawa 1325109280Ssimokawacode: 1326113584Ssimokawa jmp_jc_jnc_call address ';' 1327113584Ssimokawa { 1328113584Ssimokawa expression_t immed; 1329103285Sikob 1330103285Sikob make_expression(&immed, 0); 1331103285Sikob format_3_instr($1, &sindex, &immed, &$2); 1332103285Sikob } 1333113584Ssimokawa; 1334113584Ssimokawa 1335103285Sikobcode: 1336103285Sikob T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';' 1337106790Ssimokawa { 1338106790Ssimokawa format_3_instr($5, &$2, &$4, &$6); 1339106790Ssimokawa } 1340103285Sikob; 1341103285Sikob 1342109892Ssimokawacode: 1343103285Sikob T_TEST source ',' immediate_or_a jz_jnz address ';' 1344103285Sikob { 1345109892Ssimokawa format_3_instr($5, &$2, &$4, &$6); 1346103285Sikob } 1347103285Sikob; 1348103285Sikob 1349103285Sikobcode: 1350103285Sikob T_CMP source ',' immediate_or_a je_jne address ';' 1351103285Sikob { 1352103285Sikob format_3_instr($5, &$2, &$4, &$6); 1353103285Sikob } 1354103285Sikob; 1355103285Sikob 1356103285Sikobcode: 1357103285Sikob T_MOV source jmp_jc_jnc_call address ';' 1358103285Sikob { 1359103285Sikob expression_t immed; 1360103285Sikob 1361103285Sikob make_expression(&immed, 0); 1362103285Sikob format_3_instr($3, &$2, &immed, &$4); 1363103285Sikob } 1364103285Sikob; 1365103285Sikob 1366103285Sikobcode: 1367103285Sikob T_MVI immediate jmp_jc_jnc_call address ';' 1368103285Sikob { 1369103285Sikob format_3_instr($3, &allzeros, &$2, &$4); 1370103285Sikob } 1371103285Sikob; 1372103285Sikob 1373103285Sikob%% 1374108642Ssimokawa 1375103285Sikobstatic void 1376103285Sikobprocess_field(int field_type, symbol_t *sym, int value) 1377103285Sikob{ 1378103285Sikob /* 1379113584Ssimokawa * Add the current register to its 1380113584Ssimokawa * symbol list, if it already exists, 1381113584Ssimokawa * warn if we are setting it to a 1382103285Sikob * different value, or in the bit to 1383109892Ssimokawa * the "allowed bits" of this register. 1384109892Ssimokawa */ 1385113584Ssimokawa if (sym->type == UNINITIALIZED) { 1386113584Ssimokawa sym->type = field_type; 1387103285Sikob initialize_symbol(sym); 1388103285Sikob sym->info.finfo->value = value; 1389113584Ssimokawa if (field_type != ENUM_ENTRY) { 1390113584Ssimokawa if (field_type != MASK && value == 0) { 1391113584Ssimokawa stop("Empty Field, or Enum", EX_DATAERR); 1392113584Ssimokawa /* NOTREACHED */ 1393113584Ssimokawa } 1394113584Ssimokawa sym->info.finfo->value = value; 1395103285Sikob sym->info.finfo->mask = value; 1396103285Sikob } else if (field_symbol != NULL) { 1397103285Sikob sym->info.finfo->mask = field_symbol->info.finfo->value; 1398103285Sikob } else { 1399113584Ssimokawa sym->info.finfo->mask = 0xFF; 1400113584Ssimokawa } 1401103285Sikob } else if (sym->type != field_type) { 1402113584Ssimokawa stop("Field definition mirrors a definition of the same " 1403113584Ssimokawa " name, but a different type", EX_DATAERR); 1404103285Sikob /* NOTREACHED */ 1405103285Sikob } else if (value != sym->info.finfo->value) { 1406103285Sikob stop("Field redefined with a conflicting value", EX_DATAERR); 1407113584Ssimokawa /* NOTREACHED */ 1408103285Sikob } 1409103285Sikob /* Fail if this symbol is already listed */ 1410103285Sikob if (symlist_search(&(sym->info.finfo->symrefs), 1411103285Sikob cur_symbol->name) != NULL) { 1412106790Ssimokawa stop("Field defined multiple times for register", EX_DATAERR); 1413106790Ssimokawa /* NOTREACHED */ 1414113584Ssimokawa } 1415109890Ssimokawa symlist_add(&(sym->info.finfo->symrefs), cur_symbol, 1416109890Ssimokawa SYMLIST_INSERT_HEAD); 1417109890Ssimokawa cur_symbol->info.rinfo->valid_bitmask |= sym->info.finfo->mask; 1418109890Ssimokawa cur_symbol->info.rinfo->typecheck_masks = TRUE; 1419109890Ssimokawa symlist_add(&(cur_symbol->info.rinfo->fields), sym, SYMLIST_SORT); 1420109890Ssimokawa} 1421113584Ssimokawa 1422109890Ssimokawastatic void 1423113584Ssimokawainitialize_symbol(symbol_t *symbol) 1424113584Ssimokawa{ 1425113584Ssimokawa switch (symbol->type) { 1426109890Ssimokawa case UNINITIALIZED: 1427109890Ssimokawa stop("Call to initialize_symbol with type field unset", 1428109890Ssimokawa EX_SOFTWARE); 1429109890Ssimokawa /* NOTREACHED */ 1430109890Ssimokawa break; 1431113584Ssimokawa case REGISTER: 1432109890Ssimokawa case SRAMLOC: 1433109890Ssimokawa case SCBLOC: 1434109890Ssimokawa symbol->info.rinfo = 1435109890Ssimokawa (struct reg_info *)malloc(sizeof(struct reg_info)); 1436109890Ssimokawa if (symbol->info.rinfo == NULL) { 1437109890Ssimokawa stop("Can't create register info", EX_SOFTWARE); 1438109890Ssimokawa /* NOTREACHED */ 1439109890Ssimokawa } 1440109890Ssimokawa memset(symbol->info.rinfo, 0, 1441109890Ssimokawa sizeof(struct reg_info)); 1442109890Ssimokawa SLIST_INIT(&(symbol->info.rinfo->fields)); 1443109890Ssimokawa /* 1444109890Ssimokawa * Default to allowing access in all register modes 1445106790Ssimokawa * or to the mode specified by the SCB or SRAM space 1446103285Sikob * we are in. 1447103285Sikob */ 1448103285Sikob if (scb_or_sram_symbol != NULL) 1449103285Sikob symbol->info.rinfo->modes = 1450103285Sikob scb_or_sram_symbol->info.rinfo->modes; 1451109890Ssimokawa else 1452109356Ssimokawa symbol->info.rinfo->modes = ~0; 1453109890Ssimokawa break; 1454109890Ssimokawa case ALIAS: 1455103285Sikob symbol->info.ainfo = 1456103285Sikob (struct alias_info *)malloc(sizeof(struct alias_info)); 1457109890Ssimokawa if (symbol->info.ainfo == NULL) { 1458109890Ssimokawa stop("Can't create alias info", EX_SOFTWARE); 1459109890Ssimokawa /* NOTREACHED */ 1460109890Ssimokawa } 1461109179Ssimokawa memset(symbol->info.ainfo, 0, 1462109890Ssimokawa sizeof(struct alias_info)); 1463103285Sikob break; 1464113584Ssimokawa case MASK: 1465109179Ssimokawa case FIELD: 1466109179Ssimokawa case ENUM: 1467103285Sikob case ENUM_ENTRY: 1468103285Sikob symbol->info.finfo = 1469103285Sikob (struct field_info *)malloc(sizeof(struct field_info)); 1470103285Sikob if (symbol->info.finfo == NULL) { 1471109890Ssimokawa stop("Can't create field info", EX_SOFTWARE); 1472109892Ssimokawa /* NOTREACHED */ 1473109890Ssimokawa } 1474109890Ssimokawa memset(symbol->info.finfo, 0, sizeof(struct field_info)); 1475109890Ssimokawa SLIST_INIT(&(symbol->info.finfo->symrefs)); 1476109890Ssimokawa break; 1477109890Ssimokawa case CONST: 1478113584Ssimokawa case DOWNLOAD_CONST: 1479113584Ssimokawa symbol->info.cinfo = 1480109890Ssimokawa (struct const_info *)malloc(sizeof(struct const_info)); 1481109890Ssimokawa if (symbol->info.cinfo == NULL) { 1482109890Ssimokawa stop("Can't create alias info", EX_SOFTWARE); 1483113584Ssimokawa /* NOTREACHED */ 1484113584Ssimokawa } 1485113584Ssimokawa memset(symbol->info.cinfo, 0, 1486113584Ssimokawa sizeof(struct const_info)); 1487109892Ssimokawa break; 1488109890Ssimokawa case LABEL: 1489113584Ssimokawa symbol->info.linfo = 1490113584Ssimokawa (struct label_info *)malloc(sizeof(struct label_info)); 1491109892Ssimokawa if (symbol->info.linfo == NULL) { 1492113584Ssimokawa stop("Can't create label info", EX_SOFTWARE); 1493113584Ssimokawa /* NOTREACHED */ 1494109892Ssimokawa } 1495103285Sikob memset(symbol->info.linfo, 0, 1496109890Ssimokawa sizeof(struct label_info)); 1497109890Ssimokawa break; 1498109890Ssimokawa case CONDITIONAL: 1499109403Ssimokawa symbol->info.condinfo = 1500113584Ssimokawa (struct cond_info *)malloc(sizeof(struct cond_info)); 1501113584Ssimokawa if (symbol->info.condinfo == NULL) { 1502109890Ssimokawa stop("Can't create conditional info", EX_SOFTWARE); 1503109890Ssimokawa /* NOTREACHED */ 1504113584Ssimokawa } 1505113584Ssimokawa memset(symbol->info.condinfo, 0, 1506113584Ssimokawa sizeof(struct cond_info)); 1507109890Ssimokawa break; 1508109890Ssimokawa case MACRO: 1509109890Ssimokawa symbol->info.macroinfo = 1510113584Ssimokawa (struct macro_info *)malloc(sizeof(struct macro_info)); 1511109890Ssimokawa if (symbol->info.macroinfo == NULL) { 1512113584Ssimokawa stop("Can't create macro info", EX_SOFTWARE); 1513109403Ssimokawa /* NOTREACHED */ 1514109403Ssimokawa } 1515109403Ssimokawa memset(symbol->info.macroinfo, 0, 1516113584Ssimokawa sizeof(struct macro_info)); 1517109890Ssimokawa STAILQ_INIT(&symbol->info.macroinfo->args); 1518109890Ssimokawa break; 1519113584Ssimokawa default: 1520113584Ssimokawa stop("Call to initialize_symbol with invalid symbol type", 1521113584Ssimokawa EX_SOFTWARE); 1522109890Ssimokawa /* NOTREACHED */ 1523113584Ssimokawa break; 1524113584Ssimokawa } 1525113584Ssimokawa} 1526113584Ssimokawa 1527109403Ssimokawastatic void 1528109890Ssimokawaadd_macro_arg(const char *argtext, int argnum) 1529109890Ssimokawa{ 1530109890Ssimokawa struct macro_arg *marg; 1531109890Ssimokawa int i; 1532109890Ssimokawa int retval; 1533113584Ssimokawa 1534109890Ssimokawa 1535109890Ssimokawa if (cur_symbol == NULL || cur_symbol->type != MACRO) { 1536109890Ssimokawa stop("Invalid current symbol for adding macro arg", 1537109356Ssimokawa EX_SOFTWARE); 1538109356Ssimokawa /* NOTREACHED */ 1539113584Ssimokawa } 1540109890Ssimokawa 1541109356Ssimokawa marg = (struct macro_arg *)malloc(sizeof(*marg)); 1542109356Ssimokawa if (marg == NULL) { 1543109356Ssimokawa stop("Can't create macro_arg structure", EX_SOFTWARE); 1544113584Ssimokawa /* NOTREACHED */ 1545113584Ssimokawa } 1546113584Ssimokawa marg->replacement_text = NULL; 1547113584Ssimokawa retval = snprintf(regex_pattern, sizeof(regex_pattern), 1548109403Ssimokawa "[^-/A-Za-z0-9_](%s)([^-/A-Za-z0-9_]|$)", 1549109403Ssimokawa argtext); 1550113584Ssimokawa if (retval >= sizeof(regex_pattern)) { 1551113584Ssimokawa stop("Regex text buffer too small for arg", 1552113584Ssimokawa EX_SOFTWARE); 1553109403Ssimokawa /* NOTREACHED */ 1554109890Ssimokawa } 1555109890Ssimokawa retval = regcomp(&marg->arg_regex, regex_pattern, REG_EXTENDED); 1556113584Ssimokawa if (retval != 0) { 1557103285Sikob stop("Regex compilation failed", EX_SOFTWARE); 1558109890Ssimokawa /* NOTREACHED */ 1559103285Sikob } 1560103285Sikob STAILQ_INSERT_TAIL(&cur_symbol->info.macroinfo->args, marg, links); 1561106790Ssimokawa} 1562106790Ssimokawa 1563113584Ssimokawastatic void 1564103285Sikobadd_macro_body(const char *bodytext) 1565103285Sikob{ 1566109890Ssimokawa if (cur_symbol == NULL || cur_symbol->type != MACRO) { 1567103285Sikob stop("Invalid current symbol for adding macro arg", 1568109736Ssimokawa EX_SOFTWARE); 1569109890Ssimokawa /* NOTREACHED */ 1570113584Ssimokawa } 1571109890Ssimokawa cur_symbol->info.macroinfo->body = strdup(bodytext); 1572109890Ssimokawa if (cur_symbol->info.macroinfo->body == NULL) { 1573103285Sikob stop("Can't duplicate macro body text", EX_SOFTWARE); 1574109890Ssimokawa /* NOTREACHED */ 1575109890Ssimokawa } 1576109890Ssimokawa} 1577109890Ssimokawa 1578109890Ssimokawastatic void 1579109890Ssimokawaprocess_register(symbol_t **p_symbol) 1580108995Ssimokawa{ 1581108995Ssimokawa symbol_t *symbol = *p_symbol; 1582109890Ssimokawa 1583109890Ssimokawa if (symbol->type == UNINITIALIZED) { 1584109890Ssimokawa snprintf(errbuf, sizeof(errbuf), "Undefined register %s", 1585113584Ssimokawa symbol->name); 1586109890Ssimokawa stop(errbuf, EX_DATAERR); 1587109179Ssimokawa /* NOTREACHED */ 1588109890Ssimokawa } else if (symbol->type == ALIAS) { 1589103285Sikob *p_symbol = symbol->info.ainfo->parent; 1590103285Sikob } else if ((symbol->type != REGISTER) 1591103285Sikob && (symbol->type != SCBLOC) 1592103285Sikob && (symbol->type != SRAMLOC)) { 1593109890Ssimokawa snprintf(errbuf, sizeof(errbuf), 1594109890Ssimokawa "Specified symbol %s is not a register", 1595109890Ssimokawa symbol->name); 1596109890Ssimokawa stop(errbuf, EX_DATAERR); 1597109890Ssimokawa } 1598109890Ssimokawa} 1599111892Ssimokawa 1600111892Ssimokawastatic void 1601109890Ssimokawaformat_1_instr(int opcode, symbol_ref_t *dest, expression_t *immed, 1602109890Ssimokawa symbol_ref_t *src, int ret) 1603109890Ssimokawa{ 1604109890Ssimokawa struct instruction *instr; 1605111942Ssimokawa struct ins_format1 *f1_instr; 1606113584Ssimokawa 1607113584Ssimokawa if (src->symbol == NULL) 1608113584Ssimokawa src = dest; 1609113584Ssimokawa 1610113584Ssimokawa /* Test register permissions */ 1611113584Ssimokawa test_writable_symbol(dest->symbol); 1612113584Ssimokawa test_readable_symbol(src->symbol); 1613113584Ssimokawa 1614113584Ssimokawa /* Ensure that immediate makes sense for this destination */ 1615113584Ssimokawa type_check(dest->symbol, immed, opcode); 1616111942Ssimokawa 1617109890Ssimokawa /* Allocate sequencer space for the instruction and fill it out */ 1618113584Ssimokawa instr = seq_alloc(); 1619113584Ssimokawa f1_instr = &instr->format.format1; 1620109890Ssimokawa f1_instr->ret = ret ? 1 : 0; 1621109890Ssimokawa f1_instr->opcode = opcode; 1622113584Ssimokawa f1_instr->destination = dest->symbol->info.rinfo->address 1623103285Sikob + dest->offset; 1624109890Ssimokawa f1_instr->source = src->symbol->info.rinfo->address 1625109890Ssimokawa + src->offset; 1626109890Ssimokawa f1_instr->immediate = immed->value; 1627103285Sikob 1628113584Ssimokawa if (is_download_const(immed)) 1629113584Ssimokawa f1_instr->parity = 1; 1630109890Ssimokawa else if (dest->symbol == mode_ptr.symbol) { 1631109890Ssimokawa u_int src_value; 1632109890Ssimokawa u_int dst_value; 1633109890Ssimokawa 1634109890Ssimokawa /* 1635109890Ssimokawa * Attempt to update mode information if 1636109890Ssimokawa * we are operating on the mode register. 1637109890Ssimokawa */ 1638109890Ssimokawa if (src->symbol == allones.symbol) 1639113584Ssimokawa src_value = 0xFF; 1640113584Ssimokawa else if (src->symbol == allzeros.symbol) 1641109890Ssimokawa src_value = 0; 1642109890Ssimokawa else if (src->symbol == mode_ptr.symbol) 1643109890Ssimokawa src_value = (dst_mode << 4) | src_mode; 1644109890Ssimokawa else 1645109890Ssimokawa goto cant_update; 1646109890Ssimokawa 1647113584Ssimokawa switch (opcode) { 1648109890Ssimokawa case AIC_OP_AND: 1649109890Ssimokawa dst_value = src_value & immed->value; 1650109890Ssimokawa break; 1651113584Ssimokawa case AIC_OP_XOR: 1652113584Ssimokawa dst_value = src_value ^ immed->value; 1653113584Ssimokawa break; 1654103285Sikob case AIC_OP_ADD: 1655103285Sikob dst_value = (src_value + immed->value) & 0xFF; 1656106790Ssimokawa break; 1657106790Ssimokawa case AIC_OP_OR: 1658110145Ssimokawa dst_value = src_value | immed->value; 1659103285Sikob break; 1660103285Sikob case AIC_OP_BMOV: 1661103285Sikob dst_value = src_value; 1662103285Sikob break; 1663103285Sikob default: 1664103285Sikob goto cant_update; 1665103285Sikob } 1666103285Sikob src_mode = dst_value & 0xF; 1667103285Sikob dst_mode = (dst_value >> 4) & 0xF; 1668103285Sikob } 1669103285Sikob 1670103285Sikobcant_update: 1671103285Sikob symlist_free(&immed->referenced_syms); 1672103285Sikob instruction_ptr++; 1673103285Sikob} 1674103285Sikob 1675103285Sikobstatic void 1676103285Sikobformat_2_instr(int opcode, symbol_ref_t *dest, expression_t *places, 1677103285Sikob symbol_ref_t *src, int ret) 1678103285Sikob{ 1679103285Sikob struct instruction *instr; 1680103285Sikob struct ins_format2 *f2_instr; 1681103285Sikob uint8_t shift_control; 1682103285Sikob 1683103285Sikob if (src->symbol == NULL) 1684108642Ssimokawa src = dest; 1685103285Sikob 1686103285Sikob /* Test register permissions */ 1687103285Sikob test_writable_symbol(dest->symbol); 1688108642Ssimokawa test_readable_symbol(src->symbol); 1689108642Ssimokawa 1690108642Ssimokawa /* Allocate sequencer space for the instruction and fill it out */ 1691108642Ssimokawa instr = seq_alloc(); 1692108642Ssimokawa f2_instr = &instr->format.format2; 1693108642Ssimokawa f2_instr->ret = ret ? 1 : 0; 1694108642Ssimokawa f2_instr->opcode = AIC_OP_ROL; 1695108642Ssimokawa f2_instr->destination = dest->symbol->info.rinfo->address 1696108642Ssimokawa + dest->offset; 1697108642Ssimokawa f2_instr->source = src->symbol->info.rinfo->address 1698108642Ssimokawa + src->offset; 1699108642Ssimokawa if (places->value > 8 || places->value <= 0) { 1700108642Ssimokawa stop("illegal shift value", EX_DATAERR); 1701108642Ssimokawa /* NOTREACHED */ 1702108642Ssimokawa } 1703108642Ssimokawa switch (opcode) { 1704108642Ssimokawa case AIC_OP_SHL: 1705108642Ssimokawa if (places->value == 8) 1706108642Ssimokawa shift_control = 0xf0; 1707108642Ssimokawa else 1708108642Ssimokawa shift_control = (places->value << 4) | places->value; 1709103285Sikob break; 1710103285Sikob case AIC_OP_SHR: 1711106789Ssimokawa if (places->value == 8) { 1712103285Sikob shift_control = 0xf8; 1713103285Sikob } else { 1714103285Sikob shift_control = (places->value << 4) 1715103285Sikob | (8 - places->value) 1716103285Sikob | 0x08; 1717103285Sikob } 1718103285Sikob break; 1719103285Sikob case AIC_OP_ROL: 1720103285Sikob shift_control = places->value & 0x7; 1721103285Sikob break; 1722103285Sikob case AIC_OP_ROR: 1723103285Sikob shift_control = (8 - places->value) | 0x08; 1724103285Sikob break; 1725103285Sikob default: 1726103285Sikob shift_control = 0; /* Quiet Compiler */ 1727103285Sikob stop("Invalid shift operation specified", EX_SOFTWARE); 1728103285Sikob /* NOTREACHED */ 1729103285Sikob break; 1730103285Sikob }; 1731103285Sikob f2_instr->shift_control = shift_control; 1732103285Sikob symlist_free(&places->referenced_syms); 1733103285Sikob instruction_ptr++; 1734103285Sikob} 1735103285Sikob 1736103285Sikobstatic void 1737103285Sikobformat_3_instr(int opcode, symbol_ref_t *src, 1738103285Sikob expression_t *immed, symbol_ref_t *address) 1739103285Sikob{ 1740103285Sikob struct instruction *instr; 1741103285Sikob struct ins_format3 *f3_instr; 1742103285Sikob int addr; 1743103285Sikob 1744103285Sikob /* Test register permissions */ 1745103285Sikob test_readable_symbol(src->symbol); 1746111074Ssimokawa 1747111074Ssimokawa /* Ensure that immediate makes sense for this source */ 1748111074Ssimokawa type_check(src->symbol, immed, opcode); 1749111074Ssimokawa 1750111074Ssimokawa /* Allocate sequencer space for the instruction and fill it out */ 1751103285Sikob instr = seq_alloc(); 1752103285Sikob f3_instr = &instr->format.format3; 1753103285Sikob if (address->symbol == NULL) { 1754103285Sikob /* 'dot' referrence. Use the current instruction pointer */ 1755103285Sikob addr = instruction_ptr + address->offset; 1756103285Sikob } else if (address->symbol->type == UNINITIALIZED) { 1757103285Sikob /* forward reference */ 1758103285Sikob addr = address->offset; 1759103285Sikob instr->patch_label = address->symbol; 1760103285Sikob } else 1761103285Sikob addr = address->symbol->info.linfo->address + address->offset; 1762103285Sikob f3_instr->opcode = opcode; 1763110798Ssimokawa f3_instr->address = addr; 1764116376Ssimokawa f3_instr->source = src->symbol->info.rinfo->address 1765116376Ssimokawa + src->offset; 1766103285Sikob f3_instr->immediate = immed->value; 1767111074Ssimokawa 1768103285Sikob if (is_download_const(immed)) 1769103285Sikob f3_instr->parity = 1; 1770103285Sikob 1771103285Sikob symlist_free(&immed->referenced_syms); 1772113584Ssimokawa instruction_ptr++; 1773113584Ssimokawa} 1774113584Ssimokawa 1775113584Ssimokawastatic void 1776113584Ssimokawatest_readable_symbol(symbol_t *symbol) 1777113584Ssimokawa{ 1778103285Sikob 1779109644Ssimokawa if ((symbol->info.rinfo->modes & (0x1 << src_mode)) == 0) { 1780109644Ssimokawa snprintf(errbuf, sizeof(errbuf), 1781103285Sikob "Register %s unavailable in source reg mode %d", 1782109644Ssimokawa symbol->name, src_mode); 1783109644Ssimokawa stop(errbuf, EX_DATAERR); 1784109644Ssimokawa } 1785109644Ssimokawa 1786109644Ssimokawa if (symbol->info.rinfo->mode == WO) { 1787109644Ssimokawa stop("Write Only register specified as source", 1788113584Ssimokawa EX_DATAERR); 1789103285Sikob /* NOTREACHED */ 1790103285Sikob } 1791103285Sikob} 1792103285Sikob 1793103285Sikobstatic void 1794103285Sikobtest_writable_symbol(symbol_t *symbol) 1795103285Sikob{ 1796113584Ssimokawa 1797113584Ssimokawa if ((symbol->info.rinfo->modes & (0x1 << dst_mode)) == 0) { 1798113584Ssimokawa snprintf(errbuf, sizeof(errbuf), 1799113584Ssimokawa "Register %s unavailable in destination reg mode %d", 1800113584Ssimokawa symbol->name, dst_mode); 1801113584Ssimokawa stop(errbuf, EX_DATAERR); 1802103285Sikob } 1803103285Sikob 1804103285Sikob if (symbol->info.rinfo->mode == RO) { 1805103285Sikob stop("Read Only register specified as destination", 1806103285Sikob EX_DATAERR); 1807103285Sikob /* NOTREACHED */ 1808103285Sikob } 1809103285Sikob} 1810103285Sikob 1811103285Sikobstatic void 1812103285Sikobtype_check(symbol_t *symbol, expression_t *expression, int opcode) 1813103285Sikob{ 1814103285Sikob symbol_node_t *node; 1815103285Sikob int and_op; 1816106789Ssimokawa 1817103285Sikob and_op = FALSE; 1818103285Sikob if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || AIC_OP_JZ) 1819103285Sikob and_op = TRUE; 1820103285Sikob 1821103285Sikob /* 1822103285Sikob * Make sure that we aren't attempting to write something 1823103285Sikob * that hasn't been defined. If this is an and operation, 1824103285Sikob * this is a mask, so "undefined" bits are okay. 1825103285Sikob */ 1826106789Ssimokawa if (and_op == FALSE 1827103285Sikob && (expression->value & ~symbol->info.rinfo->valid_bitmask) != 0) { 1828103285Sikob snprintf(errbuf, sizeof(errbuf), 1829113584Ssimokawa "Invalid bit(s) 0x%x in immediate written to %s", 1830103285Sikob expression->value & ~symbol->info.rinfo->valid_bitmask, 1831103285Sikob symbol->name); 1832103285Sikob stop(errbuf, EX_DATAERR); 1833103285Sikob /* NOTREACHED */ 1834103285Sikob } 1835111074Ssimokawa 1836111074Ssimokawa /* 1837111787Ssimokawa * Now make sure that all of the symbols referenced by the 1838111787Ssimokawa * expression are defined for this register. 1839111787Ssimokawa */ 1840111787Ssimokawa if (symbol->info.rinfo->typecheck_masks != FALSE) { 1841111787Ssimokawa for(node = expression->referenced_syms.slh_first; 1842111787Ssimokawa node != NULL; 1843112523Ssimokawa node = node->links.sle_next) { 1844112523Ssimokawa if ((node->symbol->type == MASK 1845103285Sikob || node->symbol->type == FIELD 1846103285Sikob || node->symbol->type == ENUM 1847103285Sikob || node->symbol->type == ENUM_ENTRY) 1848103285Sikob && symlist_search(&node->symbol->info.finfo->symrefs, 1849113584Ssimokawa symbol->name) == NULL) { 1850113584Ssimokawa snprintf(errbuf, sizeof(errbuf), 1851113584Ssimokawa "Invalid field or mask %s " 1852113584Ssimokawa "for register %s", 1853113584Ssimokawa node->symbol->name, symbol->name); 1854113584Ssimokawa stop(errbuf, EX_DATAERR); 1855103285Sikob /* NOTREACHED */ 1856103285Sikob } 1857103285Sikob } 1858113584Ssimokawa } 1859103285Sikob} 1860103285Sikob 1861103285Sikobstatic void 1862113584Ssimokawamake_expression(expression_t *immed, int value) 1863103285Sikob{ 1864103285Sikob SLIST_INIT(&immed->referenced_syms); 1865103285Sikob immed->value = value & 0xff; 1866103285Sikob} 1867113584Ssimokawa 1868103285Sikobstatic void 1869113584Ssimokawaadd_conditional(symbol_t *symbol) 1870113584Ssimokawa{ 1871113584Ssimokawa static int numfuncs; 1872113584Ssimokawa 1873113584Ssimokawa if (numfuncs == 0) { 1874109736Ssimokawa /* add a special conditional, "0" */ 1875109736Ssimokawa symbol_t *false_func; 1876109736Ssimokawa 1877109736Ssimokawa false_func = symtable_get("0"); 1878103285Sikob if (false_func->type != UNINITIALIZED) { 1879113584Ssimokawa stop("Conditional expression '0' " 1880113584Ssimokawa "conflicts with a symbol", EX_DATAERR); 1881113584Ssimokawa /* NOTREACHED */ 1882113584Ssimokawa } 1883113584Ssimokawa false_func->type = CONDITIONAL; 1884113584Ssimokawa initialize_symbol(false_func); 1885113584Ssimokawa false_func->info.condinfo->func_num = numfuncs++; 1886110269Ssimokawa symlist_add(&patch_functions, false_func, SYMLIST_INSERT_HEAD); 1887110269Ssimokawa } 1888110269Ssimokawa 1889110269Ssimokawa /* This condition has occurred before */ 1890110269Ssimokawa if (symbol->type == CONDITIONAL) 1891110269Ssimokawa return; 1892110798Ssimokawa 1893110269Ssimokawa if (symbol->type != UNINITIALIZED) { 1894113584Ssimokawa stop("Conditional expression conflicts with a symbol", 1895113584Ssimokawa EX_DATAERR); 1896103285Sikob /* NOTREACHED */ 1897103285Sikob } 1898103285Sikob 1899103285Sikob symbol->type = CONDITIONAL; 1900103285Sikob initialize_symbol(symbol); 1901103285Sikob symbol->info.condinfo->func_num = numfuncs++; 1902103285Sikob symlist_add(&patch_functions, symbol, SYMLIST_INSERT_HEAD); 1903103285Sikob} 1904103285Sikob 1905103285Sikobstatic void 1906103285Sikobadd_version(const char *verstring) 1907103285Sikob{ 1908103285Sikob const char prefix[] = " * "; 1909103285Sikob int newlen; 1910103285Sikob int oldlen; 1911103285Sikob 1912103285Sikob newlen = strlen(verstring) + strlen(prefix); 1913103285Sikob oldlen = 0; 1914103285Sikob if (versions != NULL) 1915103285Sikob oldlen = strlen(versions); 1916103285Sikob versions = realloc(versions, newlen + oldlen + 2); 1917103285Sikob if (versions == NULL) 1918103285Sikob stop("Can't allocate version string", EX_SOFTWARE); 1919103285Sikob strcpy(&versions[oldlen], prefix); 1920103285Sikob strcpy(&versions[oldlen + strlen(prefix)], verstring); 1921103285Sikob versions[newlen + oldlen] = '\n'; 1922103285Sikob versions[newlen + oldlen + 1] = '\0'; 1923103285Sikob} 1924103285Sikob 1925103285Sikobvoid 1926103285Sikobyyerror(const char *string) 1927103285Sikob{ 1928103285Sikob stop(string, EX_DATAERR); 1929103285Sikob} 1930103285Sikob 1931103285Sikobstatic int 1932113584Ssimokawais_download_const(expression_t *immed) 1933113584Ssimokawa{ 1934113584Ssimokawa if ((immed->referenced_syms.slh_first != NULL) 1935113584Ssimokawa && (immed->referenced_syms.slh_first->symbol->type == DOWNLOAD_CONST)) 1936113584Ssimokawa return (TRUE); 1937113584Ssimokawa 1938113584Ssimokawa return (FALSE); 1939113584Ssimokawa} 1940113584Ssimokawa