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