* asranlib/asranlib.c, link/lkar.h, link/lkar.c:
[fw/sdcc] / as / z80 / z80adr.c
1 /* z80adr.c
2
3    Copyright (C) 1989-1995 Alan R. Baldwin
4    721 Berkeley St., Kent, Ohio 44240
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
9 later version.
10
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.
15
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/>. */
18
19 /*
20  * Extensions: P. Felber
21  */
22
23 #include <stdio.h>
24 #include <setjmp.h>
25 #include "asm.h"
26 #include "z80.h"
27
28 /*
29  * Read an address specifier. Pack the
30  * address information into the supplied
31  * `expr' structure. Return the mode of
32  * the address.
33  *
34  * This addr(esp) routine performs the following addressing decoding:
35  *
36  *      address         mode            flag            addr            base
37  *      #n              S_IMMED         0               n               NULL
38  *      label           s_type          ----            s_addr          s_area
39  *      [REG]           S_IND+icode     0               0               NULL
40  *      [label]         S_INDM          ----            s_addr          s_area
41  *      offset[REG]     S_IND+icode     ----            offset          ----
42  */
43 int
44 addr(esp)
45 register struct expr *esp;
46 {
47         register int c, mode = 0, indx;
48
49         if ((c = getnb()) == '#') {
50                 expr(esp, 0);
51                 esp->e_mode = S_IMMED;
52         } else
53         if (c == LFIND) {
54                 if ((indx = admode(R8)) != 0) {
55                         mode = S_INDB;
56                 } else
57                 if ((indx = admode(R16)) != 0) {
58                         mode = S_INDR;
59                 } else
60                 if ((indx = admode(R8X)) != 0) {
61                         mode = S_R8X;
62                         aerr();
63                 } else
64                 if ((indx = admode(R16X)) != 0) {
65                         mode = S_R16X;
66                         aerr();
67                 } else {
68                         expr(esp, 0);
69                         esp->e_mode = S_INDM;
70                 }
71                 if (indx) {
72                         esp->e_mode = (mode + indx)&0xFF;
73                         esp->e_base.e_ap = NULL;
74                 }
75                 if ((c = getnb()) != RTIND)
76                         qerr();
77         } else {
78                 unget(c);
79                 if ((indx = admode(R8)) != 0) {
80                         mode = S_R8;
81                 } else
82                 if ((indx = admode(R16)) != 0) {
83                         mode = S_R16;
84                 } else
85                 if ((indx = admode(R8X)) != 0) {
86                         mode = S_R8X;
87                 } else
88                 if ((indx = admode(R16X)) != 0) {
89                         mode = S_R16X;
90                 } else {
91                         expr(esp, 0);
92                         esp->e_mode = S_USER;
93                 }
94                 if (indx) {
95                         esp->e_addr = indx&0xFF;
96                         esp->e_mode = mode;
97                         esp->e_base.e_ap = NULL;
98                 }
99                 if ((c = getnb()) == LFIND) {
100 #ifndef GAMEBOY
101                         if ((indx=admode(R16))!=0
102                                 && ((indx&0xFF)==IX || (indx&0xFF)==IY)) {
103 #else /* GAMEBOY */
104                         if ((indx=admode(R16))!=0) {
105 #endif /* GAMEBOY */
106                                 esp->e_mode = S_INDR + (indx&0xFF);
107                         } else {
108                                 aerr();
109                         }
110                         if ((c = getnb()) != RTIND)
111                                 qerr();
112                 } else {
113                         unget(c);
114                 }
115         }
116         return (esp->e_mode);
117 }
118
119 /*
120  * Enter admode() to search a specific addressing mode table
121  * for a match. Return the addressing value on a match or
122  * zero for no match.
123  */
124 int
125 admode(sp)
126 register struct adsym *sp;
127 {
128         register char *ptr;
129         register int i;
130         register const char *ips;
131
132         ips = ip;
133         unget(getnb());
134
135         i = 0;
136         while ( *(ptr = (char *) &sp[i]) ) {
137                 if (srch(ptr)) {
138                         return(sp[i].a_val);
139                 }
140                 i++;
141         }
142         ip = ips;
143         return(0);
144 }
145
146 /*
147  *      srch --- does string match ?
148  */
149 int
150 srch(str)
151 register char *str;
152 {
153         register const char *ptr;
154         ptr = ip;
155
156 #if     CASE_SENSITIVE
157         while (*ptr && *str) {
158                 if (*ptr != *str)
159                         break;
160                 ptr++;
161                 str++;
162         }
163         if (*ptr == *str) {
164                 ip = ptr;
165                 return(1);
166         }
167 #else
168         while (*ptr && *str) {
169                 if (ccase[(unsigned char)(*ptr)] != ccase[(unsigned char)(*str)])
170                         break;
171                 ptr++;
172                 str++;
173         }
174         if (ccase[(unsigned char)(*ptr)] == ccase[(unsigned char)(*str)]) {
175                 ip = ptr;
176                 return(1);
177         }
178 #endif
179
180         if (!*str)
181                 if (any(*ptr," \t\n,);")) {
182                         ip = ptr;
183                         return(1);
184                 }
185         return(0);
186 }
187
188 /*
189  *      any --- does str contain c?
190  */
191 int
192 any(c,str)
193 char    c, *str;
194 {
195         while (*str)
196                 if(*str++ == c)
197                         return(1);
198         return(0);
199 }
200
201 /*
202  * Registers
203  */
204
205 struct  adsym   R8[] = {
206     { "b",      B|0400 },
207     { "c",      C|0400 },
208     { "d",      D|0400 },
209     { "e",      E|0400 },
210     { "h",      H|0400 },
211     { "l",      L|0400 },
212     { "a",      A|0400 },
213     { "B",      B|0400 },
214     { "C",      C|0400 },
215     { "D",      D|0400 },
216     { "E",      E|0400 },
217     { "H",      H|0400 },
218     { "L",      L|0400 },
219     { "A",      A|0400 },
220     { "",       000 }
221 };
222
223 struct  adsym   R8X[] = {
224     { "i",      I|0400 },
225     { "r",      R|0400 },
226     { "I",      I|0400 },
227     { "R",      R|0400 },
228     { "",       000 }
229 };
230
231 struct  adsym   R16[] = {
232     { "bc",     BC|0400 },
233     { "de",     DE|0400 },
234     { "hl",     HL|0400 },
235     { "sp",     SP|0400 },
236     { "BC",     BC|0400 },
237     { "DE",     DE|0400 },
238     { "HL",     HL|0400 },
239     { "SP",     SP|0400 },
240 #ifndef GAMEBOY
241     { "ix",     IX|0400 },
242     { "iy",     IY|0400 },
243     { "IX",     IX|0400 },
244     { "IY",     IY|0400 },
245 #else /* GAMEBOY */
246     { "hl-",    HLD|0400 },
247     { "hl+",    HLI|0400 },
248     { "hld",    HLD|0400 },
249     { "hli",    HLI|0400 },
250     { "HL-",    HLD|0400 },
251     { "HL+",    HLI|0400 },
252     { "HLD",    HLD|0400 },
253     { "HLI",    HLI|0400 },
254 #endif /* GAMEBOY */
255     { "",       000 }
256 };
257
258 struct  adsym   R16X[] = {
259     { "af",     AF|0400 },
260     { "AF",     AF|0400 },
261 #ifndef GAMEBOY
262     { "af'",    AF|0400 },
263     { "AF'",    AF|0400 },
264 #endif /* GAMEBOY */
265     { "",       000 }
266 };
267
268 /*
269  * Conditional definitions
270  */
271
272 struct  adsym   CND[] = {
273     { "NZ",     NZ|0400 },
274     { "Z",      Z |0400 },
275     { "NC",     NC|0400 },
276     { "C",      CS|0400 },
277     { "nz",     NZ|0400 },
278     { "z",      Z |0400 },
279     { "nc",     NC|0400 },
280     { "c",      CS|0400 },
281 #ifndef GAMEBOY
282     { "PO",     PO|0400 },
283     { "PE",     PE|0400 },
284     { "P",      P |0400 },
285     { "M",      M |0400 },
286     { "po",     PO|0400 },
287     { "pe",     PE|0400 },
288     { "p",      P |0400 },
289     { "m",      M |0400 },
290 #endif /* GAMEBOY */
291     { "",       000 }
292 };