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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gdb/] [gdb-6.8/] [sim/] [m68hc11/] [m68hc11_sim.c] - Blame information for rev 26

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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