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