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