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

Subversion Repositories rf68000

[/] [rf68000/] [trunk/] [software/] [vasm/] [cpus/] [rf68000/] [cpu.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 robfinch
/*
2
** cpu.c Motorola M68k, CPU32 and ColdFire cpu-description file
3
** (c) in 2002-2022 by Frank Wille
4
*/
5
 
6
#include <math.h>
7
#include "vasm.h"
8
#include "error.h"
9
 
10
#include "operands.h"
11
 
12
const struct specreg SpecRegs[] = {
13
#include "specregs.h"
14
};
15
static int specreg_cnt = sizeof(SpecRegs)/sizeof(SpecRegs[0]);
16
 
17
mnemonic mnemonics[] = {
18
#include "opcodes.h"
19
};
20
int mnemonic_cnt = sizeof(mnemonics)/sizeof(mnemonics[0]);
21
 
22
const struct cpu_models models[] = {
23
#include "cpu_models.h"
24
};
25
int model_cnt = sizeof(models)/sizeof(models[0]);
26
 
27
 
28
char *cpu_copyright="vasm M68k/CPU32/ColdFire cpu backend 2.5f (c) 2002-2022 Frank Wille";
29
char *cpuname = "M68k";
30
int bitsperbyte = 8;
31
int bytespertaddr = 4;
32
 
33
int m68k_mid = 1;                     /* default a.out MID: 68000/68010 */
34
 
35
static hashtable *spechash;
36
static hashtable *movchash;
37
 
38
static uint32_t cpu_type = m68000;
39
static expr *baseexp[7];              /* basereg: expression loaded to reg. */
40
static signed char sdreg = -1;        /* current small-data base register */
41
static signed char last_sdreg = -1;
42
static unsigned char optmainswitch = 1;
43
static unsigned char phxass_compat = 0;
44
static unsigned char devpac_compat = 0;
45
static unsigned char gas = 0;         /* true enables GNU-as mnemonics */
46
static unsigned char sgs = 0;         /* true enables & as immediate prefix */
47
static unsigned char no_fpu = 0;      /* true: FPU code/direct. disallowed */
48
static unsigned char elfregs = 0;     /* true: %Rn instead of Rn reg. names */
49
static unsigned char fpu_id = 1;      /* default coprocessor id for FPU */
50
static unsigned char opt_gen = 1;     /* generic optimizations (not Devpac) */
51
static unsigned char opt_movem = 0;   /* MOVEM Rn -> MOVE Rn */
52
static unsigned char opt_pea = 0;     /* MOVE.L #x,-(sp) -> PEA x */
53
static unsigned char opt_clr = 0;     /* MOVE #0,<ea> -> CLR <ea> */
54
static unsigned char opt_st = 0;      /* MOVE.B #-1,<ea> -> ST <ea> */
55
static unsigned char opt_lsl = 0;     /* LSL #1,Dn -> ADD Dn,Dn */
56
static unsigned char opt_mul = 0;     /* MULU/MULS #n,Dn -> LSL/ASL #n,Dn */
57
static unsigned char opt_div = 0;     /* DIVU/DIVS.L #n,Dn -> LSR/ASR #n,Dn */
58
static unsigned char opt_fconst = 1;  /* Fxxx.D #m,FPn -> Fxxx.S #m,FPn */
59
static unsigned char opt_brajmp = 0;  /* branch to different sect. into jump */
60
static unsigned char opt_pc = 1;      /* <label> -> (<label>,PC) */
61
static unsigned char opt_bra = 1;     /* B<cc>.L -> B<cc>.W -> B<cc>.B */
62
static unsigned char opt_allbra = 0;  /* also optimizes sized branches */
63
static unsigned char opt_jbra = 0;    /* JMP/JSR <ext> -> BRA.L/BSR.L (020+) */
64
static unsigned char opt_disp = 1;    /* (0,An) -> (An), etc. */
65
static unsigned char opt_abs = 1;     /* optimize absolute addresses to 16bit */
66
static unsigned char opt_moveq = 1;   /* MOVE.L #x,Dn -> MOVEQ #x,Dn */
67
static unsigned char opt_nmovq = 0;   /* MOVE.L #x,Dn -> MOVEQ #x,Dn & NEG Dn*/
68
static unsigned char opt_quick = 1;   /* ADD/SUB #x,Rn -> ADDQ/SUBQ #x,Rn */
69
static unsigned char opt_branop = 1;  /* BRA.B *+2 -> NOP */
70
static unsigned char opt_bdisp = 1;   /* base displacement optimization */
71
static unsigned char opt_odisp = 1;   /* outer displacement optimization */
72
static unsigned char opt_lea = 1;     /* ADD/SUB #x,An -> LEA (x,An),An */
73
static unsigned char opt_lquick = 1;  /* LEA (x,An),An -> ADDQ/SUBQ #x,An */
74
static unsigned char opt_immaddr = 1; /* <op>.L #x,An -> <op>.W #x,An */
75
static unsigned char opt_speed = 0;   /* optimize for speed, code may grow */
76
static unsigned char opt_size = 0;    /* optimize for size, even when slower */
77
static unsigned char opt_sc = 0;      /* external JMP/JSR are 16-bit PC-rel. */
78
static unsigned char opt_sd = 0;      /* small data opts: abs.L -> (d16,An) */
79
static unsigned char no_opt = 0;      /* don't optimize at all! */
80
static unsigned char warn_opts = 0;   /* warn on optimizations/translations */
81
static unsigned char convert_brackets = 0;  /* convert [ into ( for <020 */
82
static unsigned char typechk = 1;     /* check value types and ranges */
83
static unsigned char ign_unambig_ext = 0;  /* don't check unambig. size ext. */
84
static unsigned char ign_unsized_ext = 0;  /* don't check size on unsized */
85
static unsigned char regsymredef = 0; /* allow redefinition of reg. symbols */
86
static unsigned char kick1hunks = 0;  /* no optim. to 32-bit PC-displacem. */
87
static unsigned char no_dpc = 0;      /* abs. PC-displacments not allowed */
88
static unsigned char extsd = 0;       /* small-data with ext. addr. modes */
89
static char current_ext;              /* extension of current parsed inst. */
90
 
91
static char b_str[] = "b";
92
static char w_str[] = "w";
93
static char l_str[] = "l";
94
static char q_str[] = "q";
95
static char s_str[] = "s";
96
static char d_str[] = "d";
97
static char x_str[] = "x";
98
static char p_str[] = "p";
99
 
100
static char optc_name[] = "__OPTC";
101
static char cpu_name[] = "__CPU";
102
static char mmu_name[] = "__MMU";
103
static char fpu_name[] = "__FPU";
104
static char g2_name[] = "__G2";
105
static char lk_name[] = "__LK";
106
static char movembytes_name[] = "_MOVEMBYTES";
107
static char movemregs_name[] = "_MOVEMREGS";
108
static char movemsize_name[] = " MOVEMSIZE";
109
 
110
static symbol *movembytes,*movemregs,*movemsize;
111
 
112
static int OC_JMP,OC_JSR,OC_MOVEQ,OC_MOV3Q,OC_LEA,OC_PEA,OC_SUBA,OC_CLR;
113
static int OC_ST,OC_ADDQ,OC_SUBQ,OC_ADDA,OC_ADD,OC_BRA,OC_BSR,OC_TST;
114
static int OC_NOT,OC_NOOP,OC_FNOP,OC_MOVEA,OC_EXT,OC_MVZ,OC_MOVE;
115
static int OC_ASRI,OC_LSRI,OC_ASLI,OC_LSLI,OC_NEG;
116
static int OC_FMOVEMTOLIST,OC_FMOVEMTOSPEC,OC_FMOVEMFROMSPEC;
117
static int OC_FMUL,OC_FSMUL,OC_FDMUL,OC_FSGLMUL,OC_LOAD,OC_SWAP;
118
 
119
static struct {
120
  int *var;
121
  const char *name;
122
  int16_t optype[2];
123
} code_tab[] = {
124
  /* Note: keep same order as in mnemonics table! */
125
  &OC_ADD,              "add",    DA,0,
126
  &OC_ADDA,             "adda",   0,0,
127
  &OC_ADDQ,             "addq",   0,AD,
128
  &OC_ASLI,             "asl",    QI,0,
129
  &OC_ASRI,             "asr",    QI,0,
130
  &OC_BRA,              "bra",    0,0,
131
  &OC_BSR,              "bsr",    0,0,
132
  &OC_CLR,              "clr",    0,0,
133
  &OC_EXT,              "ext",    0,0,
134
  &OC_FMOVEMTOLIST,     "fmovem", MR,FL,
135
  &OC_FMOVEMFROMSPEC,   "fmovem", FS,AM,
136
  &OC_FMOVEMTOSPEC,     "fmovem", MA,FS,
137
  &OC_FMUL,             "fmul",   FA,F_,
138
  &OC_FSMUL,            "fsmul",  FA,F_,
139
  &OC_FDMUL,            "fdmul",  FA,F_,
140
  &OC_FNOP,             "fnop",   0,0,
141
  &OC_FSGLMUL,          "fsglmul",FA,F_,
142
  &OC_JMP,              "jmp",    0,0,
143
  &OC_JSR,              "jsr",    0,0,
144
  &OC_LEA,              "lea",    0,0,
145
  &OC_LOAD,             "load",   0,0,
146
  &OC_LSLI,             "lsl",    QI,0,
147
  &OC_LSRI,             "lsr",    QI,0,
148
  &OC_MOV3Q,            "mov3q",  0,0,
149
  &OC_MOVE,             "move",   DA,AD,
150
  &OC_MOVEA,            "movea",  0,0,
151
  &OC_MOVEQ,            "moveq",  0,0,
152
  &OC_MVZ,              "mvz",    0,0,
153
  &OC_NEG,              "neg",    D_,0,
154
  &OC_NOT,              "not",    0,0,
155
  &OC_PEA,              "pea",    0,0,
156
  &OC_ST,               "st",     AD,0,
157
  &OC_SUBA,             "suba",   0,0,
158
  &OC_SUBQ,             "subq",   0,AD,
159
  &OC_SWAP,             "swap",   D_,0,
160
  &OC_TST,              "tst",    0,0,
161
  &OC_NOOP,             " no-op", 0,0
162
};
163
 
164
/* Several instruction copies allow optimizations to generate
165
   additional instructions.
166
   The ipslot has to be reset to 0, before using copy_instruction(),
167
   ip_singleop() and ip_dualop(). */
168
#define MAX_IP_COPIES 4
169
static int ipslot;
170
static instruction newip[MAX_IP_COPIES];
171
static operand newop[MAX_IP_COPIES][MAX_OPERANDS];
172
 
173
void *rf68k_setval(int be,void *dest,size_t size,uint64_t val)
174
{
175
        return (setval(be,dest,size,val));
176
}
177
 
178
void *rf68k_setval_signext(int be,void *dest,size_t extsz,size_t valsz,int64_t val)
179
{
180
        return(setval_signext(be,dest,extsz,valsz,val));
181
}
182
 
183
operand *new_operand(void)
184
{
185
  return mycalloc(sizeof(operand));
186
}
187
 
188
 
189
static void free_op_exp(operand *op)
190
{
191
  if (op) {
192
    if (op->value[0])
193
      free_expr(op->value[0]);
194
    if (op->value[1])
195
      free_expr(op->value[1]);
196
    op->value[0] = op->value[1] = NULL;
197
  }
198
}
199
 
200
 
201
static void free_operand(operand *op)
202
{
203
  if (op) {
204
    free_op_exp(op);
205
    myfree(op);
206
  }
207
}
208
 
209
 
210
static operand *clr_operand(operand *op)
211
{
212
  memset(op,0,sizeof(operand));
213
  return op;
214
}
215
 
216
 
217
void init_instruction_ext(instruction_ext *ixp)
218
{
219
  ixp->un.real.flags = 0;
220
  ixp->un.real.last_size = -1;
221
  ixp->un.real.orig_ext = -1;
222
}
223
 
224
 
225
static instruction *clr_instruction(instruction *ip)
226
{
227
  memset(ip,0,sizeof(instruction));
228
  return ip;
229
}
230
 
231
 
232
static instruction *copy_instruction(instruction *sip)
233
/* copy an instruction and its operands */
234
{
235
  instruction *dip = &newip[ipslot];
236
  operand *dop = newop[ipslot];
237
  int i;
238
 
239
  if (ipslot >= MAX_IP_COPIES)
240
    ierror(0);
241
  dip->code = sip->code;
242
  dip->qualifiers[0] = sip->qualifiers[0];
243
  for (i=0; i<MAX_OPERANDS; i++) {
244
    if (sip->op[i] != NULL) {
245
      dip->op[i] = &dop[i];
246
      *dip->op[i] = *sip->op[i];
247
    }
248
    else
249
      dip->op[i] = NULL;
250
  }
251
  dip->ext = sip->ext;
252
  ++ipslot;
253
  return dip;
254
}
255
 
256
 
257
int m68k_data_operand(int bits)
258
/* return data operand type for these number of bits */
259
{
260
  switch (bits) {
261
    case 8: return OP_D8;
262
    case 16: return OP_D16;
263
    case 32: return OP_D32;
264
    case 64: return OP_D64;
265
    case OPSZ_FLOAT|32: return OP_F32;
266
    case OPSZ_FLOAT|64: return OP_F64;
267
    case OPSZ_FLOAT|96: return OP_F96;
268
    case OPSZ_FLOAT|97: return OP_FPD;  /* packed decimal */
269
  }
270
  cpu_error(38,OPSZ_BITS(bits)); /* data obj. with n bits size are not supp. */
271
  return 0;
272
}
273
 
274
 
275
int m68k_available(int idx)
276
/* Check if mnemonic is available for selected cpu_type. */
277
{
278
  return (mnemonics[idx].ext.available & cpu_type) != 0;
279
}
280
 
281
 
282
int m68k_operand_optional(operand *op,int type)
283
/* Check if operand is optional */
284
{
285
  if (optypes[type].flags & OTF_OPT) {
286
    memset(op,0,sizeof(operand));
287
    op->mode = -1;  /* @@@FIXME! */
288
    return 1;
289
  }
290
  return 0;
291
}
292
 
293
 
294
static int phxass_cpu_num(uint32_t type)
295
{
296
  static const int cpus[] = {
297
    68000,68010,68020,68030,68040,68060
298
  };
299
  int i;
300
 
301
  for (i=5; i>=0; i--)
302
    if (type & (1L<<i))
303
      return cpus[i];
304
 
305
  return 0;  /* not a cpu known to PhxAss, like for example ColdFire */
306
}
307
 
308
 
309
static void set_optc_symbol(void)
310
{
311
  /* set PhxAss __OPTC symbol from current optimization flags */
312
  taddr optc = 0;
313
 
314
  if (optmainswitch && !no_opt) {
315
    if (opt_disp && opt_abs && opt_moveq && opt_lea && opt_immaddr)
316
      optc |= 0x001;
317
    if (opt_pc)
318
      optc |= 0x002;
319
    if (opt_quick && opt_lquick)
320
      optc |= 0x004;
321
    if (opt_bra && opt_brajmp)
322
      optc |= 0x108;  /* T is always set together with B */
323
    if (opt_lsl)
324
      optc |= 0x010;
325
    if (opt_pea)
326
      optc |= 0x020;
327
    if (opt_clr && opt_st && opt_fconst)
328
      optc |= 0x040;
329
    if (opt_gen)
330
      optc |= 0x080;
331
    if (opt_movem)
332
      optc |= 0x200;
333
  }
334
 
335
  set_internal_abs(optc_name,optc);
336
}
337
 
338
 
339
static void set_g2_symbol(void)
340
{
341
  /* Devpac __G2 symbol
342
   * Bits 0-7:   version and features (e.g. 43) - we don't use it!
343
   * Bits 8-15:  cpu type - 68000
344
   * Bits 16-23: host system - we set all bits to indicate an unknown host
345
   */
346
  set_internal_abs(g2_name,0xff0000|((phxass_cpu_num(cpu_type)-68000)<<8));
347
}
348
 
349
 
350
static void check_apollo_conflicts(void)
351
{
352
  static int apollo_checks_done = 0;
353
 
354
  if (!apollo_checks_done) {
355
    /* When the Apollo cpu type is enabled for the first time, we have
356
       to make sure that "load" is disabled as a directive. */
357
    hashdata data;
358
 
359
    if (find_name_nc(dirhash,mnemonics[OC_LOAD].name,&data)) {
360
      rem_hashentry(dirhash,mnemonics[OC_LOAD].name,nocase);
361
      /*cpu_error(63,mnemonics[OC_LOAD].name);*/
362
    }
363
    apollo_checks_done = 1;
364
  }
365
}
366
 
367
 
368
void cpu_opts(void *opts)
369
/* set cpu options for following atoms */
370
{
371
  int cmd = ((optcmd *)opts)->cmd;
372
  int arg = ((optcmd *)opts)->arg;
373
 
374
  if (cmd>OCMD_NOOPT && cmd<OCMD_OPTWARN && arg!=0)
375
    no_opt = 0;
376
 
377
  switch (cmd) {
378
    case OCMD_NOP:
379
      break;
380
    case OCMD_CPU:
381
      cpu_type = arg;
382
      if (cpu_type & (m68040up|mcffpu))
383
        fpu_id = 1;
384
      if (phxass_compat) {
385
        set_internal_abs(cpu_name,phxass_cpu_num(cpu_type));
386
        set_internal_abs(mmu_name,(cpu_type & mmmu)!=0);
387
      }
388
      if (devpac_compat)
389
        set_g2_symbol();
390
      set_internal_abs(vasmsym_name,cpu_type&CPUMASK);
391
      if (cpu_type & apollo)
392
        check_apollo_conflicts();
393
      break;
394
    case OCMD_FPU:
395
      fpu_id = arg;
396
      if (phxass_compat)
397
        set_internal_abs(fpu_name,(cpu_type & mfloat)?fpu_id:0);
398
      break;
399
    case OCMD_SDREG:
400
      sdreg = arg;
401
      break;
402
 
403
    case OCMD_NOOPT: no_opt=arg; break;
404
    case OCMD_OPTGEN: opt_gen=arg; break;
405
    case OCMD_OPTMOVEM: opt_movem=arg; break;
406
    case OCMD_OPTPEA: opt_pea=arg; break;
407
    case OCMD_OPTCLR: opt_clr=arg; break;
408
    case OCMD_OPTST: opt_st=arg; break;
409
    case OCMD_OPTLSL: opt_lsl=arg; break;
410
    case OCMD_OPTMUL: opt_mul=arg; break;
411
    case OCMD_OPTDIV: opt_div=arg; break;
412
    case OCMD_OPTFCONST: opt_fconst=arg; break;
413
    case OCMD_OPTBRAJMP: opt_brajmp=arg; break;
414
    case OCMD_OPTJBRA: opt_jbra=arg; break;
415
    case OCMD_OPTPC: opt_pc=arg; break;
416
    case OCMD_OPTBRA: opt_bra=arg; break;
417
    case OCMD_OPTDISP: opt_disp=arg; break;
418
    case OCMD_OPTABS: opt_abs=arg; break;
419
    case OCMD_OPTMOVEQ: opt_moveq=arg; break;
420
    case OCMD_OPTNMOVQ: opt_nmovq=arg; break;
421
    case OCMD_OPTQUICK: opt_quick=arg; break;
422
    case OCMD_OPTBRANOP: opt_branop=arg; break;
423
    case OCMD_OPTBDISP: opt_bdisp=arg; break;
424
    case OCMD_OPTODISP: opt_odisp=arg; break;
425
    case OCMD_OPTLEA: opt_lea=arg; break;
426
    case OCMD_OPTLQUICK: opt_lquick=arg; break;
427
    case OCMD_OPTIMMADDR: opt_immaddr=arg; break;
428
    case OCMD_OPTSPEED: opt_speed=arg; break;
429
    case OCMD_OPTSIZE: opt_size=arg; break;
430
    case OCMD_SMALLCODE: opt_sc=arg; break;
431
    case OCMD_SMALLDATA: opt_sd=arg; break;
432
 
433
    case OCMD_OPTWARN: warn_opts=arg; break;
434
    case OCMD_CHKPIC: pic_check=arg; break;
435
    case OCMD_CHKTYPE: typechk=arg; break;
436
    case OCMD_NOWARN: no_warn=arg; break;
437
 
438
    default: ierror(0); break;
439
  }
440
}
441
 
442
 
443
static void add_cpu_opt(section *s,int cmd,int arg)
444
{
445
  if (s || current_section) {
446
    optcmd *new = mymalloc(sizeof(optcmd));
447
 
448
    new->cmd = cmd;
449
    new->arg = arg;
450
    add_atom(s,new_opts_atom(new));
451
    cpu_opts(new);
452
  }
453
  else {
454
    /* no section known at this point, so set the option immediately: it will
455
       automatically become the initial option of the first section */
456
    optcmd o;
457
 
458
    o.cmd = cmd;
459
    o.arg = arg;
460
    cpu_opts(&o);
461
  }
462
}
463
 
464
 
465
static void cpu_opts_optinit(section *s)
466
/* create initial optimization atoms */
467
{
468
  add_cpu_opt(s,OCMD_NOOPT,no_opt);
469
  add_cpu_opt(s,OCMD_OPTGEN,opt_gen);
470
  add_cpu_opt(s,OCMD_OPTMOVEM,opt_movem);
471
  add_cpu_opt(s,OCMD_OPTPEA,opt_pea);
472
  add_cpu_opt(s,OCMD_OPTCLR,opt_clr);
473
  add_cpu_opt(s,OCMD_OPTST,opt_st);
474
  add_cpu_opt(s,OCMD_OPTLSL,opt_lsl);
475
  add_cpu_opt(s,OCMD_OPTMUL,opt_mul);
476
  add_cpu_opt(s,OCMD_OPTDIV,opt_div);
477
  add_cpu_opt(s,OCMD_OPTFCONST,opt_fconst);
478
  add_cpu_opt(s,OCMD_OPTBRAJMP,opt_brajmp);
479
  add_cpu_opt(s,OCMD_OPTJBRA,opt_jbra);
480
  add_cpu_opt(s,OCMD_OPTPC,opt_pc);
481
  add_cpu_opt(s,OCMD_OPTBRA,opt_bra);
482
  add_cpu_opt(s,OCMD_OPTDISP,opt_disp);
483
  add_cpu_opt(s,OCMD_OPTABS,opt_abs);
484
  add_cpu_opt(s,OCMD_OPTMOVEQ,opt_moveq);
485
  add_cpu_opt(s,OCMD_OPTNMOVQ,opt_nmovq);
486
  add_cpu_opt(s,OCMD_OPTQUICK,opt_quick);
487
  add_cpu_opt(s,OCMD_OPTBRANOP,opt_branop);
488
  add_cpu_opt(s,OCMD_OPTBDISP,opt_bdisp);
489
  add_cpu_opt(s,OCMD_OPTODISP,opt_odisp);
490
  add_cpu_opt(s,OCMD_OPTLEA,opt_lea);
491
  add_cpu_opt(s,OCMD_OPTLQUICK,opt_lquick);
492
  add_cpu_opt(s,OCMD_OPTIMMADDR,opt_immaddr);
493
  add_cpu_opt(s,OCMD_OPTSPEED,opt_speed);
494
  add_cpu_opt(s,OCMD_OPTSIZE,opt_size);
495
  add_cpu_opt(s,OCMD_SMALLCODE,opt_sc);
496
  add_cpu_opt(s,OCMD_SMALLDATA,opt_sd);
497
 
498
  if (phxass_compat)
499
    set_optc_symbol();
500
}
501
 
502
 
503
void cpu_opts_init(section *s)
504
/* set initial cpu opts */
505
{
506
  add_cpu_opt(s,OCMD_CPU,cpu_type);
507
  add_cpu_opt(s,OCMD_FPU,fpu_id);
508
  add_cpu_opt(s,OCMD_SDREG,sdreg);
509
  cpu_opts_optinit(s);
510
  add_cpu_opt(s,OCMD_OPTWARN,warn_opts);
511
  add_cpu_opt(s,OCMD_CHKPIC,pic_check);
512
  add_cpu_opt(s,OCMD_CHKTYPE,typechk);
513
  add_cpu_opt(s,OCMD_NOWARN,no_warn);
514
}
515
 
516
 
517
void print_cpu_opts(FILE *f,void *opts)
518
{
519
  static const char *ocmds[] = {
520
    "opt generic","opt movem","opt pea","opt clr","opt st","opt lsl",
521
    "opt mul","opt div","opt float const","opt branch to jump",
522
    "opt jump to longbranch","opt pc-relative","opt branch",
523
    "opt displacement","opt absolute","opt moveq","opt neg.moveq",
524
    "opt quick", "opt branch to nop","opt base disp","opt outer disp",
525
    "opt adda/subq to lea","opt lea to addq/subq","opt immediate areg",
526
    "opt for speed","opt for size","opt small code","opt small data",
527
    "warn about optimizations","PIC check","type and range checks",
528
    "hide all warnings"
529
  };
530
  static const char *cpus[32] = {
531
    "m68000","m68010","m68020","m68030","m68040","m68060",
532
    "m6888x","m68851","cpu32",
533
    "CF-ISA_A","CF-ISA_A+","CF-ISA_B","CF-ISA_C",
534
    "CF-hwdiv","CF-MAC","CF-EMAC","CF-USP","CF-FPU","CF-MMU",NULL,
535
    "ac68080",
536
    NULL
537
  };
538
  int cmd = ((optcmd *)opts)->cmd;
539
  int arg = ((optcmd *)opts)->arg;
540
 
541
  fprintf(f,"opts: ");
542
  if (cmd == OCMD_CPU) {
543
    int i;
544
 
545
    arg &= CPUMASK;
546
    fprintf(f,"cpu types:");
547
    for (i=0; i<32; i++) {
548
      if ((arg & (1<<i)) && cpus[i])
549
        fprintf(f," %s",cpus[i]);
550
    }
551
  }
552
  else if (cmd == OCMD_NOP)
553
    fprintf(f,"none");
554
  else if (cmd == OCMD_FPU)
555
    fprintf(f,"fpu id %d (f%xxx)",arg,(unsigned)arg<<1);
556
  else if (cmd == OCMD_SDREG) {
557
    if (arg >= 0)
558
      fprintf(f,"small data base reg is a%d",arg);
559
    else
560
      fprintf(f,"small data is disabled");
561
  }
562
  else if (cmd == OCMD_NOOPT)
563
    fprintf(f,"optimizations %sabled",arg?"dis":"en");
564
  else
565
    fprintf(f,"%s (%d)",ocmds[cmd-OCMD_OPTGEN],arg);
566
}
567
 
568
 
569
static void conv2ieee80(int be,uint8_t *buf,tfloat f)
570
/* extended precision */
571
/* @@@ Warning: precision is lost! Converting to double precision. */
572
{
573
  uint64_t man;
574
  uint32_t exp;
575
  union {
576
    double dp;
577
    uint64_t x;
578
  } conv;
579
 
580
  conv.dp = (double)f;
581
  if (conv.x == 0) {
582
    memset(buf,0,12);  /* 0.0 */
583
  }
584
  else if (conv.x == 0x8000000000000000LL) {
585
    if (be) {
586
      buf[0] = 0x80;
587
      memset(buf+1,0,11);  /* -0.0 */
588
    }
589
    else {
590
      buf[11] = 0x80;
591
      memset(buf,0,11);  /* -0.0 */
592
    }
593
  }
594
  else {
595
    man = ((conv.x & 0xfffffffffffffLL) << 11) | 0x8000000000000000LL;
596
    exp = ((conv.x >> 52) & 0x7ff) - 0x3ff + 0x3fff;
597
    if (be) {
598
      buf[0] = ((conv.x >> 56) & 0x80) | (exp >> 8);
599
      buf[1] = exp & 0xff;
600
      buf[2] = 0;
601
      buf[3] = 0;
602
      rf68k_setval(1,buf+4,8,man);
603
    }
604
    else {
605
      buf[11] = ((conv.x >> 56) & 0x80) | (exp >> 8);
606
      buf[10] = exp & 0xff;
607
      buf[9] = 0;
608
      buf[8] = 0;
609
      rf68k_setval(0,buf,8,man);
610
    }
611
  }
612
}
613
 
614
 
615
static void pkdec_out(unsigned char *p,unsigned val)
616
/* convert value between 0 and 99 to BCD for Packed Decimal format */
617
{
618
  *p = (((val / 10) % 10) << 4) | (val % 10);
619
}
620
 
621
 
622
static void conv2packed(unsigned char *buf,tfloat f)
623
{
624
  static const unsigned char masks[2] = { 0x0f, 0xf0 };
625
  static const unsigned char shifts[2] = { 4, 0 };
626
  char nrm[32];
627
  int i,e;
628
  unsigned long long r;
629
  unsigned char s = 0;
630
  unsigned char *p;
631
 
632
  if (sprintf(nrm,"%1.16e",(double)f) >= 31)
633
    ierror(0);
634
  if (sscanf(nrm,"%d.%llue%d",&i,&r,&e) != 3)  /* @@@ r is ignored here */
635
    ierror(0);
636
  if (i < 0) {
637
    i = -i;
638
    s |= 0x80;  /* sign of mantissa */
639
  }
640
  if (e < 0) {
641
    e = -e;
642
    s |= 0x40;  /* sign of exponent */
643
  }
644
  pkdec_out(&buf[0],(e/100)%10);
645
  buf[0] |= s;
646
  pkdec_out(&buf[1],e%100);
647
  buf[2] = 0;
648
  pkdec_out(&buf[3],i%10);
649
  p = (unsigned char *)nrm;
650
  while (*p++ != '.');  /* find beginning of fractional part */
651
  for (i=8; i<24; i++) {
652
    buf[i>>1] &= masks[i&1];
653
    if (isdigit(*p))
654
      buf[i>>1] |= (*p++ & 0x0f) << shifts[i&1];
655
  }
656
}
657
 
658
 
659
static taddr reverse(uint32_t v,int size)
660
/* reverse bit-order in v */
661
{
662
  int i;
663
  uint32_t r = 0;
664
 
665
  for (i=0; i<size; i++) {
666
    r <<= 1;
667
    if (v & (1L<<i))
668
      r++;
669
  }
670
  return (taddr)r;
671
}
672
 
673
 
674
static int cntones(taddr v,int bits)
675
/* count number of bits set */
676
{
677
  int i,r;
678
 
679
  for (i=0,r=0; i<bits; i++) {
680
    r += v & 1;
681
    v >>= 1;
682
  }
683
  return r;
684
}
685
 
686
 
687
static int lsbit(taddr v,int start,int end)
688
/* return index of first least significant bit set */
689
{
690
  int i;
691
 
692
  for (i=start; i<end; i++) {
693
    if (v & (1<<i))
694
      break;
695
  }
696
  return i;
697
}
698
 
699
 
700
static int msbit(taddr v,int start,int end)
701
/* return index of first most significant bit set */
702
{
703
  int i;
704
 
705
  for (i=start; i>end; i--) {
706
    if (v & (1<<i))
707
      break;
708
  }
709
  return i;
710
}
711
 
712
 
713
static int getextcode(char c)
714
{
715
  switch (tolower((unsigned char)c)) {
716
    case 'b':
717
      return EXT_BYTE;
718
    case 'w':
719
      return EXT_WORD;
720
    case 'l':
721
      return EXT_LONG;
722
    case 's':
723
      return EXT_SINGLE;
724
    case 'd':
725
      return EXT_DOUBLE;
726
    case 'x':
727
      return EXT_EXTENDED;
728
    case 'p':
729
      return EXT_PACKED;
730
  }
731
  return 0;
732
}
733
 
734
 
735
static int getmacextcode(char c)
736
{
737
  switch (tolower((unsigned char)c)) {
738
    case 'l':
739
      return EXT_LOWER;
740
    case 'u':
741
      return EXT_UPPER;
742
  }
743
  return 0;
744
}
745
 
746
 
747
static int read_extension(char **s,int extcode)
748
{
749
  char *p = *s;
750
 
751
  if (*p++ == '.') {
752
    int x = getextcode(*p++);
753
 
754
    if (x) {
755
      extcode = x;
756
      *s = p;
757
    }
758
  }
759
  return extcode;
760
}
761
 
762
 
763
static int is_float_ext(void)
764
{
765
  switch (current_ext) {
766
    case 's':
767
    case 'd':
768
    case 'x':
769
    case 'p':
770
      return 1;
771
  }
772
  return 0;
773
}
774
 
775
 
776
static uint16_t lc_ext_to_size(char ext)
777
/* convert lower-case extension character to a SIZE_xxx code */
778
{
779
  switch (ext) {
780
    case 'b': return SIZE_BYTE;
781
    case 'w': return SIZE_WORD;
782
    case 'l': return SIZE_LONG;
783
    case 's': return SIZE_SINGLE;
784
    case 'd': return SIZE_DOUBLE;
785
    case 'x': return SIZE_EXTENDED;
786
    case 'p': return SIZE_PACKED;
787
    case 'q': return SIZE_DOUBLE;
788
  }
789
  return 0;
790
}
791
 
792
 
793
static int branch_size(char ext)
794
/* branch size for each size-extension code */
795
{
796
  switch (ext) {
797
    case 'b':
798
    case 's':
799
      return 0;
800
    case 'l':
801
      return 4;
802
  }
803
  return 2;
804
}
805
 
806
 
807
int ext_unary_eval(int type,taddr val,taddr *result,int cnst)
808
{
809
  switch (type) {
810
    case CNTONES:
811
      *result = cnst ? (taddr)cntones(val,32) : 0;
812
      return 1;
813
    default:
814
      break;
815
  }
816
  return 0;  /* unknown type */
817
}
818
 
819
 
820
static uint16_t eval_rlsymbol(char **start)
821
/* Parse and evaluate a register list symbol, return its value.
822
   Return zero otherwise. May cause an error message on illegal symbol type. */
823
{
824
  symbol *sym;
825
  char *name;
826
  taddr val = 0;
827
 
828
  if (name = parse_symbol(start)) {
829
    if ((sym = find_symbol(name)) &&
830
        (sym->flags & REGLIST) && sym->type==EXPRESSION) {
831
      if (!eval_expr(sym->expr,&val,NULL,0))
832
        ierror(0);  /* REGLIST must be constant */
833
    }
834
    else
835
      cpu_error(66);  /* not a valid register list symbol */
836
  }
837
  return (uint16_t)val;
838
}
839
 
840
 
841
static signed char getreg(char **start,int indexreg)
842
/* checks stream for a data or address register (might include extension)
843
   return -1 on failure, otherwise return a bit-field containing
844
   the following information:
845
  Bit7 6     5     4     3         2    1    0
846
   ---------------------------------------------
847
  | 0 | extension (1-7) | An reg. | reg. number |
848
   --------------------------------------------- */
849
{
850
  char *s = *start;
851
  char *p = NULL;
852
  char *q;
853
  strbuf *loc;
854
  signed char reg = -1;
855
  regsym *sym;
856
 
857
  if (loc = get_local_label(0,&s)) {
858
    p = loc->str;
859
    q = p + loc->len;
860
  }
861
  else if (ISIDSTART(*s) || (elfregs && *s=='%')) {
862
    p = s++;
863
    while (ISIDCHAR(*s) && *s!='.')
864
      s++;
865
    q = s;
866
    if (elfregs && *p=='%')
867
      p++;
868
    if (s-p == 2) {
869
      if ((*p=='D' || *p=='d' || *p=='A' || *p=='a') &&
870
          (*(p+1)>='0' && *(p+1)<='7'))
871
        reg = ((*p=='A' || *p=='a') ? REGAn : 0) | (*(p+1) - '0');
872
      else if ((*p=='S' || *p=='s') && (*(p+1)=='P' || *(p+1)=='p'))
873
        reg = REGAn + 7;
874
    }
875
  }
876
  if (reg<0 && p!=NULL && ((sym = find_regsym(p,q-p)) != NULL)) {
877
    /* register symbol found */
878
    if (sym->reg_type==RSTYPE_Dn || sym->reg_type==RSTYPE_An)
879
      reg = ((sym->reg_type==RSTYPE_An) ? REGAn : 0)
880
            | (signed char)sym->reg_num;
881
  }
882
 
883
  if (reg >= 0) {
884
    if (*s == '.') {
885
      int extcode;
886
 
887
      if (!indexreg) {
888
        /* ColdFire MAC register extension? */
889
        extcode = getmacextcode(*(s+1));
890
      }
891
      else {
892
        /* index register extension */
893
        extcode = getextcode(*(s+1));
894
      }
895
      if (extcode) {
896
        reg |= extcode << 4;
897
        *start = s + 2;
898
      }
899
    }
900
    else
901
      *start = s;
902
  }
903
  return reg;
904
}
905
 
906
 
907
static uint16_t scan_Rnlist(char **start)
908
/* returns bit field for a Dn/An register list
909
   returns 0 otherwise */
910
{
911
  char *p = *start;
912
 
913
  if (getreg(&p,0) >= 0) {
914
    uint16_t list = 0;
915
    signed char lastreg=-1,reg,rx;
916
    int rangemode = 0;
917
 
918
    for (p=*start; *p; p++) {
919
      p = skip(p);
920
      if (rangemode && (*p>='0' && *p<='7')) {  /* allows d0-7 */
921
        reg = (lastreg & REGAn) | (*p - '0');
922
        p++;
923
      }
924
      else if ((reg = getreg(&p,0)) < 0) {
925
        cpu_error(2);  /* invalid register list */
926
        return 0;
927
      }
928
 
929
      if (rangemode) {
930
        /* lastreg...reg describes a range of registers */
931
        list &= ~(1<<lastreg);
932
        if (lastreg > reg) {
933
          rx = reg;
934
          reg = lastreg;
935
          lastreg = rx;
936
        }
937
        else if (lastreg == reg)
938
          cpu_error(17);  /* Rn-Rn */
939
        for (rx=lastreg; rx<=reg; rx++) {
940
          if (list & (1<<rx))
941
            cpu_error(17);  /* double register in list */
942
          else
943
            list |= 1<<rx;
944
        }
945
        rangemode = 0;
946
      }
947
      else {
948
        if (list & (1<<reg))
949
          cpu_error(17);  /* double register in list */
950
        else
951
          list |= 1<<reg;
952
      }
953
 
954
      lastreg = reg;
955
      p = skip(p);
956
      if (*p == '-')
957
        rangemode = 1;
958
      else if (*p != '/')
959
        break;
960
    }
961
    *start = p;
962
    return list;
963
  }
964
  return eval_rlsymbol(start);
965
}
966
 
967
 
968
static signed char getbreg(char **start)
969
{
970
  signed char reg = -1;
971
  char *s = *start;
972
  char *p = NULL;
973
  char *q;
974
  strbuf *loc;
975
  regsym *sym;
976
 
977
  if (loc = get_local_label(0,&s)) {
978
    p = loc->str;
979
    q = p + loc->len;
980
  }
981
  else if (ISIDSTART(*s) || (elfregs && *s=='%')) {
982
    p = s++;
983
    while (ISIDCHAR(*s) && *s!='.')
984
      s++;
985
    q = s;
986
    if (elfregs && *p=='%')
987
      p++;
988
    if (s-p==2 && (*p=='B' || *p=='b') && (*(p+1)>='0' && *(p+1)<='7'))
989
      reg = *(p+1) - '0';
990
  }
991
  if (reg<0 && p!=NULL && ((sym = find_regsym(p,q-p)) != NULL)) {
992
    /* register symbol found */
993
    if (sym->reg_type==RSTYPE_Bn)
994
      reg = (signed char)sym->reg_num;
995
  }
996
  if (reg >= 0)
997
    *start = s;
998
  return reg;
999
}
1000
 
1001
 
1002
static signed char getfreg(char **start)
1003
/* checks stream for an FPU register
1004
   return -1 on failure, 0-7 for FP0-FP7 and
1005
   10 for FPIAR, 11 for FPSR and 12 for FPCR */
1006
{
1007
  signed char reg = -1;
1008
  char *s = *start;
1009
  char *p = NULL;
1010
  char *q;
1011
  strbuf *loc;
1012
  regsym *sym;
1013
 
1014
  if (loc = get_local_label(0,&s)) {
1015
    p = loc->str;
1016
    q = p + loc->len;
1017
  }
1018
  else if (ISIDSTART(*s) || (elfregs && *s=='%')) {
1019
    p = s++;
1020
    while (ISIDCHAR(*s) && *s!='.')
1021
      s++;
1022
    q = s;
1023
    if (elfregs && *p=='%')
1024
      p++;
1025
    if (s-p==3 && !strnicmp(p,"FP",2) && (*(p+2)>='0' && *(p+2)<='7'))
1026
      reg = *(p+2) - '0';
1027
    else if (s-p==5 && !strnicmp(p,"FPIAR",5))
1028
      reg = 10;
1029
    else if (s-p==4 && !strnicmp(p,"FPSR",4))
1030
      reg = 11;
1031
    else if (s-p==4 && !strnicmp(p,"FPCR",4))
1032
      reg = 12;
1033
 
1034
  }
1035
  if (reg<0 && p!=NULL && ((sym = find_regsym(p,q-p)) != NULL)) {
1036
    /* register symbol found */
1037
    if (sym->reg_type==RSTYPE_FPn)
1038
      reg = (signed char)sym->reg_num;
1039
  }
1040
  if (reg >= 0)
1041
    *start = s;
1042
  return reg;
1043
}
1044
 
1045
 
1046
static uint16_t scan_FPnlist(char **start)
1047
/* returns bit field for a FPn or FPIAR/FPSR/FPCR register list
1048
   returns 0 otherwise */
1049
{
1050
  char *p = *start;
1051
 
1052
  if (getfreg(&p) >= 0) {
1053
    signed char lastreg=-1,reg,rx;
1054
    uint16_t list = 0;
1055
    int fpnmode = -1;
1056
    int rangemode = 0;
1057
 
1058
    for (p=*start; *p; p++) {
1059
      p = skip(p);
1060
      if (rangemode && fpnmode && (*p>='0' && *p<='7')) { /* allows fp0-7 */
1061
        reg = *p++ - '0';
1062
      }
1063
      else if ((reg = getfreg(&p)) < 0) {
1064
        cpu_error(2);  /* invalid register list */
1065
        return 0;
1066
      }
1067
 
1068
      if (fpnmode < 0) {
1069
        fpnmode = (reg > 7) ? 0 : 1;
1070
      }
1071
      else {
1072
        /* disallow mixing of fp0-fp7 and fpiar/fpsr/fpcr lists */
1073
        if ((reg<=7 && !fpnmode) || (reg>7 && fpnmode)) {
1074
          cpu_error(2);  /* invalid register list */
1075
          return 0;
1076
        }
1077
      }
1078
 
1079
      if (fpnmode) {
1080
        if (rangemode) {
1081
          /* lastreg...reg describes a range of registers */
1082
          if (lastreg > reg) {
1083
            rx = reg;
1084
            reg = lastreg;
1085
            lastreg = rx;
1086
          }
1087
          for (rx=lastreg; rx<=reg; rx++)
1088
            list |= 1<<(7-rx);
1089
          rangemode = 0;
1090
        }
1091
        else
1092
          list |= 1<<(7-reg);
1093
      }
1094
      else
1095
        list |= 1<<reg;
1096
 
1097
      lastreg = reg;
1098
      p = skip(p);
1099
      if (*p == '-') {
1100
        if (!fpnmode)
1101
          cpu_error(2);  /* invalid register list */
1102
        else
1103
          rangemode = 1;
1104
      }
1105
      else if (*p != '/')
1106
        break;
1107
    }
1108
    *start = p;
1109
    return list;
1110
  }
1111
  return eval_rlsymbol(start);
1112
}
1113
 
1114
 
1115
static char *getspecreg(char *s,operand *op,int first,int last,int cpuchk)
1116
{
1117
  char *p = NULL;
1118
  char *q;
1119
  strbuf *loc;
1120
 
1121
  if ((*s=='<' && *(s+1)=='<') || (*s=='>' && *(s+1)=='>')) {
1122
    /* ColdFire MAC scale factor << or >>, treated as special reg. name */
1123
    p = s;
1124
    s += 2;
1125
    q = s;
1126
  }
1127
  else if (loc = get_local_label(0,&s)) {
1128
    p = loc->str;
1129
    q = p + loc->len;
1130
  }
1131
  else {
1132
    if (elfregs && *s=='%')
1133
      s++;
1134
    if (ISIDSTART(*s)) {
1135
      p = s++;
1136
      while (ISIDCHAR(*s) && *s!='.')
1137
        s++;
1138
      q = s;
1139
    }
1140
  }
1141
 
1142
  if (p) {
1143
    int i;
1144
    hashdata data;
1145
 
1146
    if (!find_namelen_nc(spechash,p,q-p,&data)) {
1147
      i = -1;
1148
      if (cpu_type & apollo) {  /* handle Apollo En registers as regsyms */
1149
        regsym *sym;
1150
        if ((sym = find_regsym(p,q-p)) != NULL) {
1151
          /* register symbol found */
1152
          if (sym->reg_type==RSTYPE_En &&
1153
              sym->reg_num>=first && sym->reg_num<=last)
1154
            i = sym->reg_num;
1155
        }
1156
      }
1157
    }
1158
    else
1159
      i = data.idx;
1160
 
1161
    if (i>=first && i<=last &&
1162
        (!cpuchk || (SpecRegs[i].available & cpu_type))) {
1163
      op->mode = MODE_SpecReg;
1164
      op->reg = i;
1165
      op->value[0] = number_expr(SpecRegs[i].code);
1166
      return s;
1167
    }
1168
  }
1169
  return NULL;
1170
}
1171
 
1172
 
1173
static char *getctrlreg(char *s,operand *op,int first,int last)
1174
{
1175
  char *p = NULL;
1176
  char *q;
1177
  strbuf *loc;
1178
 
1179
  if (loc = get_local_label(0,&s)) {
1180
    p = loc->str;
1181
    q = p + loc->len;
1182
  }
1183
  else {
1184
    if (elfregs && *s=='%')
1185
      s++;
1186
    if (ISIDSTART(*s)) {
1187
      p = s++;
1188
      while (ISIDCHAR(*s) && *s!='.')
1189
        s++;
1190
      q = s;
1191
    }
1192
  }
1193
 
1194
  if (p) {
1195
    int i;
1196
    hashdata data;
1197
 
1198
    if (find_namelen_nc(movchash,p,q-p,&data)) {
1199
      i = data.idx;
1200
      if (i>=first && i<=last && (SpecRegs[i].available & cpu_type)) {
1201
        op->mode = MODE_SpecReg;
1202
        op->reg = i;  /* @@@ Warning: indexes 128-255 are stored negative! */
1203
        op->value[0] = number_expr(SpecRegs[i].code);
1204
        return s;
1205
      }
1206
    }
1207
  }
1208
  return NULL;
1209
}
1210
 
1211
 
1212
static int get_any_register(char **start,operand *op,struct optype *ot)
1213
/* checks for Dn, An, register lists and any other special register;
1214
   fill op->mode, op->register, op->value[0] accordingly when successful
1215
   and return with != 0 */
1216
{
1217
  char *s = *start;
1218
  signed char reg;
1219
 
1220
  if ((reg = getreg(start,0)) >= 0) {
1221
    /* Dn or An */
1222
    char *p = skip(*start);
1223
 
1224
    op->mode = REGisAn(reg) ? MODE_An : MODE_Dn;
1225
    op->reg = REGget(reg);
1226
 
1227
    if (ot->flags & OTF_VXRNG4) {
1228
      /* Apollo AMMX four-vector-registers range */
1229
      if (!REGisAn(reg) && *p=='-') {
1230
        *start = skip(p+1);
1231
        if (!(reg&3) && getreg(start,0)==reg+3)
1232
          return 1;  /* D0-D3 or D4-D7 */
1233
      }
1234
      *start = s;
1235
      return 0;
1236
    }
1237
    else if (*p=='-' || *p=='/' || (ot->flags & OTF_REGLIST)) {
1238
      /* it's a register list */
1239
      op->mode = MODE_Extended;
1240
      op->reg = REG_RnList;
1241
      *start = s;
1242
      op->value[0] = number_expr((taddr)scan_Rnlist(start));
1243
    }
1244
    else {
1245
      unsigned char sf = reg >> 4;
1246
 
1247
      if (sf==EXT_UPPER || sf==EXT_LOWER || (ot->flags & FL_MAC)) {
1248
        /* ColdFire MAC U/L register extension found, store in bf_offset */
1249
        op->flags |= FL_MAC;
1250
        op->bf_offset = sf == EXT_UPPER;
1251
      }
1252
    }
1253
    return 1;
1254
  }
1255
 
1256
  else if ((cpu_type & (mfloat|mcffpu)) && (reg = getfreg(start)) >= 0) {
1257
    /* FPn */
1258
    char *p = skip(*start);
1259
 
1260
    if (*p=='-' || *p=='/' || (ot->flags & OTF_REGLIST)) {
1261
      /* it's a register list */
1262
      uint16_t lst;
1263
 
1264
      op->mode = MODE_Extended;
1265
      op->reg = REG_FPnList;
1266
      *start = s;
1267
      lst = scan_FPnlist(start);
1268
      if (reg >= 10)
1269
        op->flags |= FL_FPSpec;  /* fpiar/fpcr/fpsr list */
1270
      op->value[0] = number_expr((taddr)lst);
1271
    }
1272
    else {
1273
      op->mode = MODE_FPn;
1274
      if (reg >= 10) {
1275
        /* fpiar,fpsr,fpcr */
1276
        switch (reg) {
1277
          case 10: op->reg = 1; break;
1278
          case 11: op->reg = 2; break;
1279
          case 12: op->reg = 4; break;
1280
          default: ierror(0); break;
1281
        }
1282
        op->flags |= FL_FPSpec;
1283
      }
1284
      else
1285
        op->reg = reg;
1286
    }
1287
    return 1;
1288
  }
1289
 
1290
  else if ((cpu_type&apollo) && (reg = getbreg(start)) >= 0) {
1291
    /* Bn (Apollo only) */
1292
    op->mode = MODE_An;
1293
    op->reg = REGget(reg);
1294
    op->flags |= FL_BnReg;
1295
    return 1;
1296
  }
1297
 
1298
  else if (ot->flags & OTF_MOVCREG) {
1299
    /* check, if it's a MOVEC control register (SFC,VBR, etc.) */
1300
    int first,last;
1301
 
1302
    if (ot->flags & OTF_SRRANGE) {
1303
      first = ot->first;
1304
      last = ot->last;
1305
    }
1306
    else {
1307
      first = FIRST_CTRLREG;
1308
      last = LAST_CTRLREG;
1309
    }
1310
    if (s = getctrlreg(s,op,first,last)) {
1311
      *start = s;
1312
      return 1;
1313
    }
1314
  }
1315
 
1316
  else /*if (ot->flags & OTF_SPECREG)*/ {
1317
    /* check, if it's one of our special register symbols (CCR,SR, etc.) */
1318
    int first,last;
1319
 
1320
    if (ot->flags & OTF_SRRANGE) {
1321
      first = ot->first;
1322
      last = ot->last;
1323
    }
1324
    else {
1325
      first = 0;
1326
      last = FIRST_CTRLREG - 1;
1327
    }
1328
 
1329
    if (s = getspecreg(s,op,first,last,1)) {
1330
      if (ot->flags & OTF_VXRNG4) {
1331
        /* need a four-vector-register range, E0-E3, E20-E23, etc. */
1332
        int vxreg = (unsigned char)op->reg;
1333
        operand dummy;
1334
 
1335
        s = skip(s);
1336
        if (*s=='-' && !(SpecRegs[vxreg].code&3)) {
1337
          s = skip(s+1);
1338
          if ((s = getspecreg(s,&dummy,vxreg+3,vxreg+3,1)) == NULL)
1339
            return 0;
1340
        }
1341
        else
1342
          return 0;
1343
      }
1344
      *start = s;
1345
      return 1;
1346
    }
1347
  }
1348
 
1349
  return 0;
1350
}
1351
 
1352
 
1353
static short getbasereg(char **start)
1354
/* returns any register which could be a base or index register,
1355
   including an optional extension and a scaling factor,
1356
   like d0-d7,a0-a7,b0-b7,pc,zd0,zd7,za0-za7,zpc
1357
   Bits 0-4:
1358
 
1359
    8 - 15    = a0-a7
1360
   this means Bit 3 identifies an address register
1361
    16        = pc
1362
   Bit  5     = treat a0-a7 as b0-b7 (Apollo Core only)
1363
   Bit  7     = Zero-flag (for suppressed registers: zdn,zan,zpc)
1364
   Bits 8-10  = [REGext_Shift] optional extension (1=.b, 2=.w ... 7=.p)
1365
   Bits 12-13 = [REGscale_Shift] scale factor (0=*1, 1=*2, 2=*4, 3=*8)
1366
   returns -1 when no valid register was found */
1367
{
1368
  char *s = *start;
1369
  char *p = NULL;
1370
  char *q;
1371
  strbuf *loc;
1372
  short r = 0;
1373
  regsym *sym;
1374
 
1375
  if (loc = get_local_label(0,&s)) {
1376
    p = loc->str;
1377
    q = p + loc->len;
1378
    r = -1;
1379
  }
1380
  else if (ISIDSTART(*s) || (elfregs && *s=='%')) {
1381
    p = s++;
1382
    while (ISIDCHAR(*s) && *s!='.')
1383
      s++;
1384
    if (elfregs && *p=='%')
1385
      p++;
1386
    if ((s-p)==3 && (*p=='z' || *p=='Z')) {
1387
      r |= REGZero;
1388
      p++;
1389
    }
1390
    if ((s-p) == 2) {
1391
      if ((*p=='D' || *p=='d' || *p=='A' || *p=='a') &&
1392
          (*(p+1)>='0' && *(p+1)<='7'))
1393
        r |= ((*p=='A' || *p=='a') ? REGAn : 0) | (short)(*(p+1) - '0');
1394
      else if ((*p=='S' || *p=='s') && (*(p+1)=='P' || *(p+1)=='p'))
1395
        r |= REGAn+7;
1396
      else if ((*p=='P' || *p=='p') && (*(p+1)=='C' || *(p+1)=='c'))
1397
        r |= REGPC;
1398
      else if ((cpu_type & apollo) && (*p=='B' || *p=='b') &&
1399
               (*(p+1)>='0' && *(p+1)<='7'))
1400
        r |= (short)(*(p+1) - '0') | REGBn | REGAn;
1401
      else
1402
        r = -1;
1403
    }
1404
    else
1405
      r = -1;
1406
    p = *start;
1407
    q = s;
1408
  }
1409
  else
1410
    r = -1;
1411
  if (r<0 && p!=NULL && ((sym = find_regsym(p,q-p)) != NULL)) {
1412
    /* register symbol found */
1413
    if (sym->reg_type==RSTYPE_Dn || sym->reg_type==RSTYPE_An ||
1414
        ((cpu_type&apollo) && sym->reg_type==RSTYPE_Bn)) {
1415
      r = ((sym->reg_type==RSTYPE_Dn) ? 0 : REGAn)
1416
          | (signed char)sym->reg_num;
1417
      if (sym->reg_type == RSTYPE_Bn)
1418
        r |= REGBn;
1419
    }
1420
  }
1421
 
1422
  if (r >= 0) {
1423
    if (*s == '.') {  /* read size extension */
1424
      int extcode = getextcode(*(s+1));
1425
 
1426
      if (extcode && !ISIDCHAR(*(s+2))) {
1427
        r |= extcode << REGext_Shift;
1428
        s += 2;
1429
      }
1430
      else
1431
        return -1;
1432
    }
1433
 
1434
    if (*s == '*') {  /* read scale factor */
1435
      short fac;
1436
 
1437
      s++;
1438
      fac = (short)parse_constexpr(&s);
1439
      switch (fac) {
1440
        case 1:
1441
          break;
1442
        case 2:
1443
          r |= 1 << REGscale_Shift;
1444
          break;
1445
        case 4:
1446
          r |= 2 << REGscale_Shift;
1447
          break;
1448
        case 8:
1449
          r |= 3 << REGscale_Shift;
1450
          break;
1451
        default:
1452
          cpu_error(10);  /* illegal scale factor */
1453
          break;
1454
      }
1455
    }
1456
    *start = s;
1457
  }
1458
  return r;
1459
}
1460
 
1461
 
1462
static void set_index(operand *op,short i)
1463
/* fill index register, including size and scale, into format word */
1464
{
1465
  if (i >= 0) {
1466
    unsigned s = REGscale(i);
1467
 
1468
    op->flags |= FL_UsesFormat;
1469
 
1470
    if (REGisZero(i)) {
1471
      op->flags |= FL_020up;
1472
      op->format |= FW_FullFormat | FW_IndexSuppress;
1473
      /* clear Postindexed, even when zero-reg. was specified as post-index */
1474
      op->format &= ~FW_Postindexed;
1475
    }
1476
    else if (s) {
1477
      /* ColdFire allows scale factors *2 and *4 (*8 when FPU is present),
1478
         otherwise 68020+ is required. */
1479
      if (!(cpu_type & mcf) || (s > 2 && !(cpu_type & mcffpu)))
1480
        op->flags |= FL_020up;
1481
    }
1482
 
1483
    op->format |= (REGisAn(i) ? FW_IndexAn : 0) |
1484
                  FW_IndexReg(i) |
1485
                  ((REGext(i)==EXT_LONG) ? FW_LongIndex : 0) |
1486
                  FW_Scale(s);
1487
  }
1488
}
1489
 
1490
 
1491
static taddr getbfk(char **p,int *dflag)
1492
/* get a bit field specifier {Dm:Dn}/{m:n} or a k-factor {#n}/{Dn},
1493
   dflag is set for a data register. */
1494
{
1495
  signed char reg = getreg(p,0);
1496
 
1497
  if (reg >= 0) {
1498
    *dflag = 1;
1499
    if (REGisDn(reg))
1500
      return 0x80 + REGget(reg);
1501
    else
1502
      cpu_error(18);  /* data register required */
1503
  }
1504
  else {
1505
    *dflag = 0;
1506
    if (**p == '#')  /* skip for k-factor and gcc-syntax */
1507
      *p += 1;
1508
    return parse_constexpr(p);
1509
  }
1510
  return 0;
1511
}
1512
 
1513
 
1514
static void check_basereg(operand *op)
1515
/* Check if the operand's address register matches one of the currently
1516
   active BASEREG registers and automatically subtract its base-expression
1517
   from the operand's displacement value.
1518
   op->reg ist guaranteed to be between 0 and 7 and op->mode has an
1519
   appropriate addressing mode! */
1520
{
1521
  if (op->reg<=6 && baseexp[op->reg] && op->value[0]) {
1522
    if (find_base(op->value[0],NULL,NULL,0) == BASE_OK) {
1523
      expr *new = make_expr(SUB,op->value[0],copy_tree(baseexp[op->reg]));
1524
 
1525
      simplify_expr(new);
1526
      op->value[0] = new;
1527
      op->flags |= FL_BaseReg;  /* mark potential BASEREG expression */
1528
    }
1529
  }
1530
}
1531
 
1532
 
1533
static int fix_basereg(operand *op,int final)
1534
/* Check whether the left side of the "<exp> - <base>" expression is still
1535
   undefined. When it became a constant expression in the meantime, then
1536
   do not treat it any longer as a BASEREG operand. */
1537
{
1538
  taddr val;
1539
  expr *left;
1540
 
1541
  if (op->value[0]!=NULL && (left=op->value[0]->left)!=NULL) {
1542
    if (eval_expr(left,&val,NULL,0)) {
1543
      /* Kill the subtrahend of the base-relative expression. */
1544
      if (final) {
1545
        op->value[0]->left = NULL;
1546
        free_expr(op->value[0]);
1547
      }
1548
      op->value[0] = left;
1549
      op->flags &= ~FL_BaseReg;
1550
      return 1;  /* fixed */
1551
    }
1552
  }
1553
  return 0;  /* nothing changed */
1554
}
1555
 
1556
 
1557
static char *parse_immediate(char *start,operand *op,int is_float,int is_quad)
1558
/* Parse an immediate operand of unknown size, which can be byte, word,
1559
   long, quadword, single-, double-, extended-precision float or packed.
1560
   is_float: Decimal constants are parsed as floating point. Hex, octal or
1561
   binary constants directly into IEEE format.
1562
   is_quad: 64-bit expressions are converted into thuge type, not taddr,
1563
   so they don't allow labels and relocations. */
1564
{
1565
  if (is_float)
1566
    op->value[0] = parse_expr_float(&start);
1567
  else if (is_quad)
1568
    op->value[0] = parse_expr_huge(&start);
1569
  else
1570
    op->value[0] = parse_expr(&start);
1571
  return start;
1572
}
1573
 
1574
 
1575
static int base_disp_and_ext(operand *op,char **p)
1576
/* Parse expression to value[0] and return the displacement-extension when
1577
   given (or 0 when missing). Returns -1 when no valid expression was found. */
1578
{
1579
  if ((op->value[0] = parse_expr(p)) != NULL) {
1580
    int disp_size;
1581
 
1582
    if ((disp_size = read_extension(p,0)) != 0)
1583
      op->flags |= FL_NoOptBase;  /* do not optimize, when size is given */
1584
    return disp_size;
1585
  }
1586
  return -1;
1587
}
1588
 
1589
 
1590
int parse_operand(char *p,int len,operand *op,int required)
1591
{
1592
  uint16_t reqmode = optypes[required].modes;
1593
  uint32_t reqflags = optypes[required].flags;
1594
  char *start = p;
1595
  int i;
1596
 
1597
  op->mode = op->reg = -1;
1598
  op->flags = 0;
1599
  op->format = 0;
1600
  op->value[0] = op->value[1] = NULL;
1601
  p = skip(p);
1602
  if (convert_brackets && !(cpu_type & (m68020up|cpu32|mcf))) {
1603
    char c,*p2=p;
1604
 
1605
    while ((c = *p2) != '\0') {
1606
      if (c == '[')
1607
        *p2 = '(';
1608
      else if (c== ']')
1609
        *p2 = ')';
1610
      p2++;
1611
    }
1612
  }
1613
 
1614
  if (reqflags & OTF_DATA) {
1615
    /* a data definition */
1616
    op->mode = MODE_Extended;
1617
    op->reg = REG_Immediate;
1618
    p = parse_immediate(p,op,
1619
                        (reqflags&OTF_FLTIMM)!=0,
1620
                        (reqflags&OTF_QUADIMM)!=0);
1621
  }
1622
  else if (*p=='#' || (sgs && *p=='&')) {
1623
    /* immediate addressing mode */
1624
    p++;
1625
    op->mode = MODE_Extended;
1626
    op->reg = REG_Immediate;
1627
    p = parse_immediate(p,op,
1628
                        (reqflags&OTF_FLTIMM)!=0 && is_float_ext(),
1629
                        (reqflags&OTF_QUADIMM)!=0 || current_ext=='q');
1630
  }
1631
  else {
1632
    if (get_any_register(&p,op,&optypes[required])) {
1633
      char *ptmp = skip(p);
1634
 
1635
      if (*ptmp == ':') {
1636
        /* possible register-pair definition */
1637
        signed char reg;
1638
 
1639
        ptmp = skip(ptmp+1);
1640
 
1641
        if ((cpu_type&apollo) && (op->mode==MODE_Dn ||
1642
            op->mode==MODE_An || op->mode==MODE_SpecReg)) {
1643
          if (reqflags & OTF_VXRNG2) {
1644
            if (op->mode == MODE_SpecReg) {
1645
              /* Apollo: En:En+1 (AMMX) */
1646
              int vxreg = (unsigned char)op->reg;
1647
              operand dummy;
1648
 
1649
              if (!(SpecRegs[vxreg].code&1) &&
1650
                  (ptmp = getspecreg(ptmp,&dummy,vxreg+1,vxreg+1,1))) {
1651
                op->flags |= FL_DoubleReg;
1652
                p = ptmp;
1653
              }
1654
            }
1655
            else if ((op->flags&FL_BnReg) && !(op->reg&1)) {
1656
              /* Apollo: Bn:Bn+1 */
1657
              reg = getbreg(&ptmp);
1658
              if (reg == op->reg+1) {
1659
                op->flags |= FL_DoubleReg;
1660
                p = ptmp;
1661
              }
1662
            }
1663
            else if (!(op->reg&1)) {
1664
              /* Apollo: Dn:Dn+1, An:An+1 */
1665
              reg = getreg(&ptmp,0);
1666
              if (reg>=0 && REGget(reg)==op->reg+1 &&
1667
                  (op->mode==MODE_An)==(REGisAn(reg)!=0)) {
1668
                op->flags |= FL_DoubleReg;
1669
                p = ptmp;
1670
              }
1671
            }
1672
          }
1673
          else if (op->mode!=MODE_SpecReg && !(op->flags&FL_BnReg)) {
1674
            /* Apollo: Rm:Rn */
1675
            reg = getreg(&ptmp,0);
1676
            if (reg >= 0) {
1677
              if (op->mode == MODE_An) {
1678
                op->mode = MODE_Dn; /* make it appear as Dn/DoubleReg mode */
1679
                op->reg |= REGAn;   /* restore An-bit for Rm */
1680
              }
1681
              op->reg |= reg << 4;  /* insert Rn with 4 bits too */
1682
              op->flags |= FL_DoubleReg;
1683
              p = ptmp;
1684
            }
1685
            else {
1686
              cpu_error(44);  /* register expected */
1687
              return PO_CORRUPT;
1688
            }
1689
          }
1690
        }
1691
        else if (op->mode == MODE_Dn) {
1692
          /* Dm:Dn expected */
1693
          reg = getreg(&ptmp,0);
1694
          if (reg>=0 && REGisDn(reg)) {
1695
            op->reg |= reg << 4;
1696
            op->flags |= FL_DoubleReg | FL_020up;
1697
            p = ptmp;
1698
          }
1699
          else {
1700
            cpu_error(18);  /* data register required */
1701
            return PO_CORRUPT;
1702
          }
1703
        }
1704
        else if (op->mode == MODE_FPn) {
1705
          /* FPm:FPn expected */
1706
          reg = getfreg(&ptmp);
1707
          if (reg>=0 && reg<=7) {
1708
            op->reg |= reg << 4;
1709
            op->flags |= FL_DoubleReg;
1710
            p = ptmp;
1711
          }
1712
          else {
1713
            cpu_error(42);  /* FP register required */
1714
            return PO_CORRUPT;
1715
          }
1716
        }
1717
      }
1718
      p = skip(p);
1719
    }
1720
 
1721
    else {
1722
      /* no direct register */
1723
      int disp_size = 0;
1724
      int od_size;
1725
      char *start_term = NULL;
1726
 
1727
      if (*p=='-' && *(p+1)=='(') {
1728
        char *ptmp = skip(p+2);
1729
        signed char reg;
1730
 
1731
        reg = getreg(&ptmp,0);
1732
        if (reg<0 && (cpu_type&apollo)) {
1733
          if ((reg = getbreg(&ptmp)) >= 0)
1734
            op->flags |= FL_BnReg;  /* Apollo Core: use Bn instead of An */
1735
        }
1736
 
1737
        if (reg >= 0) {
1738
          /* addressing mode An indirect with predecrement */
1739
          if (!REGisAn(reg))
1740
            cpu_error(4);  /* address register required */
1741
          ptmp = skip(ptmp);
1742
          if (*ptmp != ')') {
1743
            cpu_error(3);  /* missing ) */
1744
            return PO_CORRUPT;
1745
          }
1746
          else
1747
            ptmp++;
1748
          p = ptmp;
1749
          op->mode = MODE_AnPreDec;
1750
          op->reg = REGget(reg);
1751
        }
1752
      }
1753
 
1754
      parse_expression:
1755
      if ((*p!='(' || start_term!=NULL) && op->mode<0) {
1756
        /* this can only be an expression - parse it */
1757
        disp_size = base_disp_and_ext(op,&p);
1758
        p = skip(p);
1759
      }
1760
 
1761
      if (*p=='(' && op->mode<0) {  /* "(..." */
1762
        int mem_indir;
1763
        short reg,idx=-1;
1764
 
1765
        start_term = p;
1766
        p = skip(p+1);
1767
 
1768
        parse_indir:
1769
        if (*p == '[') {
1770
          /* 020+ memory indirect addressing mode */
1771
          p = skip(p+1);
1772
          if (op->value[0]) {
1773
            /* An already parsed displacement expression before '[' */
1774
            /* becomes an outer displacement for compatibility. */
1775
            if (!devpac_compat)
1776
              cpu_error(6);  /* warn about displacement at bad position */
1777
            op->value[1] = op->value[0];
1778
            od_size = disp_size ? disp_size : EXT_WORD;
1779
            op->value[0] = NULL;
1780
            disp_size = 0;
1781
            if (op->flags & FL_NoOptBase) {
1782
              op->flags &= ~FL_NoOptBase;
1783
              op->flags |= FL_NoOptOuter;
1784
            }
1785
          }
1786
          mem_indir = 1;
1787
        }
1788
        else
1789
          mem_indir = 0;
1790
 
1791
        reg = getbasereg(&p);
1792
        if (reg<0 && op->value[0]==NULL) {
1793
          /* no register identified and still no value read: try it again */
1794
          disp_size = base_disp_and_ext(op,&p);
1795
          p = skip(p);
1796
          if (*p == ')') {
1797
            /* expression was only the first term: read the full expression */
1798
            p = start_term;
1799
            goto parse_expression;
1800
          }
1801
          if (*p == ',') {    /* "(displacement," expects register */
1802
            p = skip(p+1);
1803
            if ((reg = getbasereg(&p)) < 0) {
1804
              if (*p == '[')
1805
                goto parse_indir;
1806
              cpu_error(7);  /* base or index register expected */
1807
              return PO_CORRUPT;
1808
            }
1809
          }
1810
        }
1811
 
1812
        /* check for illegal displacement extension */
1813
        if (op->value[0] && disp_size>EXT_LONG) {
1814
          cpu_error(5);  /* bad extension */
1815
          disp_size = 0;
1816
        }
1817
 
1818
        p = skip(p);
1819
        if (mem_indir && reg<0) {
1820
          /* "([val" without register means base reg is suppressed */
1821
          reg = REGZero | REGAn | 0;
1822
        }
1823
        else if (reg>0 && REGisZero(reg))
1824
          op->flags |= FL_ZBase;  /* ZAn was explicitly specified */
1825
 
1826
        if (reg >= 0) {  /* "(Rn" or "(d,Rn" or "([Rn" or "([bd,Rn" */
1827
          int clbrk = 0;
1828
 
1829
          if ((REGisAn(reg) || REGisPC(reg)) &&
1830
              !REGscale(reg) && !REGext(reg)) {
1831
            /* Rn is a base register An or PC, try to read index now */
1832
 
1833
            if (*p == ']' && mem_indir) {  /* "([bd,Rn]" */
1834
              /* if we ever see an index, it will be postindexed */
1835
              op->format |= FW_Postindexed;
1836
              p = skip(p+1);
1837
              clbrk = 1;
1838
            }
1839
 
1840
            parse_index:
1841
            if (*p == ',') {  /* read index register */
1842
              char *pidx = p;
1843
 
1844
              p = skip(p+1);
1845
              if ((idx = getbasereg(&p)) >= 0) {
1846
                /* "(d,Rn,Xn" or "([bd,Rn],Xn" or "([bd,Rn,Xn" */
1847
                p = skip(p);
1848
                if (*p == ']' && mem_indir) {  /* "([bd,Rn,Xn]" */
1849
                  p = skip(p+1);
1850
                  if (clbrk)
1851
                    cpu_error(13);  /* too many ] */
1852
                  else
1853
                    clbrk = 1;
1854
                }
1855
              }
1856
              else {
1857
                if (!mem_indir || !clbrk) {
1858
                  if (op->value[0] == NULL) {
1859
                    /* (An,bd) is treated as (bd,An) for compatibility */
1860
                    if ((disp_size = base_disp_and_ext(op,&p)) < 0) {
1861
                      cpu_error(12);  /* index register expected */
1862
                      return PO_CORRUPT;
1863
                    }
1864
                    else {
1865
                      if (!devpac_compat)
1866
                        cpu_error(6);  /* displacement at bad position */
1867
                      p = skip(p);
1868
                      goto parse_index;
1869
                    }
1870
                  }
1871
                  else {
1872
                    cpu_error(12);  /* index register expected */
1873
                    return PO_CORRUPT;
1874
                  }
1875
                }
1876
                else
1877
                  p = pidx;  /* back to ',' to parse outer displacement */
1878
              }
1879
            }
1880
            if (idx < 0)
1881
              op->format &= ~FW_Postindexed;  /* index was suppressed */
1882
          }
1883
          else {
1884
            /* Rn is already the index, assume ZA0 as base */
1885
            if (!(reqflags & FL_DoubleReg)) {
1886
              idx = reg;
1887
              reg = REGZero | REGAn | 0;
1888
              op->flags &= ~FL_ZBase;
1889
            }
1890
          }
1891
 
1892
          if (mem_indir) {
1893
            if (!clbrk) {
1894
              if (*p != ']')
1895
                cpu_error(8);  /* missing ] */
1896
              else
1897
                p = skip(p+1);
1898
            }
1899
            if (*p == ',') {  /* "([bd,Rn],Xn,od" or "([bd,Rn,Xn],od" */
1900
              /* read outer displacement */
1901
              p = skip(p+1);
1902
              if (op->value[1] == NULL) {
1903
                if ((op->value[1] = parse_expr(&p)) != NULL) {
1904
                  if ((od_size = read_extension(&p,0)) != 0)
1905
                    op->flags |= FL_NoOptOuter;  /* do not optimize with size */
1906
                  else
1907
                    od_size = EXT_WORD;
1908
                  p = skip(p);
1909
                }
1910
                else
1911
                  cpu_error(14);  /* missing outer displacement */
1912
              }
1913
            }
1914
            if (op->value[1] != NULL) {
1915
              /* set outer displacement */
1916
              if (od_size == EXT_WORD)
1917
                op->format |= FW_IndSize(FW_Word);
1918
              else if (od_size == EXT_LONG)
1919
                op->format |= FW_IndSize(FW_Long);
1920
              else
1921
                cpu_error(5);  /* bad extension */
1922
            }
1923
            else
1924
              op->format |= FW_IndSize(FW_Null);  /* no outer disp. given */
1925
          }
1926
        }
1927
 
1928
        if (*p==',' && op->value[0]==NULL) {
1929
          /* (Rn,bd) is treated as (bd,Rn) for compatibility reasons */
1930
          p = skip(p+1);
1931
          disp_size = base_disp_and_ext(op,&p);
1932
          if (disp_size >= 0) {
1933
            p = skip(p);
1934
            if (!devpac_compat)
1935
              cpu_error(6);  /* warn about displacement at bad position */
1936
          }
1937
        }
1938
        if (*p++ != ')')
1939
          cpu_error(15,')');  /* ) expected */
1940
 
1941
        /* parsing completed, determine addressing mode */
1942
 
1943
        if (reg >= 0) {
1944
          if (idx >= 0) {
1945
            if (REGisPC(idx)) {
1946
              cpu_error(16);  /* can't use PC register as index */
1947
              return PO_CORRUPT;
1948
            }
1949
            if (REGisBn(idx)) {
1950
              cpu_error(61,(int)REGget(idx));  /* can't use Bn as index */
1951
              return PO_CORRUPT;
1952
            }
1953
            if (cpu_type & mcf) {
1954
              if (REGext(idx)!=0 && REGext(idx)!=EXT_LONG)
1955
                cpu_error(5);  /* bad extension - only .l for ColdFire */
1956
              idx &= ~(EXT_MASK<<REGext_Shift);
1957
              idx |= EXT_LONG<<REGext_Shift;
1958
            }
1959
            else if (REGext(idx)!=0 &&
1960
                     REGext(idx)!=EXT_LONG && REGext(idx)!=EXT_WORD) {
1961
              cpu_error(5);  /* bad extension */
1962
              idx &= ~(EXT_MASK<<REGext_Shift);
1963
            }
1964
            if (REGisZero(idx))
1965
              op->flags |= FL_ZIndex;  /* ZRn was explicitly specified */
1966
          }
1967
 
1968
          /* set default displacement sizes */
1969
          if (!disp_size)
1970
            disp_size = idx<0 ? EXT_WORD : EXT_BYTE;
1971
 
1972
          if (!mem_indir && !REGisZero(reg) && op->value[1]==NULL &&
1973
              ((idx<0 && disp_size==EXT_WORD) ||
1974
               (idx>=0 && disp_size==EXT_BYTE && !REGisZero(idx)))) {
1975
            /* normal 68000 addressing modes, including 020+ scaling */
1976
            if (idx < 0) {
1977
              if (op->value[0]) {
1978
                if (REGisPC(reg)) {
1979
                  op->mode = MODE_Extended;           /* (d16,PC) */
1980
                  op->reg = REG_PC16Disp;
1981
                }
1982
                else {
1983
                  op->mode = MODE_An16Disp;           /* (d16,An) */
1984
                  op->reg = REGget(reg);
1985
                  check_basereg(op);
1986
                }
1987
              }
1988
              else if (REGisPC(reg)) {
1989
                op->mode = MODE_Extended;             /* (PC) -> (0,PC) */
1990
                op->reg = REG_PC16Disp;
1991
                op->value[0] = number_expr(0);
1992
              }
1993
              else {
1994
                if (*p == '+') {
1995
                  op->mode = MODE_AnPostInc;          /* (An)+ */
1996
                  op->reg = REGget(reg);
1997
                  p++;
1998
                }
1999
                else {
2000
                  char *ptmp = skip(p);
2001
 
2002
                  op->mode = MODE_AnIndir;            /* (An) */
2003
                  op->reg = REGget(reg);
2004
                  if (*ptmp == ':') {
2005
                    /* (Rm):(Rn) expected, store reg as 4 bit */
2006
                    op->reg = REGgetA(reg);
2007
                    ptmp = skip(ptmp+1);
2008
                    if (*ptmp == '(') {
2009
                      ptmp = skip(ptmp+1);
2010
                      reg = getreg(&ptmp,0);
2011
                      if (reg >= 0) {
2012
                        ptmp = skip(ptmp);
2013
                        if (*ptmp++ == ')') {         /* (Rn):(Rm) */
2014
                          op->reg |= REGgetA(reg) << 4;
2015
                          op->flags |= FL_DoubleReg | FL_020up | FL_noCPU32;
2016
                          p = ptmp;
2017
                        }
2018
                      }
2019
                    }
2020
                    if (p != ptmp) {
2021
                      cpu_error(1);  /* illegal addressing mode */
2022
                      return PO_CORRUPT;
2023
                    }
2024
                  }
2025
                }
2026
              }
2027
            }
2028
            else {
2029
              if (!op->value[0]) {
2030
                /* need a displacement for indexed addressing modes */
2031
                op->value[0] = number_expr(0);
2032
              }
2033
              if (REGisPC(reg)) {                     /* (d8,PC,Xn) */
2034
                op->mode = MODE_Extended;
2035
                op->reg = REG_PC8Format;
2036
              }
2037
              else {
2038
                op->mode = MODE_An8Format;            /* (d8,An,Xn) */
2039
                op->reg = REGget(reg);
2040
                check_basereg(op);
2041
              }
2042
              set_index(op,idx);
2043
            }
2044
          }
2045
          else {
2046
            /* the remaining addressing modes require a full format word */
2047
            op->format |= FW_FullFormat;
2048
            op->flags |= FL_UsesFormat | FL_020up;
2049
            /* no memory-indirect modes for CPU32 */
2050
            if (mem_indir)
2051
              op->flags |= FL_noCPU32;
2052
 
2053
            if (REGisPC(reg)) {
2054
              op->mode = MODE_Extended;               /* ([bd,PC,Xn],od) */
2055
              op->reg = REG_PC8Format;
2056
            }
2057
            else {
2058
              op->mode = MODE_An8Format;              /* ([bd,An,Xn],od) */
2059
              op->reg = REGget(reg);
2060
              check_basereg(op);
2061
            }
2062
            if (REGisZero(reg))
2063
              op->format |= FW_BaseSuppress;
2064
 
2065
            if (idx < 0)
2066
              idx = REGZero | 0;  /* no index given: assume ZD0.w */
2067
            set_index(op,idx);
2068
 
2069
            if (op->value[0]) {
2070
              if (disp_size == EXT_LONG)
2071
                op->format |= FW_BDSize(FW_Long);
2072
              else
2073
                op->format |= FW_BDSize(FW_Word);
2074
            }
2075
            else
2076
              op->format |= FW_BDSize(FW_Null);  /* base disp. suppressed */
2077
          }
2078
 
2079
          if (REGisBn(reg))
2080
            op->flags |= FL_BnReg;  /* Apollo Core: Bn instead of An */
2081
        }
2082
      }
2083
 
2084
      if (op->mode<0 && op->value[0]!=NULL) {
2085
        /* we have read a value but no register at all,
2086
           then it's an absolute addressing mode */
2087
        op->mode = MODE_Extended;
2088
        if (disp_size == EXT_WORD) {
2089
          op->reg = REG_AbsShort;
2090
        }
2091
        else {
2092
          if (reqflags & OTF_REGLIST) {
2093
            op->reg = (required==RL) ? REG_RnList : REG_FPnList;
2094
            /* op->flags |= FL_PossRegList;  @@@ not needed? */
2095
          }
2096
          else
2097
            op->reg = REG_AbsLong;
2098
          if (disp_size!=0 && disp_size!=EXT_LONG)
2099
            cpu_error(5);  /* bad extension */
2100
        }
2101
      }
2102
 
2103
      p = skip(p);
2104
      if (*p=='&' || (reqflags & FL_MAC)) {
2105
        /* ColdFire MAC MASK specifier */
2106
        op->flags |= FL_MAC;
2107
        if (*p == '&') {
2108
          op->bf_width = 1;
2109
          p = skip(p+1);
2110
        }
2111
        else
2112
          op->bf_width = 0;
2113
      }
2114
    }
2115
 
2116
    if (*p == '{') {
2117
      /* bit field specifier or k-factor */
2118
      int dflag,absk = 0;
2119
      taddr bfval;
2120
 
2121
      p = skip(p+1);
2122
      if (*p == '#')
2123
        absk = 1;   /* probably absolute k-factor */
2124
      bfval = getbfk(&p,&dflag);
2125
      op->flags |= dflag ? FL_BFoffsetDyn : 0;
2126
      p = skip(p);
2127
      if (*p==':') {
2128
        absk = 0;
2129
        p = skip(p+1);
2130
        op->bf_offset = (unsigned char)bfval;
2131
        op->bf_width = (unsigned char)getbfk(&p,&dflag);
2132
        op->flags |= dflag ? FL_BFwidthDyn : 0;
2133
        p = skip(p);
2134
        if (*p == '}')
2135
          p++;
2136
        else
2137
          cpu_error(15,'}');  /* } expected */
2138
        op->flags |= FL_Bitfield | FL_020up | FL_noCPU32;
2139
      }
2140
      else if (*p == '}') {
2141
        if (absk) {
2142
          op->bf_offset = (unsigned char)bfval;
2143
          if (typechk && (bfval<-64 || bfval>63))
2144
            cpu_error(21);  /* value from -64 to 63 required */
2145
        }
2146
        else  /* k-factor is a data register */
2147
          op->bf_offset = (unsigned char)(bfval & 7) << 4;
2148
        op->flags |= FL_KFactor;
2149
        p++;
2150
      }
2151
      else {
2152
        cpu_error(1);  /* illegal addressing mode */
2153
        return PO_CORRUPT;
2154
      }
2155
    }
2156
  }
2157
 
2158
  /* compare parsed addressing mode against requirements */
2159
 
2160
  for (i=0; i<16; i++) {
2161
    if (reqmode & (1<<i)) {
2162
      /*printf("%x:%x %d:%d %d:%d\n",op->flags&FL_CheckMask,reqflags&FL_CheckMask,op->mode,addrmodes[i].mode,op->reg,addrmodes[i].reg);*/
2163
      if ((op->flags&FL_CheckMask)==(reqflags&FL_CheckMask) &&
2164
          addrmodes[i].mode==op->mode &&
2165
          (addrmodes[i].reg<0 || addrmodes[i].reg==op->reg)) {
2166
        if (reqflags & OTF_CHKREG) {
2167
          if ((unsigned char)op->reg < optypes[required].first ||
2168
              (unsigned char)op->reg > optypes[required].last)
2169
            return PO_NOMATCH;
2170
        }
2171
        if (required == DP) {
2172
          /* never optimize d(An) operand for MOVEP */
2173
          op->flags |= FL_NoOpt;
2174
          if (op->mode == MODE_AnIndir) {
2175
            /* translate (An) into 0(An) for MOVEP */
2176
            op->mode = MODE_An16Disp;
2177
            op->value[0] = number_expr(0);
2178
            cpu_error(48,(int)op->reg,(int)op->reg);  /* warn about it */
2179
          }
2180
        }
2181
 
2182
        p = skip(p);
2183
        if (*p!='\0' && p<(start+len))
2184
          cpu_error(67);  /* trailing garbage in operand */
2185
        return PO_MATCH;
2186
      }
2187
    }
2188
  }
2189
 
2190
  return PO_NOMATCH;
2191
}
2192
 
2193
 
2194
static void eval_oper(operand *op,section *sec,taddr pc,int final)
2195
/* evaluate operand expression */
2196
{
2197
  int i;
2198
 
2199
  for (i=0; i<2; i++) {
2200
    op->base[i] = NULL;
2201
    if (type_of_expr(op->value[i]) == NUM) {
2202
eval:
2203
      if (!eval_expr(op->value[i],&op->extval[i],sec,pc)) {
2204
        op->basetype[i] = find_base(op->value[i],&op->base[i],sec,pc);
2205
 
2206
        if (op->basetype[i] == BASE_ILLEGAL) {
2207
          if (op->flags & FL_BaseReg) {
2208
            if (fix_basereg(op,final))
2209
              goto eval;  /* evaluate fixed operand again */
2210
          }
2211
          if (final)
2212
            general_error(38);  /* illegal relocation */
2213
        }
2214
      }
2215
      op->flags |= FL_ExtVal0 << i;
2216
    }
2217
    else {
2218
      op->extval[i] = 0x7fffffff;  /* dummy to prevent immediate opt. */
2219
      op->flags &= ~(FL_ExtVal0 << i);
2220
    }
2221
  }
2222
}
2223
 
2224
 
2225
static int copy_float_exp(unsigned char *d,operand *op,int size)
2226
/* write immediate floating point expression of 'size' to
2227
   destination buffer, return 0 when everything was ok, else error-code */
2228
{
2229
  int et;
2230
  thuge h;
2231
  tfloat f;
2232
 
2233
  if (op->flags & FL_ExtVal0)
2234
    et = NUM;
2235
  else
2236
    et = type_of_expr(op->value[0]);
2237
 
2238
  if (et == NUM) {
2239
    if (op->base[0])
2240
      return 20;  /* constant integer expression required */
2241
  }
2242
  else if (et == HUG) {
2243
    if (!eval_expr_huge(op->value[0],&h))
2244
      return 59;  /* cannot evaluate huge integer */
2245
  }
2246
  else if (et == FLT) {
2247
    if (!eval_expr_float(op->value[0],&f))
2248
      return 60;  /* cannot evaluate floating point */
2249
  }
2250
  else
2251
    return 37;  /* immediate operand has illegal type */
2252
 
2253
  switch (size) {
2254
 
2255
    case EXT_SINGLE:
2256
      if (et == NUM)
2257
        rf68k_setval(1,d,4,op->extval[0]);
2258
      else if (et == HUG)
2259
        huge_to_mem(1,d,4,h);
2260
      else
2261
        conv2ieee32(1,d,f);
2262
      break;
2263
 
2264
    case EXT_DOUBLE:
2265
      if (et == NUM)
2266
        rf68k_setval_signext(1,d,4,4,op->extval[0]);
2267
      else if (et == HUG)
2268
        huge_to_mem(1,d,8,h);
2269
      else
2270
        conv2ieee64(1,d,f);
2271
      break;
2272
 
2273
    case EXT_EXTENDED:
2274
      if (et == NUM)
2275
        rf68k_setval_signext(1,d,8,4,op->extval[0]);
2276
      else if (et == HUG)
2277
        huge_to_mem(1,d,12,h);
2278
      else
2279
        conv2ieee80(1,d,f);
2280
      break;
2281
 
2282
    case EXT_PACKED:
2283
      if (et == NUM)
2284
        rf68k_setval_signext(1,d,8,4,op->extval[0]);
2285
      else if (et == HUG)
2286
        huge_to_mem(1,d,12,h);
2287
      else
2288
        conv2packed(d,f);
2289
      break;
2290
 
2291
    default:
2292
      return 34;  /* illegal opcode extension */
2293
  }
2294
 
2295
  return 0;
2296
}
2297
 
2298
 
2299
static void optimize_oper(operand *op,struct optype *ot,section *sec,
2300
                          taddr pc,taddr cpc,int final)
2301
/* evaluate expressions in operand and try to optimize addressing modes */
2302
{
2303
  int size16[2]; /* true, when extval[] fits into 16 bits */
2304
  taddr pcdisp;  /* calculated pc displacement = (label - current_pc) */
2305
  int pcdisp16;  /* true, when pcdisp fits into 16 bits */
2306
  int absdpc;    /* true, when PC-displ. is const. in a non-absolute sect. */
2307
  int undef;     /* true, when first base-symbol is still undefined */
2308
  int secrel;    /* pc-relative reference in current section */
2309
  int bdopt;     /* true, when base-displacement optimization allowed */
2310
  int odopt;     /* true, when outer-displacement optimization allowed */
2311
 
2312
  if (!(op->flags & FL_DoNotEval))
2313
    eval_oper(op,sec,pc,final);
2314
 
2315
  if ((op->flags & FL_NoOpt)==FL_NoOpt ||
2316
      op->mode<MODE_An16Disp || op->mode>MODE_Extended ||
2317
      (op->mode==MODE_Extended && op->reg>REG_PC8Format))
2318
    return;
2319
 
2320
  /* optimize and fix addressing modes */
2321
 
2322
  bdopt = !(op->flags & FL_NoOptBase);
2323
  odopt = !(op->flags & FL_NoOptOuter);
2324
  size16[0] = op->extval[0]>=-0x8000 && op->extval[0]<=0x7fff;
2325
  size16[1] = op->extval[1]>=-0x8000 && op->extval[1]<=0x7fff;
2326
  pcdisp = op->extval[0] - cpc;
2327
  pcdisp16 = pcdisp>=-0x8000 && pcdisp<=0x7fff;
2328
  absdpc = !(sec->flags & ABSOLUTE) && op->base[0]==NULL;
2329
  undef = (op->base[0]==NULL) ? 0 : EXTREF(op->base[0]);
2330
  secrel = (sec->flags & ABSOLUTE) ? op->base[0]==NULL :
2331
           op->base[0]!=NULL && LOCREF(op->base[0]) && op->base[0]->sec==sec;
2332
 
2333
  if (bdopt) {  /* base displacement optimizations allowed */
2334
 
2335
    if (op->mode==MODE_An16Disp) {
2336
      if (opt_disp && !op->base[0] && op->extval[0]==0 &&
2337
          (ot->modes & (1<<AM_AnIndir))) {
2338
        /* (0,An) --> (An) */
2339
        op->mode = MODE_AnIndir;
2340
        if (final) {
2341
          free_expr(op->value[0]);
2342
          if (warn_opts>1)
2343
            cpu_error(49,"(0,An)->(An)");
2344
        }
2345
        op->value[0] = NULL;
2346
      }
2347
      else if (((op->base[0] && !undef) || (!op->base[0] && !size16[0])) &&
2348
               (cpu_type & (m68020up|cpu32)) && op->reg!=sdreg &&
2349
               (ot->modes & (1<<AM_An8Format))) {
2350
        /* (d16,An) --> (bd32,An,ZDn.w) for 020+ only */
2351
        op->mode = MODE_An8Format;
2352
        op->format = FW_FullFormat | FW_IndexSuppress | FW_BDSize(FW_Long);
2353
        op->flags |= FL_UsesFormat | FL_020up;
2354
        if (final && warn_opts>1)
2355
          cpu_error(50,"(d16,An)->(bd32,An,ZDn.w)");
2356
      }
2357
    }
2358
 
2359
    else if (op->mode==MODE_Extended && op->reg==REG_PC16Disp &&
2360
             (cpu_type & (m68020up|cpu32)) &&
2361
             (ot->modes & (1<<AM_PC8Format))) {
2362
      if ((absdpc && !size16[0]) || (secrel && !pcdisp16)) {
2363
        /* (d16,PC) --> (bd32,PC,ZDn.w) for 020+ only */
2364
        op->reg = REG_PC8Format;
2365
        op->format = FW_FullFormat | FW_IndexSuppress | FW_BDSize(FW_Long);
2366
        op->flags |= FL_UsesFormat | FL_020up;
2367
        if (final && warn_opts>1)
2368
          cpu_error(50,"(d16,PC)->(bd32,PC,ZDn.w)");
2369
      }
2370
    }
2371
 
2372
    else if (op->mode==MODE_An8Format && (op->flags & FL_UsesFormat) &&
2373
             !(op->format & FW_FullFormat)) {
2374
      if ((cpu_type & (m68020up|cpu32)) &&
2375
          ((op->base[0] && !undef) ||
2376
           (!op->base[0] && (op->extval[0]<-0x80 || op->extval[0]>0x7f)))) {
2377
        /* (d8,An,Rn) --> (bd,An,Rn) */
2378
        op->format &= 0xff00;
2379
        op->format |= FW_FullFormat | FW_BDSize(FW_Word);
2380
        op->flags |= FL_020up;
2381
        if (final && warn_opts>1)
2382
          cpu_error(50,"(d8,An,Rn)->(bd,An,Rn)");
2383
      }
2384
    }
2385
 
2386
    else if (op->mode==MODE_Extended && op->reg==REG_PC8Format &&
2387
             (op->flags & FL_UsesFormat) && !(op->format & FW_FullFormat)) {
2388
      int pcdisp8 = absdpc ?
2389
                    (op->extval[0]>=-0x80 && op->extval[0]<=0x7f) :
2390
                    ((pcdisp>=-0x80 && pcdisp<=0x7f) || undef);
2391
 
2392
      if ((cpu_type & (m68020up|cpu32)) && !pcdisp8) {
2393
        /* (d8,PC,Rn) --> (bd,PC,Rn) */
2394
        op->format &= 0xff00;
2395
        op->format |= FW_FullFormat | FW_BDSize(FW_Word);
2396
        op->flags |= FL_020up;
2397
        if (final && warn_opts>1)
2398
          cpu_error(50,"(d8,PC,Rn)->(bd,PC,Rn)");
2399
      }
2400
    }
2401
 
2402
    else if (op->mode==MODE_Extended && op->reg==REG_AbsShort &&
2403
             (ot->modes & (1<<AM_AbsLong))) {
2404
      if (!op->base[0] && !size16[0]) {
2405
        /* absval.w --> absval.l */
2406
        op->reg = REG_AbsLong;
2407
        if (final && warn_opts>1)
2408
          cpu_error(50,"abs.w->abs.l");
2409
      }
2410
      else if (op->base[0] && typechk && LOCREF(op->base[0])) {
2411
        /* label.w --> label.l */
2412
        op->reg = REG_AbsLong;
2413
        if (final)
2414
          cpu_error(22);  /* need 32 bits to reference a program label */
2415
      }
2416
    }
2417
 
2418
    else if (op->mode==MODE_Extended && op->reg==REG_AbsLong) {
2419
      if (opt_abs && !op->base[0] && size16[0] &&
2420
          (ot->modes & (1<<AM_AbsShort))) {
2421
        /* absval.l --> absval.w */
2422
        op->reg = REG_AbsShort;
2423
        if (final && warn_opts>1)
2424
          cpu_error(49,"abs.l->abs.w");
2425
      }
2426
      else if (sdreg>=0 && op->base[0]!=NULL &&
2427
               (ot->modes & (1<<AM_An16Disp)) &&
2428
               ((opt_gen && (op->base[0]->flags&NEAR)) ||
2429
                (opt_sd && LOCREF(op->base[0]) &&
2430
                 (op->base[0]->sec->flags&NEAR_ADDRESSING))) &&
2431
               op->extval[0]>=0 && op->extval[0]<=0xffff) {
2432
        /* label.l --> label(An) base relative near addressing */
2433
        op->mode = MODE_An16Disp;
2434
        op->reg = sdreg;
2435
        if (final && warn_opts>1)
2436
          cpu_error(49,"label->(label,An)");
2437
      }
2438
      else if (opt_pc && (ot->modes & (1<<AM_PC16Disp))) {
2439
        if (secrel && pcdisp16) {
2440
          /* label.l --> d16(PC) */
2441
          op->reg = REG_PC16Disp;
2442
          if (final && warn_opts>1)
2443
            cpu_error(49,"label->(d16,PC)");
2444
        }
2445
      }
2446
    }
2447
  }
2448
 
2449
  if (op->mode==MODE_An8Format && (op->flags & FL_UsesFormat) &&
2450
      (op->format & FW_FullFormat)) {
2451
 
2452
    if (FW_getIndSize(op->format)==FW_None) {  /* no memory indirection */
2453
      if (FW_getBDSize(op->format) > FW_Null) {
2454
        if (opt_bdisp && bdopt && !op->base[0] && op->extval[0]==0) {
2455
          /* (0,An,...) --> (An,...) */
2456
          op->format &= ~FW_BDSize(FW_SizeMask);
2457
          op->format |= FW_BDSize(FW_Null);
2458
          if (final && warn_opts>1)
2459
            cpu_error(49,"(0,An,...)->(An,...)");
2460
        }
2461
        else if (bdopt && (op->base[0] || (!op->base[0] && !size16[0])) &&
2462
                 FW_getBDSize(op->format)==FW_Word) {
2463
          /* (bd16,An,...) --> (bd32,An,...) */
2464
          op->format &= ~FW_BDSize(FW_SizeMask);
2465
          op->format |= FW_BDSize(FW_Long);
2466
          if (final && warn_opts>1)
2467
            cpu_error(50,"(bd16,An,...)->(bd32,An,...)");
2468
        }
2469
        else if (opt_bdisp && bdopt && !op->base[0] && size16[0] &&
2470
                 FW_getBDSize(op->format)==FW_Long) {
2471
          if ((op->format & FW_IndexSuppress) &&
2472
              (ot->modes & (1<<AM_An16Disp)) &&
2473
              !(op->flags & FL_ZIndex)) {
2474
            /* (bd32,An,ZRn) --> (d16,An) */
2475
            op->mode = MODE_An16Disp;
2476
            op->format = 0;
2477
            op->flags &= ~(FL_UsesFormat | FL_020up | FL_noCPU32);
2478
            if (final && warn_opts>1)
2479
              cpu_error(49,"(bd32,An,ZRn)->(d16,An)");
2480
          }
2481
          else {
2482
            /* (bd32,An,Rn) --> (bd16,An,Rn) */
2483
            op->format &= ~FW_BDSize(FW_SizeMask);
2484
            op->format |= FW_BDSize(FW_Word);
2485
            if (final && warn_opts>1)
2486
              cpu_error(49,"(bd32,An,Rn)->(d16,An,Rn)");
2487
          }
2488
        }
2489
      }
2490
      else if (opt_gen && !op->base[0] &&
2491
               (op->format & FW_IndexSuppress) &&
2492
               !(op->format & FW_BaseSuppress) &&
2493
               (ot->modes & (1<<AM_AnIndir)) &&
2494
               !(op->flags & FL_ZIndex)) {
2495
        /* (An,ZRn) --> (An) */
2496
        op->mode = MODE_AnIndir;
2497
        op->format = 0;
2498
        op->flags &= ~(FL_UsesFormat | FL_020up | FL_noCPU32);
2499
        if (final && warn_opts>1)
2500
          cpu_error(49,"(An,ZRn)->(An)");
2501
      }
2502
    }
2503
 
2504
    else {  /* memory indirection */
2505
      if (opt_bdisp && bdopt && !op->base[0] &&
2506
          FW_getBDSize(op->format)>FW_Null && op->extval[0]==0) {
2507
        /* ([0,An,...],...) --> ([An,...],...) */
2508
        op->format &= ~FW_BDSize(FW_SizeMask);
2509
        op->format |= FW_BDSize(FW_Null);
2510
        if (final && warn_opts>1)
2511
           cpu_error(49,"([0,An,...],...)->([An,...],...)");
2512
      }
2513
      else if (bdopt && (op->base[0] || (!op->base[0] && !size16[0])) &&
2514
               FW_getBDSize(op->format)==FW_Word) {
2515
        /* ([bd16,An,...],...) --> ([bd32,An,...],...) */
2516
        op->format &= ~FW_BDSize(FW_SizeMask);
2517
        op->format |= FW_BDSize(FW_Long);
2518
        if (final && warn_opts>1)
2519
           cpu_error(50,"([bd16,An,...],...)->([bd32,An,...],...)");
2520
      }
2521
      else if (opt_bdisp && bdopt && !op->base[0] && size16[0] &&
2522
               FW_getBDSize(op->format)==FW_Long) {
2523
        /* ([bd32,An,...],...) --> ([bd16,An,...],...) */
2524
        op->format &= ~FW_BDSize(FW_SizeMask);
2525
        op->format |= FW_BDSize(FW_Word);
2526
        if (final && warn_opts>1)
2527
           cpu_error(49,"([bd32,An,...],...)->([bd16,An,...],...)");
2528
      }
2529
      if (FW_getIndSize(op->format) >= FW_Word) {  /* outer displacement */
2530
        if (opt_odisp && odopt && !op->base[1] && op->extval[1]==0) {
2531
          /* ([...],0) --> ([...]) */
2532
          op->format &= ~FW_IndSize(FW_SizeMask);
2533
          op->format |= FW_IndSize(FW_Null);
2534
          if (final && warn_opts>1)
2535
             cpu_error(49,"([...],0)->([...])");
2536
        }
2537
        else if (odopt && (op->base[1] || (!op->base[1] && !size16[1])) &&
2538
                 FW_getIndSize(op->format)==FW_Word) {
2539
          /* ([...],od16) --> ([...],od32) */
2540
          op->format &= ~FW_IndSize(FW_SizeMask);
2541
          op->format |= FW_IndSize(FW_Long);
2542
          if (final && warn_opts>1)
2543
             cpu_error(50,"([...],od16)->([...],od32)");
2544
        }
2545
        else if (opt_odisp && odopt && !op->base[1] && size16[1] &&
2546
                 FW_getIndSize(op->format)==FW_Long) {
2547
          /* ([...],od32) --> ([...],od16) */
2548
          op->format &= ~FW_IndSize(FW_SizeMask);
2549
          op->format |= FW_IndSize(FW_Word);
2550
          if (final && warn_opts>1)
2551
             cpu_error(49,"([...],od32)->([...],od16)");
2552
        }
2553
      }
2554
    }
2555
  }
2556
 
2557
  else if (op->mode==MODE_Extended && op->reg==REG_PC8Format &&
2558
           (op->flags & FL_UsesFormat) && (op->format & FW_FullFormat)) {
2559
 
2560
    if (FW_getIndSize(op->format)==FW_None) {  /* no memory indirection */
2561
      if (FW_getBDSize(op->format) > FW_Null) {
2562
        if (opt_bdisp && bdopt && absdpc && op->extval[0]==0) {
2563
          /* (0,PC,...) --> (PC,...) */
2564
          op->format &= ~FW_BDSize(FW_SizeMask);
2565
          op->format |= FW_BDSize(FW_Null);
2566
          if (final && warn_opts>1)
2567
             cpu_error(49,"(0,PC,...)->(PC,...)");
2568
        }
2569
        else if (bdopt && ((secrel && !pcdisp16) || (absdpc && !size16[0]))
2570
                 && FW_getBDSize(op->format)==FW_Word) {
2571
          /* (bd16,PC,...) --> (bd32,PC,...) */
2572
          op->format &= ~FW_BDSize(FW_SizeMask);
2573
          op->format |= FW_BDSize(FW_Long);
2574
          if (final && warn_opts>1)
2575
             cpu_error(50,"(bd16,PC,...)->(bd32,PC,...)");
2576
        }
2577
        else if (opt_bdisp && bdopt &&
2578
                 ((secrel && pcdisp16) || (absdpc && size16[0]))
2579
                 && FW_getBDSize(op->format)==FW_Long) {
2580
          if ((op->format & FW_IndexSuppress) &&
2581
              (ot->modes & (1<<AM_PC16Disp)) &&
2582
              !(op->flags & FL_ZIndex)) {
2583
            /* (bd32,PC,ZRn) --> (d16,PC) */
2584
            op->reg = REG_PC16Disp;
2585
            op->format = 0;
2586
            op->flags &= ~(FL_UsesFormat | FL_020up | FL_noCPU32);
2587
            if (final && warn_opts>1)
2588
               cpu_error(49,"(bd32,PC,ZRn)->(d16,PC)");
2589
          }
2590
          else {
2591
            /* (bd32,PC,Rn) --> (bd16,PC,Rn) */
2592
            op->format &= ~FW_BDSize(FW_SizeMask);
2593
            op->format |= FW_BDSize(FW_Word);
2594
            if (final && warn_opts>1)
2595
               cpu_error(49,"(bd32,PC,Rn)->(bd16,PC,Rn)");
2596
          }
2597
        }
2598
      }
2599
    }
2600
 
2601
    else {  /* memory indirection */
2602
      if (opt_bdisp && bdopt && absdpc &&
2603
          FW_getBDSize(op->format)>FW_Null && op->extval[0]==0) {
2604
        /* ([0,PC,...],...) --> ([PC,...],...) */
2605
        op->format &= ~FW_BDSize(FW_SizeMask);
2606
        op->format |= FW_BDSize(FW_Null);
2607
        if (final && warn_opts>1)
2608
            cpu_error(49,"([0,PC,...],...)->([PC,...],...)");
2609
      }
2610
      else if (bdopt && ((secrel && !pcdisp16) || (absdpc && !size16[0])) &&
2611
               FW_getBDSize(op->format)==FW_Word) {
2612
        /* ([bd16,PC,...],...) --> ([bd32,PC,...],...) */
2613
        op->format &= ~FW_BDSize(FW_SizeMask);
2614
        op->format |= FW_BDSize(FW_Long);
2615
        if (final && warn_opts>1)
2616
            cpu_error(50,"([bd16,PC,...],...)->([bd32,PC,...],...)");
2617
      }
2618
      else if (opt_bdisp && bdopt &&
2619
               ((secrel && pcdisp16) || (absdpc && size16[0])) &&
2620
               FW_getBDSize(op->format)==FW_Long) {
2621
        /* ([bd32,PC,...],...) --> ([bd16,PC,...],...) */
2622
        op->format &= ~FW_BDSize(FW_SizeMask);
2623
        op->format |= FW_BDSize(FW_Word);
2624
        if (final && warn_opts>1)
2625
            cpu_error(49,"([bd32,PC,...],...)->([bd16,PC,...],...)");
2626
      }
2627
      if (FW_getIndSize(op->format) >= FW_Word) {  /* outer displacement */
2628
        if (opt_odisp && !op->base[1] && odopt && op->extval[1]==0) {
2629
          /* ([...],0) --> ([...]) */
2630
          op->format &= ~FW_IndSize(FW_SizeMask);
2631
          op->format |= FW_IndSize(FW_Null);
2632
          if (final && warn_opts>1)
2633
              cpu_error(49,"([...],0)->([...])");
2634
        }
2635
        else if (odopt && (op->base[1] || (!op->base[1] && !size16[1])) &&
2636
                 FW_getIndSize(op->format)==FW_Word) {
2637
          /* ([...],od16) --> ([...],od32) */
2638
          op->format &= ~FW_IndSize(FW_SizeMask);
2639
          op->format |= FW_IndSize(FW_Long);
2640
          if (final && warn_opts>1)
2641
              cpu_error(50,"([...],od16)->([...],od32)");
2642
        }
2643
        else if (opt_odisp && odopt && !op->base[1] && size16[1] &&
2644
                 FW_getIndSize(op->format)==FW_Long) {
2645
          /* ([...],od32) --> ([...],od16) */
2646
          op->format &= ~FW_IndSize(FW_SizeMask);
2647
          op->format |= FW_IndSize(FW_Word);
2648
          if (final && warn_opts>1)
2649
              cpu_error(49,"([...],od32)->([...],od16)");
2650
        }
2651
      }
2652
    }
2653
  }
2654
}
2655
 
2656
 
2657
static int optypes_subset(mnemonic *mold,mnemonic *mnew)
2658
/* returns TRUE, when optypes of mold are a subset of mnew */
2659
{
2660
  int i;
2661
 
2662
  for (i=0; i<MAX_OPERANDS; i++) {
2663
    int ot_old = mold->operand_type[i];
2664
    int ot_new = mnew->operand_type[i];
2665
    uint32_t fl_old = optypes[ot_old].flags;
2666
    uint32_t fl_new = optypes[ot_new].flags;
2667
    uint16_t m = optypes[ot_old].modes;
2668
 
2669
    if ((!ot_old && ot_new) || (!ot_new && ot_old))
2670
      return 0;  /* different number of operands */
2671
 
2672
    if ((optypes[ot_new].modes & m) != m ||
2673
        (fl_old&FL_CheckMask) != (fl_new&FL_CheckMask))
2674
      return 0;  /* addressing modes are not a subset of current mnemo */
2675
 
2676
    if ((fl_old&(OTF_SPECREG|OTF_MOVCREG))!=(fl_new&(OTF_SPECREG|OTF_MOVCREG)))
2677
      return 0;  /* different special/control registers */
2678
 
2679
    if (fl_old & (OTF_SPECREG|OTF_MOVCREG)) {
2680
      if (optypes[ot_old].first < optypes[ot_new].first ||
2681
          optypes[ot_old].last > optypes[ot_new].last)
2682
        return 0;  /* special register range is not a subset */
2683
    }
2684
  }
2685
 
2686
  return 1;
2687
}
2688
 
2689
 
2690
static instruction *ip_dualop(int code,char *q,signed char mode1,
2691
                              signed char reg1,uint16_t flags1,
2692
                              uint16_t format1,expr *exp1,
2693
                              signed char mode2, signed char reg2,
2694
                              uint16_t flags2, uint16_t format2,
2695
                              expr *exp2)
2696
{
2697
  instruction *ip;
2698
 
2699
  if (ipslot >= MAX_IP_COPIES)
2700
    ierror(0);
2701
  ip = clr_instruction(&newip[ipslot]);
2702
  ip->code = code;
2703
  ip->qualifiers[0] = q;
2704
  ip->op[0] = clr_operand(&newop[ipslot][0]);
2705
  ip->op[0]->mode = mode1;
2706
  ip->op[0]->reg = reg1;
2707
  ip->op[0]->flags = flags1;
2708
  ip->op[0]->format = format1;
2709
  ip->op[0]->value[0] = exp1;
2710
  if (mode2 >= 0) {
2711
    ip->op[1] = clr_operand(&newop[ipslot][1]);
2712
    ip->op[1]->mode = mode2;
2713
    ip->op[1]->reg = reg2;
2714
    ip->op[1]->flags = flags2;
2715
    ip->op[1]->format = format2;
2716
    ip->op[1]->value[0] = exp2;
2717
  }
2718
  ++ipslot;
2719
  return ip;
2720
}
2721
 
2722
 
2723
static instruction *ip_singleop(int code,char *q,signed char mode,
2724
                                signed char reg,uint16_t flags,
2725
                                uint16_t format,expr *exp)
2726
{
2727
  return ip_dualop(code,q,mode,reg,flags,format,exp,-1,0,0,0,NULL);
2728
}
2729
 
2730
 
2731
static int test_incr_ea(operand *op,taddr offset)
2732
/* test if we could increment the EA in this operand */
2733
{
2734
  signed char m,r;
2735
  taddr val;
2736
 
2737
  m = op->mode;
2738
  if (m<MODE_AnIndir || m>MODE_Extended)
2739
    return 0;
2740
  val = op->extval[0] + offset;
2741
  if (m == MODE_An8Format) {
2742
    if (op->format & FW_FullFormat)
2743
      return 0;  /* too complex, doesn't make sense */
2744
    if (val<-0x80 || val>0x7f)
2745
      return 0;
2746
  }
2747
  else if (m == MODE_An16Disp) {
2748
    if (val<-0x8000 || val>0x7fff)
2749
      return 0;
2750
  }
2751
  else if (m == MODE_Extended) {
2752
    r = op->reg;
2753
    if (r > REG_AbsLong)
2754
      return 0;  /* no PC-modes for now */
2755
  }
2756
  return 1;
2757
}
2758
 
2759
 
2760
static void incr_ea(operand *op,taddr offset,int final)
2761
/* increment the EA in 'op' by 'offset' when the addressing mode is suitable */
2762
{
2763
  if (final) {
2764
    signed char m = op->mode;
2765
    signed char r = op->reg;
2766
 
2767
    if (m == MODE_AnIndir) {
2768
      /* change to (d16,An) and allocate the d16 expression */
2769
      op->mode = MODE_An16Disp;
2770
      op->value[0] = number_expr(offset);
2771
    }
2772
    else if (m==MODE_An16Disp || m==MODE_An8Format ||
2773
             (m==MODE_Extended && (r==REG_AbsShort || r==REG_AbsLong))) {
2774
      /* increment the expression by 'offset' */
2775
      op->value[0] = make_expr(ADD,op->value[0],number_expr(offset));
2776
    }
2777
  }
2778
  else {
2779
    /* we will definitely need (d16,An) after incrementation for (An) */
2780
    if (op->mode == MODE_AnIndir) {
2781
      op->mode = MODE_An16Disp;
2782
      op->flags |= FL_NoOpt;
2783
    }
2784
  }
2785
}
2786
 
2787
 
2788
static int aindir_in_list(operand *op,taddr list)
2789
/* tests if operand is (An)+ or -(An) and An is present in register list */
2790
{
2791
  if (op->mode==MODE_AnPostInc || op->mode==MODE_AnPreDec)
2792
    return (list & (1 << (REGAn + REGget(op->reg)))) != 0;
2793
  return 0;
2794
}
2795
 
2796
 
2797
static unsigned char optimize_instruction(instruction *iplist,section *sec,
2798
                                          taddr pc,int final)
2799
{
2800
  instruction *ip = iplist;
2801
  mnemonic *mnemo = &mnemonics[ip->code];
2802
  char ext = ip->qualifiers[0] ?
2803
             tolower((unsigned char)ip->qualifiers[0][0]) : '\0';
2804
  unsigned char ipflags = ip->ext.un.real.flags;
2805
  signed char lastsize = ip->ext.un.real.last_size;
2806
  char orig_ext = (char)ip->ext.un.real.orig_ext;
2807
  uint16_t oc;
2808
  taddr val=0,cpc;
2809
  int abs=0,pcrelok=0,i;
2810
 
2811
  /* See if the next instruction fits as well, and includes the
2812
     addressing modes of the current one. Following instructions
2813
     usually have higher CPU requirements. */
2814
  while (mnemo->name==mnemonics[ip->code+1].name &&
2815
         (mnemonics[ip->code+1].ext.available & cpu_type) != 0) {
2816
    mnemonic *nextmn = &mnemonics[ip->code+1];
2817
    uint16_t nextsize = nextmn->ext.size;
2818
 
2819
    /* first check if next instruction supports current size extension */
2820
    if ((mnemo->ext.size&SIZE_MASK) != SIZE_UNSIZED ||
2821
        (nextsize&SIZE_MASK) != SIZE_UNSIZED) {
2822
      if ((nextsize&S_CFCHECK) && (cpu_type&mcf))
2823
        nextsize &= ~(SIZE_BYTE|SIZE_WORD);  /* ColdFire */
2824
      if ((nextsize & lc_ext_to_size(ext)) == 0)
2825
        break;  /* size not supported */
2826
    }
2827
    if (!optypes_subset(mnemo,nextmn) ||
2828
        S_OPCODE_SIZE(nextmn->ext.size) > S_OPCODE_SIZE(mnemo->ext.size))
2829
      break;  /* not all operand types supported or instruction is bigger */
2830
    ip->code++;
2831
  }
2832
  mnemo = &mnemonics[ip->code];
2833
 
2834
  cpc = pc + (S_OPCODE_SIZE(mnemo->ext.size) << 1);
2835
  if (phxass_compat) {
2836
    /* For PhxAss-compatibility, set value of the "current-pc-symbol"
2837
       to pc + S_OPCODE_SIZE. */
2838
    pc = cpc;
2839
  }
2840
 
2841
  /* Make sure JMP/JSR (label,PC) is never optimized (to a short-branch) */
2842
  if ((mnemo->ext.opcode[0]==0x4ec0 || mnemo->ext.opcode[0]==0x4e80) &&
2843
      ip->op[0]!=NULL && ip->op[0]->mode==MODE_Extended &&
2844
      ip->op[0]->reg==REG_PC16Disp)
2845
    ip->op[0]->flags |= FL_NoOpt;  /* do not optimize */
2846
 
2847
  /* evaluate and optimize operands */
2848
  for (i=0; i<MAX_OPERANDS && ip->op[i]!=NULL; i++)
2849
    optimize_oper(ip->op[i],&optypes[mnemo->operand_type[i]],sec,pc,cpc,final);
2850
 
2851
  /* resolve register lists in MOVEM instructions */
2852
  if (mnemo->ext.opcode[0]==0x4880 && mnemo->operand_type[0]!=IR &&
2853
      mnemo->ext.place[0]==D16 && mnemo->ext.place[1]==SEA &&
2854
      ip->op[1]->base[0]==NULL && ip->op[1]->value[0]!=NULL &&
2855
      ip->op[1]->value[0]->type==SYM &&
2856
      (ip->op[1]->value[0]->c.sym->flags & REGLIST)) {
2857
    /* destination operand seems to be the register list - swap them */
2858
    ip->op[0]->reg = REG_AbsLong;
2859
    ip->op[1]->reg = REG_RnList;
2860
    ip->code += 3;  /* take matching mnemonic with swapped operands */
2861
    mnemo = &mnemonics[ip->code];
2862
    if (final && ip->op[0]->base[0]==NULL && ip->op[0]->value[0]!=NULL &&
2863
        ip->op[0]->value[0]->type==SYM &&
2864
        (ip->op[0]->value[0]->c.sym->flags & REGLIST))
2865
      cpu_error(62);  /* register list on both sides */
2866
  }
2867
  /* resolve register lists in FMOVEM instructions */
2868
  else if (mnemo->operand_type[0] == FL) {
2869
    if (ip->op[1]->base[0]==NULL && ip->op[1]->value[0]!=NULL &&
2870
        ip->op[1]->value[0]->type==SYM &&
2871
        (ip->op[1]->value[0]->c.sym->flags & REGLIST)) {
2872
      if (ip->op[1]->extval[0] & 0x1c00)
2873
        ip->code = OC_FMOVEMTOSPEC;  /* list contains special registers */
2874
      else if (mnemo->operand_type[1] == AC)
2875
        ip->code = OC_FMOVEMTOLIST;
2876
      else if (mnemo->operand_type[1] == CFMM)
2877
        ip->code = OC_FMOVEMTOLIST - 1;
2878
      else
2879
        goto dontswap;
2880
      /* destination operand seems to be register list - swap them */
2881
      ip->op[0]->reg = REG_AbsLong;
2882
      ip->op[1]->reg = REG_FPnList;
2883
      mnemo = &mnemonics[ip->code];
2884
      if (final && ip->op[0]->base[0]==NULL && ip->op[0]->value[0]!=NULL &&
2885
          ip->op[0]->value[0]->type==SYM &&
2886
          (ip->op[0]->value[0]->c.sym->flags & REGLIST))
2887
        cpu_error(62);  /* register list on both sides */
2888
    }
2889
    else if (ip->op[0]->base[0]==NULL && (ip->op[0]->extval[0] & 0x1c00)) {
2890
      /* register list in first operand contains special registers */
2891
      ip->code = OC_FMOVEMFROMSPEC;
2892
      mnemo = &mnemonics[ip->code];
2893
    }
2894
  }
2895
  else if (mnemo->operand_type[1]==FL && ip->op[1]->base[0]==NULL &&
2896
           (ip->op[1]->extval[0] & 0x1c00)) {
2897
    /* register list in first operand contains special registers */
2898
    ip->code = OC_FMOVEMTOSPEC;
2899
    mnemo = &mnemonics[ip->code];
2900
  }
2901
  else if (mnemo->ext.place[1]==F13 && ip->op[0]->mode==MODE_Extended &&
2902
           ip->op[0]->reg==REG_Immediate) {
2903
    /* FMOVEM.L #x,FPcrs - may be 64 or 96 bits for two or three registers */
2904
    switch (cntones(ip->op[1]->extval[0],16)) {
2905
      case 2:
2906
        ip->qualifiers[0] = d_str;  /* two registers: 64 bit immediate */
2907
        break;
2908
      case 3:
2909
        ip->qualifiers[0] = x_str;  /* three registers: 96 bit immediate */
2910
        break;
2911
    }
2912
  }
2913
dontswap:
2914
  ip->ext.un.copy.next = NULL;
2915
 
2916
  /* assign _MOVEMBYTES and _MOVEMREGS when opcode is MOVEM */
2917
  if ((mnemo->ext.opcode[0] & 0xfbff) == 0x4880) {
2918
    expr *rlexp = (mnemo->ext.opcode[0] & 0x0400) ?
2919
                  ip->op[1]->value[0] : ip->op[0]->value[0];
2920
    taddr val;
2921
 
2922
    if (!eval_expr(rlexp,&val,NULL,0) && final)
2923
      general_error(30);  /* expression must be constant */
2924
    movemregs->expr = rlexp;
2925
    if (movemsize->expr->type != NUM)
2926
      ierror(0);
2927
    movemsize->expr->c.val = ext=='w' ? 2 : 4;
2928
  }
2929
 
2930
  if (no_opt)
2931
    return ipflags;   /* no optimizations wanted */
2932
 
2933
  /* STAGE 1
2934
     all instructions optimized here may be optimized again in the 2nd stage */
2935
  oc = mnemo->ext.opcode[0];
2936
  if (ip->op[0]) {
2937
    val = ip->op[0]->extval[0];
2938
    abs = ip->op[0]->base[0]==NULL;
2939
    pcrelok = (sec->flags&ABSOLUTE) ? abs :
2940
              !abs && LOCREF(ip->op[0]->base[0])
2941
              && ip->op[0]->base[0]->sec==sec;
2942
  }
2943
 
2944
  if (opt_mul && abs && (oc==0xc0c0 || oc==0xc1c0 || oc==0x4c00) &&
2945
      !(mnemo->ext.opcode[1] & 0x0400) &&
2946
      ip->op[0]->mode==MODE_Extended && ip->op[0]->reg==REG_Immediate) {
2947
    /* MULU/MULS #x,Dn */
2948
    int muls = (oc&0x0100)!=0 || (mnemo->ext.opcode[1]&0x0800)!=0;
2949
 
2950
    if (val == 0) {
2951
      /* mulu/muls #0,Dn -> moveq #0,Dn */
2952
      ip->code = OC_MOVEQ;
2953
      ip->qualifiers[0] = l_str;
2954
      if (final && warn_opts)
2955
        cpu_error(51,"mulu/muls #0,Dn -> moveq #0,Dn");
2956
    }
2957
 
2958
    else if (val == 1) {
2959
      if (ext=='w' && muls) {
2960
        /* muls.w #1,Dn -> ext.l Dn */
2961
        ip->code = OC_EXT;
2962
        ip->qualifiers[0] = l_str;
2963
        if (final) {
2964
          free_operand(ip->op[0]);
2965
          if (warn_opts)
2966
            cpu_error(51,"muls.w #1,Dn -> ext.l Dn");
2967
        }
2968
        ip->op[0] = ip->op[1];
2969
        ip->op[1] = NULL;
2970
      }
2971
      else if (ext=='w' && !muls && (cpu_type&(mcfb|mcfc))) {
2972
        /* ColdFire ISA_B/ISA_C: mulu.w #1,Dn -> mvz.w Dn,Dn */
2973
        ip->code = OC_MVZ;
2974
        if (final) {
2975
          free_operand(ip->op[0]);
2976
          if (warn_opts)
2977
            cpu_error(51,"mulu.w #1,Dn -> mvz.w Dn,Dn");
2978
        }
2979
        ip->op[0] = ip->op[1];
2980
      }
2981
      else if (ext == 'l') {
2982
        /* mulu.l/muls.l #1,Dn -> tst.l Dn */
2983
        ip->code = OC_TST;
2984
        if (final) {
2985
          free_operand(ip->op[0]);
2986
          if (warn_opts)
2987
            cpu_error(51,"mulu/muls.l #1,Dn -> tst.l Dn");
2988
        }
2989
        ip->op[0] = ip->op[1];
2990
        ip->op[1] = NULL;
2991
      }
2992
    }
2993
 
2994
    else if (val==-1 && muls) {
2995
      if (ext == 'w') {
2996
        /* muls.w #-1,Dn -> ext.l Dn + neg.l Dn */
2997
        if (opt_speed) {
2998
          ip->code = OC_EXT;
2999
          ip->qualifiers[0] = l_str;
3000
          if (final) {
3001
            free_operand(ip->op[0]);
3002
            if (warn_opts)
3003
              cpu_error(51,"muls.w #-1,Dn -> ext.l Dn + neg.l Dn");
3004
          }
3005
          ip->op[0] = ip->op[1];
3006
          ip->op[1] = NULL;
3007
          ip->ext.un.copy.next = ip_singleop(OC_NEG,l_str,MODE_Dn,
3008
                                             ip->op[0]->reg,0,0,NULL);
3009
        }
3010
      }
3011
      else {
3012
        /* muls.l #-1,Dn -> neg.l Dn */
3013
        ip->code = OC_NEG;
3014
        if (final) {
3015
          free_operand(ip->op[0]);
3016
          if (warn_opts)
3017
            cpu_error(51,"mulu/muls #-1,Dn -> neg.l Dn");
3018
        }
3019
        ip->op[0] = ip->op[1];
3020
        ip->op[1] = NULL;
3021
      }
3022
    }
3023
 
3024
    else if (val>=2 && val<=0x100 && cntones(val,9)==1) {
3025
      val = lsbit(val,1,9);
3026
      if (ext=='w' && muls && opt_speed) {
3027
        /* muls.w #x,Dn -> ext.l Dn + asl.l #x,Dn */
3028
        instruction *ip2 = copy_instruction(ip);
3029
 
3030
        ip->code = OC_EXT;
3031
        ip->qualifiers[0] = l_str;
3032
        ip2->code = OC_ASLI;
3033
        ip2->qualifiers[0] = l_str;
3034
        ip2->op[0]->extval[0] = val;
3035
        if (final) {
3036
          free_operand(ip->op[0]);
3037
          free_expr(ip2->op[0]->value[0]);
3038
          ip2->op[0]->value[0] = number_expr(val);
3039
          if (warn_opts)
3040
            cpu_error(51,"muls.w #x,Dn -> ext.l Dn + asl.l #x,Dn");
3041
        }
3042
        else
3043
          ip2->op[0]->flags |= FL_DoNotEval;
3044
        ip->op[0] = ip->op[1];
3045
        ip->op[1] = NULL;
3046
        ip->ext.un.copy.next = ip2;  /* append ASL */
3047
        ip = ip2;  /* make stage 2 look at the ASL */
3048
      }
3049
      else if (ext=='w' && !muls && (cpu_type&(mcfb|mcfc)) && opt_speed) {
3050
        /* ColdFire ISA_B/ISA_C: mulu.w #x,Dn -> mvz.w Dn,Dn + lsl.l #x,Dn */
3051
        instruction *ip2 = copy_instruction(ip);
3052
 
3053
        ip->code = OC_MVZ;
3054
        ip->qualifiers[0] = w_str;
3055
        ip->op[0] = ip->op[1];
3056
        ip2->code = OC_LSLI;
3057
        ip2->qualifiers[0] = l_str;
3058
        ip2->op[0]->extval[0] = val;
3059
        if (final) {
3060
          free_expr(ip2->op[0]->value[0]);
3061
          ip2->op[0]->value[0] = number_expr(val);
3062
          if (warn_opts)
3063
            cpu_error(51,"mulu.w #x,Dn -> mvz.w Dn,Dn + lsl.l #x,Dn");
3064
        }
3065
        else
3066
          ip2->op[0]->flags |= FL_DoNotEval;
3067
        ip->ext.un.copy.next = ip2;  /* append LSL */
3068
        /* ip = ip2;  stage 2 optimization doesn't make sense for ColdFire */
3069
      }
3070
      else if (ext == 'l') {
3071
        /* mulu/muls.l #x,Dn -> lsl/asl.l #x,Dn */
3072
        ip->code = muls ? OC_ASLI : OC_LSLI;
3073
        if (final) {
3074
          free_expr(ip->op[0]->value[0]);
3075
          ip->op[0]->value[0] = number_expr(val);
3076
          if (warn_opts)
3077
            cpu_error(51,"mulu/muls.l #x,Dn -> lsl/asl.l #x,Dn");
3078
        }
3079
        else
3080
          ip->op[0]->flags |= FL_DoNotEval;
3081
        ip->op[0]->extval[0] = val;
3082
      }
3083
    }
3084
 
3085
    else if (val<=-2 && val>=-0x100 && muls && cntones(-val,9)==1) {
3086
      val = lsbit(-val,1,9);
3087
      if (opt_speed && ext=='w') {
3088
        /* muls.w #-x,Dn -> ext.l Dn + asl.l #x,Dn + neg.l Dn */
3089
        instruction *ip2 = copy_instruction(ip);
3090
 
3091
        ip->code = OC_EXT;
3092
        ip->qualifiers[0] = l_str;
3093
        ip2->code = OC_ASLI;
3094
        ip2->qualifiers[0] = l_str;
3095
        ip2->op[0]->extval[0] = val;
3096
        if (final) {
3097
          free_operand(ip->op[0]);
3098
          free_expr(ip2->op[0]->value[0]);
3099
          ip2->op[0]->value[0] = number_expr(val);
3100
          if (warn_opts)
3101
            cpu_error(51,"muls.w #-x,Dn -> ext.l Dn + asl.l #x,Dn + neg.l Dn");
3102
        }
3103
        else
3104
          ip2->op[0]->flags |= FL_DoNotEval;
3105
        ip->op[0] = ip->op[1];
3106
        ip->op[1] = NULL;
3107
        ip->ext.un.copy.next = ip2;  /* append ASL */
3108
        ip2->ext.un.copy.next = ip_singleop(OC_NEG,l_str,MODE_Dn,
3109
                                           ip2->op[1]->reg,0,0,NULL);
3110
        ip = ip2;  /* make stage 2 look at the ASL */
3111
      }
3112
      else if (ext == 'l' && opt_speed) {
3113
        /* muls.l #-x,Dn -> asl.l #x,Dn + neg.l Dn */
3114
        ip->code = OC_ASLI;
3115
        if (final) {
3116
          free_expr(ip->op[0]->value[0]);
3117
          ip->op[0]->value[0] = number_expr(val);
3118
          if (warn_opts)
3119
            cpu_error(51,"muls.l #-x,Dn -> asl.l #x,Dn + neg.l Dn");
3120
        }
3121
        else
3122
          ip->op[0]->flags |= FL_DoNotEval;
3123
        ip->op[0]->extval[0] = val;
3124
        ip->ext.un.copy.next = ip_singleop(OC_NEG,l_str,MODE_Dn,
3125
                                           ip->op[1]->reg,0,0,NULL);
3126
      }
3127
    }
3128
  }
3129
 
3130
  /* STAGE 2 - reread, in case instruction was optimized in stage 1 */
3131
  if (ip->code >= 0) {
3132
    mnemo = &mnemonics[ip->code];
3133
    oc = mnemo->ext.opcode[0];
3134
    ext = ip->qualifiers[0] ?
3135
          tolower((unsigned char)ip->qualifiers[0][0]) : '\0';
3136
  }
3137
 
3138
  if ((ip->code==OC_MOVE || oc==0x0040) &&
3139
      ip->op[0]->mode==MODE_Extended && ip->op[0]->reg==REG_Immediate) {
3140
    int movqabsl = opt_moveq && abs && ext=='l' && ip->op[1]->mode==MODE_Dn;
3141
 
3142
    /* MOVE/MOVEA immediate instruction */
3143
    if (movqabsl && val>=-0x80 && val<=0x7f) {
3144
      /* move.l #x,Dn --> moveq #x,Dn */
3145
      ip->code = OC_MOVEQ;
3146
      ip->qualifiers[0] = l_str;
3147
      if (final && warn_opts>1)
3148
        cpu_error(51,"move.l #x,Dn -> moveq #x,Dn");
3149
    }
3150
    else if (movqabsl && (!(cpu_type & (m68040|mcf)) || opt_size) &&
3151
             ((val>=0x80 && val<=0xfe) || (val>=-0x100 && val<=-0x82)) &&
3152
             !(val&1)) {
3153
      /* move.l #x,Dn --> moveq #x>>1,Dn ; add.w Dn,Dn */
3154
      ip->code = OC_MOVEQ;
3155
      ip->qualifiers[0] = l_str;
3156
      if (final) {
3157
        free_expr(ip->op[0]->value[0]);
3158
        ip->op[0]->value[0] = number_expr(val >> 1);
3159
        if (warn_opts > 1)
3160
          cpu_error(51,"move.l #x,Dn -> moveq #x,Dn + add.w Dn,Dn");
3161
      }
3162
      else
3163
        ip->op[0]->flags |= FL_DoNotEval;
3164
      ip->op[0]->extval[0] = val >> 1;
3165
      ip->ext.un.copy.next = ip_dualop(OC_ADD,(cpu_type & mcf)?l_str:w_str,
3166
                                       MODE_Dn,ip->op[1]->reg,0,0,NULL,
3167
                                       MODE_Dn,ip->op[1]->reg,0,0,NULL);
3168
    }
3169
    else if (opt_nmovq && abs && ext=='l' && ip->op[1]->mode==MODE_Dn &&
3170
             !(cpu_type & (m68040|mcf)) && val>=0x80 && val<=0xff) {
3171
      /* move.l #x,Dn --> moveq #x^$ff,Dn ; not.b Dn */
3172
      ip->code = OC_MOVEQ;
3173
      ip->qualifiers[0] = l_str;
3174
      if (final) {
3175
        free_expr(ip->op[0]->value[0]);
3176
        ip->op[0]->value[0] = number_expr(val^0xff);
3177
        if (warn_opts)
3178
          cpu_error(51,"move.l #x,Dn -> moveq #y,Dn + not.b Dn");
3179
      }
3180
      else
3181
        ip->op[0]->flags |= FL_DoNotEval;
3182
      ip->op[0]->extval[0] = val^0xff;
3183
      ip->ext.un.copy.next = ip_singleop(OC_NOT,b_str,
3184
                                         MODE_Dn,ip->op[1]->reg,0,0,NULL);
3185
    }
3186
    else if (movqabsl && !(cpu_type & m68040) &&
3187
             (((val&0xffff)==0 && val>=0x10000 && val<=0x7f0000) ||
3188
              ((val&0xffff)==0xffff && (utaddr)val>=0xff80ffff
3189
               && (utaddr)val<=0xfffeffff))) {
3190
      /* move.l #x,Dn --> moveq #x>>16,Dn ; swap Dn */
3191
      ip->code = OC_MOVEQ;
3192
      ip->qualifiers[0] = l_str;
3193
      if (final) {
3194
        free_expr(ip->op[0]->value[0]);
3195
        ip->op[0]->value[0] = number_expr(val >> 16);
3196
        if (warn_opts > 1)
3197
          cpu_error(51,"move.l #x,Dn -> moveq #y,Dn + swap Dn");
3198
      }
3199
      else
3200
        ip->op[0]->flags |= FL_DoNotEval;
3201
      ip->op[0]->extval[0] = val >> 16;
3202
      ip->ext.un.copy.next = ip_singleop(OC_SWAP,w_str,
3203
                                         MODE_Dn,ip->op[1]->reg,0,0,NULL);
3204
    }
3205
    else if (opt_nmovq && abs && ext=='l' && ip->op[1]->mode==MODE_Dn &&
3206
             !(cpu_type & (m68040|mcf)) &&
3207
             (((utaddr)val>=0xff81 && (utaddr)val<=0xffff) ||
3208
              ((utaddr)val>=0xffff0001 && (utaddr)val<=0xffff0080))) {
3209
      /* move.l #x,Dn --> moveq #-x,Dn ; neg.w Dn */
3210
      ip->code = OC_MOVEQ;
3211
      ip->qualifiers[0] = l_str;
3212
      if (final) {
3213
        free_expr(ip->op[0]->value[0]);
3214
        ip->op[0]->value[0] = number_expr(-((int16_t)val));
3215
        if (warn_opts)
3216
          cpu_error(51,"move.l #x,Dn -> moveq #y,Dn + neg.w Dn");
3217
      }
3218
      else
3219
        ip->op[0]->flags |= FL_DoNotEval;
3220
      ip->op[0]->extval[0] = -((int16_t)val);
3221
      ip->ext.un.copy.next = ip_singleop(OC_NEG,w_str,
3222
                                         MODE_Dn,ip->op[1]->reg,0,0,NULL);
3223
    }
3224
    else if (opt_size && movqabsl && (val&0xff)==0 && !(cpu_type & mcf) &&
3225
             val>=0x100 && val<=0x7f00) {
3226
      /* move.l #x,Dn --> moveq #x>>n,Dn ; lsl.w #n,Dn */
3227
      instruction *ip2 = ip_dualop(OC_LSLI,w_str,
3228
                                   MODE_Extended,REG_Immediate,
3229
                                   FL_NoOpt,0,ip->op[0]->value[0], /* dummy */
3230
                                   MODE_Dn,ip->op[1]->reg,FL_NoOpt,0,NULL);
3231
      int shift = msbit(val,14,8) - 6;
3232
 
3233
      ip->code = OC_MOVEQ;
3234
      ip->qualifiers[0] = l_str;
3235
      if (final) {
3236
        free_expr(ip->op[0]->value[0]);
3237
        ip->op[0]->value[0] = number_expr(val >> shift);
3238
        ip2->op[0]->value[0] = number_expr(shift);
3239
        if (warn_opts)
3240
          cpu_error(51,"move.l #x,Dn -> moveq #x>>n,Dn + lsl.w #n,Dn");
3241
      }
3242
      else {
3243
        ip->op[0]->flags |= FL_DoNotEval;
3244
        ip2->op[0]->flags |= FL_DoNotEval;
3245
      }
3246
      ip->op[0]->extval[0] = val >> shift;
3247
      ip2->op[0]->extval[0] = shift;
3248
      ip->ext.un.copy.next = ip2;
3249
    }
3250
    else if (opt_gen && abs && val==0 && !(oc&0x0040) &&
3251
             ((cpu_type & (m68010up|mcf|cpu32)) || opt_clr)) {
3252
      /* move #0,<ea> --> clr <ea> */
3253
      ip->code = OC_CLR;
3254
      if (final)
3255
        free_operand(ip->op[0]);
3256
      ip->op[0] = ip->op[1];
3257
      ip->op[1] = NULL;
3258
      if (final && (warn_opts>1 ||
3259
                    (warn_opts && !(cpu_type&(m68010up|mcf|cpu32)))))
3260
        cpu_error(51,"move #0 -> clr");
3261
    }
3262
    else if (opt_moveq && abs && ext=='l' && (val==-1 || (val>=1 && val<=7)) &&
3263
             (cpu_type & (mcfb|mcfc))) {
3264
      /* move.l #x,<ea> -> mov3q #x,<ea> for x=-1,1..7 */
3265
      ip->code = OC_MOV3Q;
3266
      if (final && warn_opts>1)
3267
        cpu_error(51,"move.l #x -> mov3q #x");
3268
    }
3269
    else if (opt_st && abs && ext=='b' && !(oc&0x0040) && (val&0xff)==0xff) {
3270
      /* move.b #-1,<ea> --> st <ea> */
3271
      if (!(cpu_type & mcf) || ip->op[1]->mode==MODE_Dn) {
3272
        ip->code = OC_ST;
3273
        if (final)
3274
          free_operand(ip->op[0]);
3275
        ip->op[0] = ip->op[1];
3276
        ip->op[1] = NULL;
3277
        if (final && warn_opts)
3278
          cpu_error(51,"move.b #-1 -> st");
3279
      }
3280
    }
3281
    else if (opt_pea && ip->op[1]->mode==MODE_AnPreDec &&
3282
             ip->op[1]->reg==7 && ext=='l') {
3283
      /* move.l #x,-(a7) --> pea x */
3284
      if (abs && val>=-0x8000 && val<=0x7fff) {
3285
        ip->op[0]->reg = REG_AbsShort;
3286
        ip->code = OC_PEA;
3287
        if (final)
3288
          free_operand(ip->op[1]);
3289
        ip->op[1] = NULL;
3290
        if (final && warn_opts)
3291
          cpu_error(51,"move.l #x,-(a7) -> pea x.w");
3292
      }
3293
      else if (cpu_type & (m68000|m68010|m68020|m68030|cpu32)) {
3294
        /* Faster for 68000-68030 only. */
3295
        ip->op[0]->reg = REG_AbsLong;
3296
        ip->code = OC_PEA;
3297
        if (final)
3298
          free_operand(ip->op[1]);
3299
        ip->op[1] = NULL;
3300
        if (final && warn_opts)
3301
          cpu_error(51,"move.l #x,-(a7) -> pea x.l");
3302
      }
3303
    }
3304
    else if (opt_gen && oc==0x0040) {
3305
      if (abs && val==0) {
3306
        /* movea #0,An --> suba.l An,An */
3307
        ip->code = OC_SUBA;
3308
        ip->qualifiers[0] = l_str;
3309
        ip->op[0]->mode = MODE_An;
3310
        ip->op[0]->reg = ip->op[1]->reg;
3311
        if (final && warn_opts>1)
3312
          cpu_error(51,"movea #0,An -> suba.l An,An");
3313
      }
3314
      else if (!abs && ext=='l') {
3315
        /* movea.l #label,An --> lea label,An */
3316
        ip->code = OC_LEA;
3317
        ip->op[0]->reg = REG_AbsLong;
3318
        if (final && warn_opts>1)
3319
          cpu_error(51,"movea.l #label,An -> lea label,An");
3320
      }
3321
    }
3322
  }
3323
 
3324
  else if (opt_moveq && abs && (oc & 0xff7f)==0x7100 &&
3325
           ip->op[0]->mode==MODE_Extended && ip->op[0]->reg==REG_Immediate &&
3326
           ((val>=-0x80 && !(oc&0x0080)) || val>=0) && val<=0x7f) {
3327
    /* MVS #-128..127,Dn or MVZ #0..127,Dn --> MOVEQ */
3328
    ip->code = OC_MOVEQ;
3329
    ip->qualifiers[0] = l_str;
3330
    if (final && warn_opts>1)
3331
      cpu_error(51,"mvs/mvz #x,Dn -> moveq #x,Dn");
3332
  }
3333
 
3334
  else if ((opt_gen || opt_movem) && (oc & 0xfbff) == 0x4880) {
3335
    /* MOVEM */
3336
    int o = (oc & 0x0400) ? 1 : 0;
3337
 
3338
    if (ip->op[o]->mode==MODE_Extended &&
3339
        (ip->op[o]->reg==REG_RnList || ip->op[o]->reg==REG_Immediate) &&
3340
        ip->op[o]->base[0]==NULL && !(ip->op[o]->flags & FL_NoOpt)) {
3341
      taddr list = ip->op[o]->extval[0];
3342
      int regs = cntones(list,16);
3343
 
3344
      if (regs == 0) {
3345
        /* no registers in list - delete instruction */
3346
        ip->code = -1;
3347
        if (final && warn_opts>1)
3348
          cpu_error(51,"movem deleted");
3349
      }
3350
      else if (regs == 1) {
3351
        /* a single register - MOVEM <ea>,Rn --> MOVE <ea>,Rn */
3352
        if ((opt_movem || (!(list&0xff) && o==1)) &&
3353
            !aindir_in_list(ip->op[o^1],list)) {
3354
          signed char r = lsbit(list,0,16);
3355
 
3356
          ip->code = OC_MOVE;
3357
          ip->op[o]->mode = REGisAn(r) ? MODE_An : MODE_Dn;
3358
          ip->op[o]->reg = REGget(r);
3359
          if (final && (warn_opts>1 || (warn_opts && ((list&0xff) || o==0))))
3360
            cpu_error(51,"movem ea,Rn -> move ea,Rn");
3361
        }
3362
      }
3363
      else if (regs==2 && opt_speed &&
3364
               ((cpu_type & m68040) || (!(cpu_type & (m68000|m68010)) &&
3365
                ip->op[o^1]->mode<=MODE_AnPreDec))) {
3366
        /* MOVEM with two registers is faster with two separate MOVEs,
3367
           when not using 68000 or 68010. Addressing modes with displacement
3368
           or extended addressing modes for 68040 only. */
3369
        taddr offs = ext=='l' ? 4 : 2;
3370
 
3371
        if ((opt_movem || (!(list&0xff) && o==1)) &&
3372
            test_incr_ea(ip->op[o^1],offs) &&
3373
            !aindir_in_list(ip->op[o^1],list)) {
3374
          signed char r = lsbit(list,0,16);
3375
          instruction *ip2;
3376
 
3377
          /* make two identical move instructions */
3378
          ip->code = OC_MOVE;
3379
          ip->op[o]->mode = REGisAn(r) ? MODE_An : MODE_Dn;
3380
          ip->op[o]->reg = REGget(r);
3381
          ip2 = copy_instruction(ip);
3382
          r = lsbit(list,r+1,16);
3383
          /* determine which register to move first */
3384
          if (o==0 && ip->op[1]->mode==MODE_AnPreDec) {
3385
            ip->op[o]->mode = REGisAn(r) ? MODE_An : MODE_Dn;
3386
            ip->op[o]->reg = REGget(r);
3387
          }
3388
          else {
3389
            ip2->op[o]->mode = REGisAn(r) ? MODE_An : MODE_Dn;
3390
            ip2->op[o]->reg = REGget(r);
3391
          }
3392
          /* increment EA of second move */
3393
          incr_ea(ip2->op[o^1],offs,final);
3394
          ip->ext.un.copy.next = ip2;  /* append the 2nd MOVE */
3395
          if (final && (warn_opts>1 || (warn_opts && ((list&0xff) || o==0))))
3396
            cpu_error(51,"movem ea,Rm/Rn -> move ea,Rm + move ea,Rn");
3397
        }
3398
      }
3399
    }
3400
  }
3401
 
3402
  else if (opt_gen && !strcmp(mnemo->name,"fmovem") &&
3403
           (mnemo->ext.opcode[1] & 0xcfff) == 0xc000) {
3404
    /* FMOVEM */
3405
    int o = (mnemo->ext.opcode[1] & 0x2000) ? 0 : 1;
3406
 
3407
    if (ip->op[o]->mode==MODE_Extended && ip->op[o]->reg==REG_FPnList &&
3408
        ip->op[o]->base[0]==NULL && !(ip->op[o]->flags & FL_NoOpt) &&
3409
        ip->op[o]->extval[0]==0) {
3410
      /* no registers in list - delete instruction */
3411
      ip->code = -1;
3412
      if (final && warn_opts>1)
3413
        cpu_error(51,"fmovem deleted");
3414
    }
3415
  }
3416
 
3417
  else if (opt_gen && oc==0x4200 && ip->op[0]->mode==MODE_Dn && ext=='l') {
3418
    /* CLR.L Dn --> MOVEQ #0,Dn */
3419
    ip->code = OC_MOVEQ;
3420
    ip->qualifiers[0] = l_str;
3421
    if (final) {
3422
      ip->op[1] = ip->op[0];
3423
      ip->op[0] = new_operand();
3424
      ip->op[0]->mode = MODE_Extended;
3425
      ip->op[0]->reg = REG_Immediate;
3426
      ip->op[0]->value[0] = number_expr(0);
3427
      if (warn_opts>1)
3428
        cpu_error(51,"clr.l Dn -> moveq #0,Dn");
3429
    }
3430
    else
3431
      ip->op[0] = NULL;
3432
  }
3433
 
3434
  else if (opt_gen && abs && (oc==0xc000 || oc==0x0200) &&
3435
           ip->op[0]->mode==MODE_Extended && ip->op[0]->reg==REG_Immediate) {
3436
    /* ANDI/AND #x,<ea> */
3437
 
3438
    if ((cpu_type & (mcfb|mcfc)) && ip->op[1]->mode==MODE_Dn && ext=='l' &&
3439
        (val==0xff || val==0xffff)) {
3440
      /* ColdFire ISA_B/ISA_C: andi.l #$ff/$ffff,Dn -> mvz.b/w Dn,Dn */
3441
      ip->code = OC_MVZ;
3442
      ip->qualifiers[0] = val==0xff ? b_str : w_str;
3443
      if (final) {
3444
        free_operand(ip->op[0]);
3445
        if (warn_opts>1)
3446
          cpu_error(51,"andi.l #$ff/$ffff,Dn -> mvz.b/w Dn,Dn");
3447
      }
3448
      ip->op[0] = ip->op[1];
3449
    }
3450
    else if ((val==0xff && ext=='b') || (val==0xffff && ext=='w') ||
3451
             (val==0xffffffff && ext=='l')) {
3452
      /* andi.b/w/l #$ff/$ffff/$ffffffff,<ea> -> tst.b/w/l <ea> */
3453
      ip->code = OC_TST;
3454
      if (final) {
3455
        free_operand(ip->op[0]);
3456
        if (warn_opts>1)
3457
          cpu_error(51,"andi.b/w/l #$ff/$ffff/$fffffff -> tst");
3458
      }
3459
      ip->op[0] = ip->op[1];
3460
      ip->op[1] = NULL;
3461
    }
3462
    else if (val==0 && ((cpu_type & (m68010up|mcf|cpu32)) || opt_clr)) {
3463
      /* andi.x #0,<ea> -> clr.x <ea> */
3464
      ip->code = OC_CLR;
3465
      if (final) {
3466
        free_operand(ip->op[0]);
3467
        if (warn_opts>1)
3468
          cpu_error(51,"and #0 -> clr");
3469
      }
3470
      ip->op[0] = ip->op[1];
3471
      ip->op[1] = NULL;
3472
    }
3473
  }
3474
 
3475
  else if (opt_gen && abs && val==0 &&
3476
           (oc==0x8000 || oc==0x0000 || oc==0x0a00) &&
3477
           S_SIZEMODE(mnemo->ext.size)!=S_MOVE &&
3478
           ip->op[0]->mode==MODE_Extended && ip->op[0]->reg==REG_Immediate) {
3479
    /* ORI/OR/EORI #0,<ea> --> TST <ea> */
3480
    ip->code = OC_TST;
3481
    if (final) {
3482
      free_operand(ip->op[0]);
3483
      if (warn_opts>1)
3484
        cpu_error(51,"ori #0 -> tst");
3485
    }
3486
    ip->op[0] = ip->op[1];
3487
    ip->op[1] = NULL;
3488
  }
3489
 
3490
  else if (opt_gen && abs && oc==0x0a00) {
3491
    if ((ext=='b' && (val&0xff)==0xff) ||
3492
        (ext=='w' && (val&0xffff)==0xffff) || (ext=='l' && val==-1)) {
3493
      /* EORI #-1,<ea> --> NOT <ea> */
3494
      ip->code = OC_NOT;
3495
      if (final)
3496
        free_operand(ip->op[0]);
3497
      ip->op[0] = ip->op[1];
3498
      ip->op[1] = NULL;
3499
      if (final && warn_opts>1)
3500
        cpu_error(51,"eori #-1 -> not");
3501
    }
3502
  }
3503
 
3504
  else if ((oc==0x0600 || oc==0xd000 || oc==0xd0c0 ||
3505
            oc==0x0400 || oc==0x9000 || oc==0x90c0)) {
3506
    if (ip->op[0]->mode==MODE_Extended &&
3507
        ip->op[0]->reg==REG_Immediate && abs) {
3508
      /* ADD/ADDI/ADDA/SUB/SUBI/SUBA Immediate --> ADDQ/SUBQ */
3509
      if (opt_quick && val>=1 && val<=8) {
3510
        ip->code = (oc&0x4200) ? OC_ADDQ : OC_SUBQ;
3511
        if (final && warn_opts>1)
3512
          cpu_error(51,"add/sub #x -> addq/subq #x");
3513
      }
3514
      else if ((oc&0x90c0) == 0x90c0) {  /* ADDA/SUBA */
3515
        if (!(oc & 0x4000))
3516
          val = -val;
3517
        if (opt_gen && val == 0) {
3518
          ip->code = -1;  /* delete ADDA/SUBA #0,An */
3519
          if (final && warn_opts>1)
3520
            cpu_error(51,"adda/suba #0,An deleted");
3521
        }
3522
        else if (opt_lea && val>=-0x8000 && val<=0x7fff) {
3523
          /* ADDA/SUBA Immediate --> LEA d(An),An */
3524
          ip->qualifiers[0] = l_str;
3525
          ip->code = OC_LEA;
3526
          ip->op[0]->mode = MODE_An16Disp;
3527
          ip->op[0]->reg = ip->op[1]->reg;
3528
          if (!(oc&0x4000) && final) {
3529
            free_expr(ip->op[0]->value[0]);
3530
            ip->op[0]->value[0] = number_expr(val);
3531
          }
3532
          else
3533
            ip->op[0]->flags |= FL_DoNotEval;
3534
          ip->op[0]->extval[0] = val;
3535
          if (final && warn_opts>1)
3536
            cpu_error(51,"adda/suba #x,An -> lea (d,An),An");
3537
        }
3538
      }
3539
    }
3540
  }
3541
 
3542
  else if (oc==0x41c0) {
3543
    if (ip->op[0]->mode==MODE_An16Disp && abs) {
3544
      if (opt_gen && ip->op[0]->reg==ip->op[1]->reg && val==0) {
3545
        /* delete LEA (0,An),An */
3546
        ip->code = -1;
3547
        if (final && warn_opts>1)
3548
          cpu_error(51,"lea (0,An),An deleted");
3549
      }
3550
      else if (opt_lquick && ip->op[0]->reg==ip->op[1]->reg &&
3551
               val!=0 && val>=-8 && val<=8) {
3552
        /* LEA (d,An),An --> ADDQ/SUBQ #d,An */
3553
        if (val < 0) {
3554
          ip->code = OC_SUBQ;
3555
          val = -val;
3556
          if (final) {
3557
            free_op_exp(ip->op[0]);
3558
            ip->op[0]->value[0] = number_expr(val);
3559
          }
3560
        }
3561
        else
3562
          ip->code = OC_ADDQ;
3563
        ip->qualifiers[0] = l_str;
3564
        ip->op[0]->mode = MODE_Extended;
3565
        ip->op[0]->reg = REG_Immediate;
3566
        if (final && warn_opts>1)
3567
          cpu_error(51,"lea (d,An),An -> addq/subq #d,An");
3568
      }
3569
      else if (opt_gen && (val<-0x8000 || val>0x7fff) &&
3570
               !(cpu_type & (m68020up|cpu32))) {
3571
        /* 68000/010: LEA (d32,Am),An --> MOVEA.L Am,An ; ADDA.L #d32,An */
3572
        if (ip->op[0]->reg == ip->op[1]->reg) {
3573
          /* special case: LEA (d32,An),An -> ADDA.L #d32,An */
3574
          ip->code = OC_ADDA;
3575
          ip->op[0]->mode = MODE_Extended;
3576
          ip->op[0]->reg = REG_Immediate;
3577
          ip->op[0]->flags |= FL_NoOpt;
3578
        }
3579
        else {
3580
          instruction *ip2 = ip_dualop(OC_ADDA,l_str,
3581
                                       MODE_Extended,REG_Immediate,
3582
                                       FL_NoOpt,0,ip->op[0]->value[0],
3583
                                       MODE_An,ip->op[1]->reg,
3584
                                       FL_NoOpt,0,NULL);
3585
          ip->code = OC_MOVEA;
3586
          ip->op[0]->mode = MODE_An;
3587
          ip->ext.un.copy.next = ip2;  /* append the ADDA */
3588
        }
3589
        ip->qualifiers[0] = l_str;
3590
        if (final)
3591
          cpu_error(47); /* lea-displacement out of range, changed */
3592
      }
3593
    }
3594
    else if (opt_gen && ip->op[0]->mode==MODE_AnIndir &&
3595
             ip->op[0]->reg==ip->op[1]->reg) {
3596
      /* delete LEA (An),An */
3597
      ip->code = -1;
3598
      if (final && warn_opts>1)
3599
        cpu_error(51,"lea (An),An deleted");
3600
    }
3601
    else if (opt_gen && abs && val==0 && ip->op[0]->mode==MODE_Extended &&
3602
             (ip->op[0]->reg==REG_AbsShort || ip->op[0]->reg==REG_AbsLong)) {
3603
      /* LEA 0,An -> SUBA.L An,An */
3604
      ip->code = OC_SUBA;
3605
      ip->qualifiers[0] = l_str;
3606
      ip->op[0]->mode = MODE_An;
3607
      ip->op[0]->reg = ip->op[1]->reg;
3608
      if (final && warn_opts>1)
3609
        cpu_error(51,"lea 0,An -> suba.l An,An");
3610
    }
3611
  }
3612
 
3613
  else if (opt_gen && oc==0x4808 && ip->op[1]->base[0]==NULL) {
3614
    /* LINK.L --> LINK.W */
3615
    taddr val = ip->op[1]->extval[0];
3616
 
3617
    if (val>=-0x8000 && val<=0x7fff) {
3618
      ip->qualifiers[0] = w_str;
3619
      ip->code--;
3620
      if (final && warn_opts>1)
3621
        cpu_error(51,"link.l -> link.w");
3622
    }
3623
  }
3624
 
3625
  else if (opt_gen && oc==0x4e50 && ip->op[1]->base[0]==NULL &&
3626
           (cpu_type & (m68020up|cpu32))) {
3627
    /* LINK.W --> LINK.L */
3628
    taddr val = ip->op[1]->extval[0];
3629
 
3630
    if (val<-0x8000 || val>0x7fff) {
3631
      ip->qualifiers[0] = l_str;
3632
      ip->code++;
3633
      if (final)
3634
        cpu_error(45);  /* link.w changed to link.l */
3635
    }
3636
  }
3637
 
3638
  else if (oc==0x0c00 || oc==0xb000 || oc==0xb0c0) {
3639
    if (opt_gen && abs && val==0 &&
3640
        ip->op[0]->mode==MODE_Extended && ip->op[0]->reg==REG_Immediate) {
3641
      /* CMP/CMPI/CMPA #0 --> TST */
3642
      if (oc!=0xb0c0 || (cpu_type & (m68020up|cpu32|mcf))) {
3643
        if (oc == 0xb0c0) {
3644
          /* optimize both CMP.W #0,An and CMP.L #0,An to TST.L An */
3645
          ip->code = OC_TST + 1;
3646
          ip->qualifiers[0] = l_str;
3647
        }
3648
        else
3649
          ip->code = OC_TST;
3650
        if (final)
3651
          free_operand(ip->op[0]);
3652
        ip->op[0] = ip->op[1];
3653
        ip->op[1] = NULL;
3654
        if (final && warn_opts>1)
3655
          cpu_error(51,"cmp #0 -> tst");
3656
      }
3657
    }
3658
  }
3659
 
3660
  else if ((((oc&0xf1ff)==0xe100 && opt_gen) ||
3661
            ((oc&0xf1ff)==0xe108 && opt_lsl)) && !(cpu_type&(m68060|mcf))) {
3662
    /* LSL is only optimized with opt_lsl */
3663
    if ((oc&0x0e00) == 0x0200)
3664
      val = 1;  /* ASL/LSL Dn (missing immediate operand assumed as 1) */
3665
    if (val == 1) {
3666
      /* ASL/LSL #1,Dn --> ADD Dn,Dn */
3667
      ip->code = OC_ADD;
3668
      ip->op[0]->mode = MODE_Dn;
3669
      if (!(oc&0x0e00))
3670
        ip->op[0]->reg = ip->op[1]->reg;
3671
      if (final && (warn_opts>1 || (warn_opts && (oc&0x0008))))
3672
        cpu_error(51,"asl/lsl #1 -> add");
3673
    }
3674
    else if (opt_speed && opt_lsl && val==2 && (ext=='b' || ext=='w')) {
3675
      /* ASL/LSL #2,Dn --> ADD Dn,Dn + ADD Dn,Dn (just .B and .W) */
3676
      ip->code = OC_ADD;
3677
      ip->op[0]->mode = MODE_Dn;
3678
      ip->op[0]->reg = ip->op[1]->reg;
3679
      ip->ext.un.copy.next = copy_instruction(ip);
3680
      if (final && (warn_opts>1 || (warn_opts && (oc&0x0008))))
3681
        cpu_error(51,"asl/lsl #2 -> add add");
3682
    }
3683
  }
3684
 
3685
  else if (opt_fconst && (mnemo->ext.available & (mfpu|m68040up)) &&
3686
           abs && mnemo->operand_type[0]==FA && mnemo->operand_type[1]==F_ &&
3687
           ip->op[0]->mode==MODE_Extended && ip->op[0]->reg==REG_Immediate) {
3688
    unsigned char buf[12];
3689
    uint64_t man;
3690
    int exp;
3691
 
3692
    if (ext == 'x') {
3693
      if (copy_float_exp(buf,ip->op[0],EXT_EXTENDED) != 0)
3694
        ext = 0;
3695
    }
3696
    else if (ext == 'd') {
3697
      if (copy_float_exp(buf,ip->op[0],EXT_DOUBLE) != 0)
3698
        ext = 0;
3699
    }
3700
    else if (ext == 's') {
3701
      if (copy_float_exp(buf,ip->op[0],EXT_SINGLE) != 0)
3702
        ext = 0;
3703
    }
3704
    else
3705
      ext = 0;
3706
 
3707
    if (ext == 'x') {
3708
      /* Fxxx.X #m,FPn */
3709
      int i;
3710
 
3711
      for (i=1,exp=0; i<12; i++)
3712
        exp |= buf[i];
3713
      if (!exp && (buf[0]==0x00 || buf[0]==0x80)) {
3714
        /* Special case: 0.0 or -0.0 -> convert to double.
3715
           We do not need to handle the "final" case here, because
3716
           0.0 is always translated to single-precision in the next step. */
3717
        ip->qualifiers[0] = d_str;
3718
        ext = 'd';
3719
      }
3720
      else {
3721
        exp = ((((int)buf[0]&0x7f)<<8) | (int)buf[1]) - 0x3fff;
3722
        man = readval(1,buf+4,8) & 0x7fffffffffffffffLL;
3723
        if (exp>=-0x3ff && exp<=0x400 && (man&0x7ff)==0) {
3724
          /* double precision would be sufficient, so convert */
3725
          int64_t v = (buf[0] & 0x80) ? -0x8000000000000000LL : 0;
3726
 
3727
          v = v | ((int64_t)(exp+0x3ff) << 52) | (man >> 11);
3728
          if (final) {
3729
            free_op_exp(ip->op[0]);
3730
            ip->op[0]->value[0] = huge_expr(huge_from_int(v));
3731
            if (warn_opts>1)
3732
              cpu_error(51,"f<op>.x #m,FPn -> f<op>.d #m,FPn");
3733
          }
3734
          ip->qualifiers[0] = d_str;
3735
          ext = 'd';
3736
          rf68k_setval(1,buf,8,v);
3737
        }
3738
      }
3739
    }
3740
 
3741
    if (ext == 'd') {
3742
      /* Fxxx.D #m,FPn */
3743
      exp = ((((int)buf[0]&0x7f)<<4) | (((int)buf[1]&0xf0)>>4)) - 0x3ff;
3744
      man = readval(1,buf,8) & 0xfffffffffffffLL;
3745
      if ((exp>=-0x7f && exp<=0x80 && (man&0x1fffffff)==0) ||
3746
          (exp==-0x3ff && man==0)) {  /* also allow all zeros for 0.0 */
3747
        /* single precision would be sufficient, so convert */
3748
        uint32_t v = (buf[0]&0x80) ? 0x80000000 : 0;  /* m. sign */
3749
 
3750
        if (exp != -0x3ff)
3751
          v |= (uint32_t)(exp+0x7f) << 23;  /* exponent */
3752
        v |= (uint32_t)(man >> 29);         /* mantissa */
3753
        if (final) {
3754
          free_op_exp(ip->op[0]);
3755
          ip->op[0]->value[0] = number_expr((taddr)v);
3756
          if (warn_opts>1)
3757
            cpu_error(51,"f<op>.d #m,FPn -> f<op>.s #m,FPn");
3758
        }
3759
        ip->qualifiers[0] = s_str;
3760
        ext = 's';
3761
        rf68k_setval(1,buf,4,v);
3762
      }
3763
    }
3764
 
3765
    if (final && (!strcmp(mnemo->name,"fdiv") || !strcmp(mnemo->name,"fsdiv")
3766
        || !strcmp(mnemo->name,"fddiv") || !strcmp(mnemo->name,"fsgldiv"))) {
3767
      /* FxDIV.s #m,FPn and FxDIV.d #m,FPn
3768
         Can be optimized to FxMUL.s/FxMUL.d #1/m,FPn when m is a power of 2,
3769
         which is the case when the mantissa is zero. */
3770
      int optok = 0;
3771
 
3772
      if (ext == 's') {
3773
        exp = ((((int)buf[0]&0x7f)<<1) | (((int)buf[1]&0x80)>>7)) - 0x7f;
3774
        if ((readval(1,buf,4) & 0x007fffffLL) == 0
3775
            && exp!=-0x7f) {
3776
          setbits(1,buf,16,1,8,0x7f-exp);  /* 8-bit exponent to offset 1 */
3777
          free_op_exp(ip->op[0]);
3778
          ip->op[0]->value[0] = number_expr(readval(1,buf,4));
3779
          optok = 1;
3780
        }
3781
      }
3782
      else if (ext == 'd') {
3783
        exp = ((((int)buf[0]&0x7f)<<4) | (((int)buf[1]&0xf0)>>4)) - 0x3ff;
3784
        if ((readval(1,buf,8) & 0xfffffffffffffLL) == 0 && exp!=-0x3ff) {
3785
          setbits(1,buf,16,1,11,0x3ff-exp);  /* 11-bit exponent to offset 1 */
3786
          free_op_exp(ip->op[0]);
3787
          ip->op[0]->value[0] = huge_expr(huge_from_mem(1,buf,8));
3788
          optok = 1;
3789
        }
3790
      }
3791
      else if (ext == 'x') {
3792
        exp = ((((int)buf[0]&0x7f)<<8) | (int)buf[1]) - 0x3fff;
3793
        if ((readval(1,buf+4,8) & 0x7fffffffffffffffLL) == 0) {
3794
          setbits(1,buf,16,1,15,0x3fff-exp);  /* 15-bit exponent to offset 1 */
3795
          free_op_exp(ip->op[0]);
3796
          ip->op[0]->value[0] = huge_expr(huge_from_mem(1,buf,12));
3797
          optok = 1;
3798
        }
3799
      }
3800
      if (optok) {
3801
        if (!strcmp(mnemo->name,"fdiv")) {
3802
          ip->code = OC_FMUL;
3803
          if (warn_opts>1)
3804
            cpu_error(51,"fdiv #m,FPn -> fmul #1/m,FPn");
3805
        }
3806
        else if (!strcmp(mnemo->name,"fsdiv")) {
3807
          ip->code = OC_FSMUL;
3808
          if (warn_opts>1)
3809
            cpu_error(51,"fsdiv #m,FPn -> fsmul #1/m,FPn");
3810
        }
3811
        else if (!strcmp(mnemo->name,"fddiv")) {
3812
          ip->code = OC_FDMUL;
3813
          if (warn_opts>1)
3814
            cpu_error(51,"fddiv #m,FPn -> fdmul #1/m,FPn");
3815
        }
3816
        else if (!strcmp(mnemo->name,"fsgldiv")) {
3817
          ip->code = OC_FSGLMUL;
3818
          if (warn_opts>1)
3819
            cpu_error(51,"fsgldiv #m,FPn -> fsglmul #1/m,FPn");
3820
        }
3821
      }
3822
    }
3823
  }
3824
 
3825
  else if ((oc&0xfeff) == 0x80c0 && abs &&
3826
           ip->op[0]->mode==MODE_Extended && ip->op[0]->reg==REG_Immediate) {
3827
    /* DIVU.W/DIVS.W #x,Dn */
3828
 
3829
    if (val == 0) {
3830
      /* divu.w/divs.w #0,Dn */
3831
      if (final)
3832
        cpu_error(60);  /* division by zero */
3833
    }
3834
    else if (opt_div && val == 1 && (cpu_type & (mcfb|mcfc))) {
3835
      /* ColdFire ISA_B/ISA_C: divu.w/divs.w #1,Dn -> mvz.w Dn,Dn */
3836
      ip->code = OC_MVZ;
3837
      if (final) {
3838
        free_operand(ip->op[0]);
3839
        if (warn_opts)
3840
          cpu_error(51,"divu/divs.w #1,Dn -> mvz.w Dn,Dn");
3841
      }
3842
      ip->op[0] = ip->op[1];
3843
    }
3844
    else if (opt_div && opt_speed && val ==-1 && (oc&0x0100) &&
3845
             (cpu_type & (mcfb|mcfc))) {
3846
      /* ColdFire ISA_B/ISA_C: divs.w #-1,Dn -> neg.w Dn + mvz.w Dn,Dn */
3847
      ip->code = OC_NEG;
3848
      if (final) {
3849
        free_operand(ip->op[0]);
3850
        if (warn_opts)
3851
          cpu_error(51,"divs.w #-1,Dn -> neg.w Dn + mvz.w Dn,Dn");
3852
      }
3853
      ip->op[0] = ip->op[1];
3854
      ip->op[1] = NULL;
3855
      ip->ext.un.copy.next = ip_dualop(OC_MVZ,w_str,
3856
                                       MODE_Dn,ip->op[0]->reg,0,0,NULL,
3857
                                       MODE_Dn,ip->op[0]->reg,0,0,NULL);
3858
    }
3859
  }
3860
 
3861
  else if (oc == 0x4c40) {
3862
    if (abs &&
3863
        ip->op[0]->mode==MODE_Extended && ip->op[0]->reg==REG_Immediate) {
3864
      /* DIVU.L/DIVS.L #x,Dn */
3865
 
3866
      if (val == 0) {
3867
        /* divu.l/divs.l #0,Dn */
3868
        if (final)
3869
          cpu_error(60);  /* division by zero */
3870
      }
3871
      else if (opt_div && mnemo->operand_type[1]==D_) {
3872
        if (val == 1) {
3873
          /* divu.l/divs.l #1,Dn -> tst.l Dn */
3874
          ip->code = OC_TST;
3875
          if (final) {
3876
            free_operand(ip->op[0]);
3877
            if (warn_opts)
3878
              cpu_error(51,"divu/divs.l #1,Dn -> tst.l Dn");
3879
          }
3880
          ip->op[0] = ip->op[1];
3881
          ip->op[1] = NULL;
3882
        }
3883
        else if (val==-1 && (mnemo->ext.opcode[1] & 0x0800)) {
3884
          /* divs.l #-1,Dn -> neg.l Dn */
3885
          ip->code = OC_NEG;
3886
          if (final) {
3887
            free_operand(ip->op[0]);
3888
            if (warn_opts)
3889
              cpu_error(51,"divs.l #-1,Dn -> neg.l Dn");
3890
          }
3891
          ip->op[0] = ip->op[1];
3892
          ip->op[1] = NULL;
3893
        }
3894
        else if (val>=2 && val<=0x100 && (mnemo->ext.opcode[1] & 0x0800)==0 &&
3895
                 cntones(val,9)==1) {
3896
          /* divu.l #x,Dn -> lsr.l #x,Dn */
3897
          ip->code = OC_LSRI;
3898
          val = lsbit(val,1,9);
3899
          if (final) {
3900
            free_expr(ip->op[0]->value[0]);
3901
            ip->op[0]->value[0] = number_expr(val);
3902
            if (warn_opts)
3903
              cpu_error(51,"divu.l #x,Dn -> lsr.l #x,Dn");
3904
          }
3905
          else
3906
            ip->op[0]->flags |= FL_DoNotEval;
3907
          ip->op[0]->extval[0] = val;
3908
        }
3909
      }
3910
    }
3911
    if (final && mnemo->operand_type[1]==DD && !(mnemo->ext.opcode[1]&0x0400)
3912
        && ((ip->op[1]->reg>>4) & 0xf) == (ip->op[1]->reg & 0xf))
3913
      /* DIVxL.L <ea>,Dn:Dn is DIVx.L <ea>,Dn */
3914
      cpu_error(65);  /* Dr and Dq are identical! */
3915
  }
3916
 
3917
  else if (oc==0x4ec0 || oc==0x4e80) {
3918
    if (pcrelok && opt_pc && !(ip->op[0]->flags & FL_NoOpt) &&
3919
        ip->op[0]->mode==MODE_Extended &&
3920
        (ip->op[0]->reg==REG_AbsLong || ip->op[0]->reg==REG_PC16Disp)) {
3921
      /* JMP/JSR label --> BRA/BSR label */
3922
      taddr diff = val - cpc;
3923
 
3924
      if (lastsize==0 || (diff==0 && (oc & 0x40))) {
3925
        ip->code = -1;  /* delete a JMP to following location */
3926
        if (final && warn_opts>1)
3927
          cpu_error(51,"jmp deleted");
3928
      }
3929
      else if (diff>=-0x8000 && diff<=0x7fff) {
3930
        if (diff>=-0x80 && diff<=0x7f) {
3931
          if ((lastsize==2 && diff==0) ||
3932
              (lastsize==4 && diff==2))
3933
            ip->qualifiers[0] = w_str;
3934
          else
3935
            ip->qualifiers[0] = b_str;
3936
          ip->code = (oc & 0x40) ? OC_BRA : OC_BSR;
3937
          ip->op[0]->reg = REG_AbsLong;
3938
        }
3939
        else {
3940
          ip->qualifiers[0] = w_str;
3941
          ip->code = (oc & 0x40) ? OC_BRA : OC_BSR;
3942
          ip->op[0]->reg = REG_AbsLong;
3943
        }
3944
        if (final && warn_opts>1)
3945
          cpu_error(51,"jmp/jsr -> bra/bsr");
3946
      }
3947
    }
3948
    else if (!(ip->op[0]->flags & FL_NoOpt) &&
3949
             ip->op[0]->mode==MODE_Extended && ip->op[0]->reg==REG_AbsLong &&
3950
             !abs && EXTREF(ip->op[0]->base[0])) {
3951
      if (opt_sc) {
3952
        /* JMP/JSR extlabel --> JMP/JSR extlabel(PC) */
3953
        ip->op[0]->reg = REG_PC16Disp;
3954
        if (final && warn_opts>1)
3955
          cpu_error(51,"jmp/jsr -> jmp/jsr (PC)");
3956
      }
3957
      else if (opt_jbra && !kick1hunks && (cpu_type & (m68020up|cpu32))) {
3958
        /* JMP/JSR extlabel -> BRA.L/BSR.L extlabel (68020+, CPU32) */
3959
        ip->qualifiers[0] = l_str;
3960
        ip->code = (oc & 0x40) ? OC_BRA+1 : OC_BSR+1;  /* +1 for .L form */
3961
        if (final && warn_opts>1)
3962
          cpu_error(51,"jmp/jsr -> bra.l/bsr.l");
3963
      }
3964
    }
3965
  }
3966
 
3967
  else if ((oc & 0xf000)==0x6000) {
3968
    /* Bcc label */
3969
    if (opt_bra && ((ipflags&IFL_UNSIZED) || opt_allbra) && pcrelok) {
3970
      taddr diff = val - cpc;
3971
      int resolvewarn = (sec->flags&RESOLVE_WARN)!=0;
3972
 
3973
      switch (lastsize) {
3974
        case 0:
3975
#if 0
3976
          /* keep branch deleted until no more optimizations took place */
3977
          if (diff!=-2 && done)
3978
#else
3979
          if (diff != -2)
3980
#endif
3981
            ip->qualifiers[0] = b_str;
3982
          else
3983
            ip->code = -1;
3984
          break;
3985
        case 2:
3986
          if (diff==0 && oc!=0x6100 && !resolvewarn)
3987
            ip->code = -1;
3988
          else if (diff<-0x80 || diff>0x7f || diff==0)
3989
            ip->qualifiers[0] = w_str;
3990
          else
3991
            ip->qualifiers[0] = b_str;
3992
          break;
3993
        case 4:
3994
          if (diff==2) {
3995
            if (oc!=0x6100 && !resolvewarn)
3996
              ip->code = -1;
3997
            else
3998
              ip->qualifiers[0] = w_str;
3999
          }
4000
          else if (diff>=-0x80 && diff<=0x80 && !resolvewarn) {
4001
            ip->qualifiers[0] = b_str;
4002
          }
4003
          else if (diff<-0x8000 || diff>0x7fff) {
4004
            if (cpu_type & (m68020up|cpu32|mcfb|mcfc)) {
4005
              ip->qualifiers[0] = l_str;
4006
            }
4007
            else {
4008
              ip->qualifiers[0] = emptystr;
4009
              ipflags |= IFL_RETAINLASTSIZE;
4010
              if (oc < 0x6200) {
4011
                /* BRA/BSR label --> JMP/JSR label */
4012
                ip->code = (oc==0x6000) ? OC_JMP : OC_JSR;
4013
                if (final)
4014
                  cpu_error(46);  /* branch out of range changed to jmp */
4015
              }
4016
              else {
4017
                /* Bcc label --> B!cc *+8, JMP label */
4018
                instruction *ip2;
4019
 
4020
                /* make a new absolute JMP to the Bcc's destination */
4021
                ip2 = ip_singleop(OC_JMP,emptystr,
4022
                                  MODE_Extended,REG_AbsLong,
4023
                                  FL_NoOpt,0,ip->op[0]->value[0]);
4024
                ip->code += (oc&0x0100) ? -2 : 2; /* negate branch condition */
4025
                ip->qualifiers[0] = b_str;
4026
                ip->op[0]->flags |= FL_NoOpt;
4027
                ip->ext.un.copy.next = ip2;  /* append the JMP */
4028
                if (final) {
4029
                  /* assign "*+8" as the Bcc's expression */
4030
                  ip->op[0]->value[0] = make_expr(ADD,curpc_expr(),
4031
                          number_expr(phxass_compat ? 6 : 8));
4032
                  cpu_error(46);  /* branch out of range changed to jmp */
4033
                }
4034
              }
4035
            }
4036
          }
4037
          else
4038
            ip->qualifiers[0] = w_str;
4039
          break;
4040
        case 6:
4041
          if (diff>=-0x8000 && diff<=0x7fff && !resolvewarn)
4042
            ip->qualifiers[0] = w_str;
4043
          else
4044
            ip->qualifiers[0] = l_str;
4045
          break;
4046
        default:
4047
          if (ext == '\0')
4048
            ip->qualifiers[0] = w_str;
4049
          break;
4050
      }
4051
      if (final && warn_opts>1) {
4052
        /* print the finally performed kind of optimization */
4053
        if (ip->code == -1)
4054
          cpu_error(51,"branch deleted");
4055
        else {
4056
          char new_ext = tolower((unsigned char)ip->qualifiers[0][0]);
4057
          int oldsize = branch_size(orig_ext);
4058
          int newsize = branch_size(new_ext);
4059
 
4060
          if (newsize != oldsize)
4061
            cpu_error(newsize<oldsize?53:54,new_ext);
4062
        }
4063
      }
4064
    }
4065
    else if (opt_branop && oc!=0x6100 && pcrelok && val-cpc==0 &&
4066
             (ext=='b' || ext=='s')) {
4067
      /* short-branch with zero-distance which cannot be optimized
4068
         is turned into a NOP */
4069
      ip->qualifiers[0] = emptystr;
4070
      ip->code = OC_NOOP;
4071
      if (final)
4072
        free_operand(ip->op[0]);
4073
      ip->op[0] = NULL;
4074
      if (final)
4075
        cpu_error(57);  /* bra.b *+2 turned into a nop */
4076
    }
4077
    else if (opt_brajmp && !abs && ip->op[0]->base[0]->sec!=sec &&
4078
             LOCREF(ip->op[0]->base[0])) {
4079
      /* reference to label from different section */
4080
      ip->qualifiers[0] = emptystr;
4081
      if (oc < 0x6200) {
4082
        /* BRA/BSR label --> JMP/JSR label */
4083
        ip->code = (oc==0x6000) ? OC_JMP : OC_JSR;
4084
        if (final && warn_opts>1)
4085
          cpu_error(52,"bra/bsr -> jmp/jsr");
4086
      }
4087
      else {
4088
        /* Bcc label --> B!cc *+8, JMP label */
4089
        instruction *ip2;
4090
 
4091
        /* make a new absolute JMP to the Bcc's destination */
4092
        ip2 = ip_singleop(OC_JMP,emptystr,
4093
                          MODE_Extended,REG_AbsLong,
4094
                          FL_NoOpt,0,ip->op[0]->value[0]);
4095
        ip->code += (oc&0x0100) ? -2 : 2; /* negate branch condition */
4096
        ip->qualifiers[0] = b_str;
4097
        ip->op[0]->flags |= FL_NoOpt;
4098
        ip->ext.un.copy.next = ip2;  /* append the JMP */
4099
        if (final) {
4100
          /* assign "*+8" as the Bcc's expression */
4101
          ip->op[0]->value[0] = make_expr(ADD,curpc_expr(),
4102
                  number_expr(phxass_compat ? 6 : 8));
4103
          if (warn_opts>1)
4104
            cpu_error(52,"b<cc> label -> b<!cc> *+8, jmp label");
4105
        }
4106
      }
4107
    }
4108
  }
4109
 
4110
  else if ((oc & 0xff80)==0xf080 && ip->code!=OC_FNOP) {
4111
    /* cpBcc label */
4112
    if (opt_bra && ((ipflags&IFL_UNSIZED) || opt_allbra) && pcrelok) {
4113
      taddr diff = val - cpc;
4114
 
4115
      switch (lastsize) {
4116
        case 4:
4117
          if (diff<-0x8000 || diff>0x7fff)
4118
            ip->qualifiers[0] = l_str;
4119
          else
4120
            ip->qualifiers[0] = w_str;
4121
          break;
4122
        case 6:
4123
          if (diff>=-0x8000 && diff<=0x7fff)
4124
            ip->qualifiers[0] = w_str;
4125
          else
4126
            ip->qualifiers[0] = l_str;
4127
          break;
4128
        default:
4129
          if (ext == '\0')
4130
            ip->qualifiers[0] = w_str;
4131
          break;
4132
      }
4133
      if (final && warn_opts>1 && (ipflags&IFL_UNSIZED))
4134
        cpu_error(53,*(ip->qualifiers[0]));
4135
    }
4136
  }
4137
  else if (oc==0xf000 && !(mnemo->ext.available & mfloat)
4138
           && (mnemo->ext.opcode[1] & 0xe000) == 0x8000) {
4139
    if (final && ip->op[2]!=NULL && ip->op[2]->base[0]==NULL
4140
        && ip->op[2]->extval[0]==0 && ip->op[3]!=NULL)
4141
      cpu_error(64);  /* An operand at level #0 causes F-line Exception */
4142
  }
4143
 
4144
  if (opt_immaddr && abs && ext=='l' && ip->op[0]!=NULL &&
4145
      ip->op[0]->mode==MODE_Extended && ip->op[0]->reg==REG_Immediate &&
4146
      ip->op[1]!=NULL && ip->op[1]->mode==MODE_An &&
4147
      val>=-0x8000 && val<=0x7fff &&
4148
      !(cpu_type & mcf) && (mnemonics[ip->code].ext.size & SIZE_WORD) &&
4149
      (mnemonics[ip->code].ext.opcode[0] & 0xfeff) != 0x5000) {
4150
    /* op.L #x,An --> op.W #x,An (if not ColdFire and not ADDQ/SUBQ) */
4151
    ip->qualifiers[0] = w_str;
4152
    if (final && warn_opts>1)
4153
      cpu_error(51,"<op>.L #x,An -> <op>.W #x,An");
4154
  }
4155
 
4156
  /* Try to optimize operands again, in case an instruction was optimized. */
4157
  /* WARNING: 'ext' may be trashed at this point! */
4158
 
4159
  for (ip=iplist; ip; ip=ip->ext.un.copy.next) {
4160
    if (ip->code >= 0) {
4161
      for (i=0; i<MAX_OPERANDS && ip->op[i]!=NULL; i++)
4162
        optimize_oper(ip->op[i],&optypes[mnemonics[ip->code].operand_type[i]],
4163
                      sec,pc,cpc,final);
4164
    }
4165
  }
4166
 
4167
  return ipflags;
4168
}
4169
 
4170
 
4171
static size_t oper_size(instruction *ip,operand *op,struct optype *ot)
4172
/* returns number of bytes for a single operand */
4173
{
4174
  int mode = op->mode;
4175
  int reg = op->reg;
4176
 
4177
  if (ot->flags & OTF_NOSIZE) {
4178
    return 0;
4179
  }
4180
  else if (mode==MODE_An16Disp || (mode==MODE_Extended &&
4181
           (reg==REG_PC16Disp || reg==REG_AbsShort))) {
4182
    return 2;
4183
  }
4184
  else if (mode==MODE_Extended && reg==REG_AbsLong) {
4185
    if (ot->flags & OTF_BRANCH)
4186
      return (taddr)branch_size(ip->qualifiers[0] ?
4187
                                tolower((unsigned char)ip->qualifiers[0][0]) :
4188
                                '\0');
4189
    else if (ot->flags & OTF_DBRA)
4190
      return 2;
4191
    else
4192
      return 4;
4193
  }
4194
  else if (mode==MODE_Extended && reg==REG_Immediate) {
4195
    switch (ip->qualifiers[0] ?
4196
            tolower((unsigned char)ip->qualifiers[0][0]) : '\0') {
4197
      case 'b':
4198
      case 'w':
4199
        return 2;
4200
      case 'l':
4201
      case 's':
4202
        return 4;
4203
      case 'q':
4204
      case 'd':
4205
        return 8;
4206
      case 'x':
4207
      case 'p':
4208
        return 12;
4209
    }
4210
  }
4211
  else if (mode==MODE_An8Format ||
4212
           (mode==MODE_Extended && reg==REG_PC8Format)) {
4213
    if (op->flags & FL_UsesFormat) {
4214
      size_t n = 2;
4215
 
4216
      if (op->format & FW_FullFormat) {
4217
        if (FW_getBDSize(op->format) == FW_Word)
4218
          n += 2;
4219
        else if (FW_getBDSize(op->format) == FW_Long)
4220
          n += 4;
4221
        if (FW_getIndSize(op->format) == FW_Word)
4222
          n += 2;
4223
        else if (FW_getIndSize(op->format) == FW_Long)
4224
          n += 4;
4225
      }
4226
      return n;
4227
    }
4228
    else
4229
      ierror(0);
4230
  }
4231
 
4232
  return 0;
4233
}
4234
 
4235
 
4236
static size_t ip_size(instruction *ip)
4237
{
4238
  if (ip->code >= 0) {
4239
    mnemonic *mnemo = &mnemonics[ip->code];
4240
    size_t size = S_OPCODE_SIZE(mnemo->ext.size) << 1;
4241
    int i;
4242
 
4243
    for (i=0; i<MAX_OPERANDS && ip->op[i]!=NULL; i++)
4244
      size += oper_size(ip,ip->op[i],&optypes[mnemo->operand_type[i]]);
4245
    return size;
4246
  }
4247
  return 0;
4248
}
4249
 
4250
 
4251
static size_t iplist_size(instruction *ip)
4252
{
4253
  size_t size = 0;
4254
 
4255
  do {
4256
    size += ip_size(ip);
4257
  }
4258
  while ((ip = ip->ext.un.copy.next) != NULL);
4259
  return size;
4260
}
4261
 
4262
 
4263
size_t instruction_size(instruction *realip,section *sec,taddr pc)
4264
/* Calculate the size of the current instruction; must be identical
4265
   to the data created by eval_instruction. */
4266
{
4267
  mnemonic *mnemo = &mnemonics[realip->code];
4268
  char ext = realip->qualifiers[0] ?
4269
             tolower((unsigned char)realip->qualifiers[0][0]) : '\0';
4270
  int i;
4271
  size_t size;
4272
  instruction *ip;
4273
  unsigned char extflags;
4274
  uint16_t extsize;
4275
 
4276
  /* check if current mnemonic is valid for selected cpu-type */
4277
  while (!(mnemo->ext.available & cpu_type)) {
4278
    /* try next mnemonic from table, when it still has the same
4279
       name and all operand-types */
4280
    mnemonic *lastm = mnemo;
4281
 
4282
    mnemo++;
4283
    if (lastm->name==mnemo->name || !optypes_subset(lastm,mnemo))
4284
      cpu_error(0);  /* instruction not supported */
4285
    realip->code++;
4286
  }
4287
 
4288
  extsize = mnemo->ext.size;
4289
 
4290
  /* remember the instruction's original extension, before optimizations */
4291
  if (realip->ext.un.real.orig_ext < 0)
4292
    realip->ext.un.real.orig_ext = (signed char)ext;
4293
 
4294
  if (opt_allbra && ign_unambig_ext && ext) {
4295
    /* Strip the size extension from branch instructions, no matter if
4296
       illegal or not. The optimizer will find the best size. */
4297
    for (i=0; i<MAX_OPERANDS; i++) {
4298
      if (mnemonics[realip->code].operand_type[i] == BR) {
4299
        ext = '\0';
4300
        realip->qualifiers[0] = emptystr;
4301
        break;
4302
      }
4303
    }
4304
  }
4305
 
4306
  if (ext == '\0') {
4307
    /* remember when developer didn't specify a size extension */
4308
    realip->ext.un.real.flags |= IFL_UNSIZED;
4309
 
4310
    /* assign a default extension for sized instructions, when missing */
4311
    if ((extsize & SIZE_MASK) != 0) {
4312
      if ((extsize & S_CFCHECK) && (cpu_type & mcf))
4313
        extsize &= ~(SIZE_BYTE|SIZE_WORD);  /* SIZE_LONG for ColdFire only */
4314
      if ((cpu_type & mcf) && (extsize & SIZE_LONG))  /* ColdFire prefers .l */
4315
        realip->qualifiers[0] = l_str;
4316
      else if ((extsize & (SIZE_WORD|SIZE_DOUBLE|S_QUADDEF)) ==
4317
               (SIZE_WORD|SIZE_DOUBLE|S_QUADDEF))  /* AMMX prefers .q */
4318
        realip->qualifiers[0] = q_str;
4319
      else if (extsize & SIZE_WORD)
4320
        realip->qualifiers[0] = w_str;
4321
      else if (extsize & SIZE_BYTE)
4322
        realip->qualifiers[0] = b_str;
4323
      else if (extsize & SIZE_LONG)
4324
        realip->qualifiers[0] = l_str;
4325
      else if (extsize & SIZE_EXTENDED)
4326
        realip->qualifiers[0] = x_str;
4327
      else if (extsize & SIZE_SINGLE)
4328
        realip->qualifiers[0] = s_str;
4329
      else if (extsize & SIZE_DOUBLE)
4330
        realip->qualifiers[0] = d_str;
4331
      else if (extsize & SIZE_PACKED)
4332
        realip->qualifiers[0] = p_str;
4333
      else
4334
        ierror(0);
4335
      ext = realip->qualifiers[0][0];
4336
    }
4337
  }
4338
 
4339
  /* check if opcode extension is valid */
4340
  if ((mnemo->ext.size & SIZE_MASK) == SIZE_UNSIZED) {
4341
    if (ext != '\0') {
4342
      if (!ign_unsized_ext)
4343
        cpu_error(35);  /* extension for unsized instruction ignored */
4344
      ext = '\0';
4345
      realip->qualifiers[0] = emptystr;
4346
    }
4347
  }
4348
  else {
4349
    int uacode;
4350
    int err = 0;
4351
    uint16_t extsize = mnemo->ext.size;
4352
    uint16_t sz  = lc_ext_to_size(ext);  /* convert ext. to SIZE-code */
4353
 
4354
    if ((mnemo->ext.size&SIZE_UNAMBIG) && (mnemo->ext.available&cpu_type))
4355
      uacode = realip->code;  /* last mnemonic with unambiguous size ext. */
4356
    else
4357
      uacode = -1;
4358
 
4359
    /* Find a mnemonic with same name and operands which matches the
4360
       given size extension. */
4361
    while (!((((extsize&S_CFCHECK) && (cpu_type&mcf)) ?
4362
              (extsize & ~(SIZE_BYTE|SIZE_WORD)) : extsize) & sz)) {
4363
      mnemo++;
4364
      if ((err = mnemonics[realip->code].name!=mnemo->name) != 0)
4365
        break;
4366
      if ((err = !optypes_subset(&mnemonics[realip->code],mnemo)) != 0)
4367
        break;
4368
 
4369
      realip->code++;
4370
      extsize = mnemo->ext.size;
4371
      if ((mnemo->ext.size&SIZE_UNAMBIG) && (mnemo->ext.available&cpu_type))
4372
        uacode = realip->code;
4373
    }
4374
 
4375
    if (err) {
4376
      if (ign_unambig_ext && uacode>=0) {
4377
        /* size extension is wrong, but we can guess the right one */
4378
        realip->code = uacode;
4379
        mnemo = &mnemonics[uacode];
4380
        extsize = mnemo->ext.size;
4381
        ext = '\0';
4382
        realip->qualifiers[0] = emptystr;
4383
      }
4384
      else
4385
        cpu_error(34);  /* illegal opcode extension */
4386
    }
4387
 
4388
    if (!(mnemo->ext.available & cpu_type))
4389
      cpu_error(0);  /* instruction not supported */
4390
  }
4391
 
4392
  /* check if we are uncertain about the side of a register list operand */
4393
#if 0
4394
  /* @@@ Why should we forbid optimizations here? FL_PossRegList is useless? */
4395
  if (realip->op[0]!=NULL && realip->op[1]!=NULL) {
4396
    if ((realip->op[0]->flags & FL_PossRegList) &&
4397
        realip->op[1]->mode==MODE_Extended &&
4398
        realip->op[1]->reg==REG_AbsLong) {
4399
      realip->op[0]->flags &= ~FL_PossRegList;
4400
      realip->op[0]->flags |= FL_NoOpt;
4401
      realip->op[1]->flags |= FL_NoOpt;
4402
    }
4403
    else if ((realip->op[1]->flags & FL_PossRegList) &&
4404
             realip->op[0]->mode==MODE_Extended &&
4405
             realip->op[0]->reg==REG_AbsLong) {
4406
      realip->op[1]->flags &= ~FL_PossRegList;
4407
      realip->op[1]->flags |= FL_NoOpt;
4408
      realip->op[0]->flags |= FL_NoOpt;
4409
    }
4410
  }
4411
#endif
4412
 
4413
  /* fix instructions, which were not correctly recognized through
4414
     parse_operand() due to missing information. */
4415
  if (mnemo->ext.opcode[0]==0xf518 && !(cpu_type & m68040up)) {
4416
    /* try 68030/68851 PFLUSHA instead */
4417
    realip->code++;
4418
  }
4419
 
4420
  /* do optimizations on a copy of the current instruction */
4421
  ipslot = 0;
4422
  ip = copy_instruction(realip);
4423
  extflags = optimize_instruction(ip,sec,pc,0);
4424
 
4425
  /* and determine current size (from optimized copy) */
4426
  size = iplist_size(ip);
4427
  if (!(extflags & IFL_RETAINLASTSIZE))
4428
    realip->ext.un.real.last_size = size;  /* remember size for next pass */
4429
 
4430
  return size;
4431
}
4432
 
4433
 
4434
static void write_val(unsigned char *d,int pos,int size,taddr val,int sign)
4435
/* insert value 'val' with 'size' bits at bit-position 'pos' */
4436
{
4437
  if (typechk) {
4438
    if (sign) {
4439
      if ((val > (1L << (size-1)) - 1) || (val < -(1L << (size-1)))) {
4440
        if (val > 0 && val < (1L << size))
4441
          cpu_error(27,val,-(1L<<(size-1)),
4442
                    (1L<<(size-1))-1,
4443
                    val-(1L<<size));    /* using signed operand as unsigned */
4444
        else
4445
          cpu_error(25,val,-(1L<<(size-1)),
4446
                    (1L<<(size-1))-1);  /* operand value out of range */
4447
      }
4448
    }
4449
    else {
4450
      if ((utaddr)val > (1L << size) - 1)
4451
        cpu_error(25,val,0,(1L<<size)-1);  /* operand value out of range */
4452
    }
4453
  }
4454
 
4455
  d += pos>>3;
4456
  pos &= 7;
4457
 
4458
  while (size > 0) {
4459
    int shift = 8-pos-size;
4460
    unsigned char v;
4461
 
4462
    if (shift > 0)
4463
      v = (val << shift) & 0xff;
4464
    else if (shift < 0)
4465
      v = (val >> -shift) & 0xff;
4466
    else
4467
      v = val & 0xff;
4468
    *d++ |= v;
4469
    size -= 8-pos;
4470
    pos = 0;
4471
  }
4472
}
4473
 
4474
 
4475
static unsigned char *write_branch(dblock *db,unsigned char *d,operand *op,
4476
                                   char ext,section *sec,taddr pc,
4477
                                   mnemonic *mnemo,int bcc)
4478
/* calculate and write branch displacement of desired size, handle relocs */
4479
{
4480
  int lbra = (mnemo->ext.size & SIZE_LONG) != 0;
4481
 
4482
  if (!bcc && ext!='w' && ext!='l')
4483
    ierror(0);
4484
 
4485
  if (op->base[0] && is_pc_reloc(op->base[0],sec)) {
4486
    /* external branch label, or label from different section */
4487
    taddr addend = op->extval[0];
4488
    int size,offset;
4489
 
4490
    switch (ext) {
4491
      case 'b':
4492
      case 's':
4493
        addend--;   /* reloc-offset is stored 1 byte before PC-location */
4494
        *(d-1) = addend & 0xff;
4495
        size = 8;
4496
        offset = 1;
4497
        break;
4498
      case 'l':
4499
        if (lbra) {
4500
          if (mnemo->ext.place[1] != DBR) {
4501
            if (bcc)
4502
              *(d-1) = 0xff;
4503
            offset = d - (unsigned char *)db->data;
4504
            d = rf68k_setval(1,d,4,addend);
4505
            size = 32;
4506
            break;
4507
          }
4508
          else
4509
            addend |= 1;  /* DBcc.L - drop into 'w'-case */
4510
        }
4511
        else {
4512
          cpu_error(0);  /* instruction not supported */
4513
          break;
4514
        }
4515
      case 'w':
4516
        if (bcc)
4517
          *(d-1) = 0;
4518
        offset = d - (unsigned char *)db->data;
4519
        d = rf68k_setval(1,d,2,addend);
4520
        size = 16;
4521
        break;
4522
      default:
4523
        cpu_error(34);  /* illegal opcode extension */
4524
        break;
4525
    }
4526
    add_extnreloc(&db->relocs,op->base[0],addend,REL_PC,0,size,offset);
4527
  }
4528
  else {
4529
    /* known label from the same section - can be resolved immediately */
4530
    taddr diff = op->extval[0] - pc;
4531
 
4532
    switch (ext) {
4533
      case 'b':
4534
      case 's':
4535
        if (diff>=-0x80 && diff<=0x7f && diff!=0 && (diff!=-1 || !lbra))
4536
          *(d-1) = diff & 0xff;
4537
        else
4538
          cpu_error(28);  /* branch destination out of range */
4539
        break;
4540
      case 'l':
4541
        if (lbra) {
4542
          if (mnemo->ext.place[1] != DBR) {
4543
            if (bcc)
4544
              *(d-1) = 0xff;
4545
            d = rf68k_setval(1,d,4,diff);
4546
            break;
4547
          }
4548
          else
4549
            diff |= 1;  /* DBcc.L - drop into 'w'-case */
4550
        }
4551
        else {
4552
          cpu_error(0);  /* instruction not supported */
4553
          break;
4554
        }
4555
      case 'w':
4556
        if (diff>=-0x8000 && diff<=0x7fff) {
4557
          if (bcc)
4558
            *(d-1) = 0;
4559
          d = rf68k_setval(1,d,2,diff);
4560
        }
4561
        else
4562
          cpu_error(28);  /* branch destination out of range */
4563
        break;
4564
      default:
4565
        cpu_error(34);  /* illegal opcode extension */
4566
        break;
4567
    }
4568
  }
4569
 
4570
  return d;
4571
}
4572
 
4573
 
4574
static unsigned char *write_extval(int num,size_t size,dblock *db,
4575
                                   unsigned char *d,operand *op,int rtype)
4576
{
4577
  if (rtype==REL_ABS && op->basetype[num]==BASE_PCREL)
4578
    op->extval[num] += d - db->data;  /* fix addend for label differences */
4579
 
4580
  return rf68k_setval(1,d,size,op->extval[num]);
4581
}
4582
 
4583
 
4584
static unsigned char *write_ea_ext(dblock *db,unsigned char *d,operand *op,
4585
                                   char ext,section *sec,taddr pc)
4586
/* write effective address extension words, handle relocs */
4587
{
4588
  if (op->mode>MODE_Extended ||
4589
      (op->mode==MODE_Extended && op->reg>REG_Immediate)) {
4590
    ierror(0);
4591
  }
4592
  else if (op->mode >= MODE_An16Disp) {
4593
    int rtype = REL_NONE;
4594
    int roffs = d - (unsigned char *)db->data;
4595
    int rsize = 0;
4596
    int ortype = REL_NONE;
4597
    int orsize = 0;
4598
 
4599
    if (op->flags & FL_020up) {
4600
      if (!(cpu_type & (m68020up|cpu32))) {
4601
        cpu_error(0);  /* instruction not supported */
4602
      }
4603
      else if (op->flags & FL_noCPU32) {
4604
        if (cpu_type & cpu32)
4605
          cpu_error(0);  /* instruction not supported */
4606
      }
4607
    }
4608
 
4609
    if (op->mode == MODE_An16Disp) {
4610
      /* d16(An) needs one extension word */
4611
      if (op->base[0]) {
4612
        rsize = 16;
4613
        if ((EXTREF(op->base[0]) && op->reg!=sdreg) ||
4614
            op->basetype[0]==BASE_PCREL)
4615
          rtype = REL_ABS;
4616
        else if (op->basetype[0]==BASE_OK)
4617
          rtype = REL_SD;
4618
        else
4619
          general_error(38);  /* illegal relocation */
4620
      }
4621
      if (rtype==REL_SD && LOCREF(op->base[0])) {
4622
        if (typechk && (op->extval[0]<0 || op->extval[0]>0xffff))
4623
          cpu_error(29);  /* displacement out of range */
4624
      }
4625
      else {
4626
        if (typechk && (op->extval[0]<-0x8000 || op->extval[0]>0x7fff))
4627
          cpu_error(29);  /* displacement out of range */
4628
      }
4629
      d = write_extval(0,2,db,d,op,rtype);
4630
    }
4631
 
4632
    else if (op->mode == MODE_An8Format) {
4633
      if (!(op->flags & FL_UsesFormat))
4634
        ierror(0);
4635
      if (op->format & FW_FullFormat) {
4636
        /* ([bd,An,Rn.x*s],od): format word + base- and outer-displacement */
4637
        d = rf68k_setval(1,d,2,op->format);
4638
        roffs += 2;
4639
        if (FW_getBDSize(op->format) == FW_Word) {
4640
          if (op->base[0]) {
4641
            rsize = 16;
4642
            if ((EXTREF(op->base[0]) && (!extsd || op->reg!=sdreg)) ||
4643
                op->basetype[0]==BASE_PCREL)
4644
              rtype = REL_ABS;
4645
            else if (extsd && op->reg==sdreg && op->basetype[0]==BASE_OK)
4646
              rtype = REL_SD;
4647
            else
4648
              general_error(38);  /* illegal relocation */
4649
          }
4650
          if (rtype==REL_SD && LOCREF(op->base[0])) {
4651
            if (typechk && (op->extval[0]<0 || op->extval[0]>0xffff))
4652
              cpu_error(29);  /* displacement out of range */
4653
          }
4654
          else {
4655
            if (typechk && (op->extval[0]<-0x8000 || op->extval[0]>0x7fff))
4656
              cpu_error(29);  /* displacement out of range */
4657
          }
4658
          d = write_extval(0,2,db,d,op,rtype);
4659
        }
4660
        else if (FW_getBDSize(op->format) == FW_Long) {
4661
          if (op->base[0]) {
4662
            rtype = REL_ABS;
4663
            rsize = 32;
4664
          }
4665
          d = write_extval(0,4,db,d,op,rtype);
4666
        }
4667
        if (FW_getIndSize(op->format) == FW_Word) {
4668
          if (typechk && (op->extval[1]<-0x8000 || op->extval[1]>0x7fff))
4669
            cpu_error(29);  /* displacement out of range */
4670
          if (op->base[1]) {
4671
            orsize = 16;
4672
            if (EXTREF(op->base[1]) ||
4673
                (LOCREF(op->base[1]) && op->basetype[1]==BASE_PCREL))
4674
              ortype = REL_ABS;
4675
            else
4676
              cpu_error(30);  /* absolute displacement expected */
4677
          }
4678
          d = write_extval(1,2,db,d,op,ortype);
4679
        }
4680
        else if (FW_getIndSize(op->format) == FW_Long) {
4681
          if (op->base[1]) {
4682
            ortype = REL_ABS;
4683
            orsize = 32;
4684
          }
4685
          d = write_extval(1,4,db,d,op,ortype);
4686
        }
4687
      }
4688
      else {
4689
        /* (d8,An,Rn.x*s) needs one format word as extension */
4690
        if (typechk && (op->extval[0]<-0x80 || op->extval[0]>0x7f))
4691
          cpu_error(29);  /* displacement out of range */
4692
        if (op->base[0]) {
4693
          rsize = 8;
4694
          if (EXTREF(op->base[0]) ||
4695
              (LOCREF(op->base[0]) && op->basetype[0]==BASE_PCREL))
4696
            rtype = REL_ABS;
4697
          else
4698
            cpu_error(30);  /* absolute displacement expected */
4699
        }
4700
        *d++ = (op->format>>8) & 0xff;
4701
        *d++ = op->extval[0] & 0xff;
4702
      }
4703
    }
4704
 
4705
    else if (op->mode == MODE_Extended) {
4706
 
4707
      if (op->reg == REG_PC16Disp) {
4708
        /* d16(PC) needs one extension word */
4709
        taddr disp = op->extval[0];
4710
 
4711
        if (op->base[0]!=NULL && is_pc_reloc(op->base[0],sec)) {
4712
          rtype = REL_PC;
4713
          rsize = 16;
4714
        }
4715
        else if (op->base[0]!=NULL || (sec->flags&ABSOLUTE))
4716
          disp = op->extval[0] - pc;
4717
        else
4718
          cpu_error(no_dpc ? 26 : 68);  /* absolute PC-displacement */
4719
        if (typechk && (disp<-0x8000 || disp>0x7fff))
4720
          cpu_error(29);  /* displacement out of range */
4721
        d = rf68k_setval(1,d,2,disp);
4722
      }
4723
 
4724
      else if (op->reg == REG_PC8Format) {
4725
        taddr disp = op->extval[0];
4726
 
4727
        if (!(op->flags & FL_UsesFormat))
4728
          ierror(0);
4729
        if (op->format & FW_FullFormat) {
4730
          /* ([bd,PC,Rn.x*s],od): format word + base- and outer-displacement */
4731
          d = rf68k_setval(1,d,2,op->format);
4732
          roffs += 2;
4733
          if (FW_getBDSize(op->format) == FW_Word) {
4734
            if (op->base[0]!=NULL && is_pc_reloc(op->base[0],sec)) {
4735
              rtype = REL_PC;
4736
              rsize = 16;
4737
              op->extval[0] += 2;  /* pc-relative xref fix */
4738
              disp += 2;
4739
            }
4740
            else if (op->base[0]!=NULL || (sec->flags&ABSOLUTE))
4741
              disp = op->extval[0] - pc;
4742
            else
4743
              cpu_error(no_dpc ? 26 : 68);  /* absolute PC-displacement */
4744
            if (typechk && (disp<-0x8000 || disp>0x7fff))
4745
              cpu_error(29);  /* displacement out of range */
4746
            d = rf68k_setval(1,d,2,disp);
4747
          }
4748
          else if (FW_getBDSize(op->format) == FW_Long) {
4749
            if (op->base[0]!=NULL && is_pc_reloc(op->base[0],sec)) {
4750
              rtype = REL_PC;
4751
              rsize = 32;
4752
              op->extval[0] += 2;  /* pc-relative xref fix */
4753
              disp += 2;
4754
            }
4755
            else if (op->base[0]!=NULL || (sec->flags&ABSOLUTE))
4756
              disp = op->extval[0] - pc;
4757
            else
4758
              cpu_error(no_dpc ? 26 : 68);  /* absolute PC-displacement */
4759
            d = rf68k_setval(1,d,4,disp);
4760
          }
4761
          if (FW_getIndSize(op->format) == FW_Word) {
4762
            if (typechk && (op->extval[1]<-0x8000 || op->extval[1]>0x7fff))
4763
              cpu_error(29);  /* displacement out of range */
4764
            if (op->base[1]) {
4765
              if (EXTREF(op->base[1])) {
4766
                ortype = REL_ABS;
4767
                orsize = 16;
4768
              }
4769
              else
4770
                cpu_error(30);  /* absolute displacement expected */
4771
            }
4772
            d = write_extval(1,2,db,d,op,ortype);
4773
          }
4774
          else if (FW_getIndSize(op->format) == FW_Long) {
4775
            if (op->base[1]) {
4776
              ortype = REL_ABS;
4777
              orsize = 32;
4778
            }
4779
            d = write_extval(1,4,db,d,op,ortype);
4780
          }
4781
        }
4782
        else {
4783
          /* (d8,PC,Rn.x*s) needs one format word as extension */
4784
          if (op->base[0]!=NULL && is_pc_reloc(op->base[0],sec)) {
4785
            rtype = REL_PC;
4786
            rsize = 8;
4787
            roffs++;
4788
            op->extval[0] += 1;  /* pc-relative xref fix */
4789
            disp += 1;
4790
          }
4791
          else if (op->base[0]!=NULL || (sec->flags&ABSOLUTE))
4792
            disp = op->extval[0] - pc;
4793
          else
4794
            cpu_error(no_dpc ? 26 : 68);  /* absolute PC-displacement */
4795
          if (typechk && (disp<-0x80 || disp>0x7f))
4796
            cpu_error(29);  /* displacement out of range */
4797
          *d++ = (op->format>>8) & 0xff;
4798
          *d++ = disp & 0xff;
4799
        }
4800
      }
4801
 
4802
      else if (op->reg == REG_AbsShort) {
4803
        /* label.w */
4804
        if (typechk && (op->extval[0]<-0x8000 || op->extval[0]>0x7fff))
4805
          cpu_error(32);  /* absolute short address out of range */
4806
        if (op->base[0]) {
4807
          rtype = REL_ABS;
4808
          rsize = 16;
4809
        }
4810
        d = write_extval(0,2,db,d,op,rtype);
4811
      }
4812
 
4813
      else if (op->reg == REG_AbsLong) {
4814
        /* label.l */
4815
        if (op->base[0]) {
4816
          rtype = REL_ABS;
4817
          rsize = 32;
4818
        }
4819
        d = write_extval(0,4,db,d,op,rtype);
4820
      }
4821
 
4822
      else if (op->reg == REG_Immediate) {
4823
        /* #immediate */
4824
        int err;
4825
 
4826
        if (op->base[0] != NULL)
4827
          rtype = REL_ABS;
4828
 
4829
        switch (ext) {
4830
          case 'b':
4831
            if (op->flags & FL_ExtVal0) {
4832
              roffs++;
4833
              rsize = 8;
4834
              *d++ = 0;
4835
              d = write_extval(0,1,db,d,op,rtype);
4836
              if (typechk && (op->extval[0]<-0x80 || op->extval[0]>0xff))
4837
                cpu_error(36);  /* immediate operand out of range */
4838
            }
4839
            else
4840
              cpu_error(37);  /* immediate operand has illegal type */
4841
            break;
4842
          case 'w':
4843
            if (op->flags & FL_ExtVal0) {
4844
              rsize = 16;
4845
              d = write_extval(0,2,db,d,op,rtype);
4846
              if (typechk && (op->extval[0]<-0x8000 || op->extval[0]>0xffff))
4847
                cpu_error(36);  /* immediate operand out of range */
4848
            }
4849
            else if (type_of_expr(op->value[0])==HUG && (cpu_type&apollo)) {
4850
              /* Apollo AMMX 64-bit as WORD */
4851
              thuge hval;
4852
 
4853
              if (!eval_expr_huge(op->value[0],&hval))
4854
                general_error(59);  /* cannot evaluate huge integer */
4855
              d = huge_to_mem(1,d,2,hval);
4856
              if (typechk && !huge_chkrange(hval,16))
4857
                cpu_error(36);  /* immediate operand out of range */
4858
            }
4859
            else
4860
              cpu_error(37);  /* immediate operand has illegal type */
4861
            break;
4862
          case 'l':
4863
            if (op->flags & FL_ExtVal0) {
4864
              rsize = 32;
4865
              d = write_extval(0,4,db,d,op,rtype);
4866
            }
4867
            else if (type_of_expr(op->value[0]) == FLT) {
4868
              if ((err = copy_float_exp(d,op,EXT_SINGLE)) != 0)
4869
                cpu_error(err);
4870
              d += 4;
4871
            }
4872
            else
4873
              cpu_error(37);  /* immediate operand has illegal type */
4874
            break;
4875
          case 's':
4876
            if ((err = copy_float_exp(d,op,EXT_SINGLE)) != 0)
4877
              cpu_error(err);
4878
            d += 4;
4879
            break;
4880
          case 'd':
4881
          case 'q':
4882
            if ((err = copy_float_exp(d,op,EXT_DOUBLE)) != 0)
4883
              cpu_error(err);
4884
            d += 8;
4885
            break;
4886
          case 'x':
4887
            if ((err = copy_float_exp(d,op,EXT_EXTENDED)) != 0)
4888
              cpu_error(err);
4889
            d += 12;
4890
            break;
4891
          case 'p':
4892
            if ((err = copy_float_exp(d,op,EXT_PACKED)) != 0)
4893
              cpu_error(err);
4894
            d += 12;
4895
            break;
4896
        }
4897
      }
4898
    }
4899
 
4900
    /* append relocations */
4901
    if (rtype != REL_NONE) {
4902
      if (rtype==REL_ABS && op->basetype[0]==BASE_PCREL)
4903
        rtype = REL_PC;
4904
      add_extnreloc(&db->relocs,op->base[0],op->extval[0],rtype,0,rsize,roffs);
4905
    }
4906
    if (ortype != REL_NONE) {
4907
      if (ortype==REL_ABS && op->basetype[1]==BASE_PCREL)
4908
        ortype = REL_PC;
4909
      add_extnreloc(&db->relocs,op->base[1],op->extval[1],ortype,0,orsize,
4910
                    (rtype==REL_NONE) ? roffs : roffs+rsize/8);
4911
    }
4912
  }
4913
  return d;
4914
}
4915
 
4916
 
4917
static uint16_t apollo_bank_prefix(instruction *ip)
4918
/* generate Apollo bank prefix */
4919
{
4920
  uint16_t bank = 0x7100;
4921
  uint16_t ddddd = 0;
4922
 
4923
  /* calculate bank prefix */
4924
  if (ip->op[0]->mode == MODE_SpecReg) {
4925
    uint16_t aaReg = ip->op[0]->reg - REG_VX00;  /* e0 - e23 */
4926
    bank |= (1 + (aaReg >> 3)) << 2;
4927
  }
4928
 
4929
  if (ip->op[1] != NULL) {
4930
    if (ip->op[1]->mode == MODE_SpecReg) {
4931
      uint16_t bbReg = ip->op[1]->reg - REG_VX00;  /* e0 - e23 */
4932
      ddddd |= ((bbReg % 8) << 2) | (1 + (bbReg >> 3));  /* ddd-dd==reg-bank */
4933
      bank |= (1 + (bbReg >> 3));
4934
    }
4935
    else
4936
      ddddd = ip->op[1]->reg << 2;
4937
  }
4938
  else {
4939
    /* For a single operand instr, both AA and BB should be the same */
4940
    uint16_t bbReg = ip->op[0]->reg - REG_VX00;  /* e0 - e23 */
4941
    bank |= (1 + (bbReg >> 3));
4942
  }
4943
 
4944
  switch (ip_size(ip)) {
4945
    case 4:
4946
      /* SS = 00 */
4947
      break;
4948
    case 6:
4949
      /* SS = 01 */
4950
      bank |= 0x40;
4951
      break;
4952
    case 8:
4953
      /* SS = 10 */
4954
      bank |= 0x80;
4955
      break;
4956
    case 10:
4957
      /* SS = 11 */
4958
      bank |= 0xc0;
4959
      break;
4960
    default:
4961
      cpu_error(70); /* bank prefix not encodable due to size limit */
4962
      break;
4963
  }
4964
 
4965
  /* handle 3rd operand */
4966
  if (ip->op[2] != NULL) {
4967
    if (ip->op[2]->mode != -1) {
4968
      /* optional operand was not omitted - refer to m68k_operand_optional() */
4969
      uint16_t dbank;
4970
 
4971
      if (ip->op[2]->mode == MODE_FPn)
4972
        dbank = ip->op[2]->reg << 2;
4973
      else if (ip->op[2]->mode == MODE_SpecReg)
4974
        dbank = (1 + ((ip->op[2]->reg - REG_VX00) >> 3)) |
4975
                (((ip->op[2]->reg - REG_VX00) % 8) << 2);
4976
      else
4977
        ierror(0);
4978
 
4979
      ddddd ^= dbank;
4980
      bank |= (((ddddd >> 2) & 7) << 9) | ((ddddd & 3) << 4);
4981
    }
4982
    free_operand(ip->op[2]);
4983
    ip->op[2] = NULL;
4984
  }
4985
 
4986
  return bank;
4987
}
4988
 
4989
 
4990
dblock *eval_instruction(instruction *ip,section *sec,taddr pc)
4991
/* Convert an instruction into a DATA atom, including relocations
4992
   if necessary. */
4993
{
4994
  dblock *db = new_dblock();
4995
  unsigned char ipflags = ip->ext.un.real.flags;
4996
  signed char lastsize = ip->ext.un.real.last_size;
4997
  instruction *realip = ip;
4998
  uint8_t *d;
4999
 
5000
  /* really execute optimizations now */
5001
  ipslot = 0;
5002
  optimize_instruction(ip,sec,pc,1);
5003
 
5004
  /* determine instruction size and allocate data atom */
5005
  if ((db->size = iplist_size(ip)) != 0) {
5006
    d = db->data = mymalloc(db->size);
5007
  }
5008
  else {
5009
    db->data = NULL;
5010
    goto eval_done;
5011
  }
5012
 
5013
  /* encode instructions */
5014
  do {
5015
    if (ip->code >= 0) {
5016
      mnemonic *mnemo = &mnemonics[ip->code];
5017
      char ext = ip->qualifiers[0] ?
5018
                 tolower((unsigned char)ip->qualifiers[0][0]) : '\0';
5019
      uint16_t sz = ((mnemo->ext.size & SIZE_MASK) == SIZE_UNSIZED) ?
5020
                    SIZE_UNSIZED : lc_ext_to_size(ext);
5021
      unsigned opclen = S_OPCODE_SIZE(mnemo->ext.size);
5022
      unsigned char *dbstart = d;
5023
      int i;
5024
 
5025
      /* warn about a bad alias instruction mnemonic */
5026
      if (mnemo->ext.available & malias)
5027
        cpu_error(33);  /* deprecated instruction alias */
5028
 
5029
      if (mnemo->ext.available & mbanked) {
5030
        /* write Apollo bank prefix */
5031
        uint16_t bank = apollo_bank_prefix(ip);
5032
 
5033
        *d++ = bank >> 8;
5034
        *d++ = bank & 0xff;
5035
        pc += 2;
5036
        dbstart += 2;
5037
        opclen--;
5038
 
5039
        /* reduce operands back to base types */
5040
        for (i=0; i<MAX_OPERANDS && ip->op[i]!=NULL; i++) {
5041
          operand *op = ip->op[i];
5042
 
5043
          if (op->mode == MODE_SpecReg) {
5044
            op->mode = (mnemo->ext.place[i] == SEA || mnemo->ext.place[i] == MEA) ? MODE_Dn : MODE_FPn;
5045
            op->reg = (op->reg - REG_VX00) % 8;
5046
            op->flags = 0;
5047
          }
5048
        }
5049
      }
5050
 
5051
      /* copy opcode */
5052
      if (mnemo->ext.available & mfpu)
5053
        *d++ = (mnemo->ext.opcode[0] >> 8) | (fpu_id << 1);
5054
      else
5055
        *d++ = mnemo->ext.opcode[0] >> 8;
5056
 
5057
      *d++ = mnemo->ext.opcode[0] & 0xff;
5058
      pc += 2;
5059
 
5060
      if (opclen > 1) {
5061
        *d++ = mnemo->ext.opcode[1] >> 8;
5062
        *d++ = mnemo->ext.opcode[1] & 0xff;
5063
        pc += 2;
5064
 
5065
        if (opclen > 2) {
5066
          *d++ = 0;
5067
          *d++ = 0;
5068
          pc += 2;
5069
        }
5070
      }
5071
 
5072
      /* insert size-extension into opcode, when required */
5073
      switch (S_SIZEMODE(mnemo->ext.size)) {
5074
        case S_NONE:
5075
          break;
5076
        case S_STD:
5077
          switch (sz) {
5078
            case SIZE_WORD: *(dbstart+1) |= 0x40; break;
5079
            case SIZE_LONG: *(dbstart+1) |= 0x80; break;
5080
          }
5081
          break;
5082
        case S_STD1:
5083
          switch (sz) {
5084
            case SIZE_BYTE: *(dbstart+1) |= 0x40; break;
5085
            case SIZE_WORD: *(dbstart+1) |= 0x80; break;
5086
            case SIZE_LONG: *(dbstart+1) |= 0xc0; break;
5087
          }
5088
          break;
5089
        case S_HI:
5090
          switch (sz) {
5091
            case SIZE_WORD: *dbstart |= 0x02; break;
5092
            case SIZE_LONG: *dbstart |= 0x04; break;
5093
          }
5094
          break;
5095
        case S_CAS:
5096
          switch (sz) {
5097
            case SIZE_BYTE: *dbstart |= 0x02; break;
5098
            case SIZE_WORD: *dbstart |= 0x04; break;
5099
            case SIZE_LONG: *dbstart |= 0x06; break;
5100
          }
5101
          break;
5102
        case S_MOVE:
5103
          switch (sz) {
5104
            case SIZE_BYTE: *dbstart |= 0x10; break;
5105
            case SIZE_WORD: *dbstart |= 0x30; break;
5106
            case SIZE_LONG: *dbstart |= 0x20; break;
5107
          }
5108
          break;
5109
        case S_WL8:
5110
          if (sz == SIZE_LONG)
5111
            *dbstart |= 1;
5112
          break;
5113
        case S_LW7:
5114
          if (sz == SIZE_WORD)
5115
            *(dbstart+1) |= 0x80;
5116
          break;
5117
        case S_WL6:
5118
          if (sz == SIZE_LONG)
5119
            *(dbstart+1) |= 0x40;
5120
          break;
5121
        case S_MAC:
5122
          if (sz == SIZE_LONG)
5123
            *(dbstart+2) |= 8;
5124
          break;
5125
        case S_AMMX:
5126
          if (sz == SIZE_WORD)
5127
            *dbstart |= 1;
5128
          break;
5129
        case S_TRAP:
5130
          switch (sz) {
5131
            case SIZE_WORD: *(dbstart+1) |= 0x02; break;
5132
            case SIZE_LONG: *(dbstart+1) |= 0x03; break;
5133
          }
5134
          break;
5135
        case S_EXT:
5136
          switch (sz) {
5137
            case SIZE_WORD: *(dbstart+3) |= 0x40; break;
5138
            case SIZE_LONG: *(dbstart+3) |= 0x80; break;
5139
          }
5140
          break;
5141
        case S_FP:
5142
          switch (sz) {
5143
            case SIZE_SINGLE:   *(dbstart+2) |= 0x04; break;
5144
            case SIZE_EXTENDED: *(dbstart+2) |= 0x08; break;
5145
            case SIZE_PACKED:   *(dbstart+2) |= 0x0c; break;
5146
            case SIZE_WORD:     *(dbstart+2) |= 0x10; break;
5147
            case SIZE_DOUBLE:   *(dbstart+2) |= 0x14; break;
5148
            case SIZE_BYTE:     *(dbstart+2) |= 0x18; break;
5149
          }
5150
          break;
5151
        default:
5152
          ierror(0);
5153
          break;
5154
      }
5155
 
5156
      /* check illegal addressing mode combinations for ColdFire MOVE */
5157
      if ((cpu_type & mcf) && ip->code==OC_MOVE) {
5158
        operand *src = ip->op[0];
5159
        operand *dst = ip->op[1];
5160
 
5161
        if (src->mode >= MODE_An16Disp) {
5162
          if ((src->mode==MODE_An16Disp ||
5163
               (src->mode==MODE_Extended && src->reg==REG_PC16Disp))) {
5164
            if (dst->mode==MODE_An8Format ||
5165
                (dst->mode==MODE_Extended && dst->reg<=REG_AbsLong))
5166
              cpu_error(41);  /* illegal combination of CF addressing modes */
5167
          }
5168
          else {
5169
            if (dst->mode==MODE_An16Disp) {
5170
              if (!(cpu_type & (mcfb|mcfc)) ||
5171
                  (src->mode!=MODE_Extended || src->reg!=REG_Immediate) ||
5172
                  (sz!=SIZE_BYTE && sz!=SIZE_WORD))
5173
                /* ISA_B also allows "#x,d(An)" for byte and word size */
5174
                cpu_error(41);  /* illegal combination of CF addr. modes */
5175
            }
5176
            else if (dst->mode==MODE_An8Format ||
5177
                     (dst->mode==MODE_Extended && dst->reg<=REG_AbsLong))
5178
              cpu_error(41);  /* illegal combination of CF addressing modes */
5179
          }
5180
        }
5181
      }
5182
 
5183
      /* write operands / insert addressing mode into opcode */
5184
      for (i=0; i<MAX_OPERANDS && ip->op[i]!=NULL; i++) {
5185
        operand *op = ip->op[i];
5186
        struct oper_insert *oii = &insert_info[mnemo->ext.place[i]];
5187
        unsigned char *newd = d;
5188
 
5189
        switch (oii->mode) {
5190
          case M_bfea:
5191
            if (op->flags & FL_BFoffsetDyn) {
5192
              op->bf_offset |= 32;
5193
            }
5194
            else if (op->bf_offset>31) {
5195
              cpu_error(19);  /* illegal bitfield width/offset */
5196
            }
5197
            if (op->flags & FL_BFwidthDyn) {
5198
              op->bf_width |= 32;
5199
            }
5200
            else {
5201
              if (op->bf_width > 32)
5202
                cpu_error(19);  /* illegal bitfield width/offset */
5203
              op->bf_width &= 31;
5204
            }
5205
            *(dbstart+2) |= (op->bf_offset>>2) & 15;
5206
            *(dbstart+3) |= ((op->bf_offset&3)<<6) | (op->bf_width&63);
5207
            /* fall through */
5208
 
5209
          case M_ea:
5210
            if (oii->flags & IIF_MASK)
5211
              *(dbstart+3) |= op->bf_width ? (1<<oii->pos) : 0;
5212
            if (oii->flags & IIF_NOMODE)
5213
              *(dbstart+1) |= REGget(op->reg);
5214
            else
5215
              *(dbstart+1) |= ((op->mode & 7) << 3) | REGget(op->reg);
5216
            /* fall through */
5217
 
5218
          case M_noea:
5219
            newd = write_ea_ext(db,d,op,ext,sec,pc);
5220
            /* fall through */
5221
 
5222
          case M_nop:
5223
            break;
5224
 
5225
          case M_kfea:
5226
            *(dbstart+1) |= ((op->mode & 7) << 3) | REGget(op->reg);
5227
            *(dbstart+2) |= (op->flags & FL_BFoffsetDyn) ? 0x10 : 0;
5228
            *(dbstart+3) |= op->bf_offset & 0x7f;
5229
            newd = write_ea_ext(db,d,op,ext,sec,pc);
5230
            break;
5231
 
5232
          case M_high_ea:
5233
            *(dbstart) |= (REGget(op->reg) << 1) | ((op->mode & 4) >> 2);
5234
            *(dbstart+1) |= (op->mode & 3) << 6;
5235
            newd = write_ea_ext(db,d,op,ext,sec,pc);
5236
            break;
5237
 
5238
          case M_func:
5239
            if (oii->flags & IIF_ABSVAL) {
5240
              if (op->base[0] != NULL) {
5241
                cpu_error(24);  /* absolute value expected */
5242
                break;
5243
              }
5244
            }
5245
            (oii->insert)(dbstart,oii,op);
5246
            break;
5247
 
5248
          case M_branch:
5249
            newd = write_branch(db,d,op,ext,sec,pc,mnemo,
5250
                                (oii->flags&IIF_BCC)?1:0);
5251
            break;
5252
 
5253
          case M_val0:
5254
            if (op->base[0] == NULL) {
5255
              taddr v = op->extval[0];
5256
 
5257
              if (oii->flags & IIF_MASK) {
5258
                if (v == 0)
5259
                  v = 1 << oii->size;
5260
                else if (v == (1<<oii->size))
5261
                  v = 0;
5262
              }
5263
              else if (oii->flags & IIF_3Q) {
5264
                if (v == 0)
5265
                  v = -1;
5266
                else if (v == -1)
5267
                  v = 0;
5268
              }
5269
              if (oii->flags & IIF_REVERSE)
5270
                v = reverse(v,oii->size);
5271
              write_val(dbstart,oii->pos,oii->size,v,
5272
                        (oii->flags&IIF_SIGNED)!=0);
5273
            }
5274
            else
5275
              cpu_error(24);  /* absolute value expected */
5276
            break;
5277
 
5278
          case M_reg:
5279
            if (op->mode<MODE_Extended || op->mode==MODE_FPn) {
5280
              taddr r = (taddr)op->reg;
5281
 
5282
              if (oii->size>3 && op->mode==MODE_An)
5283
                r += REGAn;
5284
              write_val(dbstart,oii->pos,oii->size,r,0);
5285
            }
5286
            else
5287
              ierror(0);
5288
            break;
5289
 
5290
          default:
5291
            ierror(0);
5292
            break;
5293
        }
5294
        pc += newd - d;
5295
        d = newd;
5296
      }
5297
    }
5298
  }
5299
  while ((ip = ip->ext.un.copy.next) != NULL);
5300
 
5301
eval_done:
5302
  /* restore flags and last_size of real ip to allow instruction_size() */
5303
  realip->ext.un.real.flags = ipflags;
5304
  realip->ext.un.real.last_size = lastsize;
5305
 
5306
  return db;
5307
}
5308
 
5309
 
5310
dblock *eval_data(operand *op,size_t bitsize,section *sec,taddr pc)
5311
/* Create a dblock (with relocs, if necessary) for size bits of data. */
5312
{
5313
  dblock *db = new_dblock();
5314
  symbol *base = NULL;
5315
  int btype,etype;
5316
  taddr val = 0;
5317
  thuge hval;
5318
  tfloat fval;
5319
 
5320
  db->size = bitsize >> 3;
5321
  db->data = mymalloc(db->size);
5322
 
5323
  etype = type_of_expr(op->value[0]);
5324
  if (etype == FLT) {
5325
    if (!eval_expr_float(op->value[0],&fval))
5326
      general_error(60);  /* cannot evaluate floating point */
5327
  }
5328
  else if (bitsize > 32) {
5329
    if (!eval_expr_huge(op->value[0],&hval))
5330
      general_error(59);  /* cannot evaluate huge integer */
5331
    etype = HUG;
5332
  }
5333
  else {
5334
    if (!eval_expr(op->value[0],&val,sec,pc)) {
5335
      btype = find_base(op->value[0],&base,sec,pc);
5336
      if (btype == BASE_ILLEGAL)
5337
        general_error(38);  /* illegal relocation */
5338
    }
5339
    etype = NUM;
5340
  }
5341
 
5342
  switch (bitsize) {
5343
    case 8:
5344
      if (etype == NUM) {
5345
        if (typechk && (val<-0x80 || val>0xff))
5346
          cpu_error(39);  /* data out of range */
5347
        db->data[0] = val & 0xff;
5348
      }
5349
      else if (etype == FLT)
5350
        cpu_error(40);  /* data has illegal type */
5351
      else
5352
        ierror(0);
5353
      break;
5354
 
5355
    case 16:
5356
      if (etype == NUM) {
5357
        if (typechk && (val<-0x8000 || val>0xffff))
5358
          cpu_error(39);  /* data out of range */
5359
        rf68k_setval(1,db->data,2,val);
5360
      }
5361
      else if (etype == FLT)
5362
        cpu_error(40);  /* data has illegal type */
5363
      else
5364
        ierror(0);
5365
      break;
5366
 
5367
    case 32:
5368
      if (etype == NUM)
5369
        rf68k_setval(1,db->data,4,val);
5370
      else if (etype == FLT)
5371
        conv2ieee32(1,db->data,fval);
5372
      else
5373
        ierror(0);
5374
      break;
5375
 
5376
    case 64:
5377
      if (etype == HUG) {
5378
        if (typechk && !huge_chkrange(hval,64))
5379
          cpu_error(39);  /* data out of range */
5380
        huge_to_mem(1,db->data,8,hval);
5381
      }
5382
      else if (etype == FLT)
5383
        conv2ieee64(1,db->data,fval);
5384
      else
5385
        ierror(0);
5386
      break;
5387
 
5388
    case 96:
5389
      if (etype == HUG) {
5390
        if (typechk && !huge_chkrange(hval,96))
5391
          cpu_error(39);  /* data out of range */
5392
        huge_to_mem(1,db->data,12,hval);
5393
      }
5394
      else if (etype == FLT)
5395
        conv2ieee80(1,db->data,fval);
5396
      else
5397
        ierror(0);
5398
      break;
5399
 
5400
    case 97:
5401
      if (etype == FLT)
5402
        conv2packed(db->data,fval);
5403
      else
5404
        ierror(0);
5405
      break;
5406
 
5407
    default:
5408
      cpu_error(38,bitsize); /* data objects with x size are not supported */
5409
      break;
5410
  }
5411
 
5412
  if (base) {
5413
    /* relocation required */
5414
    add_extnreloc(&db->relocs,base,val,btype==BASE_PCREL?REL_PC:REL_ABS,
5415
                  0,bitsize,0);
5416
  }
5417
 
5418
  return db;
5419
}
5420
 
5421
 
5422
int init_cpu()
5423
{
5424
  int i,j,code_tab_cnt;
5425
  hashdata data;
5426
 
5427
  if (!gas) {
5428
    /* remove gas mnemonics from the hash table */
5429
    for (i=0; i<mnemonic_cnt; i++) {
5430
      if (mnemonics[i].ext.available & mgas) {
5431
        rem_hashentry(mnemohash,mnemonics[i].name,0);
5432
        while (i+1<mnemonic_cnt &&
5433
               !strcmp(mnemonics[i].name,mnemonics[i+1].name))
5434
          i++;
5435
      }
5436
    }
5437
  }
5438
 
5439
  /* remember all mnemonic locations which we need */
5440
  code_tab_cnt = sizeof(code_tab) / sizeof(code_tab[0]);
5441
  for (i=0,j=0; i<mnemonic_cnt && j<code_tab_cnt; i++)
5442
    if (!strcmp(mnemonics[i].name,code_tab[j].name))
5443
      if ((code_tab[j].optype[0] == 0 ||
5444
           mnemonics[i].operand_type[0] == (int)code_tab[j].optype[0]) &&
5445
          (code_tab[j].optype[1] == 0 ||
5446
           mnemonics[i].operand_type[1] == (int)code_tab[j].optype[1]))
5447
        *code_tab[j++].var = i;
5448
  if (j < code_tab_cnt)
5449
    ierror(0);
5450
 
5451
  /* flag all mnemonics with an unambiguous size extension */
5452
  for (i=0; i<mnemonic_cnt; i++) {
5453
    if (countbits((taddr)mnemonics[i].ext.size & SIZE_MASK) == 1)
5454
      mnemonics[i].ext.size |= SIZE_UNAMBIG;
5455
  }
5456
 
5457
  /* predefine some register symbols */
5458
  new_regsym(0,0,elfregs?"%sp":"sp",RSTYPE_An,0,7);
5459
  new_regsym(0,0,elfregs?"%fp":"fp",RSTYPE_An,0,6);
5460
 
5461
  /* build hash table for special register names */
5462
  spechash = new_hashtable(0x1000);
5463
  movchash = new_hashtable(0x800);
5464
  for (i=0; i<specreg_cnt; i++) {
5465
    data.idx = i;
5466
    add_hashentry(i<FIRST_CTRLREG?spechash:movchash,SpecRegs[i].name,data);
5467
  }
5468
  if (debug && spechash->collisions)
5469
    fprintf(stderr,"*** %d special register collisions!!\n",spechash->collisions);
5470
  if (debug && movchash->collisions)
5471
    fprintf(stderr,"*** %d control register collisions!!\n",movchash->collisions);
5472
 
5473
  /* reset baseregs */
5474
  for (i=0; i<7; i++)
5475
    baseexp[i] = NULL;  /* disable basereg for A0-A7 */
5476
 
5477
  /* predefine cpu symbols */
5478
  if (phxass_compat) {
5479
    set_optc_symbol();
5480
    set_internal_abs(cpu_name,phxass_cpu_num(cpu_type));
5481
    set_internal_abs(mmu_name,(cpu_type & mmmu)!=0);
5482
    set_internal_abs(fpu_name,(cpu_type & mfloat)?fpu_id:0);
5483
  }
5484
  if (devpac_compat) {
5485
    taddr f = 99;
5486
 
5487
    /* __G2 contains host, version and cpu information */
5488
    set_g2_symbol();
5489
 
5490
    /* __LK is 0 for TOS executables, 1 for GST-, 2 for DRI-linkable,
5491
       3 for Amiga-linkable, 4 for Amiga executable.
5492
       Set it to 99 when creating an object file of unknown format. */
5493
    if (!strcmp(output_format,"tos"))
5494
      f = 0;
5495
    else if (!strcmp(output_format,"hunkexe"))
5496
      f = 4;
5497
    else if (!strcmp(output_format,"hunk"))
5498
      f = 3;
5499
    set_internal_abs(lk_name,f);
5500
  }
5501
 
5502
  /* for BAsm compatibility */
5503
  movemregs = internal_abs(movemregs_name);
5504
  movemsize = internal_abs(movemsize_name);
5505
  movembytes = internal_abs(movembytes_name);
5506
  movembytes->expr = make_expr(MUL,new_sym_expr(movemsize),
5507
                       make_expr(CNTONES,new_sym_expr(movemregs),NULL));
5508
 
5509
  /* __VASM */
5510
  set_internal_abs(vasmsym_name,cpu_type&CPUMASK);
5511
 
5512
  return 1;
5513
}
5514
 
5515
 
5516
static void set_cpu_type(uint32_t type,int addatom)
5517
{
5518
  if (type & (m68k|cpu32|mcf_all|apollo)) {
5519
    cpu_type = (cpu_type & ~(m68k|cpu32|mcf_all|apollo)) | type;
5520
    if (gas) {
5521
      if (!(type & (m68020|m68030|cpu32)))
5522
        cpu_type &= ~(m68881|m68882);  /* no 88x FPU when not 020 or 030 */
5523
      if (!no_fpu && (type & (m68020|m68030|cpu32)))
5524
        cpu_type |= m68881|m68882;  /* gas compatibility: always have FPU */
5525
    }
5526
  }
5527
  else if (type & (m68881|m68882))
5528
    cpu_type = (cpu_type & ~(m68881|m68882)) | (no_fpu ? 0 : type);
5529
  else if (type == m68851)
5530
    cpu_type |= m68851;
5531
 
5532
  if (addatom)
5533
    add_cpu_opt(0,OCMD_CPU,cpu_type);
5534
 
5535
  if (cpu_type & (m68020up | mcf))
5536
    m68k_mid = 2;  /* need 68020+ */
5537
}
5538
 
5539
 
5540
static uint32_t get_cpu_type(char **str)
5541
{
5542
  char *s = *str;
5543
  uint32_t type = 0;
5544
  int len,i;
5545
 
5546
  while (ISIDCHAR(*s))
5547
    s++;
5548
  len = s - *str;
5549
 
5550
  for (i=0; i<model_cnt; i++) {
5551
    if (strlen(models[i].name)==len && !strnicmp(*str,models[i].name,len)) {
5552
      type = models[i].type;
5553
      break;
5554
    }
5555
  }
5556
 
5557
  *str = s;
5558
  return type;
5559
}
5560
 
5561
 
5562
static void clear_all_opts(void)
5563
{
5564
  opt_movem = opt_pea = opt_clr = opt_st = opt_lsl = opt_mul = opt_div = 0;
5565
  opt_fconst = opt_brajmp = opt_pc = opt_bra = opt_allbra = opt_jbra = 0;
5566
  opt_disp = opt_abs = opt_moveq = opt_nmovq = opt_quick = opt_branop = 0;
5567
  opt_bdisp = opt_odisp = opt_lea = opt_lquick = opt_immaddr = 0;
5568
  opt_gen = opt_speed = opt_size = 0;
5569
}
5570
 
5571
 
5572
int cpu_args(char *arg)
5573
{
5574
  char *p = arg;
5575
  int i;
5576
 
5577
  if (!strcmp(p,"-phxass")) {
5578
    phxass_compat = 1;
5579
    opt_allbra = opt_brajmp = opt_sd = 1;
5580
    opt_fconst = 0;
5581
    ign_unambig_ext = ign_unsized_ext = 1;
5582
    return 0;  /* leave option visible for syntax modules */
5583
  }
5584
 
5585
  if (!strcmp(p,"-devpac")) {
5586
    /* set all options to Devpac-compatible defaults */
5587
    devpac_compat = 1;
5588
#ifdef OUTTOS
5589
    tos_hisoft_dri = 0;  /* no extended symbol names unless OPT X+ is given */
5590
#endif
5591
    clear_all_opts();
5592
    no_symbols = 1;
5593
    warn_opts = 2;
5594
    ign_unsized_ext = 1;
5595
    unsigned_shift = 1;
5596
    no_dpc = 1;
5597
    return 0;  /* leave option visible for syntax modules */
5598
  }
5599
 
5600
  if (!strcmp(p,"-kick1hunks")) {
5601
    kick1hunks = 1;
5602
    return  0;  /* leave option visible for syntax modules */
5603
  }
5604
 
5605
  if (!strncmp(p,"-m",2)) {
5606
    uint32_t cpu;
5607
 
5608
    p += 2;
5609
    if (!strcmp(p,"no-68881"))
5610
      goto nofpu;
5611
    if (!strncmp(p,"cf",2))
5612
      p += 2;  /* allow -mcf for ColdFire models */
5613
    cpu = get_cpu_type(&p);
5614
    if (!cpu)
5615
      return 0;
5616
    set_cpu_type(cpu,0);
5617
  }
5618
  else if (!strncmp(p,"-sdreg=",7)) {
5619
    i = atoi(p+7);
5620
    if (i>=0 && i<=6)
5621
      sdreg = i;
5622
    else
5623
      cpu_error(58);  /* not a valid small data register */
5624
  }
5625
  else if (!strcmp(p,"-no-opt")) {
5626
    clear_all_opts();
5627
    no_opt = 1;
5628
    optmainswitch = 0;
5629
  }
5630
  else if (!strcmp(p,"-no-fpu")) {
5631
nofpu:
5632
    no_fpu = 1;
5633
    cpu_type &= ~(m68881|m68882);
5634
  }
5635
  else if (!strcmp(p,"-gas")) {
5636
    gas = 1;
5637
    commentchar = '|';
5638
    set_cpu_type(m68020,0);  /* gas compatibility defaults to 68020/68881 */
5639
    opt_jbra = !no_opt;
5640
  }
5641
  else if (!strcmp(p,"-sgs"))
5642
    sgs = 1;
5643
  else if (!strcmp(p,"-extsd"))
5644
    extsd = 1;
5645
  else if (!strcmp(p,"-rangewarnings"))
5646
    modify_cpu_err(WARNING,25,29,32,36,0);
5647
  else if (!strcmp(p,"-conv-brackets"))
5648
    convert_brackets = 1;
5649
  else if (!strcmp(p,"-regsymredef"))
5650
    regsymredef = 1;
5651
  else if (!strcmp(p,"-elfregs"))
5652
    elfregs = 1;
5653
  else if (!strcmp(p,"-guess-ext"))
5654
    ign_unambig_ext = ign_unsized_ext = 1;
5655
  else if (!strcmp(p,"-nodpc"))
5656
    no_dpc = 1;
5657
  else if (!strcmp(p,"-no-typechk"))
5658
    typechk = 0;
5659
  else if (!strcmp(p,"-showcrit"))
5660
    warn_opts = 1;
5661
  else if (!strcmp(p,"-showopt"))
5662
    warn_opts = 2;
5663
  else if (!strcmp(p,"-sc"))
5664
    opt_sc = !no_opt;
5665
  else if (!strcmp(p,"-sd"))
5666
    opt_sd = !no_opt;
5667
  else if (!strcmp(p,"-opt-movem"))
5668
    opt_movem = !no_opt;
5669
  else if (!strcmp(p,"-opt-pea"))
5670
    opt_pea = !no_opt;
5671
  else if (!strcmp(p,"-opt-clr"))
5672
    opt_clr = !no_opt;
5673
  else if (!strcmp(p,"-opt-st"))
5674
    opt_st = !no_opt;
5675
  else if (!strcmp(p,"-opt-lsl"))
5676
    opt_lsl = !no_opt;
5677
  else if (!strcmp(p,"-opt-mul"))
5678
    opt_mul = !no_opt;
5679
  else if (!strcmp(p,"-opt-div"))
5680
    opt_div = !no_opt;
5681
  else if (!strcmp(p,"-opt-fconst"))
5682
    opt_fconst = !no_opt;
5683
  else if (!strcmp(p,"-opt-nmoveq"))
5684
    opt_nmovq = !no_opt;
5685
  else if (!strcmp(p,"-opt-brajmp"))
5686
    opt_brajmp = !no_opt;
5687
  else if (!strcmp(p,"-opt-allbra"))
5688
    opt_bra = opt_allbra = !no_opt;
5689
  else if (!strcmp(p,"-opt-jbra"))
5690
    opt_jbra = !no_opt;
5691
  else if (!strcmp(p,"-opt-speed"))
5692
    opt_speed = !no_opt;
5693
  else if (!strcmp(p,"-opt-size"))
5694
    opt_size = !no_opt;
5695
  else
5696
    return 0;
5697
 
5698
  return 1;
5699
}
5700
 
5701
 
5702
char *parse_instruction(char *s,int *inst_len,char **ext,int *ext_len,
5703
                        int *ext_cnt)
5704
/* parse instruction and save extension locations */
5705
{
5706
  char *inst = s;
5707
  int cnt = *ext_cnt;
5708
 
5709
  if (*s == '.')  /* allow dot as first char */
5710
    s++;
5711
  while (*s && *s!='.' && !isspace((unsigned char)*s))
5712
    s++;
5713
  *inst_len = s - inst;
5714
 
5715
  while (*s=='.' && cnt<MAX_QUALIFIERS) {
5716
    s++;
5717
    ext[cnt] = s;
5718
    while (*s && *s!='.' && !isspace((unsigned char)*s))
5719
      s++;
5720
    ext_len[cnt] = s - ext[cnt];
5721
    if (ext_len[cnt] <= 0)
5722
      cpu_error(34);  /* illegal opcode extension */
5723
    else
5724
      cnt++;
5725
  }
5726
  *ext_cnt = cnt;
5727
 
5728
  if (cnt > 0)
5729
    current_ext = tolower((unsigned char)ext[0][0]);
5730
  else
5731
    current_ext = '\0';
5732
  return s;
5733
}
5734
 
5735
 
5736
int set_default_qualifiers(char **q,int *q_len)
5737
/* fill in pointers to default qualifiers, return number of qualifiers */
5738
{
5739
  q[0] = (cpu_type & mcf) ? l_str : w_str;
5740
  q_len[0] = 1;
5741
  return 1;
5742
}
5743
 
5744
 
5745
static char validchar(char *s)
5746
{
5747
  return ISEOL(s) ? 0 : *s;
5748
}
5749
 
5750
 
5751
static void phxass_optc(uint16_t optc)
5752
/* set optimizations according to PhxAss OPTC flags */
5753
{
5754
  if (!optmainswitch)
5755
    return;
5756
 
5757
  if (optc == 0) {
5758
    no_opt = 1;  /* no optimizations */
5759
    return;
5760
  }
5761
  if (optc & 0x001) { /* N */
5762
    opt_gen = opt_disp = opt_abs = opt_moveq = opt_bdisp = opt_odisp = 1;
5763
    opt_lea = opt_immaddr = 1;
5764
  }
5765
  if (optc & 0x002) /* R */
5766
    opt_pc = 1;
5767
  if (optc & 0x004) /* Q */
5768
    opt_quick = opt_lquick = 1;
5769
  if (optc & 0x008) /* B */
5770
    opt_bra = opt_brajmp = 1;
5771
  if (optc & 0x010) /* L */
5772
    opt_lsl = 1;
5773
  if (optc & 0x020) /* P */
5774
    opt_pea = 1;
5775
  if (optc & 0x040) /* S */
5776
    opt_clr = opt_st = opt_fconst = opt_disp = opt_bdisp = opt_odisp = 1;
5777
  if (optc & 0x080) /* M */
5778
    opt_gen = 1;
5779
  if (optc & 0x100) /* T */
5780
    ;  /* ignored */
5781
  if (optc & 0x200) /* D */
5782
    opt_movem = 1;
5783
}
5784
 
5785
 
5786
static void phxass_option(char opt)
5787
/* parse a phxass-style option */
5788
{
5789
  if (!optmainswitch)
5790
    return;
5791
 
5792
  switch (toupper((unsigned char)opt)) {
5793
    case '0':
5794
      no_opt = 1;  /* no optimizations */
5795
      break;
5796
    case '3':  /* enable all */
5797
    case '!':
5798
      opt_lsl = opt_pea = opt_clr = opt_st = opt_fconst = 1;
5799
      opt_disp = opt_bdisp = opt_odisp = opt_movem = 1;
5800
      /* fall through */
5801
    case '1':  /* enable standard */
5802
    case '2':
5803
    case '*':
5804
      opt_pc = opt_quick = opt_lquick = opt_bra = opt_brajmp = 1;
5805
      /* fall through */
5806
    case 'N':  /* normal */
5807
      opt_gen = opt_disp = opt_abs = opt_moveq = opt_bdisp = opt_odisp = 1;
5808
      opt_lea = opt_immaddr = 1;
5809
      break;
5810
    case 'R':  /* relative */
5811
      opt_pc = 1;
5812
      break;
5813
    case 'Q':  /* quick */
5814
      opt_quick = opt_lquick = 1;
5815
      break;
5816
    case 'B':  /* branches */
5817
      opt_bra = opt_brajmp = opt_allbra = 1;
5818
      break;
5819
    case 'L':  /* logical shifts */
5820
      opt_lsl = 1;
5821
      break;
5822
    case 'P':  /* pea */
5823
      opt_pea = 1;
5824
      break;
5825
    case 'S':  /* special */
5826
      opt_clr = opt_st = opt_fconst = opt_disp = opt_bdisp = opt_odisp = 1;
5827
      break;
5828
    case 'D':  /* movem single */
5829
      opt_movem = 1;
5830
      /* fall through */
5831
    case 'M':  /* delete movem */
5832
      opt_gen = 1;
5833
      break;
5834
  }
5835
}
5836
 
5837
 
5838
static char *devpac_option(char *s)
5839
/* parse a devpac-style option (default) */
5840
{
5841
  static const int opt_map[] = {  /* maps OPT O<n> to a vasm option */
5842
    OCMD_OPTBRA,OCMD_OPTDISP,OCMD_OPTABS,OCMD_OPTMOVEQ,OCMD_OPTQUICK,
5843
    OCMD_NOP,OCMD_OPTBRANOP,OCMD_OPTBDISP,OCMD_OPTODISP,OCMD_OPTLEA,
5844
    OCMD_OPTLQUICK,OCMD_OPTIMMADDR
5845
  };
5846
  char opt,ext,c;
5847
  int flag = 1;
5848
  int num;
5849
 
5850
  if (!strnicmp(s,"no",2)) {  /* no... prefix for option */
5851
    flag = 0;
5852
    s += 2;
5853
  }
5854
 
5855
  if (!strnicmp(s,"autopc",6)) {
5856
    add_cpu_opt(0,OCMD_OPTPC,flag);
5857
    return s+6;
5858
  }
5859
  else if (!strnicmp(s,"case",4)) {
5860
    nocase = !flag;
5861
    return s+4;
5862
  }
5863
  else if (!strnicmp(s,"chkpc",5)) {
5864
    add_cpu_opt(0,OCMD_CHKPIC,flag);
5865
    return s+5;
5866
  }
5867
  else if (!strnicmp(s,"debug",5)) {
5868
    no_symbols = !flag;
5869
    return s+5;
5870
  }
5871
  else if (!strnicmp(s,"symtab",6)) {
5872
    listnosyms = !flag;
5873
    return s+6;
5874
  }
5875
  else if (!strnicmp(s,"type",4)) {
5876
    add_cpu_opt(0,OCMD_CHKTYPE,flag);
5877
    return s+4;
5878
  }
5879
  else if (!strnicmp(s,"warn",4)) {
5880
    no_warn = !flag;  /* must also be recognized during parsing */
5881
    add_cpu_opt(0,OCMD_NOWARN,!flag);
5882
    return s+4;
5883
  }
5884
  else if (!strnicmp(s,"xdebug",6)) {
5885
    if (flag)
5886
      no_symbols = 0;
5887
#ifdef OUTTOS
5888
    tos_hisoft_dri = flag;  /* extended symbol names for Atari */
5889
#endif
5890
#ifdef OUTHUNK
5891
    hunk_onlyglobal = flag; /* only xdef-symbols in objects for Amiga */
5892
#endif
5893
    return s+6;
5894
  }
5895
  else if (!flag)
5896
    goto devpac_err;
5897
 
5898
  if (!strnicmp(s,"p=",2)) {
5899
    uint32_t cpu;
5900
 
5901
    s++;
5902
    do {
5903
      s++;
5904
      if ((cpu = get_cpu_type(&s)) != 0)
5905
        set_cpu_type(cpu,1);
5906
      else
5907
        cpu_error(43);  /* unknown cpu type */
5908
    }
5909
    while (*s == '/');  /* another CPU/FPU/MMU specification? */
5910
    return s;
5911
  }
5912
 
5913
  if ((opt = tolower((unsigned char)validchar(s))) != 0) {
5914
    ext = validchar(s+1);
5915
    if (isdigit((unsigned char)ext))
5916
      num = atoi(s+1);
5917
    else
5918
      num = -1;
5919
 
5920
    do
5921
      c = validchar(++s);
5922
    while (c!=0 && c!=',' && c!='+' && c!='-');
5923
 
5924
    if (c==0 || c==',') {
5925
      switch (opt) {
5926
        case 'l':  /* Ln : Atari only */
5927
          if (num >= 0)
5928
            exec_out = num == 0;
5929
          break;
5930
        default:
5931
          cpu_error(31,toupper((unsigned char)opt),c);  /* unkn. opt ignored */
5932
          break;
5933
      }
5934
      return s;
5935
    }
5936
 
5937
    else if (c != 0) {
5938
      flag = c=='+';
5939
      if (ext == c)
5940
        ext = 0;
5941
 
5942
      switch (opt) {
5943
        case 'a':
5944
          if (optmainswitch)
5945
            add_cpu_opt(0,OCMD_OPTPC,flag);
5946
          break;
5947
        case 'c':
5948
          nocase = !flag;
5949
          break;
5950
        case 'd':
5951
          no_symbols = !flag;
5952
          break;
5953
        case 'l':  /* L+/- : Amiga only */
5954
          exec_out = !flag;
5955
          break;
5956
        case 'm':
5957
          /* macro expansion in listing file */
5958
          break;
5959
        case 'o':
5960
          if (!optmainswitch)
5961
            break;
5962
          if (isdigit((unsigned char)ext) && num>=1 && num<=12) {
5963
            add_cpu_opt(0,opt_map[num-1],flag);
5964
          }
5965
          else {
5966
            switch (tolower((unsigned char)ext)) {
5967
              case '\0':
5968
                if (!flag) {
5969
                  /* clear all optimization flags, set no_opt */
5970
                  clear_all_opts();
5971
                  add_cpu_opt(0,OCMD_NOOPT,1);
5972
                }
5973
                else {
5974
                  /* enable all safe optimizations, as in vasm-default */
5975
                  add_cpu_opt(0,OCMD_OPTBRA,1);
5976
                  add_cpu_opt(0,OCMD_OPTDISP,1);
5977
                  add_cpu_opt(0,OCMD_OPTABS,1);
5978
                  add_cpu_opt(0,OCMD_OPTMOVEQ,1);
5979
                  add_cpu_opt(0,OCMD_OPTQUICK,1);
5980
                  add_cpu_opt(0,OCMD_OPTBRANOP,1);
5981
                  add_cpu_opt(0,OCMD_OPTBDISP,1);
5982
                  add_cpu_opt(0,OCMD_OPTODISP,1);
5983
                  add_cpu_opt(0,OCMD_OPTLEA,1);
5984
                  add_cpu_opt(0,OCMD_OPTLQUICK,1);
5985
                  add_cpu_opt(0,OCMD_OPTIMMADDR,1);
5986
                  if (!devpac_compat) {
5987
                    /* enable safe vasm-specific optimizations */
5988
                    add_cpu_opt(0,OCMD_OPTGEN,1);
5989
                    add_cpu_opt(0,OCMD_OPTPC,1);
5990
                    add_cpu_opt(0,OCMD_OPTFCONST,1);
5991
                  }
5992
                }
5993
                break;
5994
              case 'b': /* vasm-specific */
5995
                add_cpu_opt(0,OCMD_OPTJBRA,flag);
5996
                break;
5997
              case 'c': /* vasm-specific */
5998
                add_cpu_opt(0,OCMD_OPTCLR,flag);
5999
                break;
6000
              case 'd': /* vasm-specific */
6001
                add_cpu_opt(0,OCMD_OPTDIV,flag);
6002
                break;
6003
              case 'f': /* vasm-specific */
6004
                add_cpu_opt(0,OCMD_OPTFCONST,flag);
6005
                break;
6006
              case 'g': /* vasm-specific */
6007
                add_cpu_opt(0,OCMD_OPTGEN,flag);
6008
                break;
6009
              case 'j': /* vasm-specific */
6010
                add_cpu_opt(0,OCMD_OPTBRAJMP,flag);
6011
                break;
6012
              case 'l': /* vasm-specific */
6013
                add_cpu_opt(0,OCMD_OPTLSL,flag);
6014
                break;
6015
              case 'm': /* vasm-specific */
6016
                add_cpu_opt(0,OCMD_OPTMOVEM,flag);
6017
                break;
6018
              case 'n': /* vasm-specific */
6019
                add_cpu_opt(0,OCMD_SMALLDATA,flag);
6020
                break;
6021
              case 'p': /* vasm-specific */
6022
                add_cpu_opt(0,OCMD_OPTPEA,flag);
6023
                break;
6024
              case 'q': /* vasm-specific */
6025
                add_cpu_opt(0,OCMD_OPTNMOVQ,flag);
6026
                break;
6027
              case 's': /* vasm-specific */
6028
                add_cpu_opt(0,OCMD_OPTSPEED,flag);
6029
                break;
6030
              case 't': /* vasm-specific */
6031
                add_cpu_opt(0,OCMD_OPTST,flag);
6032
                break;
6033
              case 'w':
6034
                add_cpu_opt(0,OCMD_OPTWARN,flag?2:0);
6035
                break;
6036
              case 'x': /* vasm-specific */
6037
                add_cpu_opt(0,OCMD_OPTMUL,flag);
6038
                break;
6039
              case 'z': /* vasm-specific */
6040
                add_cpu_opt(0,OCMD_OPTSIZE,flag);
6041
                break;
6042
              default:
6043
                cpu_error(31,opt,ext);  /* unknown option ignored */
6044
                break;
6045
            }
6046
          }
6047
          break;
6048
        case 'p':
6049
          add_cpu_opt(0,OCMD_CHKPIC,flag);
6050
          break;
6051
        case 's':
6052
          listnosyms = !flag;
6053
          break;
6054
        case 't':
6055
          add_cpu_opt(0,OCMD_CHKTYPE,flag);
6056
          break;
6057
        case 'w':
6058
          no_warn = !flag;  /* must also be recognized during parsing */
6059
          add_cpu_opt(0,OCMD_NOWARN,!flag);
6060
          break;
6061
        case 'x':
6062
          if (flag)
6063
            no_symbols = 0;
6064
#ifdef OUTTOS
6065
          tos_hisoft_dri = flag;  /* extended symbol names for Atari */
6066
#endif
6067
#ifdef OUTHUNK
6068
          hunk_onlyglobal = flag; /* only xdef-symbols in objects for Amiga */
6069
#endif
6070
          break;
6071
        default:
6072
          cpu_error(31,toupper((unsigned char)opt),c);  /* unkn. opt ignored */
6073
          break;
6074
      }
6075
      return ++s;
6076
    }
6077
  }
6078
 
6079
  devpac_err:
6080
  cpu_error(23);  /* option expected */
6081
  return NULL;
6082
}
6083
 
6084
 
6085
char *parse_cpu_special(char *start)
6086
/* parse cpu-specific directives; return pointer to end of
6087
   cpu-specific text */
6088
{
6089
  char *name=start,*s=start;
6090
  uint32_t cpu;
6091
 
6092
  if (ISIDSTART(*s)) {
6093
    s++;
6094
    while (ISIDCHAR(*s))
6095
      s++;
6096
    if (dotdirs && *name=='.')
6097
      name++;
6098
 
6099
    if ((s-name==4 && !strnicmp(name,"near",4)) ||
6100
        (s-name==5 && !strnicmp(name,"sdreg",5))) {
6101
      /* NEAR <An> */
6102
      signed char r;
6103
 
6104
      s = skip(s);
6105
      r = getreg(&s,0);
6106
      if (r >= 0) {
6107
        if (r>=(REGAn+0) && r<=(REGAn+6))  /* a0-a6 */
6108
          sdreg = REGget(r);
6109
        else
6110
          cpu_error(58);  /* not a valid small data register */
6111
      }
6112
      else if (!dotdirs && !strnicmp(s,"code",4)) {
6113
        add_cpu_opt(0,OCMD_SMALLCODE,1);
6114
        return skip_line(s);
6115
      }
6116
      else
6117
        sdreg = last_sdreg;
6118
      add_cpu_opt(0,OCMD_SDREG,sdreg);
6119
      /* skip rest of line to be compatible to other assemblers */
6120
      return skip_line(s);
6121
    }
6122
 
6123
    else if (s-name==3 && !strnicmp(name,"far",3)) {
6124
      /* FAR */
6125
      if (sdreg >= 0) {
6126
        last_sdreg = sdreg;
6127
        sdreg = -1;
6128
        add_cpu_opt(0,OCMD_SDREG,sdreg);
6129
      }
6130
      add_cpu_opt(0,OCMD_SMALLCODE,0);
6131
      eol(s);
6132
      return skip_line(s);
6133
    }
6134
 
6135
    else if (s-name==8 && !strnicmp(name,"initnear",8)) {
6136
      /* INITNEAR */
6137
      if (sdreg >= 0) {
6138
        dblock *db = new_dblock();
6139
 
6140
        db->size = 6;
6141
        db->data = mymalloc(6);
6142
        db->data[0] = 0x41 | (sdreg << 1);  /* LEA _LinkerDB,An */
6143
        db->data[1] = 0xf9;
6144
        memset(&db->data[2],0,4);
6145
        add_extnreloc(&db->relocs,new_import("_LinkerDB"),0,REL_ABS,0,32,2);
6146
        add_atom(0,new_data_atom(db,2));
6147
      }
6148
      else
6149
        cpu_error(59);  /* small data mode is not enabled */
6150
      return skip_line(s);
6151
    }
6152
 
6153
    else if (s-name==7 && !strnicmp(name,"basereg",7)) {
6154
      /* BASEREG <expression>,<An> */
6155
      expr *exp;
6156
      signed char reg;
6157
 
6158
      s = skip(s);
6159
      if ((exp = parse_expr(&s)) != NULL) {
6160
        s = skip(s);
6161
        if (*s == ',') {
6162
          s = skip(s+1);
6163
          reg = getreg(&s,0);
6164
          if (reg>=(REGAn+0) && reg<=(REGAn+6)) {
6165
            if (baseexp[REGget(reg)]!=NULL && !phxass_compat) {
6166
              cpu_error(55,REGget(reg));  /* basereg already in use */
6167
            }
6168
            else {
6169
              baseexp[REGget(reg)] = exp;
6170
              eol(s);
6171
            }
6172
          }
6173
          else
6174
            cpu_error(4);  /* address register required */
6175
        }
6176
        else
6177
          cpu_error(15,',');  /* , expected */
6178
      }
6179
      return skip_line(s);
6180
    }
6181
 
6182
    else if (s-name==4 && !strnicmp(name,"endb",4)) {
6183
      signed char reg;
6184
 
6185
      s = skip(s);
6186
      reg = getreg(&s,0);
6187
      if (reg>=(REGAn+0) && reg<=(REGAn+6)) {
6188
        if (baseexp[REGget(reg)] != NULL) {
6189
          baseexp[REGget(reg)] = NULL;
6190
          eol(s);
6191
        }
6192
        else
6193
          cpu_error(56,REGget(reg));  /* basereg is already free */
6194
      }
6195
      else if (phxass_compat) {
6196
        /* ignore register specification as long as it is unambiguous */
6197
        for (reg=0; reg<=6; reg++) {
6198
          if (baseexp[reg] != NULL) {
6199
            baseexp[reg] = NULL;
6200
            break;
6201
          }
6202
        }
6203
        for (; reg<=6; reg++) {
6204
          if (baseexp[reg] != NULL)  /* more than one register in use? */
6205
            cpu_error(4);            /* address register required */
6206
        }
6207
      }
6208
      else
6209
        cpu_error(4);  /* address register required */
6210
      return skip_line(s);
6211
    }
6212
 
6213
    else if (s-name==7 && !strnicmp(name,"machine",7)) {
6214
      /* MACHINE <cpu-type> */
6215
      int acflag = 0;
6216
 
6217
      s = skip(s);
6218
      if (!strnicmp(s,"mc",2)) {
6219
        s += 2;  /* Devpac-compatible MACHINE mc680x0 */
6220
        acflag = -1;
6221
      }
6222
      else if (!strnicmp(s,"ac",2)) {
6223
        s += 2;  /* Apollo Core ac680x0 */
6224
        acflag = 1;
6225
      }
6226
 
6227
      cpu = get_cpu_type(&s);
6228
 
6229
      if (cpu!=0 &&
6230
          ((!(cpu&apollo) && acflag<=0) || ((cpu&apollo) && acflag>=0))) {
6231
        set_cpu_type(cpu,1);
6232
        eol(s);
6233
      }
6234
      else
6235
        cpu_error(43);  /* unknown cpu type */
6236
      return skip_line(s);
6237
    }
6238
 
6239
    else if ((s-name)>=5 && (s-name)<=8 && !strnicmp(name,"mcf",3)) {
6240
      /* MCF5xxx ColdFire */
6241
      s = name + 3;
6242
      if ((cpu = get_cpu_type(&s)) != 0) {
6243
        set_cpu_type(cpu,1);
6244
        eol(s);
6245
        return skip_line(s);
6246
      }
6247
      return start;
6248
    }
6249
 
6250
    else if (s-name==7 && !strnicmp(name,"mc",2)) {
6251
      /* MC680x0 */
6252
      s = name + 2;
6253
      cpu = get_cpu_type(&s);
6254
      if (cpu!=0 && !(cpu&apollo)) {
6255
        set_cpu_type(cpu,1);
6256
        eol(s);
6257
        return skip_line(s);
6258
      }
6259
      return start;
6260
    }
6261
 
6262
    else if (s-name==7 && !strnicmp(name,"ac",2)) {
6263
      /* Apollo Core AC680x0 */
6264
      s = name + 2;
6265
      cpu = get_cpu_type(&s);
6266
      if (cpu & apollo) {
6267
        set_cpu_type(cpu,1);
6268
        eol(s);
6269
        return skip_line(s);
6270
      }
6271
      return start;
6272
    }
6273
 
6274
    else if (s-name==5 && !strnicmp(name,"cpu32",5)) {
6275
      /* CPU32 */
6276
      set_cpu_type(cpu32,1);
6277
      eol(s);
6278
      return skip_line(s);
6279
    }
6280
 
6281
    else if (s-name==3 && !strnicmp(name,"fpu",3)) {
6282
      /* FPU [<cpID>] */
6283
      taddr id = 1;
6284
 
6285
      s = skip(s);
6286
      if (validchar(s))
6287
        id = parse_constexpr(&s);
6288
      if (id>0 && id<8 && !no_fpu) {
6289
        if (id>1 && (cpu_type & (m68040up|mcffpu)))
6290
          cpu_error(71,(int)id);  /* bad FPU id for selected cpu type */
6291
        fpu_id = (unsigned char)id;
6292
        add_cpu_opt(0,OCMD_FPU,fpu_id);
6293
        cpu_type |= m68881|m68882;
6294
      }
6295
      else
6296
        cpu_type &= ~(m68881|m68882);
6297
      add_cpu_opt(0,OCMD_CPU,cpu_type);
6298
      eol(s);
6299
      return skip_line(s);
6300
    }
6301
 
6302
    else if (s-name==3 && !strnicmp(name,"opt",3)) {
6303
      if (phxass_compat) {
6304
        /* OPT [single-letter-options] - PhxAss options */
6305
        s = skip(s);
6306
        clear_all_opts();  /* first disable all */
6307
        while (validchar(s))
6308
          phxass_option(*s++);
6309
        cpu_opts_optinit(NULL);  /* now create new opt atoms */
6310
      }
6311
      else {
6312
        /* OPT <option>[,<option>...] - Devpac options */
6313
        char *s2 = s;
6314
 
6315
        do {
6316
          if (!(s2 = devpac_option(skip(s2))))
6317
            break;
6318
          s2 = skip(s2);
6319
        }
6320
        while (*s2++ == ',');  /* another option? */
6321
      }
6322
      return skip_line(s);
6323
    }
6324
 
6325
    else if (phxass_compat && s-name==4 && !strnicmp(name,"optc",4)) {
6326
      /* OPTC <expression> - set PhxAss optimization flags */
6327
      taddr optc = 0;
6328
 
6329
      s = skip(s);
6330
      clear_all_opts();  /* first disable all */
6331
      if (validchar(s))
6332
        optc = parse_constexpr(&s);
6333
      phxass_optc((uint16_t)optc);
6334
      cpu_opts_optinit(NULL);  /* now create new opt atoms */
6335
      return skip_line(s);
6336
    }
6337
  }
6338
  return start;
6339
}
6340
 
6341
 
6342
int parse_cpu_label(char *labname,char **start)
6343
/* parse cpu-specific directives following a label field,
6344
   return zero when no valid directive was recognized */
6345
{
6346
  char *dir=*start,*s=*start;
6347
 
6348
  if (ISIDSTART(*s)) {
6349
    s++;
6350
    while (ISIDCHAR(*s))
6351
      s++;
6352
    if (dotdirs && *dir=='.')
6353
      dir++;
6354
 
6355
    if ((s-dir==4 && !strnicmp(dir,"equr",4)) ||
6356
        (s-dir==5 && !strnicmp(dir,"fequr",5))) {
6357
      /* label EQUR Rn */
6358
      operand dummy;
6359
      signed char r;
6360
      char *upd;
6361
 
6362
      s = skip(s);
6363
      if ((r = getreg(&s,0)) >= 0)
6364
        new_regsym(regsymredef,0,labname,
6365
                   REGisAn(r)?RSTYPE_An:RSTYPE_Dn,0,REGget(r));
6366
      else if ((r = getfreg(&s)) >= 0)
6367
        new_regsym(regsymredef,0,labname,RSTYPE_FPn,0,r);
6368
      else if ((r = getbreg(&s)) >= 0)
6369
        new_regsym(regsymredef,0,labname,RSTYPE_Bn,0,r);
6370
      else if (upd = getspecreg(s,&dummy,REG_VX00,REG_VX23,0)) {
6371
        new_regsym(regsymredef,0,labname,RSTYPE_En,0,
6372
                   (unsigned char)dummy.reg);
6373
        s = upd;
6374
      }
6375
      else
6376
        cpu_error(44);  /* register expected */
6377
      eol(s);
6378
      *start = skip_line(s);
6379
      return 1;
6380
    }
6381
 
6382
    else if ((s-dir==3 && !strnicmp(dir,"reg",3)) ||
6383
             (s-dir==5 && !strnicmp(dir,"equrl",5))) {
6384
      /* label REG reglist */
6385
      symbol *sym;
6386
 
6387
      s = skip(s);
6388
      sym = new_equate(labname,number_expr((taddr)scan_Rnlist(&s)));
6389
      sym->flags |= REGLIST;
6390
      eol(s);
6391
      *start = skip_line(s);
6392
      return 1;
6393
    }
6394
 
6395
    else if ((s-dir==4 && !strnicmp(dir,"freg",4)) ||
6396
             (s-dir==6 && !strnicmp(dir,"fequrl",6))) {
6397
      /* label FREG reglist */
6398
      symbol *sym;
6399
 
6400
      s = skip(s);
6401
      sym = new_equate(labname,number_expr((taddr)scan_FPnlist(&s)));
6402
      sym->flags |= REGLIST;
6403
      eol(s);
6404
      *start = skip_line(s);
6405
      return 1;
6406
    }
6407
  }
6408
 
6409
  return 0;
6410
}

powered by: WebSVN 2.1.0

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