OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [gas/] [config/] [tc-z80.c] - Blame information for rev 205

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 205 julius
/* tc-z80.c -- Assemble code for the Zilog Z80 and ASCII R800
2
   Copyright 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
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
9
   the Free Software Foundation; either version 3, or (at your option)
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"
23
#include "safe-ctype.h"
24
#include "subsegs.h"
25
 
26
/* Exported constants.  */
27
const char comment_chars[] = ";\0";
28
const char line_comment_chars[] = "#;\0";
29
const char line_separator_chars[] = "\0";
30
const char EXP_CHARS[] = "eE\0";
31
const char FLT_CHARS[] = "RrFf\0";
32
 
33
/* For machine specific options.  */
34
const char * md_shortopts = ""; /* None yet.  */
35
 
36
enum options
37
{
38
  OPTION_MACH_Z80 = OPTION_MD_BASE,
39
  OPTION_MACH_R800,
40
  OPTION_MACH_IUD,
41
  OPTION_MACH_WUD,
42
  OPTION_MACH_FUD,
43
  OPTION_MACH_IUP,
44
  OPTION_MACH_WUP,
45
  OPTION_MACH_FUP
46
};
47
 
48
#define INS_Z80    1
49
#define INS_UNDOC  2
50
#define INS_UNPORT 4
51
#define INS_R800   8
52
 
53
struct option md_longopts[] =
54
{
55
  { "z80",       no_argument, NULL, OPTION_MACH_Z80},
56
  { "r800",      no_argument, NULL, OPTION_MACH_R800},
57
  { "ignore-undocumented-instructions", no_argument, NULL, OPTION_MACH_IUD },
58
  { "Wnud",  no_argument, NULL, OPTION_MACH_IUD },
59
  { "warn-undocumented-instructions",  no_argument, NULL, OPTION_MACH_WUD },
60
  { "Wud",  no_argument, NULL, OPTION_MACH_WUD },
61
  { "forbid-undocumented-instructions", no_argument, NULL, OPTION_MACH_FUD },
62
  { "Fud",  no_argument, NULL, OPTION_MACH_FUD },
63
  { "ignore-unportable-instructions", no_argument, NULL, OPTION_MACH_IUP },
64
  { "Wnup",  no_argument, NULL, OPTION_MACH_IUP },
65
  { "warn-unportable-instructions",  no_argument, NULL, OPTION_MACH_WUP },
66
  { "Wup",  no_argument, NULL, OPTION_MACH_WUP },
67
  { "forbid-unportable-instructions", no_argument, NULL, OPTION_MACH_FUP },
68
  { "Fup",  no_argument, NULL, OPTION_MACH_FUP },
69
 
70
  { NULL, no_argument, NULL, 0 }
71
} ;
72
 
73
size_t md_longopts_size = sizeof (md_longopts);
74
 
75
extern int coff_flags;
76
/* Instruction classes that silently assembled.  */
77
static int ins_ok = INS_Z80 | INS_UNDOC;
78
/* Instruction classes that generate errors.  */
79
static int ins_err = INS_R800;
80
/* Instruction classes actually used, determines machine type.  */
81
static int ins_used = INS_Z80;
82
 
83
int
84
md_parse_option (int c, char* arg ATTRIBUTE_UNUSED)
85
{
86
  switch (c)
87
    {
88
    default:
89
      return 0;
90
    case OPTION_MACH_Z80:
91
      ins_ok &= ~INS_R800;
92
      ins_err |= INS_R800;
93
      break;
94
    case OPTION_MACH_R800:
95
      ins_ok = INS_Z80 | INS_UNDOC | INS_R800;
96
      ins_err = INS_UNPORT;
97
      break;
98
    case OPTION_MACH_IUD:
99
      ins_ok |= INS_UNDOC;
100
      ins_err &= ~INS_UNDOC;
101
      break;
102
    case OPTION_MACH_IUP:
103
      ins_ok |= INS_UNDOC | INS_UNPORT;
104
      ins_err &= ~(INS_UNDOC | INS_UNPORT);
105
      break;
106
    case OPTION_MACH_WUD:
107
      if ((ins_ok & INS_R800) == 0)
108
        {
109
          ins_ok &= ~(INS_UNDOC|INS_UNPORT);
110
          ins_err &= ~INS_UNDOC;
111
        }
112
      break;
113
    case OPTION_MACH_WUP:
114
      ins_ok &= ~INS_UNPORT;
115
      ins_err &= ~(INS_UNDOC|INS_UNPORT);
116
      break;
117
    case OPTION_MACH_FUD:
118
      if ((ins_ok & INS_R800) == 0)
119
        {
120
          ins_ok &= (INS_UNDOC | INS_UNPORT);
121
          ins_err |= INS_UNDOC | INS_UNPORT;
122
        }
123
      break;
124
    case OPTION_MACH_FUP:
125
      ins_ok &= ~INS_UNPORT;
126
      ins_err |= INS_UNPORT;
127
      break;
128
    }
129
 
130
  return 1;
131
}
132
 
133
void
134
md_show_usage (FILE * f)
135
{
136
  fprintf (f, "\n\
137
CPU model/instruction set options:\n\
138
\n\
139
  -z80\t\t  assemble for Z80\n\
140
  -ignore-undocumented-instructions\n\
141
  -Wnud\n\
142
\tsilently assemble undocumented Z80-instructions that work on R800\n\
143
  -ignore-unportable-instructions\n\
144
  -Wnup\n\
145
\tsilently assemble all undocumented Z80-instructions\n\
146
  -warn-undocumented-instructions\n\
147
  -Wud\n\
148
\tissue warnings for undocumented Z80-instructions that work on R800\n\
149
  -warn-unportable-instructions\n\
150
  -Wup\n\
151
\tissue warnings for other undocumented Z80-instructions\n\
152
  -forbid-undocumented-instructions\n\
153
  -Fud\n\
154
\ttreat all undocumented z80-instructions as errors\n\
155
  -forbid-unportable-instructions\n\
156
  -Fup\n\
157
\ttreat undocumented z80-instructions that do not work on R800 as errors\n\
158
  -r800\t  assemble for R800\n\n\
159
Default: -z80 -ignore-undocument-instructions -warn-unportable-instructions.\n");
160
}
161
 
162
static symbolS * zero;
163
 
164
void
165
md_begin (void)
166
{
167
  expressionS nul;
168
  char * p;
169
 
170
  p = input_line_pointer;
171
  input_line_pointer = "0";
172
  nul.X_md=0;
173
  expression (& nul);
174
  input_line_pointer = p;
175
  zero = make_expr_symbol (& nul);
176
  /* We do not use relaxation (yet).  */
177
  linkrelax = 0;
178
}
179
 
180
void
181
z80_md_end (void)
182
{
183
  int mach_type;
184
 
185
  if (ins_used & (INS_UNPORT | INS_R800))
186
    ins_used |= INS_UNDOC;
187
 
188
  switch (ins_used)
189
    {
190
    case INS_Z80:
191
      mach_type = bfd_mach_z80strict;
192
      break;
193
    case INS_Z80|INS_UNDOC:
194
      mach_type = bfd_mach_z80;
195
      break;
196
    case INS_Z80|INS_UNDOC|INS_UNPORT:
197
      mach_type = bfd_mach_z80full;
198
      break;
199
    case INS_Z80|INS_UNDOC|INS_R800:
200
      mach_type = bfd_mach_r800;
201
      break;
202
    default:
203
      mach_type = 0;
204
    }
205
 
206
  bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach_type);
207
}
208
 
209
static const char *
210
skip_space (const char *s)
211
{
212
  while (*s == ' ' || *s == '\t')
213
    ++s;
214
  return s;
215
}
216
 
217
/* A non-zero return-value causes a continue in the
218
   function read_a_source_file () in ../read.c.  */
219
int
220
z80_start_line_hook (void)
221
{
222
  char *p, quote;
223
  char buf[4];
224
 
225
  /* Convert one character constants.  */
226
  for (p = input_line_pointer; *p && *p != '\n'; ++p)
227
    {
228
      switch (*p)
229
        {
230
        case '\'':
231
          if (p[1] != 0 && p[1] != '\'' && p[2] == '\'')
232
            {
233
              snprintf (buf, 4, "%3d", (unsigned char)p[1]);
234
              *p++ = buf[0];
235
              *p++ = buf[1];
236
              *p++ = buf[2];
237
              break;
238
            }
239
        case '"':
240
          for (quote = *p++; quote != *p && '\n' != *p; ++p)
241
            /* No escapes.  */ ;
242
          if (quote != *p)
243
            {
244
              as_bad (_("-- unterminated string"));
245
              ignore_rest_of_line ();
246
              return 1;
247
            }
248
          break;
249
        }
250
    }
251
  /* Check for <label>[:] [.](EQU|DEFL) <value>.  */
252
  if (is_name_beginner (*input_line_pointer))
253
    {
254
      char c, *rest, *line_start;
255
      int len;
256
      symbolS * symbolP;
257
 
258
      line_start = input_line_pointer;
259
      LISTING_NEWLINE ();
260
      if (ignore_input ())
261
        return 0;
262
 
263
      c = get_symbol_end ();
264
      rest = input_line_pointer + 1;
265
 
266
      if (*rest == ':')
267
        ++rest;
268
      if (*rest == ' ' || *rest == '\t')
269
        ++rest;
270
      if (*rest == '.')
271
        ++rest;
272
      if (strncasecmp (rest, "EQU", 3) == 0)
273
        len = 3;
274
      else if (strncasecmp (rest, "DEFL", 4) == 0)
275
        len = 4;
276
      else
277
        len = 0;
278
      if (len && (rest[len] == ' ' || rest[len] == '\t'))
279
        {
280
          /* Handle assignment here.  */
281
          input_line_pointer = rest + len;
282
          if (line_start[-1] == '\n')
283
            bump_line_counters ();
284
          /* Most Z80 assemblers require the first definition of a
285
             label to use "EQU" and redefinitions to have "DEFL".  */
286
          if (len == 3 && (symbolP = symbol_find (line_start)) != NULL)
287
            {
288
              if (S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP))
289
                as_bad (_("symbol `%s' is already defined"), line_start);
290
            }
291
          equals (line_start, 1);
292
          return 1;
293
        }
294
      else
295
        {
296
          /* Restore line and pointer.  */
297
          *input_line_pointer = c;
298
          input_line_pointer = line_start;
299
        }
300
    }
301
  return 0;
302
}
303
 
304
symbolS *
305
md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
306
{
307
  return NULL;
308
}
309
 
310
char *
311
md_atof (int type ATTRIBUTE_UNUSED, char *litP ATTRIBUTE_UNUSED,
312
         int *sizeP ATTRIBUTE_UNUSED)
313
{
314
  return _("floating point numbers are not implemented");
315
}
316
 
317
valueT
318
md_section_align (segT seg ATTRIBUTE_UNUSED, valueT size)
319
{
320
  return size;
321
}
322
 
323
long
324
md_pcrel_from (fixS * fixp)
325
{
326
  return fixp->fx_where +
327
    fixp->fx_frag->fr_address + 1;
328
}
329
 
330
typedef const char * (asfunc)(char, char, const char*);
331
 
332
typedef struct _table_t
333
{
334
  char* name;
335
  char prefix;
336
  char opcode;
337
  asfunc * fp;
338
} table_t;
339
 
340
/* Compares the key for structs that start with a char * to the key.  */
341
static int
342
key_cmp (const void * a, const void * b)
343
{
344
  const char *str_a, *str_b;
345
 
346
  str_a = *((const char**)a);
347
  str_b = *((const char**)b);
348
  return strcmp (str_a, str_b);
349
}
350
 
351
#define BUFLEN 8 /* Large enough for any keyword.  */
352
 
353
char buf[BUFLEN];
354
const char *key = buf;
355
 
356
#define R_STACKABLE (0x80)
357
#define R_ARITH     (0x40)
358
#define R_IX        (0x20)
359
#define R_IY        (0x10)
360
#define R_INDEX     (R_IX | R_IY)
361
 
362
#define REG_A (7)
363
#define REG_B (0)
364
#define REG_C (1)
365
#define REG_D (2)
366
#define REG_E (3)
367
#define REG_H (4)
368
#define REG_L (5)
369
#define REG_F (6 | 8)
370
#define REG_I (9)
371
#define REG_R (10)
372
 
373
#define REG_AF (3 | R_STACKABLE)
374
#define REG_BC (0 | R_STACKABLE | R_ARITH)
375
#define REG_DE (1 | R_STACKABLE | R_ARITH)
376
#define REG_HL (2 | R_STACKABLE | R_ARITH)
377
#define REG_SP (3 | R_ARITH)
378
 
379
static const struct reg_entry
380
{
381
  char* name;
382
  int number;
383
} regtable[] =
384
{
385
  {"a",  REG_A },
386
  {"af", REG_AF },
387
  {"b",  REG_B },
388
  {"bc", REG_BC },
389
  {"c",  REG_C },
390
  {"d",  REG_D },
391
  {"de", REG_DE },
392
  {"e",  REG_E },
393
  {"f",  REG_F },
394
  {"h",  REG_H },
395
  {"hl", REG_HL },
396
  {"i",  REG_I },
397
  {"ix", REG_HL | R_IX },
398
  {"ixh",REG_H | R_IX },
399
  {"ixl",REG_L | R_IX },
400
  {"iy", REG_HL | R_IY },
401
  {"iyh",REG_H | R_IY },
402
  {"iyl",REG_L | R_IY },
403
  {"l",  REG_L },
404
  {"r",  REG_R },
405
  {"sp", REG_SP },
406
} ;
407
 
408
/* Prevent an error on a line from also generating
409
   a "junk at end of line" error message.  */
410
static char err_flag;
411
 
412
static void
413
error (const char * message)
414
{
415
  as_bad ("%s", message);
416
  err_flag = 1;
417
}
418
 
419
static void
420
ill_op (void)
421
{
422
  error (_("illegal operand"));
423
}
424
 
425
static void
426
wrong_mach (int ins_type)
427
{
428
  const char *p;
429
 
430
  switch (ins_type)
431
    {
432
    case INS_UNDOC:
433
      p = "undocumented instruction";
434
      break;
435
    case INS_UNPORT:
436
      p = "instruction does not work on R800";
437
      break;
438
    case INS_R800:
439
      p = "instruction only works R800";
440
      break;
441
    default:
442
      p = 0; /* Not reachable.  */
443
    }
444
 
445
  if (ins_type & ins_err)
446
    error (_(p));
447
  else
448
    as_warn (_(p));
449
}
450
 
451
static void
452
check_mach (int ins_type)
453
{
454
  if ((ins_type & ins_ok) == 0)
455
    wrong_mach (ins_type);
456
  ins_used |= ins_type;
457
}
458
 
459
/* Check whether an expression is indirect.  */
460
static int
461
is_indir (const char *s)
462
{
463
  char quote;
464
  const char *p;
465
  int indir, depth;
466
 
467
  /* Indirection is indicated with parentheses.  */
468
  indir = (*s == '(');
469
 
470
  for (p = s, depth = 0; *p && *p != ','; ++p)
471
    {
472
      switch (*p)
473
        {
474
        case '"':
475
        case '\'':
476
          for (quote = *p++; quote != *p && *p != '\n'; ++p)
477
            if (*p == '\\' && p[1])
478
              ++p;
479
          break;
480
        case '(':
481
          ++ depth;
482
          break;
483
        case ')':
484
          -- depth;
485
          if (depth == 0)
486
            {
487
              p = skip_space (p + 1);
488
              if (*p && *p != ',')
489
                indir = 0;
490
              --p;
491
            }
492
          if (depth < 0)
493
            error (_("mismatched parentheses"));
494
          break;
495
        }
496
    }
497
 
498
  if (depth != 0)
499
    error (_("mismatched parentheses"));
500
 
501
  return indir;
502
}
503
 
504
/* Parse general expression.  */
505
static const char *
506
parse_exp2 (const char *s, expressionS *op, segT *pseg)
507
{
508
  const char *p;
509
  int indir;
510
  int i;
511
  const struct reg_entry * regp;
512
  expressionS offset;
513
 
514
  p = skip_space (s);
515
  op->X_md = indir = is_indir (p);
516
  if (indir)
517
    p = skip_space (p + 1);
518
 
519
  for (i = 0; i < BUFLEN; ++i)
520
    {
521
      if (!ISALPHA (p[i])) /* Register names consist of letters only.  */
522
        break;
523
      buf[i] = TOLOWER (p[i]);
524
    }
525
 
526
  if ((i < BUFLEN) && ((p[i] == 0) || (strchr (")+-, \t", p[i]))))
527
    {
528
      buf[i] = 0;
529
      regp = bsearch (& key, regtable, ARRAY_SIZE (regtable),
530
                      sizeof (regtable[0]), key_cmp);
531
      if (regp)
532
        {
533
          *pseg = reg_section;
534
          op->X_add_symbol = op->X_op_symbol = 0;
535
          op->X_add_number = regp->number;
536
          op->X_op = O_register;
537
          p += strlen (regp->name);
538
          p = skip_space (p);
539
          if (indir)
540
            {
541
              if (*p == ')')
542
                ++p;
543
              if ((regp->number & R_INDEX) && (regp->number & R_ARITH))
544
                {
545
                  op->X_op = O_md1;
546
 
547
                  if  ((*p == '+') || (*p == '-'))
548
                    {
549
                      input_line_pointer = (char*) p;
550
                      expression (& offset);
551
                      p = skip_space (input_line_pointer);
552
                      if (*p != ')')
553
                        error (_("bad offset expression syntax"));
554
                      else
555
                        ++ p;
556
                      op->X_add_symbol = make_expr_symbol (& offset);
557
                      return p;
558
                    }
559
 
560
                  /* We treat (i[xy]) as (i[xy]+0), which is how it will
561
                     end up anyway, unless we're processing jp (i[xy]).  */
562
                  op->X_add_symbol = zero;
563
                }
564
            }
565
          p = skip_space (p);
566
 
567
          if ((*p == 0) || (*p == ','))
568
            return p;
569
        }
570
    }
571
  /* Not an argument involving a register; use the generic parser.  */
572
  input_line_pointer = (char*) s ;
573
  *pseg = expression (op);
574
  if (op->X_op == O_absent)
575
    error (_("missing operand"));
576
  if (op->X_op == O_illegal)
577
    error (_("bad expression syntax"));
578
  return input_line_pointer;
579
}
580
 
581
static const char *
582
parse_exp (const char *s, expressionS *op)
583
{
584
  segT dummy;
585
  return parse_exp2 (s, op, & dummy);
586
}
587
 
588
/* Condition codes, including some synonyms provided by HiTech zas.  */
589
static const struct reg_entry cc_tab[] =
590
{
591
  { "age", 6 << 3 },
592
  { "alt", 7 << 3 },
593
  { "c",   3 << 3 },
594
  { "di",  4 << 3 },
595
  { "ei",  5 << 3 },
596
  { "lge", 2 << 3 },
597
  { "llt", 3 << 3 },
598
  { "m",   7 << 3 },
599
  { "nc",  2 << 3 },
600
  { "nz",  0 << 3 },
601
  { "p",   6 << 3 },
602
  { "pe",  5 << 3 },
603
  { "po",  4 << 3 },
604
  { "z",   1 << 3 },
605
} ;
606
 
607
/* Parse condition code.  */
608
static const char *
609
parse_cc (const char *s, char * op)
610
{
611
  const char *p;
612
  int i;
613
  struct reg_entry * cc_p;
614
 
615
  for (i = 0; i < BUFLEN; ++i)
616
    {
617
      if (!ISALPHA (s[i])) /* Condition codes consist of letters only.  */
618
        break;
619
      buf[i] = TOLOWER (s[i]);
620
    }
621
 
622
  if ((i < BUFLEN)
623
      && ((s[i] == 0) || (s[i] == ',')))
624
    {
625
      buf[i] = 0;
626
      cc_p = bsearch (&key, cc_tab, ARRAY_SIZE (cc_tab),
627
                      sizeof (cc_tab[0]), key_cmp);
628
    }
629
  else
630
    cc_p = NULL;
631
 
632
  if (cc_p)
633
    {
634
      *op = cc_p->number;
635
      p = s + i;
636
    }
637
  else
638
    p = NULL;
639
 
640
  return p;
641
}
642
 
643
static const char *
644
emit_insn (char prefix, char opcode, const char * args)
645
{
646
  char *p;
647
 
648
  if (prefix)
649
    {
650
      p = frag_more (2);
651
      *p++ = prefix;
652
    }
653
  else
654
    p = frag_more (1);
655
  *p = opcode;
656
  return args;
657
}
658
 
659
void z80_cons_fix_new (fragS *frag_p, int offset, int nbytes, expressionS *exp)
660
{
661
  bfd_reloc_code_real_type r[4] =
662
    {
663
      BFD_RELOC_8,
664
      BFD_RELOC_16,
665
      BFD_RELOC_24,
666
      BFD_RELOC_32
667
    };
668
 
669
  if (nbytes < 1 || nbytes > 4)
670
    {
671
      as_bad (_("unsupported BFD relocation size %u"), nbytes);
672
    }
673
  else
674
    {
675
      fix_new_exp (frag_p, offset, nbytes, exp, 0, r[nbytes-1]);
676
    }
677
}
678
 
679
static void
680
emit_byte (expressionS * val, bfd_reloc_code_real_type r_type)
681
{
682
  char *p;
683
  int lo, hi;
684
  fixS * fixp;
685
 
686
  p = frag_more (1);
687
  *p = val->X_add_number;
688
  if ((r_type == BFD_RELOC_8_PCREL) && (val->X_op == O_constant))
689
    {
690
      as_bad (_("cannot make a relative jump to an absolute location"));
691
    }
692
  else if (val->X_op == O_constant)
693
    {
694
      lo = -128;
695
      hi = (BFD_RELOC_8 == r_type) ? 255 : 127;
696
 
697
      if ((val->X_add_number < lo) || (val->X_add_number > hi))
698
        {
699
          if (r_type == BFD_RELOC_Z80_DISP8)
700
            as_bad (_("offset too large"));
701
          else
702
            as_warn (_("overflow"));
703
        }
704
    }
705
  else
706
    {
707
      fixp = fix_new_exp (frag_now, p - frag_now->fr_literal, 1, val,
708
                          (r_type == BFD_RELOC_8_PCREL) ? TRUE : FALSE, r_type);
709
      /* FIXME : Process constant offsets immediately.  */
710
    }
711
}
712
 
713
static void
714
emit_word (expressionS * val)
715
{
716
  char *p;
717
 
718
  p = frag_more (2);
719
  if (   (val->X_op == O_register)
720
      || (val->X_op == O_md1))
721
    ill_op ();
722
  else
723
    {
724
      *p = val->X_add_number;
725
      p[1] = (val->X_add_number>>8);
726
      if (val->X_op != O_constant)
727
        fix_new_exp (frag_now, p - frag_now->fr_literal, 2,
728
                     val, FALSE, BFD_RELOC_16);
729
    }
730
}
731
 
732
static void
733
emit_mx (char prefix, char opcode, int shift, expressionS * arg)
734
     /* The operand m may be r, (hl), (ix+d), (iy+d),
735
        if 0 == prefix m may also be ixl, ixh, iyl, iyh.  */
736
{
737
  char *q;
738
  int rnum;
739
 
740
  rnum = arg->X_add_number;
741
  switch (arg->X_op)
742
    {
743
    case O_register:
744
      if (arg->X_md)
745
        {
746
          if (rnum != REG_HL)
747
            {
748
              ill_op ();
749
              break;
750
            }
751
          else
752
            rnum = 6;
753
        }
754
      else
755
        {
756
          if ((prefix == 0) && (rnum & R_INDEX))
757
            {
758
              prefix = (rnum & R_IX) ? 0xDD : 0xFD;
759
              check_mach (INS_UNDOC);
760
              rnum &= ~R_INDEX;
761
            }
762
          if (rnum > 7)
763
            {
764
              ill_op ();
765
              break;
766
            }
767
        }
768
      q = frag_more (prefix ? 2 : 1);
769
      if (prefix)
770
        * q ++ = prefix;
771
      * q ++ = opcode + (rnum << shift);
772
      break;
773
    case O_md1:
774
      q = frag_more (2);
775
      *q++ = (rnum & R_IX) ? 0xDD : 0xFD;
776
      *q = (prefix) ? prefix : (opcode + (6 << shift));
777
      emit_byte (symbol_get_value_expression (arg->X_add_symbol),
778
                 BFD_RELOC_Z80_DISP8);
779
      if (prefix)
780
        {
781
          q = frag_more (1);
782
          *q = opcode+(6<<shift);
783
        }
784
      break;
785
    default:
786
      abort ();
787
    }
788
}
789
 
790
/* The operand m may be r, (hl), (ix+d), (iy+d),
791
   if 0 = prefix m may also be ixl, ixh, iyl, iyh.  */
792
static const char *
793
emit_m (char prefix, char opcode, const char *args)
794
{
795
  expressionS arg_m;
796
  const char *p;
797
 
798
  p = parse_exp (args, &arg_m);
799
  switch (arg_m.X_op)
800
    {
801
    case O_md1:
802
    case O_register:
803
      emit_mx (prefix, opcode, 0, &arg_m);
804
      break;
805
    default:
806
      ill_op ();
807
    }
808
  return p;
809
}
810
 
811
/* The operand m may be as above or one of the undocumented
812
   combinations (ix+d),r and (iy+d),r (if unportable instructions
813
   are allowed).  */
814
static const char *
815
emit_mr (char prefix, char opcode, const char *args)
816
{
817
  expressionS arg_m, arg_r;
818
  const char *p;
819
 
820
  p = parse_exp (args, & arg_m);
821
 
822
  switch (arg_m.X_op)
823
    {
824
    case O_md1:
825
      if (*p == ',')
826
        {
827
          p = parse_exp (p + 1, & arg_r);
828
 
829
          if ((arg_r.X_md == 0)
830
              && (arg_r.X_op == O_register)
831
              && (arg_r.X_add_number < 8))
832
            opcode += arg_r.X_add_number-6; /* Emit_mx () will add 6.  */
833
          else
834
            {
835
              ill_op ();
836
              break;
837
            }
838
          check_mach (INS_UNPORT);
839
        }
840
    case O_register:
841
      emit_mx (prefix, opcode, 0, & arg_m);
842
      break;
843
    default:
844
      ill_op ();
845
    }
846
  return p;
847
}
848
 
849
static void
850
emit_sx (char prefix, char opcode, expressionS * arg_p)
851
{
852
  char *q;
853
 
854
  switch (arg_p->X_op)
855
    {
856
    case O_register:
857
    case O_md1:
858
      emit_mx (prefix, opcode, 0, arg_p);
859
      break;
860
    default:
861
      if (arg_p->X_md)
862
        ill_op ();
863
      else
864
        {
865
          q = frag_more (prefix ? 2 : 1);
866
          if (prefix)
867
            *q++ = prefix;
868
          *q = opcode ^ 0x46;
869
          emit_byte (arg_p, BFD_RELOC_8);
870
        }
871
    }
872
}
873
 
874
/* The operand s may be r, (hl), (ix+d), (iy+d), n.  */
875
static const char *
876
emit_s (char prefix, char opcode, const char *args)
877
{
878
  expressionS arg_s;
879
  const char *p;
880
 
881
  p = parse_exp (args, & arg_s);
882
  emit_sx (prefix, opcode, & arg_s);
883
  return p;
884
}
885
 
886
static const char *
887
emit_call (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
888
{
889
  expressionS addr;
890
  const char *p;  char *q;
891
 
892
  p = parse_exp (args, &addr);
893
  if (addr.X_md)
894
    ill_op ();
895
  else
896
    {
897
      q = frag_more (1);
898
      *q = opcode;
899
      emit_word (& addr);
900
    }
901
  return p;
902
}
903
 
904
/* Operand may be rr, r, (hl), (ix+d), (iy+d).  */
905
static const char *
906
emit_incdec (char prefix, char opcode, const char * args)
907
{
908
  expressionS operand;
909
  int rnum;
910
  const char *p;  char *q;
911
 
912
  p = parse_exp (args, &operand);
913
  rnum = operand.X_add_number;
914
  if ((! operand.X_md)
915
      && (operand.X_op == O_register)
916
      && (R_ARITH&rnum))
917
    {
918
      q = frag_more ((rnum & R_INDEX) ? 2 : 1);
919
      if (rnum & R_INDEX)
920
        *q++ = (rnum & R_IX) ? 0xDD : 0xFD;
921
      *q = prefix + ((rnum & 3) << 4);
922
    }
923
  else
924
    {
925
      if ((operand.X_op == O_md1) || (operand.X_op == O_register))
926
        emit_mx (0, opcode, 3, & operand);
927
      else
928
        ill_op ();
929
    }
930
  return p;
931
}
932
 
933
static const char *
934
emit_jr (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
935
{
936
  expressionS addr;
937
  const char *p;
938
  char *q;
939
 
940
  p = parse_exp (args, &addr);
941
  if (addr.X_md)
942
    ill_op ();
943
  else
944
    {
945
      q = frag_more (1);
946
      *q = opcode;
947
      emit_byte (&addr, BFD_RELOC_8_PCREL);
948
    }
949
  return p;
950
}
951
 
952
static const char *
953
emit_jp (char prefix, char opcode, const char * args)
954
{
955
  expressionS addr;
956
  const char *p;
957
  char *q;
958
  int rnum;
959
 
960
  p = parse_exp (args, & addr);
961
  if (addr.X_md)
962
    {
963
      rnum = addr.X_add_number;
964
      if ((addr.X_op == O_register && (rnum & ~R_INDEX) == REG_HL)
965
         /* An operand (i[xy]) would have been rewritten to (i[xy]+0)
966
            in parse_exp ().  */
967
          || (addr.X_op == O_md1 && addr.X_add_symbol == zero))
968
        {
969
          q = frag_more ((rnum & R_INDEX) ? 2 : 1);
970
          if (rnum & R_INDEX)
971
            *q++ = (rnum & R_IX) ? 0xDD : 0xFD;
972
          *q = prefix;
973
        }
974
      else
975
        ill_op ();
976
    }
977
  else
978
    {
979
      q = frag_more (1);
980
      *q = opcode;
981
      emit_word (& addr);
982
    }
983
  return p;
984
}
985
 
986
static const char *
987
emit_im (char prefix, char opcode, const char * args)
988
{
989
  expressionS mode;
990
  const char *p;
991
  char *q;
992
 
993
  p = parse_exp (args, & mode);
994
  if (mode.X_md || (mode.X_op != O_constant))
995
    ill_op ();
996
  else
997
    switch (mode.X_add_number)
998
      {
999
      case 1:
1000
      case 2:
1001
        ++mode.X_add_number;
1002
        /* Fall through.  */
1003
      case 0:
1004
        q = frag_more (2);
1005
        *q++ = prefix;
1006
        *q = opcode + 8*mode.X_add_number;
1007
        break;
1008
      default:
1009
        ill_op ();
1010
      }
1011
  return p;
1012
}
1013
 
1014
static const char *
1015
emit_pop (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1016
{
1017
  expressionS regp;
1018
  const char *p;
1019
  char *q;
1020
 
1021
  p = parse_exp (args, & regp);
1022
  if ((!regp.X_md)
1023
      && (regp.X_op == O_register)
1024
      && (regp.X_add_number & R_STACKABLE))
1025
    {
1026
      int rnum;
1027
 
1028
      rnum = regp.X_add_number;
1029
      if (rnum&R_INDEX)
1030
        {
1031
          q = frag_more (2);
1032
          *q++ = (rnum&R_IX)?0xDD:0xFD;
1033
        }
1034
      else
1035
        q = frag_more (1);
1036
      *q = opcode + ((rnum & 3) << 4);
1037
    }
1038
  else
1039
    ill_op ();
1040
 
1041
  return p;
1042
}
1043
 
1044
static const char *
1045
emit_retcc (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1046
{
1047
  char cc, *q;
1048
  const char *p;
1049
 
1050
  p = parse_cc (args, &cc);
1051
  q = frag_more (1);
1052
  if (p)
1053
    *q = opcode + cc;
1054
  else
1055
    *q = prefix;
1056
  return p ? p : args;
1057
}
1058
 
1059
static const char *
1060
emit_adc (char prefix, char opcode, const char * args)
1061
{
1062
  expressionS term;
1063
  int rnum;
1064
  const char *p;
1065
  char *q;
1066
 
1067
  p = parse_exp (args, &term);
1068
  if (*p++ != ',')
1069
    {
1070
      error (_("bad intruction syntax"));
1071
      return p;
1072
    }
1073
 
1074
  if ((term.X_md) || (term.X_op != O_register))
1075
    ill_op ();
1076
  else
1077
    switch (term.X_add_number)
1078
      {
1079
      case REG_A:
1080
        p = emit_s (0, prefix, p);
1081
        break;
1082
      case REG_HL:
1083
        p = parse_exp (p, &term);
1084
        if ((!term.X_md) && (term.X_op == O_register))
1085
          {
1086
            rnum = term.X_add_number;
1087
            if (R_ARITH == (rnum & (R_ARITH | R_INDEX)))
1088
              {
1089
                q = frag_more (2);
1090
                *q++ = 0xED;
1091
                *q = opcode + ((rnum & 3) << 4);
1092
                break;
1093
              }
1094
          }
1095
        /* Fall through.  */
1096
      default:
1097
        ill_op ();
1098
      }
1099
  return p;
1100
}
1101
 
1102
static const char *
1103
emit_add (char prefix, char opcode, const char * args)
1104
{
1105
  expressionS term;
1106
  int lhs, rhs;
1107
  const char *p;
1108
  char *q;
1109
 
1110
  p = parse_exp (args, &term);
1111
  if (*p++ != ',')
1112
    {
1113
      error (_("bad intruction syntax"));
1114
      return p;
1115
    }
1116
 
1117
  if ((term.X_md) || (term.X_op != O_register))
1118
    ill_op ();
1119
  else
1120
    switch (term.X_add_number & ~R_INDEX)
1121
      {
1122
      case REG_A:
1123
        p = emit_s (0, prefix, p);
1124
        break;
1125
      case REG_HL:
1126
        lhs = term.X_add_number;
1127
        p = parse_exp (p, &term);
1128
        if ((!term.X_md) && (term.X_op == O_register))
1129
          {
1130
            rhs = term.X_add_number;
1131
            if ((rhs & R_ARITH)
1132
                && ((rhs == lhs) || ((rhs & ~R_INDEX) != REG_HL)))
1133
              {
1134
                q = frag_more ((lhs & R_INDEX) ? 2 : 1);
1135
                if (lhs & R_INDEX)
1136
                  *q++ = (lhs & R_IX) ? 0xDD : 0xFD;
1137
                *q = opcode + ((rhs & 3) << 4);
1138
                break;
1139
              }
1140
          }
1141
        /* Fall through.  */
1142
      default:
1143
        ill_op ();
1144
      }
1145
  return p;
1146
}
1147
 
1148
static const char *
1149
emit_bit (char prefix, char opcode, const char * args)
1150
{
1151
  expressionS b;
1152
  int bn;
1153
  const char *p;
1154
 
1155
  p = parse_exp (args, &b);
1156
  if (*p++ != ',')
1157
    error (_("bad intruction syntax"));
1158
 
1159
  bn = b.X_add_number;
1160
  if ((!b.X_md)
1161
      && (b.X_op == O_constant)
1162
      && (0 <= bn)
1163
      && (bn < 8))
1164
    {
1165
      if (opcode == 0x40)
1166
        /* Bit : no optional third operand.  */
1167
        p = emit_m (prefix, opcode + (bn << 3), p);
1168
      else
1169
        /* Set, res : resulting byte can be copied to register.  */
1170
        p = emit_mr (prefix, opcode + (bn << 3), p);
1171
    }
1172
  else
1173
    ill_op ();
1174
  return p;
1175
}
1176
 
1177
static const char *
1178
emit_jpcc (char prefix, char opcode, const char * args)
1179
{
1180
  char cc;
1181
  const char *p;
1182
 
1183
  p = parse_cc (args, & cc);
1184
  if (p && *p++ == ',')
1185
    p = emit_call (0, opcode + cc, p);
1186
  else
1187
    p = (prefix == (char)0xC3)
1188
      ? emit_jp (0xE9, prefix, args)
1189
      : emit_call (0, prefix, args);
1190
  return p;
1191
}
1192
 
1193
static const char *
1194
emit_jrcc (char prefix, char opcode, const char * args)
1195
{
1196
  char cc;
1197
  const char *p;
1198
 
1199
  p = parse_cc (args, &cc);
1200
  if (p && *p++ == ',')
1201
    {
1202
      if (cc > (3 << 3))
1203
        error (_("condition code invalid for jr"));
1204
      else
1205
        p = emit_jr (0, opcode + cc, p);
1206
    }
1207
  else
1208
    p = emit_jr (0, prefix, args);
1209
 
1210
  return p;
1211
}
1212
 
1213
static const char *
1214
emit_ex (char prefix_in ATTRIBUTE_UNUSED,
1215
         char opcode_in ATTRIBUTE_UNUSED, const char * args)
1216
{
1217
  expressionS op;
1218
  const char * p;
1219
  char prefix, opcode;
1220
 
1221
  p = parse_exp (args, &op);
1222
  p = skip_space (p);
1223
  if (*p++ != ',')
1224
    {
1225
      error (_("bad instruction syntax"));
1226
      return p;
1227
    }
1228
 
1229
  prefix = opcode = 0;
1230
  if (op.X_op == O_register)
1231
    switch (op.X_add_number | (op.X_md ? 0x8000 : 0))
1232
      {
1233
      case REG_AF:
1234
        if (TOLOWER (*p++) == 'a' && TOLOWER (*p++) == 'f')
1235
          {
1236
            /* The scrubber changes '\'' to '`' in this context.  */
1237
            if (*p == '`')
1238
              ++p;
1239
            opcode = 0x08;
1240
          }
1241
        break;
1242
      case REG_DE:
1243
        if (TOLOWER (*p++) == 'h' && TOLOWER (*p++) == 'l')
1244
          opcode = 0xEB;
1245
        break;
1246
      case REG_SP|0x8000:
1247
        p = parse_exp (p, & op);
1248
        if (op.X_op == O_register
1249
            && op.X_md == 0
1250
            && (op.X_add_number & ~R_INDEX) == REG_HL)
1251
          {
1252
            opcode = 0xE3;
1253
            if (R_INDEX & op.X_add_number)
1254
              prefix = (R_IX & op.X_add_number) ? 0xDD : 0xFD;
1255
          }
1256
        break;
1257
      }
1258
  if (opcode)
1259
    emit_insn (prefix, opcode, p);
1260
  else
1261
    ill_op ();
1262
 
1263
  return p;
1264
}
1265
 
1266
static const char *
1267
emit_in (char prefix ATTRIBUTE_UNUSED, char opcode ATTRIBUTE_UNUSED,
1268
        const char * args)
1269
{
1270
  expressionS reg, port;
1271
  const char *p;
1272
  char *q;
1273
 
1274
  p = parse_exp (args, &reg);
1275
  if (*p++ != ',')
1276
    {
1277
      error (_("bad intruction syntax"));
1278
      return p;
1279
    }
1280
 
1281
  p = parse_exp (p, &port);
1282
  if (reg.X_md == 0
1283
      && reg.X_op == O_register
1284
      && (reg.X_add_number <= 7 || reg.X_add_number == REG_F)
1285
      && (port.X_md))
1286
    {
1287
      if (port.X_op != O_md1 && port.X_op != O_register)
1288
        {
1289
          if (REG_A == reg.X_add_number)
1290
            {
1291
              q = frag_more (1);
1292
              *q = 0xDB;
1293
              emit_byte (&port, BFD_RELOC_8);
1294
            }
1295
          else
1296
            ill_op ();
1297
        }
1298
      else
1299
        {
1300
          if (port.X_add_number == REG_C)
1301
            {
1302
              if (reg.X_add_number == REG_F)
1303
                check_mach (INS_UNDOC);
1304
              else
1305
                {
1306
                  q = frag_more (2);
1307
                  *q++ = 0xED;
1308
                  *q = 0x40|((reg.X_add_number&7)<<3);
1309
                }
1310
            }
1311
          else
1312
            ill_op ();
1313
        }
1314
    }
1315
  else
1316
    ill_op ();
1317
  return p;
1318
}
1319
 
1320
static const char *
1321
emit_out (char prefix ATTRIBUTE_UNUSED, char opcode ATTRIBUTE_UNUSED,
1322
         const char * args)
1323
{
1324
  expressionS reg, port;
1325
  const char *p;
1326
  char *q;
1327
 
1328
  p = parse_exp (args, & port);
1329
  if (*p++ != ',')
1330
    {
1331
      error (_("bad intruction syntax"));
1332
      return p;
1333
    }
1334
  p = parse_exp (p, &reg);
1335
  if (!port.X_md)
1336
    { ill_op (); return p; }
1337
  /* Allow "out (c), 0" as unportable instruction.  */
1338
  if (reg.X_op == O_constant && reg.X_add_number == 0)
1339
    {
1340
      check_mach (INS_UNPORT);
1341
      reg.X_op = O_register;
1342
      reg.X_add_number = 6;
1343
    }
1344
  if (reg.X_md
1345
      || reg.X_op != O_register
1346
      || reg.X_add_number > 7)
1347
    ill_op ();
1348
  else
1349
    if (port.X_op != O_register && port.X_op != O_md1)
1350
      {
1351
        if (REG_A == reg.X_add_number)
1352
          {
1353
            q = frag_more (1);
1354
            *q = 0xD3;
1355
            emit_byte (&port, BFD_RELOC_8);
1356
          }
1357
        else
1358
          ill_op ();
1359
      }
1360
    else
1361
      {
1362
        if (REG_C == port.X_add_number)
1363
          {
1364
            q = frag_more (2);
1365
            *q++ = 0xED;
1366
            *q = 0x41 | (reg.X_add_number << 3);
1367
          }
1368
        else
1369
          ill_op ();
1370
      }
1371
  return p;
1372
}
1373
 
1374
static const char *
1375
emit_rst (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1376
{
1377
  expressionS addr;
1378
  const char *p;
1379
  char *q;
1380
 
1381
  p = parse_exp (args, &addr);
1382
  if (addr.X_op != O_constant)
1383
    {
1384
      error ("rst needs constant address");
1385
      return p;
1386
    }
1387
 
1388
  if (addr.X_add_number & ~(7 << 3))
1389
    ill_op ();
1390
  else
1391
    {
1392
      q = frag_more (1);
1393
      *q = opcode + (addr.X_add_number & (7 << 3));
1394
    }
1395
  return p;
1396
}
1397
 
1398
static void
1399
emit_ldxhl (char prefix, char opcode, expressionS *src, expressionS *d)
1400
{
1401
  char *q;
1402
 
1403
  if (src->X_md)
1404
    ill_op ();
1405
  else
1406
    {
1407
      if (src->X_op == O_register)
1408
        {
1409
          if (src->X_add_number>7)
1410
            ill_op ();
1411
          if (prefix)
1412
            {
1413
              q = frag_more (2);
1414
              *q++ = prefix;
1415
            }
1416
          else
1417
        q = frag_more (1);
1418
          *q = opcode + src->X_add_number;
1419
          if (d)
1420
            emit_byte (d, BFD_RELOC_Z80_DISP8);
1421
        }
1422
      else
1423
        {
1424
          if (prefix)
1425
            {
1426
              q = frag_more (2);
1427
              *q++ = prefix;
1428
            }
1429
          else
1430
            q = frag_more (1);
1431
          *q = opcode^0x46;
1432
          if (d)
1433
            emit_byte (d, BFD_RELOC_Z80_DISP8);
1434
          emit_byte (src, BFD_RELOC_8);
1435
        }
1436
    }
1437
}
1438
 
1439
static void
1440
emit_ldreg (int dest, expressionS * src)
1441
{
1442
  char *q;
1443
  int rnum;
1444
 
1445
  switch (dest)
1446
    {
1447
      /* 8 Bit ld group:  */
1448
    case REG_I:
1449
    case REG_R:
1450
      if (src->X_md == 0 && src->X_op == O_register && src->X_add_number == REG_A)
1451
        {
1452
          q = frag_more (2);
1453
          *q++ = 0xED;
1454
          *q = (dest == REG_I) ? 0x47 : 0x4F;
1455
        }
1456
      else
1457
        ill_op ();
1458
      break;
1459
 
1460
    case REG_A:
1461
      if ((src->X_md) && src->X_op != O_register && src->X_op != O_md1)
1462
        {
1463
          q = frag_more (1);
1464
          *q = 0x3A;
1465
          emit_word (src);
1466
          break;
1467
        }
1468
 
1469
      if ((src->X_md)
1470
          && src->X_op == O_register
1471
          && (src->X_add_number == REG_BC || src->X_add_number == REG_DE))
1472
        {
1473
          q = frag_more (1);
1474
          *q = 0x0A + ((src->X_add_number & 1) << 4);
1475
          break;
1476
        }
1477
 
1478
      if ((!src->X_md)
1479
          && src->X_op == O_register
1480
          && (src->X_add_number == REG_R || src->X_add_number == REG_I))
1481
        {
1482
          q = frag_more (2);
1483
          *q++ = 0xED;
1484
          *q = (src->X_add_number == REG_I) ? 0x57 : 0x5F;
1485
          break;
1486
        }
1487
      /* Fall through.  */
1488
    case REG_B:
1489
    case REG_C:
1490
    case REG_D:
1491
    case REG_E:
1492
      emit_sx (0, 0x40 + (dest << 3), src);
1493
      break;
1494
 
1495
    case REG_H:
1496
    case REG_L:
1497
      if ((src->X_md == 0)
1498
          && (src->X_op == O_register)
1499
          && (src->X_add_number & R_INDEX))
1500
        ill_op ();
1501
      else
1502
        emit_sx (0, 0x40 + (dest << 3), src);
1503
      break;
1504
 
1505
    case R_IX | REG_H:
1506
    case R_IX | REG_L:
1507
    case R_IY | REG_H:
1508
    case R_IY | REG_L:
1509
      if (src->X_md)
1510
        {
1511
          ill_op ();
1512
          break;
1513
        }
1514
      check_mach (INS_UNDOC);
1515
      if (src-> X_op == O_register)
1516
        {
1517
          rnum = src->X_add_number;
1518
          if ((rnum & ~R_INDEX) < 8
1519
              && ((rnum & R_INDEX) == (dest & R_INDEX)
1520
                   || (   (rnum & ~R_INDEX) != REG_H
1521
                       && (rnum & ~R_INDEX) != REG_L)))
1522
            {
1523
              q = frag_more (2);
1524
              *q++ = (dest & R_IX) ? 0xDD : 0xFD;
1525
              *q = 0x40 + ((dest & 0x07) << 3) + (rnum & 7);
1526
            }
1527
          else
1528
            ill_op ();
1529
        }
1530
      else
1531
        {
1532
          q = frag_more (2);
1533
          *q++ = (dest & R_IX) ? 0xDD : 0xFD;
1534
          *q = 0x06 + ((dest & 0x07) << 3);
1535
          emit_byte (src, BFD_RELOC_8);
1536
        }
1537
      break;
1538
 
1539
      /* 16 Bit ld group:  */
1540
    case REG_SP:
1541
      if (src->X_md == 0
1542
          && src->X_op == O_register
1543
          && REG_HL == (src->X_add_number &~ R_INDEX))
1544
        {
1545
          q = frag_more ((src->X_add_number & R_INDEX) ? 2 : 1);
1546
          if (src->X_add_number & R_INDEX)
1547
            *q++ = (src->X_add_number & R_IX) ? 0xDD : 0xFD;
1548
          *q = 0xF9;
1549
          break;
1550
        }
1551
      /* Fall through.  */
1552
    case REG_BC:
1553
    case REG_DE:
1554
      if (src->X_op == O_register || src->X_op == O_md1)
1555
        ill_op ();
1556
      q = frag_more (src->X_md ? 2 : 1);
1557
      if (src->X_md)
1558
        {
1559
          *q++ = 0xED;
1560
          *q = 0x4B + ((dest & 3) << 4);
1561
        }
1562
      else
1563
        *q = 0x01 + ((dest & 3) << 4);
1564
      emit_word (src);
1565
      break;
1566
 
1567
    case REG_HL:
1568
    case REG_HL | R_IX:
1569
    case REG_HL | R_IY:
1570
      if (src->X_op == O_register || src->X_op == O_md1)
1571
        ill_op ();
1572
      q = frag_more ((dest & R_INDEX) ? 2 : 1);
1573
      if (dest & R_INDEX)
1574
        * q ++ = (dest & R_IX) ? 0xDD : 0xFD;
1575
      *q = (src->X_md) ? 0x2A : 0x21;
1576
      emit_word (src);
1577
      break;
1578
 
1579
    case REG_AF:
1580
    case REG_F:
1581
      ill_op ();
1582
      break;
1583
 
1584
    default:
1585
      abort ();
1586
    }
1587
}
1588
 
1589
static const char *
1590
emit_ld (char prefix_in ATTRIBUTE_UNUSED, char opcode_in ATTRIBUTE_UNUSED,
1591
        const char * args)
1592
{
1593
  expressionS dst, src;
1594
  const char *p;
1595
  char *q;
1596
  char prefix, opcode;
1597
 
1598
  p = parse_exp (args, &dst);
1599
  if (*p++ != ',')
1600
    error (_("bad intruction syntax"));
1601
  p = parse_exp (p, &src);
1602
 
1603
  switch (dst.X_op)
1604
    {
1605
    case O_md1:
1606
      emit_ldxhl ((dst.X_add_number & R_IX) ? 0xDD : 0xFD, 0x70,
1607
                  &src, symbol_get_value_expression (dst.X_add_symbol));
1608
      break;
1609
 
1610
    case O_register:
1611
      if (dst.X_md)
1612
        {
1613
          switch (dst.X_add_number)
1614
            {
1615
            case REG_BC:
1616
            case REG_DE:
1617
              if (src.X_md == 0 && src.X_op == O_register && src.X_add_number == REG_A)
1618
                {
1619
                  q = frag_more (1);
1620
                  *q = 0x02 + ( (dst.X_add_number & 1) << 4);
1621
                }
1622
              else
1623
                ill_op ();
1624
              break;
1625
            case REG_HL:
1626
              emit_ldxhl (0, 0x70, &src, NULL);
1627
              break;
1628
            default:
1629
              ill_op ();
1630
            }
1631
        }
1632
      else
1633
        emit_ldreg (dst.X_add_number, &src);
1634
      break;
1635
 
1636
    default:
1637
      if (src.X_md != 0 || src.X_op != O_register)
1638
        ill_op ();
1639
      prefix = opcode = 0;
1640
      switch (src.X_add_number)
1641
        {
1642
        case REG_A:
1643
          opcode = 0x32; break;
1644
        case REG_BC: case REG_DE: case REG_SP:
1645
          prefix = 0xED; opcode = 0x43 + ((src.X_add_number&3)<<4); break;
1646
        case REG_HL:
1647
          opcode = 0x22; break;
1648
        case REG_HL|R_IX:
1649
          prefix = 0xDD; opcode = 0x22; break;
1650
        case REG_HL|R_IY:
1651
          prefix = 0xFD; opcode = 0x22; break;
1652
        }
1653
      if (opcode)
1654
        {
1655
          q = frag_more (prefix?2:1);
1656
          if (prefix)
1657
            *q++ = prefix;
1658
          *q = opcode;
1659
          emit_word (&dst);
1660
        }
1661
      else
1662
        ill_op ();
1663
    }
1664
  return p;
1665
}
1666
 
1667
static void
1668
emit_data (int size ATTRIBUTE_UNUSED)
1669
{
1670
  const char *p, *q;
1671
  char *u, quote;
1672
  int cnt;
1673
  expressionS exp;
1674
 
1675
  if (is_it_end_of_statement ())
1676
    {
1677
      demand_empty_rest_of_line ();
1678
      return;
1679
    }
1680
  p = skip_space (input_line_pointer);
1681
 
1682
  do
1683
    {
1684
      if (*p == '\"' || *p == '\'')
1685
        {
1686
            for (quote = *p, q = ++p, cnt = 0; *p && quote != *p; ++p, ++cnt)
1687
              ;
1688
            u = frag_more (cnt);
1689
            memcpy (u, q, cnt);
1690
            if (!*p)
1691
              as_warn (_("unterminated string"));
1692
            else
1693
              p = skip_space (p+1);
1694
        }
1695
      else
1696
        {
1697
          p = parse_exp (p, &exp);
1698
          if (exp.X_op == O_md1 || exp.X_op == O_register)
1699
            {
1700
              ill_op ();
1701
              break;
1702
            }
1703
          if (exp.X_md)
1704
            as_warn (_("parentheses ignored"));
1705
          emit_byte (&exp, BFD_RELOC_8);
1706
          p = skip_space (p);
1707
        }
1708
    }
1709
  while (*p++ == ',') ;
1710
  input_line_pointer = (char *)(p-1);
1711
}
1712
 
1713
static const char *
1714
emit_mulub (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1715
{
1716
  const char *p;
1717
 
1718
  p = skip_space (args);
1719
  if (TOLOWER (*p++) != 'a' || *p++ != ',')
1720
    ill_op ();
1721
  else
1722
    {
1723
      char *q, reg;
1724
 
1725
      reg = TOLOWER (*p++);
1726
      switch (reg)
1727
        {
1728
        case 'b':
1729
        case 'c':
1730
        case 'd':
1731
        case 'e':
1732
          check_mach (INS_R800);
1733
          if (!*skip_space (p))
1734
            {
1735
              q = frag_more (2);
1736
              *q++ = prefix;
1737
              *q = opcode + ((reg - 'b') << 3);
1738
              break;
1739
            }
1740
        default:
1741
          ill_op ();
1742
        }
1743
    }
1744
  return p;
1745
}
1746
 
1747
static const char *
1748
emit_muluw (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
1749
{
1750
  const char *p;
1751
 
1752
  p = skip_space (args);
1753
  if (TOLOWER (*p++) != 'h' || TOLOWER (*p++) != 'l' || *p++ != ',')
1754
    ill_op ();
1755
  else
1756
    {
1757
      expressionS reg;
1758
      char *q;
1759
 
1760
      p = parse_exp (p, & reg);
1761
 
1762
      if ((!reg.X_md) && reg.X_op == O_register)
1763
        switch (reg.X_add_number)
1764
          {
1765
          case REG_BC:
1766
          case REG_SP:
1767
            check_mach (INS_R800);
1768
            q = frag_more (2);
1769
            *q++ = prefix;
1770
            *q = opcode + ((reg.X_add_number & 3) << 4);
1771
            break;
1772
          default:
1773
            ill_op ();
1774
          }
1775
    }
1776
  return p;
1777
}
1778
 
1779
/* Port specific pseudo ops.  */
1780
const pseudo_typeS md_pseudo_table[] =
1781
{
1782
  { "db" , emit_data, 1},
1783
  { "d24", cons, 3},
1784
  { "d32", cons, 4},
1785
  { "def24", cons, 3},
1786
  { "def32", cons, 4},
1787
  { "defb", emit_data, 1},
1788
  { "defs", s_space, 1}, /* Synonym for ds on some assemblers.  */
1789
  { "defw", cons, 2},
1790
  { "ds",   s_space, 1}, /* Fill with bytes rather than words.  */
1791
  { "dw", cons, 2},
1792
  { "psect", obj_coff_section, 0}, /* TODO: Translate attributes.  */
1793
  { "set", 0, 0},                 /* Real instruction on z80.  */
1794
  { NULL, 0, 0 }
1795
} ;
1796
 
1797
static table_t instab[] =
1798
{
1799
  { "adc",  0x88, 0x4A, emit_adc },
1800
  { "add",  0x80, 0x09, emit_add },
1801
  { "and",  0x00, 0xA0, emit_s },
1802
  { "bit",  0xCB, 0x40, emit_bit },
1803
  { "call", 0xCD, 0xC4, emit_jpcc },
1804
  { "ccf",  0x00, 0x3F, emit_insn },
1805
  { "cp",   0x00, 0xB8, emit_s },
1806
  { "cpd",  0xED, 0xA9, emit_insn },
1807
  { "cpdr", 0xED, 0xB9, emit_insn },
1808
  { "cpi",  0xED, 0xA1, emit_insn },
1809
  { "cpir", 0xED, 0xB1, emit_insn },
1810
  { "cpl",  0x00, 0x2F, emit_insn },
1811
  { "daa",  0x00, 0x27, emit_insn },
1812
  { "dec",  0x0B, 0x05, emit_incdec },
1813
  { "di",   0x00, 0xF3, emit_insn },
1814
  { "djnz", 0x00, 0x10, emit_jr },
1815
  { "ei",   0x00, 0xFB, emit_insn },
1816
  { "ex",   0x00, 0x00, emit_ex},
1817
  { "exx",  0x00, 0xD9, emit_insn },
1818
  { "halt", 0x00, 0x76, emit_insn },
1819
  { "im",   0xED, 0x46, emit_im },
1820
  { "in",   0x00, 0x00, emit_in },
1821
  { "inc",  0x03, 0x04, emit_incdec },
1822
  { "ind",  0xED, 0xAA, emit_insn },
1823
  { "indr", 0xED, 0xBA, emit_insn },
1824
  { "ini",  0xED, 0xA2, emit_insn },
1825
  { "inir", 0xED, 0xB2, emit_insn },
1826
  { "jp",   0xC3, 0xC2, emit_jpcc },
1827
  { "jr",   0x18, 0x20, emit_jrcc },
1828
  { "ld",   0x00, 0x00, emit_ld },
1829
  { "ldd",  0xED, 0xA8, emit_insn },
1830
  { "lddr", 0xED, 0xB8, emit_insn },
1831
  { "ldi",  0xED, 0xA0, emit_insn },
1832
  { "ldir", 0xED, 0xB0, emit_insn },
1833
  { "mulub", 0xED, 0xC5, emit_mulub }, /* R800 only.  */
1834
  { "muluw", 0xED, 0xC3, emit_muluw }, /* R800 only.  */
1835
  { "neg",  0xed, 0x44, emit_insn },
1836
  { "nop",  0x00, 0x00, emit_insn },
1837
  { "or",   0x00, 0xB0, emit_s },
1838
  { "otdr", 0xED, 0xBB, emit_insn },
1839
  { "otir", 0xED, 0xB3, emit_insn },
1840
  { "out",  0x00, 0x00, emit_out },
1841
  { "outd", 0xED, 0xAB, emit_insn },
1842
  { "outi", 0xED, 0xA3, emit_insn },
1843
  { "pop",  0x00, 0xC1, emit_pop },
1844
  { "push", 0x00, 0xC5, emit_pop },
1845
  { "res",  0xCB, 0x80, emit_bit },
1846
  { "ret",  0xC9, 0xC0, emit_retcc },
1847
  { "reti", 0xED, 0x4D, emit_insn },
1848
  { "retn", 0xED, 0x45, emit_insn },
1849
  { "rl",   0xCB, 0x10, emit_mr },
1850
  { "rla",  0x00, 0x17, emit_insn },
1851
  { "rlc",  0xCB, 0x00, emit_mr },
1852
  { "rlca", 0x00, 0x07, emit_insn },
1853
  { "rld",  0xED, 0x6F, emit_insn },
1854
  { "rr",   0xCB, 0x18, emit_mr },
1855
  { "rra",  0x00, 0x1F, emit_insn },
1856
  { "rrc",  0xCB, 0x08, emit_mr },
1857
  { "rrca", 0x00, 0x0F, emit_insn },
1858
  { "rrd",  0xED, 0x67, emit_insn },
1859
  { "rst",  0x00, 0xC7, emit_rst},
1860
  { "sbc",  0x98, 0x42, emit_adc },
1861
  { "scf",  0x00, 0x37, emit_insn },
1862
  { "set",  0xCB, 0xC0, emit_bit },
1863
  { "sla",  0xCB, 0x20, emit_mr },
1864
  { "sli",  0xCB, 0x30, emit_mr },
1865
  { "sll",  0xCB, 0x30, emit_mr },
1866
  { "sra",  0xCB, 0x28, emit_mr },
1867
  { "srl",  0xCB, 0x38, emit_mr },
1868
  { "sub",  0x00, 0x90, emit_s },
1869
  { "xor",  0x00, 0xA8, emit_s },
1870
} ;
1871
 
1872
void
1873
md_assemble (char* str)
1874
{
1875
  const char *p;
1876
  char * old_ptr;
1877
  int i;
1878
  table_t *insp;
1879
 
1880
  err_flag = 0;
1881
  old_ptr = input_line_pointer;
1882
  p = skip_space (str);
1883
  for (i = 0; (i < BUFLEN) && (ISALPHA (*p));)
1884
    buf[i++] = TOLOWER (*p++);
1885
 
1886
  if (i == BUFLEN)
1887
    {
1888
      buf[BUFLEN-3] = buf[BUFLEN-2] = '.'; /* Mark opcode as abbreviated.  */
1889
      buf[BUFLEN-1] = 0;
1890
      as_bad (_("Unknown instruction '%s'"), buf);
1891
    }
1892
  else if ((*p) && (!ISSPACE (*p)))
1893
    as_bad (_("syntax error"));
1894
  else
1895
    {
1896
      buf[i] = 0;
1897
      p = skip_space (p);
1898
      key = buf;
1899
 
1900
      insp = bsearch (&key, instab, ARRAY_SIZE (instab),
1901
                    sizeof (instab[0]), key_cmp);
1902
      if (!insp)
1903
        as_bad (_("Unknown instruction '%s'"), buf);
1904
      else
1905
        {
1906
          p = insp->fp (insp->prefix, insp->opcode, p);
1907
          p = skip_space (p);
1908
        if ((!err_flag) && *p)
1909
          as_bad (_("junk at end of line, first unrecognized character is `%c'"),
1910
                  *p);
1911
        }
1912
    }
1913
  input_line_pointer = old_ptr;
1914
}
1915
 
1916
void
1917
md_apply_fix (fixS * fixP, valueT* valP, segT seg ATTRIBUTE_UNUSED)
1918
{
1919
  long val = * (long *) valP;
1920
  char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
1921
 
1922
  switch (fixP->fx_r_type)
1923
    {
1924
    case BFD_RELOC_8_PCREL:
1925
      if (fixP->fx_addsy)
1926
        {
1927
          fixP->fx_no_overflow = 1;
1928
          fixP->fx_done = 0;
1929
        }
1930
      else
1931
        {
1932
          fixP->fx_no_overflow = (-128 <= val && val < 128);
1933
          if (!fixP->fx_no_overflow)
1934
            as_bad_where (fixP->fx_file, fixP->fx_line,
1935
                          _("relative jump out of range"));
1936
          *buf++ = val;
1937
          fixP->fx_done = 1;
1938
        }
1939
      break;
1940
 
1941
    case BFD_RELOC_Z80_DISP8:
1942
      if (fixP->fx_addsy)
1943
        {
1944
          fixP->fx_no_overflow = 1;
1945
          fixP->fx_done = 0;
1946
        }
1947
      else
1948
        {
1949
          fixP->fx_no_overflow = (-128 <= val && val < 128);
1950
          if (!fixP->fx_no_overflow)
1951
            as_bad_where (fixP->fx_file, fixP->fx_line,
1952
                          _("index offset  out of range"));
1953
          *buf++ = val;
1954
          fixP->fx_done = 1;
1955
        }
1956
      break;
1957
 
1958
    case BFD_RELOC_8:
1959
      if (val > 255 || val < -128)
1960
        as_warn_where (fixP->fx_file, fixP->fx_line, _("overflow"));
1961
      *buf++ = val;
1962
      fixP->fx_no_overflow = 1;
1963
      if (fixP->fx_addsy == NULL)
1964
        fixP->fx_done = 1;
1965
      break;
1966
 
1967
    case BFD_RELOC_16:
1968
      *buf++ = val;
1969
      *buf++ = (val >> 8);
1970
      fixP->fx_no_overflow = 1;
1971
      if (fixP->fx_addsy == NULL)
1972
        fixP->fx_done = 1;
1973
      break;
1974
 
1975
    case BFD_RELOC_24: /* Def24 may produce this.  */
1976
      *buf++ = val;
1977
      *buf++ = (val >> 8);
1978
      *buf++ = (val >> 16);
1979
      fixP->fx_no_overflow = 1;
1980
      if (fixP->fx_addsy == NULL)
1981
        fixP->fx_done = 1;
1982
      break;
1983
 
1984
    case BFD_RELOC_32: /* Def32 and .long may produce this.  */
1985
      *buf++ = val;
1986
      *buf++ = (val >> 8);
1987
      *buf++ = (val >> 16);
1988
      *buf++ = (val >> 24);
1989
      if (fixP->fx_addsy == NULL)
1990
        fixP->fx_done = 1;
1991
      break;
1992
 
1993
    default:
1994
      printf (_("md_apply_fix: unknown r_type 0x%x\n"), fixP->fx_r_type);
1995
      abort ();
1996
    }
1997
}
1998
 
1999
/* GAS will call this to generate a reloc.  GAS will pass the
2000
   resulting reloc to `bfd_install_relocation'.  This currently works
2001
   poorly, as `bfd_install_relocation' often does the wrong thing, and
2002
   instances of `tc_gen_reloc' have been written to work around the
2003
   problems, which in turns makes it difficult to fix
2004
   `bfd_install_relocation'.  */
2005
 
2006
/* If while processing a fixup, a reloc really
2007
   needs to be created then it is done here.  */
2008
 
2009
arelent *
2010
tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED , fixS *fixp)
2011
{
2012
  arelent *reloc;
2013
 
2014
  if (! bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type))
2015
    {
2016
      as_bad_where (fixp->fx_file, fixp->fx_line,
2017
                    _("reloc %d not supported by object file format"),
2018
                    (int) fixp->fx_r_type);
2019
      return NULL;
2020
    }
2021
 
2022
  reloc               = xmalloc (sizeof (arelent));
2023
  reloc->sym_ptr_ptr  = xmalloc (sizeof (asymbol *));
2024
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
2025
  reloc->address      = fixp->fx_frag->fr_address + fixp->fx_where;
2026
  reloc->howto        = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
2027
  reloc->addend       = fixp->fx_offset;
2028
 
2029
  return reloc;
2030
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.