1 /* rabadr.c */
2
3 /*
4 * Copyright (C) 1989-2009 Alan R. Baldwin
5 *
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.
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 * Alan R. Baldwin
21 * 721 Berkeley St.
22 * Kent, Ohio 44240
23 *
24 * ported to the Rabbit2000 by
25 * Ulrich Raich and Razaq Ijoduola
26 * PS Division
27 * CERN
28 * CH-1211 Geneva-23
29 * email: Ulrich dot Raich at cern dot ch
30 */
31
32 /*
33 * Extensions: P. Felber
34 *
35 * Altered by Leland Morrison to support rabbit 2000
36 * and rabbit 4000 instruction sets (2011)
37 */
38
39 #include "asxxxx.h"
40 #include "rab.h"
41
42 /*
43 * Read an address specifier. Pack the
44 * address information into the supplied
45 * `expr' structure. Return the mode of
46 * the address.
47 *
48 * This addr(esp) routine performs the following addressing decoding:
49 *
50 * address mode flag addr base
51 * #n S_IMMED 0 n NULL
52 * label s_type ---- s_addr s_area
53 * [REG] S_IND+icode 0 0 NULL
54 * [label] S_INDM ---- s_addr s_area
55 * offset[REG] S_IND+icode ---- offset ----
56 */
57 int
addr(esp)58 addr(esp)
59 struct expr *esp;
60 {
61 int c, mode, indx;
62
63 if ((c = getnb()) == '#') {
64 expr(esp, 0);
65 esp->e_mode = S_IMMED;
66 #if 0
67 /* ljm - leading digit is used for offset for dd(ix|iy|sp) */
68 } else if ((c == '-') || ((c >= '0') && (c <= '9'))) {
69 unget(c);
70 expr(esp, 0);
71 esp->e_mode = S_IMMED;
72 #endif
73 } else
74 if (c == LFIND) {
75 /* ljm comment -
76 * '(' number ')'
77 * or '(' register=[hl,ix,iy,sp,bc,de] ')'
78 * ref to memory, scan the next 'symbol' to see if
79 * it is a register or an absolute address
80 */
81 if ((indx = admode(R8)) != 0) {
82 mode = S_INDB;
83 } else
84 if ((indx = admode(R8X)) != 0) {
85 mode = S_R8X;
86 aerr();
87 } else
88 if ((indx = admode(R16X)) != 0) {
89 mode = S_R16X;
90 aerr();
91 } else
92 if ((indx = admode(R16)) != 0) {
93 mode = S_INDR;
94 } else {
95 mode = S_INDM;
96 expr(esp, 0);
97 esp->e_mode = mode;
98 }
99 if (indx) {
100 esp->e_mode = (mode + indx)&0xFF;
101 esp->e_base.e_ap = NULL;
102 }
103 /* ljm comment -
104 * flag an error if the closing paren is absent
105 */
106 if ((c = getnb()) != RTIND) {
107 qerr();
108 }
109 } else {
110 unget(c);
111 /* ljm -
112 * cases:
113 * register
114 * symbol
115 * symbol(register)
116 * number
117 * number(register)
118 *
119 * scan the list(s) of registers to see if the
120 * name matches the name of one of the processor
121 * registers
122 */
123 if ((indx = admode(R8)) != 0) {
124 mode = S_R8;
125 } else
126 if ((indx = admode(R8X)) != 0) {
127 mode = S_R8X;
128 } else
129 if ((indx = admode(R16X)) != 0) {
130 mode = S_R16X;
131 } else
132 if ((indx = admode(R16)) != 0) {
133 mode = S_R16;
134 } else
135 if ((indx = admode(R32_JKHL)) != 0) {
136 mode = S_R32_JKHL;
137 } else
138 if ((indx = admode(R32_BCDE)) != 0) {
139 mode = S_R32_BCDE;
140 } else
141 if ((indx = admode(RXPC)) != 0) {
142 mode = S_RXPC;
143 } else {
144 mode = S_USER;
145 expr(esp, 0);
146 esp->e_mode = mode;
147 }
148 if (indx) {
149 esp->e_addr = indx&0xFF;
150 esp->e_mode = mode;
151 esp->e_base.e_ap = NULL;
152 }
153 if ((c = getnb()) == LFIND) {
154 indx = admode(R16);
155 if ((indx&0xFF)==IX || (indx&0xFF)==IY ||
156 (indx&0xFF)==SP)
157 {
158 esp->e_mode = S_INDR + (indx&0xFF);
159 } else if ( (indx&0xFF)==HL ) {
160 esp->e_mode = S_IDHL_OFFSET;
161 } else {
162 aerr();
163 }
164 if ((c = getnb()) != RTIND)
165 qerr();
166 } else {
167 unget(c);
168 }
169 }
170 return (esp->e_mode);
171 }
172
173 /*
174 * Enter admode() to search a specific addressing mode table
175 * for a match. Return the addressing value on a match or
176 * zero for no match.
177 */
178 int
admode(sp)179 admode(sp)
180 struct adsym *sp;
181 {
182 char *ptr;
183 int i;
184 char *ips;
185
186 ips = ip;
187 unget(getnb());
188
189 i = 0;
190 while ( *(ptr = &sp[i].a_str[0]) ) {
191 if (srch(ptr)) {
192 return(sp[i].a_val);
193 }
194 i++;
195 }
196 ip = ips;
197 return(0);
198 }
199
200 /*
201 * srch --- does string match ?
202 */
203 int
srch(str)204 srch(str)
205 char *str;
206 {
207 char *ptr;
208 ptr = ip;
209
210 while (*ptr && *str) {
211 if (ccase[*ptr & 0x007F] != ccase[*str & 0x007F])
212 break;
213 ptr++;
214 str++;
215 }
216 if (ccase[*ptr & 0x007F] == ccase[*str & 0x007F]) {
217 ip = ptr;
218 return(1);
219 }
220
221 if (!*str) {
222 if (!(ctype[*ptr & 0x007F] & LTR16)) {
223 ip = ptr;
224 return(1);
225 }
226 }
227 return(0);
228 }
229
230 /*
231 * Registers
232 */
233
234 struct adsym R8[] = {
235 { "b", B|0400 },
236 { "c", C|0400 },
237 { "d", D|0400 },
238 { "e", E|0400 },
239 { "h", H|0400 },
240 { "l", L|0400 },
241 { "a", A|0400 },
242 { "", 0000 }
243 };
244
245 struct adsym R8X[] = {
246 { "eir", EIR|0400},
247 { "iir", IIR|0400},
248 { "", 0000 }
249 };
250
251 struct adsym R8IP[] = {
252 { "ip", IP|0400 },
253 { "", 0000 }
254 };
255
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 }
264 };
265
266 struct adsym R16X[] = {
267 { "af'", AF|0400 }, /* af' must be first !!! */
268 { "af", AF|0400 },
269 { "", 0000 }
270 };
271
272 struct adsym R32_BCDE[] = {
273 { "bcde", BCDE|0400 },
274 { "", 0000 }
275 };
276
277 struct adsym R32_JKHL[] = {
278 { "jkhl", JKHL|0400 },
279 { "", 0000 }
280 };
281
282 struct adsym RXPC[] = {
283 { "xpc", 1|0400 },
284 { "", 0000 }
285 };
286
287 /*
288 * Conditional definitions
289 */
290
291 struct adsym CND[] = {
292 { "NZ", NZ|0400 },
293 { "Z", Z |0400 },
294 { "NC", NC|0400 },
295 { "C", CS|0400 },
296 { "LZ", PO|0400 },
297 { "LO", PE|0400 },
298 { "P", P |0400 },
299 { "M", M |0400 },
300 { "", 0000 }
301 };
302
303 struct adsym ALT_CND[] = {
304 { "GT", CC_GT|0400 },
305 { "GTU", CC_GTU|0400 },
306 { "LT", CC_LT|0400 },
307 { "V", CC_V |0400 },
308 { "NZ", CC_NZ|0400 },
309 { "Z", CC_Z |0400 },
310 { "NC", CC_NC|0400 },
311 { "C", CC_C |0400 },
312 { "", 0000 }
313 };
314