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