Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1126 savelij 1
/* codepdp11.c */
2
/*****************************************************************************/
3
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4
/*                                                                           */
5
/* AS                                                                        */
6
/*                                                                           */
7
/* Code Generator PDP-11                                                     */
8
/*                                                                           */
9
/*****************************************************************************/
10
 
11
#include "stdinc.h"
12
#include <string.h>
13
 
14
#include "bpemu.h"
15
#include "strutil.h"
16
#include "headids.h"
17
#include "asmdef.h"
18
#include "asmsub.h"
19
#include "asmpars.h"
20
#include "asmallg.h"
21
#include "asmcode.h"
22
#include "asmitree.h"
23
#include "codevars.h"
24
#include "codepseudo.h"
25
#include "errmsg.h"
26
#include "intpseudo.h"
27
#include "motpseudo.h"
28
#include "onoff_common.h"
29
#include "cpu2phys.h"
30
#include "decfloat.h"
31
#include "codepdp11.h"
32
 
33
#define default_regsyms_name "DEFAULT_REGSYMS"
34
 
35
#define REG_PC 7
36
#define REG_SP 6
37
 
38
#define APR_COUNT 8
39
#define ASSUME_COUNT (2 * APR_COUNT)
40
 
41
typedef enum
42
{
43
  ModReg = 0,
44
  ModImm = 1,
45
  ModMem = 2
46
} adr_mode_t;
47
 
48
#define MModReg (1 << ModReg)
49
#define MModImm (1 << ModImm)
50
#define MModMem (1 << ModMem)
51
 
52
#define CODE_FLAG_GEN_IMM (1 << 0)
53
#define CODE_FLAG_16BIT (1 << 1)
54
 
55
/* only used for FP11 insns */
56
 
57
#define CODE_FLAG_32BIT (1 << 2)
58
#define CODE_FLAG_F64BIT (1 << 3)
59
#define CODE_FLAG_ARGSWAP (1 << 4)
60
 
61
typedef struct
62
{
63
  Word mode;
64
  unsigned count;
65
  Word vals[4];
66
} adr_vals_t;
67
 
68
enum
69
{
70
  e_ext_eis = 0, /* MUL, DIV, ASH, ASHC */
71
  e_ext_fis = 1, /* FADD, FSUB, FDIV, FMUL */
72
  e_ext_fp11 = 2,
73
  e_ext_cis = 3,
74
  e_ext_opt_cnt,
75
  e_ext_sob_sxt = e_ext_opt_cnt,
76
  e_ext_xor = 5,
77
  e_ext_rtt = 6,
78
  e_ext_mark = 7,
79
  e_ext_mfpt = 8,
80
  e_ext_mfp_mtp = 9,
81
  e_ext_spl = 10,
82
  e_ext_csm = 11,
83
  e_ext_wrtlck = 12,
84
  e_ext_tstset = 13,
85
  e_ext_mfps_mtps = 14,
86
  e_ext_wd16 = 15, /* not a real extension, but an instruction set discriminator */
87
  e_ext_cnt
88
};
89
 
90
#define e_cpu_flag_eis (1 << e_ext_eis)
91
#define e_cpu_flag_fis (1 << e_ext_fis)
92
#define e_cpu_flag_fp11 (1 << e_ext_fp11)
93
#define e_cpu_flag_cis (1 << e_ext_cis)
94
#define e_cpu_flag_sob_sxt (1 << e_ext_sob_sxt)
95
#define e_cpu_flag_xor (1 << e_ext_xor)
96
#define e_cpu_flag_rtt (1 << e_ext_rtt)
97
#define e_cpu_flag_mark (1 << e_ext_mark)
98
#define e_cpu_flag_mfpt (1 << e_ext_mfpt)
99
#define e_cpu_flag_mfp_mtp (1 << e_ext_mfp_mtp)
100
#define e_cpu_flag_spl (1 << e_ext_spl)
101
#define e_cpu_flag_csm (1 << e_ext_csm)
102
#define e_cpu_flag_wrtlck (1 << e_ext_wrtlck)
103
#define e_cpu_flag_tstset (1 << e_ext_tstset)
104
#define e_cpu_flag_mfps_mtps (1 << e_ext_mfps_mtps)
105
#define e_cpu_flag_wd16 (1 << e_ext_wd16)
106
 
107
typedef struct
108
{
109
  char name[15];
110
  Byte addr_space, opt_flags;
111
  Word flags;
112
} cpu_props_t;
113
 
114
static const cpu_props_t *p_curr_cpu_props;
115
static tSymbolSize op_size;
116
static Boolean default_regsyms;
117
static LongInt *reg_par, *reg_pdr;
118
 
119
static Boolean is_wd16(void)
120
{
121
  return !!(p_curr_cpu_props->flags & e_cpu_flag_wd16);
122
}
123
 
124
/*-------------------------------------------------------------------------*/
125
/* Register Symbols */
126
 
127
/*!------------------------------------------------------------------------
128
 * \fn     decode_reg_core(const char *p_arg, Word *p_result, tSymbolSize *p_size)
129
 * \brief  check whether argument is a CPU register
130
 * \param  p_arg argument to check
131
 * \param  p_result numeric register value if yes
132
 * \param  p_size returns register size
133
 * \return True if yes
134
 * ------------------------------------------------------------------------ */
135
 
136
static Boolean decode_reg_core(const char *p_arg, Word *p_result, tSymbolSize *p_size)
137
{
138
  if (!as_strcasecmp(p_arg, "PC") && default_regsyms)
139
  {
140
    *p_result = REG_PC | REGSYM_FLAG_ALIAS;
141
    *p_size = eSymbolSize16Bit;
142
    return True;
143
  }
144
  else if (!as_strcasecmp(p_arg, "SP") && default_regsyms)
145
  {
146
    *p_result = REG_SP | REGSYM_FLAG_ALIAS;
147
    *p_size = eSymbolSize16Bit;
148
    return True;
149
  }
150
 
151
  switch (strlen(p_arg))
152
  {
153
    case 2:
154
      if ((((as_toupper(*p_arg) == 'R') && default_regsyms)
155
        || (*p_arg == '%'))
156
       && isdigit(p_arg[1])
157
       && (p_arg[1] < '8'))
158
      {
159
        *p_result = p_arg[1] - '0';
160
        *p_size = eSymbolSize16Bit;
161
        return True;
162
      }
163
      break;
164
    case 3:
165
      if ((as_toupper(*p_arg) == 'A')
166
       && (as_toupper(p_arg[1]) == 'C')
167
       && isdigit(p_arg[2])
168
       && (p_arg[2] < '6'))
169
      {
170
        *p_result = p_arg[2] - '0';
171
        *p_size = eSymbolSizeFloat64Bit;
172
        return True;
173
      }
174
      break;
175
    default:
176
      break;
177
  }
178
  return False;
179
}
180
 
181
/*!------------------------------------------------------------------------
182
 * \fn     dissect_reg_pdp11(char *p_dest, size_t dest_size, tRegInt value, tSymbolSize inp_size)
183
 * \brief  dissect register symbols - PDP-11 variant
184
 * \param  p_dest destination buffer
185
 * \param  dest_size destination buffer size
186
 * \param  value numeric register value
187
 * \param  inp_size register size
188
 * ------------------------------------------------------------------------ */
189
 
190
static void dissect_reg_pdp11(char *p_dest, size_t dest_size, tRegInt value, tSymbolSize inp_size)
191
{
192
  switch (inp_size)
193
  {
194
    case eSymbolSize16Bit:
195
      switch (value)
196
      {
197
        case REGSYM_FLAG_ALIAS | REG_PC:
198
          as_snprintf(p_dest, dest_size, "PC");
199
          break;
200
        case REGSYM_FLAG_ALIAS | REG_SP:
201
          as_snprintf(p_dest, dest_size, "SP");
202
          break;
203
        default:
204
          as_snprintf(p_dest, dest_size, "R%u", (unsigned)(value & 7));
205
      }
206
      break;
207
    case eSymbolSizeFloat64Bit:
208
      as_snprintf(p_dest, dest_size, "AC%u", (unsigned)(value & 7));
209
      break;
210
    default:
211
      as_snprintf(p_dest, dest_size, "%d-%u", (int)inp_size, (unsigned)value);
212
  }
213
}
214
 
215
/*--------------------------------------------------------------------------*/
216
/* PDP-11 specific flags */
217
 
218
/*!------------------------------------------------------------------------
219
 * \fn     onoff_ext_add(Boolean def_value)
220
 * \brief  register on/off command for specific instruction set extension
221
 * \param  def_value default value of flag upon first use
222
 * ------------------------------------------------------------------------ */
223
 
224
static Byte ext_registered = 0;
225
 
226
unsigned ext_test_and_set(unsigned mask)
227
{
228
  unsigned curr = ext_registered;
229
 
230
  ext_registered |= mask;
231
  return curr & mask;
232
}
233
 
234
static const char ext_names[e_ext_opt_cnt][5] = { "EIS", "FIS", "FP11", "CIS" };
235
static Boolean ext_avail[e_ext_opt_cnt];
236
 
237
/* default value setting only upon first registration, similar to scheme in
238
   onoff_common.c: */
239
 
240
static void onoff_ext_add(unsigned ext, Boolean def_value)
241
{
242
  Byte ext_mask = 1 << ext;
243
 
244
  if (!ext_test_and_set(ext_mask))
245
    SetFlag(&ext_avail[ext], ext_names[ext], def_value);
246
  AddONOFF(ext_names[ext], &ext_avail[ext], ext_names[ext], False);
247
}
248
 
249
/*!------------------------------------------------------------------------
250
 * \fn     check_cpu_ext(unsigned ext)
251
 * \brief  check whether instruction is allowed on CPU
252
 * \param  ext request instruction set extension
253
 * \return True if usage is OK
254
 * ------------------------------------------------------------------------ */
255
 
256
static Boolean check_cpu_ext(unsigned ext)
257
{
258
  unsigned mask = 1 << ext;
259
 
260
  if (p_curr_cpu_props->flags & mask)
261
    return True;
262
  else if ((ext < e_ext_opt_cnt) && (p_curr_cpu_props->opt_flags & mask) && ext_avail[ext])
263
    return True;
264
  else
265
  {
266
    if (ext < e_ext_opt_cnt)
267
      WrXErrorPos(ErrNum_InstructionNotSupported, ext_names[ext], &OpPart.Pos);
268
    else
269
      WrStrErrorPos(ErrNum_InstructionNotSupported, &OpPart);
270
    return False;
271
  }
272
}
273
 
274
/*--------------------------------------------------------------------------*/
275
/* Address Mode Parser */
276
 
277
/*!------------------------------------------------------------------------
278
 * \fn     check_sup_mode(void)
279
 * \brief  check for CPU in supervisor mode
280
 * \return constant true
281
 * ------------------------------------------------------------------------ */
282
 
283
static Boolean check_sup_mode(void)
284
{
285
  if (!SupAllowed)
286
    WrStrErrorPos(ErrNum_PrivOrder, &OpPart);
287
  return True;
288
}
289
 
290
/*!------------------------------------------------------------------------
291
 * \fn     reset_adr_vals(adr_vals_t *p_vals)
292
 * \brief  clear encoded addressing mode
293
 * \param  p_vals encoded mode to reset
294
 * ------------------------------------------------------------------------ */
295
 
296
static void reset_adr_vals(adr_vals_t *p_vals)
297
{
298
  p_vals->mode = 0;
299
  p_vals->count = 0;
300
  p_vals->vals[0] = 0;
301
}
302
 
303
/*!------------------------------------------------------------------------
304
 * \fn     decode_reg(const tStrComp *p_arg, Word *p_result, tSymbolSize *p_size, tSymbolSize req_size, Boolean must_be_reg)
305
 * \brief  check whether argument is a CPU register or register alias
306
 * \param  p_arg argument to check
307
 * \param  p_result numeric register value if yes
308
 * \param  p_size returns operand size of register (I16 or F64)
309
 * \param  req_size request specific operand/register size
310
 * \param  must_be_reg argument is expected to be a register
311
 * \return RegEvalResult
312
 * ------------------------------------------------------------------------ */
313
 
314
static tErrorNum chk_reg_size(tSymbolSize req_size, tSymbolSize act_size)
315
{
316
  if ((act_size == eSymbolSizeUnknown)
317
   || (req_size == eSymbolSizeUnknown)
318
   || (req_size == act_size))
319
    return ErrNum_None;
320
  else if ((req_size == eSymbolSize16Bit) && (act_size == eSymbolSizeFloat64Bit))
321
    return ErrNum_IntButFloat;
322
  else if ((req_size == eSymbolSizeFloat64Bit) && (act_size == eSymbolSize16Bit))
323
    return ErrNum_FloatButInt;
324
  else
325
    return ErrNum_InvOpSize;
326
}
327
 
328
static tRegEvalResult decode_reg(const tStrComp *p_arg, Word *p_result, tSymbolSize *p_size, tSymbolSize req_size, Boolean must_be_reg)
329
{
330
  tRegDescr reg_descr;
331
  tEvalResult eval_result;
332
  tRegEvalResult reg_eval_result;
333
 
334
  if (decode_reg_core(p_arg->str.p_str, p_result, &eval_result.DataSize))
335
  {
336
    reg_descr.Reg = *p_result;
337
    reg_eval_result = eIsReg;
338
  }
339
  else
340
    reg_eval_result = EvalStrRegExpressionAsOperand(p_arg, &reg_descr, &eval_result, eSymbolSizeUnknown, must_be_reg);
341
 
342
  if (reg_eval_result == eIsReg)
343
  {
344
    tErrorNum error_num = chk_reg_size(req_size, eval_result.DataSize);
345
 
346
    if (error_num)
347
    {
348
      WrStrErrorPos(error_num, p_arg);
349
      reg_eval_result = must_be_reg ? eIsNoReg : eRegAbort;
350
    }
351
  }
352
 
353
  *p_result = reg_descr.Reg & ~REGSYM_FLAG_ALIAS;
354
  if (p_size) *p_size = eval_result.DataSize;
355
  return reg_eval_result;
356
}
357
 
358
static Boolean decode_reg_or_const(const tStrComp *p_arg, Word *p_result)
359
{
360
  switch (decode_reg(p_arg, p_result, NULL, eSymbolSize16Bit, False))
361
  {
362
    case eIsReg:
363
      return True;
364
    case eIsNoReg:
365
    {
366
      Boolean ok;
367
      *p_result = EvalStrIntExpression(p_arg, UInt3, &ok);
368
      return ok;
369
    }
370
    default:
371
      return False;
372
  }
373
}
374
 
375
/*!------------------------------------------------------------------------
376
 * \fn     decode_adr(tStrComp *p_arg, adr_vals_t *p_result, Word pc_value, unsigned mode_mask)
377
 * \brief  parse address expression
378
 * \param  p_arg source argument
379
 * \param  p_result parsed result
380
 * \param  pc_value value of PC to be used in PC-relative calculation
381
 * \param  mode_mask bit mask of allowed addressing modes
382
 * \return True if success
383
 * ------------------------------------------------------------------------ */
384
 
385
static Boolean is_pre_decrement(const tStrComp *p_arg, Word *p_result, tRegEvalResult *p_reg_eval_result)
386
{
387
  String reg;
388
  tStrComp reg_comp;
389
  size_t arg_len = strlen(p_arg->str.p_str);
390
 
391
  if ((arg_len < 4)
392
   || (p_arg->str.p_str[0] != '-')
393
   || (p_arg->str.p_str[1] != '(')
394
   || (p_arg->str.p_str[arg_len - 1] != ')'))
395
    return False;
396
  StrCompMkTemp(&reg_comp, reg, sizeof(reg));
397
  StrCompCopySub(&reg_comp, p_arg, 2, arg_len - 3);
398
  KillPrefBlanksStrComp(&reg_comp);
399
  KillPostBlanksStrComp(&reg_comp);
400
  *p_reg_eval_result = decode_reg(&reg_comp, p_result, NULL, eSymbolSize16Bit, False);
401
  return (*p_reg_eval_result != eIsNoReg);
402
}
403
 
404
static Boolean is_post_increment(const tStrComp *p_arg, Word *p_result, tRegEvalResult *p_reg_eval_result)
405
{
406
  String reg;
407
  tStrComp reg_comp;
408
  size_t arg_len = strlen(p_arg->str.p_str);
409
 
410
  if ((arg_len < 4)
411
   || (p_arg->str.p_str[0] != '(')
412
   || (p_arg->str.p_str[arg_len - 2] != ')')
413
   || (p_arg->str.p_str[arg_len - 1] != '+'))
414
    return False;
415
  StrCompMkTemp(&reg_comp, reg, sizeof(reg));
416
  StrCompCopySub(&reg_comp, p_arg, 1, arg_len - 3);
417
  KillPrefBlanksStrComp(&reg_comp);
418
  KillPostBlanksStrComp(&reg_comp);
419
 
420
  /* Opposed to -(...), (...)+ cannot be interpreted as an arbitrary
421
     arithmetic expression.  The expression in parentheses MUST be a
422
     register: */
423
 
424
  *p_reg_eval_result = decode_reg(&reg_comp, p_result, NULL, eSymbolSize16Bit, True);
425
  if (*p_reg_eval_result == eIsNoReg)
426
    *p_reg_eval_result = eRegAbort;
427
  return (*p_reg_eval_result != eIsNoReg);
428
}
429
 
430
static Boolean decode_abs(const tStrComp *p_arg, Word *p_addr)
431
{
432
  Boolean ok;
433
 
434
  *p_addr = EvalStrIntExpression(p_arg, UInt16, &ok);
435
  return ok;
436
}
437
 
438
static Boolean decode_imm8(const tStrComp *p_arg, Word *p_value)
439
{
440
  Boolean ok;
441
 
442
  *p_value = EvalStrIntExpression(p_arg, Int8, &ok) & 0xff;
443
  return ok;
444
}
445
 
446
static Boolean check_mode_mask(unsigned mode_mask, unsigned act_mask, tStrComp *p_arg)
447
{
448
  if (!(mode_mask & act_mask))
449
  {
450
    WrStrErrorPos(ErrNum_InvAddrMode, p_arg);
451
    return False;
452
  }
453
  else
454
    return True;
455
}
456
 
457
static Boolean decode_adr(tStrComp *p_arg, adr_vals_t *p_result, Word pc_value, unsigned mode_mask)
458
{
459
  tEvalResult eval_result;
460
  tRegEvalResult reg_eval_result;
461
  Boolean deferred;
462
  tStrComp arg;
463
  int arg_len, split_pos;
464
 
465
  reset_adr_vals(p_result);
466
 
467
  /* split off deferred flag? */
468
 
469
  deferred = (p_arg->str.p_str[0] == '@');
470
  StrCompRefRight(&arg, p_arg, deferred);
471
  if (deferred)
472
    KillPrefBlanksStrCompRef(&arg);
473
 
474
  /* Rn, @Rn, ACn: */
475
 
476
  switch (decode_reg(&arg, &p_result->mode, NULL, (deferred || (op_size < eSymbolSizeFloat32Bit)) ? eSymbolSize16Bit : eSymbolSizeFloat64Bit, False))
477
  {
478
    case eIsReg:
479
      p_result->mode |= deferred ? 010 : 000;
480
      return check_mode_mask(mode_mask, deferred ? MModMem : MModReg, p_arg);
481
    case eRegAbort:
482
      return False;
483
    default:
484
      break;
485
  }
486
 
487
  /* #imm, @#abs */
488
 
489
  if (*arg.str.p_str == '#')
490
  {
491
    tStrComp imm_arg;
492
 
493
    if (!deferred && !check_mode_mask(mode_mask, deferred ? MModMem : MModImm, p_arg))
494
      return False;
495
    StrCompRefRight(&imm_arg, &arg, 1);
496
 
497
    if (deferred)
498
    {
499
      eval_result.OK = decode_abs(&imm_arg, &p_result->vals[0]);
500
      if (eval_result.OK)
501
        p_result->count = 2;
502
    }
503
    else switch (op_size)
504
    {
505
      case eSymbolSize8Bit:
506
        eval_result.OK = decode_imm8(&imm_arg, &p_result->vals[0]);
507
        if (eval_result.OK)
508
          p_result->count = 2;
509
        break;
510
      case eSymbolSize16Bit:
511
        p_result->vals[0] = EvalStrIntExpressionWithResult(&imm_arg, Int16, &eval_result);
512
        if (eval_result.OK)
513
          p_result->count = 2;
514
        break;
515
      case eSymbolSize32Bit:
516
      {
517
        LongWord l_val = EvalStrIntExpressionWithResult(&imm_arg, Int32, &eval_result);
518
        if (eval_result.OK)
519
        {
520
          p_result->vals[0] = (l_val >> 16) & 0xffff;
521
          p_result->vals[1] = l_val & 0xffff;
522
          p_result->count = 4;
523
        }
524
        break;
525
      }
526
      case eSymbolSizeFloat32Bit:
527
      {
528
        Double f_val = EvalStrFloatExpressionWithResult(&imm_arg, Float64, &eval_result);
529
        if (eval_result.OK)
530
        {
531
          int ret = Double_2_dec4(f_val, p_result->vals);
532
          eval_result.OK = check_dec_fp_dispose_result(ret, &imm_arg);
533
        }
534
        if (eval_result.OK)
535
          p_result->count = 4;
536
        break;
537
      }  
538
      case eSymbolSizeFloat64Bit:
539
      {
540
        Double f_val = EvalStrFloatExpressionWithResult(&imm_arg, Float64, &eval_result);
541
        if (eval_result.OK)
542
        {
543
          int ret = Double_2_dec8(f_val, p_result->vals);
544
          eval_result.OK = check_dec_fp_dispose_result(ret, &imm_arg);
545
        }
546
        if (eval_result.OK)
547
          p_result->count = 8;
548
        break;
549
      }  
550
      case eSymbolSizeUnknown:
551
        WrStrErrorPos(ErrNum_UndefOpSizes, p_arg);
552
        eval_result.OK = False;
553
        break;
554
      default:
555
        WrStrErrorPos(ErrNum_InvOpSize, p_arg);
556
        eval_result.OK = False;
557
    }
558
    if (eval_result.OK)
559
    {
560
      /* immediate is actually (PC)+, absolute is actually @(PC)+ */
561
 
562
      p_result->mode = (deferred ? 030 : 020) | REG_PC;
563
    }
564
    return eval_result.OK;
565
  }
566
 
567
  /* (Rn)+, @(Rn)+ */
568
 
569
  if (is_post_increment(&arg, &p_result->mode, &reg_eval_result))
570
  {
571
    if (eRegAbort == reg_eval_result)
572
      return False;
573
    p_result->mode |= deferred ? 030 : 020;
574
    return check_mode_mask(mode_mask, MModMem, p_arg);
575
  }
576
 
577
  /* -(Rn), @-(Rn) */
578
 
579
  if (is_pre_decrement(&arg, &p_result->mode, &reg_eval_result))
580
  {
581
    if (eRegAbort == reg_eval_result)
582
      return False;
583
    p_result->mode |= (deferred ? 050 : 040);
584
    return check_mode_mask(mode_mask, MModMem, p_arg);
585
  }
586
 
587
  /* (Rn), X(Rn) */
588
 
589
  split_pos = FindDispBaseSplitWithQualifier(arg.str.p_str, &arg_len, NULL, "()");
590
  if (split_pos >= 0)
591
  {
592
    tStrComp disp_arg, reg_arg;
593
 
594
    StrCompSplitRef(&disp_arg, &reg_arg, &arg, &arg.str.p_str[split_pos]);
595
    KillPostBlanksStrComp(&disp_arg);
596
    KillPrefBlanksStrCompRef(&reg_arg);
597
    StrCompShorten(&reg_arg, 1);
598
    KillPostBlanksStrComp(&reg_arg);
599
 
600
    if (!decode_reg_or_const(&reg_arg, &p_result->mode))
601
      return False;
602
    if (!*disp_arg.str.p_str && !deferred)
603
      p_result->mode |= 010;
604
    else
605
    {
606
      p_result->vals[0] = EvalStrIntExpressionWithResult(&disp_arg, Int16, &eval_result);
607
      if (!eval_result.OK)
608
        return False;
609
      p_result->mode |= deferred ? 070 : 060;
610
      p_result->count = 2;
611
    }
612
    return check_mode_mask(mode_mask, MModMem, p_arg);
613
  }
614
 
615
  /* Remains: rel, @rel
616
     PC value is the PC value after displacement was loaded: */
617
 
618
  p_result->vals[0] = EvalStrIntExpressionWithResult(&arg, UInt16, &eval_result) - (pc_value + 2);
619
  if (!eval_result.OK)
620
    return False;
621
  p_result->mode = REG_PC | (deferred ? 070 : 060);
622
  p_result->count = 2;
623
  return check_mode_mask(mode_mask, MModMem, p_arg);
624
}
625
 
626
/*!------------------------------------------------------------------------
627
 * \fn     decode_ac_03(tStrComp *p_arg, Word *p_result)
628
 * \brief  handle FP11 argument that may only refer AC0...AC3
629
 * \param  p_arg source argument
630
 * \param  p_result resulting AC number
631
 * \return True if valid argument
632
 * ------------------------------------------------------------------------ */
633
 
634
static Boolean decode_ac_03(tStrComp *p_arg, Word *p_result)
635
{
636
  adr_vals_t adr_vals;
637
 
638
  /* operand size must have been set to a floating point type before */
639
  if (!decode_adr(p_arg, &adr_vals, EProgCounter() + 2, MModReg))
640
    return False;
641
  *p_result = adr_vals.mode & 7;
642
  if (*p_result > 3)
643
  {
644
    WrStrErrorPos(ErrNum_InvAddrMode, p_arg);
645
    return False;
646
  }
647
  return True;
648
}
649
 
650
/*--------------------------------------------------------------------------*/
651
/* Instruction Handler Helpers */
652
 
653
static void append_word(Word code)
654
{
655
  WAsmCode[CodeLen >> 1] = code;
656
  CodeLen += 2;
657
}
658
 
659
static void append_adr_vals(const adr_vals_t *p_vals)
660
{
661
  if (p_vals->count >= 2)
662
    append_word(p_vals->vals[0]);
663
  if (p_vals->count >= 4)
664
    append_word(p_vals->vals[1]);
665
  if (p_vals->count >= 6)
666
    append_word(p_vals->vals[2]);
667
  if (p_vals->count >= 8)
668
    append_word(p_vals->vals[3]);
669
}
670
 
671
static unsigned imm_mask(Word code)
672
{
673
  return (code & CODE_FLAG_GEN_IMM) ? MModImm : 0;
674
}
675
 
676
/*--------------------------------------------------------------------------*/
677
/* Instruction Handlers */
678
 
679
/*!------------------------------------------------------------------------
680
 * \fn     decode_fixed(Word code)
681
 * \brief  handle instructions without argument
682
 * \param  code machine code
683
 * ------------------------------------------------------------------------ */
684
 
685
static void decode_fixed(Word code)
686
{
687
  if (ChkArgCnt(0, 0))
688
    append_word(code);
689
}
690
 
691
/*!------------------------------------------------------------------------
692
 * \fn     decode_fixed_sup(Word code)
693
 * \brief  handle privileged instructions without argument
694
 * \param  code machine code
695
 * ------------------------------------------------------------------------ */
696
 
697
static void decode_fixed_sup(Word code)
698
{
699
  if (ChkArgCnt(0, 0) && check_sup_mode())
700
    append_word(code);
701
}
702
 
703
/*!------------------------------------------------------------------------
704
 * \fn     decode_mfpt(Word code)
705
 * \brief  handle MFPT instruction
706
 * \param  code machine code
707
 * ------------------------------------------------------------------------ */
708
 
709
static void decode_mfpt(Word code)
710
{
711
  if (ChkArgCnt(0, 0) && check_cpu_ext(e_ext_mfpt))
712
    append_word(code);
713
}
714
 
715
/*!------------------------------------------------------------------------
716
 * \fn     decode_rtt(Word code)
717
 * \brief  handle RTT instruction
718
 * \param  code machine code
719
 * ------------------------------------------------------------------------ */
720
 
721
static void decode_rtt(Word code)
722
{
723
  if (ChkArgCnt(0, 0) && check_cpu_ext(e_ext_rtt))
724
    append_word(code);
725
}
726
 
727
/*!------------------------------------------------------------------------
728
 * \fn     decode_one_reg(Word code)
729
 * \brief  handle instructions with one register as argument
730
 * \param  code machine code
731
 * ------------------------------------------------------------------------ */
732
 
733
static void decode_one_reg(Word code)
734
{
735
  if (ChkArgCnt(1, 1))
736
  {
737
    adr_vals_t reg_adr_vals;
738
 
739
    op_size = eSymbolSize16Bit;
740
    if (decode_adr(&ArgStr[1], &reg_adr_vals, EProgCounter() + 2, MModReg))
741
      append_word((code & 0xfff8) | reg_adr_vals.mode);
742
  }
743
}
744
 
745
/*!------------------------------------------------------------------------
746
 * \fn     decode_two_reg(Word code)
747
 * \brief  handle instructions with two registers as argument
748
 * \param  code machine code
749
 * ------------------------------------------------------------------------ */
750
 
751
static void decode_two_reg(Word code)
752
{
753
  if (ChkArgCnt(2, 2))
754
  {
755
    adr_vals_t src_adr_vals, dest_adr_vals;
756
 
757
    op_size = eSymbolSize16Bit;
758
    if (decode_adr(&ArgStr[1], &src_adr_vals, EProgCounter() + 2, MModReg)
759
     && decode_adr(&ArgStr[2], &dest_adr_vals, EProgCounter() + 2, MModReg))
760
      append_word((code & 0xffc0) | ((src_adr_vals.mode & 7) << 3) | (dest_adr_vals.mode & 7));
761
  }
762
}
763
 
764
/*!------------------------------------------------------------------------
765
 * \fn     decode_one_arg(Word code)
766
 * \brief  handle instructions with one generic arg
767
 * \param  code machine code
768
 * ------------------------------------------------------------------------ */
769
 
770
static void decode_one_arg(Word code)
771
{
772
  if (ChkArgCnt(1, 1))
773
  {
774
    adr_vals_t adr_vals;
775
 
776
    op_size = (code & CODE_FLAG_16BIT) ? eSymbolSize16Bit : eSymbolSize8Bit;
777
    if (decode_adr(&ArgStr[1], &adr_vals, EProgCounter() + 2, MModReg | MModMem | imm_mask(code)))
778
    {
779
      append_word((code & 0177700) | adr_vals.mode);
780
      append_adr_vals(&adr_vals);
781
    }
782
  }
783
}
784
 
785
/*!------------------------------------------------------------------------
786
 * \fn     decode_tstset(Word code)
787
 * \brief  handle TSTSET instruction
788
 * \param  code machine code
789
 * ------------------------------------------------------------------------ */
790
 
791
static void decode_tstset(Word code)
792
{
793
  if (ChkArgCnt(1, 1) && check_cpu_ext(e_ext_tstset))
794
  {
795
    adr_vals_t adr_vals;
796
 
797
    op_size = (code & CODE_FLAG_16BIT) ? eSymbolSize16Bit : eSymbolSize8Bit;
798
    if (decode_adr(&ArgStr[1], &adr_vals, EProgCounter() + 2, MModReg | MModMem | imm_mask(code)))
799
    {
800
      append_word((code & 0177700) | adr_vals.mode);
801
      append_adr_vals(&adr_vals);
802
    }
803
  }
804
}
805
 
806
/*!------------------------------------------------------------------------
807
 * \fn     decode_mfp_mtp(Word code)
808
 * \brief  handle MFP/MTP instructions
809
 * \param  code machine code
810
 * ------------------------------------------------------------------------ */
811
 
812
static void decode_mfp_mtp(Word code)
813
{
814
  if (ChkArgCnt(1, 1) && check_cpu_ext(e_ext_mfp_mtp))
815
  {
816
    adr_vals_t adr_vals;
817
 
818
    op_size = (code & CODE_FLAG_16BIT) ? eSymbolSize16Bit : eSymbolSize8Bit;
819
    if (decode_adr(&ArgStr[1], &adr_vals, EProgCounter() + 2, MModReg | MModMem | imm_mask(code)))
820
    {
821
      append_word((code & 0177700) | adr_vals.mode);
822
      append_adr_vals(&adr_vals);
823
    }
824
  }
825
}
826
 
827
/*!------------------------------------------------------------------------
828
 * \fn     decode_mfps_mtps(Word code)
829
 * \brief  handle MFPS/MTPS instructions
830
 * \param  code machine code
831
 * ------------------------------------------------------------------------ */
832
 
833
static void decode_mfps_mtps(Word code)
834
{
835
  if (ChkArgCnt(1, 1) && check_cpu_ext(e_ext_mfps_mtps))
836
  {
837
    adr_vals_t adr_vals;
838
 
839
    op_size = (code & CODE_FLAG_16BIT) ? eSymbolSize16Bit : eSymbolSize8Bit;
840
    if (decode_adr(&ArgStr[1], &adr_vals, EProgCounter() + 2, MModReg | MModMem | imm_mask(code)))
841
    {
842
      append_word((code & 0177700) | adr_vals.mode);
843
      append_adr_vals(&adr_vals);
844
    }
845
  }
846
}
847
 
848
/*!------------------------------------------------------------------------
849
 * \fn     decode_csm(Word code)
850
 * \brief  handle CSM instruction
851
 * \param  code machine code
852
 * ------------------------------------------------------------------------ */
853
 
854
static void decode_csm(Word code)
855
{
856
  /* TODO: not in kernel mode */
857
  if (ChkArgCnt(1, 1) && check_cpu_ext(e_ext_csm))
858
  {
859
    adr_vals_t adr_vals;
860
 
861
    op_size = (code & CODE_FLAG_16BIT) ? eSymbolSize16Bit : eSymbolSize8Bit;
862
    if (decode_adr(&ArgStr[1], &adr_vals, EProgCounter() + 2, MModReg | MModMem | imm_mask(code)))
863
    {
864
      append_word((code & 0177700) | adr_vals.mode);
865
      append_adr_vals(&adr_vals);
866
    }
867
  }
868
}
869
 
870
/*!------------------------------------------------------------------------
871
 * \fn     decode_sxt(Word code)
872
 * \brief  handle SXT instruction
873
 * \param  code machine code
874
 * ------------------------------------------------------------------------ */
875
 
876
static void decode_sxt(Word code)
877
{
878
  if (ChkArgCnt(1, 1) && check_cpu_ext(e_ext_sob_sxt))
879
  {
880
    adr_vals_t adr_vals;
881
 
882
    op_size = (code & CODE_FLAG_16BIT) ? eSymbolSize16Bit : eSymbolSize8Bit;
883
    if (decode_adr(&ArgStr[1], &adr_vals, EProgCounter() + 2, MModReg | MModMem | imm_mask(code)))
884
    {
885
      append_word((code & 0177700) | adr_vals.mode);
886
      append_adr_vals(&adr_vals);
887
    }
888
  }
889
}
890
 
891
/*!------------------------------------------------------------------------
892
 * \fn     decode_fp11_f1_f3(Word code)
893
 * \brief  handle FP11 instructions with two arguments (AC is dest)
894
 * \param  code machine code
895
 * ------------------------------------------------------------------------ */
896
 
897
static void decode_fp11_f1_f3(Word code)
898
{
899
  if (ChkArgCnt(2, 2) && check_cpu_ext(e_ext_fp11))
900
  {
901
    adr_vals_t adr_vals;
902
    Word ac_num;
903
    int ac_arg_index = (code & CODE_FLAG_ARGSWAP) ? 1 : 2;
904
 
905
    if (code & CODE_FLAG_16BIT)
906
      op_size = eSymbolSize16Bit;
907
    else if (code & CODE_FLAG_32BIT)
908
      op_size = eSymbolSize32Bit;
909
    else if (code & CODE_FLAG_F64BIT)
910
      op_size = eSymbolSizeFloat64Bit;
911
    else
912
      op_size = eSymbolSizeFloat32Bit;
913
    if (decode_adr(&ArgStr[3 - ac_arg_index], &adr_vals, EProgCounter() + 2, MModReg | MModMem | imm_mask(code)))
914
    {
915
      op_size = (code & CODE_FLAG_F64BIT) ? eSymbolSizeFloat64Bit : eSymbolSizeFloat32Bit;
916
      if (decode_ac_03(&ArgStr[ac_arg_index], &ac_num))
917
      {
918
        append_word((code & 0177400) | (ac_num << 6) | adr_vals.mode);
919
        append_adr_vals(&adr_vals);
920
      }
921
    }
922
  }
923
}
924
 
925
/*!------------------------------------------------------------------------
926
 * \fn     decode_fp11_f2(Word code)
927
 * \brief  handle FP11 instructions with one (float) arg
928
 * \param  code machine code
929
 * ------------------------------------------------------------------------ */
930
 
931
static void decode_fp11_f2(Word code)
932
{
933
  if (ChkArgCnt(1, 1) && check_cpu_ext(e_ext_fp11))
934
  {
935
    adr_vals_t adr_vals;
936
 
937
    op_size = (code & CODE_FLAG_F64BIT) ? eSymbolSizeFloat64Bit : eSymbolSizeFloat32Bit;
938
    if (decode_adr(&ArgStr[1], &adr_vals, EProgCounter() + 2, MModReg | MModMem | imm_mask(code)))
939
    {
940
      append_word((code & 0177700) | adr_vals.mode);
941
      append_adr_vals(&adr_vals);
942
    }
943
  }
944
}
945
 
946
/*!------------------------------------------------------------------------
947
 * \fn     void decode_fp11_f4(Word code)
948
 * \brief  handle FP11 instructions with one (int) arg
949
 * \param  code machine code
950
 * ------------------------------------------------------------------------ */
951
 
952
static void decode_fp11_f4(Word code)
953
{
954
  if (ChkArgCnt(1, 1) && check_cpu_ext(e_ext_fp11))
955
  {
956
    adr_vals_t adr_vals;
957
 
958
    if (code & CODE_FLAG_16BIT)
959
      op_size = eSymbolSize16Bit;
960
    else if (code & CODE_FLAG_32BIT)
961
      op_size = eSymbolSize32Bit;
962
    else
963
      op_size = eSymbolSize8Bit;
964
    if (decode_adr(&ArgStr[1], &adr_vals, EProgCounter() + 2, MModReg | MModMem | imm_mask(code)))
965
    {
966
      append_word((code & 0177700) | adr_vals.mode);
967
      append_adr_vals(&adr_vals);
968
    }
969
  }
970
}
971
 
972
/*!------------------------------------------------------------------------
973
 * \fn     decode_fp11_f5(Word code)
974
 * \brief  handle FP11 instructions with no arg
975
 * \param  code machine code
976
 * ------------------------------------------------------------------------ */
977
 
978
static void decode_fp11_f5(Word code)
979
{
980
  if (ChkArgCnt(0, 0) && check_cpu_ext(e_ext_fp11))
981
    append_word(code);
982
}
983
 
984
/*!------------------------------------------------------------------------
985
 * \fn     decode_cis_0(Word code)
986
 * \brief  handle CIS instructions with no arguments
987
 * \param  code machine code
988
 * ------------------------------------------------------------------------ */
989
 
990
static void decode_cis_0(Word code)
991
{
992
  if (ChkArgCnt(0, 0) && check_cpu_ext(e_ext_cis))
993
    append_word(code);
994
}
995
 
996
/* TODO: CIS instructions take address of descriptors.  Should
997
   this be written as absolute addressing? */
998
 
999
/*!------------------------------------------------------------------------
1000
 * \fn     decode_cis_1i(Word code)
1001
 * \brief  handle CIS instructions with one address and one immediate argument
1002
 * \param  code machine code
1003
 * ------------------------------------------------------------------------ */
1004
 
1005
static void decode_cis_1i(Word code)
1006
{
1007
  Word src, imm;
1008
 
1009
  if (ChkArgCnt(2, 2)
1010
   && check_cpu_ext(e_ext_cis)
1011
   && decode_abs(&ArgStr[1], &src)
1012
   && decode_imm8(&ArgStr[2], &imm))
1013
  {
1014
    append_word(code);
1015
    append_word(src);
1016
    append_word(imm);
1017
  }
1018
}
1019
 
1020
/*!------------------------------------------------------------------------
1021
 * \fn     decode_cis_2(Word code)
1022
 * \brief  handle CIS instructions with two address arguments
1023
 * \param  code machine code
1024
 * ------------------------------------------------------------------------ */
1025
 
1026
static void decode_cis_2(Word code)
1027
{
1028
  Word src, dest;
1029
 
1030
  if (ChkArgCnt(2, 2)
1031
   && check_cpu_ext(e_ext_cis)
1032
   && decode_abs(&ArgStr[1], &src)
1033
   && decode_abs(&ArgStr[2], &dest))
1034
  {
1035
    append_word(code);
1036
    append_word(src);
1037
    append_word(dest);
1038
  }
1039
}
1040
 
1041
/*!------------------------------------------------------------------------
1042
 * \fn     decode_cis_2i(Word code)
1043
 * \brief  handle CIS instructions with two address and one immediate argument
1044
 * \param  code machine code
1045
 * ------------------------------------------------------------------------ */
1046
 
1047
static void decode_cis_2i(Word code)
1048
{
1049
  Word src, dest, imm;
1050
 
1051
  if (ChkArgCnt(3, 3)
1052
   && check_cpu_ext(e_ext_cis)
1053
   && decode_abs(&ArgStr[1], &src)
1054
   && decode_abs(&ArgStr[2], &dest)
1055
   && decode_imm8(&ArgStr[3], &imm))
1056
  {
1057
    append_word(code);
1058
    append_word(src);
1059
    append_word(dest);
1060
    append_word(imm);
1061
  }
1062
}
1063
 
1064
/*!------------------------------------------------------------------------
1065
 * \fn     decode_cis_2i1(Word code)
1066
 * \brief  handle CIS instructions with two src address, one immediate,
1067
           and one dest address argument
1068
 * \param  code machine code
1069
 * ------------------------------------------------------------------------ */
1070
 
1071
static void decode_cis_2i1(Word code)
1072
{
1073
  Word src1, src2, dest, imm;
1074
 
1075
  if (ChkArgCnt(4, 4)
1076
   && check_cpu_ext(e_ext_cis)
1077
   && decode_abs(&ArgStr[1], &src1)
1078
   && decode_abs(&ArgStr[2], &src2)
1079
   && decode_imm8(&ArgStr[3], &imm)
1080
   && decode_abs(&ArgStr[4], &dest))
1081
  {
1082
    append_word(code);
1083
    append_word(src1);
1084
    append_word(src2);
1085
    append_word(imm);
1086
    append_word(dest);
1087
  }
1088
}
1089
 
1090
/*!------------------------------------------------------------------------
1091
 * \fn     decode_cis_3(Word code)
1092
 * \brief  handle CIS instructions with three address arguments
1093
 * \param  code machine code
1094
 * ------------------------------------------------------------------------ */
1095
 
1096
static void decode_cis_3(Word code)
1097
{
1098
  Word src1, src2, dest;
1099
 
1100
  if (ChkArgCnt(3, 3)
1101
   && check_cpu_ext(e_ext_cis)
1102
   && decode_abs(&ArgStr[1], &src1)
1103
   && decode_abs(&ArgStr[2], &src2)
1104
   && decode_abs(&ArgStr[3], &dest))
1105
  {
1106
    append_word(code);
1107
    append_word(src1);
1108
    append_word(src2);
1109
    append_word(dest);
1110
  }
1111
}
1112
 
1113
/*!------------------------------------------------------------------------
1114
 * \fn     decode_cis_ld(Word code)
1115
 * \brief  handle CIS instructions with one post-inc argument
1116
 * \param  code machine code
1117
 * ------------------------------------------------------------------------ */
1118
 
1119
static void decode_cis_ld(Word code)
1120
{
1121
  adr_vals_t adr_vals;
1122
 
1123
  if (ChkArgCnt(1, 1)
1124
   && check_cpu_ext(e_ext_cis)
1125
   && decode_adr(&ArgStr[1], &adr_vals, EProgCounter() + 2, MModMem))
1126
  {
1127
    if ((adr_vals.mode & 070) != 020) WrStrErrorPos(ErrNum_InvAddrMode, &ArgStr[1]);
1128
    else
1129
      append_word(code | (adr_vals.mode & 07));
1130
  }
1131
}
1132
 
1133
/*!------------------------------------------------------------------------
1134
 * \fn     decode_wrtlck(Word code)
1135
 * \brief  handle WRTLCK instruction
1136
 * \param  code machine code
1137
 * ------------------------------------------------------------------------ */
1138
 
1139
static void decode_wrtlck(Word code)
1140
{
1141
  if (ChkArgCnt(1, 1) && check_cpu_ext(e_ext_wrtlck))
1142
  {
1143
    adr_vals_t adr_vals;
1144
 
1145
    op_size = (code & CODE_FLAG_16BIT) ? eSymbolSize16Bit : eSymbolSize8Bit;
1146
    if (decode_adr(&ArgStr[1], &adr_vals, EProgCounter() + 2, MModMem | imm_mask(code)))
1147
    {
1148
      append_word((code & 0177700) | adr_vals.mode);
1149
      append_adr_vals(&adr_vals);
1150
    }
1151
  }
1152
}
1153
 
1154
/*!------------------------------------------------------------------------
1155
 * \fn     decode_two_arg(Word code)
1156
 * \brief  handle instructions with two generic args
1157
 * \param  code machine code
1158
 * ------------------------------------------------------------------------ */
1159
 
1160
static void decode_two_arg(Word code)
1161
{
1162
  if (ChkArgCnt(2, 2))
1163
  {
1164
    adr_vals_t src_adr_vals, dest_adr_vals;
1165
 
1166
    op_size = (code & CODE_FLAG_16BIT) ? eSymbolSize16Bit : eSymbolSize8Bit;
1167
    if (decode_adr(&ArgStr[1], &src_adr_vals, EProgCounter() + 2, MModReg | MModMem | MModImm)
1168
     && decode_adr(&ArgStr[2], &dest_adr_vals, EProgCounter() + 2 + src_adr_vals.count, MModReg | MModMem | imm_mask(code)))
1169
    {
1170
      append_word((code & 0170000) | (src_adr_vals.mode << 6) | dest_adr_vals.mode);
1171
      append_adr_vals(&src_adr_vals);
1172
      append_adr_vals(&dest_adr_vals);
1173
    }
1174
  }
1175
}
1176
 
1177
/*!------------------------------------------------------------------------
1178
 * \fn     decode_eis(Word code)
1179
 * \brief  handle EIS instructions
1180
 * \param  code machine code
1181
 * ------------------------------------------------------------------------ */
1182
 
1183
static void decode_eis(Word code)
1184
{
1185
  if (ChkArgCnt(2, 2) && check_cpu_ext(e_ext_eis))
1186
  {
1187
    adr_vals_t src_adr_vals, dest_adr_vals;
1188
 
1189
    op_size = eSymbolSize16Bit;
1190
    if (decode_adr(&ArgStr[1], &src_adr_vals, EProgCounter() + 2, MModReg | MModMem | MModImm)
1191
     && decode_adr(&ArgStr[2], &dest_adr_vals, EProgCounter() + 2 + src_adr_vals.count, MModReg))
1192
    {
1193
      append_word((code & 0177000) | ((dest_adr_vals.mode & 7) << 6) | src_adr_vals.mode);
1194
      append_adr_vals(&src_adr_vals);
1195
    }
1196
  }
1197
}
1198
 
1199
/*!------------------------------------------------------------------------
1200
 * \fn     decode_reg_gen(Word code)
1201
 * \brief  handle instructions with one register and one general argument
1202
 * \param  code machine code
1203
 * ------------------------------------------------------------------------ */
1204
 
1205
static void decode_reg_gen(Word code)
1206
{
1207
  if (ChkArgCnt(2, 2))
1208
  {
1209
    adr_vals_t reg_adr_vals, dest_adr_vals;
1210
 
1211
    op_size = eSymbolSize16Bit;
1212
    if (decode_adr(&ArgStr[1], &reg_adr_vals, EProgCounter() + 2, MModReg)
1213
     && decode_adr(&ArgStr[2], &dest_adr_vals, EProgCounter() + 2 + reg_adr_vals.count, MModReg | MModMem | MModImm))
1214
    {
1215
      append_word((code & 0177000) | ((reg_adr_vals.mode & 7) << 6) | dest_adr_vals.mode);
1216
      append_adr_vals(&dest_adr_vals);
1217
    }
1218
  }
1219
}
1220
 
1221
/*!------------------------------------------------------------------------
1222
 * \fn     decode_xor(Word code)
1223
 * \brief  handle XOR instruction
1224
 * \param  code machine code
1225
 * ------------------------------------------------------------------------ */
1226
 
1227
static void decode_xor(Word code)
1228
{
1229
  if (ChkArgCnt(2, 2) && check_cpu_ext(e_ext_xor))
1230
  {
1231
    adr_vals_t src_adr_vals, dest_adr_vals;
1232
 
1233
    op_size = eSymbolSize16Bit;
1234
    if (decode_adr(&ArgStr[1], &src_adr_vals, EProgCounter() + 2, MModReg)
1235
     && decode_adr(&ArgStr[2], &dest_adr_vals, EProgCounter() + 2 + src_adr_vals.count, MModReg | MModMem | imm_mask(code)))
1236
    {
1237
      append_word((code & 0177000) | ((src_adr_vals.mode & 7) << 6) | dest_adr_vals.mode);
1238
      append_adr_vals(&dest_adr_vals);
1239
    }
1240
  }
1241
}
1242
 
1243
/*!------------------------------------------------------------------------
1244
 * \fn     decode_fis(Word code)
1245
 * \brief  handle FIS instructions
1246
 * \param  code machine code
1247
 * ------------------------------------------------------------------------ */
1248
 
1249
static void decode_fis(Word code)
1250
{
1251
  adr_vals_t reg_adr_vals;
1252
 
1253
  if (ChkArgCnt(1, 1)
1254
   && check_cpu_ext(e_ext_fis)
1255
   && decode_adr(&ArgStr[1], &reg_adr_vals, EProgCounter() + 2, MModReg))
1256
    append_word((code & 0177770) | (reg_adr_vals.mode & 7));
1257
}
1258
 
1259
/*!------------------------------------------------------------------------
1260
 * \fn     decode_branch(Word code)
1261
 * \brief  handle branch instructions
1262
 * \param  code machine code
1263
 * ------------------------------------------------------------------------ */
1264
 
1265
static void decode_branch(Word code)
1266
{
1267
  if (ChkArgCnt(1, 1))
1268
  {
1269
    tEvalResult eval_result;
1270
    LongInt dist = EvalStrIntExpressionWithResult(&ArgStr[1], UInt16, &eval_result) - (EProgCounter() + 2);
1271
 
1272
    if (eval_result.OK)
1273
    {
1274
      if ((dist & 1) && !mFirstPassUnknownOrQuestionable(eval_result.Flags)) WrStrErrorPos(ErrNum_DistIsOdd, &ArgStr[1]);
1275
      else
1276
      {
1277
        dist /= 2;
1278
        if (!RangeCheck(dist, SInt8) && !mFirstPassUnknownOrQuestionable(eval_result.Flags)) WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[1]);
1279
        else
1280
          append_word((code & 0xff00) | (dist & 0x00ff));
1281
      }
1282
    }
1283
  }
1284
}
1285
 
1286
/*!------------------------------------------------------------------------
1287
 * \fn     decode_sob(Word code)
1288
 * \brief  handle SOB instruction
1289
 * \param  code machine code
1290
 * ------------------------------------------------------------------------ */
1291
 
1292
static void decode_sob(Word code)
1293
{
1294
  adr_vals_t reg_adr_vals;
1295
 
1296
  if (ChkArgCnt(2, 2)
1297
   && check_cpu_ext(e_ext_sob_sxt)
1298
   && decode_adr(&ArgStr[1], &reg_adr_vals, EProgCounter() + 2, MModReg))
1299
  {
1300
    tEvalResult eval_result;
1301
    LongInt dist = EvalStrIntExpressionWithResult(&ArgStr[2], UInt16, &eval_result) - (EProgCounter() + 2);
1302
 
1303
    if ((dist & 1) && !mFirstPassUnknownOrQuestionable(eval_result.Flags)) WrStrErrorPos(ErrNum_DistIsOdd, &ArgStr[1]);
1304
    else
1305
    {
1306
      dist /= 2;
1307
      if (((dist > 0) || (dist < -63)) && !mFirstPassUnknownOrQuestionable(eval_result.Flags)) WrStrErrorPos(ErrNum_JmpDistTooBig, &ArgStr[1]);
1308
      else
1309
        append_word((code & 0177000) | ((reg_adr_vals.mode & 7) << 6) | ((-dist) & 077));
1310
    }
1311
  }
1312
}
1313
 
1314
/*!------------------------------------------------------------------------
1315
 * \fn     decode_jmp(Word code)
1316
 * \brief  handle JMP instruction
1317
 * \param  code machine code
1318
 * ------------------------------------------------------------------------ */
1319
 
1320
static void decode_jmp(Word code)
1321
{
1322
  if (ChkArgCnt(1, 1))
1323
  {
1324
    adr_vals_t adr_vals;
1325
 
1326
    op_size = eSymbolSize16Bit;
1327
    if (decode_adr(&ArgStr[1], &adr_vals, EProgCounter() + 2, MModMem | MModImm))
1328
    {
1329
      append_word((code & 0177700) | adr_vals.mode);
1330
      append_adr_vals(&adr_vals);
1331
    }
1332
  }
1333
}
1334
 
1335
/*!------------------------------------------------------------------------
1336
 * \fn     decode_jsr_core(Word code, Word reg)
1337
 * \brief  JSR instruction common core
1338
 * \param  code machine code
1339
 * \param  reg register operand
1340
 * ------------------------------------------------------------------------ */
1341
 
1342
static void decode_jsr_core(Word code, Word reg)
1343
{
1344
  adr_vals_t addr_adr_vals;
1345
 
1346
  op_size = eSymbolSize16Bit;
1347
  if (decode_adr(&ArgStr[ArgCnt], &addr_adr_vals, EProgCounter() + 2, (is_wd16() ? 0 : MModReg) | MModMem | MModImm))
1348
  {
1349
    append_word((code & 0177000) | ((reg & 7) << 6) | addr_adr_vals.mode);
1350
    append_adr_vals(&addr_adr_vals);
1351
  }
1352
}
1353
 
1354
/*!------------------------------------------------------------------------
1355
 * \fn     decode_jsr(Word code)
1356
 * \brief  handle JSR instruction
1357
 * \param  code machine code
1358
 * ------------------------------------------------------------------------ */
1359
 
1360
static void decode_jsr(Word code)
1361
{
1362
  if (ChkArgCnt(2, 2))
1363
  {
1364
    adr_vals_t reg_adr_vals;
1365
 
1366
    op_size = eSymbolSize16Bit;
1367
    if (decode_adr(&ArgStr[1], &reg_adr_vals, EProgCounter() + 2, MModReg))
1368
      decode_jsr_core(code, reg_adr_vals.mode & 7);
1369
  }
1370
}
1371
 
1372
/*!------------------------------------------------------------------------
1373
 * \fn     decode_call(Word code)
1374
 * \brief  handle CALL instruction
1375
 * \param  code machine code
1376
 * ------------------------------------------------------------------------ */
1377
 
1378
static void decode_call(Word code)
1379
{
1380
  if (ChkArgCnt(1, 1))
1381
    decode_jsr_core(code, REG_PC);
1382
}
1383
 
1384
/*!------------------------------------------------------------------------
1385
 * \fn     decode_rts(Word code)
1386
 * \brief  handle RTS instruction
1387
 * \param  code machine code
1388
 * ------------------------------------------------------------------------ */
1389
 
1390
static void decode_rts(Word code)
1391
{
1392
  if (ChkArgCnt(1, 1))
1393
  {
1394
    adr_vals_t reg_adr_vals;
1395
 
1396
    op_size = eSymbolSize16Bit;
1397
    if (decode_adr(&ArgStr[1], &reg_adr_vals, EProgCounter() + 2, MModReg))
1398
      append_word((code & 0177770) | (reg_adr_vals.mode & 7));
1399
  }
1400
}
1401
 
1402
/*!------------------------------------------------------------------------
1403
 * \fn     decode_imm6(Word code)
1404
 * \brief  handle instructions with 6 bit numeric argument
1405
 * \param  code machine code
1406
 * ------------------------------------------------------------------------ */
1407
 
1408
static void decode_imm6(Word code)
1409
{
1410
  if (ChkArgCnt(1, 1))
1411
  {
1412
    Boolean ok;
1413
    Word num = EvalStrIntExpression(&ArgStr[1], UInt6, &ok);
1414
 
1415
    if (ok)
1416
      append_word(code | (num & 63));
1417
  }
1418
}
1419
 
1420
/*!------------------------------------------------------------------------
1421
 * \fn     decode_mark(Word code)
1422
 * \brief  handle MARK instruction
1423
 * \param  code machine code
1424
 * ------------------------------------------------------------------------ */
1425
 
1426
static void decode_mark(Word code)
1427
{
1428
  if (check_cpu_ext(e_ext_mark))
1429
    decode_imm6(code);
1430
}
1431
 
1432
/*!------------------------------------------------------------------------
1433
 * \fn     decode_imm4p1_reg(Word code)
1434
 * \brief  handle instructions with 4 bit immediate and register argument
1435
 * \param  code machine code
1436
 * ------------------------------------------------------------------------ */
1437
 
1438
static void decode_imm4p1_reg(Word code)
1439
{
1440
  adr_vals_t reg_adr_vals;
1441
 
1442
  if (ChkArgCnt(2, 2)
1443
   && decode_adr(&ArgStr[2], &reg_adr_vals, EProgCounter() + 2, MModReg))
1444
  {
1445
    tEvalResult eval_result;
1446
    Word imm_val = EvalStrIntExpressionWithResult(&ArgStr[1], UInt5, &eval_result);
1447
 
1448
    if (eval_result.OK)
1449
    {
1450
      if (mFirstPassUnknownOrQuestionable(eval_result.Flags))
1451
        imm_val = 1;
1452
      if (ChkRange(imm_val, 1, 16))
1453
        append_word(code | ((reg_adr_vals.mode & 7) << 6) | ((imm_val - 1) & 15));
1454
    }
1455
  }
1456
}
1457
 
1458
/*!------------------------------------------------------------------------
1459
 * \fn     decode_spl(Word code)
1460
 * \brief  handle SPL instruction
1461
 * \param  code machine code
1462
 * ------------------------------------------------------------------------ */
1463
 
1464
static void decode_spl(Word code)
1465
{
1466
  if (ChkArgCnt(1, 1) && check_cpu_ext(e_ext_spl))
1467
  {
1468
    Boolean ok;
1469
    Word num = EvalStrIntExpression(&ArgStr[1], UInt3, &ok);
1470
 
1471
    if (ok)
1472
      append_word(code | (num & 7));
1473
  }
1474
}
1475
 
1476
/*!------------------------------------------------------------------------
1477
 * \fn     decode_trap(Word code)
1478
 * \brief  handle trap instructions
1479
 * \param  code machine code
1480
 * ------------------------------------------------------------------------ */
1481
 
1482
static void decode_trap(Word code)
1483
{
1484
  if (ChkArgCnt(0, 1))
1485
  {
1486
    Boolean ok = True;
1487
    Word num = (ArgCnt >= 1) ? EvalStrIntExpression(&ArgStr[1], UInt8, &ok) : 0;
1488
 
1489
    if (ok)
1490
      append_word(code | (num & 255));
1491
  }
1492
}
1493
 
1494
/*!------------------------------------------------------------------------
1495
 * \fn     decode_flags(Word code)
1496
 * \brief  handle generic flag set/clear instructions
1497
 * \param  code machine code
1498
 * ------------------------------------------------------------------------ */
1499
 
1500
static void decode_flags(Word code)
1501
{
1502
  if (ChkArgCnt(1, 1))
1503
  {
1504
    Boolean ok = True;
1505
    Word num = EvalStrIntExpression(&ArgStr[1], UInt4, &ok);
1506
 
1507
    if (ok)
1508
      append_word(code | (num & 15));
1509
  }
1510
}
1511
 
1512
/*!------------------------------------------------------------------------
1513
 * \fn     decode_lcc(Word code)
1514
 * \brief  handle LCC instruction (WD16)
1515
 * \param  code machine code
1516
 * ------------------------------------------------------------------------ */
1517
 
1518
static void decode_lcc(Word code)
1519
{
1520
  if (ChkArgCnt(1, 1))
1521
  {
1522
    Boolean ok;
1523
    Word num = EvalStrIntExpression(&ArgStr[1], UInt4, &ok);
1524
 
1525
    if (ok)
1526
      append_word(code | (num & 15));
1527
  }
1528
}
1529
 
1530
/*!------------------------------------------------------------------------
1531
 * \fn     decode_format11(Word code)
1532
 * \brief  handle format 11 instructions
1533
 * \param  code machine code
1534
 * ------------------------------------------------------------------------ */
1535
 
1536
static Boolean decode_adr_01(tStrComp *p_arg, adr_vals_t *p_vals)
1537
{
1538
  if (!decode_adr(p_arg, p_vals, EProgCounter() + 2, MModReg | MModMem))
1539
    return False;
1540
 
1541
  switch (p_vals->mode & 070)
1542
  {
1543
    case 010:
1544
      p_vals->mode = (p_vals->mode & 007) | 000;
1545
      break;
1546
    case 070:
1547
      if (p_vals->vals[0] == 0)
1548
      {
1549
        p_vals->count = 0;
1550
        p_vals->mode = (p_vals->mode & 007) | 010;
1551
        break;
1552
      }
1553
      /* else fall-through */
1554
    default:
1555
      WrStrErrorPos(ErrNum_InvAddrMode, p_arg);
1556
      reset_adr_vals(p_vals);
1557
      return False;
1558
  }
1559
  return True;
1560
}
1561
 
1562
static void decode_format11(Word code)
1563
{
1564
  adr_vals_t src_adr_vals, dest_adr_vals;
1565
 
1566
  if (ChkArgCnt(2, 2)
1567
   && decode_adr_01(&ArgStr[1], &src_adr_vals)
1568
   && decode_adr_01(&ArgStr[2], &dest_adr_vals))
1569
    append_word(code | ((src_adr_vals.mode & 15) << 4) | (dest_adr_vals.mode& 15));
1570
}
1571
 
1572
 
1573
/*!------------------------------------------------------------------------
1574
 * \fn     decode_pseudo(void)
1575
 * \brief  handle pseudo instructions
1576
 * \return True if handled
1577
 * ------------------------------------------------------------------------ */
1578
 
1579
static Boolean decode_pseudo(void)
1580
{
1581
  if (Memo("REG"))
1582
  {
1583
    if (LabPart.str.p_str[0])
1584
      CodeREG(0);
1585
    else if (ChkArgCnt(1, 1))
1586
    {
1587
      Boolean IsON;
1588
 
1589
      if (CheckONOFFArg(&ArgStr[1], &IsON))
1590
        SetFlag(&default_regsyms, default_regsyms_name, IsON);
1591
    }
1592
    return True;
1593
  }
1594
 
1595
  if (Memo("BYTE"))
1596
  {
1597
    DecodeIntelDB(eIntPseudoFlag_DECFormat | eIntPseudoFlag_AllowString);
1598
    return True;
1599
  }
1600
 
1601
  if (Memo("WORD"))
1602
  {
1603
    DecodeIntelDW(eIntPseudoFlag_AllowInt | eIntPseudoFlag_AllowString | eIntPseudoFlag_DECFormat);
1604
    return True;
1605
  }
1606
 
1607
  if (is_wd16())
1608
  {
1609
    if (Memo("FLT3"))
1610
    {
1611
      DecodeIntelDM(eIntPseudoFlag_AllowFloat | eIntPseudoFlag_DECFormat);
1612
      return True;
1613
    }
1614
  }
1615
  {
1616
    if (Memo("FLT2"))
1617
    {
1618
      DecodeIntelDD(eIntPseudoFlag_AllowFloat | eIntPseudoFlag_DECFormat);
1619
      return True;
1620
    }
1621
 
1622
    if (Memo("FLT4"))
1623
    {
1624
      DecodeIntelDQ(eIntPseudoFlag_AllowFloat | eIntPseudoFlag_DECFormat);
1625
      return True;
1626
    }
1627
  }
1628
 
1629
  if (Memo("PRWINS"))
1630
  {
1631
    cpu_2_phys_area_dump(SegCode, stdout);
1632
    return True;
1633
  }
1634
 
1635
  return False;
1636
}
1637
 
1638
/*--------------------------------------------------------------------------*/
1639
/* Memory Management */
1640
 
1641
/*!------------------------------------------------------------------------
1642
 * \fn     update_apr(void)
1643
 * \brief  compute the CPU -> physical mapping from the current APR values
1644
 * ------------------------------------------------------------------------ */
1645
 
1646
static void update_apr(void)
1647
{
1648
  int z;
1649
  LargeWord base, size;
1650
  Word acf;
1651
 
1652
  cpu_2_phys_area_clear(SegCode);
1653
  for (z = 0, base = 0; z < APR_COUNT; z++, base += 0x2000)
1654
  {
1655
    /* page at least read only? */
1656
 
1657
    acf = reg_pdr[z] & 7;
1658
    if ((acf == 00) || (acf == 03) || (acf == 07))
1659
      continue;
1660
 
1661
    /* extract size field */
1662
 
1663
    size = (reg_pdr[z] >> 8) & 0xff;
1664
 
1665
    /* expand downward -> size field is 2s complement of number of blocks */
1666
 
1667
    if (reg_pdr[z] & 0x08)
1668
    {
1669
      size = ((size ^ 0xff) + 1) << 6;
1670
      cpu_2_phys_area_add(SegCode, base + 0x2000 - size, (reg_par[z] << 6) + 0x2000 - size, size);
1671
    }
1672
 
1673
    /* expand upward -> size field is highest block number */
1674
 
1675
    else
1676
    {
1677
      size = ((size & 0x7f) + 1) << 6;
1678
      cpu_2_phys_area_add(SegCode, base, reg_par[z] << 6, size);
1679
    }
1680
  }
1681
  cpu_2_phys_area_set_cpu_end(SegCode, 0xffff);
1682
}
1683
 
1684
/*--------------------------------------------------------------------------*/
1685
/* Instruction Lookup Table */
1686
 
1687
/*!------------------------------------------------------------------------
1688
 * \fn     init_branches(void)
1689
 * \brief  add branch instructions to lookup table (same on PDP-11 and WD16)
1690
 * ------------------------------------------------------------------------ */
1691
 
1692
static void init_branches(void)
1693
{
1694
  AddInstTable(InstTable, "BCC" , 0103000, decode_branch);
1695
  AddInstTable(InstTable, "BCS" , 0103400, decode_branch);
1696
  AddInstTable(InstTable, "BEQ" , 0001400, decode_branch);
1697
  AddInstTable(InstTable, "BGE" , 0002000, decode_branch);
1698
  AddInstTable(InstTable, "BGT" , 0003000, decode_branch);
1699
  AddInstTable(InstTable, "BHI" , 0101000, decode_branch);
1700
  AddInstTable(InstTable, "BHIS", 0103000, decode_branch);
1701
  AddInstTable(InstTable, "BLE" , 0003400, decode_branch);
1702
  AddInstTable(InstTable, "BLO" , 0103400, decode_branch);
1703
  AddInstTable(InstTable, "BLOS", 0101400, decode_branch);
1704
  AddInstTable(InstTable, "BLT" , 0002400, decode_branch);
1705
  AddInstTable(InstTable, "BMI" , 0100400, decode_branch);
1706
  AddInstTable(InstTable, "BNE" , 0001000, decode_branch);
1707
  AddInstTable(InstTable, "BPL" , 0100000, decode_branch);
1708
  AddInstTable(InstTable, "BR"  , 0000400, decode_branch);
1709
  AddInstTable(InstTable, "BVC" , 0102000, decode_branch);
1710
  AddInstTable(InstTable, "BVS" , 0102400, decode_branch);
1711
}
1712
 
1713
/*!------------------------------------------------------------------------
1714
 * \fn     init_fields_pdp11(void)
1715
 * \brief  create lookup table - PDP-11 encoding
1716
 * ------------------------------------------------------------------------ */
1717
 
1718
static void add_one_arg(const char *p_name, Word code)
1719
{
1720
  char name[10];
1721
 
1722
  AddInstTable(InstTable, p_name, code | CODE_FLAG_16BIT, decode_one_arg);
1723
  as_snprintf(name, sizeof(name), "%sB", p_name);
1724
  AddInstTable(InstTable, name, 0100000 | code, decode_one_arg);
1725
}
1726
 
1727
static void add_two_arg(const char *p_name, Word code)
1728
{
1729
  char name[10];
1730
 
1731
  AddInstTable(InstTable, p_name, code | CODE_FLAG_16BIT, decode_two_arg);
1732
  as_snprintf(name, sizeof(name), "%sB", p_name);
1733
  AddInstTable(InstTable, name, 0100000 | code, decode_two_arg);
1734
}
1735
 
1736
static void add_fp11(const char *p_name, Word code, InstProc proc)
1737
{
1738
  char name[10];
1739
 
1740
  as_snprintf(name, sizeof(name), "%sF", p_name);
1741
  AddInstTable(InstTable, name, code, proc);
1742
  as_snprintf(name, sizeof(name), "%sD", p_name);
1743
  AddInstTable(InstTable, name, code | CODE_FLAG_F64BIT, proc);
1744
}
1745
 
1746
static void add_cis(const char *p_name, Word code, InstProc inline_proc)
1747
{
1748
  char name[10];
1749
 
1750
  AddInstTable(InstTable, p_name, code, decode_cis_0);
1751
  as_snprintf(name, sizeof(name), "%sI", p_name);
1752
  AddInstTable(InstTable, name, code | 0000100, inline_proc);
1753
}
1754
 
1755
static void init_fields_pdp11(void)
1756
{
1757
  InstTable = CreateInstTable(201);
1758
  SetDynamicInstTable(InstTable);
1759
 
1760
  AddInstTable(InstTable, "BPT",   000003, decode_fixed);
1761
  AddInstTable(InstTable, "CCC",   000257, decode_fixed);
1762
  AddInstTable(InstTable, "CLC",   000241, decode_fixed);
1763
  AddInstTable(InstTable, "CLN",   000250, decode_fixed);
1764
  AddInstTable(InstTable, "CLV",   000242, decode_fixed);
1765
  AddInstTable(InstTable, "CLZ",   000244, decode_fixed);
1766
  AddInstTable(InstTable, "HALT",  000000, decode_fixed_sup);
1767
  AddInstTable(InstTable, "IOT",   000004, decode_fixed);
1768
  AddInstTable(InstTable, "MFPT",  000007, decode_mfpt);
1769
  AddInstTable(InstTable, "NOP",   NOPCode, decode_fixed);
1770
  AddInstTable(InstTable, "RESET", 000005, decode_fixed_sup);
1771
  AddInstTable(InstTable, "RTI",   000002, decode_fixed);
1772
  AddInstTable(InstTable, "RTT",   000006, decode_rtt);
1773
  AddInstTable(InstTable, "SCC",   000277, decode_fixed);
1774
  AddInstTable(InstTable, "SEC",   000261, decode_fixed);
1775
  AddInstTable(InstTable, "SEN",   000270, decode_fixed);
1776
  AddInstTable(InstTable, "SEV",   000262, decode_fixed);
1777
  AddInstTable(InstTable, "SEZ",   000264, decode_fixed);
1778
  AddInstTable(InstTable, "WAIT",  000001, decode_fixed);
1779
 
1780
  add_one_arg("ADC", 005500);
1781
  add_one_arg("ASL", 006300);
1782
  add_one_arg("ASR", 006200);
1783
  add_one_arg("CLR", 005000);
1784
  add_one_arg("COM", 005100);
1785
  add_one_arg("NEG", 005400);
1786
  add_one_arg("DEC", 005300);
1787
  add_one_arg("INC", 005200);
1788
  add_one_arg("ROL", 006100);
1789
  add_one_arg("ROR", 006000);
1790
  add_one_arg("SBC", 005600);
1791
  AddInstTable(InstTable, "SWAB", 000300, decode_one_arg);
1792
  AddInstTable(InstTable, "SXT", 006700, decode_sxt);
1793
  add_one_arg("TST", 005700);
1794
  AddInstTable(InstTable, "TSTSET", 0007200, decode_tstset);
1795
  AddInstTable(InstTable, "WRTLCK", 0007300, decode_wrtlck);
1796
  AddInstTable(InstTable, "CSM"   , 0007000 | CODE_FLAG_16BIT | CODE_FLAG_GEN_IMM, decode_csm);
1797
  AddInstTable(InstTable, "MFPD"  , 0006500 | CODE_FLAG_16BIT | CODE_FLAG_GEN_IMM, decode_mfp_mtp);
1798
  AddInstTable(InstTable, "MFPI"  , 0106500 | CODE_FLAG_16BIT | CODE_FLAG_GEN_IMM, decode_mfp_mtp);
1799
  AddInstTable(InstTable, "MFPS"  , 0106700 , decode_mfps_mtps);
1800
  AddInstTable(InstTable, "MTPD"  , 0006600 | CODE_FLAG_16BIT, decode_mfp_mtp);
1801
  AddInstTable(InstTable, "MTPI"  , 0106600 | CODE_FLAG_16BIT, decode_mfp_mtp);
1802
  AddInstTable(InstTable, "MTPS"  , 0106400 | CODE_FLAG_GEN_IMM, decode_mfps_mtps);
1803
 
1804
  AddInstTable(InstTable, "FADD"  , 0075000, decode_fis);
1805
  AddInstTable(InstTable, "FSUB"  , 0075010, decode_fis);
1806
  AddInstTable(InstTable, "FMUL"  , 0075020, decode_fis);
1807
  AddInstTable(InstTable, "FDIV"  , 0075030, decode_fis);
1808
 
1809
  add_fp11("ADD" , 0172000 | CODE_FLAG_GEN_IMM, decode_fp11_f1_f3);
1810
  add_fp11("CMP" , 0173400 | CODE_FLAG_GEN_IMM, decode_fp11_f1_f3);
1811
  add_fp11("DIV" , 0174400 | CODE_FLAG_GEN_IMM, decode_fp11_f1_f3);
1812
  AddInstTable(InstTable, "LDCDF", 0177400 | CODE_FLAG_GEN_IMM | CODE_FLAG_F64BIT, decode_fp11_f1_f3);
1813
  AddInstTable(InstTable, "LDCFD", 0177400 | CODE_FLAG_GEN_IMM, decode_fp11_f1_f3);
1814
  AddInstTable(InstTable, "LDCIF", 0177000 | CODE_FLAG_GEN_IMM | CODE_FLAG_16BIT, decode_fp11_f1_f3);
1815
  AddInstTable(InstTable, "LDCID", 0177000 | CODE_FLAG_GEN_IMM | CODE_FLAG_16BIT | CODE_FLAG_F64BIT, decode_fp11_f1_f3);
1816
  AddInstTable(InstTable, "LDCLF", 0177000 | CODE_FLAG_GEN_IMM | CODE_FLAG_32BIT, decode_fp11_f1_f3);
1817
  AddInstTable(InstTable, "LDCLD", 0177000 | CODE_FLAG_GEN_IMM | CODE_FLAG_32BIT | CODE_FLAG_F64BIT, decode_fp11_f1_f3);
1818
  AddInstTable(InstTable, "STCFI", 0175400 | CODE_FLAG_ARGSWAP | CODE_FLAG_16BIT, decode_fp11_f1_f3);
1819
  AddInstTable(InstTable, "STCDI", 0175400 | CODE_FLAG_ARGSWAP | CODE_FLAG_16BIT | CODE_FLAG_F64BIT, decode_fp11_f1_f3);
1820
  AddInstTable(InstTable, "STCFL", 0175400 | CODE_FLAG_ARGSWAP | CODE_FLAG_32BIT, decode_fp11_f1_f3);
1821
  AddInstTable(InstTable, "STCDL", 0175400 | CODE_FLAG_ARGSWAP | CODE_FLAG_32BIT | CODE_FLAG_F64BIT, decode_fp11_f1_f3);
1822
  AddInstTable(InstTable, "LDEXP", 0176400 | CODE_FLAG_GEN_IMM | CODE_FLAG_16BIT, decode_fp11_f1_f3);
1823
  AddInstTable(InstTable, "STEXP", 0175000 | CODE_FLAG_ARGSWAP | CODE_FLAG_16BIT, decode_fp11_f1_f3);
1824
  add_fp11("LD"  , 0172400 | CODE_FLAG_GEN_IMM, decode_fp11_f1_f3);
1825
  add_fp11("ST"  , 0174000 | CODE_FLAG_ARGSWAP, decode_fp11_f1_f3);
1826
  add_fp11("MOD" , 0171400 | CODE_FLAG_GEN_IMM, decode_fp11_f1_f3);
1827
  add_fp11("MUL" , 0171000 | CODE_FLAG_GEN_IMM, decode_fp11_f1_f3);
1828
  add_fp11("SUB" , 0173000 | CODE_FLAG_GEN_IMM, decode_fp11_f1_f3);
1829
 
1830
  add_fp11("ABS" , 0170600, decode_fp11_f2);
1831
  add_fp11("CLR" , 0170400, decode_fp11_f2);
1832
  add_fp11("NEG" , 0170700, decode_fp11_f2);
1833
  add_fp11("TST" , 0170500 | CODE_FLAG_GEN_IMM, decode_fp11_f2);
1834
 
1835
  AddInstTable(InstTable, "LDFPS", 0170100 | CODE_FLAG_16BIT | CODE_FLAG_GEN_IMM, decode_fp11_f4);
1836
  AddInstTable(InstTable, "STFPS", 0170200 | CODE_FLAG_16BIT, decode_fp11_f4);
1837
  AddInstTable(InstTable, "STST" , 0170300 | CODE_FLAG_32BIT, decode_fp11_f4);
1838
 
1839
  AddInstTable(InstTable, "CFCC", 0170000, decode_fp11_f5);
1840
  AddInstTable(InstTable, "SETF", 0170001, decode_fp11_f5);
1841
  AddInstTable(InstTable, "SETD", 0170011, decode_fp11_f5);
1842
  AddInstTable(InstTable, "SETI", 0170002, decode_fp11_f5);
1843
  AddInstTable(InstTable, "SETL", 0170012, decode_fp11_f5);
1844
 
1845
  add_two_arg("CMP", 0020000 | CODE_FLAG_GEN_IMM);
1846
  add_two_arg("BIC", 0040000);
1847
  add_two_arg("BIS", 0050000);
1848
  add_two_arg("BIT", 0030000 | CODE_FLAG_GEN_IMM);
1849
  add_two_arg("MOV", 0010000);
1850
  AddInstTable(InstTable, "ADD", 0060000 | CODE_FLAG_16BIT, decode_two_arg);
1851
  AddInstTable(InstTable, "SUB", 0160000 | CODE_FLAG_16BIT, decode_two_arg);
1852
 
1853
  AddInstTable(InstTable, "ASH" , 0072000, decode_eis);
1854
  AddInstTable(InstTable, "ASHC", 0073000, decode_eis);
1855
  AddInstTable(InstTable, "DIV" , 0071000, decode_eis);
1856
  AddInstTable(InstTable, "MUL" , 0070000, decode_eis);
1857
  AddInstTable(InstTable, "XOR" , 0074000, decode_xor);
1858
 
1859
  init_branches();
1860
  AddInstTable(InstTable, "SOB" , 0077000, decode_sob);
1861
 
1862
  AddInstTable(InstTable, "JMP" , 000100, decode_jmp);
1863
  AddInstTable(InstTable, "JSR" , 004000, decode_jsr);
1864
  AddInstTable(InstTable, "CALL", 004000, decode_call);
1865
  AddInstTable(InstTable, "RTS" , 000200, decode_rts);
1866
  AddInstTable(InstTable, "MARK", 006400, decode_mark);
1867
 
1868
  AddInstTable(InstTable, "EMT"  , 0104000, decode_trap);
1869
  AddInstTable(InstTable, "TRAP" , 0104400, decode_trap);
1870
  AddInstTable(InstTable, "SPL"  , 0000230, decode_spl);
1871
 
1872
  AddInstTable(InstTable, "C" , 000240, decode_flags);
1873
  AddInstTable(InstTable, "S" , 000260, decode_flags);
1874
 
1875
  add_cis("ADDN" , 0076050, decode_cis_3);
1876
  add_cis("ADDP" , 0076070, decode_cis_3);
1877
  add_cis("ASHN" , 0076056, decode_cis_2i);
1878
  add_cis("ASHP" , 0076076, decode_cis_2i);
1879
  add_cis("CMPC" , 0076044, decode_cis_2i);
1880
  add_cis("CMPN" , 0076052, decode_cis_2);
1881
  add_cis("CMPP" , 0076072, decode_cis_2);
1882
  add_cis("CVTLN", 0076057, decode_cis_2);
1883
  add_cis("CVTLP", 0076077, decode_cis_2);
1884
  add_cis("CVTNL", 0076053, decode_cis_2);
1885
  add_cis("CVTPL", 0076073, decode_cis_2);
1886
  add_cis("CVTNP", 0076055, decode_cis_2);
1887
  add_cis("CVTPN", 0076054, decode_cis_2);
1888
  add_cis("DIVP" , 0076075, decode_cis_3);
1889
  add_cis("LOCC" , 0076040, decode_cis_2i);
1890
  AddInstTable(InstTable, "L2DR" , 0076020, decode_cis_ld);
1891
  AddInstTable(InstTable, "L3DR" , 0076060, decode_cis_ld);
1892
  add_cis("MATC" , 0076045, decode_cis_2);
1893
  add_cis("MOVC" , 0076030, decode_cis_2i);
1894
  add_cis("MOVRC", 0076031, decode_cis_2i);
1895
  add_cis("MOVTC", 0076032, decode_cis_2i1);
1896
  add_cis("MULP" , 0076074, decode_cis_3);
1897
  add_cis("SCANC", 0076042, decode_cis_2);
1898
  add_cis("SKPC" , 0076041, decode_cis_1i);
1899
  add_cis("SPANC", 0076043, decode_cis_2);
1900
  add_cis("SUBN" , 0076051, decode_cis_3);
1901
  add_cis("SUBP" , 0076071, decode_cis_3);
1902
}
1903
 
1904
/*!------------------------------------------------------------------------
1905
 * \fn     init_fields_wd16(void)
1906
 * \brief  create lookup table - WD16 encoding
1907
 * ------------------------------------------------------------------------ */
1908
 
1909
static Boolean TrueFnc(void)
1910
{
1911
  return True;
1912
}
1913
 
1914
static void init_fields_wd16(void)
1915
{
1916
  InstTable = CreateInstTable(201);
1917
  SetDynamicInstTable(InstTable);
1918
 
1919
  AddInstTable(InstTable, "NOP"  , NOPCode, decode_fixed);
1920
  AddInstTable(InstTable, "RESET", 0x0001 , decode_fixed);
1921
  AddInstTable(InstTable, "IEN"  , 0x0002 , decode_fixed);
1922
  AddInstTable(InstTable, "IDS"  , 0x0003 , decode_fixed);
1923
  AddInstTable(InstTable, "HALT" , 0x0004 , decode_fixed);
1924
  AddInstTable(InstTable, "XCT"  , 0x0005 , decode_fixed);
1925
  AddInstTable(InstTable, "BPT"  , 0x0006 , decode_fixed);
1926
  AddInstTable(InstTable, "WFI"  , 0x0007 , decode_fixed);
1927
  AddInstTable(InstTable, "RSVC" , 0x0008 , decode_fixed);
1928
  AddInstTable(InstTable, "RRTT" , 0x0009 , decode_fixed);
1929
  AddInstTable(InstTable, "SAVE" , 0x000a , decode_fixed); SaveIsOccupiedFnc = TrueFnc;
1930
  AddInstTable(InstTable, "SAVS" , 0x000b , decode_fixed);
1931
  AddInstTable(InstTable, "REST" , 0x000c , decode_fixed);
1932
  AddInstTable(InstTable, "RRTN" , 0x000d , decode_fixed);
1933
  AddInstTable(InstTable, "RSTS" , 0x000e , decode_fixed);
1934
  AddInstTable(InstTable, "RTT"  , 0x000f , decode_fixed);
1935
 
1936
  AddInstTable(InstTable, "IAK"  , 0x0010 , decode_one_reg);
1937
  AddInstTable(InstTable, "RTN"  , 0x0018 , decode_one_reg);
1938
  AddInstTable(InstTable, "MSKO" , 0x0020 , decode_one_reg);
1939
  AddInstTable(InstTable, "PRTN" , 0x0028 , decode_one_reg);
1940
 
1941
  AddInstTable(InstTable, "LCC"  , 0x0030 , decode_lcc);
1942
 
1943
  AddInstTable(InstTable, "SVCA" , 0x0040 , decode_imm6);
1944
  AddInstTable(InstTable, "SVCB" , 0x0080 , decode_imm6);
1945
  AddInstTable(InstTable, "SVCC" , 0x00c0 , decode_imm6);
1946
 
1947
  AddInstTable(InstTable, "ADDI" , 0x0800 , decode_imm4p1_reg);
1948
  AddInstTable(InstTable, "SUBI" , 0x0810 , decode_imm4p1_reg);
1949
  AddInstTable(InstTable, "BICI" , 0x0820 , decode_imm4p1_reg);
1950
  AddInstTable(InstTable, "MOVI" , 0x0830 , decode_imm4p1_reg);
1951
  AddInstTable(InstTable, "SSRR" , 0x8800 , decode_imm4p1_reg);
1952
  AddInstTable(InstTable, "SSLR" , 0x8810 , decode_imm4p1_reg);
1953
  AddInstTable(InstTable, "SSRA" , 0x8820 , decode_imm4p1_reg);
1954
  AddInstTable(InstTable, "SSLA" , 0x8830 , decode_imm4p1_reg);
1955
  AddInstTable(InstTable, "SDRR" , 0x8e00 , decode_imm4p1_reg);
1956
  AddInstTable(InstTable, "SDLR" , 0x8e10 , decode_imm4p1_reg);
1957
  AddInstTable(InstTable, "SDRA" , 0x8e20 , decode_imm4p1_reg);
1958
  AddInstTable(InstTable, "SDLA" , 0x8e30 , decode_imm4p1_reg);
1959
 
1960
  add_one_arg("ROR", 0x0a00);
1961
  add_one_arg("ROL", 0x0a40);
1962
  add_one_arg("TST", 0x0a80);
1963
  add_one_arg("ASL", 0x0ac0);
1964
  add_one_arg("SET", 0x0b00); SetIsOccupiedFnc = TrueFnc;
1965
  add_one_arg("CLR", 0x0b40);
1966
  add_one_arg("ASR", 0x0b80);
1967
  add_one_arg("COM", 0x0c00);
1968
  add_one_arg("NEG", 0x0c40);
1969
  add_one_arg("INC", 0x0c80);
1970
  add_one_arg("DEC", 0x0cc0);
1971
  AddInstTable(InstTable, "SWAB" , 0x0bc0, decode_one_arg);
1972
  AddInstTable(InstTable, "SWAD" , 0x8bc0, decode_one_arg);
1973
  AddInstTable(InstTable, "IW2"  , 0x0d00, decode_one_arg);
1974
  AddInstTable(InstTable, "SXT"  , 0x0d40, decode_one_arg);
1975
  AddInstTable(InstTable, "TCALL", 0x0d80 | CODE_FLAG_GEN_IMM | CODE_FLAG_16BIT, decode_one_arg);
1976
  AddInstTable(InstTable, "TJMP" , 0x0dc0 | CODE_FLAG_GEN_IMM | CODE_FLAG_16BIT, decode_one_arg);
1977
  AddInstTable(InstTable, "LSTS" , 0x8d00 | CODE_FLAG_GEN_IMM | CODE_FLAG_16BIT, decode_one_arg);
1978
  AddInstTable(InstTable, "SSTS" , 0x8d40, decode_one_arg);
1979
  AddInstTable(InstTable, "ADC"  , 0x8d80, decode_one_arg);
1980
  AddInstTable(InstTable, "SBC"  , 0x8dc0, decode_one_arg);
1981
 
1982
  AddInstTable(InstTable, "MBWU" , 0x0e00, decode_two_reg);
1983
  AddInstTable(InstTable, "MBWD" , 0x0e40, decode_two_reg);
1984
  AddInstTable(InstTable, "MBBU" , 0x0e80, decode_two_reg);
1985
  AddInstTable(InstTable, "MBBD" , 0x0ec0, decode_two_reg);
1986
  AddInstTable(InstTable, "MBWA" , 0x0f00, decode_two_reg);
1987
  AddInstTable(InstTable, "MBBA" , 0x0f40, decode_two_reg);
1988
  AddInstTable(InstTable, "MABW" , 0x0f80, decode_two_reg);
1989
  AddInstTable(InstTable, "MABB" , 0x0fc0, decode_two_reg);
1990
 
1991
  AddInstTable(InstTable, "JSR" , 0x7000, decode_jsr);
1992
  AddInstTable(InstTable, "CALL", 0x7000, decode_call);
1993
  AddInstTable(InstTable, "LEA" , 0x7200, decode_jsr);
1994
  AddInstTable(InstTable, "JMP" , 0x7200, decode_call);
1995
  AddInstTable(InstTable, "ASH" , 0x7400, decode_reg_gen);
1996
  AddInstTable(InstTable, "SOB" , 0x7600, decode_sob);
1997
  AddInstTable(InstTable, "XCH" , 0x7800, decode_reg_gen);
1998
  AddInstTable(InstTable, "ASHC", 0x7a00, decode_reg_gen);
1999
  AddInstTable(InstTable, "MUL" , 0x7c00, decode_reg_gen);
2000
  AddInstTable(InstTable, "DIV" , 0x7e00, decode_reg_gen);
2001
 
2002
  AddInstTable(InstTable, "ADD" , 0x1000 | CODE_FLAG_16BIT, decode_two_arg);
2003
  AddInstTable(InstTable, "SUB" , 0x2000 | CODE_FLAG_16BIT, decode_two_arg);
2004
  AddInstTable(InstTable, "AND" , 0x3000 | CODE_FLAG_16BIT, decode_two_arg);
2005
  AddInstTable(InstTable, "BIC" , 0x4000 | CODE_FLAG_16BIT, decode_two_arg);
2006
  AddInstTable(InstTable, "BIS" , 0x5000 | CODE_FLAG_16BIT, decode_two_arg);
2007
  AddInstTable(InstTable, "XOR" , 0x6000 | CODE_FLAG_16BIT, decode_two_arg);
2008
  AddInstTable(InstTable, "CMP" , 0x9000 | CODE_FLAG_GEN_IMM | CODE_FLAG_16BIT, decode_two_arg);
2009
  AddInstTable(InstTable, "BIT" , 0xa000 | CODE_FLAG_GEN_IMM | CODE_FLAG_16BIT, decode_two_arg);
2010
  AddInstTable(InstTable, "MOV" , 0xb000 | CODE_FLAG_16BIT, decode_two_arg);
2011
  AddInstTable(InstTable, "CMPB", 0xc000 | CODE_FLAG_GEN_IMM, decode_two_arg);
2012
  AddInstTable(InstTable, "MOVB", 0xd000, decode_two_arg);
2013
  AddInstTable(InstTable, "BISB", 0xe000, decode_two_arg);
2014
 
2015
  AddInstTable(InstTable, "FADD", 0xf000, decode_format11);
2016
  AddInstTable(InstTable, "FSUB", 0xf100, decode_format11);
2017
  AddInstTable(InstTable, "FMUL", 0xf200, decode_format11);
2018
  AddInstTable(InstTable, "FDIV", 0xf300, decode_format11);
2019
  AddInstTable(InstTable, "FCMP", 0xf400, decode_format11);
2020
 
2021
  init_branches();
2022
}
2023
 
2024
/*!------------------------------------------------------------------------
2025
 * \fn     deinit_fields(void)
2026
 * \brief  destroy/cleanup lookup table
2027
 * ------------------------------------------------------------------------ */
2028
 
2029
static void deinit_fields(void)
2030
{
2031
  DestroyInstTable(InstTable);
2032
}
2033
 
2034
/*--------------------------------------------------------------------------*/
2035
/* Interface Functions */
2036
 
2037
/*!------------------------------------------------------------------------
2038
 * \fn     intern_symbol_pdp11(char *pArg, TempResult *pResult)
2039
 * \brief  handle built-in (register) symbols for PDP-11
2040
 * \param  p_arg source argument
2041
 * \param  p_result result buffer
2042
 * ------------------------------------------------------------------------ */
2043
 
2044
static void intern_symbol_pdp11(char *p_arg, TempResult *p_result)
2045
{
2046
  Word reg_num;
2047
 
2048
  if (decode_reg_core(p_arg, &reg_num, &p_result->DataSize))
2049
  {
2050
    p_result->Typ = TempReg;
2051
    p_result->Contents.RegDescr.Reg = reg_num;
2052
    p_result->Contents.RegDescr.Dissect = dissect_reg_pdp11;
2053
    p_result->Contents.RegDescr.compare = NULL;
2054
  }
2055
}
2056
 
2057
/*!------------------------------------------------------------------------
2058
 * \fn     make_code_pdp11(void)
2059
 * \brief  encode machine instruction
2060
 * ------------------------------------------------------------------------ */
2061
 
2062
static void make_code_pdp11(void)
2063
{
2064
  CodeLen = 0; DontPrint = False;
2065
  op_size = eSymbolSizeUnknown;
2066
 
2067
  /* to be ignored */
2068
 
2069
  if (Memo("")) return;
2070
 
2071
  /* Pseudo Instructions */
2072
 
2073
  if (decode_pseudo())
2074
    return;
2075
 
2076
  /* machine instructions may not begin on odd addresses */
2077
 
2078
  if (Odd(EProgCounter()))
2079
  {
2080
    if (DoPadding)
2081
      InsertPadding(1, False);
2082
    else
2083
      WrError(ErrNum_AddrNotAligned);
2084
  }
2085
 
2086
  if (!LookupInstTable(InstTable, OpPart.str.p_str))
2087
    WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
2088
}
2089
 
2090
/*!------------------------------------------------------------------------
2091
 * \fn     is_def_pdp11(void)
2092
 * \brief  check whether insn makes own use of label
2093
 * \return True if yes
2094
 * ------------------------------------------------------------------------ */
2095
 
2096
static Boolean is_def_pdp11(void)
2097
{
2098
  return Memo("REG");
2099
}
2100
 
2101
/*!------------------------------------------------------------------------
2102
 * \fn     initpass_pdp11(void)
2103
 * \brief  pre-initialize APRs to 1:1 mapping
2104
 * ------------------------------------------------------------------------ */
2105
 
2106
static void initpass_pdp11(void)
2107
{
2108
  /* if the PDP-11 target is never used, the memory never gets allocated: */
2109
 
2110
  if (reg_par)
2111
  {
2112
    int z;
2113
 
2114
    /* initialize APRs to 1:1 mapping */
2115
 
2116
    for (z = 0; z < APR_COUNT; z++)
2117
    {
2118
      reg_par[z] = z << 7;
2119
      reg_pdr[z] = 0x7f05;
2120
    }
2121
  }
2122
  ext_registered = 0;
2123
}
2124
 
2125
/*!------------------------------------------------------------------------
2126
 * \fn     switch_from_pdp11(void)
2127
 * \brief  deinitialize as target
2128
 * ------------------------------------------------------------------------ */
2129
 
2130
static void switch_from_pdp11(void)
2131
{
2132
  deinit_fields();
2133
  p_curr_cpu_props = NULL;
2134
}
2135
 
2136
/*!------------------------------------------------------------------------
2137
 * \fn     switch_to_pdp11(void *p_user)
2138
 * \brief  prepare to assemble code for this target
2139
 * ------------------------------------------------------------------------ */
2140
 
2141
static void switch_to_pdp11(void *p_user)
2142
{
2143
  static char *p_assume_reg_names = NULL;
2144
  static ASSUMERec *p_assumes = NULL;
2145
  const TFamilyDescr *p_descr;
2146
 
2147
  p_curr_cpu_props = (const cpu_props_t*)p_user;
2148
  p_descr = FindFamilyByName(is_wd16() ? "WD16" : "PDP-11");
2149
  TurnWords = False;
2150
  SetIntConstMode(eIntConstModeC);
2151
 
2152
  PCSymbol = "*";
2153
  HeaderID = p_descr->Id;
2154
  NOPCode = is_wd16() ? 0x0000 : 000240;
2155
  DivideChars = ",";
2156
 
2157
  ValidSegs = 1 << SegCode;
2158
  Grans[SegCode] = 1;
2159
  ListGrans[SegCode] = 2;
2160
  SegInits[SegCode] = 0;
2161
  SegLimits[SegCode] = IntTypeDefs[p_curr_cpu_props->addr_space].Max;
2162
 
2163
  MakeCode = make_code_pdp11;
2164
  IsDef = is_def_pdp11;
2165
  SwitchFrom = switch_from_pdp11;
2166
  InternSymbol = intern_symbol_pdp11;
2167
  DissectReg = dissect_reg_pdp11;
2168
  multi_char_le = True;
2169
 
2170
  if (!is_wd16())
2171
    onoff_supmode_add();
2172
  AddONOFF(DoPaddingName, &DoPadding, DoPaddingName, False);
2173
  if (p_curr_cpu_props->opt_flags & e_cpu_flag_eis)
2174
    onoff_ext_add(e_ext_eis, False);
2175
  if (p_curr_cpu_props->opt_flags & e_cpu_flag_fis)
2176
    onoff_ext_add(e_ext_fis, False);
2177
  if (p_curr_cpu_props->opt_flags & e_cpu_flag_fp11)
2178
    onoff_ext_add(e_ext_fp11, False);
2179
  if (p_curr_cpu_props->opt_flags & e_cpu_flag_cis)
2180
    onoff_ext_add(e_ext_cis, False);
2181
  if (!ext_test_and_set(0x80))
2182
    SetFlag(&default_regsyms, default_regsyms_name, True);
2183
 
2184
  /* create list of PDP-11 paging registers upon first use */
2185
 
2186
  if (!is_wd16())
2187
  {
2188
    if (!reg_par)
2189
    {
2190
      reg_par = (LongInt*)calloc(APR_COUNT, sizeof(*reg_par));
2191
      reg_pdr = (LongInt*)calloc(APR_COUNT, sizeof(*reg_pdr));
2192
      initpass_pdp11();
2193
    }
2194
    if (!p_assumes)
2195
    {
2196
      int apr_index, assume_index, l;
2197
      char *p_reg_name;
2198
 
2199
      if (!p_assume_reg_names)
2200
        p_assume_reg_names = (char*)malloc(ASSUME_COUNT * (4 + 1));
2201
      p_assumes = (ASSUMERec*)calloc(ASSUME_COUNT, sizeof(*p_assumes));
2202
 
2203
      p_reg_name = p_assume_reg_names;
2204
      for (apr_index = 0; apr_index < APR_COUNT; apr_index++)
2205
      {
2206
        l = as_snprintf(p_reg_name, 6, "PAR%c", apr_index + '0');
2207
        p_assumes[apr_index * 2].Name = p_reg_name;
2208
        p_assumes[apr_index * 2].Dest = &reg_par[apr_index];
2209
        p_reg_name += l + 1;
2210
        l = as_snprintf(p_reg_name, 6, "PDR%c", apr_index + '0');
2211
        p_assumes[apr_index * 2 + 1].Name = p_reg_name;
2212
        p_assumes[apr_index * 2 + 1].Dest = &reg_pdr[apr_index];
2213
        p_reg_name += l + 1;
2214
      }
2215
      for (assume_index = 0; assume_index < ASSUME_COUNT; assume_index++)
2216
      {
2217
        p_assumes[assume_index].Min = 0x0000;
2218
        p_assumes[assume_index].Max = 0xffff;
2219
        p_assumes[assume_index].NothingVal = 0x0000;
2220
        p_assumes[assume_index].pPostProc = update_apr;
2221
      }
2222
    }
2223
    pASSUMERecs = p_assumes;
2224
    ASSUMERecCnt = ASSUME_COUNT;
2225
    update_apr();
2226
  }
2227
 
2228
  if (is_wd16())
2229
    init_fields_wd16();
2230
  else
2231
    init_fields_pdp11();
2232
}
2233
 
2234
/*!------------------------------------------------------------------------
2235
 * \fn     codepdp11_init(void)
2236
 * \brief  register PDP-11 target
2237
 * ------------------------------------------------------------------------ */
2238
 
2239
/* NOTE: the KEV-11C implements DIS, which is actually a subset of CIS, but
2240
   since noone knows which subset, we just treat DIS as CIS: */
2241
 
2242
#define opt_cpu_flags_lsi11 (e_cpu_flag_eis | e_cpu_flag_fis | e_cpu_flag_cis)
2243
#define cpu_flags_lsi11 (e_cpu_flag_sob_sxt | e_cpu_flag_xor | e_cpu_flag_rtt | e_cpu_flag_mark | e_cpu_flag_mfps_mtps)
2244
 
2245
#define opt_cpu_flags_f11 (e_cpu_flag_fp11)
2246
#define cpu_flags_f11 (e_cpu_flag_sob_sxt | e_cpu_flag_mark | e_cpu_flag_rtt | e_cpu_flag_xor | e_cpu_flag_mfpt | e_cpu_flag_eis | e_cpu_flag_mfp_mtp | e_cpu_flag_mfps_mtps)
2247
 
2248
#define opt_cpu_flags_t11 0
2249
#define cpu_flags_t11 (e_cpu_flag_sob_sxt | e_cpu_flag_rtt | e_cpu_flag_mfps_mtps)
2250
 
2251
#define opt_cpu_flags_j11 0
2252
#define cpu_flags_j11 (e_cpu_flag_eis | e_cpu_flag_fp11 | e_cpu_flag_sob_sxt | e_cpu_flag_xor | e_cpu_flag_rtt | e_cpu_flag_mark | e_cpu_flag_mfpt | e_cpu_flag_mfp_mtp | e_cpu_flag_mfps_mtps | e_cpu_flag_spl | e_cpu_flag_csm | e_cpu_flag_wrtlck | e_cpu_flag_tstset)
2253
 
2254
static const cpu_props_t cpu_props[] =
2255
{
2256
  {      "PDP-11/03" , UInt16, opt_cpu_flags_lsi11              , cpu_flags_lsi11 },
2257
  {      "PDP-11/04" , UInt16, 0                                , e_cpu_flag_rtt },
2258
  {      "PDP-11/05" , UInt16, 0                                , 0 }, /* OEM version of PDP-11/10 */
2259
  {      "PDP-11/10" , UInt16, 0                                , 0 },
2260
  {      "PDP-11/15" , UInt16, 0                                , 0 }, /* OEM version of PDP-11/20 */
2261
  {      "PDP-11/20" , UInt16, 0                                , 0 },
2262
  {      "PDP-11/23" , UInt22, opt_cpu_flags_f11                , cpu_flags_f11 },
2263
  {      "PDP-11/24" , UInt22, opt_cpu_flags_f11                , cpu_flags_f11 },
2264
  {      "PDP-11/34" , UInt18, e_cpu_flag_fp11                  ,                   e_cpu_flag_sob_sxt | e_cpu_flag_mark | e_cpu_flag_rtt | e_cpu_flag_eis | e_cpu_flag_xor                   | e_cpu_flag_mfp_mtp | e_cpu_flag_mfps_mtps },
2265
  {      "PDP-11/35" , UInt18, e_cpu_flag_eis | e_cpu_flag_fis  ,                   e_cpu_flag_sob_sxt | e_cpu_flag_mark | e_cpu_flag_rtt                  | e_cpu_flag_xor                   | e_cpu_flag_mfp_mtp }, /* OEM version of PDP-11/40 */
2266
  {      "PDP-11/40" , UInt18, e_cpu_flag_eis | e_cpu_flag_fis  ,                   e_cpu_flag_sob_sxt | e_cpu_flag_mark | e_cpu_flag_rtt                  | e_cpu_flag_xor                   | e_cpu_flag_mfp_mtp },
2267
  {      "PDP-11/44" , UInt22, e_cpu_flag_fp11 | e_cpu_flag_cis ,                   e_cpu_flag_sob_sxt | e_cpu_flag_mark | e_cpu_flag_rtt | e_cpu_flag_eis | e_cpu_flag_xor | e_cpu_flag_mfpt | e_cpu_flag_mfp_mtp | e_cpu_flag_spl | e_cpu_flag_csm },
2268
  {      "PDP-11/45" , UInt18, e_cpu_flag_fp11                  ,                   e_cpu_flag_sob_sxt | e_cpu_flag_mark | e_cpu_flag_rtt | e_cpu_flag_eis | e_cpu_flag_xor                                        | e_cpu_flag_spl },
2269
  {      "PDP-11/50" , UInt18, e_cpu_flag_fp11                  ,                   e_cpu_flag_sob_sxt | e_cpu_flag_mark | e_cpu_flag_rtt | e_cpu_flag_eis | e_cpu_flag_xor                                        | e_cpu_flag_spl },
2270
  { "MicroPDP-11/53" , UInt22, opt_cpu_flags_j11                , cpu_flags_j11 },
2271
  {      "PDP-11/55" , UInt18, e_cpu_flag_fp11                  ,                   e_cpu_flag_sob_sxt | e_cpu_flag_mark | e_cpu_flag_rtt | e_cpu_flag_eis | e_cpu_flag_xor                                        | e_cpu_flag_spl },
2272
  {      "PDP-11/60" , UInt18, 0                                , e_cpu_flag_fp11 | e_cpu_flag_sob_sxt | e_cpu_flag_mark | e_cpu_flag_rtt | e_cpu_flag_eis | e_cpu_flag_xor                   | e_cpu_flag_mfp_mtp },
2273
  {      "PDP-11/70" , UInt22, e_cpu_flag_fp11                  ,                   e_cpu_flag_sob_sxt | e_cpu_flag_mark | e_cpu_flag_rtt | e_cpu_flag_eis | e_cpu_flag_xor                   | e_cpu_flag_mfp_mtp | e_cpu_flag_spl },
2274
  { "MicroPDP-11/73" , UInt22, opt_cpu_flags_j11                , cpu_flags_j11 },
2275
  { "MicroPDP-11/83" , UInt22, opt_cpu_flags_j11                , cpu_flags_j11 },
2276
  {      "PDP-11/84" , UInt22, opt_cpu_flags_j11                , cpu_flags_j11 },
2277
  { "MicroPDP-11/93" , UInt22, opt_cpu_flags_j11                , cpu_flags_j11 },
2278
  {      "PDP-11/94" , UInt22, opt_cpu_flags_j11                , cpu_flags_j11 },
2279
  {           "T-11" , UInt16, opt_cpu_flags_t11                , cpu_flags_t11 },
2280
 
2281
  /* The WD16 is basically an LSI-11 with
2282
     - different microcode,
2283
     - different opcodes,
2284
     - different floating point format
2285
     but same architecture: */
2286
 
2287
  {           "WD16" , UInt16, 0                                , e_cpu_flag_wd16 | e_cpu_flag_sob_sxt },
2288
};
2289
 
2290
void codepdp11_init(void)
2291
{
2292
  const cpu_props_t *p_prop;
2293
 
2294
  for (p_prop = cpu_props; p_prop < cpu_props + as_array_size(cpu_props); p_prop++)
2295
    (void)AddCPUUserWithArgs(p_prop->name, switch_to_pdp11, (void*)p_prop, NULL, NULL);
2296
 
2297
  AddInitPassProc(initpass_pdp11);
2298
}