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