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