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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [gdb-5.3/] [sim/] [m68hc11/] [m68hc11_sim.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* m6811_cpu.c -- 68HC11&68HC12 CPU Emulation
2
   Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3
   Written by Stephane Carrez (stcarrez@nerim.fr)
4
 
5
This file is part of GDB, GAS, and the GNU binutils.
6
 
7
GDB, GAS, and the GNU binutils are free software; you can redistribute
8
them and/or modify them under the terms of the GNU General Public
9
License as published by the Free Software Foundation; either version
10
1, or (at your option) any later version.
11
 
12
GDB, GAS, and the GNU binutils are distributed in the hope that they
13
will be useful, but WITHOUT ANY WARRANTY; without even the implied
14
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15
the GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with this file; see the file COPYING.  If not, write to the Free
19
Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
 
21
#include "sim-main.h"
22
#include "sim-assert.h"
23
#include "sim-module.h"
24
#include "sim-options.h"
25
 
26
enum {
27
  OPTION_CPU_RESET = OPTION_START,
28
  OPTION_EMUL_OS,
29
  OPTION_CPU_CONFIG,
30
  OPTION_CPU_MODE
31
};
32
 
33
static DECLARE_OPTION_HANDLER (cpu_option_handler);
34
 
35
static const OPTION cpu_options[] =
36
{
37
  { {"cpu-reset", no_argument, NULL, OPTION_CPU_RESET },
38
      '\0', NULL, "Reset the CPU",
39
      cpu_option_handler },
40
 
41
  { {"emulos",    no_argument, NULL, OPTION_EMUL_OS },
42
      '\0', NULL, "Emulate some OS system calls (read, write, ...)",
43
      cpu_option_handler },
44
 
45
  { {"cpu-config", required_argument, NULL, OPTION_CPU_CONFIG },
46
      '\0', NULL, "Specify the initial CPU configuration register",
47
      cpu_option_handler },
48
 
49
  { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
50
};
51
 
52
 
53
static SIM_RC
54
cpu_option_handler (SIM_DESC sd, sim_cpu *cpu,
55
                    int opt, char *arg, int is_command)
56
{
57
  int val;
58
 
59
  cpu = STATE_CPU (sd, 0);
60
  switch (opt)
61
    {
62
    case OPTION_CPU_RESET:
63
      sim_board_reset (sd);
64
      break;
65
 
66
    case OPTION_EMUL_OS:
67
      cpu->cpu_emul_syscall = 1;
68
      break;
69
 
70
    case OPTION_CPU_CONFIG:
71
      if (sscanf(arg, "0x%x", &val) == 1
72
          || sscanf(arg, "%d", &val) == 1)
73
        {
74
          cpu->cpu_config = val;
75
          cpu->cpu_use_local_config = 1;
76
        }
77
      else
78
        cpu->cpu_use_local_config = 0;
79
      break;
80
 
81
    case OPTION_CPU_MODE:
82
      break;
83
    }
84
 
85
  return SIM_RC_OK;
86
}
87
 
88
 
89
void
90
cpu_call (sim_cpu *cpu, uint16 addr)
91
{
92
 
93
  cpu_set_pc (cpu, addr);
94
}
95
 
96
void
97
cpu_return (sim_cpu *cpu)
98
{
99
}
100
 
101
/* Set the stack pointer and re-compute the current frame.  */
102
void
103
cpu_set_sp (sim_cpu *cpu, uint16 val)
104
{
105
  cpu->cpu_regs.sp = val;
106
}
107
 
108
uint16
109
cpu_get_reg (sim_cpu* cpu, uint8 reg)
110
{
111
  switch (reg)
112
    {
113
    case 0:
114
      return cpu_get_x (cpu);
115
 
116
    case 1:
117
      return cpu_get_y (cpu);
118
 
119
    case 2:
120
      return cpu_get_sp (cpu);
121
 
122
    case 3:
123
      return cpu_get_pc (cpu);
124
 
125
    default:
126
      return 0;
127
    }
128
}
129
 
130
uint16
131
cpu_get_src_reg (sim_cpu* cpu, uint8 reg)
132
{
133
  switch (reg)
134
    {
135
    case 0:
136
      return cpu_get_a (cpu);
137
 
138
    case 1:
139
      return cpu_get_b (cpu);
140
 
141
    case 2:
142
      return cpu_get_ccr (cpu);
143
 
144
    case 3:
145
      return cpu_get_tmp3 (cpu);
146
 
147
    case 4:
148
      return cpu_get_d (cpu);
149
 
150
    case 5:
151
      return cpu_get_x (cpu);
152
 
153
    case 6:
154
      return cpu_get_y (cpu);
155
 
156
    case 7:
157
      return cpu_get_sp (cpu);
158
 
159
    default:
160
      return 0;
161
    }
162
}
163
 
164
void
165
cpu_set_dst_reg (sim_cpu* cpu, uint8 reg, uint16 val)
166
{
167
  switch (reg)
168
    {
169
    case 0:
170
      cpu_set_a (cpu, val);
171
      break;
172
 
173
    case 1:
174
      cpu_set_b (cpu, val);
175
      break;
176
 
177
    case 2:
178
      cpu_set_ccr (cpu, val);
179
      break;
180
 
181
    case 3:
182
      cpu_set_tmp2 (cpu, val);
183
      break;
184
 
185
    case 4:
186
      cpu_set_d (cpu, val);
187
      break;
188
 
189
    case 5:
190
      cpu_set_x (cpu, val);
191
      break;
192
 
193
    case 6:
194
      cpu_set_y (cpu, val);
195
      break;
196
 
197
    case 7:
198
      cpu_set_sp (cpu, val);
199
      break;
200
 
201
    default:
202
      break;
203
    }
204
}
205
 
206
void
207
cpu_set_reg (sim_cpu* cpu, uint8 reg, uint16 val)
208
{
209
  switch (reg)
210
    {
211
    case 0:
212
      cpu_set_x (cpu, val);
213
      break;
214
 
215
    case 1:
216
      cpu_set_y (cpu, val);
217
      break;
218
 
219
    case 2:
220
      cpu_set_sp (cpu, val);
221
      break;
222
 
223
    case 3:
224
      cpu_set_pc (cpu, val);
225
      break;
226
 
227
    default:
228
      break;
229
    }
230
}
231
 
232
/* Returns the address of a 68HC12 indexed operand.
233
   Pre and post modifications are handled on the source register.  */
234
uint16
235
cpu_get_indexed_operand_addr (sim_cpu* cpu, int restrict)
236
{
237
  uint8 reg;
238
  uint16 sval;
239
  uint16 addr;
240
  uint8 code;
241
 
242
  code = cpu_fetch8 (cpu);
243
 
244
  /* n,r with 5-bit signed constant.  */
245
  if ((code & 0x20) == 0)
246
    {
247
      reg = (code >> 6) & 3;
248
      sval = (code & 0x1f);
249
      if (code & 0x10)
250
        sval |= 0xfff0;
251
 
252
      addr = cpu_get_reg (cpu, reg);
253
      addr += sval;
254
    }
255
 
256
  /* Auto pre/post increment/decrement.  */
257
  else if ((code & 0xc0) != 0xc0)
258
    {
259
      reg = (code >> 6) & 3;
260
      sval = (code & 0x0f);
261
      if (sval & 0x8)
262
        {
263
          sval |= 0xfff0;
264
        }
265
      else
266
        {
267
          sval = sval + 1;
268
        }
269
      addr = cpu_get_reg (cpu, reg);
270
      cpu_set_reg (cpu, reg, addr + sval);
271
      if ((code & 0x10) == 0)
272
        {
273
          addr += sval;
274
        }
275
    }
276
 
277
  /* [n,r] 16-bits offset indexed indirect.  */
278
  else if ((code & 0x07) == 3)
279
    {
280
      if (restrict)
281
        {
282
          return 0;
283
        }
284
      reg = (code >> 3) & 0x03;
285
      addr = cpu_get_reg (cpu, reg);
286
      addr += cpu_fetch16 (cpu);
287
      addr = memory_read16 (cpu, addr);
288
      cpu_add_cycles (cpu, 1);
289
    }
290
  else if ((code & 0x4) == 0)
291
    {
292
      if (restrict)
293
        {
294
          return 0;
295
        }
296
      reg = (code >> 3) & 0x03;
297
      addr = cpu_get_reg (cpu, reg);
298
      if (code & 0x2)
299
        {
300
          sval = cpu_fetch16 (cpu);
301
          cpu_add_cycles (cpu, 1);
302
        }
303
      else
304
        {
305
          sval = cpu_fetch8 (cpu);
306
          if (code & 0x1)
307
            sval |= 0xff00;
308
          cpu_add_cycles (cpu, 1);
309
        }
310
      addr += sval;
311
    }
312
  else
313
    {
314
      reg = (code >> 3) & 0x03;
315
      addr = cpu_get_reg (cpu, reg);
316
      switch (code & 3)
317
        {
318
        case 0:
319
          addr += cpu_get_a (cpu);
320
          break;
321
        case 1:
322
          addr += cpu_get_b (cpu);
323
          break;
324
        case 2:
325
          addr += cpu_get_d (cpu);
326
          break;
327
        case 3:
328
        default:
329
          addr += cpu_get_d (cpu);
330
          addr = memory_read16 (cpu, addr);
331
          cpu_add_cycles (cpu, 1);
332
          break;
333
        }
334
    }
335
 
336
  return addr;
337
}
338
 
339
uint8
340
cpu_get_indexed_operand8 (sim_cpu* cpu, int restrict)
341
{
342
  uint16 addr;
343
 
344
  addr = cpu_get_indexed_operand_addr (cpu, restrict);
345
  return memory_read8 (cpu, addr);
346
}
347
 
348
uint16
349
cpu_get_indexed_operand16 (sim_cpu* cpu, int restrict)
350
{
351
  uint16 addr;
352
 
353
  addr = cpu_get_indexed_operand_addr (cpu, restrict);
354
  return memory_read16 (cpu, addr);
355
}
356
 
357
void
358
cpu_move8 (sim_cpu *cpu, uint8 code)
359
{
360
  uint8 src;
361
  uint16 addr;
362
 
363
  switch (code)
364
    {
365
    case 0x0b:
366
      src = cpu_fetch8 (cpu);
367
      addr = cpu_fetch16 (cpu);
368
      break;
369
 
370
    case 0x08:
371
      addr = cpu_get_indexed_operand_addr (cpu, 1);
372
      src = cpu_fetch8 (cpu);
373
      break;
374
 
375
    case 0x0c:
376
      addr = cpu_fetch16 (cpu);
377
      src = memory_read8 (cpu, addr);
378
      addr = cpu_fetch16 (cpu);
379
      break;
380
 
381
    case 0x09:
382
      addr = cpu_get_indexed_operand_addr (cpu, 1);
383
      src = memory_read8 (cpu, cpu_fetch16 (cpu));
384
      break;
385
 
386
    case 0x0d:
387
      src = cpu_get_indexed_operand8 (cpu, 1);
388
      addr = cpu_fetch16 (cpu);
389
      break;
390
 
391
    case 0x0a:
392
      src = cpu_get_indexed_operand8 (cpu, 1);
393
      addr = cpu_get_indexed_operand_addr (cpu, 1);
394
      break;
395
 
396
    default:
397
      sim_engine_abort (CPU_STATE (cpu), cpu, 0,
398
                        "Invalid code 0x%0x -- internal error?", code);
399
      return;
400
    }
401
  memory_write8 (cpu, addr, src);
402
}
403
 
404
void
405
cpu_move16 (sim_cpu *cpu, uint8 code)
406
{
407
  uint16 src;
408
  uint16 addr;
409
 
410
  switch (code)
411
    {
412
    case 0x03:
413
      src = cpu_fetch16 (cpu);
414
      addr = cpu_fetch16 (cpu);
415
      break;
416
 
417
    case 0x00:
418
      addr = cpu_get_indexed_operand_addr (cpu, 1);
419
      src = cpu_fetch16 (cpu);
420
      break;
421
 
422
    case 0x04:
423
      addr = cpu_fetch16 (cpu);
424
      src = memory_read16 (cpu, addr);
425
      addr = cpu_fetch16 (cpu);
426
      break;
427
 
428
    case 0x01:
429
      addr = cpu_get_indexed_operand_addr (cpu, 1);
430
      src = memory_read16 (cpu, cpu_fetch16 (cpu));
431
      break;
432
 
433
    case 0x05:
434
      src = cpu_get_indexed_operand16 (cpu, 1);
435
      addr = cpu_fetch16 (cpu);
436
      break;
437
 
438
    case 0x02:
439
      src = cpu_get_indexed_operand16 (cpu, 1);
440
      addr = cpu_get_indexed_operand_addr (cpu, 1);
441
      break;
442
 
443
    default:
444
      sim_engine_abort (CPU_STATE (cpu), cpu, 0,
445
                        "Invalid code 0x%0x -- internal error?", code);
446
      return;
447
    }
448
  memory_write16 (cpu, addr, src);
449
}
450
 
451
int
452
cpu_initialize (SIM_DESC sd, sim_cpu *cpu)
453
{
454
  sim_add_option_table (sd, 0, cpu_options);
455
 
456
  memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
457
 
458
  cpu->cpu_absolute_cycle = 0;
459
  cpu->cpu_current_cycle  = 0;
460
  cpu->cpu_emul_syscall   = 1;
461
  cpu->cpu_running        = 1;
462
  cpu->cpu_stop_on_interrupt = 0;
463
  cpu->cpu_frequency = 8 * 1000 * 1000;
464
  cpu->cpu_use_elf_start = 0;
465
  cpu->cpu_elf_start     = 0;
466
  cpu->cpu_use_local_config = 0;
467
  cpu->cpu_config        = M6811_NOSEC | M6811_NOCOP | M6811_ROMON |
468
    M6811_EEON;
469
  interrupts_initialize (sd, cpu);
470
 
471
  cpu->cpu_is_initialized = 1;
472
  return 0;
473
}
474
 
475
 
476
/* Reinitialize the processor after a reset.  */
477
int
478
cpu_reset (sim_cpu *cpu)
479
{
480
  /* Initialize the config register.
481
     It is only initialized at reset time.  */
482
  memset (cpu->ios, 0, sizeof (cpu->ios));
483
  if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
484
    cpu->ios[M6811_INIT] = 0x1;
485
  else
486
    cpu->ios[M6811_INIT] = 0;
487
 
488
  /* Output compare registers set to 0xFFFF.  */
489
  cpu->ios[M6811_TOC1_H] = 0xFF;
490
  cpu->ios[M6811_TOC1_L] = 0xFF;
491
  cpu->ios[M6811_TOC2_H] = 0xFF;
492
  cpu->ios[M6811_TOC2_L] = 0xFF;
493
  cpu->ios[M6811_TOC3_H] = 0xFF;
494
  cpu->ios[M6811_TOC4_L] = 0xFF;
495
  cpu->ios[M6811_TOC5_H] = 0xFF;
496
  cpu->ios[M6811_TOC5_L] = 0xFF;
497
 
498
  /* Setup the processor registers.  */
499
  memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
500
  cpu->cpu_absolute_cycle = 0;
501
  cpu->cpu_current_cycle  = 0;
502
  cpu->cpu_is_initialized = 0;
503
 
504
  /* Reset interrupts.  */
505
  interrupts_reset (&cpu->cpu_interrupts);
506
 
507
  /* Reinitialize the CPU operating mode.  */
508
  cpu->ios[M6811_HPRIO] = cpu->cpu_mode;
509
  return 0;
510
}
511
 
512
/* Reinitialize the processor after a reset.  */
513
int
514
cpu_restart (sim_cpu *cpu)
515
{
516
  uint16 addr;
517
 
518
  /* Get CPU starting address depending on the CPU mode.  */
519
  if (cpu->cpu_use_elf_start == 0)
520
    {
521
      switch ((cpu->ios[M6811_HPRIO]) & (M6811_SMOD | M6811_MDA))
522
        {
523
          /* Single Chip  */
524
        default:
525
        case 0 :
526
          addr = memory_read16 (cpu, 0xFFFE);
527
          break;
528
 
529
          /* Expanded Multiplexed  */
530
        case M6811_MDA:
531
          addr = memory_read16 (cpu, 0xFFFE);
532
          break;
533
 
534
          /* Special Bootstrap  */
535
        case M6811_SMOD:
536
          addr = 0;
537
          break;
538
 
539
          /* Factory Test  */
540
        case M6811_MDA | M6811_SMOD:
541
          addr = memory_read16 (cpu, 0xFFFE);
542
          break;
543
        }
544
    }
545
  else
546
    {
547
      addr = cpu->cpu_elf_start;
548
    }
549
 
550
  /* Setup the processor registers.  */
551
  cpu->cpu_insn_pc  = addr;
552
  cpu->cpu_regs.pc  = addr;
553
  cpu->cpu_regs.ccr = M6811_X_BIT | M6811_I_BIT | M6811_S_BIT;
554
  cpu->cpu_absolute_cycle = 0;
555
  cpu->cpu_is_initialized = 1;
556
  cpu->cpu_current_cycle  = 0;
557
 
558
  cpu_call (cpu, addr);
559
 
560
  return 0;
561
}
562
 
563
void
564
print_io_reg_desc (SIM_DESC sd, io_reg_desc *desc, int val, int mode)
565
{
566
  while (desc->mask)
567
    {
568
      if (val & desc->mask)
569
        sim_io_printf (sd, "%s",
570
                       mode == 0 ? desc->short_name : desc->long_name);
571
      desc++;
572
    }
573
}
574
 
575
void
576
print_io_byte (SIM_DESC sd, const char *name, io_reg_desc *desc,
577
               uint8 val, uint16 addr)
578
{
579
  sim_io_printf (sd, "  %-9.9s @ 0x%04x 0x%02x ", name, addr, val);
580
  if (desc)
581
    print_io_reg_desc (sd, desc, val, 0);
582
}
583
 
584
void
585
cpu_ccr_update_tst8 (sim_cpu *proc, uint8 val)
586
{
587
  cpu_set_ccr_V (proc, 0);
588
  cpu_set_ccr_N (proc, val & 0x80 ? 1 : 0);
589
  cpu_set_ccr_Z (proc, val == 0 ? 1 : 0);
590
}
591
 
592
 
593
uint16
594
cpu_fetch_relbranch (sim_cpu *cpu)
595
{
596
  uint16 addr = (uint16) cpu_fetch8 (cpu);
597
 
598
  if (addr & 0x0080)
599
    {
600
      addr |= 0xFF00;
601
    }
602
  addr += cpu->cpu_regs.pc;
603
  return addr;
604
}
605
 
606
uint16
607
cpu_fetch_relbranch16 (sim_cpu *cpu)
608
{
609
  uint16 addr = cpu_fetch16 (cpu);
610
 
611
  addr += cpu->cpu_regs.pc;
612
  return addr;
613
}
614
 
615
/* Push all the CPU registers (when an interruption occurs).  */
616
void
617
cpu_push_all (sim_cpu *cpu)
618
{
619
  if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
620
    {
621
      cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.pc);
622
      cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.iy);
623
      cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.ix);
624
      cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.d);
625
      cpu_m68hc11_push_uint8 (cpu, cpu->cpu_regs.ccr);
626
    }
627
  else
628
    {
629
      cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.pc);
630
      cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.iy);
631
      cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.ix);
632
      cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.d);
633
      cpu_m68hc12_push_uint8 (cpu, cpu->cpu_regs.ccr);
634
    }
635
}
636
 
637
/* Simulation of the dbcc/ibcc/tbcc 68HC12 conditional branch operations.  */
638
void
639
cpu_dbcc (sim_cpu* cpu)
640
{
641
  uint8 code;
642
  uint16 addr;
643
  uint16 inc;
644
  uint16 reg;
645
 
646
  code = cpu_fetch8 (cpu);
647
  switch (code & 0xc0)
648
    {
649
    case 0x80: /* ibcc */
650
      inc = 1;
651
      break;
652
    case 0x40: /* tbcc */
653
      inc = 0;
654
      break;
655
    case 0:    /* dbcc */
656
      inc = -1;
657
      break;
658
    default:
659
      abort ();
660
      break;
661
    }
662
 
663
  addr = cpu_fetch8 (cpu);
664
  if (code & 0x10)
665
    addr |= 0xff00;
666
 
667
  addr += cpu_get_pc (cpu);
668
  reg = cpu_get_src_reg (cpu, code & 0x07);
669
  reg += inc;
670
 
671
  /* Branch according to register value.  */
672
  if ((reg != 0 && (code & 0x20)) || (reg == 0 && !(code & 0x20)))
673
    {
674
      cpu_set_pc (cpu, addr);
675
    }
676
  cpu_set_dst_reg (cpu, code & 0x07, reg);
677
}
678
 
679
void
680
cpu_exg (sim_cpu* cpu, uint8 code)
681
{
682
  uint8 r1, r2;
683
  uint16 src1;
684
  uint16 src2;
685
 
686
  r1 = (code >> 4) & 0x07;
687
  r2 = code & 0x07;
688
  if (code & 0x80)
689
    {
690
      src1 = cpu_get_src_reg (cpu, r1);
691
      src2 = cpu_get_src_reg (cpu, r2);
692
      if (r2 == 1 || r2 == 2)
693
        src2 |= 0xff00;
694
 
695
      cpu_set_dst_reg (cpu, r2, src1);
696
      cpu_set_dst_reg (cpu, r1, src2);
697
    }
698
  else
699
    {
700
      src1 = cpu_get_src_reg (cpu, r1);
701
 
702
      /* Sign extend the 8-bit registers (A, B, CCR).  */
703
      if ((r1 == 0 || r1 == 1 || r1 == 2) && (src1 & 0x80))
704
        src1 |= 0xff00;
705
 
706
      cpu_set_dst_reg (cpu, r2, src1);
707
    }
708
}
709
 
710
/* Handle special instructions.  */
711
void
712
cpu_special (sim_cpu *cpu, enum M6811_Special special)
713
{
714
  switch (special)
715
    {
716
    case M6811_RTI:
717
      {
718
        uint8 ccr;
719
 
720
        ccr = cpu_m68hc11_pop_uint8 (cpu);
721
        cpu_set_ccr (cpu, ccr);
722
        cpu_set_d (cpu, cpu_m68hc11_pop_uint16 (cpu));
723
        cpu_set_x (cpu, cpu_m68hc11_pop_uint16 (cpu));
724
        cpu_set_y (cpu, cpu_m68hc11_pop_uint16 (cpu));
725
        cpu_set_pc (cpu, cpu_m68hc11_pop_uint16 (cpu));
726
        cpu_return (cpu);
727
        break;
728
      }
729
 
730
    case M6812_RTI:
731
      {
732
        uint8 ccr;
733
 
734
        ccr = cpu_m68hc12_pop_uint8 (cpu);
735
        cpu_set_ccr (cpu, ccr);
736
        cpu_set_d (cpu, cpu_m68hc12_pop_uint16 (cpu));
737
        cpu_set_x (cpu, cpu_m68hc12_pop_uint16 (cpu));
738
        cpu_set_y (cpu, cpu_m68hc12_pop_uint16 (cpu));
739
        cpu_set_pc (cpu, cpu_m68hc12_pop_uint16 (cpu));
740
        cpu_return (cpu);
741
        break;
742
      }
743
 
744
    case M6811_WAI:
745
      /* In the ELF-start mode, we are in a special mode where
746
         the WAI corresponds to an exit.  */
747
      if (cpu->cpu_use_elf_start)
748
        {
749
          cpu_set_pc (cpu, cpu->cpu_insn_pc);
750
          sim_engine_halt (CPU_STATE (cpu), cpu,
751
                           NULL, NULL_CIA, sim_exited,
752
                           cpu_get_d (cpu));
753
          return;
754
        }
755
      /* SCz: not correct... */
756
      cpu_push_all (cpu);
757
      break;
758
 
759
    case M6811_SWI:
760
      interrupts_raise (&cpu->cpu_interrupts, M6811_INT_SWI);
761
      interrupts_process (&cpu->cpu_interrupts);
762
      break;
763
 
764
    case M6811_EMUL_SYSCALL:
765
    case M6811_ILLEGAL:
766
      if (cpu->cpu_emul_syscall)
767
        {
768
          uint8 op = memory_read8 (cpu,
769
                                   cpu_get_pc (cpu) - 1);
770
          if (op == 0x41)
771
            {
772
              cpu_set_pc (cpu, cpu->cpu_insn_pc);
773
              sim_engine_halt (CPU_STATE (cpu), cpu,
774
                               NULL, NULL_CIA, sim_exited,
775
                               cpu_get_d (cpu));
776
              return;
777
            }
778
          else
779
            {
780
              emul_os (op, cpu);
781
            }
782
          return;
783
        }
784
 
785
      interrupts_raise (&cpu->cpu_interrupts, M6811_INT_ILLEGAL);
786
      interrupts_process (&cpu->cpu_interrupts);
787
      break;
788
 
789
    case M6811_TEST:
790
    case M6812_BGND:
791
      {
792
        SIM_DESC sd;
793
 
794
        sd = CPU_STATE (cpu);
795
 
796
        /* Breakpoint instruction if we are under gdb.  */
797
        if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
798
          {
799
            cpu->cpu_regs.pc --;
800
            sim_engine_halt (CPU_STATE (cpu), cpu,
801
                             0, cpu_get_pc (cpu), sim_stopped,
802
                             SIM_SIGTRAP);
803
          }
804
        /* else this is a nop but not in test factory mode.  */
805
        break;
806
      }
807
 
808
    case M6812_IDIVS:
809
      {
810
        int32 src1 = (int16) cpu_get_d (cpu);
811
        int32 src2 = (int16) cpu_get_x (cpu);
812
 
813
        if (src2 == 0)
814
          {
815
            cpu_set_ccr_C (cpu, 1);
816
          }
817
        else
818
          {
819
            cpu_set_d (cpu, src1 % src2);
820
            src1 = src1 / src2;
821
            cpu_set_x (cpu, src1);
822
            cpu_set_ccr_C (cpu, 0);
823
            cpu_set_ccr_Z (cpu, src1 == 0);
824
            cpu_set_ccr_N (cpu, src1 & 0x8000);
825
            cpu_set_ccr_V (cpu, src1 >= 32768 || src1 < -32768);
826
          }
827
      }
828
      break;
829
 
830
    case M6812_EDIV:
831
      {
832
        uint32 src1 = (uint32) cpu_get_x (cpu);
833
        uint32 src2 = (uint32) (cpu_get_y (cpu) << 16)
834
          | (uint32) (cpu_get_d (cpu));
835
 
836
        if (src1 == 0)
837
          {
838
            cpu_set_ccr_C (cpu, 1);
839
          }
840
        else
841
          {
842
            cpu_set_ccr_C (cpu, 0);
843
            cpu_set_d (cpu, src2 % src1);
844
            src2 = src2 / src1;
845
            cpu_set_y (cpu, src2);
846
            cpu_set_ccr_Z (cpu, src2 == 0);
847
            cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
848
            cpu_set_ccr_V (cpu, (src2 & 0xffff0000) != 0);
849
          }
850
      }
851
      break;
852
 
853
    case M6812_EDIVS:
854
      {
855
        int32 src1 = (int16) cpu_get_x (cpu);
856
        int32 src2 = (uint32) (cpu_get_y (cpu) << 16)
857
          | (uint32) (cpu_get_d (cpu));
858
 
859
        if (src1 == 0)
860
          {
861
            cpu_set_ccr_C (cpu, 1);
862
          }
863
        else
864
          {
865
            cpu_set_ccr_C (cpu, 0);
866
            cpu_set_d (cpu, src2 % src1);
867
            src2 = src2 / src1;
868
            cpu_set_y (cpu, src2);
869
            cpu_set_ccr_Z (cpu, src2 == 0);
870
            cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
871
            cpu_set_ccr_V (cpu, src2 > 32767 || src2 < -32768);
872
          }
873
      }
874
      break;
875
 
876
    case M6812_EMULS:
877
      {
878
        int32 src1, src2;
879
 
880
        src1 = (int16) cpu_get_d (cpu);
881
        src2 = (int16) cpu_get_y (cpu);
882
        src1 = src1 * src2;
883
        cpu_set_d (cpu, src1 & 0x0ffff);
884
        cpu_set_y (cpu, src1 >> 16);
885
        cpu_set_ccr_Z (cpu, src1 == 0);
886
        cpu_set_ccr_N (cpu, (src1 & 0x80000000) != 0);
887
        cpu_set_ccr_C (cpu, (src1 & 0x00008000) != 0);
888
      }
889
      break;
890
 
891
    case M6812_EMACS:
892
      {
893
        int32 src1, src2;
894
        uint16 addr;
895
 
896
        addr = cpu_fetch16 (cpu);
897
        src1 = (int16) memory_read16 (cpu, cpu_get_x (cpu));
898
        src2 = (int16) memory_read16 (cpu, cpu_get_y (cpu));
899
        src1 = src1 * src2;
900
        src2 = (((uint32) memory_read16 (cpu, addr)) << 16)
901
          | (uint32) memory_read16 (cpu, addr + 2);
902
 
903
        memory_write16 (cpu, addr, (src1 + src2) >> 16);
904
        memory_write16 (cpu, addr + 2, (src1 + src2));
905
 
906
 
907
      }
908
      break;
909
 
910
    case M6812_CALL:
911
      {
912
        uint8 page;
913
        uint16 addr;
914
 
915
        addr = cpu_fetch16 (cpu);
916
        page = cpu_fetch8 (cpu);
917
 
918
        cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
919
        cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
920
 
921
        cpu_set_page (cpu, page);
922
        cpu_set_pc (cpu, addr);
923
      }
924
      break;
925
 
926
    case M6812_CALL_INDIRECT:
927
      {
928
        uint8 code;
929
        uint16 addr;
930
        uint8 page;
931
 
932
        code = memory_read8 (cpu, cpu_get_pc (cpu));
933
        /* Indirect addressing call has the page specified in the
934
           memory location pointed to by the address.  */
935
        if ((code & 0xE3) == 0xE3)
936
          {
937
            addr = cpu_get_indexed_operand_addr (cpu, 0);
938
            page = memory_read8 (cpu, addr + 2);
939
            addr = memory_read16 (cpu, addr);
940
          }
941
        else
942
          {
943
            /* Otherwise, page is in the opcode.  */
944
            addr = cpu_get_indexed_operand16 (cpu, 0);
945
            page = cpu_fetch8 (cpu);
946
          }
947
        cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
948
        cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
949
        cpu_set_page (cpu, page);
950
        cpu_set_pc (cpu, addr);
951
      }
952
      break;
953
 
954
    case M6812_RTC:
955
      {
956
        uint8 page = cpu_m68hc12_pop_uint8 (cpu);
957
        uint16 addr = cpu_m68hc12_pop_uint16 (cpu);
958
 
959
        cpu_set_page (cpu, page);
960
        cpu_set_pc (cpu, addr);
961
      }
962
      break;
963
 
964
    case M6812_ETBL:
965
    default:
966
      sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
967
                       cpu_get_pc (cpu), sim_stopped,
968
                       SIM_SIGILL);
969
      break;
970
    }
971
}
972
 
973
 
974
void
975
cpu_single_step (sim_cpu *cpu)
976
{
977
  cpu->cpu_current_cycle = 0;
978
  cpu->cpu_insn_pc = cpu_get_pc (cpu);
979
 
980
  /* Handle the pending interrupts.  If an interrupt is handled,
981
     treat this as an single step.  */
982
  if (interrupts_process (&cpu->cpu_interrupts))
983
    {
984
      cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
985
      return;
986
    }
987
 
988
  /*  printf("PC = 0x%04x\n", cpu_get_pc (cpu));*/
989
  cpu->cpu_interpretor (cpu);
990
  cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
991
}
992
 
993
/* VARARGS */
994
void
995
sim_memory_error (sim_cpu *cpu, SIM_SIGNAL excep,
996
                  uint16 addr, const char *message, ...)
997
{
998
  char buf[1024];
999
  va_list args;
1000
 
1001
  va_start (args, message);
1002
  vsprintf (buf, message, args);
1003
  va_end (args);
1004
 
1005
  sim_io_printf (CPU_STATE (cpu), "%s\n", buf);
1006
  cpu_memory_exception (cpu, excep, addr, buf);
1007
}
1008
 
1009
 
1010
void
1011
cpu_memory_exception (sim_cpu *cpu, SIM_SIGNAL excep,
1012
                      uint16 addr, const char *message)
1013
{
1014
  if (cpu->cpu_running == 0)
1015
    return;
1016
 
1017
  cpu_set_pc (cpu, cpu->cpu_insn_pc);
1018
  sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
1019
                   cpu_get_pc (cpu), sim_stopped, excep);
1020
 
1021
#if 0
1022
  cpu->mem_exception = excep;
1023
  cpu->fault_addr    = addr;
1024
  cpu->fault_msg     = strdup (message);
1025
 
1026
  if (cpu->cpu_use_handler)
1027
    {
1028
      longjmp (&cpu->cpu_exception_handler, 1);
1029
    }
1030
  (* cpu->callback->printf_filtered)
1031
    (cpu->callback, "Fault at 0x%04x: %s\n", addr, message);
1032
#endif
1033
}
1034
 
1035
void
1036
cpu_info (SIM_DESC sd, sim_cpu *cpu)
1037
{
1038
  sim_io_printf (sd, "CPU info:\n");
1039
  sim_io_printf (sd, "  Absolute cycle: %s\n",
1040
                 cycle_to_string (cpu, cpu->cpu_absolute_cycle));
1041
 
1042
  sim_io_printf (sd, "  Syscall emulation: %s\n",
1043
                 cpu->cpu_emul_syscall ? "yes, via 0xcd <n>" : "no");
1044
  sim_io_printf (sd, "  Memory errors detection: %s\n",
1045
                 cpu->cpu_check_memory ? "yes" : "no");
1046
  sim_io_printf (sd, "  Stop on interrupt: %s\n",
1047
                 cpu->cpu_stop_on_interrupt ? "yes" : "no");
1048
}
1049
 

powered by: WebSVN 2.1.0

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