tc-z80.c revision 1.7 1 1.7 christos /* tc-z80.c -- Assemble code for the Zilog Z80, Z180, EZ80 and ASCII R800
2 1.7 christos Copyright (C) 2005-2020 Free Software Foundation, Inc.
3 1.1 christos Contributed by Arnold Metselaar <arnold_m (at) operamail.com>
4 1.1 christos
5 1.1 christos This file is part of GAS, the GNU Assembler.
6 1.1 christos
7 1.1 christos GAS is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3, or (at your option)
10 1.1 christos any later version.
11 1.1 christos
12 1.1 christos GAS is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with GAS; see the file COPYING. If not, write to the Free
19 1.1 christos Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20 1.1 christos 02110-1301, USA. */
21 1.1 christos
22 1.1 christos #include "as.h"
23 1.1 christos #include "safe-ctype.h"
24 1.1 christos #include "subsegs.h"
25 1.7 christos #include "elf/z80.h"
26 1.7 christos #include "dwarf2dbg.h"
27 1.1 christos
28 1.1 christos /* Exported constants. */
29 1.1 christos const char comment_chars[] = ";\0";
30 1.1 christos const char line_comment_chars[] = "#;\0";
31 1.1 christos const char line_separator_chars[] = "\0";
32 1.1 christos const char EXP_CHARS[] = "eE\0";
33 1.7 christos const char FLT_CHARS[] = "RrDdFfSsHh\0";
34 1.1 christos
35 1.1 christos /* For machine specific options. */
36 1.1 christos const char * md_shortopts = ""; /* None yet. */
37 1.1 christos
38 1.1 christos enum options
39 1.1 christos {
40 1.1 christos OPTION_MACH_Z80 = OPTION_MD_BASE,
41 1.1 christos OPTION_MACH_R800,
42 1.7 christos OPTION_MACH_Z180,
43 1.7 christos OPTION_MACH_EZ80_Z80,
44 1.7 christos OPTION_MACH_EZ80_ADL,
45 1.7 christos OPTION_MACH_GBZ80,
46 1.7 christos OPTION_MACH_INST,
47 1.7 christos OPTION_MACH_NO_INST,
48 1.1 christos OPTION_MACH_IUD,
49 1.1 christos OPTION_MACH_WUD,
50 1.1 christos OPTION_MACH_FUD,
51 1.1 christos OPTION_MACH_IUP,
52 1.1 christos OPTION_MACH_WUP,
53 1.7 christos OPTION_MACH_FUP,
54 1.7 christos OPTION_FP_SINGLE_FORMAT,
55 1.7 christos OPTION_FP_DOUBLE_FORMAT,
56 1.7 christos OPTION_COMPAT_LL_PREFIX,
57 1.7 christos OPTION_COMPAT_COLONLESS,
58 1.7 christos OPTION_COMPAT_SDCC
59 1.1 christos };
60 1.1 christos
61 1.7 christos #define INS_Z80 (1 << 0)
62 1.7 christos #define INS_R800 (1 << 1)
63 1.7 christos #define INS_GBZ80 (1 << 2)
64 1.7 christos #define INS_Z180 (1 << 3)
65 1.7 christos #define INS_EZ80 (1 << 4)
66 1.7 christos #define INS_MARCH_MASK 0xffff
67 1.7 christos
68 1.7 christos #define INS_IDX_HALF (1 << 16)
69 1.7 christos #define INS_IN_F_C (1 << 17)
70 1.7 christos #define INS_OUT_C_0 (1 << 18)
71 1.7 christos #define INS_SLI (1 << 19)
72 1.7 christos #define INS_ROT_II_LD (1 << 20) /* instructions like SLA (ii+d),r; which is: LD r,(ii+d); SLA r; LD (ii+d),r */
73 1.7 christos #define INS_TUNE_MASK 0xffff0000
74 1.7 christos
75 1.7 christos #define INS_NOT_GBZ80 (INS_Z80 | INS_Z180 | INS_R800 | INS_EZ80)
76 1.7 christos
77 1.7 christos #define INS_ALL 0
78 1.7 christos #define INS_UNDOC (INS_IDX_HALF | INS_IN_F_C)
79 1.7 christos #define INS_UNPORT (INS_OUT_C_0 | INS_SLI | INS_ROT_II_LD)
80 1.1 christos
81 1.1 christos struct option md_longopts[] =
82 1.1 christos {
83 1.1 christos { "z80", no_argument, NULL, OPTION_MACH_Z80},
84 1.1 christos { "r800", no_argument, NULL, OPTION_MACH_R800},
85 1.7 christos { "z180", no_argument, NULL, OPTION_MACH_Z180},
86 1.7 christos { "ez80", no_argument, NULL, OPTION_MACH_EZ80_Z80},
87 1.7 christos { "ez80-adl", no_argument, NULL, OPTION_MACH_EZ80_ADL},
88 1.7 christos { "fp-s", required_argument, NULL, OPTION_FP_SINGLE_FORMAT},
89 1.7 christos { "fp-d", required_argument, NULL, OPTION_FP_DOUBLE_FORMAT},
90 1.7 christos { "strict", no_argument, NULL, OPTION_MACH_FUD},
91 1.7 christos { "full", no_argument, NULL, OPTION_MACH_IUP},
92 1.7 christos { "with-inst", required_argument, NULL, OPTION_MACH_INST},
93 1.7 christos { "Wnins", required_argument, NULL, OPTION_MACH_INST},
94 1.7 christos { "without-inst", required_argument, NULL, OPTION_MACH_NO_INST},
95 1.7 christos { "local-prefix", required_argument, NULL, OPTION_COMPAT_LL_PREFIX},
96 1.7 christos { "colonless", no_argument, NULL, OPTION_COMPAT_COLONLESS},
97 1.7 christos { "sdcc", no_argument, NULL, OPTION_COMPAT_SDCC},
98 1.7 christos { "Fins", required_argument, NULL, OPTION_MACH_NO_INST},
99 1.1 christos { "ignore-undocumented-instructions", no_argument, NULL, OPTION_MACH_IUD },
100 1.1 christos { "Wnud", no_argument, NULL, OPTION_MACH_IUD },
101 1.1 christos { "warn-undocumented-instructions", no_argument, NULL, OPTION_MACH_WUD },
102 1.1 christos { "Wud", no_argument, NULL, OPTION_MACH_WUD },
103 1.1 christos { "forbid-undocumented-instructions", no_argument, NULL, OPTION_MACH_FUD },
104 1.1 christos { "Fud", no_argument, NULL, OPTION_MACH_FUD },
105 1.1 christos { "ignore-unportable-instructions", no_argument, NULL, OPTION_MACH_IUP },
106 1.1 christos { "Wnup", no_argument, NULL, OPTION_MACH_IUP },
107 1.1 christos { "warn-unportable-instructions", no_argument, NULL, OPTION_MACH_WUP },
108 1.1 christos { "Wup", no_argument, NULL, OPTION_MACH_WUP },
109 1.1 christos { "forbid-unportable-instructions", no_argument, NULL, OPTION_MACH_FUP },
110 1.1 christos { "Fup", no_argument, NULL, OPTION_MACH_FUP },
111 1.1 christos
112 1.1 christos { NULL, no_argument, NULL, 0 }
113 1.1 christos } ;
114 1.1 christos
115 1.1 christos size_t md_longopts_size = sizeof (md_longopts);
116 1.1 christos
117 1.1 christos extern int coff_flags;
118 1.1 christos /* Instruction classes that silently assembled. */
119 1.1 christos static int ins_ok = INS_Z80 | INS_UNDOC;
120 1.1 christos /* Instruction classes that generate errors. */
121 1.7 christos static int ins_err = ~(INS_Z80 | INS_UNDOC);
122 1.7 christos /* eZ80 CPU mode (ADL or Z80) */
123 1.7 christos static int cpu_mode = 0; /* 0 - Z80, 1 - ADL */
124 1.7 christos /* accept SDCC specific instruction encoding */
125 1.7 christos static int sdcc_compat = 0;
126 1.7 christos /* accept colonless labels */
127 1.7 christos static int colonless_labels = 0;
128 1.7 christos /* local label prefix (NULL - default) */
129 1.7 christos static const char *local_label_prefix = NULL;
130 1.7 christos /* floating point support */
131 1.7 christos typedef const char *(*str_to_float_t)(char *litP, int *sizeP);
132 1.7 christos static str_to_float_t str_to_float;
133 1.7 christos static str_to_float_t str_to_double;
134 1.7 christos
135 1.7 christos /* mode of current instruction */
136 1.7 christos #define INST_MODE_S 0 /* short data mode */
137 1.7 christos #define INST_MODE_IS 0 /* short instruction mode */
138 1.7 christos #define INST_MODE_L 2 /* long data mode */
139 1.7 christos #define INST_MODE_IL 1 /* long instruction mode */
140 1.7 christos #define INST_MODE_FORCED 4 /* CPU mode changed by instruction suffix*/
141 1.7 christos static char inst_mode;
142 1.7 christos
143 1.7 christos static int
144 1.7 christos setup_instruction (const char *inst, int *add, int *sub)
145 1.7 christos {
146 1.7 christos int n;
147 1.7 christos if (!strcmp (inst, "idx-reg-halves"))
148 1.7 christos n = INS_IDX_HALF;
149 1.7 christos else if (!strcmp (inst, "sli"))
150 1.7 christos n = INS_SLI;
151 1.7 christos else if (!strcmp (inst, "op-ii-ld"))
152 1.7 christos n = INS_ROT_II_LD;
153 1.7 christos else if (!strcmp (inst, "in-f-c"))
154 1.7 christos n = INS_IN_F_C;
155 1.7 christos else if (!strcmp (inst, "out-c-0"))
156 1.7 christos n = INS_OUT_C_0;
157 1.7 christos else
158 1.7 christos return 0;
159 1.7 christos *add |= n;
160 1.7 christos *sub &= ~n;
161 1.7 christos return 1;
162 1.7 christos }
163 1.7 christos
164 1.7 christos static const char *
165 1.7 christos str_to_zeda32 (char *litP, int *sizeP);
166 1.7 christos static const char *
167 1.7 christos str_to_float48 (char *litP, int *sizeP);
168 1.7 christos static const char *
169 1.7 christos str_to_ieee754_h (char *litP, int *sizeP);
170 1.7 christos static const char *
171 1.7 christos str_to_ieee754_s (char *litP, int *sizeP);
172 1.7 christos static const char *
173 1.7 christos str_to_ieee754_d (char *litP, int *sizeP);
174 1.7 christos
175 1.7 christos static str_to_float_t
176 1.7 christos get_str_to_float (const char *arg)
177 1.7 christos {
178 1.7 christos if (strcasecmp (arg, "zeda32") == 0)
179 1.7 christos return str_to_zeda32;
180 1.7 christos
181 1.7 christos if (strcasecmp (arg, "math48") == 0)
182 1.7 christos return str_to_float48;
183 1.7 christos
184 1.7 christos if (strcasecmp (arg, "half") != 0)
185 1.7 christos return str_to_ieee754_h;
186 1.7 christos
187 1.7 christos if (strcasecmp (arg, "single") != 0)
188 1.7 christos return str_to_ieee754_s;
189 1.7 christos
190 1.7 christos if (strcasecmp (arg, "double") != 0)
191 1.7 christos return str_to_ieee754_d;
192 1.7 christos
193 1.7 christos if (strcasecmp (arg, "ieee754") == 0)
194 1.7 christos as_fatal (_("invalid floating point numbers type `%s'"), arg);
195 1.7 christos return NULL;
196 1.7 christos }
197 1.7 christos
198 1.7 christos static int
199 1.7 christos setup_instruction_list (const char *list, int *add, int *sub)
200 1.7 christos {
201 1.7 christos char buf[16];
202 1.7 christos const char *b;
203 1.7 christos const char *e;
204 1.7 christos int sz;
205 1.7 christos int res = 0;
206 1.7 christos for (b = list; *b != '\0';)
207 1.7 christos {
208 1.7 christos e = strchr (b, ',');
209 1.7 christos if (e == NULL)
210 1.7 christos sz = strlen (b);
211 1.7 christos else
212 1.7 christos sz = e - b;
213 1.7 christos if (sz == 0 || sz >= (int)sizeof (buf))
214 1.7 christos {
215 1.7 christos as_bad (_("invalid INST in command line: %s"), b);
216 1.7 christos return 0;
217 1.7 christos }
218 1.7 christos memcpy (buf, b, sz);
219 1.7 christos buf[sz] = '\0';
220 1.7 christos if (setup_instruction (buf, add, sub))
221 1.7 christos res++;
222 1.7 christos else
223 1.7 christos {
224 1.7 christos as_bad (_("invalid INST in command line: %s"), buf);
225 1.7 christos return 0;
226 1.7 christos }
227 1.7 christos b = &b[sz];
228 1.7 christos if (*b == ',')
229 1.7 christos ++b;
230 1.7 christos }
231 1.7 christos return res;
232 1.7 christos }
233 1.1 christos
234 1.1 christos int
235 1.7 christos md_parse_option (int c, const char* arg)
236 1.1 christos {
237 1.1 christos switch (c)
238 1.1 christos {
239 1.1 christos default:
240 1.1 christos return 0;
241 1.1 christos case OPTION_MACH_Z80:
242 1.7 christos ins_ok = (ins_ok & INS_TUNE_MASK) | INS_Z80;
243 1.7 christos ins_err = (ins_err & INS_MARCH_MASK) | (~INS_Z80 & INS_MARCH_MASK);
244 1.1 christos break;
245 1.1 christos case OPTION_MACH_R800:
246 1.7 christos ins_ok = INS_R800 | INS_IDX_HALF;
247 1.1 christos ins_err = INS_UNPORT;
248 1.1 christos break;
249 1.7 christos case OPTION_MACH_Z180:
250 1.7 christos ins_ok = INS_Z180;
251 1.7 christos ins_err = INS_UNDOC | INS_UNPORT;
252 1.7 christos break;
253 1.7 christos case OPTION_MACH_EZ80_Z80:
254 1.7 christos ins_ok = INS_EZ80;
255 1.7 christos ins_err = (INS_UNDOC | INS_UNPORT) & ~INS_IDX_HALF;
256 1.7 christos cpu_mode = 0;
257 1.7 christos break;
258 1.7 christos case OPTION_MACH_EZ80_ADL:
259 1.7 christos ins_ok = INS_EZ80;
260 1.7 christos ins_err = (INS_UNDOC | INS_UNPORT) & ~INS_IDX_HALF;
261 1.7 christos cpu_mode = 1;
262 1.7 christos break;
263 1.7 christos case OPTION_MACH_GBZ80:
264 1.7 christos ins_ok = INS_GBZ80;
265 1.7 christos ins_err = INS_UNDOC | INS_UNPORT;
266 1.7 christos break;
267 1.7 christos case OPTION_FP_SINGLE_FORMAT:
268 1.7 christos str_to_float = get_str_to_float (arg);
269 1.7 christos break;
270 1.7 christos case OPTION_FP_DOUBLE_FORMAT:
271 1.7 christos str_to_double = get_str_to_float (arg);
272 1.7 christos break;
273 1.7 christos case OPTION_MACH_INST:
274 1.7 christos if ((ins_ok & INS_GBZ80) == 0)
275 1.7 christos return setup_instruction_list (arg, & ins_ok, & ins_err);
276 1.7 christos break;
277 1.7 christos case OPTION_MACH_NO_INST:
278 1.7 christos if ((ins_ok & INS_GBZ80) == 0)
279 1.7 christos return setup_instruction_list (arg, & ins_err, & ins_ok);
280 1.1 christos break;
281 1.1 christos case OPTION_MACH_WUD:
282 1.7 christos case OPTION_MACH_IUD:
283 1.7 christos if ((ins_ok & INS_GBZ80) == 0)
284 1.7 christos {
285 1.7 christos ins_ok |= INS_UNDOC;
286 1.7 christos ins_err &= ~INS_UNDOC;
287 1.7 christos }
288 1.1 christos break;
289 1.1 christos case OPTION_MACH_WUP:
290 1.7 christos case OPTION_MACH_IUP:
291 1.7 christos if ((ins_ok & INS_GBZ80) == 0)
292 1.7 christos {
293 1.7 christos ins_ok |= INS_UNDOC | INS_UNPORT;
294 1.7 christos ins_err &= ~(INS_UNDOC | INS_UNPORT);
295 1.7 christos }
296 1.1 christos break;
297 1.1 christos case OPTION_MACH_FUD:
298 1.7 christos if ((ins_ok & (INS_R800 | INS_GBZ80)) == 0)
299 1.1 christos {
300 1.1 christos ins_ok &= (INS_UNDOC | INS_UNPORT);
301 1.1 christos ins_err |= INS_UNDOC | INS_UNPORT;
302 1.1 christos }
303 1.1 christos break;
304 1.1 christos case OPTION_MACH_FUP:
305 1.1 christos ins_ok &= ~INS_UNPORT;
306 1.1 christos ins_err |= INS_UNPORT;
307 1.1 christos break;
308 1.7 christos case OPTION_COMPAT_LL_PREFIX:
309 1.7 christos local_label_prefix = (arg && *arg) ? arg : NULL;
310 1.7 christos break;
311 1.7 christos case OPTION_COMPAT_SDCC:
312 1.7 christos sdcc_compat = 1;
313 1.7 christos local_label_prefix = "_";
314 1.7 christos break;
315 1.7 christos case OPTION_COMPAT_COLONLESS:
316 1.7 christos colonless_labels = 1;
317 1.7 christos break;
318 1.1 christos }
319 1.1 christos
320 1.1 christos return 1;
321 1.1 christos }
322 1.1 christos
323 1.1 christos void
324 1.1 christos md_show_usage (FILE * f)
325 1.1 christos {
326 1.1 christos fprintf (f, "\n\
327 1.7 christos CPU model options:\n\
328 1.7 christos -z80\t\t\t assemble for Z80\n\
329 1.7 christos -r800\t\t\t assemble for R800\n\
330 1.7 christos -z180\t\t\t assemble for Z180\n\
331 1.7 christos -ez80\t\t\t assemble for eZ80 in Z80 mode by default\n\
332 1.7 christos -ez80-adl\t\t assemble for eZ80 in ADL mode by default\n\
333 1.7 christos \n\
334 1.7 christos Compatibility options:\n\
335 1.7 christos -local-prefix=TEXT\t treat labels prefixed by TEXT as local\n\
336 1.7 christos -colonless\t\t permit colonless labels\n\
337 1.7 christos -sdcc\t\t\t accept SDCC specific instruction syntax\n\
338 1.7 christos -fp-s=FORMAT\t\t set single precission FP numbers format\n\
339 1.7 christos -fp-d=FORMAT\t\t set double precission FP numbers format\n\
340 1.7 christos Where FORMAT one of:\n\
341 1.7 christos ieee754\t\t IEEE754 compatible\n\
342 1.7 christos half\t\t\t IEEE754 half precision (16 bit)\n\
343 1.7 christos single\t\t IEEE754 single precision (32 bit)\n\
344 1.7 christos double\t\t IEEE754 double precision (64 bit)\n\
345 1.7 christos zeda32\t\t Zeda z80float library 32 bit format\n\
346 1.7 christos math48\t\t 48 bit format from Math48 library\n\
347 1.1 christos \n\
348 1.7 christos Support for known undocumented instructions:\n\
349 1.7 christos -strict\t\t assemble only documented instructions\n\
350 1.7 christos -full\t\t\t assemble all undocumented instructions\n\
351 1.7 christos -with-inst=INST[,...]\n\
352 1.7 christos -Wnins INST[,...]\t assemble specified instruction(s)\n\
353 1.7 christos -without-inst=INST[,...]\n\
354 1.7 christos -Fins INST[,...]\t do not assemble specified instruction(s)\n\
355 1.7 christos Where INST is one of:\n\
356 1.7 christos idx-reg-halves\t instructions with halves of index registers\n\
357 1.7 christos sli\t\t\t instruction SLI/SLL\n\
358 1.7 christos op-ii-ld\t\t instructions like SLA (II+dd),R (opcodes DD/FD CB dd xx)\n\
359 1.7 christos in-f-c\t\t instruction IN F,(C)\n\
360 1.7 christos out-c-0\t\t instruction OUT (C),0\n\
361 1.7 christos \n\
362 1.7 christos Obsolete options:\n\
363 1.1 christos -ignore-undocumented-instructions\n\
364 1.7 christos -Wnud\t\t\t silently assemble undocumented Z80-instructions that work on R800\n\
365 1.1 christos -ignore-unportable-instructions\n\
366 1.7 christos -Wnup\t\t\t silently assemble all undocumented Z80-instructions\n\
367 1.1 christos -warn-undocumented-instructions\n\
368 1.7 christos -Wud\t\t\t issue warnings for undocumented Z80-instructions that work on R800\n\
369 1.1 christos -warn-unportable-instructions\n\
370 1.7 christos -Wup\t\t\t issue warnings for other undocumented Z80-instructions\n\
371 1.1 christos -forbid-undocumented-instructions\n\
372 1.7 christos -Fud\t\t\t treat all undocumented Z80-instructions as errors\n\
373 1.1 christos -forbid-unportable-instructions\n\
374 1.7 christos -Fup\t\t\t treat undocumented Z80-instructions that do not work on R800 as errors\n\
375 1.7 christos \n\
376 1.6 christos Default: -z80 -ignore-undocumented-instructions -warn-unportable-instructions.\n");
377 1.1 christos }
378 1.1 christos
379 1.1 christos static symbolS * zero;
380 1.1 christos
381 1.1 christos struct reg_entry
382 1.1 christos {
383 1.5 christos const char* name;
384 1.1 christos int number;
385 1.1 christos };
386 1.1 christos #define R_STACKABLE (0x80)
387 1.1 christos #define R_ARITH (0x40)
388 1.1 christos #define R_IX (0x20)
389 1.1 christos #define R_IY (0x10)
390 1.1 christos #define R_INDEX (R_IX | R_IY)
391 1.1 christos
392 1.1 christos #define REG_A (7)
393 1.1 christos #define REG_B (0)
394 1.1 christos #define REG_C (1)
395 1.1 christos #define REG_D (2)
396 1.1 christos #define REG_E (3)
397 1.1 christos #define REG_H (4)
398 1.1 christos #define REG_L (5)
399 1.1 christos #define REG_F (6 | 8)
400 1.1 christos #define REG_I (9)
401 1.1 christos #define REG_R (10)
402 1.7 christos #define REG_MB (11)
403 1.1 christos
404 1.1 christos #define REG_AF (3 | R_STACKABLE)
405 1.1 christos #define REG_BC (0 | R_STACKABLE | R_ARITH)
406 1.1 christos #define REG_DE (1 | R_STACKABLE | R_ARITH)
407 1.1 christos #define REG_HL (2 | R_STACKABLE | R_ARITH)
408 1.1 christos #define REG_IX (REG_HL | R_IX)
409 1.1 christos #define REG_IY (REG_HL | R_IY)
410 1.1 christos #define REG_SP (3 | R_ARITH)
411 1.1 christos
412 1.1 christos static const struct reg_entry regtable[] =
413 1.1 christos {
414 1.1 christos {"a", REG_A },
415 1.1 christos {"af", REG_AF },
416 1.1 christos {"b", REG_B },
417 1.1 christos {"bc", REG_BC },
418 1.1 christos {"c", REG_C },
419 1.1 christos {"d", REG_D },
420 1.1 christos {"de", REG_DE },
421 1.1 christos {"e", REG_E },
422 1.1 christos {"f", REG_F },
423 1.1 christos {"h", REG_H },
424 1.1 christos {"hl", REG_HL },
425 1.1 christos {"i", REG_I },
426 1.1 christos {"ix", REG_IX },
427 1.1 christos {"ixh",REG_H | R_IX },
428 1.1 christos {"ixl",REG_L | R_IX },
429 1.1 christos {"iy", REG_IY },
430 1.1 christos {"iyh",REG_H | R_IY },
431 1.1 christos {"iyl",REG_L | R_IY },
432 1.1 christos {"l", REG_L },
433 1.7 christos {"mb", REG_MB },
434 1.1 christos {"r", REG_R },
435 1.1 christos {"sp", REG_SP },
436 1.1 christos } ;
437 1.1 christos
438 1.1 christos #define BUFLEN 8 /* Large enough for any keyword. */
439 1.1 christos
440 1.1 christos void
441 1.1 christos md_begin (void)
442 1.1 christos {
443 1.1 christos expressionS nul, reg;
444 1.1 christos char * p;
445 1.1 christos unsigned int i, j, k;
446 1.1 christos char buf[BUFLEN];
447 1.1 christos
448 1.7 christos if (ins_ok & INS_EZ80) /* if select EZ80 cpu then */
449 1.7 christos listing_lhs_width = 6; /* use 6 bytes per line in the listing */
450 1.7 christos
451 1.1 christos reg.X_op = O_register;
452 1.1 christos reg.X_md = 0;
453 1.1 christos reg.X_add_symbol = reg.X_op_symbol = 0;
454 1.1 christos for ( i = 0 ; i < ARRAY_SIZE ( regtable ) ; ++i )
455 1.1 christos {
456 1.1 christos reg.X_add_number = regtable[i].number;
457 1.1 christos k = strlen ( regtable[i].name );
458 1.1 christos buf[k] = 0;
459 1.1 christos if ( k+1 < BUFLEN )
460 1.1 christos {
461 1.1 christos for ( j = ( 1<<k ) ; j ; --j )
462 1.1 christos {
463 1.1 christos for ( k = 0 ; regtable[i].name[k] ; ++k )
464 1.1 christos {
465 1.7 christos buf[k] = ( j & ( 1<<k ) ) ? TOUPPER (regtable[i].name[k]) : regtable[i].name[k];
466 1.1 christos }
467 1.7 christos symbolS * psym = symbol_find_or_make (buf);
468 1.7 christos S_SET_SEGMENT (psym, reg_section);
469 1.7 christos symbol_set_value_expression (psym, ®);
470 1.1 christos }
471 1.1 christos }
472 1.1 christos }
473 1.1 christos p = input_line_pointer;
474 1.5 christos input_line_pointer = (char *) "0";
475 1.1 christos nul.X_md=0;
476 1.1 christos expression (& nul);
477 1.1 christos input_line_pointer = p;
478 1.1 christos zero = make_expr_symbol (& nul);
479 1.1 christos /* We do not use relaxation (yet). */
480 1.1 christos linkrelax = 0;
481 1.1 christos }
482 1.1 christos
483 1.1 christos void
484 1.1 christos z80_md_end (void)
485 1.1 christos {
486 1.1 christos int mach_type;
487 1.1 christos
488 1.7 christos switch (ins_ok & INS_MARCH_MASK)
489 1.1 christos {
490 1.1 christos case INS_Z80:
491 1.7 christos if (ins_ok & INS_UNPORT)
492 1.7 christos mach_type = bfd_mach_z80full;
493 1.7 christos else if (ins_ok & INS_UNDOC)
494 1.7 christos mach_type = bfd_mach_z80;
495 1.7 christos else
496 1.7 christos mach_type = bfd_mach_z80strict;
497 1.7 christos break;
498 1.7 christos case INS_R800:
499 1.7 christos mach_type = bfd_mach_r800;
500 1.1 christos break;
501 1.7 christos case INS_Z180:
502 1.7 christos mach_type = bfd_mach_z180;
503 1.1 christos break;
504 1.7 christos case INS_GBZ80:
505 1.7 christos mach_type = bfd_mach_gbz80;
506 1.1 christos break;
507 1.7 christos case INS_EZ80:
508 1.7 christos mach_type = cpu_mode ? bfd_mach_ez80_adl : bfd_mach_ez80_z80;
509 1.1 christos break;
510 1.1 christos default:
511 1.1 christos mach_type = 0;
512 1.1 christos }
513 1.1 christos
514 1.1 christos bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach_type);
515 1.1 christos }
516 1.1 christos
517 1.7 christos #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
518 1.7 christos void
519 1.7 christos z80_elf_final_processing (void)
520 1.7 christos {
521 1.7 christos unsigned elf_flags;
522 1.7 christos switch (ins_ok & INS_MARCH_MASK)
523 1.7 christos {
524 1.7 christos case INS_Z80:
525 1.7 christos elf_flags = EF_Z80_MACH_Z80;
526 1.7 christos break;
527 1.7 christos case INS_R800:
528 1.7 christos elf_flags = EF_Z80_MACH_R800;
529 1.7 christos break;
530 1.7 christos case INS_Z180:
531 1.7 christos elf_flags = EF_Z80_MACH_Z180;
532 1.7 christos break;
533 1.7 christos case INS_GBZ80:
534 1.7 christos elf_flags = EF_Z80_MACH_GBZ80;
535 1.7 christos break;
536 1.7 christos case INS_EZ80:
537 1.7 christos elf_flags = cpu_mode ? EF_Z80_MACH_EZ80_ADL : EF_Z80_MACH_EZ80_Z80;
538 1.7 christos break;
539 1.7 christos default:
540 1.7 christos elf_flags = 0;
541 1.7 christos }
542 1.7 christos
543 1.7 christos elf_elfheader (stdoutput)->e_flags = elf_flags;
544 1.7 christos }
545 1.7 christos #endif
546 1.7 christos
547 1.1 christos static const char *
548 1.1 christos skip_space (const char *s)
549 1.1 christos {
550 1.1 christos while (*s == ' ' || *s == '\t')
551 1.1 christos ++s;
552 1.1 christos return s;
553 1.1 christos }
554 1.1 christos
555 1.1 christos /* A non-zero return-value causes a continue in the
556 1.1 christos function read_a_source_file () in ../read.c. */
557 1.1 christos int
558 1.1 christos z80_start_line_hook (void)
559 1.1 christos {
560 1.1 christos char *p, quote;
561 1.1 christos char buf[4];
562 1.1 christos
563 1.1 christos /* Convert one character constants. */
564 1.1 christos for (p = input_line_pointer; *p && *p != '\n'; ++p)
565 1.1 christos {
566 1.1 christos switch (*p)
567 1.1 christos {
568 1.1 christos case '\'':
569 1.1 christos if (p[1] != 0 && p[1] != '\'' && p[2] == '\'')
570 1.1 christos {
571 1.1 christos snprintf (buf, 4, "%3d", (unsigned char)p[1]);
572 1.1 christos *p++ = buf[0];
573 1.1 christos *p++ = buf[1];
574 1.1 christos *p++ = buf[2];
575 1.1 christos break;
576 1.1 christos }
577 1.6 christos /* Fall through. */
578 1.1 christos case '"':
579 1.1 christos for (quote = *p++; quote != *p && '\n' != *p; ++p)
580 1.1 christos /* No escapes. */ ;
581 1.1 christos if (quote != *p)
582 1.1 christos {
583 1.1 christos as_bad (_("-- unterminated string"));
584 1.1 christos ignore_rest_of_line ();
585 1.1 christos return 1;
586 1.1 christos }
587 1.1 christos break;
588 1.7 christos case '#':
589 1.7 christos if (sdcc_compat)
590 1.7 christos *p = (*skip_space (p + 1) == '(') ? '+' : ' ';
591 1.7 christos break;
592 1.1 christos }
593 1.1 christos }
594 1.1 christos /* Check for <label>[:] [.](EQU|DEFL) <value>. */
595 1.1 christos if (is_name_beginner (*input_line_pointer))
596 1.1 christos {
597 1.3 christos char *name;
598 1.1 christos char c, *rest, *line_start;
599 1.1 christos int len;
600 1.1 christos
601 1.1 christos line_start = input_line_pointer;
602 1.1 christos if (ignore_input ())
603 1.1 christos return 0;
604 1.1 christos
605 1.3 christos c = get_symbol_name (&name);
606 1.1 christos rest = input_line_pointer + 1;
607 1.1 christos
608 1.7 christos if (ISSPACE (c) && colonless_labels)
609 1.7 christos {
610 1.7 christos if (c == '\n')
611 1.7 christos {
612 1.7 christos bump_line_counters ();
613 1.7 christos LISTING_NEWLINE ();
614 1.7 christos }
615 1.7 christos c = ':';
616 1.7 christos }
617 1.7 christos if (c == ':' && sdcc_compat && rest[-2] != '$')
618 1.7 christos dollar_label_clear ();
619 1.1 christos if (*rest == ':')
620 1.7 christos {
621 1.7 christos /* remove second colon if SDCC compatibility enabled */
622 1.7 christos if (sdcc_compat)
623 1.7 christos *rest = ' ';
624 1.7 christos ++rest;
625 1.7 christos }
626 1.7 christos rest = (char*)skip_space (rest);
627 1.1 christos if (*rest == '.')
628 1.1 christos ++rest;
629 1.1 christos if (strncasecmp (rest, "EQU", 3) == 0)
630 1.1 christos len = 3;
631 1.1 christos else if (strncasecmp (rest, "DEFL", 4) == 0)
632 1.1 christos len = 4;
633 1.1 christos else
634 1.1 christos len = 0;
635 1.7 christos if (len && (!ISALPHA (rest[len])))
636 1.1 christos {
637 1.1 christos /* Handle assignment here. */
638 1.1 christos if (line_start[-1] == '\n')
639 1.1 christos {
640 1.1 christos bump_line_counters ();
641 1.1 christos LISTING_NEWLINE ();
642 1.1 christos }
643 1.1 christos input_line_pointer = rest + len - 1;
644 1.1 christos /* Allow redefining with "DEFL" (len == 4), but not with "EQU". */
645 1.3 christos equals (name, len == 4);
646 1.1 christos return 1;
647 1.1 christos }
648 1.1 christos else
649 1.1 christos {
650 1.1 christos /* Restore line and pointer. */
651 1.3 christos (void) restore_line_pointer (c);
652 1.1 christos input_line_pointer = line_start;
653 1.1 christos }
654 1.1 christos }
655 1.1 christos return 0;
656 1.1 christos }
657 1.1 christos
658 1.1 christos symbolS *
659 1.1 christos md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
660 1.1 christos {
661 1.1 christos return NULL;
662 1.1 christos }
663 1.1 christos
664 1.5 christos const char *
665 1.7 christos md_atof (int type, char *litP, int *sizeP)
666 1.1 christos {
667 1.7 christos switch (type)
668 1.7 christos {
669 1.7 christos case 'f':
670 1.7 christos case 'F':
671 1.7 christos case 's':
672 1.7 christos case 'S':
673 1.7 christos if (str_to_float)
674 1.7 christos return str_to_float (litP, sizeP);
675 1.7 christos break;
676 1.7 christos case 'd':
677 1.7 christos case 'D':
678 1.7 christos case 'r':
679 1.7 christos case 'R':
680 1.7 christos if (str_to_double)
681 1.7 christos return str_to_double (litP, sizeP);
682 1.7 christos break;
683 1.7 christos }
684 1.7 christos return ieee_md_atof (type, litP, sizeP, FALSE);
685 1.1 christos }
686 1.1 christos
687 1.1 christos valueT
688 1.1 christos md_section_align (segT seg ATTRIBUTE_UNUSED, valueT size)
689 1.1 christos {
690 1.1 christos return size;
691 1.1 christos }
692 1.1 christos
693 1.1 christos long
694 1.1 christos md_pcrel_from (fixS * fixp)
695 1.1 christos {
696 1.7 christos return fixp->fx_where + fixp->fx_frag->fr_address;
697 1.1 christos }
698 1.1 christos
699 1.1 christos typedef const char * (asfunc)(char, char, const char*);
700 1.1 christos
701 1.1 christos typedef struct _table_t
702 1.1 christos {
703 1.5 christos const char* name;
704 1.5 christos unsigned char prefix;
705 1.5 christos unsigned char opcode;
706 1.1 christos asfunc * fp;
707 1.7 christos unsigned inss; /*0 - all CPU types or list of supported INS_* */
708 1.1 christos } table_t;
709 1.1 christos
710 1.1 christos /* Compares the key for structs that start with a char * to the key. */
711 1.1 christos static int
712 1.1 christos key_cmp (const void * a, const void * b)
713 1.1 christos {
714 1.1 christos const char *str_a, *str_b;
715 1.1 christos
716 1.1 christos str_a = *((const char**)a);
717 1.1 christos str_b = *((const char**)b);
718 1.1 christos return strcmp (str_a, str_b);
719 1.1 christos }
720 1.1 christos
721 1.1 christos char buf[BUFLEN];
722 1.1 christos const char *key = buf;
723 1.1 christos
724 1.1 christos /* Prevent an error on a line from also generating
725 1.1 christos a "junk at end of line" error message. */
726 1.1 christos static char err_flag;
727 1.1 christos
728 1.1 christos static void
729 1.1 christos error (const char * message)
730 1.1 christos {
731 1.7 christos if (err_flag)
732 1.7 christos return;
733 1.7 christos
734 1.1 christos as_bad ("%s", message);
735 1.1 christos err_flag = 1;
736 1.1 christos }
737 1.1 christos
738 1.1 christos static void
739 1.1 christos ill_op (void)
740 1.1 christos {
741 1.1 christos error (_("illegal operand"));
742 1.1 christos }
743 1.1 christos
744 1.1 christos static void
745 1.1 christos wrong_mach (int ins_type)
746 1.1 christos {
747 1.1 christos if (ins_type & ins_err)
748 1.7 christos ill_op ();
749 1.1 christos else
750 1.7 christos as_warn (_("undocumented instruction"));
751 1.1 christos }
752 1.1 christos
753 1.1 christos static void
754 1.1 christos check_mach (int ins_type)
755 1.1 christos {
756 1.1 christos if ((ins_type & ins_ok) == 0)
757 1.1 christos wrong_mach (ins_type);
758 1.1 christos }
759 1.1 christos
760 1.1 christos /* Check whether an expression is indirect. */
761 1.1 christos static int
762 1.1 christos is_indir (const char *s)
763 1.1 christos {
764 1.1 christos char quote;
765 1.1 christos const char *p;
766 1.1 christos int indir, depth;
767 1.1 christos
768 1.1 christos /* Indirection is indicated with parentheses. */
769 1.1 christos indir = (*s == '(');
770 1.1 christos
771 1.1 christos for (p = s, depth = 0; *p && *p != ','; ++p)
772 1.1 christos {
773 1.1 christos switch (*p)
774 1.1 christos {
775 1.1 christos case '"':
776 1.1 christos case '\'':
777 1.1 christos for (quote = *p++; quote != *p && *p != '\n'; ++p)
778 1.1 christos if (*p == '\\' && p[1])
779 1.1 christos ++p;
780 1.1 christos break;
781 1.1 christos case '(':
782 1.1 christos ++ depth;
783 1.1 christos break;
784 1.1 christos case ')':
785 1.1 christos -- depth;
786 1.1 christos if (depth == 0)
787 1.1 christos {
788 1.1 christos p = skip_space (p + 1);
789 1.1 christos if (*p && *p != ',')
790 1.1 christos indir = 0;
791 1.1 christos --p;
792 1.1 christos }
793 1.1 christos if (depth < 0)
794 1.1 christos error (_("mismatched parentheses"));
795 1.1 christos break;
796 1.1 christos }
797 1.1 christos }
798 1.1 christos
799 1.1 christos if (depth != 0)
800 1.1 christos error (_("mismatched parentheses"));
801 1.1 christos
802 1.1 christos return indir;
803 1.1 christos }
804 1.1 christos
805 1.1 christos /* Check whether a symbol involves a register. */
806 1.3 christos static int
807 1.7 christos contains_register (symbolS *sym)
808 1.1 christos {
809 1.1 christos if (sym)
810 1.7 christos {
811 1.7 christos expressionS * ex = symbol_get_value_expression(sym);
812 1.7 christos
813 1.7 christos return (O_register == ex->X_op)
814 1.7 christos || (ex->X_add_symbol && contains_register(ex->X_add_symbol))
815 1.7 christos || (ex->X_op_symbol && contains_register(ex->X_op_symbol));
816 1.7 christos }
817 1.7 christos
818 1.7 christos return 0;
819 1.1 christos }
820 1.1 christos
821 1.6 christos /* Parse general expression, not looking for indexed addressing. */
822 1.1 christos static const char *
823 1.1 christos parse_exp_not_indexed (const char *s, expressionS *op)
824 1.1 christos {
825 1.1 christos const char *p;
826 1.1 christos int indir;
827 1.7 christos int make_shift = -1;
828 1.1 christos
829 1.1 christos p = skip_space (s);
830 1.7 christos if (sdcc_compat && (*p == '<' || *p == '>'))
831 1.7 christos {
832 1.7 christos switch (*p)
833 1.7 christos {
834 1.7 christos case '<': /* LSB request */
835 1.7 christos make_shift = 0;
836 1.7 christos break;
837 1.7 christos case '>': /* MSB request */
838 1.7 christos make_shift = cpu_mode ? 16 : 8;
839 1.7 christos break;
840 1.7 christos }
841 1.7 christos s = ++p;
842 1.7 christos p = skip_space (p);
843 1.7 christos }
844 1.7 christos
845 1.1 christos op->X_md = indir = is_indir (p);
846 1.1 christos input_line_pointer = (char*) s ;
847 1.3 christos expression (op);
848 1.1 christos switch (op->X_op)
849 1.1 christos {
850 1.1 christos case O_absent:
851 1.1 christos error (_("missing operand"));
852 1.1 christos break;
853 1.1 christos case O_illegal:
854 1.1 christos error (_("bad expression syntax"));
855 1.1 christos break;
856 1.3 christos default:
857 1.3 christos break;
858 1.1 christos }
859 1.7 christos
860 1.7 christos if (make_shift >= 0)
861 1.7 christos {
862 1.7 christos /* replace [op] by [op >> shift] */
863 1.7 christos expressionS data;
864 1.7 christos op->X_add_symbol = make_expr_symbol (op);
865 1.7 christos op->X_add_number = 0;
866 1.7 christos op->X_op = O_right_shift;
867 1.7 christos memset (&data, 0, sizeof (data));
868 1.7 christos data.X_op = O_constant;
869 1.7 christos data.X_add_number = make_shift;
870 1.7 christos op->X_op_symbol = make_expr_symbol (&data);
871 1.7 christos }
872 1.1 christos return input_line_pointer;
873 1.1 christos }
874 1.1 christos
875 1.7 christos static int
876 1.7 christos unify_indexed (expressionS *op)
877 1.7 christos {
878 1.7 christos if (O_register != symbol_get_value_expression (op->X_add_symbol)->X_op)
879 1.7 christos return 0;
880 1.7 christos
881 1.7 christos int rnum = symbol_get_value_expression (op->X_add_symbol)->X_add_number;
882 1.7 christos if ( ((REG_IX != rnum) && (REG_IY != rnum)) || contains_register (op->X_op_symbol))
883 1.7 christos {
884 1.7 christos ill_op ();
885 1.7 christos return 0;
886 1.7 christos }
887 1.7 christos
888 1.7 christos /* Convert subtraction to addition of negative value. */
889 1.7 christos if (O_subtract == op->X_op)
890 1.7 christos {
891 1.7 christos expressionS minus;
892 1.7 christos minus.X_op = O_uminus;
893 1.7 christos minus.X_add_number = 0;
894 1.7 christos minus.X_add_symbol = op->X_op_symbol;
895 1.7 christos minus.X_op_symbol = 0;
896 1.7 christos op->X_op_symbol = make_expr_symbol (&minus);
897 1.7 christos op->X_op = O_add;
898 1.7 christos }
899 1.7 christos
900 1.7 christos /* Clear X_add_number of the expression. */
901 1.7 christos if (op->X_add_number != 0)
902 1.7 christos {
903 1.7 christos expressionS add;
904 1.7 christos memset (&add, 0, sizeof (add));
905 1.7 christos add.X_op = O_symbol;
906 1.7 christos add.X_add_number = op->X_add_number;
907 1.7 christos add.X_add_symbol = op->X_op_symbol;
908 1.7 christos add.X_op_symbol = 0;
909 1.7 christos op->X_add_symbol = make_expr_symbol (&add);
910 1.7 christos }
911 1.7 christos else
912 1.7 christos op->X_add_symbol = op->X_op_symbol;
913 1.7 christos
914 1.7 christos op->X_add_number = rnum;
915 1.7 christos op->X_op_symbol = 0;
916 1.7 christos return 1;
917 1.7 christos }
918 1.7 christos
919 1.7 christos /* Parse expression, change operator to O_md1 for indexed addressing. */
920 1.1 christos static const char *
921 1.1 christos parse_exp (const char *s, expressionS *op)
922 1.1 christos {
923 1.1 christos const char* res = parse_exp_not_indexed (s, op);
924 1.1 christos switch (op->X_op)
925 1.1 christos {
926 1.1 christos case O_add:
927 1.1 christos case O_subtract:
928 1.7 christos if (unify_indexed (op) && op->X_md)
929 1.7 christos op->X_op = O_md1;
930 1.1 christos break;
931 1.1 christos case O_register:
932 1.7 christos if (op->X_md && ((REG_IX == op->X_add_number) || (REG_IY == op->X_add_number)))
933 1.1 christos {
934 1.1 christos op->X_add_symbol = zero;
935 1.1 christos op->X_op = O_md1;
936 1.1 christos }
937 1.1 christos break;
938 1.7 christos case O_constant:
939 1.7 christos /* parse SDCC syntax where index register offset placed before parentheses */
940 1.7 christos if (sdcc_compat && is_indir (res))
941 1.7 christos {
942 1.7 christos expressionS off;
943 1.7 christos off = *op;
944 1.7 christos res = parse_exp (res, op);
945 1.7 christos if (op->X_op != O_md1 || op->X_add_symbol != zero)
946 1.7 christos ill_op ();
947 1.7 christos else
948 1.7 christos op->X_add_symbol = make_expr_symbol (&off);
949 1.7 christos }
950 1.7 christos break;
951 1.3 christos default:
952 1.3 christos break;
953 1.1 christos }
954 1.1 christos return res;
955 1.1 christos }
956 1.1 christos
957 1.1 christos /* Condition codes, including some synonyms provided by HiTech zas. */
958 1.1 christos static const struct reg_entry cc_tab[] =
959 1.1 christos {
960 1.1 christos { "age", 6 << 3 },
961 1.1 christos { "alt", 7 << 3 },
962 1.1 christos { "c", 3 << 3 },
963 1.1 christos { "di", 4 << 3 },
964 1.1 christos { "ei", 5 << 3 },
965 1.1 christos { "lge", 2 << 3 },
966 1.1 christos { "llt", 3 << 3 },
967 1.1 christos { "m", 7 << 3 },
968 1.1 christos { "nc", 2 << 3 },
969 1.1 christos { "nz", 0 << 3 },
970 1.1 christos { "p", 6 << 3 },
971 1.1 christos { "pe", 5 << 3 },
972 1.1 christos { "po", 4 << 3 },
973 1.1 christos { "z", 1 << 3 },
974 1.1 christos } ;
975 1.1 christos
976 1.1 christos /* Parse condition code. */
977 1.1 christos static const char *
978 1.1 christos parse_cc (const char *s, char * op)
979 1.1 christos {
980 1.1 christos const char *p;
981 1.1 christos int i;
982 1.1 christos struct reg_entry * cc_p;
983 1.1 christos
984 1.1 christos for (i = 0; i < BUFLEN; ++i)
985 1.1 christos {
986 1.1 christos if (!ISALPHA (s[i])) /* Condition codes consist of letters only. */
987 1.1 christos break;
988 1.1 christos buf[i] = TOLOWER (s[i]);
989 1.1 christos }
990 1.1 christos
991 1.1 christos if ((i < BUFLEN)
992 1.1 christos && ((s[i] == 0) || (s[i] == ',')))
993 1.1 christos {
994 1.1 christos buf[i] = 0;
995 1.1 christos cc_p = bsearch (&key, cc_tab, ARRAY_SIZE (cc_tab),
996 1.1 christos sizeof (cc_tab[0]), key_cmp);
997 1.1 christos }
998 1.1 christos else
999 1.1 christos cc_p = NULL;
1000 1.1 christos
1001 1.1 christos if (cc_p)
1002 1.1 christos {
1003 1.1 christos *op = cc_p->number;
1004 1.1 christos p = s + i;
1005 1.1 christos }
1006 1.1 christos else
1007 1.1 christos p = NULL;
1008 1.1 christos
1009 1.1 christos return p;
1010 1.1 christos }
1011 1.1 christos
1012 1.1 christos static const char *
1013 1.1 christos emit_insn (char prefix, char opcode, const char * args)
1014 1.1 christos {
1015 1.1 christos char *p;
1016 1.1 christos
1017 1.1 christos if (prefix)
1018 1.1 christos {
1019 1.1 christos p = frag_more (2);
1020 1.1 christos *p++ = prefix;
1021 1.1 christos }
1022 1.1 christos else
1023 1.1 christos p = frag_more (1);
1024 1.1 christos *p = opcode;
1025 1.1 christos return args;
1026 1.1 christos }
1027 1.1 christos
1028 1.1 christos void z80_cons_fix_new (fragS *frag_p, int offset, int nbytes, expressionS *exp)
1029 1.1 christos {
1030 1.1 christos bfd_reloc_code_real_type r[4] =
1031 1.1 christos {
1032 1.1 christos BFD_RELOC_8,
1033 1.1 christos BFD_RELOC_16,
1034 1.1 christos BFD_RELOC_24,
1035 1.1 christos BFD_RELOC_32
1036 1.1 christos };
1037 1.1 christos
1038 1.3 christos if (nbytes < 1 || nbytes > 4)
1039 1.1 christos {
1040 1.1 christos as_bad (_("unsupported BFD relocation size %u"), nbytes);
1041 1.1 christos }
1042 1.1 christos else
1043 1.1 christos {
1044 1.1 christos fix_new_exp (frag_p, offset, nbytes, exp, 0, r[nbytes-1]);
1045 1.1 christos }
1046 1.1 christos }
1047 1.1 christos
1048 1.1 christos static void
1049 1.7 christos emit_data_val (expressionS * val, int size)
1050 1.7 christos {
1051 1.7 christos char *p;
1052 1.7 christos bfd_reloc_code_real_type r_type;
1053 1.7 christos
1054 1.7 christos p = frag_more (size);
1055 1.7 christos if (val->X_op == O_constant)
1056 1.7 christos {
1057 1.7 christos int i;
1058 1.7 christos for (i = 0; i < size; ++i)
1059 1.7 christos p[i] = (char)(val->X_add_number >> (i*8));
1060 1.7 christos return;
1061 1.7 christos }
1062 1.7 christos
1063 1.7 christos switch (size)
1064 1.7 christos {
1065 1.7 christos case 1: r_type = BFD_RELOC_8; break;
1066 1.7 christos case 2: r_type = BFD_RELOC_16; break;
1067 1.7 christos case 3: r_type = BFD_RELOC_24; break;
1068 1.7 christos case 4: r_type = BFD_RELOC_32; break;
1069 1.7 christos case 8: r_type = BFD_RELOC_64; break;
1070 1.7 christos default:
1071 1.7 christos as_fatal (_("invalid data size %d"), size);
1072 1.7 christos }
1073 1.7 christos
1074 1.7 christos if ( (val->X_op == O_register)
1075 1.7 christos || (val->X_op == O_md1)
1076 1.7 christos || contains_register (val->X_add_symbol)
1077 1.7 christos || contains_register (val->X_op_symbol))
1078 1.7 christos ill_op ();
1079 1.7 christos
1080 1.7 christos if (size <= 2 && val->X_op_symbol)
1081 1.7 christos {
1082 1.7 christos bfd_boolean simplify = TRUE;
1083 1.7 christos int shift = symbol_get_value_expression (val->X_op_symbol)->X_add_number;
1084 1.7 christos if (val->X_op == O_bit_and && shift == (1 << (size*8))-1)
1085 1.7 christos shift = 0;
1086 1.7 christos else if (val->X_op != O_right_shift)
1087 1.7 christos shift = -1;
1088 1.7 christos
1089 1.7 christos if (size == 1)
1090 1.7 christos {
1091 1.7 christos switch (shift)
1092 1.7 christos {
1093 1.7 christos case 0: r_type = BFD_RELOC_Z80_BYTE0; break;
1094 1.7 christos case 8: r_type = BFD_RELOC_Z80_BYTE1; break;
1095 1.7 christos case 16: r_type = BFD_RELOC_Z80_BYTE2; break;
1096 1.7 christos case 24: r_type = BFD_RELOC_Z80_BYTE3; break;
1097 1.7 christos default: simplify = FALSE;
1098 1.7 christos }
1099 1.7 christos }
1100 1.7 christos else /* if (size == 2) */
1101 1.7 christos {
1102 1.7 christos switch (shift)
1103 1.7 christos {
1104 1.7 christos case 0: r_type = BFD_RELOC_Z80_WORD0; break;
1105 1.7 christos case 16: r_type = BFD_RELOC_Z80_WORD1; break;
1106 1.7 christos default: simplify = FALSE;
1107 1.7 christos }
1108 1.7 christos }
1109 1.7 christos
1110 1.7 christos if (simplify)
1111 1.7 christos {
1112 1.7 christos val->X_op = O_symbol;
1113 1.7 christos val->X_op_symbol = NULL;
1114 1.7 christos val->X_add_number = 0;
1115 1.7 christos }
1116 1.7 christos }
1117 1.7 christos
1118 1.7 christos fix_new_exp (frag_now, p - frag_now->fr_literal, size, val, FALSE, r_type);
1119 1.7 christos }
1120 1.7 christos
1121 1.7 christos static void
1122 1.1 christos emit_byte (expressionS * val, bfd_reloc_code_real_type r_type)
1123 1.1 christos {
1124 1.1 christos char *p;
1125 1.1 christos int lo, hi;
1126 1.1 christos
1127 1.7 christos if (r_type == BFD_RELOC_8)
1128 1.7 christos {
1129 1.7 christos emit_data_val (val, 1);
1130 1.7 christos return;
1131 1.7 christos }
1132 1.1 christos p = frag_more (1);
1133 1.1 christos *p = val->X_add_number;
1134 1.7 christos if ( contains_register (val->X_add_symbol) || contains_register (val->X_op_symbol) )
1135 1.1 christos {
1136 1.7 christos ill_op ();
1137 1.1 christos }
1138 1.1 christos else if ((r_type == BFD_RELOC_8_PCREL) && (val->X_op == O_constant))
1139 1.1 christos {
1140 1.1 christos as_bad (_("cannot make a relative jump to an absolute location"));
1141 1.1 christos }
1142 1.1 christos else if (val->X_op == O_constant)
1143 1.1 christos {
1144 1.1 christos lo = -128;
1145 1.1 christos hi = (BFD_RELOC_8 == r_type) ? 255 : 127;
1146 1.1 christos
1147 1.1 christos if ((val->X_add_number < lo) || (val->X_add_number > hi))
1148 1.1 christos {
1149 1.1 christos if (r_type == BFD_RELOC_Z80_DISP8)
1150 1.1 christos as_bad (_("offset too large"));
1151 1.1 christos else
1152 1.1 christos as_warn (_("overflow"));
1153 1.1 christos }
1154 1.1 christos }
1155 1.1 christos else
1156 1.1 christos {
1157 1.7 christos /* For symbols only, constants are stored at begin of function */
1158 1.3 christos fix_new_exp (frag_now, p - frag_now->fr_literal, 1, val,
1159 1.3 christos (r_type == BFD_RELOC_8_PCREL) ? TRUE : FALSE, r_type);
1160 1.1 christos }
1161 1.1 christos }
1162 1.1 christos
1163 1.1 christos static void
1164 1.1 christos emit_word (expressionS * val)
1165 1.1 christos {
1166 1.7 christos emit_data_val (val, (inst_mode & INST_MODE_IL) ? 3 : 2);
1167 1.1 christos }
1168 1.1 christos
1169 1.1 christos static void
1170 1.1 christos emit_mx (char prefix, char opcode, int shift, expressionS * arg)
1171 1.1 christos /* The operand m may be r, (hl), (ix+d), (iy+d),
1172 1.1 christos if 0 == prefix m may also be ixl, ixh, iyl, iyh. */
1173 1.1 christos {
1174 1.1 christos char *q;
1175 1.1 christos int rnum;
1176 1.1 christos
1177 1.1 christos rnum = arg->X_add_number;
1178 1.1 christos switch (arg->X_op)
1179 1.1 christos {
1180 1.1 christos case O_register:
1181 1.1 christos if (arg->X_md)
1182 1.1 christos {
1183 1.1 christos if (rnum != REG_HL)
1184 1.1 christos {
1185 1.1 christos ill_op ();
1186 1.1 christos break;
1187 1.1 christos }
1188 1.1 christos else
1189 1.1 christos rnum = 6;
1190 1.1 christos }
1191 1.1 christos else
1192 1.1 christos {
1193 1.1 christos if ((prefix == 0) && (rnum & R_INDEX))
1194 1.1 christos {
1195 1.1 christos prefix = (rnum & R_IX) ? 0xDD : 0xFD;
1196 1.7 christos if (!(ins_ok & INS_EZ80))
1197 1.7 christos check_mach (INS_IDX_HALF);
1198 1.1 christos rnum &= ~R_INDEX;
1199 1.1 christos }
1200 1.1 christos if (rnum > 7)
1201 1.1 christos {
1202 1.1 christos ill_op ();
1203 1.1 christos break;
1204 1.1 christos }
1205 1.1 christos }
1206 1.1 christos q = frag_more (prefix ? 2 : 1);
1207 1.1 christos if (prefix)
1208 1.1 christos * q ++ = prefix;
1209 1.1 christos * q ++ = opcode + (rnum << shift);
1210 1.1 christos break;
1211 1.1 christos case O_md1:
1212 1.7 christos if (ins_ok & INS_GBZ80)
1213 1.7 christos {
1214 1.7 christos ill_op ();
1215 1.7 christos break;
1216 1.7 christos }
1217 1.1 christos q = frag_more (2);
1218 1.1 christos *q++ = (rnum & R_IX) ? 0xDD : 0xFD;
1219 1.1 christos *q = (prefix) ? prefix : (opcode + (6 << shift));
1220 1.1 christos {
1221 1.1 christos expressionS offset = *arg;
1222 1.1 christos offset.X_op = O_symbol;
1223 1.1 christos offset.X_add_number = 0;
1224 1.1 christos emit_byte (&offset, BFD_RELOC_Z80_DISP8);
1225 1.1 christos }
1226 1.1 christos if (prefix)
1227 1.1 christos {
1228 1.1 christos q = frag_more (1);
1229 1.1 christos *q = opcode+(6<<shift);
1230 1.1 christos }
1231 1.1 christos break;
1232 1.1 christos default:
1233 1.1 christos abort ();
1234 1.1 christos }
1235 1.1 christos }
1236 1.1 christos
1237 1.1 christos /* The operand m may be r, (hl), (ix+d), (iy+d),
1238 1.1 christos if 0 = prefix m may also be ixl, ixh, iyl, iyh. */
1239 1.1 christos static const char *
1240 1.1 christos emit_m (char prefix, char opcode, const char *args)
1241 1.1 christos {
1242 1.1 christos expressionS arg_m;
1243 1.1 christos const char *p;
1244 1.1 christos
1245 1.1 christos p = parse_exp (args, &arg_m);
1246 1.1 christos switch (arg_m.X_op)
1247 1.1 christos {
1248 1.1 christos case O_md1:
1249 1.1 christos case O_register:
1250 1.1 christos emit_mx (prefix, opcode, 0, &arg_m);
1251 1.1 christos break;
1252 1.1 christos default:
1253 1.1 christos ill_op ();
1254 1.1 christos }
1255 1.1 christos return p;
1256 1.1 christos }
1257 1.1 christos
1258 1.1 christos /* The operand m may be as above or one of the undocumented
1259 1.1 christos combinations (ix+d),r and (iy+d),r (if unportable instructions
1260 1.1 christos are allowed). */
1261 1.7 christos
1262 1.1 christos static const char *
1263 1.1 christos emit_mr (char prefix, char opcode, const char *args)
1264 1.1 christos {
1265 1.1 christos expressionS arg_m, arg_r;
1266 1.1 christos const char *p;
1267 1.1 christos
1268 1.1 christos p = parse_exp (args, & arg_m);
1269 1.1 christos
1270 1.1 christos switch (arg_m.X_op)
1271 1.1 christos {
1272 1.1 christos case O_md1:
1273 1.1 christos if (*p == ',')
1274 1.1 christos {
1275 1.1 christos p = parse_exp (p + 1, & arg_r);
1276 1.1 christos
1277 1.1 christos if ((arg_r.X_md == 0)
1278 1.1 christos && (arg_r.X_op == O_register)
1279 1.1 christos && (arg_r.X_add_number < 8))
1280 1.7 christos opcode += arg_r.X_add_number - 6; /* Emit_mx () will add 6. */
1281 1.1 christos else
1282 1.1 christos {
1283 1.1 christos ill_op ();
1284 1.1 christos break;
1285 1.1 christos }
1286 1.7 christos check_mach (INS_ROT_II_LD);
1287 1.1 christos }
1288 1.6 christos /* Fall through. */
1289 1.1 christos case O_register:
1290 1.1 christos emit_mx (prefix, opcode, 0, & arg_m);
1291 1.1 christos break;
1292 1.1 christos default:
1293 1.1 christos ill_op ();
1294 1.1 christos }
1295 1.1 christos return p;
1296 1.1 christos }
1297 1.1 christos
1298 1.1 christos static void
1299 1.1 christos emit_sx (char prefix, char opcode, expressionS * arg_p)
1300 1.1 christos {
1301 1.1 christos char *q;
1302 1.1 christos
1303 1.1 christos switch (arg_p->X_op)
1304 1.1 christos {
1305 1.1 christos case O_register:
1306 1.1 christos case O_md1:
1307 1.1 christos emit_mx (prefix, opcode, 0, arg_p);
1308 1.1 christos break;
1309 1.1 christos default:
1310 1.1 christos if (arg_p->X_md)
1311 1.1 christos ill_op ();
1312 1.1 christos else
1313 1.1 christos {
1314 1.1 christos q = frag_more (prefix ? 2 : 1);
1315 1.1 christos if (prefix)
1316 1.1 christos *q++ = prefix;
1317 1.1 christos *q = opcode ^ 0x46;
1318 1.1 christos emit_byte (arg_p, BFD_RELOC_8);
1319 1.1 christos }
1320 1.1 christos }
1321 1.1 christos }
1322 1.1 christos
1323 1.1 christos /* The operand s may be r, (hl), (ix+d), (iy+d), n. */
1324 1.1 christos static const char *
1325 1.1 christos emit_s (char prefix, char opcode, const char *args)
1326 1.1 christos {
1327 1.1 christos expressionS arg_s;
1328 1.1 christos const char *p;
1329 1.1 christos
1330 1.1 christos p = parse_exp (args, & arg_s);
1331 1.7 christos if (*p == ',' && arg_s.X_md == 0 && arg_s.X_op == O_register && arg_s.X_add_number == REG_A)
1332 1.7 christos { /* possible instruction in generic format op A,x */
1333 1.7 christos if (!(ins_ok & INS_EZ80) && !sdcc_compat)
1334 1.7 christos ill_op ();
1335 1.7 christos ++p;
1336 1.7 christos p = parse_exp (p, & arg_s);
1337 1.7 christos }
1338 1.1 christos emit_sx (prefix, opcode, & arg_s);
1339 1.1 christos return p;
1340 1.1 christos }
1341 1.1 christos
1342 1.1 christos static const char *
1343 1.1 christos emit_call (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1344 1.1 christos {
1345 1.1 christos expressionS addr;
1346 1.1 christos const char *p; char *q;
1347 1.1 christos
1348 1.1 christos p = parse_exp_not_indexed (args, &addr);
1349 1.1 christos if (addr.X_md)
1350 1.1 christos ill_op ();
1351 1.1 christos else
1352 1.1 christos {
1353 1.1 christos q = frag_more (1);
1354 1.1 christos *q = opcode;
1355 1.1 christos emit_word (& addr);
1356 1.1 christos }
1357 1.1 christos return p;
1358 1.1 christos }
1359 1.1 christos
1360 1.1 christos /* Operand may be rr, r, (hl), (ix+d), (iy+d). */
1361 1.1 christos static const char *
1362 1.1 christos emit_incdec (char prefix, char opcode, const char * args)
1363 1.1 christos {
1364 1.1 christos expressionS operand;
1365 1.1 christos int rnum;
1366 1.1 christos const char *p; char *q;
1367 1.1 christos
1368 1.1 christos p = parse_exp (args, &operand);
1369 1.1 christos rnum = operand.X_add_number;
1370 1.1 christos if ((! operand.X_md)
1371 1.1 christos && (operand.X_op == O_register)
1372 1.1 christos && (R_ARITH&rnum))
1373 1.1 christos {
1374 1.1 christos q = frag_more ((rnum & R_INDEX) ? 2 : 1);
1375 1.1 christos if (rnum & R_INDEX)
1376 1.1 christos *q++ = (rnum & R_IX) ? 0xDD : 0xFD;
1377 1.1 christos *q = prefix + ((rnum & 3) << 4);
1378 1.1 christos }
1379 1.1 christos else
1380 1.1 christos {
1381 1.1 christos if ((operand.X_op == O_md1) || (operand.X_op == O_register))
1382 1.1 christos emit_mx (0, opcode, 3, & operand);
1383 1.1 christos else
1384 1.1 christos ill_op ();
1385 1.1 christos }
1386 1.1 christos return p;
1387 1.1 christos }
1388 1.1 christos
1389 1.1 christos static const char *
1390 1.1 christos emit_jr (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1391 1.1 christos {
1392 1.1 christos expressionS addr;
1393 1.1 christos const char *p;
1394 1.1 christos char *q;
1395 1.1 christos
1396 1.1 christos p = parse_exp_not_indexed (args, &addr);
1397 1.1 christos if (addr.X_md)
1398 1.1 christos ill_op ();
1399 1.1 christos else
1400 1.1 christos {
1401 1.1 christos q = frag_more (1);
1402 1.1 christos *q = opcode;
1403 1.7 christos addr.X_add_number--; /* pcrel computes after offset code */
1404 1.1 christos emit_byte (&addr, BFD_RELOC_8_PCREL);
1405 1.1 christos }
1406 1.1 christos return p;
1407 1.1 christos }
1408 1.1 christos
1409 1.1 christos static const char *
1410 1.1 christos emit_jp (char prefix, char opcode, const char * args)
1411 1.1 christos {
1412 1.1 christos expressionS addr;
1413 1.1 christos const char *p;
1414 1.1 christos char *q;
1415 1.1 christos int rnum;
1416 1.1 christos
1417 1.1 christos p = parse_exp_not_indexed (args, & addr);
1418 1.1 christos if (addr.X_md)
1419 1.1 christos {
1420 1.1 christos rnum = addr.X_add_number;
1421 1.1 christos if ((O_register == addr.X_op) && (REG_HL == (rnum & ~R_INDEX)))
1422 1.1 christos {
1423 1.1 christos q = frag_more ((rnum & R_INDEX) ? 2 : 1);
1424 1.1 christos if (rnum & R_INDEX)
1425 1.1 christos *q++ = (rnum & R_IX) ? 0xDD : 0xFD;
1426 1.1 christos *q = prefix;
1427 1.1 christos }
1428 1.1 christos else
1429 1.1 christos ill_op ();
1430 1.1 christos }
1431 1.1 christos else
1432 1.1 christos {
1433 1.1 christos q = frag_more (1);
1434 1.1 christos *q = opcode;
1435 1.1 christos emit_word (& addr);
1436 1.1 christos }
1437 1.1 christos return p;
1438 1.1 christos }
1439 1.1 christos
1440 1.1 christos static const char *
1441 1.1 christos emit_im (char prefix, char opcode, const char * args)
1442 1.1 christos {
1443 1.1 christos expressionS mode;
1444 1.1 christos const char *p;
1445 1.1 christos char *q;
1446 1.1 christos
1447 1.1 christos p = parse_exp (args, & mode);
1448 1.1 christos if (mode.X_md || (mode.X_op != O_constant))
1449 1.1 christos ill_op ();
1450 1.1 christos else
1451 1.1 christos switch (mode.X_add_number)
1452 1.1 christos {
1453 1.1 christos case 1:
1454 1.1 christos case 2:
1455 1.1 christos ++mode.X_add_number;
1456 1.1 christos /* Fall through. */
1457 1.1 christos case 0:
1458 1.1 christos q = frag_more (2);
1459 1.1 christos *q++ = prefix;
1460 1.1 christos *q = opcode + 8*mode.X_add_number;
1461 1.1 christos break;
1462 1.1 christos default:
1463 1.1 christos ill_op ();
1464 1.1 christos }
1465 1.1 christos return p;
1466 1.1 christos }
1467 1.1 christos
1468 1.1 christos static const char *
1469 1.1 christos emit_pop (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1470 1.1 christos {
1471 1.1 christos expressionS regp;
1472 1.1 christos const char *p;
1473 1.1 christos char *q;
1474 1.1 christos
1475 1.1 christos p = parse_exp (args, & regp);
1476 1.1 christos if ((!regp.X_md)
1477 1.1 christos && (regp.X_op == O_register)
1478 1.1 christos && (regp.X_add_number & R_STACKABLE))
1479 1.1 christos {
1480 1.1 christos int rnum;
1481 1.1 christos
1482 1.1 christos rnum = regp.X_add_number;
1483 1.1 christos if (rnum&R_INDEX)
1484 1.1 christos {
1485 1.1 christos q = frag_more (2);
1486 1.1 christos *q++ = (rnum&R_IX)?0xDD:0xFD;
1487 1.1 christos }
1488 1.1 christos else
1489 1.1 christos q = frag_more (1);
1490 1.1 christos *q = opcode + ((rnum & 3) << 4);
1491 1.1 christos }
1492 1.1 christos else
1493 1.1 christos ill_op ();
1494 1.1 christos
1495 1.1 christos return p;
1496 1.1 christos }
1497 1.1 christos
1498 1.1 christos static const char *
1499 1.1 christos emit_retcc (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1500 1.1 christos {
1501 1.1 christos char cc, *q;
1502 1.1 christos const char *p;
1503 1.1 christos
1504 1.1 christos p = parse_cc (args, &cc);
1505 1.1 christos q = frag_more (1);
1506 1.1 christos if (p)
1507 1.1 christos *q = opcode + cc;
1508 1.1 christos else
1509 1.1 christos *q = prefix;
1510 1.1 christos return p ? p : args;
1511 1.1 christos }
1512 1.1 christos
1513 1.1 christos static const char *
1514 1.1 christos emit_adc (char prefix, char opcode, const char * args)
1515 1.1 christos {
1516 1.1 christos expressionS term;
1517 1.1 christos int rnum;
1518 1.1 christos const char *p;
1519 1.1 christos char *q;
1520 1.1 christos
1521 1.1 christos p = parse_exp (args, &term);
1522 1.1 christos if (*p++ != ',')
1523 1.1 christos {
1524 1.3 christos error (_("bad instruction syntax"));
1525 1.1 christos return p;
1526 1.1 christos }
1527 1.1 christos
1528 1.1 christos if ((term.X_md) || (term.X_op != O_register))
1529 1.1 christos ill_op ();
1530 1.1 christos else
1531 1.1 christos switch (term.X_add_number)
1532 1.1 christos {
1533 1.1 christos case REG_A:
1534 1.1 christos p = emit_s (0, prefix, p);
1535 1.1 christos break;
1536 1.1 christos case REG_HL:
1537 1.1 christos p = parse_exp (p, &term);
1538 1.1 christos if ((!term.X_md) && (term.X_op == O_register))
1539 1.1 christos {
1540 1.1 christos rnum = term.X_add_number;
1541 1.1 christos if (R_ARITH == (rnum & (R_ARITH | R_INDEX)))
1542 1.1 christos {
1543 1.1 christos q = frag_more (2);
1544 1.1 christos *q++ = 0xED;
1545 1.1 christos *q = opcode + ((rnum & 3) << 4);
1546 1.1 christos break;
1547 1.1 christos }
1548 1.1 christos }
1549 1.1 christos /* Fall through. */
1550 1.1 christos default:
1551 1.1 christos ill_op ();
1552 1.1 christos }
1553 1.1 christos return p;
1554 1.1 christos }
1555 1.1 christos
1556 1.1 christos static const char *
1557 1.1 christos emit_add (char prefix, char opcode, const char * args)
1558 1.1 christos {
1559 1.1 christos expressionS term;
1560 1.1 christos int lhs, rhs;
1561 1.1 christos const char *p;
1562 1.1 christos char *q;
1563 1.1 christos
1564 1.1 christos p = parse_exp (args, &term);
1565 1.1 christos if (*p++ != ',')
1566 1.1 christos {
1567 1.3 christos error (_("bad instruction syntax"));
1568 1.1 christos return p;
1569 1.1 christos }
1570 1.1 christos
1571 1.1 christos if ((term.X_md) || (term.X_op != O_register))
1572 1.1 christos ill_op ();
1573 1.1 christos else
1574 1.1 christos switch (term.X_add_number & ~R_INDEX)
1575 1.1 christos {
1576 1.1 christos case REG_A:
1577 1.1 christos p = emit_s (0, prefix, p);
1578 1.1 christos break;
1579 1.1 christos case REG_HL:
1580 1.1 christos lhs = term.X_add_number;
1581 1.1 christos p = parse_exp (p, &term);
1582 1.1 christos if ((!term.X_md) && (term.X_op == O_register))
1583 1.1 christos {
1584 1.1 christos rhs = term.X_add_number;
1585 1.1 christos if ((rhs & R_ARITH)
1586 1.1 christos && ((rhs == lhs) || ((rhs & ~R_INDEX) != REG_HL)))
1587 1.1 christos {
1588 1.1 christos q = frag_more ((lhs & R_INDEX) ? 2 : 1);
1589 1.1 christos if (lhs & R_INDEX)
1590 1.1 christos *q++ = (lhs & R_IX) ? 0xDD : 0xFD;
1591 1.1 christos *q = opcode + ((rhs & 3) << 4);
1592 1.1 christos break;
1593 1.1 christos }
1594 1.1 christos }
1595 1.1 christos /* Fall through. */
1596 1.1 christos default:
1597 1.1 christos ill_op ();
1598 1.1 christos }
1599 1.1 christos return p;
1600 1.1 christos }
1601 1.1 christos
1602 1.1 christos static const char *
1603 1.1 christos emit_bit (char prefix, char opcode, const char * args)
1604 1.1 christos {
1605 1.1 christos expressionS b;
1606 1.1 christos int bn;
1607 1.1 christos const char *p;
1608 1.1 christos
1609 1.1 christos p = parse_exp (args, &b);
1610 1.1 christos if (*p++ != ',')
1611 1.3 christos error (_("bad instruction syntax"));
1612 1.1 christos
1613 1.1 christos bn = b.X_add_number;
1614 1.1 christos if ((!b.X_md)
1615 1.1 christos && (b.X_op == O_constant)
1616 1.1 christos && (0 <= bn)
1617 1.1 christos && (bn < 8))
1618 1.1 christos {
1619 1.1 christos if (opcode == 0x40)
1620 1.1 christos /* Bit : no optional third operand. */
1621 1.1 christos p = emit_m (prefix, opcode + (bn << 3), p);
1622 1.1 christos else
1623 1.1 christos /* Set, res : resulting byte can be copied to register. */
1624 1.7 christos p = emit_mr (prefix, opcode + (bn << 3), p);
1625 1.1 christos }
1626 1.1 christos else
1627 1.1 christos ill_op ();
1628 1.1 christos return p;
1629 1.1 christos }
1630 1.1 christos
1631 1.1 christos static const char *
1632 1.1 christos emit_jpcc (char prefix, char opcode, const char * args)
1633 1.1 christos {
1634 1.1 christos char cc;
1635 1.1 christos const char *p;
1636 1.1 christos
1637 1.1 christos p = parse_cc (args, & cc);
1638 1.1 christos if (p && *p++ == ',')
1639 1.1 christos p = emit_call (0, opcode + cc, p);
1640 1.1 christos else
1641 1.1 christos p = (prefix == (char)0xC3)
1642 1.1 christos ? emit_jp (0xE9, prefix, args)
1643 1.1 christos : emit_call (0, prefix, args);
1644 1.1 christos return p;
1645 1.1 christos }
1646 1.1 christos
1647 1.1 christos static const char *
1648 1.1 christos emit_jrcc (char prefix, char opcode, const char * args)
1649 1.1 christos {
1650 1.1 christos char cc;
1651 1.1 christos const char *p;
1652 1.1 christos
1653 1.1 christos p = parse_cc (args, &cc);
1654 1.1 christos if (p && *p++ == ',')
1655 1.1 christos {
1656 1.1 christos if (cc > (3 << 3))
1657 1.1 christos error (_("condition code invalid for jr"));
1658 1.1 christos else
1659 1.1 christos p = emit_jr (0, opcode + cc, p);
1660 1.1 christos }
1661 1.1 christos else
1662 1.1 christos p = emit_jr (0, prefix, args);
1663 1.1 christos
1664 1.1 christos return p;
1665 1.1 christos }
1666 1.1 christos
1667 1.1 christos static const char *
1668 1.1 christos emit_ex (char prefix_in ATTRIBUTE_UNUSED,
1669 1.1 christos char opcode_in ATTRIBUTE_UNUSED, const char * args)
1670 1.1 christos {
1671 1.1 christos expressionS op;
1672 1.1 christos const char * p;
1673 1.1 christos char prefix, opcode;
1674 1.1 christos
1675 1.1 christos p = parse_exp_not_indexed (args, &op);
1676 1.1 christos p = skip_space (p);
1677 1.1 christos if (*p++ != ',')
1678 1.1 christos {
1679 1.1 christos error (_("bad instruction syntax"));
1680 1.1 christos return p;
1681 1.1 christos }
1682 1.1 christos
1683 1.1 christos prefix = opcode = 0;
1684 1.1 christos if (op.X_op == O_register)
1685 1.1 christos switch (op.X_add_number | (op.X_md ? 0x8000 : 0))
1686 1.1 christos {
1687 1.1 christos case REG_AF:
1688 1.1 christos if (TOLOWER (*p++) == 'a' && TOLOWER (*p++) == 'f')
1689 1.1 christos {
1690 1.1 christos /* The scrubber changes '\'' to '`' in this context. */
1691 1.1 christos if (*p == '`')
1692 1.1 christos ++p;
1693 1.1 christos opcode = 0x08;
1694 1.1 christos }
1695 1.1 christos break;
1696 1.1 christos case REG_DE:
1697 1.1 christos if (TOLOWER (*p++) == 'h' && TOLOWER (*p++) == 'l')
1698 1.1 christos opcode = 0xEB;
1699 1.1 christos break;
1700 1.1 christos case REG_SP|0x8000:
1701 1.1 christos p = parse_exp (p, & op);
1702 1.1 christos if (op.X_op == O_register
1703 1.1 christos && op.X_md == 0
1704 1.1 christos && (op.X_add_number & ~R_INDEX) == REG_HL)
1705 1.1 christos {
1706 1.1 christos opcode = 0xE3;
1707 1.1 christos if (R_INDEX & op.X_add_number)
1708 1.1 christos prefix = (R_IX & op.X_add_number) ? 0xDD : 0xFD;
1709 1.1 christos }
1710 1.1 christos break;
1711 1.1 christos }
1712 1.1 christos if (opcode)
1713 1.1 christos emit_insn (prefix, opcode, p);
1714 1.1 christos else
1715 1.1 christos ill_op ();
1716 1.1 christos
1717 1.1 christos return p;
1718 1.1 christos }
1719 1.1 christos
1720 1.1 christos static const char *
1721 1.1 christos emit_in (char prefix ATTRIBUTE_UNUSED, char opcode ATTRIBUTE_UNUSED,
1722 1.1 christos const char * args)
1723 1.1 christos {
1724 1.1 christos expressionS reg, port;
1725 1.1 christos const char *p;
1726 1.1 christos char *q;
1727 1.1 christos
1728 1.1 christos p = parse_exp (args, ®);
1729 1.1 christos if (*p++ != ',')
1730 1.1 christos {
1731 1.3 christos error (_("bad instruction syntax"));
1732 1.1 christos return p;
1733 1.1 christos }
1734 1.1 christos
1735 1.1 christos p = parse_exp (p, &port);
1736 1.1 christos if (reg.X_md == 0
1737 1.1 christos && reg.X_op == O_register
1738 1.1 christos && (reg.X_add_number <= 7 || reg.X_add_number == REG_F)
1739 1.1 christos && (port.X_md))
1740 1.1 christos {
1741 1.1 christos if (port.X_op != O_md1 && port.X_op != O_register)
1742 1.1 christos {
1743 1.1 christos if (REG_A == reg.X_add_number)
1744 1.1 christos {
1745 1.1 christos q = frag_more (1);
1746 1.1 christos *q = 0xDB;
1747 1.1 christos emit_byte (&port, BFD_RELOC_8);
1748 1.1 christos }
1749 1.1 christos else
1750 1.1 christos ill_op ();
1751 1.1 christos }
1752 1.1 christos else
1753 1.1 christos {
1754 1.7 christos if (port.X_add_number == REG_C || port.X_add_number == REG_BC)
1755 1.1 christos {
1756 1.7 christos if (port.X_add_number == REG_BC && !(ins_ok & INS_EZ80))
1757 1.7 christos ill_op ();
1758 1.7 christos else if (reg.X_add_number == REG_F && !(ins_ok & INS_R800))
1759 1.7 christos check_mach (INS_IN_F_C);
1760 1.7 christos q = frag_more (2);
1761 1.7 christos *q++ = 0xED;
1762 1.7 christos *q = 0x40|((reg.X_add_number&7)<<3);
1763 1.1 christos }
1764 1.1 christos else
1765 1.1 christos ill_op ();
1766 1.1 christos }
1767 1.1 christos }
1768 1.1 christos else
1769 1.1 christos ill_op ();
1770 1.1 christos return p;
1771 1.1 christos }
1772 1.1 christos
1773 1.1 christos static const char *
1774 1.7 christos emit_in0 (char prefix ATTRIBUTE_UNUSED, char opcode ATTRIBUTE_UNUSED,
1775 1.7 christos const char * args)
1776 1.7 christos {
1777 1.7 christos expressionS reg, port;
1778 1.7 christos const char *p;
1779 1.7 christos char *q;
1780 1.7 christos
1781 1.7 christos p = parse_exp (args, ®);
1782 1.7 christos if (*p++ != ',')
1783 1.7 christos {
1784 1.7 christos error (_("bad instruction syntax"));
1785 1.7 christos return p;
1786 1.7 christos }
1787 1.7 christos
1788 1.7 christos p = parse_exp (p, &port);
1789 1.7 christos if (reg.X_md == 0
1790 1.7 christos && reg.X_op == O_register
1791 1.7 christos && reg.X_add_number <= 7
1792 1.7 christos && port.X_md
1793 1.7 christos && port.X_op != O_md1
1794 1.7 christos && port.X_op != O_register)
1795 1.7 christos {
1796 1.7 christos q = frag_more (2);
1797 1.7 christos *q++ = 0xED;
1798 1.7 christos *q = 0x00|(reg.X_add_number << 3);
1799 1.7 christos emit_byte (&port, BFD_RELOC_8);
1800 1.7 christos }
1801 1.7 christos else
1802 1.7 christos ill_op ();
1803 1.7 christos return p;
1804 1.7 christos }
1805 1.7 christos
1806 1.7 christos static const char *
1807 1.1 christos emit_out (char prefix ATTRIBUTE_UNUSED, char opcode ATTRIBUTE_UNUSED,
1808 1.1 christos const char * args)
1809 1.1 christos {
1810 1.1 christos expressionS reg, port;
1811 1.1 christos const char *p;
1812 1.1 christos char *q;
1813 1.1 christos
1814 1.1 christos p = parse_exp (args, & port);
1815 1.1 christos if (*p++ != ',')
1816 1.1 christos {
1817 1.3 christos error (_("bad instruction syntax"));
1818 1.1 christos return p;
1819 1.1 christos }
1820 1.1 christos p = parse_exp (p, ®);
1821 1.1 christos if (!port.X_md)
1822 1.1 christos { ill_op (); return p; }
1823 1.1 christos /* Allow "out (c), 0" as unportable instruction. */
1824 1.1 christos if (reg.X_op == O_constant && reg.X_add_number == 0)
1825 1.1 christos {
1826 1.7 christos check_mach (INS_OUT_C_0);
1827 1.1 christos reg.X_op = O_register;
1828 1.1 christos reg.X_add_number = 6;
1829 1.1 christos }
1830 1.1 christos if (reg.X_md
1831 1.1 christos || reg.X_op != O_register
1832 1.1 christos || reg.X_add_number > 7)
1833 1.1 christos ill_op ();
1834 1.1 christos else
1835 1.1 christos if (port.X_op != O_register && port.X_op != O_md1)
1836 1.1 christos {
1837 1.1 christos if (REG_A == reg.X_add_number)
1838 1.1 christos {
1839 1.1 christos q = frag_more (1);
1840 1.1 christos *q = 0xD3;
1841 1.1 christos emit_byte (&port, BFD_RELOC_8);
1842 1.1 christos }
1843 1.1 christos else
1844 1.1 christos ill_op ();
1845 1.1 christos }
1846 1.1 christos else
1847 1.1 christos {
1848 1.7 christos if (REG_C == port.X_add_number || port.X_add_number == REG_BC)
1849 1.1 christos {
1850 1.7 christos if (port.X_add_number == REG_BC && !(ins_ok & INS_EZ80))
1851 1.7 christos ill_op ();
1852 1.1 christos q = frag_more (2);
1853 1.1 christos *q++ = 0xED;
1854 1.1 christos *q = 0x41 | (reg.X_add_number << 3);
1855 1.1 christos }
1856 1.1 christos else
1857 1.1 christos ill_op ();
1858 1.1 christos }
1859 1.1 christos return p;
1860 1.1 christos }
1861 1.1 christos
1862 1.1 christos static const char *
1863 1.7 christos emit_out0 (char prefix ATTRIBUTE_UNUSED, char opcode ATTRIBUTE_UNUSED,
1864 1.7 christos const char * args)
1865 1.7 christos {
1866 1.7 christos expressionS reg, port;
1867 1.7 christos const char *p;
1868 1.7 christos char *q;
1869 1.7 christos
1870 1.7 christos p = parse_exp (args, & port);
1871 1.7 christos if (*p++ != ',')
1872 1.7 christos {
1873 1.7 christos error (_("bad instruction syntax"));
1874 1.7 christos return p;
1875 1.7 christos }
1876 1.7 christos p = parse_exp (p, ®);
1877 1.7 christos if (port.X_md != 0
1878 1.7 christos && port.X_op != O_register
1879 1.7 christos && port.X_op != O_md1
1880 1.7 christos && reg.X_md == 0
1881 1.7 christos && reg.X_op == O_register
1882 1.7 christos && reg.X_add_number <= 7)
1883 1.7 christos {
1884 1.7 christos q = frag_more (2);
1885 1.7 christos *q++ = 0xED;
1886 1.7 christos *q = 0x01 | (reg.X_add_number << 3);
1887 1.7 christos emit_byte (&port, BFD_RELOC_8);
1888 1.7 christos }
1889 1.7 christos else
1890 1.7 christos ill_op ();
1891 1.7 christos return p;
1892 1.7 christos }
1893 1.7 christos
1894 1.7 christos static const char *
1895 1.1 christos emit_rst (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1896 1.1 christos {
1897 1.1 christos expressionS addr;
1898 1.1 christos const char *p;
1899 1.1 christos char *q;
1900 1.1 christos
1901 1.1 christos p = parse_exp_not_indexed (args, &addr);
1902 1.1 christos if (addr.X_op != O_constant)
1903 1.1 christos {
1904 1.1 christos error ("rst needs constant address");
1905 1.1 christos return p;
1906 1.1 christos }
1907 1.1 christos
1908 1.1 christos if (addr.X_add_number & ~(7 << 3))
1909 1.1 christos ill_op ();
1910 1.1 christos else
1911 1.1 christos {
1912 1.1 christos q = frag_more (1);
1913 1.1 christos *q = opcode + (addr.X_add_number & (7 << 3));
1914 1.1 christos }
1915 1.1 christos return p;
1916 1.1 christos }
1917 1.1 christos
1918 1.7 christos /* For 8-bit indirect load to memory instructions like: LD (HL),n or LD (ii+d),n. */
1919 1.1 christos static void
1920 1.7 christos emit_ld_m_n (expressionS *dst, expressionS *src)
1921 1.1 christos {
1922 1.1 christos char *q;
1923 1.7 christos char prefix;
1924 1.7 christos expressionS dst_offset;
1925 1.1 christos
1926 1.7 christos switch (dst->X_add_number)
1927 1.7 christos {
1928 1.7 christos case REG_HL: prefix = 0x00; break;
1929 1.7 christos case REG_IX: prefix = 0xDD; break;
1930 1.7 christos case REG_IY: prefix = 0xFD; break;
1931 1.7 christos default:
1932 1.7 christos ill_op ();
1933 1.7 christos return;
1934 1.7 christos }
1935 1.7 christos
1936 1.7 christos q = frag_more (prefix ? 2 : 1);
1937 1.7 christos if (prefix)
1938 1.7 christos *q++ = prefix;
1939 1.7 christos *q = 0x36;
1940 1.7 christos if (prefix)
1941 1.1 christos {
1942 1.7 christos dst_offset = *dst;
1943 1.7 christos dst_offset.X_op = O_symbol;
1944 1.7 christos dst_offset.X_add_number = 0;
1945 1.7 christos emit_byte (& dst_offset, BFD_RELOC_Z80_DISP8);
1946 1.7 christos }
1947 1.7 christos emit_byte (src, BFD_RELOC_8);
1948 1.7 christos }
1949 1.7 christos
1950 1.7 christos /* For 8-bit load register to memory instructions: LD (<expression>),r. */
1951 1.7 christos static void
1952 1.7 christos emit_ld_m_r (expressionS *dst, expressionS *src)
1953 1.7 christos {
1954 1.7 christos char *q;
1955 1.7 christos char prefix = 0;
1956 1.7 christos expressionS dst_offset;
1957 1.7 christos
1958 1.7 christos switch (dst->X_op)
1959 1.7 christos {
1960 1.7 christos case O_md1:
1961 1.7 christos prefix = (dst->X_add_number == REG_IX) ? 0xDD : 0xFD;
1962 1.7 christos /* Fall through. */
1963 1.7 christos case O_register:
1964 1.7 christos switch (dst->X_add_number)
1965 1.7 christos {
1966 1.7 christos case REG_BC: /* LD (BC),A */
1967 1.7 christos case REG_DE: /* LD (DE),A */
1968 1.7 christos if (src->X_add_number == REG_A)
1969 1.7 christos {
1970 1.7 christos q = frag_more (1);
1971 1.7 christos *q = 0x02 | ((dst->X_add_number & 3) << 4);
1972 1.7 christos return;
1973 1.7 christos }
1974 1.7 christos break;
1975 1.7 christos case REG_IX:
1976 1.7 christos case REG_IY:
1977 1.7 christos case REG_HL: /* LD (HL),r or LD (ii+d),r */
1978 1.7 christos if (src->X_add_number <= 7)
1979 1.7 christos {
1980 1.7 christos q = frag_more (prefix ? 2 : 1);
1981 1.7 christos if (prefix)
1982 1.7 christos *q++ = prefix;
1983 1.7 christos *q = 0x70 | src->X_add_number;
1984 1.7 christos if (prefix)
1985 1.7 christos {
1986 1.7 christos dst_offset = *dst;
1987 1.7 christos dst_offset.X_op = O_symbol;
1988 1.7 christos dst_offset.X_add_number = 0;
1989 1.7 christos emit_byte (& dst_offset, BFD_RELOC_Z80_DISP8);
1990 1.7 christos }
1991 1.7 christos return;
1992 1.7 christos }
1993 1.7 christos break;
1994 1.7 christos default:;
1995 1.7 christos }
1996 1.7 christos break;
1997 1.7 christos default: /* LD (nn),A */
1998 1.7 christos if (src->X_add_number == REG_A)
1999 1.7 christos {
2000 1.7 christos q = frag_more (1);
2001 1.7 christos *q = 0x32;
2002 1.7 christos emit_word (dst);
2003 1.7 christos return;
2004 1.7 christos }
2005 1.7 christos break;
2006 1.7 christos }
2007 1.7 christos ill_op ();
2008 1.7 christos }
2009 1.7 christos
2010 1.7 christos /* For 16-bit load register to memory instructions: LD (<expression>),rr. */
2011 1.7 christos static void
2012 1.7 christos emit_ld_m_rr (expressionS *dst, expressionS *src)
2013 1.7 christos {
2014 1.7 christos char *q;
2015 1.7 christos int prefix = 0;
2016 1.7 christos int opcode = 0;
2017 1.7 christos expressionS dst_offset;
2018 1.7 christos
2019 1.7 christos switch (dst->X_op)
2020 1.7 christos {
2021 1.7 christos case O_md1: /* eZ80 instructions LD (ii+d),rr */
2022 1.7 christos case O_register: /* eZ80 instructions LD (HL),rr */
2023 1.7 christos if (!(ins_ok & INS_EZ80)) /* 16-bit indirect load group is supported by eZ80 only */
2024 1.7 christos ill_op ();
2025 1.7 christos switch (dst->X_add_number)
2026 1.7 christos {
2027 1.7 christos case REG_IX: prefix = 0xDD; break;
2028 1.7 christos case REG_IY: prefix = 0xFD; break;
2029 1.7 christos case REG_HL: prefix = 0xED; break;
2030 1.7 christos default:
2031 1.7 christos ill_op ();
2032 1.7 christos }
2033 1.7 christos switch (src->X_add_number)
2034 1.7 christos {
2035 1.7 christos case REG_BC: opcode = 0x0F; break;
2036 1.7 christos case REG_DE: opcode = 0x1F; break;
2037 1.7 christos case REG_HL: opcode = 0x2F; break;
2038 1.7 christos case REG_IX: opcode = (prefix != 0xFD) ? 0x3F : 0x3E; break;
2039 1.7 christos case REG_IY: opcode = (prefix != 0xFD) ? 0x3E : 0x3F; break;
2040 1.7 christos default:
2041 1.7 christos ill_op ();
2042 1.7 christos }
2043 1.7 christos q = frag_more (prefix ? 2 : 1);
2044 1.7 christos *q++ = prefix;
2045 1.7 christos *q = opcode;
2046 1.7 christos if (prefix == 0xFD || prefix == 0xDD)
2047 1.7 christos {
2048 1.7 christos dst_offset = *dst;
2049 1.7 christos dst_offset.X_op = O_symbol;
2050 1.7 christos dst_offset.X_add_number = 0;
2051 1.7 christos emit_byte (& dst_offset, BFD_RELOC_Z80_DISP8);
2052 1.7 christos }
2053 1.7 christos break;
2054 1.7 christos default: /* LD (nn),rr */
2055 1.7 christos if (ins_ok & INS_GBZ80)
2056 1.7 christos {
2057 1.7 christos /* GBZ80 supports only LD (nn),SP */
2058 1.7 christos if (src->X_add_number == REG_SP)
2059 1.7 christos {
2060 1.7 christos prefix = 0x00;
2061 1.7 christos opcode = 0x08;
2062 1.7 christos }
2063 1.7 christos else
2064 1.7 christos ill_op ();
2065 1.7 christos }
2066 1.1 christos else
2067 1.7 christos {
2068 1.7 christos switch (src->X_add_number)
2069 1.7 christos {
2070 1.7 christos case REG_BC: prefix = 0xED; opcode = 0x43; break;
2071 1.7 christos case REG_DE: prefix = 0xED; opcode = 0x53; break;
2072 1.7 christos case REG_HL: prefix = 0x00; opcode = 0x22; break;
2073 1.7 christos case REG_IX: prefix = 0xDD; opcode = 0x22; break;
2074 1.7 christos case REG_IY: prefix = 0xFD; opcode = 0x22; break;
2075 1.7 christos case REG_SP: prefix = 0xED; opcode = 0x73; break;
2076 1.7 christos default:
2077 1.7 christos ill_op ();
2078 1.7 christos }
2079 1.7 christos }
2080 1.7 christos q = frag_more (prefix ? 2 : 1);
2081 1.7 christos if (prefix)
2082 1.7 christos *q++ = prefix;
2083 1.7 christos *q = opcode;
2084 1.7 christos emit_word (dst);
2085 1.7 christos }
2086 1.7 christos }
2087 1.7 christos
2088 1.7 christos static void
2089 1.7 christos emit_ld_r_m (expressionS *dst, expressionS *src)
2090 1.7 christos { /* for 8-bit memory load to register: LD r,(xxx) */
2091 1.7 christos char *q;
2092 1.7 christos char prefix = 0;
2093 1.7 christos char opcode = 0;
2094 1.7 christos expressionS src_offset;
2095 1.7 christos
2096 1.7 christos if (dst->X_add_number == REG_A && src->X_op == O_register)
2097 1.7 christos { /* LD A,(BC) or LD A,(DE) */
2098 1.7 christos switch (src->X_add_number)
2099 1.7 christos {
2100 1.7 christos case REG_BC: opcode = 0x0A; break;
2101 1.7 christos case REG_DE: opcode = 0x1A; break;
2102 1.7 christos default: break;
2103 1.7 christos }
2104 1.7 christos if (opcode != 0)
2105 1.7 christos {
2106 1.7 christos q = frag_more (1);
2107 1.7 christos *q = opcode;
2108 1.7 christos return;
2109 1.7 christos }
2110 1.7 christos }
2111 1.7 christos
2112 1.7 christos switch (src->X_op)
2113 1.7 christos {
2114 1.7 christos case O_md1:
2115 1.7 christos case O_register:
2116 1.7 christos if (dst->X_add_number > 7)
2117 1.7 christos ill_op ();
2118 1.7 christos opcode = 0x46; /* LD B,(HL) */
2119 1.7 christos switch (src->X_add_number)
2120 1.7 christos {
2121 1.7 christos case REG_HL: prefix = 0x00; break;
2122 1.7 christos case REG_IX: prefix = 0xDD; break;
2123 1.7 christos case REG_IY: prefix = 0xFD; break;
2124 1.7 christos default:
2125 1.7 christos ill_op ();
2126 1.7 christos }
2127 1.7 christos q = frag_more (prefix ? 2 : 1);
2128 1.7 christos if (prefix)
2129 1.7 christos *q++ = prefix;
2130 1.7 christos *q = opcode | ((dst->X_add_number & 7) << 3);
2131 1.7 christos if (prefix)
2132 1.7 christos {
2133 1.7 christos src_offset = *src;
2134 1.7 christos src_offset.X_op = O_symbol;
2135 1.7 christos src_offset.X_add_number = 0;
2136 1.7 christos emit_byte (& src_offset, BFD_RELOC_Z80_DISP8);
2137 1.7 christos }
2138 1.7 christos break;
2139 1.7 christos default: /* LD A,(nn) */
2140 1.7 christos if (dst->X_add_number == REG_A)
2141 1.7 christos {
2142 1.7 christos q = frag_more (1);
2143 1.7 christos *q = 0x3A;
2144 1.7 christos emit_word (src);
2145 1.7 christos }
2146 1.7 christos }
2147 1.7 christos }
2148 1.7 christos
2149 1.7 christos static void
2150 1.7 christos emit_ld_r_n (expressionS *dst, expressionS *src)
2151 1.7 christos { /* for 8-bit immediate value load to register: LD r,n */
2152 1.7 christos char *q;
2153 1.7 christos char prefix = 0;
2154 1.7 christos
2155 1.7 christos switch (dst->X_add_number)
2156 1.7 christos {
2157 1.7 christos case REG_H|R_IX:
2158 1.7 christos case REG_L|R_IX:
2159 1.7 christos prefix = 0xDD;
2160 1.7 christos break;
2161 1.7 christos case REG_H|R_IY:
2162 1.7 christos case REG_L|R_IY:
2163 1.7 christos prefix = 0xFD;
2164 1.7 christos break;
2165 1.7 christos case REG_A:
2166 1.7 christos case REG_B:
2167 1.7 christos case REG_C:
2168 1.7 christos case REG_D:
2169 1.7 christos case REG_E:
2170 1.7 christos case REG_H:
2171 1.7 christos case REG_L:
2172 1.7 christos break;
2173 1.7 christos default:
2174 1.7 christos ill_op ();
2175 1.7 christos // return;
2176 1.7 christos }
2177 1.7 christos
2178 1.7 christos q = frag_more (prefix ? 2 : 1);
2179 1.7 christos if (prefix)
2180 1.7 christos {
2181 1.7 christos if (ins_ok & INS_GBZ80)
2182 1.7 christos ill_op ();
2183 1.7 christos else if (!(ins_ok & INS_EZ80))
2184 1.7 christos check_mach (INS_IDX_HALF);
2185 1.7 christos *q++ = prefix;
2186 1.1 christos }
2187 1.7 christos *q = 0x06 | ((dst->X_add_number & 7) << 3);
2188 1.7 christos emit_byte (src, BFD_RELOC_8);
2189 1.1 christos }
2190 1.1 christos
2191 1.1 christos static void
2192 1.7 christos emit_ld_r_r (expressionS *dst, expressionS *src)
2193 1.7 christos { /* mostly 8-bit load register from register instructions: LD r,r */
2194 1.7 christos /* there are some exceptions: LD SP,HL/IX/IY; LD I,HL and LD HL,I */
2195 1.1 christos char *q;
2196 1.7 christos int prefix = 0;
2197 1.7 christos int opcode = 0;
2198 1.7 christos int ii_halves = 0;
2199 1.1 christos
2200 1.7 christos switch (dst->X_add_number)
2201 1.1 christos {
2202 1.7 christos case REG_SP:
2203 1.7 christos switch (src->X_add_number)
2204 1.7 christos {
2205 1.7 christos case REG_HL: prefix = 0x00; break;
2206 1.7 christos case REG_IX: prefix = 0xDD; break;
2207 1.7 christos case REG_IY: prefix = 0xFD; break;
2208 1.7 christos default:
2209 1.7 christos ill_op ();
2210 1.7 christos }
2211 1.7 christos if (ins_ok & INS_GBZ80)
2212 1.7 christos ill_op ();
2213 1.7 christos opcode = 0xF9;
2214 1.7 christos break;
2215 1.7 christos case REG_HL:
2216 1.7 christos if (!(ins_ok & INS_EZ80))
2217 1.7 christos ill_op ();
2218 1.7 christos if (src->X_add_number != REG_I)
2219 1.7 christos ill_op ();
2220 1.7 christos if (cpu_mode < 1)
2221 1.7 christos error (_("ADL mode instruction"));
2222 1.7 christos /* LD HL,I */
2223 1.7 christos prefix = 0xED;
2224 1.7 christos opcode = 0xD7;
2225 1.7 christos break;
2226 1.1 christos case REG_I:
2227 1.7 christos if (src->X_add_number == REG_HL)
2228 1.7 christos {
2229 1.7 christos if (!(ins_ok & INS_EZ80))
2230 1.7 christos ill_op ();
2231 1.7 christos if (cpu_mode < 1)
2232 1.7 christos error (_("ADL mode instruction"));
2233 1.7 christos prefix = 0xED;
2234 1.7 christos opcode = 0xC7;
2235 1.7 christos }
2236 1.7 christos else if (src->X_add_number == REG_A)
2237 1.7 christos {
2238 1.7 christos prefix = 0xED;
2239 1.7 christos opcode = 0x47;
2240 1.7 christos }
2241 1.7 christos else
2242 1.7 christos ill_op ();
2243 1.7 christos break;
2244 1.7 christos case REG_MB:
2245 1.7 christos if (!(ins_ok & INS_EZ80) || (src->X_add_number != REG_A))
2246 1.7 christos ill_op ();
2247 1.7 christos if (cpu_mode < 1)
2248 1.7 christos error (_("ADL mode instruction"));
2249 1.7 christos prefix = 0xED;
2250 1.7 christos opcode = 0x6D;
2251 1.7 christos break;
2252 1.1 christos case REG_R:
2253 1.7 christos if (src->X_add_number == REG_A) /* LD R,A */
2254 1.7 christos {
2255 1.7 christos prefix = 0xED;
2256 1.7 christos opcode = 0x4F;
2257 1.7 christos }
2258 1.1 christos else
2259 1.7 christos ill_op ();
2260 1.1 christos break;
2261 1.1 christos case REG_A:
2262 1.7 christos if (src->X_add_number == REG_I) /* LD A,I */
2263 1.7 christos {
2264 1.7 christos prefix = 0xED;
2265 1.7 christos opcode = 0x57;
2266 1.7 christos break;
2267 1.7 christos }
2268 1.7 christos else if (src->X_add_number == REG_R) /* LD A,R */
2269 1.7 christos {
2270 1.7 christos prefix = 0xED;
2271 1.7 christos opcode = 0x5F;
2272 1.7 christos break;
2273 1.7 christos }
2274 1.7 christos else if (src->X_add_number == REG_MB) /* LD A,MB */
2275 1.7 christos {
2276 1.7 christos if (!(ins_ok & INS_EZ80))
2277 1.7 christos ill_op ();
2278 1.7 christos else
2279 1.7 christos {
2280 1.7 christos if (cpu_mode < 1)
2281 1.7 christos error (_("ADL mode instruction"));
2282 1.7 christos prefix = 0xED;
2283 1.7 christos opcode = 0x6E;
2284 1.7 christos }
2285 1.7 christos break;
2286 1.7 christos }
2287 1.7 christos /* Fall through. */
2288 1.1 christos case REG_B:
2289 1.1 christos case REG_C:
2290 1.1 christos case REG_D:
2291 1.1 christos case REG_E:
2292 1.7 christos case REG_H:
2293 1.7 christos case REG_L:
2294 1.7 christos prefix = 0x00;
2295 1.7 christos break;
2296 1.7 christos case REG_H|R_IX:
2297 1.7 christos case REG_L|R_IX:
2298 1.7 christos prefix = 0xDD;
2299 1.7 christos ii_halves = 1;
2300 1.7 christos break;
2301 1.7 christos case REG_H|R_IY:
2302 1.7 christos case REG_L|R_IY:
2303 1.7 christos prefix = 0xFD;
2304 1.7 christos ii_halves = 1;
2305 1.7 christos break;
2306 1.7 christos default:
2307 1.7 christos ill_op ();
2308 1.7 christos }
2309 1.7 christos
2310 1.7 christos if (opcode == 0)
2311 1.7 christos {
2312 1.7 christos switch (src->X_add_number)
2313 1.7 christos {
2314 1.7 christos case REG_A:
2315 1.7 christos case REG_B:
2316 1.7 christos case REG_C:
2317 1.7 christos case REG_D:
2318 1.7 christos case REG_E:
2319 1.7 christos break;
2320 1.7 christos case REG_H:
2321 1.7 christos case REG_L:
2322 1.7 christos if (prefix != 0)
2323 1.7 christos ill_op (); /* LD iiH/L,H/L are not permitted */
2324 1.7 christos break;
2325 1.7 christos case REG_H|R_IX:
2326 1.7 christos case REG_L|R_IX:
2327 1.7 christos if (prefix == 0xFD || dst->X_add_number == REG_H || dst->X_add_number == REG_L)
2328 1.7 christos ill_op (); /* LD IYL,IXL and LD H,IXH are not permitted */
2329 1.7 christos prefix = 0xDD;
2330 1.7 christos ii_halves = 1;
2331 1.7 christos break;
2332 1.7 christos case REG_H|R_IY:
2333 1.7 christos case REG_L|R_IY:
2334 1.7 christos if (prefix == 0xDD || dst->X_add_number == REG_H || dst->X_add_number == REG_L)
2335 1.7 christos ill_op (); /* LD IXH,IYH and LD L,IYL are not permitted */
2336 1.7 christos prefix = 0xFD;
2337 1.7 christos ii_halves = 1;
2338 1.7 christos break;
2339 1.7 christos default:
2340 1.7 christos ill_op ();
2341 1.7 christos }
2342 1.7 christos opcode = 0x40 + ((dst->X_add_number & 7) << 3) + (src->X_add_number & 7);
2343 1.7 christos }
2344 1.7 christos if ((ins_ok & INS_GBZ80) && prefix != 0)
2345 1.7 christos ill_op ();
2346 1.7 christos if (ii_halves && !(ins_ok & INS_EZ80))
2347 1.7 christos check_mach (INS_IDX_HALF);
2348 1.7 christos if (prefix == 0 && (ins_ok & INS_EZ80))
2349 1.7 christos {
2350 1.7 christos switch (opcode)
2351 1.7 christos {
2352 1.7 christos case 0x40: /* SIS prefix, in Z80 it is LD B,B */
2353 1.7 christos case 0x49: /* LIS prefix, in Z80 it is LD C,C */
2354 1.7 christos case 0x52: /* SIL prefix, in Z80 it is LD D,D */
2355 1.7 christos case 0x5B: /* LIL prefix, in Z80 it is LD E,E */
2356 1.7 christos as_warn (_("unsupported instruction, assembled as NOP"));
2357 1.7 christos opcode = 0x00;
2358 1.7 christos break;
2359 1.7 christos default:;
2360 1.7 christos }
2361 1.7 christos }
2362 1.7 christos q = frag_more (prefix ? 2 : 1);
2363 1.7 christos if (prefix)
2364 1.7 christos *q++ = prefix;
2365 1.7 christos *q = opcode;
2366 1.7 christos }
2367 1.7 christos
2368 1.7 christos static void
2369 1.7 christos emit_ld_rr_m (expressionS *dst, expressionS *src)
2370 1.7 christos { /* for 16-bit indirect load from memory to register: LD rr,(xxx) */
2371 1.7 christos char *q;
2372 1.7 christos int prefix = 0;
2373 1.7 christos int opcode = 0;
2374 1.7 christos expressionS src_offset;
2375 1.7 christos
2376 1.7 christos /* GBZ80 has no support for 16-bit load from memory instructions */
2377 1.7 christos if (ins_ok & INS_GBZ80)
2378 1.7 christos ill_op ();
2379 1.7 christos
2380 1.7 christos prefix = 0xED;
2381 1.7 christos switch (src->X_op)
2382 1.7 christos {
2383 1.7 christos case O_md1: /* LD rr,(ii+d) */
2384 1.7 christos prefix = (src->X_add_number == REG_IX) ? 0xDD : 0xFD;
2385 1.7 christos /* Fall through. */
2386 1.7 christos case O_register: /* LD rr,(HL) */
2387 1.7 christos /* currently only EZ80 has support for 16bit indirect memory load instructions */
2388 1.7 christos if (!(ins_ok & INS_EZ80))
2389 1.7 christos ill_op ();
2390 1.7 christos switch (dst->X_add_number)
2391 1.7 christos {
2392 1.7 christos case REG_BC: opcode = 0x07; break;
2393 1.7 christos case REG_DE: opcode = 0x17; break;
2394 1.7 christos case REG_HL: opcode = 0x27; break;
2395 1.7 christos case REG_IX: opcode = (!prefix || prefix == 0xDD) ? 0x37 : 0x31; break;
2396 1.7 christos case REG_IY: opcode = prefix ? ((prefix == 0xDD) ? 0x31 : 0x37) : 0x36; break;
2397 1.7 christos default:
2398 1.7 christos ill_op ();
2399 1.7 christos }
2400 1.7 christos q = frag_more (2);
2401 1.7 christos *q++ = prefix;
2402 1.7 christos *q = opcode;
2403 1.7 christos if (prefix != 0xED)
2404 1.7 christos {
2405 1.7 christos src_offset = *src;
2406 1.7 christos src_offset.X_op = O_symbol;
2407 1.7 christos src_offset.X_add_number = 0;
2408 1.7 christos emit_byte (& src_offset, BFD_RELOC_Z80_DISP8);
2409 1.7 christos }
2410 1.7 christos break;
2411 1.7 christos default: /* LD rr,(nn) */
2412 1.7 christos switch (dst->X_add_number)
2413 1.7 christos {
2414 1.7 christos case REG_BC: prefix = 0xED; opcode = 0x4B; break;
2415 1.7 christos case REG_DE: prefix = 0xED; opcode = 0x5B; break;
2416 1.7 christos case REG_HL: prefix = 0x00; opcode = 0x2A; break;
2417 1.7 christos case REG_SP: prefix = 0xED; opcode = 0x7B; break;
2418 1.7 christos case REG_IX: prefix = 0xDD; opcode = 0x2A; break;
2419 1.7 christos case REG_IY: prefix = 0xFD; opcode = 0x2A; break;
2420 1.7 christos default:
2421 1.7 christos ill_op ();
2422 1.7 christos }
2423 1.7 christos q = frag_more (prefix ? 2 : 1);
2424 1.7 christos if (prefix)
2425 1.7 christos *q++ = prefix;
2426 1.7 christos *q = opcode;
2427 1.7 christos emit_word (src);
2428 1.7 christos }
2429 1.7 christos return;
2430 1.7 christos }
2431 1.7 christos
2432 1.7 christos static void
2433 1.7 christos emit_ld_rr_nn (expressionS *dst, expressionS *src)
2434 1.7 christos { /* mostly load imediate value to multibyte register instructions: LD rr,nn */
2435 1.7 christos char *q;
2436 1.7 christos int prefix = 0x00;
2437 1.7 christos int opcode = 0x21; /* LD HL,nn */
2438 1.7 christos switch (dst->X_add_number)
2439 1.7 christos {
2440 1.7 christos case REG_IX:
2441 1.7 christos prefix = 0xDD;
2442 1.7 christos break;
2443 1.7 christos case REG_IY:
2444 1.7 christos prefix = 0xFD;
2445 1.1 christos break;
2446 1.7 christos case REG_HL:
2447 1.7 christos break;
2448 1.7 christos case REG_BC:
2449 1.7 christos case REG_DE:
2450 1.7 christos case REG_SP:
2451 1.7 christos opcode = 0x01 + ((dst->X_add_number & 3) << 4);
2452 1.7 christos break;
2453 1.7 christos default:
2454 1.7 christos ill_op ();
2455 1.7 christos return;
2456 1.7 christos }
2457 1.7 christos if (prefix && (ins_ok & INS_GBZ80))
2458 1.7 christos ill_op ();
2459 1.7 christos q = frag_more (prefix ? 2 : 1);
2460 1.7 christos if (prefix)
2461 1.7 christos *q++ = prefix;
2462 1.7 christos *q = opcode;
2463 1.7 christos emit_word (src);
2464 1.7 christos }
2465 1.7 christos
2466 1.7 christos static const char *
2467 1.7 christos emit_ld (char prefix_in ATTRIBUTE_UNUSED, char opcode_in ATTRIBUTE_UNUSED,
2468 1.7 christos const char * args)
2469 1.7 christos {
2470 1.7 christos expressionS dst, src;
2471 1.7 christos const char *p;
2472 1.7 christos
2473 1.7 christos p = parse_exp (args, & dst);
2474 1.7 christos if (*p++ != ',')
2475 1.7 christos error (_("bad instruction syntax"));
2476 1.7 christos p = parse_exp (p, & src);
2477 1.7 christos
2478 1.7 christos if (dst.X_md)
2479 1.7 christos {
2480 1.7 christos if (src.X_op == O_register)
2481 1.7 christos {
2482 1.7 christos if (src.X_add_number <= 7)
2483 1.7 christos emit_ld_m_r (& dst, & src); /* LD (xxx),r */
2484 1.7 christos else
2485 1.7 christos emit_ld_m_rr (& dst, & src); /* LD (xxx),rr */
2486 1.7 christos }
2487 1.7 christos else
2488 1.7 christos emit_ld_m_n (& dst, & src); /* LD (hl),n or LD (ix/y+r),n */
2489 1.7 christos }
2490 1.7 christos else if (dst.X_op == O_register)
2491 1.7 christos {
2492 1.7 christos if (src.X_md)
2493 1.7 christos {
2494 1.7 christos if (dst.X_add_number <= 7)
2495 1.7 christos emit_ld_r_m (& dst, & src);
2496 1.7 christos else
2497 1.7 christos emit_ld_rr_m (& dst, & src);
2498 1.7 christos }
2499 1.7 christos else if (src.X_op == O_register)
2500 1.7 christos emit_ld_r_r (& dst, & src);
2501 1.7 christos else if ((dst.X_add_number & ~R_INDEX) <= 7)
2502 1.7 christos emit_ld_r_n (& dst, & src);
2503 1.7 christos else
2504 1.7 christos emit_ld_rr_nn (& dst, & src);
2505 1.7 christos }
2506 1.7 christos else
2507 1.7 christos ill_op ();
2508 1.7 christos
2509 1.7 christos return p;
2510 1.7 christos }
2511 1.7 christos
2512 1.7 christos static const char *
2513 1.7 christos emit_lddldi (char prefix, char opcode, const char * args)
2514 1.7 christos {
2515 1.7 christos expressionS dst, src;
2516 1.7 christos const char *p;
2517 1.7 christos char *q;
2518 1.7 christos
2519 1.7 christos if (!(ins_ok & INS_GBZ80))
2520 1.7 christos return emit_insn (prefix, opcode, args);
2521 1.7 christos
2522 1.7 christos p = parse_exp (args, & dst);
2523 1.7 christos if (*p++ != ',')
2524 1.7 christos error (_("bad instruction syntax"));
2525 1.7 christos p = parse_exp (args, & src);
2526 1.7 christos
2527 1.7 christos if (dst.X_op != O_register || src.X_op != O_register)
2528 1.7 christos ill_op ();
2529 1.7 christos
2530 1.7 christos /* convert opcode 0xA0 . 0x22, 0xA8 . 0x32 */
2531 1.7 christos opcode = (opcode & 0x08) * 2 + 0x22;
2532 1.7 christos
2533 1.7 christos if (dst.X_md != 0
2534 1.7 christos && dst.X_add_number == REG_HL
2535 1.7 christos && src.X_md == 0
2536 1.7 christos && src.X_add_number == REG_A)
2537 1.7 christos opcode |= 0x00; /* LDx (HL),A */
2538 1.7 christos else if (dst.X_md == 0
2539 1.7 christos && dst.X_add_number == REG_A
2540 1.7 christos && src.X_md != 0
2541 1.7 christos && src.X_add_number == REG_HL)
2542 1.7 christos opcode |= 0x08; /* LDx A,(HL) */
2543 1.7 christos else
2544 1.7 christos ill_op ();
2545 1.7 christos
2546 1.7 christos q = frag_more (1);
2547 1.7 christos *q = opcode;
2548 1.7 christos return p;
2549 1.7 christos }
2550 1.7 christos
2551 1.7 christos static const char *
2552 1.7 christos emit_ldh (char prefix ATTRIBUTE_UNUSED, char opcode ATTRIBUTE_UNUSED,
2553 1.7 christos const char * args)
2554 1.7 christos {
2555 1.7 christos expressionS dst, src;
2556 1.7 christos const char *p;
2557 1.7 christos char *q;
2558 1.1 christos
2559 1.7 christos p = parse_exp (args, & dst);
2560 1.7 christos if (*p++ != ',')
2561 1.7 christos {
2562 1.7 christos error (_("bad instruction syntax"));
2563 1.7 christos return p;
2564 1.7 christos }
2565 1.7 christos
2566 1.7 christos p = parse_exp (p, & src);
2567 1.7 christos if (dst.X_md == 0
2568 1.7 christos && dst.X_op == O_register
2569 1.7 christos && dst.X_add_number == REG_A
2570 1.7 christos && src.X_md != 0
2571 1.7 christos && src.X_op != O_md1
2572 1.7 christos && src.X_op != O_register)
2573 1.7 christos {
2574 1.7 christos q = frag_more (1);
2575 1.7 christos *q = 0xF0;
2576 1.7 christos emit_byte (& src, BFD_RELOC_8);
2577 1.7 christos }
2578 1.7 christos else if (dst.X_md != 0
2579 1.7 christos && dst.X_op != O_md1
2580 1.7 christos && src.X_md == 0
2581 1.7 christos && src.X_op == O_register
2582 1.7 christos && src.X_add_number == REG_A)
2583 1.7 christos {
2584 1.7 christos if (dst.X_op == O_register)
2585 1.7 christos {
2586 1.7 christos if (dst.X_add_number == REG_C)
2587 1.7 christos {
2588 1.7 christos q = frag_more (1);
2589 1.7 christos *q = 0xE2;
2590 1.7 christos }
2591 1.7 christos else
2592 1.7 christos ill_op ();
2593 1.7 christos }
2594 1.1 christos else
2595 1.7 christos {
2596 1.7 christos q = frag_more (1);
2597 1.7 christos *q = 0xE0;
2598 1.7 christos emit_byte (& dst, BFD_RELOC_8);
2599 1.7 christos }
2600 1.7 christos }
2601 1.7 christos else
2602 1.7 christos ill_op ();
2603 1.7 christos
2604 1.7 christos return p;
2605 1.7 christos }
2606 1.7 christos
2607 1.7 christos static const char *
2608 1.7 christos parse_lea_pea_args (const char * args, expressionS *op)
2609 1.7 christos {
2610 1.7 christos const char *p;
2611 1.7 christos p = parse_exp (args, op);
2612 1.7 christos if (sdcc_compat && *p == ',' && op->X_op == O_register)
2613 1.7 christos {
2614 1.7 christos expressionS off;
2615 1.7 christos p = parse_exp (p + 1, &off);
2616 1.7 christos op->X_op = O_add;
2617 1.7 christos op->X_add_symbol = make_expr_symbol (&off);
2618 1.7 christos }
2619 1.7 christos return p;
2620 1.7 christos }
2621 1.7 christos
2622 1.7 christos static const char *
2623 1.7 christos emit_lea (char prefix, char opcode, const char * args)
2624 1.7 christos {
2625 1.7 christos expressionS dst, src;
2626 1.7 christos const char *p;
2627 1.7 christos char *q;
2628 1.7 christos int rnum;
2629 1.7 christos
2630 1.7 christos p = parse_exp (args, & dst);
2631 1.7 christos if (dst.X_md != 0 || dst.X_op != O_register)
2632 1.7 christos ill_op ();
2633 1.7 christos
2634 1.7 christos rnum = dst.X_add_number;
2635 1.7 christos switch (rnum)
2636 1.7 christos {
2637 1.7 christos case REG_BC:
2638 1.7 christos case REG_DE:
2639 1.7 christos case REG_HL:
2640 1.7 christos opcode = 0x02 | ((rnum & 0x03) << 4);
2641 1.7 christos break;
2642 1.7 christos case REG_IX:
2643 1.7 christos opcode = 0x32; /* lea ix,ix+d has opcode 0x32; lea ix,iy+d has opcode 0x54 */
2644 1.7 christos break;
2645 1.7 christos case REG_IY:
2646 1.7 christos opcode = 0x33; /* lea iy,iy+d has opcode 0x33; lea iy,ix+d has opcode 0x55 */
2647 1.7 christos break;
2648 1.7 christos default:
2649 1.7 christos ill_op ();
2650 1.7 christos }
2651 1.7 christos
2652 1.7 christos if (*p++ != ',')
2653 1.7 christos error (_("bad instruction syntax"));
2654 1.7 christos
2655 1.7 christos p = parse_lea_pea_args (p, & src);
2656 1.7 christos if (src.X_md != 0 || src.X_op != O_add /*&& src.X_op != O_register*/)
2657 1.7 christos ill_op ();
2658 1.7 christos
2659 1.7 christos rnum = src.X_add_number;
2660 1.7 christos switch (src.X_op)
2661 1.7 christos {
2662 1.7 christos case O_add:
2663 1.1 christos break;
2664 1.7 christos case O_register: /* permit instructions like LEA rr,IX without displacement specified */
2665 1.7 christos src.X_add_symbol = zero;
2666 1.7 christos break;
2667 1.7 christos default:
2668 1.7 christos ill_op ();
2669 1.7 christos }
2670 1.7 christos
2671 1.7 christos switch (rnum)
2672 1.7 christos {
2673 1.7 christos case REG_IX:
2674 1.7 christos opcode = (opcode == (char)0x33) ? 0x55 : (opcode|0x00);
2675 1.7 christos break;
2676 1.7 christos case REG_IY:
2677 1.7 christos opcode = (opcode == (char)0x32) ? 0x54 : (opcode|0x01);
2678 1.7 christos }
2679 1.7 christos
2680 1.7 christos q = frag_more (2);
2681 1.7 christos *q++ = prefix;
2682 1.7 christos *q = opcode;
2683 1.7 christos
2684 1.7 christos src.X_op = O_symbol;
2685 1.7 christos src.X_add_number = 0;
2686 1.7 christos emit_byte (& src, BFD_RELOC_Z80_DISP8);
2687 1.7 christos
2688 1.7 christos return p;
2689 1.7 christos }
2690 1.7 christos
2691 1.7 christos static const char *
2692 1.7 christos emit_mlt (char prefix, char opcode, const char * args)
2693 1.7 christos {
2694 1.7 christos expressionS arg;
2695 1.7 christos const char *p;
2696 1.7 christos char *q;
2697 1.7 christos
2698 1.7 christos p = parse_exp (args, & arg);
2699 1.7 christos if (arg.X_md != 0 || arg.X_op != O_register || !(arg.X_add_number & R_ARITH))
2700 1.7 christos ill_op ();
2701 1.7 christos
2702 1.7 christos q = frag_more (2);
2703 1.7 christos *q++ = prefix;
2704 1.7 christos *q = opcode | ((arg.X_add_number & 3) << 4);
2705 1.7 christos
2706 1.7 christos return p;
2707 1.7 christos }
2708 1.7 christos
2709 1.7 christos static const char *
2710 1.7 christos emit_pea (char prefix, char opcode, const char * args)
2711 1.7 christos {
2712 1.7 christos expressionS arg;
2713 1.7 christos const char *p;
2714 1.7 christos char *q;
2715 1.1 christos
2716 1.7 christos p = parse_lea_pea_args (args, & arg);
2717 1.7 christos if (arg.X_md != 0
2718 1.7 christos || (/*arg.X_op != O_register &&*/ arg.X_op != O_add)
2719 1.7 christos || !(arg.X_add_number & R_INDEX))
2720 1.7 christos ill_op ();
2721 1.7 christos /* PEA ii without displacement is mostly typo,
2722 1.7 christos because there is PUSH instruction which is shorter and faster */
2723 1.7 christos /*if (arg.X_op == O_register)
2724 1.7 christos as_warn (_("PEA is used without displacement, use PUSH instead"));*/
2725 1.7 christos
2726 1.7 christos q = frag_more (2);
2727 1.7 christos *q++ = prefix;
2728 1.7 christos *q = opcode + (arg.X_add_number == REG_IY ? 1 : 0);
2729 1.1 christos
2730 1.7 christos arg.X_op = O_symbol;
2731 1.7 christos arg.X_add_number = 0;
2732 1.7 christos emit_byte (& arg, BFD_RELOC_Z80_DISP8);
2733 1.1 christos
2734 1.7 christos return p;
2735 1.7 christos }
2736 1.1 christos
2737 1.7 christos static const char *
2738 1.7 christos emit_reti (char prefix, char opcode, const char * args)
2739 1.7 christos {
2740 1.7 christos if (ins_ok & INS_GBZ80)
2741 1.7 christos return emit_insn (0x00, 0xD9, args);
2742 1.1 christos
2743 1.7 christos return emit_insn (prefix, opcode, args);
2744 1.1 christos }
2745 1.1 christos
2746 1.1 christos static const char *
2747 1.7 christos emit_tst (char prefix, char opcode, const char *args)
2748 1.1 christos {
2749 1.7 christos expressionS arg_s;
2750 1.1 christos const char *p;
2751 1.1 christos char *q;
2752 1.7 christos int rnum;
2753 1.1 christos
2754 1.7 christos p = parse_exp (args, & arg_s);
2755 1.7 christos if (*p == ',' && arg_s.X_md == 0 && arg_s.X_op == O_register && arg_s.X_add_number == REG_A)
2756 1.7 christos {
2757 1.7 christos if (!(ins_ok & INS_EZ80))
2758 1.7 christos ill_op ();
2759 1.7 christos ++p;
2760 1.7 christos p = parse_exp (p, & arg_s);
2761 1.7 christos }
2762 1.1 christos
2763 1.7 christos rnum = arg_s.X_add_number;
2764 1.7 christos switch (arg_s.X_op)
2765 1.1 christos {
2766 1.1 christos case O_md1:
2767 1.7 christos ill_op ();
2768 1.1 christos break;
2769 1.1 christos case O_register:
2770 1.7 christos rnum = arg_s.X_add_number;
2771 1.7 christos if (arg_s.X_md != 0)
2772 1.7 christos {
2773 1.7 christos if (rnum != REG_HL)
2774 1.7 christos ill_op ();
2775 1.7 christos else
2776 1.7 christos rnum = 6;
2777 1.7 christos }
2778 1.7 christos q = frag_more (2);
2779 1.7 christos *q++ = prefix;
2780 1.7 christos *q = opcode | (rnum << 3);
2781 1.1 christos break;
2782 1.1 christos default:
2783 1.7 christos if (arg_s.X_md)
2784 1.7 christos ill_op ();
2785 1.7 christos q = frag_more (2);
2786 1.7 christos *q++ = prefix;
2787 1.7 christos *q = opcode | 0x60;
2788 1.7 christos emit_byte (& arg_s, BFD_RELOC_8);
2789 1.1 christos }
2790 1.1 christos return p;
2791 1.1 christos }
2792 1.1 christos
2793 1.7 christos static const char *
2794 1.7 christos emit_tstio (char prefix, char opcode, const char *args)
2795 1.7 christos {
2796 1.7 christos expressionS arg;
2797 1.7 christos const char *p;
2798 1.7 christos char *q;
2799 1.7 christos
2800 1.7 christos p = parse_exp (args, & arg);
2801 1.7 christos if (arg.X_md || arg.X_op == O_register || arg.X_op == O_md1)
2802 1.7 christos ill_op ();
2803 1.7 christos
2804 1.7 christos q = frag_more (2);
2805 1.7 christos *q++ = prefix;
2806 1.7 christos *q = opcode;
2807 1.7 christos emit_byte (& arg, BFD_RELOC_8);
2808 1.7 christos
2809 1.7 christos return p;
2810 1.7 christos }
2811 1.7 christos
2812 1.1 christos static void
2813 1.1 christos emit_data (int size ATTRIBUTE_UNUSED)
2814 1.1 christos {
2815 1.1 christos const char *p, *q;
2816 1.1 christos char *u, quote;
2817 1.1 christos int cnt;
2818 1.1 christos expressionS exp;
2819 1.1 christos
2820 1.1 christos if (is_it_end_of_statement ())
2821 1.1 christos {
2822 1.1 christos demand_empty_rest_of_line ();
2823 1.1 christos return;
2824 1.1 christos }
2825 1.1 christos p = skip_space (input_line_pointer);
2826 1.1 christos
2827 1.1 christos do
2828 1.1 christos {
2829 1.1 christos if (*p == '\"' || *p == '\'')
2830 1.1 christos {
2831 1.1 christos for (quote = *p, q = ++p, cnt = 0; *p && quote != *p; ++p, ++cnt)
2832 1.1 christos ;
2833 1.1 christos u = frag_more (cnt);
2834 1.1 christos memcpy (u, q, cnt);
2835 1.1 christos if (!*p)
2836 1.1 christos as_warn (_("unterminated string"));
2837 1.1 christos else
2838 1.1 christos p = skip_space (p+1);
2839 1.1 christos }
2840 1.1 christos else
2841 1.1 christos {
2842 1.1 christos p = parse_exp (p, &exp);
2843 1.1 christos if (exp.X_op == O_md1 || exp.X_op == O_register)
2844 1.1 christos {
2845 1.1 christos ill_op ();
2846 1.1 christos break;
2847 1.1 christos }
2848 1.1 christos if (exp.X_md)
2849 1.1 christos as_warn (_("parentheses ignored"));
2850 1.1 christos emit_byte (&exp, BFD_RELOC_8);
2851 1.1 christos p = skip_space (p);
2852 1.1 christos }
2853 1.1 christos }
2854 1.1 christos while (*p++ == ',') ;
2855 1.1 christos input_line_pointer = (char *)(p-1);
2856 1.1 christos }
2857 1.1 christos
2858 1.7 christos static void
2859 1.7 christos z80_cons (int size)
2860 1.7 christos {
2861 1.7 christos const char *p;
2862 1.7 christos expressionS exp;
2863 1.7 christos
2864 1.7 christos if (is_it_end_of_statement ())
2865 1.7 christos {
2866 1.7 christos demand_empty_rest_of_line ();
2867 1.7 christos return;
2868 1.7 christos }
2869 1.7 christos p = skip_space (input_line_pointer);
2870 1.7 christos
2871 1.7 christos do
2872 1.7 christos {
2873 1.7 christos p = parse_exp (p, &exp);
2874 1.7 christos if (exp.X_op == O_md1 || exp.X_op == O_register)
2875 1.7 christos {
2876 1.7 christos ill_op ();
2877 1.7 christos break;
2878 1.7 christos }
2879 1.7 christos if (exp.X_md)
2880 1.7 christos as_warn (_("parentheses ignored"));
2881 1.7 christos emit_data_val (&exp, size);
2882 1.7 christos p = skip_space (p);
2883 1.7 christos } while (*p++ == ',') ;
2884 1.7 christos input_line_pointer = (char *)(p-1);
2885 1.7 christos }
2886 1.7 christos
2887 1.7 christos /* next functions were commented out because it is difficult to mix
2888 1.7 christos both ADL and Z80 mode instructions within one COFF file:
2889 1.7 christos objdump cannot recognize point of mode switching.
2890 1.7 christos */
2891 1.7 christos static void
2892 1.7 christos set_cpu_mode (int mode)
2893 1.7 christos {
2894 1.7 christos if (ins_ok & INS_EZ80)
2895 1.7 christos cpu_mode = mode;
2896 1.7 christos else
2897 1.7 christos error (_("CPU mode is unsupported by target"));
2898 1.7 christos }
2899 1.7 christos
2900 1.7 christos static void
2901 1.7 christos assume (int arg ATTRIBUTE_UNUSED)
2902 1.7 christos {
2903 1.7 christos char *name;
2904 1.7 christos char c;
2905 1.7 christos int n;
2906 1.7 christos
2907 1.7 christos input_line_pointer = (char*)skip_space (input_line_pointer);
2908 1.7 christos c = get_symbol_name (& name);
2909 1.7 christos if (strncasecmp (name, "ADL", 4) != 0)
2910 1.7 christos {
2911 1.7 christos ill_op ();
2912 1.7 christos return;
2913 1.7 christos }
2914 1.7 christos
2915 1.7 christos restore_line_pointer (c);
2916 1.7 christos input_line_pointer = (char*)skip_space (input_line_pointer);
2917 1.7 christos if (*input_line_pointer++ != '=')
2918 1.7 christos {
2919 1.7 christos error (_("assignment expected"));
2920 1.7 christos return;
2921 1.7 christos }
2922 1.7 christos input_line_pointer = (char*)skip_space (input_line_pointer);
2923 1.7 christos n = get_single_number ();
2924 1.7 christos
2925 1.7 christos set_cpu_mode (n);
2926 1.7 christos }
2927 1.7 christos
2928 1.1 christos static const char *
2929 1.1 christos emit_mulub (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
2930 1.1 christos {
2931 1.1 christos const char *p;
2932 1.1 christos
2933 1.1 christos p = skip_space (args);
2934 1.1 christos if (TOLOWER (*p++) != 'a' || *p++ != ',')
2935 1.1 christos ill_op ();
2936 1.1 christos else
2937 1.1 christos {
2938 1.1 christos char *q, reg;
2939 1.1 christos
2940 1.1 christos reg = TOLOWER (*p++);
2941 1.1 christos switch (reg)
2942 1.1 christos {
2943 1.1 christos case 'b':
2944 1.1 christos case 'c':
2945 1.1 christos case 'd':
2946 1.1 christos case 'e':
2947 1.1 christos check_mach (INS_R800);
2948 1.1 christos if (!*skip_space (p))
2949 1.1 christos {
2950 1.1 christos q = frag_more (2);
2951 1.1 christos *q++ = prefix;
2952 1.1 christos *q = opcode + ((reg - 'b') << 3);
2953 1.1 christos break;
2954 1.1 christos }
2955 1.6 christos /* Fall through. */
2956 1.1 christos default:
2957 1.1 christos ill_op ();
2958 1.1 christos }
2959 1.1 christos }
2960 1.1 christos return p;
2961 1.1 christos }
2962 1.1 christos
2963 1.1 christos static const char *
2964 1.1 christos emit_muluw (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
2965 1.1 christos {
2966 1.1 christos const char *p;
2967 1.1 christos
2968 1.1 christos p = skip_space (args);
2969 1.1 christos if (TOLOWER (*p++) != 'h' || TOLOWER (*p++) != 'l' || *p++ != ',')
2970 1.1 christos ill_op ();
2971 1.1 christos else
2972 1.1 christos {
2973 1.1 christos expressionS reg;
2974 1.1 christos char *q;
2975 1.1 christos
2976 1.1 christos p = parse_exp (p, & reg);
2977 1.1 christos
2978 1.1 christos if ((!reg.X_md) && reg.X_op == O_register)
2979 1.1 christos switch (reg.X_add_number)
2980 1.1 christos {
2981 1.1 christos case REG_BC:
2982 1.1 christos case REG_SP:
2983 1.1 christos check_mach (INS_R800);
2984 1.1 christos q = frag_more (2);
2985 1.1 christos *q++ = prefix;
2986 1.1 christos *q = opcode + ((reg.X_add_number & 3) << 4);
2987 1.1 christos break;
2988 1.1 christos default:
2989 1.1 christos ill_op ();
2990 1.1 christos }
2991 1.1 christos }
2992 1.1 christos return p;
2993 1.1 christos }
2994 1.1 christos
2995 1.7 christos static int
2996 1.7 christos assemble_suffix (const char **suffix)
2997 1.7 christos {
2998 1.7 christos static
2999 1.7 christos const char sf[8][4] =
3000 1.7 christos {
3001 1.7 christos "il",
3002 1.7 christos "is",
3003 1.7 christos "l",
3004 1.7 christos "lil",
3005 1.7 christos "lis",
3006 1.7 christos "s",
3007 1.7 christos "sil",
3008 1.7 christos "sis"
3009 1.7 christos };
3010 1.7 christos const char *p;
3011 1.7 christos const char (*t)[4];
3012 1.7 christos char sbuf[4];
3013 1.7 christos int i;
3014 1.7 christos
3015 1.7 christos p = *suffix;
3016 1.7 christos if (*p++ != '.')
3017 1.7 christos return 0;
3018 1.7 christos
3019 1.7 christos for (i = 0; (i < 3) && (ISALPHA (*p)); i++)
3020 1.7 christos sbuf[i] = TOLOWER (*p++);
3021 1.7 christos if (*p && !ISSPACE (*p))
3022 1.7 christos return 0;
3023 1.7 christos *suffix = p;
3024 1.7 christos sbuf[i] = 0;
3025 1.7 christos
3026 1.7 christos t = bsearch (sbuf, sf, ARRAY_SIZE (sf), sizeof (sf[0]), (int(*)(const void*, const void*)) strcmp);
3027 1.7 christos if (t == NULL)
3028 1.7 christos return 0;
3029 1.7 christos i = t - sf;
3030 1.7 christos switch (i)
3031 1.7 christos {
3032 1.7 christos case 0: /* IL */
3033 1.7 christos i = cpu_mode ? 0x5B : 0x52;
3034 1.7 christos break;
3035 1.7 christos case 1: /* IS */
3036 1.7 christos i = cpu_mode ? 0x49 : 0x40;
3037 1.7 christos break;
3038 1.7 christos case 2: /* L */
3039 1.7 christos i = cpu_mode ? 0x5B : 0x49;
3040 1.7 christos break;
3041 1.7 christos case 3: /* LIL */
3042 1.7 christos i = 0x5B;
3043 1.7 christos break;
3044 1.7 christos case 4: /* LIS */
3045 1.7 christos i = 0x49;
3046 1.7 christos break;
3047 1.7 christos case 5: /* S */
3048 1.7 christos i = cpu_mode ? 0x52 : 0x40;
3049 1.7 christos break;
3050 1.7 christos case 6: /* SIL */
3051 1.7 christos i = 0x52;
3052 1.7 christos break;
3053 1.7 christos case 7: /* SIS */
3054 1.7 christos i = 0x40;
3055 1.7 christos break;
3056 1.7 christos }
3057 1.7 christos *frag_more (1) = (char)i;
3058 1.7 christos switch (i)
3059 1.7 christos {
3060 1.7 christos case 0x40: inst_mode = INST_MODE_FORCED | INST_MODE_S | INST_MODE_IS; break;
3061 1.7 christos case 0x49: inst_mode = INST_MODE_FORCED | INST_MODE_L | INST_MODE_IS; break;
3062 1.7 christos case 0x52: inst_mode = INST_MODE_FORCED | INST_MODE_S | INST_MODE_IL; break;
3063 1.7 christos case 0x5B: inst_mode = INST_MODE_FORCED | INST_MODE_L | INST_MODE_IL; break;
3064 1.7 christos }
3065 1.7 christos return 1;
3066 1.7 christos }
3067 1.7 christos
3068 1.7 christos static void
3069 1.7 christos psect (int arg)
3070 1.7 christos {
3071 1.7 christos #if defined(OBJ_ELF)
3072 1.7 christos return obj_elf_section (arg);
3073 1.7 christos #elif defined(OBJ_COFF)
3074 1.7 christos return obj_coff_section (arg);
3075 1.7 christos #else
3076 1.7 christos #error Unknown object format
3077 1.7 christos #endif
3078 1.7 christos }
3079 1.7 christos
3080 1.7 christos static void
3081 1.7 christos set_inss (int inss)
3082 1.7 christos {
3083 1.7 christos int old_ins;
3084 1.7 christos
3085 1.7 christos if (!sdcc_compat)
3086 1.7 christos as_fatal (_("Invalid directive"));
3087 1.7 christos
3088 1.7 christos old_ins = ins_ok;
3089 1.7 christos ins_ok &= INS_MARCH_MASK;
3090 1.7 christos ins_ok |= inss;
3091 1.7 christos if (old_ins != ins_ok)
3092 1.7 christos cpu_mode = 0;
3093 1.7 christos }
3094 1.7 christos
3095 1.7 christos static void
3096 1.7 christos ignore (int arg ATTRIBUTE_UNUSED)
3097 1.7 christos {
3098 1.7 christos ignore_rest_of_line ();
3099 1.7 christos }
3100 1.7 christos
3101 1.7 christos static void
3102 1.7 christos area (int arg)
3103 1.7 christos {
3104 1.7 christos char *p;
3105 1.7 christos if (!sdcc_compat)
3106 1.7 christos as_fatal (_("Invalid directive"));
3107 1.7 christos for (p = input_line_pointer; *p && *p != '(' && *p != '\n'; p++)
3108 1.7 christos ;
3109 1.7 christos if (*p == '(')
3110 1.7 christos {
3111 1.7 christos *p = '\n';
3112 1.7 christos psect (arg);
3113 1.7 christos *p++ = '(';
3114 1.7 christos ignore_rest_of_line ();
3115 1.7 christos }
3116 1.7 christos else
3117 1.7 christos psect (arg);
3118 1.7 christos }
3119 1.7 christos
3120 1.1 christos /* Port specific pseudo ops. */
3121 1.1 christos const pseudo_typeS md_pseudo_table[] =
3122 1.1 christos {
3123 1.7 christos { ".area", area, 0},
3124 1.7 christos { ".assume", assume, 0},
3125 1.7 christos { ".ez80", set_inss, INS_EZ80},
3126 1.7 christos { ".gbz80", set_inss, INS_GBZ80},
3127 1.7 christos { ".module", ignore, 0},
3128 1.7 christos { ".optsdcc", ignore, 0},
3129 1.7 christos { ".r800", set_inss, INS_R800},
3130 1.7 christos { ".set", s_set, 0},
3131 1.7 christos { ".z180", set_inss, INS_Z180},
3132 1.7 christos { ".z80", set_inss, INS_Z80},
3133 1.1 christos { "db" , emit_data, 1},
3134 1.7 christos { "d24", z80_cons, 3},
3135 1.7 christos { "d32", z80_cons, 4},
3136 1.7 christos { "def24", z80_cons, 3},
3137 1.7 christos { "def32", z80_cons, 4},
3138 1.3 christos { "defb", emit_data, 1},
3139 1.7 christos { "defm", emit_data, 1},
3140 1.1 christos { "defs", s_space, 1}, /* Synonym for ds on some assemblers. */
3141 1.7 christos { "defw", z80_cons, 2},
3142 1.1 christos { "ds", s_space, 1}, /* Fill with bytes rather than words. */
3143 1.7 christos { "dw", z80_cons, 2},
3144 1.7 christos { "psect", psect, 0}, /* TODO: Translate attributes. */
3145 1.1 christos { "set", 0, 0}, /* Real instruction on z80. */
3146 1.1 christos { NULL, 0, 0 }
3147 1.1 christos } ;
3148 1.1 christos
3149 1.1 christos static table_t instab[] =
3150 1.1 christos {
3151 1.7 christos { "adc", 0x88, 0x4A, emit_adc, INS_ALL },
3152 1.7 christos { "add", 0x80, 0x09, emit_add, INS_ALL },
3153 1.7 christos { "and", 0x00, 0xA0, emit_s, INS_ALL },
3154 1.7 christos { "bit", 0xCB, 0x40, emit_bit, INS_ALL },
3155 1.7 christos { "call", 0xCD, 0xC4, emit_jpcc, INS_ALL },
3156 1.7 christos { "ccf", 0x00, 0x3F, emit_insn, INS_ALL },
3157 1.7 christos { "cp", 0x00, 0xB8, emit_s, INS_ALL },
3158 1.7 christos { "cpd", 0xED, 0xA9, emit_insn, INS_NOT_GBZ80 },
3159 1.7 christos { "cpdr", 0xED, 0xB9, emit_insn, INS_NOT_GBZ80 },
3160 1.7 christos { "cpi", 0xED, 0xA1, emit_insn, INS_NOT_GBZ80 },
3161 1.7 christos { "cpir", 0xED, 0xB1, emit_insn, INS_NOT_GBZ80 },
3162 1.7 christos { "cpl", 0x00, 0x2F, emit_insn, INS_ALL },
3163 1.7 christos { "daa", 0x00, 0x27, emit_insn, INS_ALL },
3164 1.7 christos { "dec", 0x0B, 0x05, emit_incdec,INS_ALL },
3165 1.7 christos { "di", 0x00, 0xF3, emit_insn, INS_ALL },
3166 1.7 christos { "djnz", 0x00, 0x10, emit_jr, INS_NOT_GBZ80 },
3167 1.7 christos { "ei", 0x00, 0xFB, emit_insn, INS_ALL },
3168 1.7 christos { "ex", 0x00, 0x00, emit_ex, INS_NOT_GBZ80 },
3169 1.7 christos { "exx", 0x00, 0xD9, emit_insn, INS_NOT_GBZ80 },
3170 1.7 christos { "halt", 0x00, 0x76, emit_insn, INS_ALL },
3171 1.7 christos { "im", 0xED, 0x46, emit_im, INS_NOT_GBZ80 },
3172 1.7 christos { "in", 0x00, 0x00, emit_in, INS_NOT_GBZ80 },
3173 1.7 christos { "in0", 0xED, 0x00, emit_in0, INS_Z180|INS_EZ80 },
3174 1.7 christos { "inc", 0x03, 0x04, emit_incdec,INS_ALL },
3175 1.7 christos { "ind", 0xED, 0xAA, emit_insn, INS_NOT_GBZ80 },
3176 1.7 christos { "ind2", 0xED, 0x8C, emit_insn, INS_EZ80 },
3177 1.7 christos { "ind2r",0xED, 0x9C, emit_insn, INS_EZ80 },
3178 1.7 christos { "indm", 0xED, 0x8A, emit_insn, INS_EZ80 },
3179 1.7 christos { "indmr",0xED, 0x9A, emit_insn, INS_EZ80 },
3180 1.7 christos { "indr", 0xED, 0xBA, emit_insn, INS_NOT_GBZ80 },
3181 1.7 christos { "indrx",0xED, 0xCA, emit_insn, INS_EZ80 },
3182 1.7 christos { "ini", 0xED, 0xA2, emit_insn, INS_NOT_GBZ80 },
3183 1.7 christos { "ini2", 0xED, 0x84, emit_insn, INS_EZ80 },
3184 1.7 christos { "ini2r",0xED, 0x94, emit_insn, INS_EZ80 },
3185 1.7 christos { "inim", 0xED, 0x82, emit_insn, INS_EZ80 },
3186 1.7 christos { "inimr",0xED, 0x92, emit_insn, INS_EZ80 },
3187 1.7 christos { "inir", 0xED, 0xB2, emit_insn, INS_NOT_GBZ80 },
3188 1.7 christos { "inirx",0xED, 0xC2, emit_insn, INS_EZ80 },
3189 1.7 christos { "jp", 0xC3, 0xC2, emit_jpcc, INS_ALL },
3190 1.7 christos { "jr", 0x18, 0x20, emit_jrcc, INS_ALL },
3191 1.7 christos { "ld", 0x00, 0x00, emit_ld, INS_ALL },
3192 1.7 christos { "ldd", 0xED, 0xA8, emit_lddldi,INS_ALL }, /* GBZ80 has special meaning */
3193 1.7 christos { "lddr", 0xED, 0xB8, emit_insn, INS_NOT_GBZ80 },
3194 1.7 christos { "ldh", 0xE0, 0x00, emit_ldh, INS_GBZ80 },
3195 1.7 christos { "ldhl", 0xE0, 0x00, emit_ldh, INS_GBZ80 },
3196 1.7 christos { "ldi", 0xED, 0xA0, emit_lddldi,INS_ALL }, /* GBZ80 has special meaning */
3197 1.7 christos { "ldir", 0xED, 0xB0, emit_insn, INS_NOT_GBZ80 },
3198 1.7 christos { "lea", 0xED, 0x02, emit_lea, INS_EZ80 },
3199 1.7 christos { "mlt", 0xED, 0x4C, emit_mlt, INS_Z180|INS_EZ80 },
3200 1.7 christos { "mulub",0xED, 0xC5, emit_mulub,INS_R800 },
3201 1.7 christos { "muluw",0xED, 0xC3, emit_muluw,INS_R800 },
3202 1.7 christos { "neg", 0xed, 0x44, emit_insn, INS_NOT_GBZ80 },
3203 1.7 christos { "nop", 0x00, 0x00, emit_insn, INS_ALL },
3204 1.7 christos { "or", 0x00, 0xB0, emit_s, INS_ALL },
3205 1.7 christos { "otd2r",0xED, 0xBC, emit_insn, INS_EZ80 },
3206 1.7 christos { "otdm", 0xED, 0x8B, emit_insn, INS_Z180|INS_EZ80 },
3207 1.7 christos { "otdmr",0xED, 0x9B, emit_insn, INS_Z180|INS_EZ80 },
3208 1.7 christos { "otdr", 0xED, 0xBB, emit_insn, INS_NOT_GBZ80 },
3209 1.7 christos { "otdrx",0xED, 0xCB, emit_insn, INS_EZ80 },
3210 1.7 christos { "oti2r",0xED, 0xB4, emit_insn, INS_EZ80 },
3211 1.7 christos { "otim", 0xED, 0x83, emit_insn, INS_Z180|INS_EZ80 },
3212 1.7 christos { "otimr",0xED, 0x93, emit_insn, INS_Z180|INS_EZ80 },
3213 1.7 christos { "otir", 0xED, 0xB3, emit_insn, INS_NOT_GBZ80 },
3214 1.7 christos { "otirx",0xED, 0xC3, emit_insn, INS_EZ80 },
3215 1.7 christos { "out", 0x00, 0x00, emit_out, INS_NOT_GBZ80 },
3216 1.7 christos { "out0", 0xED, 0x01, emit_out0, INS_Z180|INS_EZ80 },
3217 1.7 christos { "outd", 0xED, 0xAB, emit_insn, INS_NOT_GBZ80 },
3218 1.7 christos { "outd2",0xED, 0xAC, emit_insn, INS_EZ80 },
3219 1.7 christos { "outi", 0xED, 0xA3, emit_insn, INS_NOT_GBZ80 },
3220 1.7 christos { "outi2",0xED, 0xA4, emit_insn, INS_EZ80 },
3221 1.7 christos { "pea", 0xED, 0x65, emit_pea, INS_EZ80 },
3222 1.7 christos { "pop", 0x00, 0xC1, emit_pop, INS_ALL },
3223 1.7 christos { "push", 0x00, 0xC5, emit_pop, INS_ALL },
3224 1.7 christos { "res", 0xCB, 0x80, emit_bit, INS_ALL },
3225 1.7 christos { "ret", 0xC9, 0xC0, emit_retcc,INS_ALL },
3226 1.7 christos { "reti", 0xED, 0x4D, emit_reti, INS_ALL }, /*GBZ80 has its own opcode for it*/
3227 1.7 christos { "retn", 0xED, 0x45, emit_insn, INS_NOT_GBZ80 },
3228 1.7 christos { "rl", 0xCB, 0x10, emit_mr, INS_ALL },
3229 1.7 christos { "rla", 0x00, 0x17, emit_insn, INS_ALL },
3230 1.7 christos { "rlc", 0xCB, 0x00, emit_mr, INS_ALL },
3231 1.7 christos { "rlca", 0x00, 0x07, emit_insn, INS_ALL },
3232 1.7 christos { "rld", 0xED, 0x6F, emit_insn, INS_NOT_GBZ80 },
3233 1.7 christos { "rr", 0xCB, 0x18, emit_mr, INS_ALL },
3234 1.7 christos { "rra", 0x00, 0x1F, emit_insn, INS_ALL },
3235 1.7 christos { "rrc", 0xCB, 0x08, emit_mr, INS_ALL },
3236 1.7 christos { "rrca", 0x00, 0x0F, emit_insn, INS_ALL },
3237 1.7 christos { "rrd", 0xED, 0x67, emit_insn, INS_NOT_GBZ80 },
3238 1.7 christos { "rsmix",0xED, 0x7E, emit_insn, INS_EZ80 },
3239 1.7 christos { "rst", 0x00, 0xC7, emit_rst, INS_ALL },
3240 1.7 christos { "sbc", 0x98, 0x42, emit_adc, INS_ALL },
3241 1.7 christos { "scf", 0x00, 0x37, emit_insn, INS_ALL },
3242 1.7 christos { "set", 0xCB, 0xC0, emit_bit, INS_ALL },
3243 1.7 christos { "sla", 0xCB, 0x20, emit_mr, INS_ALL },
3244 1.7 christos { "sli", 0xCB, 0x30, emit_mr, INS_SLI },
3245 1.7 christos { "sll", 0xCB, 0x30, emit_mr, INS_SLI },
3246 1.7 christos { "slp", 0xED, 0x76, emit_insn, INS_Z180|INS_EZ80 },
3247 1.7 christos { "sra", 0xCB, 0x28, emit_mr, INS_ALL },
3248 1.7 christos { "srl", 0xCB, 0x38, emit_mr, INS_ALL },
3249 1.7 christos { "stmix",0xED, 0x7D, emit_insn, INS_EZ80 },
3250 1.7 christos { "stop", 0x00, 0x10, emit_insn, INS_GBZ80 },
3251 1.7 christos { "sub", 0x00, 0x90, emit_s, INS_ALL },
3252 1.7 christos { "swap", 0xCB, 0x30, emit_mr, INS_GBZ80 },
3253 1.7 christos { "tst", 0xED, 0x04, emit_tst, INS_Z180|INS_EZ80 },
3254 1.7 christos { "tstio",0xED, 0x74, emit_tstio,INS_Z180|INS_EZ80 },
3255 1.7 christos { "xor", 0x00, 0xA8, emit_s, INS_ALL },
3256 1.1 christos } ;
3257 1.1 christos
3258 1.1 christos void
3259 1.7 christos md_assemble (char *str)
3260 1.1 christos {
3261 1.1 christos const char *p;
3262 1.1 christos char * old_ptr;
3263 1.1 christos int i;
3264 1.1 christos table_t *insp;
3265 1.1 christos
3266 1.1 christos err_flag = 0;
3267 1.7 christos inst_mode = cpu_mode ? (INST_MODE_L | INST_MODE_IL) : (INST_MODE_S | INST_MODE_IS);
3268 1.1 christos old_ptr = input_line_pointer;
3269 1.1 christos p = skip_space (str);
3270 1.7 christos for (i = 0; (i < BUFLEN) && (ISALPHA (*p) || ISDIGIT (*p));)
3271 1.1 christos buf[i++] = TOLOWER (*p++);
3272 1.1 christos
3273 1.1 christos if (i == BUFLEN)
3274 1.1 christos {
3275 1.1 christos buf[BUFLEN-3] = buf[BUFLEN-2] = '.'; /* Mark opcode as abbreviated. */
3276 1.1 christos buf[BUFLEN-1] = 0;
3277 1.1 christos as_bad (_("Unknown instruction '%s'"), buf);
3278 1.1 christos }
3279 1.3 christos else
3280 1.1 christos {
3281 1.7 christos dwarf2_emit_insn (0);
3282 1.7 christos if ((*p) && (!ISSPACE (*p)))
3283 1.7 christos {
3284 1.7 christos if (*p != '.' || !(ins_ok & INS_EZ80) || !assemble_suffix (&p))
3285 1.7 christos {
3286 1.7 christos as_bad (_("syntax error"));
3287 1.7 christos goto end;
3288 1.7 christos }
3289 1.7 christos }
3290 1.1 christos buf[i] = 0;
3291 1.1 christos p = skip_space (p);
3292 1.1 christos key = buf;
3293 1.3 christos
3294 1.1 christos insp = bsearch (&key, instab, ARRAY_SIZE (instab),
3295 1.1 christos sizeof (instab[0]), key_cmp);
3296 1.7 christos if (!insp || (insp->inss && !(insp->inss & ins_ok)))
3297 1.7 christos {
3298 1.7 christos as_bad (_("Unknown instruction '%s'"), buf);
3299 1.7 christos *frag_more (1) = 0;
3300 1.7 christos }
3301 1.1 christos else
3302 1.1 christos {
3303 1.1 christos p = insp->fp (insp->prefix, insp->opcode, p);
3304 1.1 christos p = skip_space (p);
3305 1.1 christos if ((!err_flag) && *p)
3306 1.1 christos as_bad (_("junk at end of line, first unrecognized character is `%c'"),
3307 1.1 christos *p);
3308 1.1 christos }
3309 1.1 christos }
3310 1.7 christos end:
3311 1.1 christos input_line_pointer = old_ptr;
3312 1.1 christos }
3313 1.1 christos
3314 1.1 christos void
3315 1.1 christos md_apply_fix (fixS * fixP, valueT* valP, segT seg ATTRIBUTE_UNUSED)
3316 1.1 christos {
3317 1.1 christos long val = * (long *) valP;
3318 1.1 christos char *p_lit = fixP->fx_where + fixP->fx_frag->fr_literal;
3319 1.1 christos
3320 1.1 christos switch (fixP->fx_r_type)
3321 1.1 christos {
3322 1.1 christos case BFD_RELOC_8_PCREL:
3323 1.1 christos if (fixP->fx_addsy)
3324 1.1 christos {
3325 1.1 christos fixP->fx_no_overflow = 1;
3326 1.1 christos fixP->fx_done = 0;
3327 1.1 christos }
3328 1.1 christos else
3329 1.1 christos {
3330 1.1 christos fixP->fx_no_overflow = (-128 <= val && val < 128);
3331 1.1 christos if (!fixP->fx_no_overflow)
3332 1.1 christos as_bad_where (fixP->fx_file, fixP->fx_line,
3333 1.1 christos _("relative jump out of range"));
3334 1.1 christos *p_lit++ = val;
3335 1.1 christos fixP->fx_done = 1;
3336 1.1 christos }
3337 1.1 christos break;
3338 1.1 christos
3339 1.1 christos case BFD_RELOC_Z80_DISP8:
3340 1.1 christos if (fixP->fx_addsy)
3341 1.1 christos {
3342 1.1 christos fixP->fx_no_overflow = 1;
3343 1.1 christos fixP->fx_done = 0;
3344 1.1 christos }
3345 1.1 christos else
3346 1.1 christos {
3347 1.1 christos fixP->fx_no_overflow = (-128 <= val && val < 128);
3348 1.1 christos if (!fixP->fx_no_overflow)
3349 1.1 christos as_bad_where (fixP->fx_file, fixP->fx_line,
3350 1.6 christos _("index offset out of range"));
3351 1.1 christos *p_lit++ = val;
3352 1.1 christos fixP->fx_done = 1;
3353 1.1 christos }
3354 1.1 christos break;
3355 1.1 christos
3356 1.7 christos case BFD_RELOC_Z80_BYTE0:
3357 1.7 christos *p_lit++ = val;
3358 1.7 christos fixP->fx_no_overflow = 1;
3359 1.7 christos if (fixP->fx_addsy == NULL)
3360 1.7 christos fixP->fx_done = 1;
3361 1.7 christos break;
3362 1.7 christos
3363 1.7 christos case BFD_RELOC_Z80_BYTE1:
3364 1.7 christos *p_lit++ = (val >> 8);
3365 1.7 christos fixP->fx_no_overflow = 1;
3366 1.7 christos if (fixP->fx_addsy == NULL)
3367 1.7 christos fixP->fx_done = 1;
3368 1.7 christos break;
3369 1.7 christos
3370 1.7 christos case BFD_RELOC_Z80_BYTE2:
3371 1.7 christos *p_lit++ = (val >> 16);
3372 1.7 christos fixP->fx_no_overflow = 1;
3373 1.7 christos if (fixP->fx_addsy == NULL)
3374 1.7 christos fixP->fx_done = 1;
3375 1.7 christos break;
3376 1.7 christos
3377 1.7 christos case BFD_RELOC_Z80_BYTE3:
3378 1.7 christos *p_lit++ = (val >> 24);
3379 1.7 christos fixP->fx_no_overflow = 1;
3380 1.7 christos if (fixP->fx_addsy == NULL)
3381 1.7 christos fixP->fx_done = 1;
3382 1.7 christos break;
3383 1.7 christos
3384 1.1 christos case BFD_RELOC_8:
3385 1.1 christos if (val > 255 || val < -128)
3386 1.1 christos as_warn_where (fixP->fx_file, fixP->fx_line, _("overflow"));
3387 1.1 christos *p_lit++ = val;
3388 1.3 christos fixP->fx_no_overflow = 1;
3389 1.1 christos if (fixP->fx_addsy == NULL)
3390 1.1 christos fixP->fx_done = 1;
3391 1.1 christos break;
3392 1.1 christos
3393 1.7 christos case BFD_RELOC_Z80_WORD1:
3394 1.7 christos *p_lit++ = (val >> 16);
3395 1.7 christos *p_lit++ = (val >> 24);
3396 1.7 christos fixP->fx_no_overflow = 1;
3397 1.7 christos if (fixP->fx_addsy == NULL)
3398 1.7 christos fixP->fx_done = 1;
3399 1.7 christos break;
3400 1.7 christos
3401 1.7 christos case BFD_RELOC_Z80_WORD0:
3402 1.1 christos case BFD_RELOC_16:
3403 1.1 christos *p_lit++ = val;
3404 1.1 christos *p_lit++ = (val >> 8);
3405 1.3 christos fixP->fx_no_overflow = 1;
3406 1.1 christos if (fixP->fx_addsy == NULL)
3407 1.1 christos fixP->fx_done = 1;
3408 1.1 christos break;
3409 1.1 christos
3410 1.1 christos case BFD_RELOC_24: /* Def24 may produce this. */
3411 1.1 christos *p_lit++ = val;
3412 1.1 christos *p_lit++ = (val >> 8);
3413 1.1 christos *p_lit++ = (val >> 16);
3414 1.3 christos fixP->fx_no_overflow = 1;
3415 1.1 christos if (fixP->fx_addsy == NULL)
3416 1.1 christos fixP->fx_done = 1;
3417 1.1 christos break;
3418 1.1 christos
3419 1.1 christos case BFD_RELOC_32: /* Def32 and .long may produce this. */
3420 1.1 christos *p_lit++ = val;
3421 1.1 christos *p_lit++ = (val >> 8);
3422 1.1 christos *p_lit++ = (val >> 16);
3423 1.1 christos *p_lit++ = (val >> 24);
3424 1.1 christos if (fixP->fx_addsy == NULL)
3425 1.1 christos fixP->fx_done = 1;
3426 1.1 christos break;
3427 1.1 christos
3428 1.1 christos default:
3429 1.1 christos printf (_("md_apply_fix: unknown r_type 0x%x\n"), fixP->fx_r_type);
3430 1.1 christos abort ();
3431 1.1 christos }
3432 1.1 christos }
3433 1.1 christos
3434 1.1 christos /* GAS will call this to generate a reloc. GAS will pass the
3435 1.1 christos resulting reloc to `bfd_install_relocation'. This currently works
3436 1.1 christos poorly, as `bfd_install_relocation' often does the wrong thing, and
3437 1.1 christos instances of `tc_gen_reloc' have been written to work around the
3438 1.1 christos problems, which in turns makes it difficult to fix
3439 1.1 christos `bfd_install_relocation'. */
3440 1.1 christos
3441 1.1 christos /* If while processing a fixup, a reloc really
3442 1.1 christos needs to be created then it is done here. */
3443 1.1 christos
3444 1.1 christos arelent *
3445 1.1 christos tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED , fixS *fixp)
3446 1.1 christos {
3447 1.1 christos arelent *reloc;
3448 1.1 christos
3449 1.1 christos if (! bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type))
3450 1.1 christos {
3451 1.1 christos as_bad_where (fixp->fx_file, fixp->fx_line,
3452 1.1 christos _("reloc %d not supported by object file format"),
3453 1.1 christos (int) fixp->fx_r_type);
3454 1.1 christos return NULL;
3455 1.1 christos }
3456 1.1 christos
3457 1.5 christos reloc = XNEW (arelent);
3458 1.5 christos reloc->sym_ptr_ptr = XNEW (asymbol *);
3459 1.1 christos *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
3460 1.1 christos reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
3461 1.1 christos reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
3462 1.1 christos reloc->addend = fixp->fx_offset;
3463 1.1 christos
3464 1.1 christos return reloc;
3465 1.1 christos }
3466 1.7 christos
3467 1.7 christos int
3468 1.7 christos z80_tc_label_is_local (const char *name)
3469 1.7 christos {
3470 1.7 christos const char *n;
3471 1.7 christos const char *p;
3472 1.7 christos if (local_label_prefix == NULL)
3473 1.7 christos return 0;
3474 1.7 christos for (p = local_label_prefix, n = name; *p && *n && *n == *p; p++, n++)
3475 1.7 christos ;
3476 1.7 christos return *p == '\0';
3477 1.7 christos }
3478 1.7 christos
3479 1.7 christos /* Parse floating point number from string and compute mantissa and
3480 1.7 christos exponent. Mantissa is normalized.
3481 1.7 christos */
3482 1.7 christos #define EXP_MIN -0x10000
3483 1.7 christos #define EXP_MAX 0x10000
3484 1.7 christos static int
3485 1.7 christos str_to_broken_float (bfd_boolean *signP, bfd_uint64_t *mantissaP, int *expP)
3486 1.7 christos {
3487 1.7 christos char *p;
3488 1.7 christos bfd_boolean sign;
3489 1.7 christos bfd_uint64_t mantissa = 0;
3490 1.7 christos int exponent = 0;
3491 1.7 christos int i;
3492 1.7 christos
3493 1.7 christos p = (char*)skip_space (input_line_pointer);
3494 1.7 christos sign = (*p == '-');
3495 1.7 christos *signP = sign;
3496 1.7 christos if (sign || *p == '+')
3497 1.7 christos ++p;
3498 1.7 christos if (strncasecmp (p, "NaN", 3) == 0)
3499 1.7 christos {
3500 1.7 christos *mantissaP = 0;
3501 1.7 christos *expP = 0;
3502 1.7 christos input_line_pointer = p + 3;
3503 1.7 christos return 1;
3504 1.7 christos }
3505 1.7 christos if (strncasecmp (p, "inf", 3) == 0)
3506 1.7 christos {
3507 1.7 christos *mantissaP = 1ull << 63;
3508 1.7 christos *expP = EXP_MAX;
3509 1.7 christos input_line_pointer = p + 3;
3510 1.7 christos return 1;
3511 1.7 christos }
3512 1.7 christos for (; ISDIGIT (*p); ++p)
3513 1.7 christos {
3514 1.7 christos if (mantissa >> 60)
3515 1.7 christos {
3516 1.7 christos if (*p >= '5')
3517 1.7 christos mantissa++;
3518 1.7 christos break;
3519 1.7 christos }
3520 1.7 christos mantissa = mantissa * 10 + (*p - '0');
3521 1.7 christos }
3522 1.7 christos /* skip non-significant digits */
3523 1.7 christos for (; ISDIGIT (*p); ++p)
3524 1.7 christos exponent++;
3525 1.7 christos
3526 1.7 christos if (*p == '.')
3527 1.7 christos {
3528 1.7 christos p++;
3529 1.7 christos if (!exponent) /* If no precission overflow. */
3530 1.7 christos {
3531 1.7 christos for (; ISDIGIT (*p); ++p, --exponent)
3532 1.7 christos {
3533 1.7 christos if (mantissa >> 60)
3534 1.7 christos {
3535 1.7 christos if (*p >= '5')
3536 1.7 christos mantissa++;
3537 1.7 christos break;
3538 1.7 christos }
3539 1.7 christos mantissa = mantissa * 10 + (*p - '0');
3540 1.7 christos }
3541 1.7 christos }
3542 1.7 christos for (; ISDIGIT (*p); ++p)
3543 1.7 christos ;
3544 1.7 christos }
3545 1.7 christos if (*p == 'e' || *p == 'E')
3546 1.7 christos {
3547 1.7 christos int es;
3548 1.7 christos int t = 0;
3549 1.7 christos ++p;
3550 1.7 christos es = (*p == '-');
3551 1.7 christos if (es || *p == '+')
3552 1.7 christos p++;
3553 1.7 christos for (; ISDIGIT (*p); ++p)
3554 1.7 christos {
3555 1.7 christos if (t < 100)
3556 1.7 christos t = t * 10 + (*p - '0');
3557 1.7 christos }
3558 1.7 christos exponent += (es) ? -t : t;
3559 1.7 christos }
3560 1.7 christos if (ISALNUM (*p) || *p == '.')
3561 1.7 christos return 0;
3562 1.7 christos input_line_pointer = p;
3563 1.7 christos if (mantissa == 0)
3564 1.7 christos {
3565 1.7 christos *mantissaP = 1ull << 63;
3566 1.7 christos *expP = EXP_MIN;
3567 1.7 christos return 1; /* result is 0 */
3568 1.7 christos }
3569 1.7 christos /* normalization */
3570 1.7 christos for (; mantissa <= ~0ull/10; --exponent)
3571 1.7 christos mantissa *= 10;
3572 1.7 christos /* Now we have sign, mantissa, and signed decimal exponent
3573 1.7 christos need to recompute to binary exponent. */
3574 1.7 christos for (i = 64; exponent > 0; --exponent)
3575 1.7 christos {
3576 1.7 christos /* be sure that no integer overflow */
3577 1.7 christos while (mantissa > ~0ull/10)
3578 1.7 christos {
3579 1.7 christos mantissa >>= 1;
3580 1.7 christos i += 1;
3581 1.7 christos }
3582 1.7 christos mantissa *= 10;
3583 1.7 christos }
3584 1.7 christos for (; exponent < 0; ++exponent)
3585 1.7 christos {
3586 1.7 christos while (!(mantissa >> 63))
3587 1.7 christos {
3588 1.7 christos mantissa <<= 1;
3589 1.7 christos i -= 1;
3590 1.7 christos }
3591 1.7 christos mantissa /= 10;
3592 1.7 christos }
3593 1.7 christos /* normalization */
3594 1.7 christos for (; !(mantissa >> 63); --i)
3595 1.7 christos mantissa <<= 1;
3596 1.7 christos *mantissaP = mantissa;
3597 1.7 christos *expP = i;
3598 1.7 christos return 1;
3599 1.7 christos }
3600 1.7 christos
3601 1.7 christos static const char *
3602 1.7 christos str_to_zeda32(char *litP, int *sizeP)
3603 1.7 christos {
3604 1.7 christos bfd_uint64_t mantissa;
3605 1.7 christos bfd_boolean sign;
3606 1.7 christos int exponent;
3607 1.7 christos unsigned i;
3608 1.7 christos
3609 1.7 christos *sizeP = 4;
3610 1.7 christos if (!str_to_broken_float (&sign, &mantissa, &exponent))
3611 1.7 christos return _("invalid syntax");
3612 1.7 christos /* I do not know why decrement is needed */
3613 1.7 christos --exponent;
3614 1.7 christos /* shift by 39 bits right keeping 25 bit mantissa for rounding */
3615 1.7 christos mantissa >>= 39;
3616 1.7 christos /* do rounding */
3617 1.7 christos ++mantissa;
3618 1.7 christos /* make 24 bit mantissa */
3619 1.7 christos mantissa >>= 1;
3620 1.7 christos /* check for overflow */
3621 1.7 christos if (mantissa >> 24)
3622 1.7 christos {
3623 1.7 christos mantissa >>= 1;
3624 1.7 christos ++exponent;
3625 1.7 christos }
3626 1.7 christos /* check for 0 */
3627 1.7 christos if (exponent < -127)
3628 1.7 christos {
3629 1.7 christos exponent = -128;
3630 1.7 christos mantissa = 0;
3631 1.7 christos }
3632 1.7 christos else if (exponent > 127)
3633 1.7 christos {
3634 1.7 christos exponent = -128;
3635 1.7 christos mantissa = sign ? 0xc00000 : 0x400000;
3636 1.7 christos }
3637 1.7 christos else if (mantissa == 0)
3638 1.7 christos {
3639 1.7 christos exponent = -128;
3640 1.7 christos mantissa = 0x200000;
3641 1.7 christos }
3642 1.7 christos else if (!sign)
3643 1.7 christos mantissa &= (1ull << 23) - 1;
3644 1.7 christos for (i = 0; i < 24; i += 8)
3645 1.7 christos *litP++ = (char)(mantissa >> i);
3646 1.7 christos *litP = (char)(0x80 + exponent);
3647 1.7 christos return NULL;
3648 1.7 christos }
3649 1.7 christos
3650 1.7 christos /*
3651 1.7 christos Math48 by Anders Hejlsberg support.
3652 1.7 christos Mantissa is 39 bits wide, exponent 8 bit wide.
3653 1.7 christos Format is:
3654 1.7 christos bit 47: sign
3655 1.7 christos bit 46-8: normalized mantissa (bits 38-0, bit39 assumed to be 1)
3656 1.7 christos bit 7-0: exponent+128 (0 - value is null)
3657 1.7 christos MIN: 2.938735877e-39
3658 1.7 christos MAX: 1.701411835e+38
3659 1.7 christos */
3660 1.7 christos static const char *
3661 1.7 christos str_to_float48(char *litP, int *sizeP)
3662 1.7 christos {
3663 1.7 christos bfd_uint64_t mantissa;
3664 1.7 christos bfd_boolean sign;
3665 1.7 christos int exponent;
3666 1.7 christos unsigned i;
3667 1.7 christos
3668 1.7 christos *sizeP = 6;
3669 1.7 christos if (!str_to_broken_float (&sign, &mantissa, &exponent))
3670 1.7 christos return _("invalid syntax");
3671 1.7 christos /* shift by 23 bits right keeping 41 bit mantissa for rounding */
3672 1.7 christos mantissa >>= 23;
3673 1.7 christos /* do rounding */
3674 1.7 christos ++mantissa;
3675 1.7 christos /* make 40 bit mantissa */
3676 1.7 christos mantissa >>= 1;
3677 1.7 christos /* check for overflow */
3678 1.7 christos if (mantissa >> 40)
3679 1.7 christos {
3680 1.7 christos mantissa >>= 1;
3681 1.7 christos ++exponent;
3682 1.7 christos }
3683 1.7 christos if (exponent < -127)
3684 1.7 christos {
3685 1.7 christos memset (litP, 0, 6);
3686 1.7 christos return NULL;
3687 1.7 christos }
3688 1.7 christos if (exponent > 127)
3689 1.7 christos return _("overflow");
3690 1.7 christos if (!sign)
3691 1.7 christos mantissa &= (1ull << 39) - 1;
3692 1.7 christos *litP++ = (char)(0x80 + exponent);
3693 1.7 christos for (i = 0; i < 40; i += 8)
3694 1.7 christos *litP++ = (char)(mantissa >> i);
3695 1.7 christos return NULL;
3696 1.7 christos }
3697 1.7 christos
3698 1.7 christos static const char *
3699 1.7 christos str_to_ieee754_h(char *litP, int *sizeP)
3700 1.7 christos {
3701 1.7 christos return ieee_md_atof ('h', litP, sizeP, FALSE);
3702 1.7 christos }
3703 1.7 christos
3704 1.7 christos static const char *
3705 1.7 christos str_to_ieee754_s(char *litP, int *sizeP)
3706 1.7 christos {
3707 1.7 christos return ieee_md_atof ('s', litP, sizeP, FALSE);
3708 1.7 christos }
3709 1.7 christos
3710 1.7 christos static const char *
3711 1.7 christos str_to_ieee754_d(char *litP, int *sizeP)
3712 1.7 christos {
3713 1.7 christos return ieee_md_atof ('d', litP, sizeP, FALSE);
3714 1.7 christos }
3715