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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gas/] [config/] [tc-z80.c] - Blame information for rev 16

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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