xref: /freebsd/sys/dev/aic7xxx/aicasm/aicasm_gram.y (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
1c5cb3888SJustin T. Gibbs %{
2098ca2bdSWarner Losh /*-
3c5cb3888SJustin T. Gibbs  * Parser for the Aic7xxx SCSI Host adapter sequencer assembler.
4c5cb3888SJustin T. Gibbs  *
5718cf2ccSPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
6718cf2ccSPedro F. Giffuni  *
7aa6dfd9dSJustin T. Gibbs  * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
863183d8cSJustin T. Gibbs  * Copyright (c) 2001, 2002 Adaptec Inc.
9c5cb3888SJustin T. Gibbs  * All rights reserved.
10c5cb3888SJustin T. Gibbs  *
11c5cb3888SJustin T. Gibbs  * Redistribution and use in source and binary forms, with or without
12c5cb3888SJustin T. Gibbs  * modification, are permitted provided that the following conditions
13c5cb3888SJustin T. Gibbs  * are met:
14c5cb3888SJustin T. Gibbs  * 1. Redistributions of source code must retain the above copyright
15f68f348bSJustin T. Gibbs  *    notice, this list of conditions, and the following disclaimer,
1641c47eeeSJustin T. Gibbs  *    without modification.
177ce72dbaSJustin T. Gibbs  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
187ce72dbaSJustin T. Gibbs  *    substantially similar to the "NO WARRANTY" disclaimer below
197ce72dbaSJustin T. Gibbs  *    ("Disclaimer") and any redistribution must be conditioned upon
207ce72dbaSJustin T. Gibbs  *    including a substantially similar Disclaimer requirement for further
217ce72dbaSJustin T. Gibbs  *    binary redistribution.
227ce72dbaSJustin T. Gibbs  * 3. Neither the names of the above-listed copyright holders nor the names
237ce72dbaSJustin T. Gibbs  *    of any contributors may be used to endorse or promote products derived
247ce72dbaSJustin T. Gibbs  *    from this software without specific prior written permission.
25c5cb3888SJustin T. Gibbs  *
26aa6dfd9dSJustin T. Gibbs  * Alternatively, this software may be distributed under the terms of the
277ce72dbaSJustin T. Gibbs  * GNU General Public License ("GPL") version 2 as published by the Free
287ce72dbaSJustin T. Gibbs  * Software Foundation.
29aa6dfd9dSJustin T. Gibbs  *
307ce72dbaSJustin T. Gibbs  * NO WARRANTY
317ce72dbaSJustin T. Gibbs  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
327ce72dbaSJustin T. Gibbs  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
337ce72dbaSJustin T. Gibbs  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
347ce72dbaSJustin T. Gibbs  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
357ce72dbaSJustin T. Gibbs  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36c5cb3888SJustin T. Gibbs  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37c5cb3888SJustin T. Gibbs  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
387ce72dbaSJustin T. Gibbs  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
397ce72dbaSJustin T. Gibbs  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
407ce72dbaSJustin T. Gibbs  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
417ce72dbaSJustin T. Gibbs  * POSSIBILITY OF SUCH DAMAGES.
42c5cb3888SJustin T. Gibbs  *
433d46a688SJustin T. Gibbs  * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm_gram.y#29 $
44c5cb3888SJustin T. Gibbs  */
45c5cb3888SJustin T. Gibbs 
467ce72dbaSJustin T. Gibbs #include <sys/types.h>
477ce72dbaSJustin T. Gibbs 
48083d01f2SJustin T. Gibbs #include <inttypes.h>
497ce72dbaSJustin T. Gibbs #include <regex.h>
50c5cb3888SJustin T. Gibbs #include <stdio.h>
51c5cb3888SJustin T. Gibbs #include <stdlib.h>
52c5cb3888SJustin T. Gibbs #include <string.h>
53c5cb3888SJustin T. Gibbs #include <sysexits.h>
54c5cb3888SJustin T. Gibbs #include <sys/queue.h>
55c5cb3888SJustin T. Gibbs 
56c66dbc92SJustin T. Gibbs #include "aicasm.h"
57c66dbc92SJustin T. Gibbs #include "aicasm_symbol.h"
58aa6dfd9dSJustin T. Gibbs #include "aicasm_insformat.h"
59c5cb3888SJustin T. Gibbs 
60*5e912f5fSJessica Clarke extern int yylineno;
61c5cb3888SJustin T. Gibbs char *yyfilename;
6263183d8cSJustin T. Gibbs char stock_prefix[] = "aic_";
6363183d8cSJustin T. Gibbs char *prefix = stock_prefix;
647ce72dbaSJustin T. Gibbs char *patch_arg_list;
652d0fbde8SJustin T. Gibbs char *versions;
667ce72dbaSJustin T. Gibbs static char errbuf[255];
677ce72dbaSJustin T. Gibbs static char regex_pattern[255];
68c5cb3888SJustin T. Gibbs static symbol_t *cur_symbol;
6963183d8cSJustin T. Gibbs static symbol_t *field_symbol;
707ce72dbaSJustin T. Gibbs static symbol_t *scb_or_sram_symbol;
71c5cb3888SJustin T. Gibbs static symtype cur_symtype;
727ce72dbaSJustin T. Gibbs static symbol_ref_t accumulator;
737ce72dbaSJustin T. Gibbs static symbol_ref_t mode_ptr;
74c5cb3888SJustin T. Gibbs static symbol_ref_t allones;
75c5cb3888SJustin T. Gibbs static symbol_ref_t allzeros;
76c5cb3888SJustin T. Gibbs static symbol_ref_t none;
77c5cb3888SJustin T. Gibbs static symbol_ref_t sindex;
78c5cb3888SJustin T. Gibbs static int instruction_ptr;
797ce72dbaSJustin T. Gibbs static int num_srams;
80c5cb3888SJustin T. Gibbs static int sram_or_scb_offset;
8137507c1bSJustin T. Gibbs static int download_constant_count;
82083d01f2SJustin T. Gibbs static int in_critical_section;
8363183d8cSJustin T. Gibbs static u_int enum_increment;
8463183d8cSJustin T. Gibbs static u_int enum_next_value;
85c5cb3888SJustin T. Gibbs 
86b18a2ef1SXin LI static void process_field(unsigned int field_type, symbol_t *sym, int mask);
8732da3127SJustin T. Gibbs static void initialize_symbol(symbol_t *symbol);
887ce72dbaSJustin T. Gibbs static void add_macro_arg(const char *argtext, int position);
897ce72dbaSJustin T. Gibbs static void add_macro_body(const char *bodytext);
9032da3127SJustin T. Gibbs static void process_register(symbol_t **p_symbol);
9132da3127SJustin T. Gibbs static void format_1_instr(int opcode, symbol_ref_t *dest,
9232da3127SJustin T. Gibbs 			   expression_t *immed, symbol_ref_t *src, int ret);
9332da3127SJustin T. Gibbs static void format_2_instr(int opcode, symbol_ref_t *dest,
9432da3127SJustin T. Gibbs 			   expression_t *places, symbol_ref_t *src, int ret);
9532da3127SJustin T. Gibbs static void format_3_instr(int opcode, symbol_ref_t *src,
9632da3127SJustin T. Gibbs 			   expression_t *immed, symbol_ref_t *address);
9732da3127SJustin T. Gibbs static void test_readable_symbol(symbol_t *symbol);
9832da3127SJustin T. Gibbs static void test_writable_symbol(symbol_t *symbol);
9932da3127SJustin T. Gibbs static void type_check(symbol_t *symbol, expression_t *expression, int and_op);
10032da3127SJustin T. Gibbs static void make_expression(expression_t *immed, int value);
10132da3127SJustin T. Gibbs static void add_conditional(symbol_t *symbol);
1022d0fbde8SJustin T. Gibbs static void add_version(const char *verstring);
10332da3127SJustin T. Gibbs static int  is_download_const(expression_t *immed);
104c5cb3888SJustin T. Gibbs 
105b18a2ef1SXin LI extern int yylex (void);
106b18a2ef1SXin LI 
107c5cb3888SJustin T. Gibbs #define SRAM_SYMNAME "SRAM_BASE"
108c5cb3888SJustin T. Gibbs #define SCB_SYMNAME "SCB_BASE"
109c5cb3888SJustin T. Gibbs %}
110c5cb3888SJustin T. Gibbs 
111c5cb3888SJustin T. Gibbs %union {
1127ce72dbaSJustin T. Gibbs 	u_int		value;
113c5cb3888SJustin T. Gibbs 	char		*str;
114c5cb3888SJustin T. Gibbs 	symbol_t	*sym;
115c5cb3888SJustin T. Gibbs 	symbol_ref_t	sym_ref;
116c5cb3888SJustin T. Gibbs 	expression_t	expression;
117c5cb3888SJustin T. Gibbs }
118c5cb3888SJustin T. Gibbs 
119c5cb3888SJustin T. Gibbs %token T_REGISTER
120c5cb3888SJustin T. Gibbs 
121c5cb3888SJustin T. Gibbs %token <value> T_CONST
122c5cb3888SJustin T. Gibbs 
1237ce72dbaSJustin T. Gibbs %token T_EXPORT
1247ce72dbaSJustin T. Gibbs 
12537507c1bSJustin T. Gibbs %token T_DOWNLOAD
12637507c1bSJustin T. Gibbs 
127c5cb3888SJustin T. Gibbs %token T_SCB
128c5cb3888SJustin T. Gibbs 
129c5cb3888SJustin T. Gibbs %token T_SRAM
130c5cb3888SJustin T. Gibbs 
131c5cb3888SJustin T. Gibbs %token T_ALIAS
132c5cb3888SJustin T. Gibbs 
133c5cb3888SJustin T. Gibbs %token T_SIZE
134c5cb3888SJustin T. Gibbs 
1357ce72dbaSJustin T. Gibbs %token T_EXPR_LSHIFT
1367ce72dbaSJustin T. Gibbs 
1377ce72dbaSJustin T. Gibbs %token T_EXPR_RSHIFT
1387ce72dbaSJustin T. Gibbs 
139c5cb3888SJustin T. Gibbs %token <value> T_ADDRESS
140c5cb3888SJustin T. Gibbs 
141c5cb3888SJustin T. Gibbs %token T_ACCESS_MODE
142c5cb3888SJustin T. Gibbs 
1437ce72dbaSJustin T. Gibbs %token T_MODES
1447ce72dbaSJustin T. Gibbs 
1457ce72dbaSJustin T. Gibbs %token T_DEFINE
1467ce72dbaSJustin T. Gibbs 
1477ce72dbaSJustin T. Gibbs %token T_SET_SRC_MODE
1487ce72dbaSJustin T. Gibbs 
1497ce72dbaSJustin T. Gibbs %token T_SET_DST_MODE
1507ce72dbaSJustin T. Gibbs 
151c5cb3888SJustin T. Gibbs %token <value> T_MODE
152c5cb3888SJustin T. Gibbs 
153083d01f2SJustin T. Gibbs %token T_BEGIN_CS
154083d01f2SJustin T. Gibbs 
155083d01f2SJustin T. Gibbs %token T_END_CS
156083d01f2SJustin T. Gibbs 
15763183d8cSJustin T. Gibbs %token T_FIELD
15863183d8cSJustin T. Gibbs 
15963183d8cSJustin T. Gibbs %token T_ENUM
160c5cb3888SJustin T. Gibbs 
161c5cb3888SJustin T. Gibbs %token T_MASK
162c5cb3888SJustin T. Gibbs 
163c5cb3888SJustin T. Gibbs %token <value> T_NUMBER
164c5cb3888SJustin T. Gibbs 
1657ce72dbaSJustin T. Gibbs %token <str> T_PATH T_STRING T_ARG T_MACROBODY
166c5cb3888SJustin T. Gibbs 
1673bafc9d4SJustin T. Gibbs %token <sym> T_CEXPR
1683bafc9d4SJustin T. Gibbs 
16963183d8cSJustin T. Gibbs %token T_EOF T_INCLUDE T_VERSION T_PREFIX T_PATCH_ARG_LIST
170c5cb3888SJustin T. Gibbs 
171c5cb3888SJustin T. Gibbs %token <value> T_SHR T_SHL T_ROR T_ROL
172c5cb3888SJustin T. Gibbs 
1733bafc9d4SJustin T. Gibbs %token <value> T_MVI T_MOV T_CLR T_BMOV
174c5cb3888SJustin T. Gibbs 
175c5cb3888SJustin T. Gibbs %token <value> T_JMP T_JC T_JNC T_JE T_JNE T_JNZ T_JZ T_CALL
176c5cb3888SJustin T. Gibbs 
177c5cb3888SJustin T. Gibbs %token <value> T_ADD T_ADC
178c5cb3888SJustin T. Gibbs 
179c5cb3888SJustin T. Gibbs %token <value> T_INC T_DEC
180c5cb3888SJustin T. Gibbs 
181c5cb3888SJustin T. Gibbs %token <value> T_STC T_CLC
182c5cb3888SJustin T. Gibbs 
183aa6dfd9dSJustin T. Gibbs %token <value> T_CMP T_NOT T_XOR
184c5cb3888SJustin T. Gibbs 
185c5cb3888SJustin T. Gibbs %token <value> T_TEST T_AND
186c5cb3888SJustin T. Gibbs 
187c5cb3888SJustin T. Gibbs %token <value> T_OR
188c5cb3888SJustin T. Gibbs 
189c5cb3888SJustin T. Gibbs %token T_RET
190c5cb3888SJustin T. Gibbs 
191c5cb3888SJustin T. Gibbs %token T_NOP
192c5cb3888SJustin T. Gibbs 
1937ce72dbaSJustin T. Gibbs %token T_ACCUM T_ALLONES T_ALLZEROS T_NONE T_SINDEX T_MODE_PTR
194c5cb3888SJustin T. Gibbs 
195c5cb3888SJustin T. Gibbs %token T_A
196c5cb3888SJustin T. Gibbs 
197c5cb3888SJustin T. Gibbs %token <sym> T_SYMBOL
198c5cb3888SJustin T. Gibbs 
199c5cb3888SJustin T. Gibbs %token T_NL
200c5cb3888SJustin T. Gibbs 
2013bafc9d4SJustin T. Gibbs %token T_IF T_ELSE T_ELSE_IF T_ENDIF
202c5cb3888SJustin T. Gibbs 
203c5cb3888SJustin T. Gibbs %type <sym_ref> reg_symbol address destination source opt_source
204c5cb3888SJustin T. Gibbs 
205c5cb3888SJustin T. Gibbs %type <expression> expression immediate immediate_or_a
206c5cb3888SJustin T. Gibbs 
2077ce72dbaSJustin T. Gibbs %type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne
208c5cb3888SJustin T. Gibbs 
2093d46a688SJustin T. Gibbs %type <value> mode_value mode_list macro_arglist
21037507c1bSJustin T. Gibbs 
211c5cb3888SJustin T. Gibbs %left '|'
212c5cb3888SJustin T. Gibbs %left '&'
2137ce72dbaSJustin T. Gibbs %left T_EXPR_LSHIFT T_EXPR_RSHIFT
214c5cb3888SJustin T. Gibbs %left '+' '-'
2157ce72dbaSJustin T. Gibbs %left '*' '/'
216c5cb3888SJustin T. Gibbs %right '~'
217c5cb3888SJustin T. Gibbs %nonassoc UMINUS
218c5cb3888SJustin T. Gibbs %%
219c5cb3888SJustin T. Gibbs 
220c5cb3888SJustin T. Gibbs program:
221c5cb3888SJustin T. Gibbs 	include
222c5cb3888SJustin T. Gibbs |	program include
22363183d8cSJustin T. Gibbs |	prefix
22463183d8cSJustin T. Gibbs |	program prefix
2257ce72dbaSJustin T. Gibbs |	patch_arg_list
2267ce72dbaSJustin T. Gibbs |	program patch_arg_list
2272d0fbde8SJustin T. Gibbs |	version
2282d0fbde8SJustin T. Gibbs |	program version
229c5cb3888SJustin T. Gibbs |	register
230c5cb3888SJustin T. Gibbs |	program register
231c5cb3888SJustin T. Gibbs |	constant
232c5cb3888SJustin T. Gibbs |	program constant
2337ce72dbaSJustin T. Gibbs |	macrodefn
2347ce72dbaSJustin T. Gibbs |	program macrodefn
235c5cb3888SJustin T. Gibbs |	scratch_ram
236c5cb3888SJustin T. Gibbs |	program scratch_ram
237c5cb3888SJustin T. Gibbs |	scb
238c5cb3888SJustin T. Gibbs |	program scb
239c5cb3888SJustin T. Gibbs |	label
240c5cb3888SJustin T. Gibbs |	program label
2417ce72dbaSJustin T. Gibbs |	set_src_mode
2427ce72dbaSJustin T. Gibbs |	program set_src_mode
2437ce72dbaSJustin T. Gibbs |	set_dst_mode
2447ce72dbaSJustin T. Gibbs |	program set_dst_mode
245083d01f2SJustin T. Gibbs |	critical_section_start
246083d01f2SJustin T. Gibbs |	program critical_section_start
247083d01f2SJustin T. Gibbs |	critical_section_end
248083d01f2SJustin T. Gibbs |	program critical_section_end
249c5cb3888SJustin T. Gibbs |	conditional
250c5cb3888SJustin T. Gibbs |	program conditional
251c5cb3888SJustin T. Gibbs |	code
252c5cb3888SJustin T. Gibbs |	program code
253c5cb3888SJustin T. Gibbs ;
254c5cb3888SJustin T. Gibbs 
255c5cb3888SJustin T. Gibbs include:
256c5cb3888SJustin T. Gibbs 	T_INCLUDE '<' T_PATH '>'
2572d0fbde8SJustin T. Gibbs 	{
2582d0fbde8SJustin T. Gibbs 		include_file($3, BRACKETED_INCLUDE);
2592d0fbde8SJustin T. Gibbs 	}
260c5cb3888SJustin T. Gibbs |	T_INCLUDE '"' T_PATH '"'
2612d0fbde8SJustin T. Gibbs 	{
2622d0fbde8SJustin T. Gibbs 		include_file($3, QUOTED_INCLUDE);
2632d0fbde8SJustin T. Gibbs 	}
2642d0fbde8SJustin T. Gibbs ;
2652d0fbde8SJustin T. Gibbs 
26663183d8cSJustin T. Gibbs prefix:
26763183d8cSJustin T. Gibbs 	T_PREFIX '=' T_STRING
26863183d8cSJustin T. Gibbs 	{
26963183d8cSJustin T. Gibbs 		if (prefix != stock_prefix)
27063183d8cSJustin T. Gibbs 			stop("Prefix multiply defined",
27163183d8cSJustin T. Gibbs 			     EX_DATAERR);
27263183d8cSJustin T. Gibbs 		prefix = strdup($3);
27363183d8cSJustin T. Gibbs 		if (prefix == NULL)
27463183d8cSJustin T. Gibbs 			stop("Unable to record prefix", EX_SOFTWARE);
27563183d8cSJustin T. Gibbs 	}
27663183d8cSJustin T. Gibbs ;
27763183d8cSJustin T. Gibbs 
2787ce72dbaSJustin T. Gibbs patch_arg_list:
2797ce72dbaSJustin T. Gibbs 	T_PATCH_ARG_LIST '=' T_STRING
2807ce72dbaSJustin T. Gibbs 	{
2817ce72dbaSJustin T. Gibbs 		if (patch_arg_list != NULL)
2827ce72dbaSJustin T. Gibbs 			stop("Patch argument list multiply defined",
2837ce72dbaSJustin T. Gibbs 			     EX_DATAERR);
2847ce72dbaSJustin T. Gibbs 		patch_arg_list = strdup($3);
2857ce72dbaSJustin T. Gibbs 		if (patch_arg_list == NULL)
2867ce72dbaSJustin T. Gibbs 			stop("Unable to record patch arg list", EX_SOFTWARE);
2877ce72dbaSJustin T. Gibbs 	}
2887ce72dbaSJustin T. Gibbs ;
2897ce72dbaSJustin T. Gibbs 
2902d0fbde8SJustin T. Gibbs version:
2912d0fbde8SJustin T. Gibbs 	T_VERSION '=' T_STRING
2922d0fbde8SJustin T. Gibbs 	{ add_version($3); }
293c5cb3888SJustin T. Gibbs ;
294c5cb3888SJustin T. Gibbs 
295c5cb3888SJustin T. Gibbs register:
296c5cb3888SJustin T. Gibbs 	T_REGISTER { cur_symtype = REGISTER; } reg_definition
297c5cb3888SJustin T. Gibbs ;
298c5cb3888SJustin T. Gibbs 
299c5cb3888SJustin T. Gibbs reg_definition:
300c5cb3888SJustin T. Gibbs 	T_SYMBOL '{'
301c5cb3888SJustin T. Gibbs 		{
302c5cb3888SJustin T. Gibbs 			if ($1->type != UNINITIALIZED) {
303c5cb3888SJustin T. Gibbs 				stop("Register multiply defined", EX_DATAERR);
304c5cb3888SJustin T. Gibbs 				/* NOTREACHED */
305c5cb3888SJustin T. Gibbs 			}
306c5cb3888SJustin T. Gibbs 			cur_symbol = $1;
307c5cb3888SJustin T. Gibbs 			cur_symbol->type = cur_symtype;
308c5cb3888SJustin T. Gibbs 			initialize_symbol(cur_symbol);
309c5cb3888SJustin T. Gibbs 		}
310c5cb3888SJustin T. Gibbs 		reg_attribute_list
311c5cb3888SJustin T. Gibbs 	'}'
312c5cb3888SJustin T. Gibbs 		{
313c5cb3888SJustin T. Gibbs 			/*
314c5cb3888SJustin T. Gibbs 			 * Default to allowing everything in for registers
315c5cb3888SJustin T. Gibbs 			 * with no bit or mask definitions.
316c5cb3888SJustin T. Gibbs 			 */
317c5cb3888SJustin T. Gibbs 			if (cur_symbol->info.rinfo->valid_bitmask == 0)
318c5cb3888SJustin T. Gibbs 				cur_symbol->info.rinfo->valid_bitmask = 0xFF;
319c5cb3888SJustin T. Gibbs 
320c5cb3888SJustin T. Gibbs 			if (cur_symbol->info.rinfo->size == 0)
321c5cb3888SJustin T. Gibbs 				cur_symbol->info.rinfo->size = 1;
322c5cb3888SJustin T. Gibbs 
323c5cb3888SJustin T. Gibbs 			/*
324c5cb3888SJustin T. Gibbs 			 * This might be useful for registers too.
325c5cb3888SJustin T. Gibbs 			 */
326c5cb3888SJustin T. Gibbs 			if (cur_symbol->type != REGISTER) {
327c5cb3888SJustin T. Gibbs 				if (cur_symbol->info.rinfo->address == 0)
328c5cb3888SJustin T. Gibbs 					cur_symbol->info.rinfo->address =
329c5cb3888SJustin T. Gibbs 					    sram_or_scb_offset;
330c5cb3888SJustin T. Gibbs 				sram_or_scb_offset +=
331c5cb3888SJustin T. Gibbs 				    cur_symbol->info.rinfo->size;
332c5cb3888SJustin T. Gibbs 			}
333c5cb3888SJustin T. Gibbs 			cur_symbol = NULL;
334c5cb3888SJustin T. Gibbs 		}
335c5cb3888SJustin T. Gibbs ;
336c5cb3888SJustin T. Gibbs 
337c5cb3888SJustin T. Gibbs reg_attribute_list:
338c5cb3888SJustin T. Gibbs 	reg_attribute
339c5cb3888SJustin T. Gibbs |	reg_attribute_list reg_attribute
340c5cb3888SJustin T. Gibbs ;
341c5cb3888SJustin T. Gibbs 
342c5cb3888SJustin T. Gibbs reg_attribute:
343c5cb3888SJustin T. Gibbs 	reg_address
344c5cb3888SJustin T. Gibbs |	size
345c5cb3888SJustin T. Gibbs |	access_mode
3467ce72dbaSJustin T. Gibbs |	modes
34763183d8cSJustin T. Gibbs |	field_defn
34863183d8cSJustin T. Gibbs |	enum_defn
349c5cb3888SJustin T. Gibbs |	mask_defn
350c5cb3888SJustin T. Gibbs |	alias
351c5cb3888SJustin T. Gibbs |	accumulator
3527ce72dbaSJustin T. Gibbs |	mode_pointer
353c5cb3888SJustin T. Gibbs |	allones
354c5cb3888SJustin T. Gibbs |	allzeros
355c5cb3888SJustin T. Gibbs |	none
356c5cb3888SJustin T. Gibbs |	sindex
357c5cb3888SJustin T. Gibbs ;
358c5cb3888SJustin T. Gibbs 
359c5cb3888SJustin T. Gibbs reg_address:
360c5cb3888SJustin T. Gibbs 	T_ADDRESS T_NUMBER
361c5cb3888SJustin T. Gibbs 	{
362c5cb3888SJustin T. Gibbs 		cur_symbol->info.rinfo->address = $2;
363c5cb3888SJustin T. Gibbs 	}
364c5cb3888SJustin T. Gibbs ;
365c5cb3888SJustin T. Gibbs 
366c5cb3888SJustin T. Gibbs size:
367c5cb3888SJustin T. Gibbs 	T_SIZE T_NUMBER
368c5cb3888SJustin T. Gibbs 	{
369c5cb3888SJustin T. Gibbs 		cur_symbol->info.rinfo->size = $2;
3707ce72dbaSJustin T. Gibbs 		if (scb_or_sram_symbol != NULL) {
3717ce72dbaSJustin T. Gibbs 			u_int max_addr;
3727ce72dbaSJustin T. Gibbs 			u_int sym_max_addr;
3737ce72dbaSJustin T. Gibbs 
3747ce72dbaSJustin T. Gibbs 			max_addr = scb_or_sram_symbol->info.rinfo->address
3757ce72dbaSJustin T. Gibbs 				 + scb_or_sram_symbol->info.rinfo->size;
3767ce72dbaSJustin T. Gibbs 			sym_max_addr = cur_symbol->info.rinfo->address
3777ce72dbaSJustin T. Gibbs 				     + cur_symbol->info.rinfo->size;
3787ce72dbaSJustin T. Gibbs 
3797ce72dbaSJustin T. Gibbs 			if (sym_max_addr > max_addr)
3807ce72dbaSJustin T. Gibbs 				stop("SCB or SRAM space exhausted", EX_DATAERR);
3817ce72dbaSJustin T. Gibbs 		}
382c5cb3888SJustin T. Gibbs 	}
383c5cb3888SJustin T. Gibbs ;
384c5cb3888SJustin T. Gibbs 
385c5cb3888SJustin T. Gibbs access_mode:
386c5cb3888SJustin T. Gibbs 	T_ACCESS_MODE T_MODE
387c5cb3888SJustin T. Gibbs 	{
388c5cb3888SJustin T. Gibbs 		cur_symbol->info.rinfo->mode = $2;
389c5cb3888SJustin T. Gibbs 	}
390c5cb3888SJustin T. Gibbs ;
391c5cb3888SJustin T. Gibbs 
3927ce72dbaSJustin T. Gibbs modes:
3937ce72dbaSJustin T. Gibbs 	T_MODES mode_list
3947ce72dbaSJustin T. Gibbs 	{
3957ce72dbaSJustin T. Gibbs 		cur_symbol->info.rinfo->modes = $2;
3967ce72dbaSJustin T. Gibbs 	}
3977ce72dbaSJustin T. Gibbs ;
3987ce72dbaSJustin T. Gibbs 
3997ce72dbaSJustin T. Gibbs mode_list:
4007ce72dbaSJustin T. Gibbs 	mode_value
4017ce72dbaSJustin T. Gibbs 	{
4027ce72dbaSJustin T. Gibbs 		$$ = $1;
4037ce72dbaSJustin T. Gibbs 	}
4047ce72dbaSJustin T. Gibbs |	mode_list ',' mode_value
4057ce72dbaSJustin T. Gibbs 	{
4067ce72dbaSJustin T. Gibbs 		$$ = $1 | $3;
4077ce72dbaSJustin T. Gibbs 	}
4087ce72dbaSJustin T. Gibbs ;
4097ce72dbaSJustin T. Gibbs 
4107ce72dbaSJustin T. Gibbs mode_value:
4117ce72dbaSJustin T. Gibbs 	T_NUMBER
4127ce72dbaSJustin T. Gibbs 	{
4137ce72dbaSJustin T. Gibbs 		if ($1 > 4) {
4147ce72dbaSJustin T. Gibbs 			stop("Valid register modes range between 0 and 4.",
4157ce72dbaSJustin T. Gibbs 			     EX_DATAERR);
4167ce72dbaSJustin T. Gibbs 			/* NOTREACHED */
4177ce72dbaSJustin T. Gibbs 		}
4187ce72dbaSJustin T. Gibbs 
4197ce72dbaSJustin T. Gibbs 		$$ = (0x1 << $1);
4207ce72dbaSJustin T. Gibbs 	}
4217ce72dbaSJustin T. Gibbs |	T_SYMBOL
4227ce72dbaSJustin T. Gibbs 	{
4237ce72dbaSJustin T. Gibbs 		symbol_t *symbol;
4247ce72dbaSJustin T. Gibbs 
4257ce72dbaSJustin T. Gibbs 		symbol = $1;
4267ce72dbaSJustin T. Gibbs 		if (symbol->type != CONST) {
4277ce72dbaSJustin T. Gibbs 			stop("Only \"const\" symbols allowed in "
4287ce72dbaSJustin T. Gibbs 			     "mode definitions.", EX_DATAERR);
4297ce72dbaSJustin T. Gibbs 			/* NOTREACHED */
4307ce72dbaSJustin T. Gibbs 		}
4317ce72dbaSJustin T. Gibbs 		if (symbol->info.cinfo->value > 4) {
4327ce72dbaSJustin T. Gibbs 			stop("Valid register modes range between 0 and 4.",
4337ce72dbaSJustin T. Gibbs 			     EX_DATAERR);
4347ce72dbaSJustin T. Gibbs 			/* NOTREACHED */
4357ce72dbaSJustin T. Gibbs 		}
4367ce72dbaSJustin T. Gibbs 		$$ = (0x1 << symbol->info.cinfo->value);
4377ce72dbaSJustin T. Gibbs 	}
4387ce72dbaSJustin T. Gibbs ;
4397ce72dbaSJustin T. Gibbs 
44063183d8cSJustin T. Gibbs field_defn:
44163183d8cSJustin T. Gibbs 	T_FIELD
442c5cb3888SJustin T. Gibbs 		{
44363183d8cSJustin T. Gibbs 			field_symbol = NULL;
44463183d8cSJustin T. Gibbs 			enum_next_value = 0;
44563183d8cSJustin T. Gibbs 			enum_increment = 1;
44663183d8cSJustin T. Gibbs 		}
44763183d8cSJustin T. Gibbs 	'{' enum_entry_list '}'
44863183d8cSJustin T. Gibbs |	T_FIELD T_SYMBOL expression
44963183d8cSJustin T. Gibbs 		{
45063183d8cSJustin T. Gibbs 			process_field(FIELD, $2, $3.value);
45163183d8cSJustin T. Gibbs 			field_symbol = $2;
45263183d8cSJustin T. Gibbs 			enum_next_value = 0;
45363183d8cSJustin T. Gibbs 			enum_increment = 0x01 << (ffs($3.value) - 1);
45463183d8cSJustin T. Gibbs 		}
45563183d8cSJustin T. Gibbs 	'{' enum_entry_list '}'
45663183d8cSJustin T. Gibbs |	T_FIELD T_SYMBOL expression
45763183d8cSJustin T. Gibbs 	{
45863183d8cSJustin T. Gibbs 		process_field(FIELD, $2, $3.value);
45963183d8cSJustin T. Gibbs 	}
46063183d8cSJustin T. Gibbs ;
46163183d8cSJustin T. Gibbs 
46263183d8cSJustin T. Gibbs enum_defn:
46363183d8cSJustin T. Gibbs 	T_ENUM
46463183d8cSJustin T. Gibbs 		{
46563183d8cSJustin T. Gibbs 			field_symbol = NULL;
46663183d8cSJustin T. Gibbs 			enum_next_value = 0;
46763183d8cSJustin T. Gibbs 			enum_increment = 1;
46863183d8cSJustin T. Gibbs 		}
46963183d8cSJustin T. Gibbs 	'{' enum_entry_list '}'
47063183d8cSJustin T. Gibbs |	T_ENUM T_SYMBOL expression
47163183d8cSJustin T. Gibbs 		{
47263183d8cSJustin T. Gibbs 			process_field(ENUM, $2, $3.value);
47363183d8cSJustin T. Gibbs 			field_symbol = $2;
47463183d8cSJustin T. Gibbs 			enum_next_value = 0;
47563183d8cSJustin T. Gibbs 			enum_increment = 0x01 << (ffs($3.value) - 1);
47663183d8cSJustin T. Gibbs 		}
47763183d8cSJustin T. Gibbs 	'{' enum_entry_list '}'
47863183d8cSJustin T. Gibbs ;
47963183d8cSJustin T. Gibbs 
48063183d8cSJustin T. Gibbs enum_entry_list:
48163183d8cSJustin T. Gibbs 	enum_entry
48263183d8cSJustin T. Gibbs |	enum_entry_list ',' enum_entry
48363183d8cSJustin T. Gibbs ;
48463183d8cSJustin T. Gibbs 
48563183d8cSJustin T. Gibbs enum_entry:
48663183d8cSJustin T. Gibbs 	T_SYMBOL
48763183d8cSJustin T. Gibbs 	{
48863183d8cSJustin T. Gibbs 		process_field(ENUM_ENTRY, $1, enum_next_value);
48963183d8cSJustin T. Gibbs 		enum_next_value += enum_increment;
49063183d8cSJustin T. Gibbs 	}
49163183d8cSJustin T. Gibbs |	T_SYMBOL expression
49263183d8cSJustin T. Gibbs 	{
49363183d8cSJustin T. Gibbs 		process_field(ENUM_ENTRY, $1, $2.value);
49463183d8cSJustin T. Gibbs 		enum_next_value = $2.value + enum_increment;
495c5cb3888SJustin T. Gibbs 	}
496c5cb3888SJustin T. Gibbs ;
497c5cb3888SJustin T. Gibbs 
498c5cb3888SJustin T. Gibbs mask_defn:
499c5cb3888SJustin T. Gibbs 	T_MASK T_SYMBOL expression
500c5cb3888SJustin T. Gibbs 	{
50163183d8cSJustin T. Gibbs 		process_field(MASK, $2, $3.value);
502c5cb3888SJustin T. Gibbs 	}
503c5cb3888SJustin T. Gibbs ;
504c5cb3888SJustin T. Gibbs 
505c5cb3888SJustin T. Gibbs alias:
506c5cb3888SJustin T. Gibbs 	T_ALIAS	T_SYMBOL
507c5cb3888SJustin T. Gibbs 	{
508c5cb3888SJustin T. Gibbs 		if ($2->type != UNINITIALIZED) {
509c5cb3888SJustin T. Gibbs 			stop("Re-definition of register alias",
510c5cb3888SJustin T. Gibbs 			     EX_DATAERR);
511c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
512c5cb3888SJustin T. Gibbs 		}
513c5cb3888SJustin T. Gibbs 		$2->type = ALIAS;
514c5cb3888SJustin T. Gibbs 		initialize_symbol($2);
515c5cb3888SJustin T. Gibbs 		$2->info.ainfo->parent = cur_symbol;
516c5cb3888SJustin T. Gibbs 	}
517c5cb3888SJustin T. Gibbs ;
518c5cb3888SJustin T. Gibbs 
519c5cb3888SJustin T. Gibbs accumulator:
520c5cb3888SJustin T. Gibbs 	T_ACCUM
521c5cb3888SJustin T. Gibbs 	{
5227ce72dbaSJustin T. Gibbs 		if (accumulator.symbol != NULL) {
523c5cb3888SJustin T. Gibbs 			stop("Only one accumulator definition allowed",
524c5cb3888SJustin T. Gibbs 			     EX_DATAERR);
525c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
526c5cb3888SJustin T. Gibbs 		}
5277ce72dbaSJustin T. Gibbs 		accumulator.symbol = cur_symbol;
5287ce72dbaSJustin T. Gibbs 	}
5297ce72dbaSJustin T. Gibbs ;
5307ce72dbaSJustin T. Gibbs 
5317ce72dbaSJustin T. Gibbs mode_pointer:
5327ce72dbaSJustin T. Gibbs 	T_MODE_PTR
5337ce72dbaSJustin T. Gibbs 	{
5347ce72dbaSJustin T. Gibbs 		if (mode_ptr.symbol != NULL) {
5357ce72dbaSJustin T. Gibbs 			stop("Only one mode pointer definition allowed",
5367ce72dbaSJustin T. Gibbs 			     EX_DATAERR);
5377ce72dbaSJustin T. Gibbs 			/* NOTREACHED */
5387ce72dbaSJustin T. Gibbs 		}
5397ce72dbaSJustin T. Gibbs 		mode_ptr.symbol = cur_symbol;
540c5cb3888SJustin T. Gibbs 	}
541c5cb3888SJustin T. Gibbs ;
542c5cb3888SJustin T. Gibbs 
543c5cb3888SJustin T. Gibbs allones:
544c5cb3888SJustin T. Gibbs 	T_ALLONES
545c5cb3888SJustin T. Gibbs 	{
546c5cb3888SJustin T. Gibbs 		if (allones.symbol != NULL) {
547c5cb3888SJustin T. Gibbs 			stop("Only one definition of allones allowed",
548c5cb3888SJustin T. Gibbs 			     EX_DATAERR);
549c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
550c5cb3888SJustin T. Gibbs 		}
551c5cb3888SJustin T. Gibbs 		allones.symbol = cur_symbol;
552c5cb3888SJustin T. Gibbs 	}
553c5cb3888SJustin T. Gibbs ;
554c5cb3888SJustin T. Gibbs 
555c5cb3888SJustin T. Gibbs allzeros:
556c5cb3888SJustin T. Gibbs 	T_ALLZEROS
557c5cb3888SJustin T. Gibbs 	{
558c5cb3888SJustin T. Gibbs 		if (allzeros.symbol != NULL) {
559c5cb3888SJustin T. Gibbs 			stop("Only one definition of allzeros allowed",
560c5cb3888SJustin T. Gibbs 			     EX_DATAERR);
561c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
562c5cb3888SJustin T. Gibbs 		}
563c5cb3888SJustin T. Gibbs 		allzeros.symbol = cur_symbol;
564c5cb3888SJustin T. Gibbs 	}
565c5cb3888SJustin T. Gibbs ;
566c5cb3888SJustin T. Gibbs 
567c5cb3888SJustin T. Gibbs none:
568c5cb3888SJustin T. Gibbs 	T_NONE
569c5cb3888SJustin T. Gibbs 	{
570c5cb3888SJustin T. Gibbs 		if (none.symbol != NULL) {
571c5cb3888SJustin T. Gibbs 			stop("Only one definition of none allowed",
572c5cb3888SJustin T. Gibbs 			     EX_DATAERR);
573c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
574c5cb3888SJustin T. Gibbs 		}
575c5cb3888SJustin T. Gibbs 		none.symbol = cur_symbol;
576c5cb3888SJustin T. Gibbs 	}
577c5cb3888SJustin T. Gibbs ;
578c5cb3888SJustin T. Gibbs 
579c5cb3888SJustin T. Gibbs sindex:
580c5cb3888SJustin T. Gibbs 	T_SINDEX
581c5cb3888SJustin T. Gibbs 	{
582c5cb3888SJustin T. Gibbs 		if (sindex.symbol != NULL) {
583c5cb3888SJustin T. Gibbs 			stop("Only one definition of sindex allowed",
584c5cb3888SJustin T. Gibbs 			     EX_DATAERR);
585c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
586c5cb3888SJustin T. Gibbs 		}
587c5cb3888SJustin T. Gibbs 		sindex.symbol = cur_symbol;
588c5cb3888SJustin T. Gibbs 	}
589c5cb3888SJustin T. Gibbs ;
590c5cb3888SJustin T. Gibbs 
591c5cb3888SJustin T. Gibbs expression:
592c5cb3888SJustin T. Gibbs 	expression '|' expression
593c5cb3888SJustin T. Gibbs 	{
594c5cb3888SJustin T. Gibbs 		 $$.value = $1.value | $3.value;
595c5cb3888SJustin T. Gibbs 		 symlist_merge(&$$.referenced_syms,
596c5cb3888SJustin T. Gibbs 			       &$1.referenced_syms,
597c5cb3888SJustin T. Gibbs 			       &$3.referenced_syms);
598c5cb3888SJustin T. Gibbs 	}
599c5cb3888SJustin T. Gibbs |	expression '&' expression
600c5cb3888SJustin T. Gibbs 	{
601c5cb3888SJustin T. Gibbs 		$$.value = $1.value & $3.value;
602c5cb3888SJustin T. Gibbs 		symlist_merge(&$$.referenced_syms,
603c5cb3888SJustin T. Gibbs 			       &$1.referenced_syms,
604c5cb3888SJustin T. Gibbs 			       &$3.referenced_syms);
605c5cb3888SJustin T. Gibbs 	}
606c5cb3888SJustin T. Gibbs |	expression '+' expression
607c5cb3888SJustin T. Gibbs 	{
608c5cb3888SJustin T. Gibbs 		$$.value = $1.value + $3.value;
609c5cb3888SJustin T. Gibbs 		symlist_merge(&$$.referenced_syms,
610c5cb3888SJustin T. Gibbs 			       &$1.referenced_syms,
611c5cb3888SJustin T. Gibbs 			       &$3.referenced_syms);
612c5cb3888SJustin T. Gibbs 	}
613c5cb3888SJustin T. Gibbs |	expression '-' expression
614c5cb3888SJustin T. Gibbs 	{
615c5cb3888SJustin T. Gibbs 		$$.value = $1.value - $3.value;
616c5cb3888SJustin T. Gibbs 		symlist_merge(&($$.referenced_syms),
617c5cb3888SJustin T. Gibbs 			       &($1.referenced_syms),
618c5cb3888SJustin T. Gibbs 			       &($3.referenced_syms));
619c5cb3888SJustin T. Gibbs 	}
6207ce72dbaSJustin T. Gibbs |	expression '*' expression
6217ce72dbaSJustin T. Gibbs 	{
6227ce72dbaSJustin T. Gibbs 		$$.value = $1.value * $3.value;
6237ce72dbaSJustin T. Gibbs 		symlist_merge(&($$.referenced_syms),
6247ce72dbaSJustin T. Gibbs 			       &($1.referenced_syms),
6257ce72dbaSJustin T. Gibbs 			       &($3.referenced_syms));
6267ce72dbaSJustin T. Gibbs 	}
6277ce72dbaSJustin T. Gibbs |	expression '/' expression
6287ce72dbaSJustin T. Gibbs 	{
6297ce72dbaSJustin T. Gibbs 		$$.value = $1.value / $3.value;
6307ce72dbaSJustin T. Gibbs 		symlist_merge(&($$.referenced_syms),
6317ce72dbaSJustin T. Gibbs 			       &($1.referenced_syms),
6327ce72dbaSJustin T. Gibbs 			       &($3.referenced_syms));
6337ce72dbaSJustin T. Gibbs 	}
6347ce72dbaSJustin T. Gibbs | 	expression T_EXPR_LSHIFT expression
6357ce72dbaSJustin T. Gibbs 	{
6367ce72dbaSJustin T. Gibbs 		$$.value = $1.value << $3.value;
6377ce72dbaSJustin T. Gibbs 		symlist_merge(&$$.referenced_syms,
6387ce72dbaSJustin T. Gibbs 			       &$1.referenced_syms,
6397ce72dbaSJustin T. Gibbs 			       &$3.referenced_syms);
6407ce72dbaSJustin T. Gibbs 	}
6417ce72dbaSJustin T. Gibbs | 	expression T_EXPR_RSHIFT expression
6427ce72dbaSJustin T. Gibbs 	{
6437ce72dbaSJustin T. Gibbs 		$$.value = $1.value >> $3.value;
6447ce72dbaSJustin T. Gibbs 		symlist_merge(&$$.referenced_syms,
6457ce72dbaSJustin T. Gibbs 			       &$1.referenced_syms,
6467ce72dbaSJustin T. Gibbs 			       &$3.referenced_syms);
6477ce72dbaSJustin T. Gibbs 	}
648c5cb3888SJustin T. Gibbs |	'(' expression ')'
649c5cb3888SJustin T. Gibbs 	{
650c5cb3888SJustin T. Gibbs 		$$ = $2;
651c5cb3888SJustin T. Gibbs 	}
652c5cb3888SJustin T. Gibbs |	'~' expression
653c5cb3888SJustin T. Gibbs 	{
654c5cb3888SJustin T. Gibbs 		$$ = $2;
655c5cb3888SJustin T. Gibbs 		$$.value = (~$$.value) & 0xFF;
656c5cb3888SJustin T. Gibbs 	}
657c5cb3888SJustin T. Gibbs |	'-' expression %prec UMINUS
658c5cb3888SJustin T. Gibbs 	{
659c5cb3888SJustin T. Gibbs 		$$ = $2;
660c5cb3888SJustin T. Gibbs 		$$.value = -$$.value;
661c5cb3888SJustin T. Gibbs 	}
662c5cb3888SJustin T. Gibbs |	T_NUMBER
663c5cb3888SJustin T. Gibbs 	{
664c5cb3888SJustin T. Gibbs 		$$.value = $1;
665c5cb3888SJustin T. Gibbs 		SLIST_INIT(&$$.referenced_syms);
666c5cb3888SJustin T. Gibbs 	}
667c5cb3888SJustin T. Gibbs |	T_SYMBOL
668c5cb3888SJustin T. Gibbs 	{
669c5cb3888SJustin T. Gibbs 		symbol_t *symbol;
670c5cb3888SJustin T. Gibbs 
671c5cb3888SJustin T. Gibbs 		symbol = $1;
672c5cb3888SJustin T. Gibbs 		switch (symbol->type) {
673c5cb3888SJustin T. Gibbs 		case ALIAS:
674c5cb3888SJustin T. Gibbs 			symbol = $1->info.ainfo->parent;
675c5cb3888SJustin T. Gibbs 		case REGISTER:
676c5cb3888SJustin T. Gibbs 		case SCBLOC:
677c5cb3888SJustin T. Gibbs 		case SRAMLOC:
678c5cb3888SJustin T. Gibbs 			$$.value = symbol->info.rinfo->address;
679c5cb3888SJustin T. Gibbs 			break;
680c5cb3888SJustin T. Gibbs 		case MASK:
68163183d8cSJustin T. Gibbs 		case FIELD:
68263183d8cSJustin T. Gibbs 		case ENUM:
68363183d8cSJustin T. Gibbs 		case ENUM_ENTRY:
68463183d8cSJustin T. Gibbs 			$$.value = symbol->info.finfo->value;
685c5cb3888SJustin T. Gibbs 			break;
68637507c1bSJustin T. Gibbs 		case DOWNLOAD_CONST:
687c5cb3888SJustin T. Gibbs 		case CONST:
688c5cb3888SJustin T. Gibbs 			$$.value = symbol->info.cinfo->value;
689c5cb3888SJustin T. Gibbs 			break;
690c5cb3888SJustin T. Gibbs 		case UNINITIALIZED:
691c5cb3888SJustin T. Gibbs 		default:
692c5cb3888SJustin T. Gibbs 		{
6937ce72dbaSJustin T. Gibbs 			snprintf(errbuf, sizeof(errbuf),
694c5cb3888SJustin T. Gibbs 				 "Undefined symbol %s referenced",
695c5cb3888SJustin T. Gibbs 				 symbol->name);
6967ce72dbaSJustin T. Gibbs 			stop(errbuf, EX_DATAERR);
697c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
698c5cb3888SJustin T. Gibbs 			break;
699c5cb3888SJustin T. Gibbs 		}
700c5cb3888SJustin T. Gibbs 		}
701c5cb3888SJustin T. Gibbs 		SLIST_INIT(&$$.referenced_syms);
702c5cb3888SJustin T. Gibbs 		symlist_add(&$$.referenced_syms, symbol, SYMLIST_INSERT_HEAD);
703c5cb3888SJustin T. Gibbs 	}
704c5cb3888SJustin T. Gibbs ;
705c5cb3888SJustin T. Gibbs 
706c5cb3888SJustin T. Gibbs constant:
7073d46a688SJustin T. Gibbs 	T_CONST T_SYMBOL expression
708c5cb3888SJustin T. Gibbs 	{
709c5cb3888SJustin T. Gibbs 		if ($2->type != UNINITIALIZED) {
71037507c1bSJustin T. Gibbs 			stop("Re-definition of symbol as a constant",
711c5cb3888SJustin T. Gibbs 			     EX_DATAERR);
712c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
713c5cb3888SJustin T. Gibbs 		}
714c5cb3888SJustin T. Gibbs 		$2->type = CONST;
715c5cb3888SJustin T. Gibbs 		initialize_symbol($2);
7163d46a688SJustin T. Gibbs 		$2->info.cinfo->value = $3.value;
717c5cb3888SJustin T. Gibbs 	}
71837507c1bSJustin T. Gibbs |	T_CONST T_SYMBOL T_DOWNLOAD
71937507c1bSJustin T. Gibbs 	{
72037507c1bSJustin T. Gibbs 		if ($1) {
72137507c1bSJustin T. Gibbs 			stop("Invalid downloaded constant declaration",
72237507c1bSJustin T. Gibbs 			     EX_DATAERR);
72337507c1bSJustin T. Gibbs 			/* NOTREACHED */
72437507c1bSJustin T. Gibbs 		}
72537507c1bSJustin T. Gibbs 		if ($2->type != UNINITIALIZED) {
72637507c1bSJustin T. Gibbs 			stop("Re-definition of symbol as a downloaded constant",
72737507c1bSJustin T. Gibbs 			     EX_DATAERR);
72837507c1bSJustin T. Gibbs 			/* NOTREACHED */
72937507c1bSJustin T. Gibbs 		}
73037507c1bSJustin T. Gibbs 		$2->type = DOWNLOAD_CONST;
73137507c1bSJustin T. Gibbs 		initialize_symbol($2);
73237507c1bSJustin T. Gibbs 		$2->info.cinfo->value = download_constant_count++;
7337ce72dbaSJustin T. Gibbs 	}
7347ce72dbaSJustin T. Gibbs ;
7357ce72dbaSJustin T. Gibbs 
7367ce72dbaSJustin T. Gibbs macrodefn_prologue:
7377ce72dbaSJustin T. Gibbs 	T_DEFINE T_SYMBOL
7387ce72dbaSJustin T. Gibbs 	{
7397ce72dbaSJustin T. Gibbs 		if ($2->type != UNINITIALIZED) {
7407ce72dbaSJustin T. Gibbs 			stop("Re-definition of symbol as a macro",
7417ce72dbaSJustin T. Gibbs 			     EX_DATAERR);
7427ce72dbaSJustin T. Gibbs 			/* NOTREACHED */
7437ce72dbaSJustin T. Gibbs 		}
7447ce72dbaSJustin T. Gibbs 		cur_symbol = $2;
7457ce72dbaSJustin T. Gibbs 		cur_symbol->type = MACRO;
7467ce72dbaSJustin T. Gibbs 		initialize_symbol(cur_symbol);
7477ce72dbaSJustin T. Gibbs 	}
7487ce72dbaSJustin T. Gibbs ;
7497ce72dbaSJustin T. Gibbs 
7507ce72dbaSJustin T. Gibbs macrodefn:
7517ce72dbaSJustin T. Gibbs 	macrodefn_prologue T_MACROBODY
7527ce72dbaSJustin T. Gibbs 	{
7537ce72dbaSJustin T. Gibbs 		add_macro_body($2);
7547ce72dbaSJustin T. Gibbs 	}
7557ce72dbaSJustin T. Gibbs |	macrodefn_prologue '(' macro_arglist ')' T_MACROBODY
7567ce72dbaSJustin T. Gibbs 	{
7577ce72dbaSJustin T. Gibbs 		add_macro_body($5);
7587ce72dbaSJustin T. Gibbs 		cur_symbol->info.macroinfo->narg = $3;
7597ce72dbaSJustin T. Gibbs 	}
7607ce72dbaSJustin T. Gibbs ;
7617ce72dbaSJustin T. Gibbs 
7627ce72dbaSJustin T. Gibbs macro_arglist:
7637ce72dbaSJustin T. Gibbs 	{
7647ce72dbaSJustin T. Gibbs 		/* Macros can take no arguments */
7657ce72dbaSJustin T. Gibbs 		$$ = 0;
7667ce72dbaSJustin T. Gibbs 	}
7677ce72dbaSJustin T. Gibbs |	T_ARG
7687ce72dbaSJustin T. Gibbs 	{
7697ce72dbaSJustin T. Gibbs 		$$ = 1;
7707ce72dbaSJustin T. Gibbs 		add_macro_arg($1, 0);
7717ce72dbaSJustin T. Gibbs 	}
7727ce72dbaSJustin T. Gibbs |	macro_arglist ',' T_ARG
7737ce72dbaSJustin T. Gibbs 	{
7747ce72dbaSJustin T. Gibbs 		if ($1 == 0) {
7759b3d1b02SYaroslav Tykhiy 			stop("Comma without preceding argument in arg list",
7767ce72dbaSJustin T. Gibbs 			     EX_DATAERR);
7777ce72dbaSJustin T. Gibbs 			/* NOTREACHED */
7787ce72dbaSJustin T. Gibbs 		}
7797ce72dbaSJustin T. Gibbs 		$$ = $1 + 1;
7807ce72dbaSJustin T. Gibbs 		add_macro_arg($3, $1);
78137507c1bSJustin T. Gibbs 	}
78237507c1bSJustin T. Gibbs ;
78337507c1bSJustin T. Gibbs 
784c5cb3888SJustin T. Gibbs scratch_ram:
785c5cb3888SJustin T. Gibbs 	T_SRAM '{'
786c5cb3888SJustin T. Gibbs 		{
7877ce72dbaSJustin T. Gibbs 			snprintf(errbuf, sizeof(errbuf), "%s%d", SRAM_SYMNAME,
7887ce72dbaSJustin T. Gibbs 				 num_srams);
789c5cb3888SJustin T. Gibbs 			cur_symbol = symtable_get(SRAM_SYMNAME);
790c5cb3888SJustin T. Gibbs 			cur_symtype = SRAMLOC;
791c5cb3888SJustin T. Gibbs 			cur_symbol->type = SRAMLOC;
792c5cb3888SJustin T. Gibbs 			initialize_symbol(cur_symbol);
793c5cb3888SJustin T. Gibbs 		}
794c5cb3888SJustin T. Gibbs 		reg_address
795c5cb3888SJustin T. Gibbs 		{
796c5cb3888SJustin T. Gibbs 			sram_or_scb_offset = cur_symbol->info.rinfo->address;
797c5cb3888SJustin T. Gibbs 		}
7987ce72dbaSJustin T. Gibbs 		size
7997ce72dbaSJustin T. Gibbs 		{
8007ce72dbaSJustin T. Gibbs 			scb_or_sram_symbol = cur_symbol;
8017ce72dbaSJustin T. Gibbs 		}
8027ce72dbaSJustin T. Gibbs 		scb_or_sram_attributes
803c5cb3888SJustin T. Gibbs 	'}'
804c5cb3888SJustin T. Gibbs 		{
805c5cb3888SJustin T. Gibbs 			cur_symbol = NULL;
8067ce72dbaSJustin T. Gibbs 			scb_or_sram_symbol = NULL;
807c5cb3888SJustin T. Gibbs 		}
808c5cb3888SJustin T. Gibbs ;
809c5cb3888SJustin T. Gibbs 
810c5cb3888SJustin T. Gibbs scb:
811c5cb3888SJustin T. Gibbs 	T_SCB '{'
812c5cb3888SJustin T. Gibbs 		{
813c5cb3888SJustin T. Gibbs 			cur_symbol = symtable_get(SCB_SYMNAME);
814c5cb3888SJustin T. Gibbs 			cur_symtype = SCBLOC;
815c5cb3888SJustin T. Gibbs 			if (cur_symbol->type != UNINITIALIZED) {
816c5cb3888SJustin T. Gibbs 				stop("Only one SRAM definition allowed",
817c5cb3888SJustin T. Gibbs 				     EX_SOFTWARE);
818c5cb3888SJustin T. Gibbs 				/* NOTREACHED */
819c5cb3888SJustin T. Gibbs 			}
820c5cb3888SJustin T. Gibbs 			cur_symbol->type = SCBLOC;
821c5cb3888SJustin T. Gibbs 			initialize_symbol(cur_symbol);
82232da3127SJustin T. Gibbs 			/* 64 bytes of SCB space */
82332da3127SJustin T. Gibbs 			cur_symbol->info.rinfo->size = 64;
824c5cb3888SJustin T. Gibbs 		}
825c5cb3888SJustin T. Gibbs 		reg_address
826c5cb3888SJustin T. Gibbs 		{
827c5cb3888SJustin T. Gibbs 			sram_or_scb_offset = cur_symbol->info.rinfo->address;
828c5cb3888SJustin T. Gibbs 		}
8297ce72dbaSJustin T. Gibbs 		size
8307ce72dbaSJustin T. Gibbs 		{
8317ce72dbaSJustin T. Gibbs 			scb_or_sram_symbol = cur_symbol;
8327ce72dbaSJustin T. Gibbs 		}
8337ce72dbaSJustin T. Gibbs 		scb_or_sram_attributes
834c5cb3888SJustin T. Gibbs 	'}'
835c5cb3888SJustin T. Gibbs 		{
836c5cb3888SJustin T. Gibbs 			cur_symbol = NULL;
8377ce72dbaSJustin T. Gibbs 			scb_or_sram_symbol = NULL;
838c5cb3888SJustin T. Gibbs 		}
839c5cb3888SJustin T. Gibbs ;
840c5cb3888SJustin T. Gibbs 
8417ce72dbaSJustin T. Gibbs scb_or_sram_attributes:
8427ce72dbaSJustin T. Gibbs 	/* NULL definition is okay */
8437ce72dbaSJustin T. Gibbs |	modes
8447ce72dbaSJustin T. Gibbs |	scb_or_sram_reg_list
8457ce72dbaSJustin T. Gibbs |	modes scb_or_sram_reg_list
8467ce72dbaSJustin T. Gibbs ;
8477ce72dbaSJustin T. Gibbs 
848c5cb3888SJustin T. Gibbs scb_or_sram_reg_list:
849c5cb3888SJustin T. Gibbs 	reg_definition
850c5cb3888SJustin T. Gibbs |	scb_or_sram_reg_list reg_definition
851c5cb3888SJustin T. Gibbs ;
852c5cb3888SJustin T. Gibbs 
853c5cb3888SJustin T. Gibbs reg_symbol:
854c5cb3888SJustin T. Gibbs 	T_SYMBOL
855c5cb3888SJustin T. Gibbs 	{
856c5cb3888SJustin T. Gibbs 		process_register(&$1);
857c5cb3888SJustin T. Gibbs 		$$.symbol = $1;
858c5cb3888SJustin T. Gibbs 		$$.offset = 0;
859c5cb3888SJustin T. Gibbs 	}
860aa6dfd9dSJustin T. Gibbs |	T_SYMBOL '[' T_SYMBOL ']'
861aa6dfd9dSJustin T. Gibbs 	{
862aa6dfd9dSJustin T. Gibbs 		process_register(&$1);
863aa6dfd9dSJustin T. Gibbs 		if ($3->type != CONST) {
864aa6dfd9dSJustin T. Gibbs 			stop("register offset must be a constant", EX_DATAERR);
865aa6dfd9dSJustin T. Gibbs 			/* NOTREACHED */
866aa6dfd9dSJustin T. Gibbs 		}
867b18a2ef1SXin LI 		if (($3->info.cinfo->value + 1) > (unsigned)$1->info.rinfo->size) {
868aa6dfd9dSJustin T. Gibbs 			stop("Accessing offset beyond range of register",
869aa6dfd9dSJustin T. Gibbs 			     EX_DATAERR);
870aa6dfd9dSJustin T. Gibbs 			/* NOTREACHED */
871aa6dfd9dSJustin T. Gibbs 		}
872aa6dfd9dSJustin T. Gibbs 		$$.symbol = $1;
873aa6dfd9dSJustin T. Gibbs 		$$.offset = $3->info.cinfo->value;
874aa6dfd9dSJustin T. Gibbs 	}
875c5cb3888SJustin T. Gibbs |	T_SYMBOL '[' T_NUMBER ']'
876c5cb3888SJustin T. Gibbs 	{
877c5cb3888SJustin T. Gibbs 		process_register(&$1);
878b18a2ef1SXin LI 		if (($3 + 1) > (unsigned)$1->info.rinfo->size) {
879c5cb3888SJustin T. Gibbs 			stop("Accessing offset beyond range of register",
880c5cb3888SJustin T. Gibbs 			     EX_DATAERR);
881c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
882c5cb3888SJustin T. Gibbs 		}
883c5cb3888SJustin T. Gibbs 		$$.symbol = $1;
884c5cb3888SJustin T. Gibbs 		$$.offset = $3;
885c5cb3888SJustin T. Gibbs 	}
886c5cb3888SJustin T. Gibbs |	T_A
887c5cb3888SJustin T. Gibbs 	{
8887ce72dbaSJustin T. Gibbs 		if (accumulator.symbol == NULL) {
889c5cb3888SJustin T. Gibbs 			stop("No accumulator has been defined", EX_DATAERR);
890c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
891c5cb3888SJustin T. Gibbs 		}
8927ce72dbaSJustin T. Gibbs 		$$.symbol = accumulator.symbol;
893c5cb3888SJustin T. Gibbs 		$$.offset = 0;
894c5cb3888SJustin T. Gibbs 	}
895c5cb3888SJustin T. Gibbs ;
896c5cb3888SJustin T. Gibbs 
897c5cb3888SJustin T. Gibbs destination:
898c5cb3888SJustin T. Gibbs 	reg_symbol
899c5cb3888SJustin T. Gibbs 	{
900c5cb3888SJustin T. Gibbs 		test_writable_symbol($1.symbol);
901c5cb3888SJustin T. Gibbs 		$$ = $1;
902c5cb3888SJustin T. Gibbs 	}
903c5cb3888SJustin T. Gibbs ;
904c5cb3888SJustin T. Gibbs 
905c5cb3888SJustin T. Gibbs immediate:
906c5cb3888SJustin T. Gibbs 	expression
907c5cb3888SJustin T. Gibbs 	{ $$ = $1; }
908c5cb3888SJustin T. Gibbs ;
909c5cb3888SJustin T. Gibbs 
910c5cb3888SJustin T. Gibbs immediate_or_a:
911c5cb3888SJustin T. Gibbs 	expression
912c5cb3888SJustin T. Gibbs 	{
9137ce72dbaSJustin T. Gibbs 		if ($1.value == 0 && is_download_const(&$1) == 0) {
9147ce72dbaSJustin T. Gibbs 			snprintf(errbuf, sizeof(errbuf),
9157ce72dbaSJustin T. Gibbs 				 "\nExpression evaluates to 0 and thus "
9167ce72dbaSJustin T. Gibbs 				 "references the accumulator.\n "
9177ce72dbaSJustin T. Gibbs 				 "If this is the desired effect, use 'A' "
9187ce72dbaSJustin T. Gibbs 				 "instead.\n");
9197ce72dbaSJustin T. Gibbs 			stop(errbuf, EX_DATAERR);
9207ce72dbaSJustin T. Gibbs 		}
921c5cb3888SJustin T. Gibbs 		$$ = $1;
922c5cb3888SJustin T. Gibbs 	}
923c5cb3888SJustin T. Gibbs |	T_A
924c5cb3888SJustin T. Gibbs 	{
925c5cb3888SJustin T. Gibbs 		SLIST_INIT(&$$.referenced_syms);
9264ff10146SJustin T. Gibbs 		symlist_add(&$$.referenced_syms, accumulator.symbol,
9274ff10146SJustin T. Gibbs 			    SYMLIST_INSERT_HEAD);
928c5cb3888SJustin T. Gibbs 		$$.value = 0;
929c5cb3888SJustin T. Gibbs 	}
930c5cb3888SJustin T. Gibbs ;
931c5cb3888SJustin T. Gibbs 
932c5cb3888SJustin T. Gibbs source:
933c5cb3888SJustin T. Gibbs 	reg_symbol
934c5cb3888SJustin T. Gibbs 	{
935c5cb3888SJustin T. Gibbs 		test_readable_symbol($1.symbol);
936c5cb3888SJustin T. Gibbs 		$$ = $1;
937c5cb3888SJustin T. Gibbs 	}
938c5cb3888SJustin T. Gibbs ;
939c5cb3888SJustin T. Gibbs 
940c5cb3888SJustin T. Gibbs opt_source:
941c5cb3888SJustin T. Gibbs 	{
942c5cb3888SJustin T. Gibbs 		$$.symbol = NULL;
943c5cb3888SJustin T. Gibbs 		$$.offset = 0;
944c5cb3888SJustin T. Gibbs 	}
945c5cb3888SJustin T. Gibbs |	',' source
946c5cb3888SJustin T. Gibbs 	{ $$ = $2; }
947c5cb3888SJustin T. Gibbs ;
948c5cb3888SJustin T. Gibbs 
949c5cb3888SJustin T. Gibbs ret:
950c5cb3888SJustin T. Gibbs 	{ $$ = 0; }
951c5cb3888SJustin T. Gibbs |	T_RET
952c5cb3888SJustin T. Gibbs 	{ $$ = 1; }
953c5cb3888SJustin T. Gibbs ;
954c5cb3888SJustin T. Gibbs 
9557ce72dbaSJustin T. Gibbs set_src_mode:
9567ce72dbaSJustin T. Gibbs 	T_SET_SRC_MODE T_NUMBER ';'
9577ce72dbaSJustin T. Gibbs 	{
9587ce72dbaSJustin T. Gibbs 		src_mode = $2;
9597ce72dbaSJustin T. Gibbs 	}
9607ce72dbaSJustin T. Gibbs ;
9617ce72dbaSJustin T. Gibbs 
9627ce72dbaSJustin T. Gibbs set_dst_mode:
9637ce72dbaSJustin T. Gibbs 	T_SET_DST_MODE T_NUMBER ';'
9647ce72dbaSJustin T. Gibbs 	{
9657ce72dbaSJustin T. Gibbs 		dst_mode = $2;
9667ce72dbaSJustin T. Gibbs 	}
9677ce72dbaSJustin T. Gibbs ;
9687ce72dbaSJustin T. Gibbs 
969083d01f2SJustin T. Gibbs critical_section_start:
9707ce72dbaSJustin T. Gibbs 	T_BEGIN_CS ';'
971083d01f2SJustin T. Gibbs 	{
972083d01f2SJustin T. Gibbs 		critical_section_t *cs;
973083d01f2SJustin T. Gibbs 
974083d01f2SJustin T. Gibbs 		if (in_critical_section != FALSE) {
975083d01f2SJustin T. Gibbs 			stop("Critical Section within Critical Section",
976083d01f2SJustin T. Gibbs 			     EX_DATAERR);
977083d01f2SJustin T. Gibbs 			/* NOTREACHED */
978083d01f2SJustin T. Gibbs 		}
979083d01f2SJustin T. Gibbs 		cs = cs_alloc();
980083d01f2SJustin T. Gibbs 		cs->begin_addr = instruction_ptr;
981083d01f2SJustin T. Gibbs 		in_critical_section = TRUE;
982083d01f2SJustin T. Gibbs 	}
9833d46a688SJustin T. Gibbs ;
984083d01f2SJustin T. Gibbs 
985083d01f2SJustin T. Gibbs critical_section_end:
9867ce72dbaSJustin T. Gibbs 	T_END_CS ';'
987083d01f2SJustin T. Gibbs 	{
988083d01f2SJustin T. Gibbs 		critical_section_t *cs;
989083d01f2SJustin T. Gibbs 
990083d01f2SJustin T. Gibbs 		if (in_critical_section == FALSE) {
991083d01f2SJustin T. Gibbs 			stop("Unballanced 'end_cs'", EX_DATAERR);
992083d01f2SJustin T. Gibbs 			/* NOTREACHED */
993083d01f2SJustin T. Gibbs 		}
994083d01f2SJustin T. Gibbs 		cs = TAILQ_LAST(&cs_tailq, cs_tailq);
995083d01f2SJustin T. Gibbs 		cs->end_addr = instruction_ptr;
996083d01f2SJustin T. Gibbs 		in_critical_section = FALSE;
997083d01f2SJustin T. Gibbs 	}
9983d46a688SJustin T. Gibbs ;
999083d01f2SJustin T. Gibbs 
10007ce72dbaSJustin T. Gibbs export:
10017ce72dbaSJustin T. Gibbs 	{ $$ = 0; }
10027ce72dbaSJustin T. Gibbs |	T_EXPORT
10037ce72dbaSJustin T. Gibbs 	{ $$ = 1; }
10047ce72dbaSJustin T. Gibbs ;
10057ce72dbaSJustin T. Gibbs 
1006c5cb3888SJustin T. Gibbs label:
10077ce72dbaSJustin T. Gibbs 	export T_SYMBOL ':'
1008c5cb3888SJustin T. Gibbs 	{
10097ce72dbaSJustin T. Gibbs 		if ($2->type != UNINITIALIZED) {
1010c5cb3888SJustin T. Gibbs 			stop("Program label multiply defined", EX_DATAERR);
1011c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
1012c5cb3888SJustin T. Gibbs 		}
10137ce72dbaSJustin T. Gibbs 		$2->type = LABEL;
10147ce72dbaSJustin T. Gibbs 		initialize_symbol($2);
10157ce72dbaSJustin T. Gibbs 		$2->info.linfo->address = instruction_ptr;
10167ce72dbaSJustin T. Gibbs 		$2->info.linfo->exported = $1;
1017c5cb3888SJustin T. Gibbs 	}
1018c5cb3888SJustin T. Gibbs ;
1019c5cb3888SJustin T. Gibbs 
1020c5cb3888SJustin T. Gibbs address:
1021c5cb3888SJustin T. Gibbs 	T_SYMBOL
1022c5cb3888SJustin T. Gibbs 	{
1023c5cb3888SJustin T. Gibbs 		$$.symbol = $1;
1024c5cb3888SJustin T. Gibbs 		$$.offset = 0;
1025c5cb3888SJustin T. Gibbs 	}
1026c5cb3888SJustin T. Gibbs |	T_SYMBOL '+' T_NUMBER
1027c5cb3888SJustin T. Gibbs 	{
1028c5cb3888SJustin T. Gibbs 		$$.symbol = $1;
1029c5cb3888SJustin T. Gibbs 		$$.offset = $3;
1030c5cb3888SJustin T. Gibbs 	}
1031c5cb3888SJustin T. Gibbs |	T_SYMBOL '-' T_NUMBER
1032c5cb3888SJustin T. Gibbs 	{
1033c5cb3888SJustin T. Gibbs 		$$.symbol = $1;
1034c5cb3888SJustin T. Gibbs 		$$.offset = -$3;
1035c5cb3888SJustin T. Gibbs 	}
1036c5cb3888SJustin T. Gibbs |	'.'
1037c5cb3888SJustin T. Gibbs 	{
1038c5cb3888SJustin T. Gibbs 		$$.symbol = NULL;
1039c5cb3888SJustin T. Gibbs 		$$.offset = 0;
1040c5cb3888SJustin T. Gibbs 	}
1041c5cb3888SJustin T. Gibbs |	'.' '+' T_NUMBER
1042c5cb3888SJustin T. Gibbs 	{
1043c5cb3888SJustin T. Gibbs 		$$.symbol = NULL;
1044c5cb3888SJustin T. Gibbs 		$$.offset = $3;
1045c5cb3888SJustin T. Gibbs 	}
1046c5cb3888SJustin T. Gibbs |	'.' '-' T_NUMBER
1047c5cb3888SJustin T. Gibbs 	{
1048c5cb3888SJustin T. Gibbs 		$$.symbol = NULL;
1049c5cb3888SJustin T. Gibbs 		$$.offset = -$3;
1050c5cb3888SJustin T. Gibbs 	}
1051c5cb3888SJustin T. Gibbs ;
1052c5cb3888SJustin T. Gibbs 
1053c5cb3888SJustin T. Gibbs conditional:
10543bafc9d4SJustin T. Gibbs 	T_IF T_CEXPR '{'
1055c5cb3888SJustin T. Gibbs 	{
10563bafc9d4SJustin T. Gibbs 		scope_t *new_scope;
10573bafc9d4SJustin T. Gibbs 
10583bafc9d4SJustin T. Gibbs 		add_conditional($2);
10593bafc9d4SJustin T. Gibbs 		new_scope = scope_alloc();
10603bafc9d4SJustin T. Gibbs 		new_scope->type = SCOPE_IF;
10613bafc9d4SJustin T. Gibbs 		new_scope->begin_addr = instruction_ptr;
10623bafc9d4SJustin T. Gibbs 		new_scope->func_num = $2->info.condinfo->func_num;
10633bafc9d4SJustin T. Gibbs 	}
10643bafc9d4SJustin T. Gibbs |	T_ELSE T_IF T_CEXPR '{'
10653bafc9d4SJustin T. Gibbs 	{
10663bafc9d4SJustin T. Gibbs 		scope_t *new_scope;
10673bafc9d4SJustin T. Gibbs 		scope_t *scope_context;
10683bafc9d4SJustin T. Gibbs 		scope_t *last_scope;
10693bafc9d4SJustin T. Gibbs 
10703bafc9d4SJustin T. Gibbs 		/*
10713bafc9d4SJustin T. Gibbs 		 * Ensure that the previous scope is either an
10723bafc9d4SJustin T. Gibbs 		 * if or and else if.
10733bafc9d4SJustin T. Gibbs 		 */
10743bafc9d4SJustin T. Gibbs 		scope_context = SLIST_FIRST(&scope_stack);
10753bafc9d4SJustin T. Gibbs 		last_scope = TAILQ_LAST(&scope_context->inner_scope,
10763bafc9d4SJustin T. Gibbs 					scope_tailq);
10773bafc9d4SJustin T. Gibbs 		if (last_scope == NULL
1078cde1b992SDimitry Andric 		 || last_scope->type == SCOPE_ELSE) {
10793bafc9d4SJustin T. Gibbs 
10803bafc9d4SJustin T. Gibbs 			stop("'else if' without leading 'if'", EX_DATAERR);
1081c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
1082c5cb3888SJustin T. Gibbs 		}
1083c5cb3888SJustin T. Gibbs 		add_conditional($3);
10843bafc9d4SJustin T. Gibbs 		new_scope = scope_alloc();
10853bafc9d4SJustin T. Gibbs 		new_scope->type = SCOPE_ELSE_IF;
10863bafc9d4SJustin T. Gibbs 		new_scope->begin_addr = instruction_ptr;
10873bafc9d4SJustin T. Gibbs 		new_scope->func_num = $3->info.condinfo->func_num;
10883bafc9d4SJustin T. Gibbs 	}
10893bafc9d4SJustin T. Gibbs |	T_ELSE '{'
10903bafc9d4SJustin T. Gibbs 	{
10913bafc9d4SJustin T. Gibbs 		scope_t *new_scope;
10923bafc9d4SJustin T. Gibbs 		scope_t *scope_context;
10933bafc9d4SJustin T. Gibbs 		scope_t *last_scope;
10943bafc9d4SJustin T. Gibbs 
10953bafc9d4SJustin T. Gibbs 		/*
10963bafc9d4SJustin T. Gibbs 		 * Ensure that the previous scope is either an
10973bafc9d4SJustin T. Gibbs 		 * if or and else if.
10983bafc9d4SJustin T. Gibbs 		 */
10993bafc9d4SJustin T. Gibbs 		scope_context = SLIST_FIRST(&scope_stack);
11003bafc9d4SJustin T. Gibbs 		last_scope = TAILQ_LAST(&scope_context->inner_scope,
11013bafc9d4SJustin T. Gibbs 					scope_tailq);
11023bafc9d4SJustin T. Gibbs 		if (last_scope == NULL
11033bafc9d4SJustin T. Gibbs 		 || last_scope->type == SCOPE_ELSE) {
11043bafc9d4SJustin T. Gibbs 
11053bafc9d4SJustin T. Gibbs 			stop("'else' without leading 'if'", EX_DATAERR);
11063bafc9d4SJustin T. Gibbs 			/* NOTREACHED */
11073bafc9d4SJustin T. Gibbs 		}
11083bafc9d4SJustin T. Gibbs 		new_scope = scope_alloc();
11093bafc9d4SJustin T. Gibbs 		new_scope->type = SCOPE_ELSE;
11103bafc9d4SJustin T. Gibbs 		new_scope->begin_addr = instruction_ptr;
11113bafc9d4SJustin T. Gibbs 	}
11123bafc9d4SJustin T. Gibbs ;
11133bafc9d4SJustin T. Gibbs 
11143bafc9d4SJustin T. Gibbs conditional:
11153bafc9d4SJustin T. Gibbs 	'}'
11163bafc9d4SJustin T. Gibbs 	{
11173bafc9d4SJustin T. Gibbs 		scope_t *scope_context;
11183bafc9d4SJustin T. Gibbs 
11193bafc9d4SJustin T. Gibbs 		scope_context = SLIST_FIRST(&scope_stack);
11203bafc9d4SJustin T. Gibbs 		if (scope_context->type == SCOPE_ROOT) {
11213bafc9d4SJustin T. Gibbs 			stop("Unexpected '}' encountered", EX_DATAERR);
11223bafc9d4SJustin T. Gibbs 			/* NOTREACHED */
11233bafc9d4SJustin T. Gibbs 		}
11243bafc9d4SJustin T. Gibbs 
11253bafc9d4SJustin T. Gibbs 		scope_context->end_addr = instruction_ptr;
11263bafc9d4SJustin T. Gibbs 
11273bafc9d4SJustin T. Gibbs 		/* Pop the scope */
11283bafc9d4SJustin T. Gibbs 		SLIST_REMOVE_HEAD(&scope_stack, scope_stack_links);
11293bafc9d4SJustin T. Gibbs 
11303bafc9d4SJustin T. Gibbs 		process_scope(scope_context);
11313bafc9d4SJustin T. Gibbs 
11323bafc9d4SJustin T. Gibbs 		if (SLIST_FIRST(&scope_stack) == NULL) {
11333bafc9d4SJustin T. Gibbs 			stop("Unexpected '}' encountered", EX_DATAERR);
11343bafc9d4SJustin T. Gibbs 			/* NOTREACHED */
11353bafc9d4SJustin T. Gibbs 		}
1136c5cb3888SJustin T. Gibbs 	}
1137c5cb3888SJustin T. Gibbs ;
1138c5cb3888SJustin T. Gibbs 
1139c5cb3888SJustin T. Gibbs f1_opcode:
1140c5cb3888SJustin T. Gibbs 	T_AND { $$ = AIC_OP_AND; }
1141c5cb3888SJustin T. Gibbs |	T_XOR { $$ = AIC_OP_XOR; }
1142c5cb3888SJustin T. Gibbs |	T_ADD { $$ = AIC_OP_ADD; }
1143c5cb3888SJustin T. Gibbs |	T_ADC { $$ = AIC_OP_ADC; }
1144c5cb3888SJustin T. Gibbs ;
1145c5cb3888SJustin T. Gibbs 
1146c5cb3888SJustin T. Gibbs code:
1147c5cb3888SJustin T. Gibbs 	f1_opcode destination ',' immediate_or_a opt_source ret ';'
1148c5cb3888SJustin T. Gibbs 	{
1149c5cb3888SJustin T. Gibbs 		format_1_instr($1, &$2, &$4, &$5, $6);
1150c5cb3888SJustin T. Gibbs 	}
1151c5cb3888SJustin T. Gibbs ;
1152c5cb3888SJustin T. Gibbs 
1153c5cb3888SJustin T. Gibbs code:
1154c5cb3888SJustin T. Gibbs 	T_OR reg_symbol ',' immediate_or_a opt_source ret ';'
1155c5cb3888SJustin T. Gibbs 	{
1156c5cb3888SJustin T. Gibbs 		format_1_instr(AIC_OP_OR, &$2, &$4, &$5, $6);
1157c5cb3888SJustin T. Gibbs 	}
1158c5cb3888SJustin T. Gibbs ;
1159c5cb3888SJustin T. Gibbs 
1160c5cb3888SJustin T. Gibbs code:
1161c5cb3888SJustin T. Gibbs 	T_INC destination opt_source ret ';'
1162c5cb3888SJustin T. Gibbs 	{
1163c5cb3888SJustin T. Gibbs 		expression_t immed;
1164c5cb3888SJustin T. Gibbs 
1165c5cb3888SJustin T. Gibbs 		make_expression(&immed, 1);
1166c5cb3888SJustin T. Gibbs 		format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4);
1167c5cb3888SJustin T. Gibbs 	}
1168c5cb3888SJustin T. Gibbs ;
1169c5cb3888SJustin T. Gibbs 
1170c5cb3888SJustin T. Gibbs code:
1171c5cb3888SJustin T. Gibbs 	T_DEC destination opt_source ret ';'
1172c5cb3888SJustin T. Gibbs 	{
1173c5cb3888SJustin T. Gibbs 		expression_t immed;
1174c5cb3888SJustin T. Gibbs 
1175c5cb3888SJustin T. Gibbs 		make_expression(&immed, -1);
1176c5cb3888SJustin T. Gibbs 		format_1_instr(AIC_OP_ADD, &$2, &immed, &$3, $4);
1177c5cb3888SJustin T. Gibbs 	}
1178c5cb3888SJustin T. Gibbs ;
1179c5cb3888SJustin T. Gibbs 
1180c5cb3888SJustin T. Gibbs code:
1181c5cb3888SJustin T. Gibbs 	T_CLC ret ';'
1182c5cb3888SJustin T. Gibbs 	{
1183c5cb3888SJustin T. Gibbs 		expression_t immed;
1184c5cb3888SJustin T. Gibbs 
1185c5cb3888SJustin T. Gibbs 		make_expression(&immed, -1);
1186c5cb3888SJustin T. Gibbs 		format_1_instr(AIC_OP_ADD, &none, &immed, &allzeros, $2);
1187c5cb3888SJustin T. Gibbs 	}
1188c5cb3888SJustin T. Gibbs |	T_CLC T_MVI destination ',' immediate_or_a ret ';'
1189c5cb3888SJustin T. Gibbs 	{
1190c5cb3888SJustin T. Gibbs 		format_1_instr(AIC_OP_ADD, &$3, &$5, &allzeros, $6);
1191c5cb3888SJustin T. Gibbs 	}
1192c5cb3888SJustin T. Gibbs ;
1193c5cb3888SJustin T. Gibbs 
1194c5cb3888SJustin T. Gibbs code:
1195c5cb3888SJustin T. Gibbs 	T_STC ret ';'
1196c5cb3888SJustin T. Gibbs 	{
1197c5cb3888SJustin T. Gibbs 		expression_t immed;
1198c5cb3888SJustin T. Gibbs 
1199c5cb3888SJustin T. Gibbs 		make_expression(&immed, 1);
1200c5cb3888SJustin T. Gibbs 		format_1_instr(AIC_OP_ADD, &none, &immed, &allones, $2);
1201c5cb3888SJustin T. Gibbs 	}
1202c5cb3888SJustin T. Gibbs |	T_STC destination ret ';'
1203c5cb3888SJustin T. Gibbs 	{
1204c5cb3888SJustin T. Gibbs 		expression_t immed;
1205c5cb3888SJustin T. Gibbs 
1206c5cb3888SJustin T. Gibbs 		make_expression(&immed, 1);
1207c5cb3888SJustin T. Gibbs 		format_1_instr(AIC_OP_ADD, &$2, &immed, &allones, $3);
1208c5cb3888SJustin T. Gibbs 	}
1209c5cb3888SJustin T. Gibbs ;
1210c5cb3888SJustin T. Gibbs 
1211c5cb3888SJustin T. Gibbs code:
121283b9eb54SJustin T. Gibbs 	T_BMOV destination ',' source ',' immediate ret ';'
12133bafc9d4SJustin T. Gibbs 	{
12143bafc9d4SJustin T. Gibbs 		format_1_instr(AIC_OP_BMOV, &$2, &$6, &$4, $7);
12153bafc9d4SJustin T. Gibbs 	}
12163bafc9d4SJustin T. Gibbs ;
12173bafc9d4SJustin T. Gibbs 
12183bafc9d4SJustin T. Gibbs code:
1219c5cb3888SJustin T. Gibbs 	T_MOV destination ',' source ret ';'
1220c5cb3888SJustin T. Gibbs 	{
1221c5cb3888SJustin T. Gibbs 		expression_t immed;
1222c5cb3888SJustin T. Gibbs 
122383b9eb54SJustin T. Gibbs 		make_expression(&immed, 1);
122483b9eb54SJustin T. Gibbs 		format_1_instr(AIC_OP_BMOV, &$2, &immed, &$4, $5);
1225c5cb3888SJustin T. Gibbs 	}
1226c5cb3888SJustin T. Gibbs ;
1227c5cb3888SJustin T. Gibbs 
1228c5cb3888SJustin T. Gibbs code:
12294ff10146SJustin T. Gibbs 	T_MVI destination ',' immediate ret ';'
1230c5cb3888SJustin T. Gibbs 	{
12314ff10146SJustin T. Gibbs 		if ($4.value == 0
12324ff10146SJustin T. Gibbs 		 && is_download_const(&$4) == 0) {
12334ff10146SJustin T. Gibbs 			expression_t immed;
12344ff10146SJustin T. Gibbs 
12354ff10146SJustin T. Gibbs 			/*
12364ff10146SJustin T. Gibbs 			 * Allow move immediates of 0 so that macros,
12374ff10146SJustin T. Gibbs 			 * that can't know the immediate's value and
12384ff10146SJustin T. Gibbs 			 * otherwise compensate, still work.
12394ff10146SJustin T. Gibbs 			 */
12407fc23fe6SScott Long 			make_expression(&immed, 1);
12417fc23fe6SScott Long 			format_1_instr(AIC_OP_BMOV, &$2, &immed, &allzeros, $5);
12424ff10146SJustin T. Gibbs 		} else {
1243c5cb3888SJustin T. Gibbs 			format_1_instr(AIC_OP_OR, &$2, &$4, &allzeros, $5);
1244c5cb3888SJustin T. Gibbs 		}
12454ff10146SJustin T. Gibbs 	}
1246c5cb3888SJustin T. Gibbs ;
1247c5cb3888SJustin T. Gibbs 
1248c5cb3888SJustin T. Gibbs code:
1249aa6dfd9dSJustin T. Gibbs 	T_NOT destination opt_source ret ';'
1250aa6dfd9dSJustin T. Gibbs 	{
1251aa6dfd9dSJustin T. Gibbs 		expression_t immed;
1252aa6dfd9dSJustin T. Gibbs 
1253aa6dfd9dSJustin T. Gibbs 		make_expression(&immed, 0xff);
1254aa6dfd9dSJustin T. Gibbs 		format_1_instr(AIC_OP_XOR, &$2, &immed, &$3, $4);
1255aa6dfd9dSJustin T. Gibbs 	}
1256aa6dfd9dSJustin T. Gibbs ;
1257aa6dfd9dSJustin T. Gibbs 
1258aa6dfd9dSJustin T. Gibbs code:
1259c5cb3888SJustin T. Gibbs 	T_CLR destination ret ';'
1260c5cb3888SJustin T. Gibbs 	{
1261c5cb3888SJustin T. Gibbs 		expression_t immed;
1262c5cb3888SJustin T. Gibbs 
1263c5cb3888SJustin T. Gibbs 		make_expression(&immed, 0xff);
1264c5cb3888SJustin T. Gibbs 		format_1_instr(AIC_OP_AND, &$2, &immed, &allzeros, $3);
1265c5cb3888SJustin T. Gibbs 	}
1266c5cb3888SJustin T. Gibbs ;
1267c5cb3888SJustin T. Gibbs 
1268c5cb3888SJustin T. Gibbs code:
12694dd5dcaeSJustin T. Gibbs 	T_NOP ret ';'
1270c5cb3888SJustin T. Gibbs 	{
1271c5cb3888SJustin T. Gibbs 		expression_t immed;
1272c5cb3888SJustin T. Gibbs 
1273c5cb3888SJustin T. Gibbs 		make_expression(&immed, 0xff);
12744dd5dcaeSJustin T. Gibbs 		format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, $2);
1275c5cb3888SJustin T. Gibbs 	}
1276c5cb3888SJustin T. Gibbs ;
1277c5cb3888SJustin T. Gibbs 
1278c5cb3888SJustin T. Gibbs code:
1279c5cb3888SJustin T. Gibbs 	T_RET ';'
1280c5cb3888SJustin T. Gibbs 	{
1281c5cb3888SJustin T. Gibbs 		expression_t immed;
1282c5cb3888SJustin T. Gibbs 
1283c5cb3888SJustin T. Gibbs 		make_expression(&immed, 0xff);
1284c5cb3888SJustin T. Gibbs 		format_1_instr(AIC_OP_AND, &none, &immed, &allzeros, TRUE);
1285c5cb3888SJustin T. Gibbs 	}
1286c5cb3888SJustin T. Gibbs ;
1287c5cb3888SJustin T. Gibbs 
1288c5cb3888SJustin T. Gibbs 	/*
1289594c945aSPedro F. Giffuni 	 * This grammar differs from the one in the aic7xxx
1290594c945aSPedro F. Giffuni 	 * reference manual since the grammar listed there is
1291c5cb3888SJustin T. Gibbs 	 * ambiguous and causes a shift/reduce conflict.
1292c5cb3888SJustin T. Gibbs 	 * It also seems more logical as the "immediate"
1293c5cb3888SJustin T. Gibbs 	 * argument is listed as the second arg like the
1294c5cb3888SJustin T. Gibbs 	 * other formats.
1295c5cb3888SJustin T. Gibbs 	 */
1296c5cb3888SJustin T. Gibbs 
1297c5cb3888SJustin T. Gibbs f2_opcode:
1298c5cb3888SJustin T. Gibbs 	T_SHL { $$ = AIC_OP_SHL; }
1299c5cb3888SJustin T. Gibbs |	T_SHR { $$ = AIC_OP_SHR; }
1300c5cb3888SJustin T. Gibbs |	T_ROL { $$ = AIC_OP_ROL; }
1301c5cb3888SJustin T. Gibbs |	T_ROR { $$ = AIC_OP_ROR; }
1302c5cb3888SJustin T. Gibbs ;
1303c5cb3888SJustin T. Gibbs 
1304c5cb3888SJustin T. Gibbs code:
1305c5cb3888SJustin T. Gibbs 	f2_opcode destination ',' expression opt_source ret ';'
1306c5cb3888SJustin T. Gibbs 	{
1307c5cb3888SJustin T. Gibbs 		format_2_instr($1, &$2, &$4, &$5, $6);
1308c5cb3888SJustin T. Gibbs 	}
1309c5cb3888SJustin T. Gibbs ;
1310c5cb3888SJustin T. Gibbs 
1311c5cb3888SJustin T. Gibbs jmp_jc_jnc_call:
1312c5cb3888SJustin T. Gibbs 	T_JMP	{ $$ = AIC_OP_JMP; }
1313c5cb3888SJustin T. Gibbs |	T_JC	{ $$ = AIC_OP_JC; }
1314c5cb3888SJustin T. Gibbs |	T_JNC	{ $$ = AIC_OP_JNC; }
1315c5cb3888SJustin T. Gibbs |	T_CALL	{ $$ = AIC_OP_CALL; }
1316c5cb3888SJustin T. Gibbs ;
1317c5cb3888SJustin T. Gibbs 
1318c5cb3888SJustin T. Gibbs jz_jnz:
1319c5cb3888SJustin T. Gibbs 	T_JZ	{ $$ = AIC_OP_JZ; }
1320c5cb3888SJustin T. Gibbs |	T_JNZ	{ $$ = AIC_OP_JNZ; }
1321c5cb3888SJustin T. Gibbs ;
1322c5cb3888SJustin T. Gibbs 
1323c5cb3888SJustin T. Gibbs je_jne:
1324c5cb3888SJustin T. Gibbs 	T_JE	{ $$ = AIC_OP_JE; }
1325c5cb3888SJustin T. Gibbs |	T_JNE	{ $$ = AIC_OP_JNE; }
1326c5cb3888SJustin T. Gibbs ;
1327c5cb3888SJustin T. Gibbs 
1328c5cb3888SJustin T. Gibbs code:
1329c5cb3888SJustin T. Gibbs 	jmp_jc_jnc_call address ';'
1330c5cb3888SJustin T. Gibbs 	{
1331c5cb3888SJustin T. Gibbs 		expression_t immed;
1332c5cb3888SJustin T. Gibbs 
1333c5cb3888SJustin T. Gibbs 		make_expression(&immed, 0);
1334c5cb3888SJustin T. Gibbs 		format_3_instr($1, &sindex, &immed, &$2);
1335c5cb3888SJustin T. Gibbs 	}
1336c5cb3888SJustin T. Gibbs ;
1337c5cb3888SJustin T. Gibbs 
1338c5cb3888SJustin T. Gibbs code:
1339c5cb3888SJustin T. Gibbs 	T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';'
1340c5cb3888SJustin T. Gibbs 	{
1341c5cb3888SJustin T. Gibbs 		format_3_instr($5, &$2, &$4, &$6);
1342c5cb3888SJustin T. Gibbs 	}
1343c5cb3888SJustin T. Gibbs ;
1344c5cb3888SJustin T. Gibbs 
1345c5cb3888SJustin T. Gibbs code:
1346c5cb3888SJustin T. Gibbs 	T_TEST source ',' immediate_or_a jz_jnz address ';'
1347c5cb3888SJustin T. Gibbs 	{
1348c5cb3888SJustin T. Gibbs 		format_3_instr($5, &$2, &$4, &$6);
1349c5cb3888SJustin T. Gibbs 	}
1350c5cb3888SJustin T. Gibbs ;
1351c5cb3888SJustin T. Gibbs 
1352c5cb3888SJustin T. Gibbs code:
1353c5cb3888SJustin T. Gibbs 	T_CMP source ',' immediate_or_a je_jne address ';'
1354c5cb3888SJustin T. Gibbs 	{
1355c5cb3888SJustin T. Gibbs 		format_3_instr($5, &$2, &$4, &$6);
1356c5cb3888SJustin T. Gibbs 	}
1357c5cb3888SJustin T. Gibbs ;
1358c5cb3888SJustin T. Gibbs 
1359c5cb3888SJustin T. Gibbs code:
1360c5cb3888SJustin T. Gibbs 	T_MOV source jmp_jc_jnc_call address ';'
1361c5cb3888SJustin T. Gibbs 	{
1362c5cb3888SJustin T. Gibbs 		expression_t immed;
1363c5cb3888SJustin T. Gibbs 
1364c5cb3888SJustin T. Gibbs 		make_expression(&immed, 0);
1365c5cb3888SJustin T. Gibbs 		format_3_instr($3, &$2, &immed, &$4);
1366c5cb3888SJustin T. Gibbs 	}
1367c5cb3888SJustin T. Gibbs ;
1368c5cb3888SJustin T. Gibbs 
1369c5cb3888SJustin T. Gibbs code:
1370c5cb3888SJustin T. Gibbs 	T_MVI immediate jmp_jc_jnc_call address ';'
1371c5cb3888SJustin T. Gibbs 	{
1372c5cb3888SJustin T. Gibbs 		format_3_instr($3, &allzeros, &$2, &$4);
1373c5cb3888SJustin T. Gibbs 	}
1374c5cb3888SJustin T. Gibbs ;
1375c5cb3888SJustin T. Gibbs 
1376c5cb3888SJustin T. Gibbs %%
1377c5cb3888SJustin T. Gibbs 
1378c5cb3888SJustin T. Gibbs static void
1379b18a2ef1SXin LI process_field(unsigned int field_type, symbol_t *sym, int value)
1380c5cb3888SJustin T. Gibbs {
1381c5cb3888SJustin T. Gibbs 	/*
1382c5cb3888SJustin T. Gibbs 	 * Add the current register to its
1383c5cb3888SJustin T. Gibbs 	 * symbol list, if it already exists,
1384c5cb3888SJustin T. Gibbs 	 * warn if we are setting it to a
1385c5cb3888SJustin T. Gibbs 	 * different value, or in the bit to
1386c5cb3888SJustin T. Gibbs 	 * the "allowed bits" of this register.
1387c5cb3888SJustin T. Gibbs 	 */
1388c5cb3888SJustin T. Gibbs 	if (sym->type == UNINITIALIZED) {
138963183d8cSJustin T. Gibbs 		sym->type = field_type;
1390c5cb3888SJustin T. Gibbs 		initialize_symbol(sym);
139163183d8cSJustin T. Gibbs 		sym->info.finfo->value = value;
139263183d8cSJustin T. Gibbs 		if (field_type != ENUM_ENTRY) {
139363183d8cSJustin T. Gibbs 			if (field_type != MASK && value == 0) {
139463183d8cSJustin T. Gibbs 				stop("Empty Field, or Enum", EX_DATAERR);
1395c5cb3888SJustin T. Gibbs 				/* NOTREACHED */
1396c5cb3888SJustin T. Gibbs 			}
139763183d8cSJustin T. Gibbs 			sym->info.finfo->value = value;
139863183d8cSJustin T. Gibbs 			sym->info.finfo->mask = value;
139963183d8cSJustin T. Gibbs 		} else if (field_symbol != NULL) {
140063183d8cSJustin T. Gibbs 			sym->info.finfo->mask = field_symbol->info.finfo->value;
140163183d8cSJustin T. Gibbs 		} else {
140263183d8cSJustin T. Gibbs 			sym->info.finfo->mask = 0xFF;
1403c5cb3888SJustin T. Gibbs 		}
140463183d8cSJustin T. Gibbs 	} else if (sym->type != field_type) {
140563183d8cSJustin T. Gibbs 		stop("Field definition mirrors a definition of the same "
1406c5cb3888SJustin T. Gibbs 		     " name, but a different type", EX_DATAERR);
1407c5cb3888SJustin T. Gibbs 		/* NOTREACHED */
140863183d8cSJustin T. Gibbs 	} else if (value != sym->info.finfo->value) {
140963183d8cSJustin T. Gibbs 		stop("Field redefined with a conflicting value", EX_DATAERR);
1410c5cb3888SJustin T. Gibbs 		/* NOTREACHED */
1411c5cb3888SJustin T. Gibbs 	}
1412c5cb3888SJustin T. Gibbs 	/* Fail if this symbol is already listed */
141363183d8cSJustin T. Gibbs 	if (symlist_search(&(sym->info.finfo->symrefs),
1414c5cb3888SJustin T. Gibbs 			   cur_symbol->name) != NULL) {
141563183d8cSJustin T. Gibbs 		stop("Field defined multiple times for register", EX_DATAERR);
1416c5cb3888SJustin T. Gibbs 		/* NOTREACHED */
1417c5cb3888SJustin T. Gibbs 	}
141863183d8cSJustin T. Gibbs 	symlist_add(&(sym->info.finfo->symrefs), cur_symbol,
1419c5cb3888SJustin T. Gibbs 		    SYMLIST_INSERT_HEAD);
142063183d8cSJustin T. Gibbs 	cur_symbol->info.rinfo->valid_bitmask |= sym->info.finfo->mask;
1421c5cb3888SJustin T. Gibbs 	cur_symbol->info.rinfo->typecheck_masks = TRUE;
142263183d8cSJustin T. Gibbs 	symlist_add(&(cur_symbol->info.rinfo->fields), sym, SYMLIST_SORT);
1423c5cb3888SJustin T. Gibbs }
1424c5cb3888SJustin T. Gibbs 
1425c5cb3888SJustin T. Gibbs static void
initialize_symbol(symbol_t * symbol)142632da3127SJustin T. Gibbs initialize_symbol(symbol_t *symbol)
1427c5cb3888SJustin T. Gibbs {
1428c5cb3888SJustin T. Gibbs 	switch (symbol->type) {
1429c5cb3888SJustin T. Gibbs 	case UNINITIALIZED:
1430c5cb3888SJustin T. Gibbs 		stop("Call to initialize_symbol with type field unset",
1431c5cb3888SJustin T. Gibbs 		     EX_SOFTWARE);
1432c5cb3888SJustin T. Gibbs 		/* NOTREACHED */
1433c5cb3888SJustin T. Gibbs 		break;
1434c5cb3888SJustin T. Gibbs 	case REGISTER:
1435c5cb3888SJustin T. Gibbs 	case SRAMLOC:
1436c5cb3888SJustin T. Gibbs 	case SCBLOC:
1437c5cb3888SJustin T. Gibbs 		symbol->info.rinfo =
1438c5cb3888SJustin T. Gibbs 		    (struct reg_info *)malloc(sizeof(struct reg_info));
1439c5cb3888SJustin T. Gibbs 		if (symbol->info.rinfo == NULL) {
1440c5cb3888SJustin T. Gibbs 			stop("Can't create register info", EX_SOFTWARE);
1441c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
1442c5cb3888SJustin T. Gibbs 		}
1443c5cb3888SJustin T. Gibbs 		memset(symbol->info.rinfo, 0,
1444c5cb3888SJustin T. Gibbs 		       sizeof(struct reg_info));
144563183d8cSJustin T. Gibbs 		SLIST_INIT(&(symbol->info.rinfo->fields));
14467ce72dbaSJustin T. Gibbs 		/*
14477ce72dbaSJustin T. Gibbs 		 * Default to allowing access in all register modes
14487ce72dbaSJustin T. Gibbs 		 * or to the mode specified by the SCB or SRAM space
14497ce72dbaSJustin T. Gibbs 		 * we are in.
14507ce72dbaSJustin T. Gibbs 		 */
14517ce72dbaSJustin T. Gibbs 		if (scb_or_sram_symbol != NULL)
14527ce72dbaSJustin T. Gibbs 			symbol->info.rinfo->modes =
14537ce72dbaSJustin T. Gibbs 			    scb_or_sram_symbol->info.rinfo->modes;
14547ce72dbaSJustin T. Gibbs 		else
14557ce72dbaSJustin T. Gibbs 			symbol->info.rinfo->modes = ~0;
1456c5cb3888SJustin T. Gibbs 		break;
1457c5cb3888SJustin T. Gibbs 	case ALIAS:
1458c5cb3888SJustin T. Gibbs 		symbol->info.ainfo =
1459c5cb3888SJustin T. Gibbs 		    (struct alias_info *)malloc(sizeof(struct alias_info));
1460c5cb3888SJustin T. Gibbs 		if (symbol->info.ainfo == NULL) {
1461c5cb3888SJustin T. Gibbs 			stop("Can't create alias info", EX_SOFTWARE);
1462c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
1463c5cb3888SJustin T. Gibbs 		}
1464c5cb3888SJustin T. Gibbs 		memset(symbol->info.ainfo, 0,
1465c5cb3888SJustin T. Gibbs 		       sizeof(struct alias_info));
1466c5cb3888SJustin T. Gibbs 		break;
1467c5cb3888SJustin T. Gibbs 	case MASK:
146863183d8cSJustin T. Gibbs 	case FIELD:
146963183d8cSJustin T. Gibbs 	case ENUM:
147063183d8cSJustin T. Gibbs 	case ENUM_ENTRY:
147163183d8cSJustin T. Gibbs 		symbol->info.finfo =
147263183d8cSJustin T. Gibbs 		    (struct field_info *)malloc(sizeof(struct field_info));
147363183d8cSJustin T. Gibbs 		if (symbol->info.finfo == NULL) {
147463183d8cSJustin T. Gibbs 			stop("Can't create field info", EX_SOFTWARE);
1475c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
1476c5cb3888SJustin T. Gibbs 		}
147763183d8cSJustin T. Gibbs 		memset(symbol->info.finfo, 0, sizeof(struct field_info));
147863183d8cSJustin T. Gibbs 		SLIST_INIT(&(symbol->info.finfo->symrefs));
1479c5cb3888SJustin T. Gibbs 		break;
1480c5cb3888SJustin T. Gibbs 	case CONST:
148137507c1bSJustin T. Gibbs 	case DOWNLOAD_CONST:
1482c5cb3888SJustin T. Gibbs 		symbol->info.cinfo =
1483c5cb3888SJustin T. Gibbs 		    (struct const_info *)malloc(sizeof(struct const_info));
1484c5cb3888SJustin T. Gibbs 		if (symbol->info.cinfo == NULL) {
1485c5cb3888SJustin T. Gibbs 			stop("Can't create alias info", EX_SOFTWARE);
1486c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
1487c5cb3888SJustin T. Gibbs 		}
1488c5cb3888SJustin T. Gibbs 		memset(symbol->info.cinfo, 0,
1489c5cb3888SJustin T. Gibbs 		       sizeof(struct const_info));
1490c5cb3888SJustin T. Gibbs 		break;
1491c5cb3888SJustin T. Gibbs 	case LABEL:
1492c5cb3888SJustin T. Gibbs 		symbol->info.linfo =
1493c5cb3888SJustin T. Gibbs 		    (struct label_info *)malloc(sizeof(struct label_info));
1494c5cb3888SJustin T. Gibbs 		if (symbol->info.linfo == NULL) {
1495c5cb3888SJustin T. Gibbs 			stop("Can't create label info", EX_SOFTWARE);
1496c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
1497c5cb3888SJustin T. Gibbs 		}
1498c5cb3888SJustin T. Gibbs 		memset(symbol->info.linfo, 0,
1499c5cb3888SJustin T. Gibbs 		       sizeof(struct label_info));
1500c5cb3888SJustin T. Gibbs 		break;
1501c5cb3888SJustin T. Gibbs 	case CONDITIONAL:
1502c5cb3888SJustin T. Gibbs 		symbol->info.condinfo =
1503c5cb3888SJustin T. Gibbs 		    (struct cond_info *)malloc(sizeof(struct cond_info));
1504c5cb3888SJustin T. Gibbs 		if (symbol->info.condinfo == NULL) {
1505c5cb3888SJustin T. Gibbs 			stop("Can't create conditional info", EX_SOFTWARE);
1506c5cb3888SJustin T. Gibbs 			/* NOTREACHED */
1507c5cb3888SJustin T. Gibbs 		}
1508c5cb3888SJustin T. Gibbs 		memset(symbol->info.condinfo, 0,
1509c5cb3888SJustin T. Gibbs 		       sizeof(struct cond_info));
1510c5cb3888SJustin T. Gibbs 		break;
15117ce72dbaSJustin T. Gibbs 	case MACRO:
15127ce72dbaSJustin T. Gibbs 		symbol->info.macroinfo =
15137ce72dbaSJustin T. Gibbs 		    (struct macro_info *)malloc(sizeof(struct macro_info));
15147ce72dbaSJustin T. Gibbs 		if (symbol->info.macroinfo == NULL) {
15157ce72dbaSJustin T. Gibbs 			stop("Can't create macro info", EX_SOFTWARE);
15167ce72dbaSJustin T. Gibbs 			/* NOTREACHED */
15177ce72dbaSJustin T. Gibbs 		}
15187ce72dbaSJustin T. Gibbs 		memset(symbol->info.macroinfo, 0,
15197ce72dbaSJustin T. Gibbs 		       sizeof(struct macro_info));
15207ce72dbaSJustin T. Gibbs 		STAILQ_INIT(&symbol->info.macroinfo->args);
15217ce72dbaSJustin T. Gibbs 		break;
1522c5cb3888SJustin T. Gibbs 	default:
1523c5cb3888SJustin T. Gibbs 		stop("Call to initialize_symbol with invalid symbol type",
1524c5cb3888SJustin T. Gibbs 		     EX_SOFTWARE);
1525c5cb3888SJustin T. Gibbs 		/* NOTREACHED */
1526c5cb3888SJustin T. Gibbs 		break;
1527c5cb3888SJustin T. Gibbs 	}
1528c5cb3888SJustin T. Gibbs }
1529c5cb3888SJustin T. Gibbs 
1530c5cb3888SJustin T. Gibbs static void
add_macro_arg(const char * argtext,int argnum __unused)1531b18a2ef1SXin LI add_macro_arg(const char *argtext, int argnum __unused)
15327ce72dbaSJustin T. Gibbs {
15337ce72dbaSJustin T. Gibbs 	struct macro_arg *marg;
15347ce72dbaSJustin T. Gibbs 	int retval;
15357ce72dbaSJustin T. Gibbs 
15367ce72dbaSJustin T. Gibbs 
15377ce72dbaSJustin T. Gibbs 	if (cur_symbol == NULL || cur_symbol->type != MACRO) {
15387ce72dbaSJustin T. Gibbs 		stop("Invalid current symbol for adding macro arg",
15397ce72dbaSJustin T. Gibbs 		     EX_SOFTWARE);
15407ce72dbaSJustin T. Gibbs 		/* NOTREACHED */
15417ce72dbaSJustin T. Gibbs 	}
15427ce72dbaSJustin T. Gibbs 
15437ce72dbaSJustin T. Gibbs 	marg = (struct macro_arg *)malloc(sizeof(*marg));
15447ce72dbaSJustin T. Gibbs 	if (marg == NULL) {
15457ce72dbaSJustin T. Gibbs 		stop("Can't create macro_arg structure", EX_SOFTWARE);
15467ce72dbaSJustin T. Gibbs 		/* NOTREACHED */
15477ce72dbaSJustin T. Gibbs 	}
15487ce72dbaSJustin T. Gibbs 	marg->replacement_text = NULL;
15497ce72dbaSJustin T. Gibbs 	retval = snprintf(regex_pattern, sizeof(regex_pattern),
15507ce72dbaSJustin T. Gibbs 			  "[^-/A-Za-z0-9_](%s)([^-/A-Za-z0-9_]|$)",
15517ce72dbaSJustin T. Gibbs 			  argtext);
1552b18a2ef1SXin LI 	if (retval >= (int)sizeof(regex_pattern)) {
15537ce72dbaSJustin T. Gibbs 		stop("Regex text buffer too small for arg",
15547ce72dbaSJustin T. Gibbs 		     EX_SOFTWARE);
15557ce72dbaSJustin T. Gibbs 		/* NOTREACHED */
15567ce72dbaSJustin T. Gibbs 	}
15577ce72dbaSJustin T. Gibbs 	retval = regcomp(&marg->arg_regex, regex_pattern, REG_EXTENDED);
15587ce72dbaSJustin T. Gibbs 	if (retval != 0) {
15597ce72dbaSJustin T. Gibbs 		stop("Regex compilation failed", EX_SOFTWARE);
15607ce72dbaSJustin T. Gibbs 		/* NOTREACHED */
15617ce72dbaSJustin T. Gibbs 	}
15627ce72dbaSJustin T. Gibbs 	STAILQ_INSERT_TAIL(&cur_symbol->info.macroinfo->args, marg, links);
15637ce72dbaSJustin T. Gibbs }
15647ce72dbaSJustin T. Gibbs 
15657ce72dbaSJustin T. Gibbs static void
add_macro_body(const char * bodytext)15667ce72dbaSJustin T. Gibbs add_macro_body(const char *bodytext)
15677ce72dbaSJustin T. Gibbs {
15687ce72dbaSJustin T. Gibbs 	if (cur_symbol == NULL || cur_symbol->type != MACRO) {
15697ce72dbaSJustin T. Gibbs 		stop("Invalid current symbol for adding macro arg",
15707ce72dbaSJustin T. Gibbs 		     EX_SOFTWARE);
15717ce72dbaSJustin T. Gibbs 		/* NOTREACHED */
15727ce72dbaSJustin T. Gibbs 	}
15737ce72dbaSJustin T. Gibbs 	cur_symbol->info.macroinfo->body = strdup(bodytext);
15747ce72dbaSJustin T. Gibbs 	if (cur_symbol->info.macroinfo->body == NULL) {
15757ce72dbaSJustin T. Gibbs 		stop("Can't duplicate macro body text", EX_SOFTWARE);
15767ce72dbaSJustin T. Gibbs 		/* NOTREACHED */
15777ce72dbaSJustin T. Gibbs 	}
15787ce72dbaSJustin T. Gibbs }
15797ce72dbaSJustin T. Gibbs 
15807ce72dbaSJustin T. Gibbs static void
process_register(symbol_t ** p_symbol)158132da3127SJustin T. Gibbs process_register(symbol_t **p_symbol)
1582c5cb3888SJustin T. Gibbs {
1583c5cb3888SJustin T. Gibbs 	symbol_t *symbol = *p_symbol;
1584c5cb3888SJustin T. Gibbs 
1585c5cb3888SJustin T. Gibbs 	if (symbol->type == UNINITIALIZED) {
15867ce72dbaSJustin T. Gibbs 		snprintf(errbuf, sizeof(errbuf), "Undefined register %s",
1587c5cb3888SJustin T. Gibbs 			 symbol->name);
15887ce72dbaSJustin T. Gibbs 		stop(errbuf, EX_DATAERR);
1589c5cb3888SJustin T. Gibbs 		/* NOTREACHED */
1590c5cb3888SJustin T. Gibbs 	} else if (symbol->type == ALIAS) {
1591c5cb3888SJustin T. Gibbs 		*p_symbol = symbol->info.ainfo->parent;
1592c5cb3888SJustin T. Gibbs 	} else if ((symbol->type != REGISTER)
1593c5cb3888SJustin T. Gibbs 		&& (symbol->type != SCBLOC)
1594c5cb3888SJustin T. Gibbs 		&& (symbol->type != SRAMLOC)) {
15957ce72dbaSJustin T. Gibbs 		snprintf(errbuf, sizeof(errbuf),
1596c5cb3888SJustin T. Gibbs 			 "Specified symbol %s is not a register",
1597c5cb3888SJustin T. Gibbs 			 symbol->name);
15987ce72dbaSJustin T. Gibbs 		stop(errbuf, EX_DATAERR);
1599c5cb3888SJustin T. Gibbs 	}
1600c5cb3888SJustin T. Gibbs }
1601c5cb3888SJustin T. Gibbs 
1602c5cb3888SJustin T. Gibbs static void
format_1_instr(int opcode,symbol_ref_t * dest,expression_t * immed,symbol_ref_t * src,int ret)160332da3127SJustin T. Gibbs format_1_instr(int opcode, symbol_ref_t *dest, expression_t *immed,
160432da3127SJustin T. Gibbs 	       symbol_ref_t *src, int ret)
1605c5cb3888SJustin T. Gibbs {
1606c5cb3888SJustin T. Gibbs 	struct instruction *instr;
1607c5cb3888SJustin T. Gibbs 	struct ins_format1 *f1_instr;
1608c5cb3888SJustin T. Gibbs 
1609c5cb3888SJustin T. Gibbs 	if (src->symbol == NULL)
1610c5cb3888SJustin T. Gibbs 		src = dest;
1611c5cb3888SJustin T. Gibbs 
1612c5cb3888SJustin T. Gibbs 	/* Test register permissions */
1613c5cb3888SJustin T. Gibbs 	test_writable_symbol(dest->symbol);
1614c5cb3888SJustin T. Gibbs 	test_readable_symbol(src->symbol);
1615c5cb3888SJustin T. Gibbs 
1616c5cb3888SJustin T. Gibbs 	/* Ensure that immediate makes sense for this destination */
1617c5cb3888SJustin T. Gibbs 	type_check(dest->symbol, immed, opcode);
1618c5cb3888SJustin T. Gibbs 
1619c5cb3888SJustin T. Gibbs 	/* Allocate sequencer space for the instruction and fill it out */
1620c5cb3888SJustin T. Gibbs 	instr = seq_alloc();
1621c5cb3888SJustin T. Gibbs 	f1_instr = &instr->format.format1;
16223bafc9d4SJustin T. Gibbs 	f1_instr->ret = ret ? 1 : 0;
16233bafc9d4SJustin T. Gibbs 	f1_instr->opcode = opcode;
1624c5cb3888SJustin T. Gibbs 	f1_instr->destination = dest->symbol->info.rinfo->address
1625c5cb3888SJustin T. Gibbs 			      + dest->offset;
1626c5cb3888SJustin T. Gibbs 	f1_instr->source = src->symbol->info.rinfo->address
1627c5cb3888SJustin T. Gibbs 			 + src->offset;
1628c5cb3888SJustin T. Gibbs 	f1_instr->immediate = immed->value;
162937507c1bSJustin T. Gibbs 
163037507c1bSJustin T. Gibbs 	if (is_download_const(immed))
16313bafc9d4SJustin T. Gibbs 		f1_instr->parity = 1;
16327ce72dbaSJustin T. Gibbs 	else if (dest->symbol == mode_ptr.symbol) {
16337ce72dbaSJustin T. Gibbs 		u_int src_value;
16347ce72dbaSJustin T. Gibbs 		u_int dst_value;
16357ce72dbaSJustin T. Gibbs 
16367ce72dbaSJustin T. Gibbs 		/*
16377ce72dbaSJustin T. Gibbs 		 * Attempt to update mode information if
16387ce72dbaSJustin T. Gibbs 		 * we are operating on the mode register.
16397ce72dbaSJustin T. Gibbs 		 */
16407ce72dbaSJustin T. Gibbs 		if (src->symbol == allones.symbol)
16417ce72dbaSJustin T. Gibbs 			src_value = 0xFF;
16427ce72dbaSJustin T. Gibbs 		else if (src->symbol == allzeros.symbol)
16437ce72dbaSJustin T. Gibbs 			src_value = 0;
16447ce72dbaSJustin T. Gibbs 		else if (src->symbol == mode_ptr.symbol)
16457ce72dbaSJustin T. Gibbs 			src_value = (dst_mode << 4) | src_mode;
16467ce72dbaSJustin T. Gibbs 		else
16477ce72dbaSJustin T. Gibbs 			goto cant_update;
16487ce72dbaSJustin T. Gibbs 
16497ce72dbaSJustin T. Gibbs 		switch (opcode) {
16507ce72dbaSJustin T. Gibbs 		case AIC_OP_AND:
16517ce72dbaSJustin T. Gibbs 			dst_value = src_value & immed->value;
16527ce72dbaSJustin T. Gibbs 			break;
16537ce72dbaSJustin T. Gibbs 		case AIC_OP_XOR:
16547ce72dbaSJustin T. Gibbs 			dst_value = src_value ^ immed->value;
16557ce72dbaSJustin T. Gibbs 			break;
16567ce72dbaSJustin T. Gibbs 		case AIC_OP_ADD:
16577ce72dbaSJustin T. Gibbs 			dst_value = (src_value + immed->value) & 0xFF;
16587ce72dbaSJustin T. Gibbs 			break;
16597ce72dbaSJustin T. Gibbs 		case AIC_OP_OR:
16607ce72dbaSJustin T. Gibbs 			dst_value = src_value | immed->value;
16617ce72dbaSJustin T. Gibbs 			break;
16627ce72dbaSJustin T. Gibbs 		case AIC_OP_BMOV:
16637ce72dbaSJustin T. Gibbs 			dst_value = src_value;
16647ce72dbaSJustin T. Gibbs 			break;
16657ce72dbaSJustin T. Gibbs 		default:
16667ce72dbaSJustin T. Gibbs 			goto cant_update;
16677ce72dbaSJustin T. Gibbs 		}
16687ce72dbaSJustin T. Gibbs 		src_mode = dst_value & 0xF;
16697ce72dbaSJustin T. Gibbs 		dst_mode = (dst_value >> 4) & 0xF;
16707ce72dbaSJustin T. Gibbs 	}
167137507c1bSJustin T. Gibbs 
1672b0e28044SRobert Drehmel cant_update:
1673c5cb3888SJustin T. Gibbs 	symlist_free(&immed->referenced_syms);
1674c5cb3888SJustin T. Gibbs 	instruction_ptr++;
1675c5cb3888SJustin T. Gibbs }
1676c5cb3888SJustin T. Gibbs 
1677c5cb3888SJustin T. Gibbs static void
format_2_instr(int opcode,symbol_ref_t * dest,expression_t * places,symbol_ref_t * src,int ret)167832da3127SJustin T. Gibbs format_2_instr(int opcode, symbol_ref_t *dest, expression_t *places,
167932da3127SJustin T. Gibbs 	       symbol_ref_t *src, int ret)
1680c5cb3888SJustin T. Gibbs {
1681c5cb3888SJustin T. Gibbs 	struct instruction *instr;
1682c5cb3888SJustin T. Gibbs 	struct ins_format2 *f2_instr;
1683aa6dfd9dSJustin T. Gibbs 	uint8_t shift_control;
1684c5cb3888SJustin T. Gibbs 
1685c5cb3888SJustin T. Gibbs 	if (src->symbol == NULL)
1686c5cb3888SJustin T. Gibbs 		src = dest;
1687c5cb3888SJustin T. Gibbs 
1688c5cb3888SJustin T. Gibbs 	/* Test register permissions */
1689c5cb3888SJustin T. Gibbs 	test_writable_symbol(dest->symbol);
1690c5cb3888SJustin T. Gibbs 	test_readable_symbol(src->symbol);
1691c5cb3888SJustin T. Gibbs 
1692c5cb3888SJustin T. Gibbs 	/* Allocate sequencer space for the instruction and fill it out */
1693c5cb3888SJustin T. Gibbs 	instr = seq_alloc();
1694c5cb3888SJustin T. Gibbs 	f2_instr = &instr->format.format2;
16953bafc9d4SJustin T. Gibbs 	f2_instr->ret = ret ? 1 : 0;
16963bafc9d4SJustin T. Gibbs 	f2_instr->opcode = AIC_OP_ROL;
1697c5cb3888SJustin T. Gibbs 	f2_instr->destination = dest->symbol->info.rinfo->address
1698c5cb3888SJustin T. Gibbs 			      + dest->offset;
1699c5cb3888SJustin T. Gibbs 	f2_instr->source = src->symbol->info.rinfo->address
1700c5cb3888SJustin T. Gibbs 			 + src->offset;
1701c5cb3888SJustin T. Gibbs 	if (places->value > 8 || places->value <= 0) {
1702c5cb3888SJustin T. Gibbs 		stop("illegal shift value", EX_DATAERR);
1703c5cb3888SJustin T. Gibbs 		/* NOTREACHED */
1704c5cb3888SJustin T. Gibbs 	}
1705c5cb3888SJustin T. Gibbs 	switch (opcode) {
1706c5cb3888SJustin T. Gibbs 	case AIC_OP_SHL:
1707c5cb3888SJustin T. Gibbs 		if (places->value == 8)
1708c5cb3888SJustin T. Gibbs 			shift_control = 0xf0;
1709c5cb3888SJustin T. Gibbs 		else
1710c5cb3888SJustin T. Gibbs 			shift_control = (places->value << 4) | places->value;
1711c5cb3888SJustin T. Gibbs 		break;
1712c5cb3888SJustin T. Gibbs 	case AIC_OP_SHR:
1713c5cb3888SJustin T. Gibbs 		if (places->value == 8) {
1714c5cb3888SJustin T. Gibbs 			shift_control = 0xf8;
1715c5cb3888SJustin T. Gibbs 		} else {
1716c5cb3888SJustin T. Gibbs 			shift_control = (places->value << 4)
1717c5cb3888SJustin T. Gibbs 				      | (8 - places->value)
1718c5cb3888SJustin T. Gibbs 				      | 0x08;
1719c5cb3888SJustin T. Gibbs 		}
1720c5cb3888SJustin T. Gibbs 		break;
1721c5cb3888SJustin T. Gibbs 	case AIC_OP_ROL:
1722c5cb3888SJustin T. Gibbs 		shift_control = places->value & 0x7;
1723c5cb3888SJustin T. Gibbs 		break;
1724c5cb3888SJustin T. Gibbs 	case AIC_OP_ROR:
1725c5cb3888SJustin T. Gibbs 		shift_control = (8 - places->value) | 0x08;
1726c5cb3888SJustin T. Gibbs 		break;
1727c5cb3888SJustin T. Gibbs 	default:
1728c5cb3888SJustin T. Gibbs 		shift_control = 0; /* Quiet Compiler */
1729c5cb3888SJustin T. Gibbs 		stop("Invalid shift operation specified", EX_SOFTWARE);
1730c5cb3888SJustin T. Gibbs 		/* NOTREACHED */
1731c5cb3888SJustin T. Gibbs 		break;
1732c5cb3888SJustin T. Gibbs 	};
1733c5cb3888SJustin T. Gibbs 	f2_instr->shift_control = shift_control;
1734c5cb3888SJustin T. Gibbs 	symlist_free(&places->referenced_syms);
1735c5cb3888SJustin T. Gibbs 	instruction_ptr++;
1736c5cb3888SJustin T. Gibbs }
1737c5cb3888SJustin T. Gibbs 
1738c5cb3888SJustin T. Gibbs static void
format_3_instr(int opcode,symbol_ref_t * src,expression_t * immed,symbol_ref_t * address)173932da3127SJustin T. Gibbs format_3_instr(int opcode, symbol_ref_t *src,
174032da3127SJustin T. Gibbs 	       expression_t *immed, symbol_ref_t *address)
1741c5cb3888SJustin T. Gibbs {
1742c5cb3888SJustin T. Gibbs 	struct instruction *instr;
1743c5cb3888SJustin T. Gibbs 	struct ins_format3 *f3_instr;
1744c5cb3888SJustin T. Gibbs 	int addr;
1745c5cb3888SJustin T. Gibbs 
1746c5cb3888SJustin T. Gibbs 	/* Test register permissions */
1747c5cb3888SJustin T. Gibbs 	test_readable_symbol(src->symbol);
1748c5cb3888SJustin T. Gibbs 
1749c5cb3888SJustin T. Gibbs 	/* Ensure that immediate makes sense for this source */
1750c5cb3888SJustin T. Gibbs 	type_check(src->symbol, immed, opcode);
1751c5cb3888SJustin T. Gibbs 
1752c5cb3888SJustin T. Gibbs 	/* Allocate sequencer space for the instruction and fill it out */
1753c5cb3888SJustin T. Gibbs 	instr = seq_alloc();
1754c5cb3888SJustin T. Gibbs 	f3_instr = &instr->format.format3;
1755c5cb3888SJustin T. Gibbs 	if (address->symbol == NULL) {
1756594c945aSPedro F. Giffuni 		/* 'dot' reference.  Use the current instruction pointer */
1757c5cb3888SJustin T. Gibbs 		addr = instruction_ptr + address->offset;
1758c5cb3888SJustin T. Gibbs 	} else if (address->symbol->type == UNINITIALIZED) {
1759c5cb3888SJustin T. Gibbs 		/* forward reference */
1760c5cb3888SJustin T. Gibbs 		addr = address->offset;
1761c5cb3888SJustin T. Gibbs 		instr->patch_label = address->symbol;
1762c5cb3888SJustin T. Gibbs 	} else
1763c5cb3888SJustin T. Gibbs 		addr = address->symbol->info.linfo->address + address->offset;
17643bafc9d4SJustin T. Gibbs 	f3_instr->opcode = opcode;
17653bafc9d4SJustin T. Gibbs 	f3_instr->address = addr;
1766c5cb3888SJustin T. Gibbs 	f3_instr->source = src->symbol->info.rinfo->address
1767c5cb3888SJustin T. Gibbs 			 + src->offset;
1768c5cb3888SJustin T. Gibbs 	f3_instr->immediate = immed->value;
176937507c1bSJustin T. Gibbs 
177037507c1bSJustin T. Gibbs 	if (is_download_const(immed))
17713bafc9d4SJustin T. Gibbs 		f3_instr->parity = 1;
177237507c1bSJustin T. Gibbs 
1773c5cb3888SJustin T. Gibbs 	symlist_free(&immed->referenced_syms);
1774c5cb3888SJustin T. Gibbs 	instruction_ptr++;
1775c5cb3888SJustin T. Gibbs }
1776c5cb3888SJustin T. Gibbs 
1777c5cb3888SJustin T. Gibbs static void
test_readable_symbol(symbol_t * symbol)177832da3127SJustin T. Gibbs test_readable_symbol(symbol_t *symbol)
1779c5cb3888SJustin T. Gibbs {
17807ce72dbaSJustin T. Gibbs 
17817ce72dbaSJustin T. Gibbs 	if ((symbol->info.rinfo->modes & (0x1 << src_mode)) == 0) {
17827ce72dbaSJustin T. Gibbs 		snprintf(errbuf, sizeof(errbuf),
17837ce72dbaSJustin T. Gibbs 			"Register %s unavailable in source reg mode %d",
17847ce72dbaSJustin T. Gibbs 			symbol->name, src_mode);
17857ce72dbaSJustin T. Gibbs 		stop(errbuf, EX_DATAERR);
17867ce72dbaSJustin T. Gibbs 	}
17877ce72dbaSJustin T. Gibbs 
1788c5cb3888SJustin T. Gibbs 	if (symbol->info.rinfo->mode == WO) {
1789c5cb3888SJustin T. Gibbs 		stop("Write Only register specified as source",
1790c5cb3888SJustin T. Gibbs 		     EX_DATAERR);
1791c5cb3888SJustin T. Gibbs 		/* NOTREACHED */
1792c5cb3888SJustin T. Gibbs 	}
1793c5cb3888SJustin T. Gibbs }
1794c5cb3888SJustin T. Gibbs 
1795c5cb3888SJustin T. Gibbs static void
test_writable_symbol(symbol_t * symbol)179632da3127SJustin T. Gibbs test_writable_symbol(symbol_t *symbol)
1797c5cb3888SJustin T. Gibbs {
17987ce72dbaSJustin T. Gibbs 
17997ce72dbaSJustin T. Gibbs 	if ((symbol->info.rinfo->modes & (0x1 << dst_mode)) == 0) {
18007ce72dbaSJustin T. Gibbs 		snprintf(errbuf, sizeof(errbuf),
18017ce72dbaSJustin T. Gibbs 			"Register %s unavailable in destination reg mode %d",
18027ce72dbaSJustin T. Gibbs 			symbol->name, dst_mode);
18037ce72dbaSJustin T. Gibbs 		stop(errbuf, EX_DATAERR);
18047ce72dbaSJustin T. Gibbs 	}
18057ce72dbaSJustin T. Gibbs 
1806c5cb3888SJustin T. Gibbs 	if (symbol->info.rinfo->mode == RO) {
1807c5cb3888SJustin T. Gibbs 		stop("Read Only register specified as destination",
1808c5cb3888SJustin T. Gibbs 		     EX_DATAERR);
1809c5cb3888SJustin T. Gibbs 		/* NOTREACHED */
1810c5cb3888SJustin T. Gibbs 	}
1811c5cb3888SJustin T. Gibbs }
1812c5cb3888SJustin T. Gibbs 
1813c5cb3888SJustin T. Gibbs static void
type_check(symbol_t * symbol,expression_t * expression,int opcode)181432da3127SJustin T. Gibbs type_check(symbol_t *symbol, expression_t *expression, int opcode)
1815c5cb3888SJustin T. Gibbs {
1816c5cb3888SJustin T. Gibbs 	symbol_node_t *node;
1817c5cb3888SJustin T. Gibbs 	int and_op;
1818b7441906SJustin T. Gibbs 	uint8_t invalid_bits;
1819c5cb3888SJustin T. Gibbs 
1820c5cb3888SJustin T. Gibbs 	and_op = FALSE;
1821b7441906SJustin T. Gibbs 	if (opcode == AIC_OP_AND
1822b7441906SJustin T. Gibbs 	 || opcode == AIC_OP_BMOV
1823b7441906SJustin T. Gibbs 	 || opcode == AIC_OP_JE
1824b7441906SJustin T. Gibbs 	 || opcode == AIC_OP_JNE
1825b7441906SJustin T. Gibbs 	 || opcode == AIC_OP_JNZ
1826b7441906SJustin T. Gibbs 	 || opcode == AIC_OP_JZ)
1827c5cb3888SJustin T. Gibbs 		and_op = TRUE;
182837507c1bSJustin T. Gibbs 
1829c5cb3888SJustin T. Gibbs 	/*
1830c5cb3888SJustin T. Gibbs 	 * Make sure that we aren't attempting to write something
1831c5cb3888SJustin T. Gibbs 	 * that hasn't been defined.  If this is an and operation,
1832c5cb3888SJustin T. Gibbs 	 * this is a mask, so "undefined" bits are okay.
1833c5cb3888SJustin T. Gibbs 	 */
1834b7441906SJustin T. Gibbs 	invalid_bits = expression->value & ~symbol->info.rinfo->valid_bitmask;
1835b7441906SJustin T. Gibbs 	if (and_op == FALSE && invalid_bits != 0) {
18367ce72dbaSJustin T. Gibbs 		snprintf(errbuf, sizeof(errbuf),
1837c5cb3888SJustin T. Gibbs 			 "Invalid bit(s) 0x%x in immediate written to %s",
1838b7441906SJustin T. Gibbs 			 invalid_bits, symbol->name);
18397ce72dbaSJustin T. Gibbs 		stop(errbuf, EX_DATAERR);
1840c5cb3888SJustin T. Gibbs 		/* NOTREACHED */
1841c5cb3888SJustin T. Gibbs 	}
1842c5cb3888SJustin T. Gibbs 
1843c5cb3888SJustin T. Gibbs 	/*
1844c5cb3888SJustin T. Gibbs 	 * Now make sure that all of the symbols referenced by the
1845c5cb3888SJustin T. Gibbs 	 * expression are defined for this register.
1846c5cb3888SJustin T. Gibbs 	 */
1847c5cb3888SJustin T. Gibbs 	if (symbol->info.rinfo->typecheck_masks != FALSE) {
1848c5cb3888SJustin T. Gibbs 		for(node = expression->referenced_syms.slh_first;
1849c5cb3888SJustin T. Gibbs 		    node != NULL;
1850c5cb3888SJustin T. Gibbs 		    node = node->links.sle_next) {
1851c5cb3888SJustin T. Gibbs 			if ((node->symbol->type == MASK
185263183d8cSJustin T. Gibbs 			  || node->symbol->type == FIELD
185363183d8cSJustin T. Gibbs 			  || node->symbol->type == ENUM
185463183d8cSJustin T. Gibbs 			  || node->symbol->type == ENUM_ENTRY)
185563183d8cSJustin T. Gibbs 			 && symlist_search(&node->symbol->info.finfo->symrefs,
1856c5cb3888SJustin T. Gibbs 					   symbol->name) == NULL) {
18577ce72dbaSJustin T. Gibbs 				snprintf(errbuf, sizeof(errbuf),
185863183d8cSJustin T. Gibbs 					 "Invalid field or mask %s "
1859c5cb3888SJustin T. Gibbs 					 "for register %s",
1860c5cb3888SJustin T. Gibbs 					 node->symbol->name, symbol->name);
18617ce72dbaSJustin T. Gibbs 				stop(errbuf, EX_DATAERR);
1862c5cb3888SJustin T. Gibbs 				/* NOTREACHED */
1863c5cb3888SJustin T. Gibbs 			}
1864c5cb3888SJustin T. Gibbs 		}
1865c5cb3888SJustin T. Gibbs 	}
1866c5cb3888SJustin T. Gibbs }
1867c5cb3888SJustin T. Gibbs 
1868c5cb3888SJustin T. Gibbs static void
make_expression(expression_t * immed,int value)186932da3127SJustin T. Gibbs make_expression(expression_t *immed, int value)
1870c5cb3888SJustin T. Gibbs {
1871c5cb3888SJustin T. Gibbs 	SLIST_INIT(&immed->referenced_syms);
1872c5cb3888SJustin T. Gibbs 	immed->value = value & 0xff;
1873c5cb3888SJustin T. Gibbs }
1874c5cb3888SJustin T. Gibbs 
1875c5cb3888SJustin T. Gibbs static void
add_conditional(symbol_t * symbol)187632da3127SJustin T. Gibbs add_conditional(symbol_t *symbol)
1877c5cb3888SJustin T. Gibbs {
18783bafc9d4SJustin T. Gibbs 	static int numfuncs;
1879c5cb3888SJustin T. Gibbs 
18803bafc9d4SJustin T. Gibbs 	if (numfuncs == 0) {
18813bafc9d4SJustin T. Gibbs 		/* add a special conditional, "0" */
18823bafc9d4SJustin T. Gibbs 		symbol_t *false_func;
18833bafc9d4SJustin T. Gibbs 
18843bafc9d4SJustin T. Gibbs 		false_func = symtable_get("0");
18853bafc9d4SJustin T. Gibbs 		if (false_func->type != UNINITIALIZED) {
18863bafc9d4SJustin T. Gibbs 			stop("Conditional expression '0' "
18873bafc9d4SJustin T. Gibbs 			     "conflicts with a symbol", EX_DATAERR);
18883bafc9d4SJustin T. Gibbs 			/* NOTREACHED */
18893bafc9d4SJustin T. Gibbs 		}
18903bafc9d4SJustin T. Gibbs 		false_func->type = CONDITIONAL;
18913bafc9d4SJustin T. Gibbs 		initialize_symbol(false_func);
18923bafc9d4SJustin T. Gibbs 		false_func->info.condinfo->func_num = numfuncs++;
18933bafc9d4SJustin T. Gibbs 		symlist_add(&patch_functions, false_func, SYMLIST_INSERT_HEAD);
18943bafc9d4SJustin T. Gibbs 	}
18953bafc9d4SJustin T. Gibbs 
18963bafc9d4SJustin T. Gibbs 	/* This condition has occurred before */
18973bafc9d4SJustin T. Gibbs 	if (symbol->type == CONDITIONAL)
18983bafc9d4SJustin T. Gibbs 		return;
18993bafc9d4SJustin T. Gibbs 
19003bafc9d4SJustin T. Gibbs 	if (symbol->type != UNINITIALIZED) {
19013bafc9d4SJustin T. Gibbs 		stop("Conditional expression conflicts with a symbol",
1902c5cb3888SJustin T. Gibbs 		     EX_DATAERR);
1903c5cb3888SJustin T. Gibbs 		/* NOTREACHED */
1904c5cb3888SJustin T. Gibbs 	}
19053bafc9d4SJustin T. Gibbs 
19063bafc9d4SJustin T. Gibbs 	symbol->type = CONDITIONAL;
19073bafc9d4SJustin T. Gibbs 	initialize_symbol(symbol);
19083bafc9d4SJustin T. Gibbs 	symbol->info.condinfo->func_num = numfuncs++;
19093bafc9d4SJustin T. Gibbs 	symlist_add(&patch_functions, symbol, SYMLIST_INSERT_HEAD);
1910c5cb3888SJustin T. Gibbs }
1911c5cb3888SJustin T. Gibbs 
19122d0fbde8SJustin T. Gibbs static void
add_version(const char * verstring)19132d0fbde8SJustin T. Gibbs add_version(const char *verstring)
19142d0fbde8SJustin T. Gibbs {
1915b18a2ef1SXin LI 	const char verprefix[] = " * ";
19162d0fbde8SJustin T. Gibbs 	int newlen;
19172d0fbde8SJustin T. Gibbs 	int oldlen;
19182d0fbde8SJustin T. Gibbs 
1919b18a2ef1SXin LI 	newlen = strlen(verstring) + strlen(verprefix);
19202d0fbde8SJustin T. Gibbs 	oldlen = 0;
19212d0fbde8SJustin T. Gibbs 	if (versions != NULL)
19222d0fbde8SJustin T. Gibbs 		oldlen = strlen(versions);
19232d0fbde8SJustin T. Gibbs 	versions = realloc(versions, newlen + oldlen + 2);
19242d0fbde8SJustin T. Gibbs 	if (versions == NULL)
19252d0fbde8SJustin T. Gibbs 		stop("Can't allocate version string", EX_SOFTWARE);
1926b18a2ef1SXin LI 	strcpy(&versions[oldlen], verprefix);
1927b18a2ef1SXin LI 	strcpy(&versions[oldlen + strlen(verprefix)], verstring);
19282d0fbde8SJustin T. Gibbs 	versions[newlen + oldlen] = '\n';
19292d0fbde8SJustin T. Gibbs 	versions[newlen + oldlen + 1] = '\0';
19302d0fbde8SJustin T. Gibbs }
19312d0fbde8SJustin T. Gibbs 
1932b18a2ef1SXin LI static void
yyerror(const char * string)193332da3127SJustin T. Gibbs yyerror(const char *string)
1934c5cb3888SJustin T. Gibbs {
1935c5cb3888SJustin T. Gibbs 	stop(string, EX_DATAERR);
1936c5cb3888SJustin T. Gibbs }
193737507c1bSJustin T. Gibbs 
193837507c1bSJustin T. Gibbs static int
is_download_const(expression_t * immed)193932da3127SJustin T. Gibbs is_download_const(expression_t *immed)
194037507c1bSJustin T. Gibbs {
194137507c1bSJustin T. Gibbs 	if ((immed->referenced_syms.slh_first != NULL)
194237507c1bSJustin T. Gibbs 	 && (immed->referenced_syms.slh_first->symbol->type == DOWNLOAD_CONST))
194337507c1bSJustin T. Gibbs 		return (TRUE);
194437507c1bSJustin T. Gibbs 
194537507c1bSJustin T. Gibbs 	return (FALSE);
194637507c1bSJustin T. Gibbs }
1947