* asranlib/asranlib.c, link/lkar.h, link/lkar.c:
[fw/sdcc] / as / mcs51 / i51adr.c
1 /* i51adr.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  * Ported from 8085 to 8051 by John Hartman 30-Apr-1995
21  * Continued, 29-May-95
22  */
23
24 #include <stdio.h>
25 #include <setjmp.h>
26 #include "asm.h"
27 #include "i8051.h"
28
29 extern int admode (struct adsym *);
30
31 struct adsym reg51[] = {        /* R0 thru R7 registers */
32 {       "R0",   R0},
33 {       "R1",   R1},
34 {       "R2",   R2},
35 {       "R3",   R3},
36 {       "R4",   R4},
37 {       "R5",   R5},
38 {       "R6",   R6},
39 {       "R7",   R7},
40 {       "A",    A},
41 {       "DPTR", DPTR},
42 {       "PC",   PC},
43 {       "C",    C},
44 {       "AB",   AB},
45 {       "r0",   R0},
46 {       "r1",   R1},
47 {       "r2",   R2},
48 {       "r3",   R3},
49 {       "r4",   R4},
50 {       "r5",   R5},
51 {       "r6",   R6},
52 {       "r7",   R7},
53 {       "a",    A},
54 {       "dptr", DPTR},
55 {       "pc",   PC},
56 {       "c",    C},
57 {       "ab",   AB},
58 {       "",     0x00}
59 };
60
61 /*  Classify argument as to address mode */
62 int
63 addr(esp)
64 register struct expr *esp;
65 {
66         register int c;
67         register unsigned rd;
68
69         if ((c = getnb()) == '#') {
70                 /*  Immediate mode */
71                 expr(esp, 0);
72                 esp->e_mode = S_IMMED;
73         }
74         else if (c == '@') {
75                 /* choices are @R0, @R1, @DPTR, @A+PC, @A+DPTR */
76                 switch (reg()) {
77                 case R0:
78                         esp->e_mode = S_AT_R;
79                         esp->e_addr = R0;
80                         break;
81                 case R1:
82                         esp->e_mode = S_AT_R;
83                         esp->e_addr = R1;
84                         break;
85                 case DPTR:
86                         esp->e_mode = S_AT_DP;
87                         esp->e_addr = DPTR;
88                         break;
89                 case A:
90                         if (getnb() == '+') {
91                                 rd = reg();
92                                 if (rd == PC) {
93                                         esp->e_mode = S_AT_APC;
94                                         esp->e_addr = 0;
95                                 } else if (rd == DPTR) {
96                                         esp->e_mode = S_AT_ADP;
97                                         esp->e_addr = 0;
98                                 } else {
99                                         aerr();
100                                 }
101                         } else
102                                 aerr();
103                         break;
104                 }
105
106                 esp->e_flag = 0;
107                 esp->e_base.e_ap = NULL;
108         }
109         else if (c == '*') {
110                 /* Force direct page */
111                 expr(esp, 0);
112                 esp->e_mode = S_DIR;
113                 if (esp->e_addr & ~0xFF)
114                         err('d');
115         }
116         else if (c == '/') {
117                 /* Force inverted bit  */
118                 expr(esp, 0);
119                 esp->e_mode = S_NOT_BIT;
120                 if (esp->e_addr & ~0xFF)
121                         err('d');
122         }
123         else {
124                 unget(c);
125
126                 /* try for register: A, AB, R0-R7, DPTR, PC, Cy */
127                 if ((esp->e_addr = admode(reg51)) != -1) {
128                         switch (esp->e_addr) {
129                         case A:
130                                 esp->e_mode = S_A;
131                                 break;
132                         case AB:
133                                 esp->e_mode = S_RAB;
134                                 break;
135                         case DPTR:
136                                 esp->e_mode = S_DPTR;
137                                 break;
138                         case PC:
139                                 esp->e_mode = S_PC;
140                                 break;
141                         case C:
142                                 esp->e_mode = S_C;
143                                 break;
144                         default:
145                                 /* R0-R7 */
146                                 esp->e_mode = S_REG;
147                         }
148                 } else {
149                         /* Must be an expression */
150                         expr(esp, 0);
151                         if ((!esp->e_flag)
152                                 && (esp->e_base.e_ap==NULL)
153                                 && !(esp->e_addr & ~0xFF)) {
154                                 esp->e_mode = S_DIR;
155                         } else {
156                                 esp->e_mode = S_EXT;
157                         }
158                 }
159         }
160         return (esp->e_mode);
161 }
162
163
164 /*
165  *      any --- does str contain c?
166  */
167 int
168 any(c,str)
169 char    c, *str;
170 {
171         while (*str)
172                 if(*str++ == c)
173                         return(1);
174         return(0);
175 }
176
177 int
178 srch(str)
179 register char *str;
180 {
181         register const char *ptr;
182         ptr = ip;
183
184 #if     CASE_SENSITIVE
185         while (*ptr && *str) {
186                 if(*ptr != *str)
187                         break;
188                 ptr++;
189                 str++;
190         }
191         if (*ptr == *str) {
192                 ip = ptr;
193                 return(1);
194         }
195 #else
196         while (*ptr && *str) {
197                 if(ccase[*ptr] != ccase[*str])
198                         break;
199                 ptr++;
200                 str++;
201         }
202         if (ccase[*ptr] == ccase[*str]) {
203                 ip = ptr;
204                 return(1);
205         }
206 #endif
207
208         if (!*str)
209                 if (any(*ptr," \t\n,];")) {
210                         ip = ptr;
211                         return(1);
212                 }
213         return(0);
214 }
215
216 /*
217  * Enter admode() to search a specific addressing mode table
218  * for a match. Return the addressing value on a match or
219  * -1 for no match.
220  */
221 int
222 admode(sp)
223 register struct adsym *sp;
224 {
225         register char *ptr;
226         register int i;
227         unget(getnb());
228         i = 0;
229         while ( *(ptr = (char *) &sp[i]) ) {
230                 if (srch(ptr)) {
231                         return(sp[i].a_val);
232                 }
233                 i++;
234         }
235         return(-1);
236 }
237
238 /*
239  *      srch --- does string match ?
240  */
241
242 /*
243  * Read a register name.  Return register value, -1 if no register found
244  */
245 int
246 reg()
247 {
248         register struct mne *mp;
249         char id[NCPS];
250
251         getid(id, -1);
252         if ((mp = mlookup(id))==NULL) {
253                 aerr();
254                 return (-1);
255         }
256         switch (mp->m_type) {
257         case S_A:
258         case S_AB:
259         case S_DPTR:
260         case S_PC:
261         case S_REG:
262                 return (mp->m_valu);
263
264         default:
265                 return (-1);
266         }
267 }