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