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