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