struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / sdas / asz80 / z80adr.c
blob6f9380e01875d68cc662ef0de8e00df7fddddbf7
1 /* z80adr.c */
3 /*
4 * Copyright (C) 1989-2009 Alan R. Baldwin
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * Alan R. Baldwin
21 * 721 Berkeley St.
22 * Kent, Ohio 44240
26 * xerr messages and order fix Copyright (C) 1989-2021 Alan R. Baldwin
27 * from ASxxxx 5.40
31 * Extensions: P. Felber
34 #include "asxxxx.h"
35 #include "z80.h"
38 * Read an address specifier. Pack the
39 * address information into the supplied
40 * `expr' structure. Return the mode of
41 * the address.
43 * This addr(esp) routine performs the following addressing decoding:
45 * address mode flag addr base
46 * #n S_IMMED 0 n NULL
47 * label s_type ---- s_addr s_area
48 * [REG] S_IND+icode 0 0 NULL
49 * [label] S_INDM ---- s_addr s_area
50 * offset[REG] S_IND+icode ---- offset ----
52 int
53 addr(esp)
54 struct expr *esp;
56 int c, mode, indx;
57 char *p;
59 /* fix order of '<', '>', and '#' */
60 p = ip;
61 if (((c = getnb()) == '<') || (c == '>')) {
62 p = ip-1;
63 if (getnb() == '#') {
64 *p = *(ip-1);
65 *(ip-1) = c;
68 ip = p;
70 if ((c = getnb()) == '#') {
71 expr(esp, 0);
72 esp->e_mode = S_IMMED;
73 } else
74 if (c == LFIND) {
75 if ((indx = admode(R8)) != 0) {
76 mode = S_INDB;
77 } else
78 if ((indx = admode(R16)) != 0) {
79 mode = S_INDR;
80 } else
81 if ((indx = admode(R8X)) != 0) {
82 mode = S_R8X;
83 xerr('a', "No I or R.");
84 } else
85 if ((indx = admode(R16X)) != 0) {
86 mode = S_R16X;
87 xerr('a', "Registers AF and AF' are invalid.");
88 } else {
89 mode = S_INDM;
90 expr(esp, 0);
91 esp->e_mode = mode;
93 if (indx) {
94 esp->e_mode = (mode + indx)&0xFF;
95 esp->e_base.e_ap = NULL;
97 if ((c = getnb()) != RTIND) {
98 xerr('a', "Missing ')'.");
100 } else {
101 unget(c);
102 if ((indx = admode(R8)) != 0) {
103 mode = S_R8;
104 } else
105 if ((indx = admode(R16)) != 0) {
106 mode = S_R16;
107 } else
108 if ((indx = admode(R8X)) != 0) {
109 mode = S_R8X;
110 } else
111 if ((indx = admode(R8U1)) != 0) {
112 mode = S_R8U1;
113 } else
114 if ((indx = admode(R8U2)) != 0) {
115 mode = S_R8U2;
116 } else
117 if ((indx = admode(R16X)) != 0) {
118 mode = S_R16X;
119 } else
120 if ((indx = admode(R8MB)) != 0) {
121 mode = S_R8MB;
122 } else {
123 mode = S_USER;
124 expr(esp, 0);
125 esp->e_mode = mode;
127 if (indx) {
128 esp->e_addr = indx&0xFF;
129 esp->e_mode = mode;
130 esp->e_base.e_ap = NULL;
132 if ((c = getnb()) == LFIND) {
133 if ((indx=admode(R16))!=0
134 && ((indx&0xFF)==IX || (indx&0xFF)==IY)) {
135 esp->e_mode = S_INDR + (indx&0xFF);
136 } else {
137 xerr('a', "Register IX or IY required.");
139 if ((c = getnb()) != RTIND)
140 xerr('a', "Missing ')'.");
141 } else {
142 unget(c);
145 return (esp->e_mode);
149 * When building a table that has variations of a common
150 * symbol always start with the most complex symbol first.
151 * for example if x, x+, and x++ are in the same table
152 * the order should be x++, x+, and then x. The search
153 * order is then most to least complex.
157 * When searching symbol tables that contain characters
158 * not of type LTR16, eg with '-' or '+', always search
159 * the more complex symbol tables first. For example:
160 * searching for x+ will match the first part of x++,
161 * a false match if the table with x+ is searched
162 * before the table with x++.
166 * Enter admode() to search a specific addressing mode table
167 * for a match. Return the addressing value on a match or
168 * zero for no match.
171 admode(sp)
172 struct adsym *sp;
174 char *ptr;
175 int i;
176 char *ips;
178 ips = ip;
179 unget(getnb());
181 i = 0;
182 while ( *(ptr = &sp[i].a_str[0]) ) {
183 if (srch(ptr)) {
184 return(sp[i].a_val);
186 i++;
188 ip = ips;
189 return(0);
193 * srch --- does string match ?
196 srch(str)
197 char *str;
199 char *ptr;
200 ptr = ip;
202 while (*ptr && *str) {
203 if (ccase[*ptr & 0x007F] != ccase[*str & 0x007F])
204 break;
205 ptr++;
206 str++;
208 if (ccase[*ptr & 0x007F] == ccase[*str & 0x007F]) {
209 ip = ptr;
210 return(1);
213 if (!*str)
214 if (!(ctype[*ptr & 0x007F] & LTR16)) {
215 ip = ptr;
216 return(1);
218 return(0);
222 * Registers
225 struct adsym R8[] = {
226 { "b", B|0400 },
227 { "c", C|0400 },
228 { "d", D|0400 },
229 { "e", E|0400 },
230 { "h", H|0400 },
231 { "l", L|0400 },
232 { "a", A|0400 },
233 { "", 0000 }
236 struct adsym R8X[] = {
237 { "i", I|0400 },
238 { "r", R|0400 },
239 { "", 0000 }
242 /* Undocumented instructions for 0xDD prefix H->IX high, L->IX low */
243 struct adsym R8U1[] = {
244 { "ixh", H|0400 },
245 { "ixl", L|0400 },
246 { "", 0000 }
249 /* Undocumented instructions for 0xFD prefix H->IY high, L->IY low */
250 struct adsym R8U2[] = {
251 { "iyh", H|0400 },
252 { "iyl", L|0400 },
253 { "", 0000 }
256 struct adsym R16[] = {
257 { "bc", BC|0400 },
258 { "de", DE|0400 },
259 { "hl", HL|0400 },
260 { "sp", SP|0400 },
261 { "ix", IX|0400 },
262 { "iy", IY|0400 },
263 { "", 0000 }
266 struct adsym R16X[] = {
267 { "af'", AF|0400 }, /* af' must be first !!! */
268 { "af", AF|0400 },
269 { "", 0000 }
272 struct adsym R8MB[] = {
273 { "mb", MB|0400 },
274 { "", 0000 }
277 struct adsym RX[] = {
278 { "x", X|0400 }, /* for ZXN pop x */
279 { "", 0000 }
283 * Conditional definitions
286 struct adsym CND[] = {
287 { "NZ", NZ|0400 },
288 { "Z", Z |0400 },
289 { "NC", NC|0400 },
290 { "C", CS|0400 },
291 { "PO", PO|0400 },
292 { "PE", PE|0400 },
293 { "P", P |0400 },
294 { "M", M |0400 },
295 { "", 0000 }