Home | History | Annotate | Line # | Download | only in msp430
      1      1.1  christos /* Simulator for TI MSP430 and MSP430X
      2      1.1  christos 
      3  1.1.1.9  christos    Copyright (C) 2013-2024 Free Software Foundation, Inc.
      4      1.1  christos    Contributed by Red Hat.
      5      1.1  christos    Based on sim/bfin/bfin-sim.c which was contributed by Analog Devices, Inc.
      6      1.1  christos 
      7      1.1  christos    This file is part of simulators.
      8      1.1  christos 
      9      1.1  christos    This program is free software; you can redistribute it and/or modify
     10      1.1  christos    it under the terms of the GNU General Public License as published by
     11      1.1  christos    the Free Software Foundation; either version 3 of the License, or
     12      1.1  christos    (at your option) any later version.
     13      1.1  christos 
     14      1.1  christos    This program is distributed in the hope that it will be useful,
     15      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17      1.1  christos    GNU General Public License for more details.
     18      1.1  christos 
     19      1.1  christos    You should have received a copy of the GNU General Public License
     20      1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     21      1.1  christos 
     22  1.1.1.8  christos /* This must come before any other includes.  */
     23  1.1.1.8  christos #include "defs.h"
     24  1.1.1.8  christos 
     25      1.1  christos #include <stdio.h>
     26      1.1  christos #include <stdlib.h>
     27      1.1  christos #include <string.h>
     28      1.1  christos #include <inttypes.h>
     29  1.1.1.3  christos #include <unistd.h>
     30      1.1  christos #include <assert.h>
     31      1.1  christos #include "opcode/msp430-decode.h"
     32      1.1  christos #include "sim-main.h"
     33  1.1.1.9  christos #include "sim-options.h"
     34  1.1.1.8  christos #include "sim-signal.h"
     35  1.1.1.3  christos #include "sim-syscall.h"
     36  1.1.1.9  christos #include "msp430-sim.h"
     37      1.1  christos 
     38      1.1  christos static sim_cia
     39      1.1  christos msp430_pc_fetch (SIM_CPU *cpu)
     40      1.1  christos {
     41  1.1.1.9  christos   struct msp430_cpu_state *msp430_cpu = MSP430_SIM_CPU (cpu);
     42  1.1.1.9  christos 
     43  1.1.1.9  christos   return msp430_cpu->regs[0];
     44      1.1  christos }
     45      1.1  christos 
     46      1.1  christos static void
     47      1.1  christos msp430_pc_store (SIM_CPU *cpu, sim_cia newpc)
     48      1.1  christos {
     49  1.1.1.9  christos   struct msp430_cpu_state *msp430_cpu = MSP430_SIM_CPU (cpu);
     50  1.1.1.9  christos 
     51  1.1.1.9  christos   msp430_cpu->regs[0] = newpc;
     52      1.1  christos }
     53      1.1  christos 
     54      1.1  christos static int
     55  1.1.1.8  christos msp430_reg_fetch (SIM_CPU *cpu, int regno, void *buf, int len)
     56      1.1  christos {
     57  1.1.1.9  christos   struct msp430_cpu_state *msp430_cpu = MSP430_SIM_CPU (cpu);
     58  1.1.1.8  christos   unsigned char *memory = buf;
     59  1.1.1.8  christos 
     60      1.1  christos   if (0 <= regno && regno < 16)
     61      1.1  christos     {
     62      1.1  christos       if (len == 2)
     63      1.1  christos 	{
     64  1.1.1.9  christos 	  int val = msp430_cpu->regs[regno];
     65  1.1.1.8  christos 	  memory[0] = val & 0xff;
     66  1.1.1.8  christos 	  memory[1] = (val >> 8) & 0xff;
     67      1.1  christos 	  return 0;
     68      1.1  christos 	}
     69      1.1  christos       else if (len == 4)
     70      1.1  christos 	{
     71  1.1.1.9  christos 	  int val = msp430_cpu->regs[regno];
     72  1.1.1.8  christos 	  memory[0] = val & 0xff;
     73  1.1.1.8  christos 	  memory[1] = (val >> 8) & 0xff;
     74  1.1.1.8  christos 	  memory[2] = (val >> 16) & 0x0f; /* Registers are only 20 bits wide.  */
     75  1.1.1.8  christos 	  memory[3] = 0;
     76      1.1  christos 	  return 0;
     77      1.1  christos 	}
     78      1.1  christos       else
     79      1.1  christos 	return -1;
     80      1.1  christos     }
     81      1.1  christos   else
     82      1.1  christos     return -1;
     83      1.1  christos }
     84      1.1  christos 
     85      1.1  christos static int
     86  1.1.1.8  christos msp430_reg_store (SIM_CPU *cpu, int regno, const void *buf, int len)
     87      1.1  christos {
     88  1.1.1.9  christos   struct msp430_cpu_state *msp430_cpu = MSP430_SIM_CPU (cpu);
     89  1.1.1.8  christos   const unsigned char *memory = buf;
     90  1.1.1.8  christos 
     91      1.1  christos   if (0 <= regno && regno < 16)
     92      1.1  christos     {
     93      1.1  christos       if (len == 2)
     94      1.1  christos 	{
     95  1.1.1.9  christos 	  msp430_cpu->regs[regno] = (memory[1] << 8) | memory[0];
     96      1.1  christos 	  return len;
     97      1.1  christos 	}
     98      1.1  christos 
     99      1.1  christos       if (len == 4)
    100      1.1  christos 	{
    101  1.1.1.9  christos 	  msp430_cpu->regs[regno] = ((memory[2] << 16) & 0xf0000)
    102  1.1.1.9  christos 				     | (memory[1] << 8) | memory[0];
    103      1.1  christos 	  return len;
    104      1.1  christos 	}
    105      1.1  christos     }
    106      1.1  christos 
    107      1.1  christos   return -1;
    108      1.1  christos }
    109      1.1  christos 
    110      1.1  christos SIM_DESC
    111      1.1  christos sim_open (SIM_OPEN_KIND kind,
    112      1.1  christos 	  struct host_callback_struct *callback,
    113      1.1  christos 	  struct bfd *abfd,
    114  1.1.1.4  christos 	  char * const *argv)
    115      1.1  christos {
    116      1.1  christos   SIM_DESC sd = sim_state_alloc (kind, callback);
    117  1.1.1.9  christos   struct msp430_cpu_state *msp430_cpu;
    118      1.1  christos   char c;
    119  1.1.1.9  christos   int i;
    120      1.1  christos 
    121      1.1  christos   /* Initialise the simulator.  */
    122      1.1  christos 
    123  1.1.1.8  christos   /* Set default options before parsing user options.  */
    124  1.1.1.8  christos   current_target_byte_order = BFD_ENDIAN_LITTLE;
    125  1.1.1.8  christos 
    126  1.1.1.9  christos   if (sim_cpu_alloc_all_extra (sd, 0, sizeof (struct msp430_cpu_state))
    127  1.1.1.9  christos       != SIM_RC_OK)
    128      1.1  christos     {
    129      1.1  christos       sim_state_free (sd);
    130      1.1  christos       return 0;
    131      1.1  christos     }
    132      1.1  christos 
    133      1.1  christos   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
    134      1.1  christos     {
    135      1.1  christos       sim_state_free (sd);
    136      1.1  christos       return 0;
    137      1.1  christos     }
    138      1.1  christos 
    139      1.1  christos   if (sim_parse_args (sd, argv) != SIM_RC_OK)
    140      1.1  christos     {
    141      1.1  christos       sim_state_free (sd);
    142      1.1  christos       return 0;
    143      1.1  christos     }
    144      1.1  christos 
    145  1.1.1.3  christos   /* Allocate memory if none specified by user.
    146  1.1.1.3  christos      Note - these values match the memory regions in the libgloss/msp430/msp430[xl]-sim.ld scripts.  */
    147  1.1.1.9  christos   if (sim_core_read_buffer (sd, STATE_CPU (sd, 0), read_map, &c, 0x2, 1) == 0)
    148  1.1.1.3  christos     sim_do_commandf (sd, "memory-region 0,0x20"); /* Needed by the GDB testsuite.  */
    149  1.1.1.9  christos   if (sim_core_read_buffer (sd, STATE_CPU (sd, 0), read_map, &c, 0x500, 1) == 0)
    150  1.1.1.7  christos     sim_do_commandf (sd, "memory-region 0x500,0xfac0");  /* RAM and/or ROM */
    151  1.1.1.9  christos   if (sim_core_read_buffer (sd, STATE_CPU (sd, 0), read_map, &c, 0xfffe, 1) == 0)
    152  1.1.1.3  christos     sim_do_commandf (sd, "memory-region 0xffc0,0x40"); /* VECTORS.  */
    153  1.1.1.9  christos   if (sim_core_read_buffer (sd, STATE_CPU (sd, 0), read_map, &c, 0x10000, 1) == 0)
    154  1.1.1.3  christos     sim_do_commandf (sd, "memory-region 0x10000,0x80000"); /* HIGH FLASH RAM.  */
    155  1.1.1.9  christos   if (sim_core_read_buffer (sd, STATE_CPU (sd, 0), read_map, &c, 0x90000, 1) == 0)
    156  1.1.1.3  christos     sim_do_commandf (sd, "memory-region 0x90000,0x70000"); /* HIGH ROM.  */
    157      1.1  christos 
    158      1.1  christos   /* Check for/establish the a reference program image.  */
    159  1.1.1.8  christos   if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
    160      1.1  christos     {
    161      1.1  christos       sim_state_free (sd);
    162      1.1  christos       return 0;
    163      1.1  christos     }
    164      1.1  christos 
    165      1.1  christos   /* Establish any remaining configuration options.  */
    166      1.1  christos   if (sim_config (sd) != SIM_RC_OK)
    167      1.1  christos     {
    168      1.1  christos       sim_state_free (sd);
    169      1.1  christos       return 0;
    170      1.1  christos     }
    171      1.1  christos 
    172      1.1  christos   if (sim_post_argv_init (sd) != SIM_RC_OK)
    173      1.1  christos     {
    174      1.1  christos       sim_state_free (sd);
    175      1.1  christos       return 0;
    176      1.1  christos     }
    177      1.1  christos 
    178      1.1  christos   /* CPU specific initialization.  */
    179  1.1.1.9  christos   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
    180  1.1.1.9  christos     {
    181  1.1.1.9  christos       SIM_CPU *cpu = STATE_CPU (sd, i);
    182      1.1  christos 
    183  1.1.1.9  christos       CPU_PC_FETCH (cpu) = msp430_pc_fetch;
    184  1.1.1.9  christos       CPU_PC_STORE (cpu) = msp430_pc_store;
    185  1.1.1.9  christos       CPU_REG_FETCH (cpu) = msp430_reg_fetch;
    186  1.1.1.9  christos       CPU_REG_STORE (cpu) = msp430_reg_store;
    187  1.1.1.9  christos 
    188  1.1.1.9  christos       msp430_cpu = MSP430_SIM_CPU (cpu);
    189  1.1.1.9  christos       msp430_cpu->cio_breakpoint = trace_sym_value (sd, "C$$IO$$");
    190  1.1.1.9  christos       msp430_cpu->cio_buffer = trace_sym_value (sd, "__CIOBUF__");
    191  1.1.1.9  christos       if (msp430_cpu->cio_buffer == -1)
    192  1.1.1.9  christos 	msp430_cpu->cio_buffer = trace_sym_value (sd, "_CIOBUF_");
    193  1.1.1.9  christos     }
    194      1.1  christos 
    195      1.1  christos   return sd;
    196      1.1  christos }
    197      1.1  christos 
    198      1.1  christos SIM_RC
    199      1.1  christos sim_create_inferior (SIM_DESC sd,
    200      1.1  christos 		     struct bfd *abfd,
    201  1.1.1.4  christos 		     char * const *argv,
    202  1.1.1.4  christos 		     char * const *env)
    203      1.1  christos {
    204      1.1  christos   unsigned char resetv[2];
    205      1.1  christos   int new_pc;
    206      1.1  christos 
    207  1.1.1.2  christos   /* Set the PC to the default reset vector if available.  */
    208  1.1.1.9  christos   sim_core_read_buffer (sd, STATE_CPU (sd, 0), read_map, resetv, 0xfffe, 2);
    209      1.1  christos   new_pc = resetv[0] + 256 * resetv[1];
    210  1.1.1.2  christos 
    211  1.1.1.2  christos   /* If the reset vector isn't initialized, then use the ELF entry.  */
    212  1.1.1.2  christos   if (abfd != NULL && !new_pc)
    213  1.1.1.2  christos     new_pc = bfd_get_start_address (abfd);
    214  1.1.1.2  christos 
    215  1.1.1.9  christos   sim_pc_set (STATE_CPU (sd, 0), new_pc);
    216  1.1.1.9  christos   msp430_pc_store (STATE_CPU (sd, 0), new_pc);
    217      1.1  christos 
    218      1.1  christos   return SIM_RC_OK;
    219      1.1  christos }
    220      1.1  christos 
    221      1.1  christos typedef struct
    222      1.1  christos {
    223      1.1  christos   SIM_DESC sd;
    224      1.1  christos   int gb_addr;
    225      1.1  christos } Get_Byte_Local_Data;
    226      1.1  christos 
    227      1.1  christos static int
    228      1.1  christos msp430_getbyte (void *vld)
    229      1.1  christos {
    230      1.1  christos   Get_Byte_Local_Data *ld = (Get_Byte_Local_Data *)vld;
    231      1.1  christos   char buf[1];
    232      1.1  christos   SIM_DESC sd = ld->sd;
    233      1.1  christos 
    234  1.1.1.9  christos   sim_core_read_buffer (sd, STATE_CPU (sd, 0), read_map, buf, ld->gb_addr, 1);
    235      1.1  christos   ld->gb_addr ++;
    236      1.1  christos   return buf[0];
    237      1.1  christos }
    238      1.1  christos 
    239  1.1.1.9  christos #define REG(N) MSP430_SIM_CPU (STATE_CPU (sd, 0))->regs[N]
    240      1.1  christos #define PC REG(MSR_PC)
    241      1.1  christos #define SP REG(MSR_SP)
    242      1.1  christos #define SR REG(MSR_SR)
    243      1.1  christos 
    244      1.1  christos static const char *
    245      1.1  christos register_names[] =
    246      1.1  christos {
    247      1.1  christos   "PC", "SP", "SR", "CG", "R4", "R5", "R6", "R7", "R8",
    248      1.1  christos   "R9", "R10", "R11", "R12", "R13", "R14", "R15"
    249      1.1  christos };
    250      1.1  christos 
    251      1.1  christos static void
    252      1.1  christos trace_reg_put (SIM_DESC sd, int n, unsigned int v)
    253      1.1  christos {
    254  1.1.1.9  christos   TRACE_REGISTER (STATE_CPU (sd, 0), "PUT: %#x -> %s", v, register_names[n]);
    255      1.1  christos   REG (n) = v;
    256      1.1  christos }
    257      1.1  christos 
    258      1.1  christos static unsigned int
    259      1.1  christos trace_reg_get (SIM_DESC sd, int n)
    260      1.1  christos {
    261  1.1.1.9  christos   TRACE_REGISTER (STATE_CPU (sd, 0), "GET: %s -> %#x", register_names[n], REG (n));
    262      1.1  christos   return REG (n);
    263      1.1  christos }
    264      1.1  christos 
    265      1.1  christos #define REG_PUT(N,V) trace_reg_put (sd, N, V)
    266      1.1  christos #define REG_GET(N)   trace_reg_get (sd, N)
    267      1.1  christos 
    268  1.1.1.2  christos /* Hardware multiply (and accumulate) support.  */
    269  1.1.1.2  christos 
    270  1.1.1.2  christos static unsigned int
    271  1.1.1.2  christos zero_ext (unsigned int v, unsigned int bits)
    272  1.1.1.2  christos {
    273  1.1.1.2  christos   v &= ((1 << bits) - 1);
    274  1.1.1.2  christos   return v;
    275  1.1.1.2  christos }
    276  1.1.1.2  christos 
    277  1.1.1.2  christos static signed long long
    278  1.1.1.2  christos sign_ext (signed long long v, unsigned int bits)
    279  1.1.1.2  christos {
    280  1.1.1.2  christos   signed long long sb = 1LL << (bits-1);	/* Sign bit.  */
    281  1.1.1.2  christos   signed long long mb = (1LL << (bits-1)) - 1LL; /* Mantissa bits.  */
    282  1.1.1.2  christos 
    283  1.1.1.2  christos   if (v & sb)
    284  1.1.1.2  christos     v = v | ~mb;
    285  1.1.1.2  christos   else
    286  1.1.1.2  christos     v = v & mb;
    287  1.1.1.2  christos   return v;
    288  1.1.1.2  christos }
    289  1.1.1.2  christos 
    290      1.1  christos static int
    291      1.1  christos get_op (SIM_DESC sd, MSP430_Opcode_Decoded *opc, int n)
    292      1.1  christos {
    293      1.1  christos   MSP430_Opcode_Operand *op = opc->op + n;
    294  1.1.1.6  christos   int rv = 0;
    295      1.1  christos   int addr;
    296      1.1  christos   unsigned char buf[4];
    297      1.1  christos   int incval = 0;
    298      1.1  christos 
    299      1.1  christos   switch (op->type)
    300      1.1  christos     {
    301      1.1  christos     case MSP430_Operand_Immediate:
    302      1.1  christos       rv =  op->addend;
    303      1.1  christos       break;
    304      1.1  christos     case MSP430_Operand_Register:
    305      1.1  christos       rv = REG_GET (op->reg);
    306      1.1  christos       break;
    307      1.1  christos     case MSP430_Operand_Indirect:
    308      1.1  christos     case MSP430_Operand_Indirect_Postinc:
    309      1.1  christos       addr = op->addend;
    310      1.1  christos       if (op->reg != MSR_None)
    311      1.1  christos 	{
    312  1.1.1.3  christos 	  int reg = REG_GET (op->reg);
    313  1.1.1.3  christos 	  int sign = opc->ofs_430x ? 20 : 16;
    314  1.1.1.3  christos 
    315  1.1.1.3  christos 	  /* Index values are signed.  */
    316  1.1.1.3  christos 	  if (addr & (1 << (sign - 1)))
    317  1.1.1.4  christos 	    addr |= -(1 << sign);
    318  1.1.1.3  christos 
    319      1.1  christos 	  addr += reg;
    320  1.1.1.3  christos 
    321  1.1.1.3  christos 	  /* For MSP430 instructions the sum is limited to 16 bits if the
    322  1.1.1.3  christos 	     address in the index register is less than 64k even if we are
    323  1.1.1.3  christos 	     running on an MSP430X CPU.  This is for MSP430 compatibility.  */
    324      1.1  christos 	  if (reg < 0x10000 && ! opc->ofs_430x)
    325  1.1.1.3  christos 	    {
    326  1.1.1.3  christos 	      if (addr >= 0x10000)
    327  1.1.1.3  christos 		fprintf (stderr, " XXX WRAPPING ADDRESS %x on read\n", addr);
    328  1.1.1.3  christos 
    329  1.1.1.3  christos 	      addr &= 0xffff;
    330  1.1.1.3  christos 	    }
    331      1.1  christos 	}
    332      1.1  christos       addr &= 0xfffff;
    333      1.1  christos       switch (opc->size)
    334      1.1  christos 	{
    335      1.1  christos 	case 8:
    336  1.1.1.9  christos 	  sim_core_read_buffer (sd, STATE_CPU (sd, 0), read_map, buf, addr, 1);
    337      1.1  christos 	  rv = buf[0];
    338      1.1  christos 	  break;
    339      1.1  christos 	case 16:
    340  1.1.1.9  christos 	  sim_core_read_buffer (sd, STATE_CPU (sd, 0), read_map, buf, addr, 2);
    341      1.1  christos 	  rv = buf[0] | (buf[1] << 8);
    342      1.1  christos 	  break;
    343      1.1  christos 	case 20:
    344      1.1  christos 	case 32:
    345  1.1.1.9  christos 	  sim_core_read_buffer (sd, STATE_CPU (sd, 0), read_map, buf, addr, 4);
    346      1.1  christos 	  rv = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
    347      1.1  christos 	  break;
    348      1.1  christos 	default:
    349      1.1  christos 	  assert (! opc->size);
    350      1.1  christos 	  break;
    351      1.1  christos 	}
    352      1.1  christos #if 0
    353      1.1  christos       /* Hack - MSP430X5438 serial port status register.  */
    354      1.1  christos       if (addr == 0x5dd)
    355      1.1  christos 	rv = 2;
    356      1.1  christos #endif
    357  1.1.1.4  christos       if ((addr >= 0x130 && addr <= 0x15B)
    358  1.1.1.4  christos 	  || (addr >= 0x4C0 && addr <= 0x4EB))
    359  1.1.1.2  christos 	{
    360  1.1.1.2  christos 	  switch (addr)
    361  1.1.1.2  christos 	    {
    362  1.1.1.4  christos 	    case 0x4CA:
    363  1.1.1.2  christos 	    case 0x13A:
    364  1.1.1.2  christos 	      switch (HWMULT (sd, hwmult_type))
    365  1.1.1.2  christos 		{
    366  1.1.1.2  christos 		case UNSIGN_MAC_32:
    367  1.1.1.2  christos 		case UNSIGN_32:
    368  1.1.1.2  christos 		  rv = zero_ext (HWMULT (sd, hwmult_result), 16);
    369  1.1.1.2  christos 		  break;
    370  1.1.1.3  christos 		case SIGN_MAC_32:
    371  1.1.1.2  christos 		case SIGN_32:
    372  1.1.1.2  christos 		  rv = sign_ext (HWMULT (sd, hwmult_signed_result), 16);
    373  1.1.1.2  christos 		  break;
    374  1.1.1.2  christos 		}
    375  1.1.1.2  christos 	      break;
    376  1.1.1.2  christos 
    377  1.1.1.4  christos 	    case 0x4CC:
    378  1.1.1.2  christos 	    case 0x13C:
    379  1.1.1.2  christos 	      switch (HWMULT (sd, hwmult_type))
    380  1.1.1.2  christos 		{
    381  1.1.1.2  christos 		case UNSIGN_MAC_32:
    382  1.1.1.2  christos 		case UNSIGN_32:
    383  1.1.1.2  christos 		  rv = zero_ext (HWMULT (sd, hwmult_result) >> 16, 16);
    384  1.1.1.2  christos 		  break;
    385  1.1.1.2  christos 
    386  1.1.1.2  christos 		case SIGN_MAC_32:
    387  1.1.1.2  christos 		case SIGN_32:
    388  1.1.1.2  christos 		  rv = sign_ext (HWMULT (sd, hwmult_signed_result) >> 16, 16);
    389  1.1.1.2  christos 		  break;
    390  1.1.1.2  christos 		}
    391  1.1.1.2  christos 	      break;
    392  1.1.1.2  christos 
    393  1.1.1.4  christos 	    case 0x4CE:
    394  1.1.1.2  christos 	    case 0x13E:
    395  1.1.1.2  christos 	      switch (HWMULT (sd, hwmult_type))
    396  1.1.1.2  christos 		{
    397  1.1.1.2  christos 		case UNSIGN_32:
    398  1.1.1.2  christos 		  rv = 0;
    399  1.1.1.2  christos 		  break;
    400  1.1.1.2  christos 		case SIGN_32:
    401  1.1.1.2  christos 		  rv = HWMULT (sd, hwmult_signed_result) < 0 ? -1 : 0;
    402  1.1.1.2  christos 		  break;
    403  1.1.1.2  christos 		case UNSIGN_MAC_32:
    404  1.1.1.2  christos 		  rv = 0; /* FIXME: Should be carry of last accumulate.  */
    405  1.1.1.2  christos 		  break;
    406  1.1.1.2  christos 		case SIGN_MAC_32:
    407  1.1.1.2  christos 		  rv = HWMULT (sd, hwmult_signed_accumulator) < 0 ? -1 : 0;
    408  1.1.1.2  christos 		  break;
    409  1.1.1.2  christos 		}
    410  1.1.1.2  christos 	      break;
    411  1.1.1.2  christos 
    412  1.1.1.4  christos 	    case 0x4E4:
    413  1.1.1.2  christos 	    case 0x154:
    414  1.1.1.2  christos 	      rv = zero_ext (HWMULT (sd, hw32mult_result), 16);
    415  1.1.1.2  christos 	      break;
    416  1.1.1.2  christos 
    417  1.1.1.4  christos 	    case 0x4E6:
    418  1.1.1.2  christos 	    case 0x156:
    419  1.1.1.2  christos 	      rv = zero_ext (HWMULT (sd, hw32mult_result) >> 16, 16);
    420  1.1.1.2  christos 	      break;
    421  1.1.1.2  christos 
    422  1.1.1.4  christos 	    case 0x4E8:
    423  1.1.1.2  christos 	    case 0x158:
    424  1.1.1.2  christos 	      rv = zero_ext (HWMULT (sd, hw32mult_result) >> 32, 16);
    425  1.1.1.2  christos 	      break;
    426  1.1.1.2  christos 
    427  1.1.1.4  christos 	    case 0x4EA:
    428  1.1.1.2  christos 	    case 0x15A:
    429  1.1.1.2  christos 	      switch (HWMULT (sd, hw32mult_type))
    430  1.1.1.2  christos 		{
    431  1.1.1.2  christos 		case UNSIGN_64: rv = zero_ext (HWMULT (sd, hw32mult_result) >> 48, 16); break;
    432  1.1.1.2  christos 		case   SIGN_64: rv = sign_ext (HWMULT (sd, hw32mult_result) >> 48, 16); break;
    433  1.1.1.2  christos 		}
    434  1.1.1.2  christos 	      break;
    435  1.1.1.2  christos 
    436  1.1.1.2  christos 	    default:
    437  1.1.1.3  christos 	      fprintf (stderr, "unimplemented HW MULT read from %x!\n", addr);
    438  1.1.1.2  christos 	      break;
    439  1.1.1.2  christos 	    }
    440  1.1.1.2  christos 	}
    441  1.1.1.2  christos 
    442  1.1.1.9  christos       TRACE_MEMORY (STATE_CPU (sd, 0), "GET: [%#x].%d -> %#x", addr, opc->size,
    443  1.1.1.3  christos 		    rv);
    444      1.1  christos       break;
    445  1.1.1.3  christos 
    446      1.1  christos     default:
    447      1.1  christos       fprintf (stderr, "invalid operand %d type %d\n", n, op->type);
    448      1.1  christos       abort ();
    449      1.1  christos     }
    450      1.1  christos 
    451      1.1  christos   switch (opc->size)
    452      1.1  christos     {
    453      1.1  christos     case 8:
    454      1.1  christos       rv &= 0xff;
    455      1.1  christos       incval = 1;
    456      1.1  christos       break;
    457      1.1  christos     case 16:
    458      1.1  christos       rv &= 0xffff;
    459      1.1  christos       incval = 2;
    460      1.1  christos       break;
    461      1.1  christos     case 20:
    462      1.1  christos       rv &= 0xfffff;
    463      1.1  christos       incval = 4;
    464      1.1  christos       break;
    465      1.1  christos     case 32:
    466      1.1  christos       rv &= 0xffffffff;
    467      1.1  christos       incval = 4;
    468      1.1  christos       break;
    469      1.1  christos     }
    470      1.1  christos 
    471      1.1  christos   if (op->type == MSP430_Operand_Indirect_Postinc)
    472      1.1  christos     REG_PUT (op->reg, REG_GET (op->reg) + incval);
    473      1.1  christos 
    474      1.1  christos   return rv;
    475      1.1  christos }
    476      1.1  christos 
    477      1.1  christos static int
    478      1.1  christos put_op (SIM_DESC sd, MSP430_Opcode_Decoded *opc, int n, int val)
    479      1.1  christos {
    480      1.1  christos   MSP430_Opcode_Operand *op = opc->op + n;
    481  1.1.1.6  christos   int rv = 0;
    482      1.1  christos   int addr;
    483      1.1  christos   unsigned char buf[4];
    484      1.1  christos   int incval = 0;
    485      1.1  christos 
    486      1.1  christos   switch (opc->size)
    487      1.1  christos     {
    488      1.1  christos     case 8:
    489      1.1  christos       val &= 0xff;
    490      1.1  christos       break;
    491      1.1  christos     case 16:
    492      1.1  christos       val &= 0xffff;
    493      1.1  christos       break;
    494      1.1  christos     case 20:
    495      1.1  christos       val &= 0xfffff;
    496      1.1  christos       break;
    497      1.1  christos     case 32:
    498      1.1  christos       val &= 0xffffffff;
    499      1.1  christos       break;
    500      1.1  christos     }
    501      1.1  christos 
    502      1.1  christos   switch (op->type)
    503      1.1  christos     {
    504      1.1  christos     case MSP430_Operand_Register:
    505      1.1  christos       REG (op->reg) = val;
    506      1.1  christos       REG_PUT (op->reg, val);
    507      1.1  christos       break;
    508      1.1  christos     case MSP430_Operand_Indirect:
    509      1.1  christos     case MSP430_Operand_Indirect_Postinc:
    510      1.1  christos       addr = op->addend;
    511      1.1  christos       if (op->reg != MSR_None)
    512      1.1  christos 	{
    513  1.1.1.3  christos 	  int reg = REG_GET (op->reg);
    514  1.1.1.3  christos 	  int sign = opc->ofs_430x ? 20 : 16;
    515  1.1.1.3  christos 
    516  1.1.1.3  christos 	  /* Index values are signed.  */
    517  1.1.1.3  christos 	  if (addr & (1 << (sign - 1)))
    518  1.1.1.4  christos 	    addr |= -(1 << sign);
    519  1.1.1.3  christos 
    520      1.1  christos 	  addr += reg;
    521  1.1.1.3  christos 
    522  1.1.1.3  christos 	  /* For MSP430 instructions the sum is limited to 16 bits if the
    523  1.1.1.3  christos 	     address in the index register is less than 64k even if we are
    524  1.1.1.3  christos 	     running on an MSP430X CPU.  This is for MSP430 compatibility.  */
    525  1.1.1.3  christos 	  if (reg < 0x10000 && ! opc->ofs_430x)
    526  1.1.1.3  christos 	    {
    527  1.1.1.3  christos 	      if (addr >= 0x10000)
    528  1.1.1.3  christos 		fprintf (stderr, " XXX WRAPPING ADDRESS %x on write\n", addr);
    529  1.1.1.3  christos 
    530  1.1.1.3  christos 	      addr &= 0xffff;
    531  1.1.1.3  christos 	    }
    532      1.1  christos 	}
    533      1.1  christos       addr &= 0xfffff;
    534      1.1  christos 
    535  1.1.1.9  christos       TRACE_MEMORY (STATE_CPU (sd, 0), "PUT: [%#x].%d <- %#x", addr, opc->size,
    536  1.1.1.3  christos 		    val);
    537      1.1  christos #if 0
    538      1.1  christos       /* Hack - MSP430X5438 serial port transmit register.  */
    539      1.1  christos       if (addr == 0x5ce)
    540      1.1  christos 	putchar (val);
    541      1.1  christos #endif
    542  1.1.1.4  christos       if ((addr >= 0x130 && addr <= 0x15B)
    543  1.1.1.4  christos 	  || (addr >= 0x4C0 && addr <= 0x4EB))
    544  1.1.1.2  christos 	{
    545  1.1.1.2  christos 	  signed int a,b;
    546  1.1.1.2  christos 
    547  1.1.1.2  christos 	  /* Hardware Multiply emulation.  */
    548  1.1.1.2  christos 	  assert (opc->size == 16);
    549  1.1.1.2  christos 
    550  1.1.1.2  christos 	  switch (addr)
    551  1.1.1.2  christos 	    {
    552  1.1.1.4  christos 	    case 0x4C0:
    553  1.1.1.4  christos 	    case 0x130:
    554  1.1.1.4  christos 	      HWMULT (sd, hwmult_op1) = val;
    555  1.1.1.4  christos 	      HWMULT (sd, hwmult_type) = UNSIGN_32;
    556  1.1.1.4  christos 	      break;
    557  1.1.1.4  christos 
    558  1.1.1.4  christos 	    case 0x4C2:
    559  1.1.1.4  christos 	    case 0x132:
    560  1.1.1.4  christos 	      HWMULT (sd, hwmult_op1) = val;
    561  1.1.1.4  christos 	      HWMULT (sd, hwmult_type) = SIGN_32;
    562  1.1.1.4  christos 	      break;
    563  1.1.1.4  christos 
    564  1.1.1.4  christos 	    case 0x4C4:
    565  1.1.1.4  christos 	    case 0x134:
    566  1.1.1.4  christos 	      HWMULT (sd, hwmult_op1) = val;
    567  1.1.1.4  christos 	      HWMULT (sd, hwmult_type) = UNSIGN_MAC_32;
    568  1.1.1.4  christos 	      break;
    569  1.1.1.4  christos 
    570  1.1.1.4  christos 	    case 0x4C6:
    571  1.1.1.4  christos 	    case 0x136:
    572  1.1.1.4  christos 	      HWMULT (sd, hwmult_op1) = val;
    573  1.1.1.4  christos 	      HWMULT (sd, hwmult_type) = SIGN_MAC_32;
    574  1.1.1.4  christos 	      break;
    575  1.1.1.2  christos 
    576  1.1.1.4  christos 	    case 0x4C8:
    577  1.1.1.4  christos 	    case 0x138:
    578  1.1.1.4  christos 	      HWMULT (sd, hwmult_op2) = val;
    579  1.1.1.2  christos 	      switch (HWMULT (sd, hwmult_type))
    580  1.1.1.2  christos 		{
    581  1.1.1.2  christos 		case UNSIGN_32:
    582  1.1.1.7  christos 		  a = HWMULT (sd, hwmult_op1);
    583  1.1.1.7  christos 		  b = HWMULT (sd, hwmult_op2);
    584  1.1.1.7  christos 		  /* For unsigned 32-bit multiplication of 16-bit operands, an
    585  1.1.1.7  christos 		     explicit cast is required to prevent any implicit
    586  1.1.1.7  christos 		     sign-extension.  */
    587  1.1.1.8  christos 		  HWMULT (sd, hwmult_result) = (uint32_t) a * (uint32_t) b;
    588  1.1.1.7  christos 		  HWMULT (sd, hwmult_signed_result) = a * b;
    589  1.1.1.2  christos 		  HWMULT (sd, hwmult_accumulator) = HWMULT (sd, hwmult_signed_accumulator) = 0;
    590  1.1.1.2  christos 		  break;
    591  1.1.1.2  christos 
    592  1.1.1.2  christos 		case SIGN_32:
    593  1.1.1.2  christos 		  a = sign_ext (HWMULT (sd, hwmult_op1), 16);
    594  1.1.1.2  christos 		  b = sign_ext (HWMULT (sd, hwmult_op2), 16);
    595  1.1.1.2  christos 		  HWMULT (sd, hwmult_signed_result) = a * b;
    596  1.1.1.8  christos 		  HWMULT (sd, hwmult_result) = (uint32_t) a * (uint32_t) b;
    597  1.1.1.2  christos 		  HWMULT (sd, hwmult_accumulator) = HWMULT (sd, hwmult_signed_accumulator) = 0;
    598  1.1.1.2  christos 		  break;
    599  1.1.1.2  christos 
    600  1.1.1.2  christos 		case UNSIGN_MAC_32:
    601  1.1.1.7  christos 		  a = HWMULT (sd, hwmult_op1);
    602  1.1.1.7  christos 		  b = HWMULT (sd, hwmult_op2);
    603  1.1.1.7  christos 		  HWMULT (sd, hwmult_accumulator)
    604  1.1.1.8  christos 		    += (uint32_t) a * (uint32_t) b;
    605  1.1.1.7  christos 		  HWMULT (sd, hwmult_signed_accumulator) += a * b;
    606  1.1.1.2  christos 		  HWMULT (sd, hwmult_result) = HWMULT (sd, hwmult_accumulator);
    607  1.1.1.2  christos 		  HWMULT (sd, hwmult_signed_result) = HWMULT (sd, hwmult_signed_accumulator);
    608  1.1.1.2  christos 		  break;
    609  1.1.1.2  christos 
    610  1.1.1.2  christos 		case SIGN_MAC_32:
    611  1.1.1.2  christos 		  a = sign_ext (HWMULT (sd, hwmult_op1), 16);
    612  1.1.1.2  christos 		  b = sign_ext (HWMULT (sd, hwmult_op2), 16);
    613  1.1.1.7  christos 		  HWMULT (sd, hwmult_accumulator)
    614  1.1.1.8  christos 		    += (uint32_t) a * (uint32_t) b;
    615  1.1.1.2  christos 		  HWMULT (sd, hwmult_signed_accumulator) += a * b;
    616  1.1.1.2  christos 		  HWMULT (sd, hwmult_result) = HWMULT (sd, hwmult_accumulator);
    617  1.1.1.2  christos 		  HWMULT (sd, hwmult_signed_result) = HWMULT (sd, hwmult_signed_accumulator);
    618  1.1.1.2  christos 		  break;
    619  1.1.1.2  christos 		}
    620  1.1.1.2  christos 	      break;
    621  1.1.1.2  christos 
    622  1.1.1.4  christos 	    case 0x4CA:
    623  1.1.1.4  christos 	    case 0x13A:
    624  1.1.1.2  christos 	      /* Copy into LOW result...  */
    625  1.1.1.2  christos 	      switch (HWMULT (sd, hwmult_type))
    626  1.1.1.2  christos 		{
    627  1.1.1.2  christos 		case UNSIGN_MAC_32:
    628  1.1.1.2  christos 		case UNSIGN_32:
    629  1.1.1.2  christos 		  HWMULT (sd, hwmult_accumulator) = HWMULT (sd, hwmult_result) = zero_ext (val, 16);
    630  1.1.1.2  christos 		  HWMULT (sd, hwmult_signed_accumulator) = sign_ext (val, 16);
    631  1.1.1.2  christos 		  break;
    632  1.1.1.2  christos 		case SIGN_MAC_32:
    633  1.1.1.2  christos 		case SIGN_32:
    634  1.1.1.2  christos 		  HWMULT (sd, hwmult_signed_accumulator) = HWMULT (sd, hwmult_result) = sign_ext (val, 16);
    635  1.1.1.2  christos 		  HWMULT (sd, hwmult_accumulator) = zero_ext (val, 16);
    636  1.1.1.2  christos 		  break;
    637  1.1.1.2  christos 		}
    638  1.1.1.2  christos 	      break;
    639  1.1.1.2  christos 
    640  1.1.1.4  christos 	    case 0x4D0:
    641  1.1.1.2  christos 	    case 0x140:
    642  1.1.1.2  christos 	      HWMULT (sd, hw32mult_op1) = val;
    643  1.1.1.2  christos 	      HWMULT (sd, hw32mult_type) = UNSIGN_64;
    644  1.1.1.2  christos 	      break;
    645  1.1.1.4  christos 
    646  1.1.1.4  christos 	    case 0x4D2:
    647  1.1.1.2  christos 	    case 0x142:
    648  1.1.1.2  christos 	      HWMULT (sd, hw32mult_op1) = (HWMULT (sd, hw32mult_op1) & 0xFFFF) | (val << 16);
    649  1.1.1.2  christos 	      break;
    650  1.1.1.4  christos 
    651  1.1.1.4  christos 	    case 0x4D4:
    652  1.1.1.2  christos 	    case 0x144:
    653  1.1.1.2  christos 	      HWMULT (sd, hw32mult_op1) = val;
    654  1.1.1.2  christos 	      HWMULT (sd, hw32mult_type) = SIGN_64;
    655  1.1.1.2  christos 	      break;
    656  1.1.1.4  christos 
    657  1.1.1.4  christos 	    case 0x4D6:
    658  1.1.1.2  christos 	    case 0x146:
    659  1.1.1.2  christos 	      HWMULT (sd, hw32mult_op1) = (HWMULT (sd, hw32mult_op1) & 0xFFFF) | (val << 16);
    660  1.1.1.2  christos 	      break;
    661  1.1.1.4  christos 
    662  1.1.1.4  christos 	    case 0x4E0:
    663  1.1.1.2  christos 	    case 0x150:
    664  1.1.1.2  christos 	      HWMULT (sd, hw32mult_op2) = val;
    665  1.1.1.2  christos 	      break;
    666  1.1.1.2  christos 
    667  1.1.1.4  christos 	    case 0x4E2:
    668  1.1.1.2  christos 	    case 0x152:
    669  1.1.1.2  christos 	      HWMULT (sd, hw32mult_op2) = (HWMULT (sd, hw32mult_op2) & 0xFFFF) | (val << 16);
    670  1.1.1.2  christos 	      switch (HWMULT (sd, hw32mult_type))
    671  1.1.1.2  christos 		{
    672  1.1.1.2  christos 		case UNSIGN_64:
    673  1.1.1.7  christos 		  HWMULT (sd, hw32mult_result)
    674  1.1.1.8  christos 		    = (uint64_t) HWMULT (sd, hw32mult_op1)
    675  1.1.1.8  christos 		    * (uint64_t) HWMULT (sd, hw32mult_op2);
    676  1.1.1.2  christos 		  break;
    677  1.1.1.2  christos 		case SIGN_64:
    678  1.1.1.7  christos 		  HWMULT (sd, hw32mult_result)
    679  1.1.1.7  christos 		    = sign_ext (HWMULT (sd, hw32mult_op1), 32)
    680  1.1.1.2  christos 		    * sign_ext (HWMULT (sd, hw32mult_op2), 32);
    681  1.1.1.2  christos 		  break;
    682  1.1.1.2  christos 		}
    683  1.1.1.2  christos 	      break;
    684  1.1.1.2  christos 
    685  1.1.1.2  christos 	    default:
    686  1.1.1.2  christos 	      fprintf (stderr, "unimplemented HW MULT write to %x!\n", addr);
    687  1.1.1.2  christos 	      break;
    688  1.1.1.2  christos 	    }
    689  1.1.1.2  christos 	}
    690  1.1.1.2  christos 
    691      1.1  christos       switch (opc->size)
    692      1.1  christos 	{
    693      1.1  christos 	case 8:
    694      1.1  christos 	  buf[0] = val;
    695  1.1.1.9  christos 	  sim_core_write_buffer (sd, STATE_CPU (sd, 0), write_map, buf, addr, 1);
    696      1.1  christos 	  break;
    697      1.1  christos 	case 16:
    698      1.1  christos 	  buf[0] = val;
    699      1.1  christos 	  buf[1] = val >> 8;
    700  1.1.1.9  christos 	  sim_core_write_buffer (sd, STATE_CPU (sd, 0), write_map, buf, addr, 2);
    701      1.1  christos 	  break;
    702      1.1  christos 	case 20:
    703      1.1  christos 	case 32:
    704      1.1  christos 	  buf[0] = val;
    705      1.1  christos 	  buf[1] = val >> 8;
    706      1.1  christos 	  buf[2] = val >> 16;
    707      1.1  christos 	  buf[3] = val >> 24;
    708  1.1.1.9  christos 	  sim_core_write_buffer (sd, STATE_CPU (sd, 0), write_map, buf, addr, 4);
    709      1.1  christos 	  break;
    710      1.1  christos 	default:
    711      1.1  christos 	  assert (! opc->size);
    712      1.1  christos 	  break;
    713      1.1  christos 	}
    714      1.1  christos       break;
    715      1.1  christos     default:
    716      1.1  christos       fprintf (stderr, "invalid operand %d type %d\n", n, op->type);
    717      1.1  christos       abort ();
    718      1.1  christos     }
    719      1.1  christos 
    720      1.1  christos   switch (opc->size)
    721      1.1  christos     {
    722      1.1  christos     case 8:
    723      1.1  christos       rv &= 0xff;
    724      1.1  christos       incval = 1;
    725      1.1  christos       break;
    726      1.1  christos     case 16:
    727      1.1  christos       rv &= 0xffff;
    728      1.1  christos       incval = 2;
    729      1.1  christos       break;
    730      1.1  christos     case 20:
    731      1.1  christos       rv &= 0xfffff;
    732      1.1  christos       incval = 4;
    733      1.1  christos       break;
    734      1.1  christos     case 32:
    735      1.1  christos       rv &= 0xffffffff;
    736      1.1  christos       incval = 4;
    737      1.1  christos       break;
    738      1.1  christos     }
    739      1.1  christos 
    740      1.1  christos   if (op->type == MSP430_Operand_Indirect_Postinc)
    741      1.1  christos     {
    742      1.1  christos       int new_val = REG_GET (op->reg) + incval;
    743      1.1  christos       /* SP is always word-aligned.  */
    744      1.1  christos       if (op->reg == MSR_SP && (new_val & 1))
    745      1.1  christos 	new_val ++;
    746      1.1  christos       REG_PUT (op->reg, new_val);
    747      1.1  christos     }
    748      1.1  christos 
    749      1.1  christos   return rv;
    750      1.1  christos }
    751      1.1  christos 
    752      1.1  christos static void
    753      1.1  christos mem_put_val (SIM_DESC sd, int addr, int val, int bits)
    754      1.1  christos {
    755      1.1  christos   MSP430_Opcode_Decoded opc;
    756      1.1  christos 
    757      1.1  christos   opc.size = bits;
    758      1.1  christos   opc.op[0].type = MSP430_Operand_Indirect;
    759      1.1  christos   opc.op[0].addend = addr;
    760      1.1  christos   opc.op[0].reg = MSR_None;
    761      1.1  christos   put_op (sd, &opc, 0, val);
    762      1.1  christos }
    763      1.1  christos 
    764      1.1  christos static int
    765      1.1  christos mem_get_val (SIM_DESC sd, int addr, int bits)
    766      1.1  christos {
    767      1.1  christos   MSP430_Opcode_Decoded opc;
    768      1.1  christos 
    769      1.1  christos   opc.size = bits;
    770      1.1  christos   opc.op[0].type = MSP430_Operand_Indirect;
    771      1.1  christos   opc.op[0].addend = addr;
    772      1.1  christos   opc.op[0].reg = MSR_None;
    773      1.1  christos   return get_op (sd, &opc, 0);
    774      1.1  christos }
    775      1.1  christos 
    776      1.1  christos #define CIO_OPEN    (0xF0)
    777      1.1  christos #define CIO_CLOSE   (0xF1)
    778      1.1  christos #define CIO_READ    (0xF2)
    779      1.1  christos #define CIO_WRITE   (0xF3)
    780      1.1  christos #define CIO_LSEEK   (0xF4)
    781      1.1  christos #define CIO_UNLINK  (0xF5)
    782      1.1  christos #define CIO_GETENV  (0xF6)
    783      1.1  christos #define CIO_RENAME  (0xF7)
    784      1.1  christos #define CIO_GETTIME (0xF8)
    785      1.1  christos #define CIO_GETCLK  (0xF9)
    786      1.1  christos #define CIO_SYNC    (0xFF)
    787      1.1  christos 
    788      1.1  christos #define CIO_I(n) (parms[(n)] + parms[(n)+1] * 256)
    789      1.1  christos #define CIO_L(n) (parms[(n)] + parms[(n)+1] * 256 \
    790      1.1  christos 		  + parms[(n)+2] * 65536 + parms[(n)+3] * 16777216)
    791      1.1  christos 
    792      1.1  christos static void
    793      1.1  christos msp430_cio (SIM_DESC sd)
    794      1.1  christos {
    795      1.1  christos   /* A block of data at __CIOBUF__ describes the I/O operation to
    796      1.1  christos      perform.  */
    797  1.1.1.9  christos   sim_cpu *cpu = STATE_CPU (sd, 0);
    798  1.1.1.9  christos   struct msp430_cpu_state *msp430_cpu = MSP430_SIM_CPU (cpu);
    799      1.1  christos   unsigned char parms[8];
    800      1.1  christos   long length;
    801      1.1  christos   int command;
    802      1.1  christos   unsigned char buffer[512];
    803      1.1  christos   long ret_buflen = 0;
    804  1.1.1.9  christos   long fd, len, rv;
    805      1.1  christos 
    806  1.1.1.9  christos   sim_core_read_buffer (sd, cpu, 0, parms, msp430_cpu->cio_buffer, 5);
    807      1.1  christos   length = CIO_I (0);
    808      1.1  christos   command = parms[2];
    809      1.1  christos 
    810  1.1.1.9  christos   sim_core_read_buffer (sd, cpu, 0, parms, msp430_cpu->cio_buffer + 3, 8);
    811  1.1.1.9  christos   sim_core_read_buffer (sd, cpu, 0, buffer, msp430_cpu->cio_buffer + 11, length);
    812      1.1  christos 
    813      1.1  christos   switch (command)
    814      1.1  christos     {
    815      1.1  christos     case CIO_WRITE:
    816      1.1  christos       fd = CIO_I (0);
    817      1.1  christos       len = CIO_I (2);
    818      1.1  christos 
    819      1.1  christos       rv = write (fd, buffer, len);
    820      1.1  christos       parms[0] = rv & 0xff;
    821      1.1  christos       parms[1] = rv >> 8;
    822      1.1  christos 
    823      1.1  christos       break;
    824      1.1  christos     }
    825      1.1  christos 
    826  1.1.1.9  christos   sim_core_write_buffer (sd, cpu, 0, parms, msp430_cpu->cio_buffer + 4, 8);
    827      1.1  christos   if (ret_buflen)
    828  1.1.1.9  christos     sim_core_write_buffer (sd, cpu, 0, buffer, msp430_cpu->cio_buffer + 12,
    829  1.1.1.9  christos 			   ret_buflen);
    830      1.1  christos }
    831      1.1  christos 
    832      1.1  christos #define SRC     get_op (sd, opcode, 1)
    833      1.1  christos #define DSRC    get_op (sd, opcode, 0)
    834      1.1  christos #define DEST(V) put_op (sd, opcode, 0, (V))
    835      1.1  christos 
    836      1.1  christos #define DO_ALU(OP,SOP,MORE)						\
    837      1.1  christos   {									\
    838      1.1  christos     int s1 = DSRC;							\
    839      1.1  christos     int s2 = SRC;							\
    840      1.1  christos     int result = s1 OP s2 MORE;						\
    841  1.1.1.9  christos     TRACE_ALU (STATE_CPU (sd, 0), "ALU: %#x %s %#x %s = %#x", s1, SOP,	\
    842  1.1.1.3  christos 	       s2, #MORE, result); \
    843      1.1  christos     DEST (result);							\
    844      1.1  christos   }
    845      1.1  christos 
    846      1.1  christos #define SIGN   (1 << (opcode->size - 1))
    847      1.1  christos #define POS(x) (((x) & SIGN) ? 0 : 1)
    848      1.1  christos #define NEG(x) (((x) & SIGN) ? 1 : 0)
    849      1.1  christos 
    850      1.1  christos #define SX(v) sign_ext (v, opcode->size)
    851      1.1  christos #define ZX(v) zero_ext (v, opcode->size)
    852      1.1  christos 
    853      1.1  christos static char *
    854      1.1  christos flags2string (int f)
    855      1.1  christos {
    856      1.1  christos   static char buf[2][6];
    857      1.1  christos   static int bi = 0;
    858      1.1  christos   char *bp = buf[bi];
    859      1.1  christos 
    860      1.1  christos   bi = (bi + 1) % 2;
    861      1.1  christos 
    862      1.1  christos   bp[0] = f & MSP430_FLAG_V ? 'V' : '-';
    863      1.1  christos   bp[1] = f & MSP430_FLAG_N ? 'N' : '-';
    864      1.1  christos   bp[2] = f & MSP430_FLAG_Z ? 'Z' : '-';
    865      1.1  christos   bp[3] = f & MSP430_FLAG_C ? 'C' : '-';
    866      1.1  christos   bp[4] = 0;
    867      1.1  christos   return bp;
    868      1.1  christos }
    869      1.1  christos 
    870      1.1  christos /* Random number that won't show up in our usual logic.  */
    871      1.1  christos #define MAGIC_OVERFLOW 0x55000F
    872      1.1  christos 
    873      1.1  christos static void
    874      1.1  christos do_flags (SIM_DESC sd,
    875      1.1  christos 	  MSP430_Opcode_Decoded *opcode,
    876      1.1  christos 	  int vnz_val, /* Signed result.  */
    877      1.1  christos 	  int carry,
    878      1.1  christos 	  int overflow)
    879      1.1  christos {
    880      1.1  christos   int f = SR;
    881      1.1  christos   int new_f = 0;
    882      1.1  christos   int signbit = 1 << (opcode->size - 1);
    883      1.1  christos 
    884      1.1  christos   f &= ~opcode->flags_0;
    885      1.1  christos   f &= ~opcode->flags_set;
    886      1.1  christos   f |= opcode->flags_1;
    887      1.1  christos 
    888      1.1  christos   if (vnz_val & signbit)
    889      1.1  christos     new_f |= MSP430_FLAG_N;
    890      1.1  christos   if (! (vnz_val & ((signbit << 1) - 1)))
    891      1.1  christos     new_f |= MSP430_FLAG_Z;
    892      1.1  christos   if (overflow == MAGIC_OVERFLOW)
    893      1.1  christos     {
    894      1.1  christos       if (vnz_val != SX (vnz_val))
    895      1.1  christos 	new_f |= MSP430_FLAG_V;
    896      1.1  christos     }
    897      1.1  christos   else
    898      1.1  christos     if (overflow)
    899      1.1  christos       new_f |= MSP430_FLAG_V;
    900      1.1  christos   if (carry)
    901      1.1  christos     new_f |= MSP430_FLAG_C;
    902      1.1  christos 
    903      1.1  christos   new_f = f | (new_f & opcode->flags_set);
    904  1.1.1.3  christos   if (SR != new_f)
    905  1.1.1.9  christos     TRACE_ALU (STATE_CPU (sd, 0), "FLAGS: %s -> %s", flags2string (SR),
    906  1.1.1.3  christos 	       flags2string (new_f));
    907  1.1.1.3  christos   else
    908  1.1.1.9  christos     TRACE_ALU (STATE_CPU (sd, 0), "FLAGS: %s", flags2string (new_f));
    909      1.1  christos   SR = new_f;
    910      1.1  christos }
    911      1.1  christos 
    912      1.1  christos #define FLAGS(vnz,c)    do_flags (sd, opcode, vnz, c, MAGIC_OVERFLOW)
    913      1.1  christos #define FLAGSV(vnz,c,v) do_flags (sd, opcode, vnz, c, v)
    914      1.1  christos 
    915      1.1  christos /* These two assume unsigned 16-bit (four digit) words.
    916      1.1  christos    Mask off unwanted bits for byte operations.  */
    917      1.1  christos 
    918      1.1  christos static int
    919      1.1  christos bcd_to_binary (int v)
    920      1.1  christos {
    921      1.1  christos   int r = (  ((v >>  0) & 0xf) * 1
    922      1.1  christos 	   + ((v >>  4) & 0xf) * 10
    923      1.1  christos 	   + ((v >>  8) & 0xf) * 100
    924      1.1  christos 	   + ((v >> 12) & 0xf) * 1000);
    925      1.1  christos   return r;
    926      1.1  christos }
    927      1.1  christos 
    928      1.1  christos static int
    929      1.1  christos binary_to_bcd (int v)
    930      1.1  christos {
    931      1.1  christos   int r = ( ((v /    1) % 10) <<  0
    932      1.1  christos 	  | ((v /   10) % 10) <<  4
    933      1.1  christos 	  | ((v /  100) % 10) <<  8
    934      1.1  christos 	  | ((v / 1000) % 10) << 12);
    935      1.1  christos   return r;
    936      1.1  christos }
    937      1.1  christos 
    938      1.1  christos static const char *
    939      1.1  christos cond_string (int cond)
    940      1.1  christos {
    941      1.1  christos   switch (cond)
    942      1.1  christos     {
    943      1.1  christos     case MSC_nz:
    944      1.1  christos       return "NZ";
    945      1.1  christos     case MSC_z:
    946      1.1  christos       return "Z";
    947      1.1  christos     case MSC_nc:
    948      1.1  christos       return "NC";
    949      1.1  christos     case MSC_c:
    950      1.1  christos       return "C";
    951      1.1  christos     case MSC_n:
    952      1.1  christos       return "N";
    953      1.1  christos     case MSC_ge:
    954      1.1  christos       return "GE";
    955      1.1  christos     case MSC_l:
    956      1.1  christos       return "L";
    957      1.1  christos     case MSC_true:
    958      1.1  christos       return "MP";
    959      1.1  christos     default:
    960      1.1  christos       return "??";
    961      1.1  christos     }
    962      1.1  christos }
    963      1.1  christos 
    964      1.1  christos /* Checks a CALL to address CALL_ADDR.  If this is a special
    965      1.1  christos    syscall address then the call is simulated and non-zero is
    966      1.1  christos    returned.  Otherwise 0 is returned.  */
    967      1.1  christos 
    968      1.1  christos static int
    969      1.1  christos maybe_perform_syscall (SIM_DESC sd, int call_addr)
    970      1.1  christos {
    971  1.1.1.9  christos   sim_cpu *cpu = STATE_CPU (sd, 0);
    972  1.1.1.9  christos   struct msp430_cpu_state *msp430_cpu = MSP430_SIM_CPU (cpu);
    973  1.1.1.9  christos 
    974      1.1  christos   if (call_addr == 0x00160)
    975      1.1  christos     {
    976      1.1  christos       int i;
    977      1.1  christos 
    978      1.1  christos       for (i = 0; i < 16; i++)
    979      1.1  christos 	{
    980      1.1  christos 	  if (i % 4 == 0)
    981      1.1  christos 	    fprintf (stderr, "\t");
    982  1.1.1.9  christos 	  fprintf (stderr, "R%-2d %05x   ", i, msp430_cpu->regs[i]);
    983      1.1  christos 	  if (i % 4 == 3)
    984      1.1  christos 	    {
    985      1.1  christos 	      int sp = SP + (3 - (i / 4)) * 2;
    986      1.1  christos 	      unsigned char buf[2];
    987      1.1  christos 
    988  1.1.1.9  christos 	      sim_core_read_buffer (sd, cpu, read_map, buf, sp, 2);
    989      1.1  christos 
    990      1.1  christos 	      fprintf (stderr, "\tSP%+d: %04x", sp - SP,
    991      1.1  christos 		       buf[0] + buf[1] * 256);
    992      1.1  christos 
    993      1.1  christos 	      if (i / 4 == 0)
    994      1.1  christos 		{
    995      1.1  christos 		  int flags = SR;
    996      1.1  christos 
    997      1.1  christos 		  fprintf (stderr, flags & 0x100 ? "   V" : "   -");
    998      1.1  christos 		  fprintf (stderr, flags & 0x004 ? "N" : "-");
    999      1.1  christos 		  fprintf (stderr, flags & 0x002 ? "Z" : "-");
   1000      1.1  christos 		  fprintf (stderr, flags & 0x001 ? "C" : "-");
   1001      1.1  christos 		}
   1002      1.1  christos 
   1003      1.1  christos 	      fprintf (stderr, "\n");
   1004      1.1  christos 	    }
   1005      1.1  christos 	}
   1006      1.1  christos       return 1;
   1007      1.1  christos     }
   1008      1.1  christos 
   1009      1.1  christos   if ((call_addr & ~0x3f) == 0x00180)
   1010      1.1  christos     {
   1011      1.1  christos       /* Syscall!  */
   1012  1.1.1.6  christos       int arg1, arg2, arg3, arg4;
   1013      1.1  christos       int syscall_num = call_addr & 0x3f;
   1014  1.1.1.6  christos 
   1015  1.1.1.6  christos       /* syscall_num == 2 is used for the variadic function "open".
   1016  1.1.1.6  christos 	 The arguments are set up differently for variadic functions.
   1017  1.1.1.6  christos 	 See slaa534.pdf distributed by TI.  */
   1018  1.1.1.6  christos       if (syscall_num == 2)
   1019  1.1.1.6  christos 	{
   1020  1.1.1.9  christos 	  arg1 = msp430_cpu->regs[12];
   1021  1.1.1.6  christos 	  arg2 = mem_get_val (sd, SP, 16);
   1022  1.1.1.6  christos 	  arg3 = mem_get_val (sd, SP + 2, 16);
   1023  1.1.1.6  christos 	  arg4 = mem_get_val (sd, SP + 4, 16);
   1024  1.1.1.6  christos 	}
   1025  1.1.1.6  christos       else
   1026  1.1.1.6  christos 	{
   1027  1.1.1.9  christos 	  arg1 = msp430_cpu->regs[12];
   1028  1.1.1.9  christos 	  arg2 = msp430_cpu->regs[13];
   1029  1.1.1.9  christos 	  arg3 = msp430_cpu->regs[14];
   1030  1.1.1.9  christos 	  arg4 = msp430_cpu->regs[15];
   1031  1.1.1.6  christos 	}
   1032  1.1.1.3  christos 
   1033  1.1.1.9  christos       msp430_cpu->regs[12] = sim_syscall (cpu, syscall_num, arg1, arg2, arg3,
   1034  1.1.1.9  christos 					  arg4);
   1035      1.1  christos       return 1;
   1036      1.1  christos     }
   1037      1.1  christos 
   1038      1.1  christos   return 0;
   1039      1.1  christos }
   1040      1.1  christos 
   1041      1.1  christos static void
   1042      1.1  christos msp430_step_once (SIM_DESC sd)
   1043      1.1  christos {
   1044  1.1.1.9  christos   sim_cpu *cpu = STATE_CPU (sd, 0);
   1045  1.1.1.9  christos   struct msp430_cpu_state *msp430_cpu = MSP430_SIM_CPU (cpu);
   1046      1.1  christos   Get_Byte_Local_Data ld;
   1047      1.1  christos   int i;
   1048      1.1  christos   int opsize;
   1049      1.1  christos   unsigned int opcode_pc;
   1050      1.1  christos   MSP430_Opcode_Decoded opcode_buf;
   1051      1.1  christos   MSP430_Opcode_Decoded *opcode = &opcode_buf;
   1052      1.1  christos   int s1, s2, result;
   1053  1.1.1.6  christos   int u1 = 0, u2, uresult;
   1054  1.1.1.9  christos   int c = 0;
   1055      1.1  christos   int carry_to_use;
   1056      1.1  christos   int n_repeats;
   1057      1.1  christos   int rept;
   1058  1.1.1.6  christos   int op_bytes = 0, op_bits;
   1059      1.1  christos 
   1060      1.1  christos   PC &= 0xfffff;
   1061      1.1  christos   opcode_pc = PC;
   1062      1.1  christos 
   1063      1.1  christos   if (opcode_pc < 0x10)
   1064      1.1  christos     {
   1065      1.1  christos       fprintf (stderr, "Fault: PC(%#x) is less than 0x10\n", opcode_pc);
   1066  1.1.1.9  christos       sim_engine_halt (sd, cpu, NULL, msp430_cpu->regs[0], sim_exited, -1);
   1067      1.1  christos       return;
   1068      1.1  christos     }
   1069      1.1  christos 
   1070  1.1.1.9  christos   if (PC == msp430_cpu->cio_breakpoint && STATE_OPEN_KIND (sd) != SIM_OPEN_DEBUG)
   1071      1.1  christos     msp430_cio (sd);
   1072      1.1  christos 
   1073      1.1  christos   ld.sd = sd;
   1074      1.1  christos   ld.gb_addr = PC;
   1075  1.1.1.9  christos   opsize = msp430_decode_opcode (msp430_cpu->regs[0], opcode, msp430_getbyte,
   1076  1.1.1.9  christos 				 &ld);
   1077      1.1  christos   PC += opsize;
   1078      1.1  christos   if (opsize <= 0)
   1079      1.1  christos     {
   1080      1.1  christos       fprintf (stderr, "Fault: undecodable opcode at %#x\n", opcode_pc);
   1081  1.1.1.9  christos       sim_engine_halt (sd, cpu, NULL, msp430_cpu->regs[0], sim_exited, -1);
   1082      1.1  christos       return;
   1083      1.1  christos     }
   1084      1.1  christos 
   1085      1.1  christos   if (opcode->repeat_reg)
   1086  1.1.1.9  christos     n_repeats = (msp430_cpu->regs[opcode->repeats] & 0x000f) + 1;
   1087      1.1  christos   else
   1088      1.1  christos     n_repeats = opcode->repeats + 1;
   1089      1.1  christos 
   1090      1.1  christos   op_bits = opcode->size;
   1091      1.1  christos   switch (op_bits)
   1092      1.1  christos     {
   1093      1.1  christos     case 8:
   1094      1.1  christos       op_bytes = 1;
   1095      1.1  christos       break;
   1096      1.1  christos     case 16:
   1097      1.1  christos       op_bytes = 2;
   1098      1.1  christos       break;
   1099      1.1  christos     case 20:
   1100      1.1  christos     case 32:
   1101      1.1  christos       op_bytes = 4;
   1102      1.1  christos       break;
   1103      1.1  christos     }
   1104      1.1  christos 
   1105  1.1.1.9  christos   if (TRACE_ANY_P (cpu))
   1106  1.1.1.9  christos     trace_prefix (sd, cpu, NULL_CIA, opcode_pc, TRACE_LINENUM_P (cpu), NULL,
   1107  1.1.1.9  christos 		  0, " ");
   1108      1.1  christos 
   1109  1.1.1.9  christos   TRACE_DISASM (cpu, opcode_pc);
   1110  1.1.1.4  christos 
   1111      1.1  christos   carry_to_use = 0;
   1112      1.1  christos   switch (opcode->id)
   1113      1.1  christos     {
   1114      1.1  christos     case MSO_unknown:
   1115      1.1  christos       break;
   1116      1.1  christos 
   1117      1.1  christos       /* Double-operand instructions.  */
   1118      1.1  christos     case MSO_mov:
   1119      1.1  christos       if (opcode->n_bytes == 2
   1120      1.1  christos 	  && opcode->op[0].type == MSP430_Operand_Register
   1121      1.1  christos 	  && opcode->op[0].reg == MSR_CG
   1122      1.1  christos 	  && opcode->op[1].type == MSP430_Operand_Immediate
   1123      1.1  christos 	  && opcode->op[1].addend == 0
   1124      1.1  christos 	  /* A 16-bit write of #0 is a NOP; an 8-bit write is a BRK.  */
   1125      1.1  christos 	  && opcode->size == 8)
   1126      1.1  christos 	{
   1127      1.1  christos 	  /* This is the designated software breakpoint instruction.  */
   1128      1.1  christos 	  PC -= opsize;
   1129  1.1.1.9  christos 	  sim_engine_halt (sd, cpu, NULL, msp430_cpu->regs[0], sim_stopped,
   1130  1.1.1.9  christos 			   SIM_SIGTRAP);
   1131      1.1  christos 	}
   1132      1.1  christos       else
   1133      1.1  christos 	{
   1134      1.1  christos 	  /* Otherwise, do the move.  */
   1135      1.1  christos 	  for (rept = 0; rept < n_repeats; rept ++)
   1136      1.1  christos 	    {
   1137      1.1  christos 	      DEST (SRC);
   1138      1.1  christos 	    }
   1139      1.1  christos 	}
   1140      1.1  christos       break;
   1141      1.1  christos 
   1142      1.1  christos     case MSO_addc:
   1143      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1144      1.1  christos 	{
   1145      1.1  christos 	  carry_to_use = (SR & MSP430_FLAG_C) ? 1 : 0;
   1146      1.1  christos 	  u1 = DSRC;
   1147      1.1  christos 	  u2 = SRC;
   1148      1.1  christos 	  s1 = SX (u1);
   1149      1.1  christos 	  s2 = SX (u2);
   1150      1.1  christos 	  uresult = u1 + u2 + carry_to_use;
   1151      1.1  christos 	  result = s1 + s2 + carry_to_use;
   1152  1.1.1.9  christos 	  TRACE_ALU (cpu, "ADDC: %#x + %#x + %d = %#x",
   1153  1.1.1.3  christos 		     u1, u2, carry_to_use, uresult);
   1154      1.1  christos 	  DEST (result);
   1155      1.1  christos 	  FLAGS (result, uresult != ZX (uresult));
   1156      1.1  christos 	}
   1157      1.1  christos       break;
   1158      1.1  christos 
   1159      1.1  christos     case MSO_add:
   1160      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1161      1.1  christos 	{
   1162      1.1  christos 	  u1 = DSRC;
   1163      1.1  christos 	  u2 = SRC;
   1164      1.1  christos 	  s1 = SX (u1);
   1165      1.1  christos 	  s2 = SX (u2);
   1166      1.1  christos 	  uresult = u1 + u2;
   1167      1.1  christos 	  result = s1 + s2;
   1168  1.1.1.9  christos 	  TRACE_ALU (cpu, "ADD: %#x + %#x = %#x", u1, u2, uresult);
   1169      1.1  christos 	  DEST (result);
   1170      1.1  christos 	  FLAGS (result, uresult != ZX (uresult));
   1171      1.1  christos 	}
   1172      1.1  christos       break;
   1173      1.1  christos 
   1174      1.1  christos     case MSO_subc:
   1175      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1176      1.1  christos 	{
   1177      1.1  christos 	  carry_to_use = (SR & MSP430_FLAG_C) ? 1 : 0;
   1178      1.1  christos 	  u1 = DSRC;
   1179      1.1  christos 	  u2 = SRC;
   1180      1.1  christos 	  s1 = SX (u1);
   1181      1.1  christos 	  s2 = SX (u2);
   1182      1.1  christos 	  uresult = ZX (~u2) + u1 + carry_to_use;
   1183      1.1  christos 	  result = s1 - s2 + (carry_to_use - 1);
   1184  1.1.1.9  christos 	  TRACE_ALU (cpu, "SUBC: %#x - %#x + %d = %#x",
   1185  1.1.1.3  christos 		     u1, u2, carry_to_use, uresult);
   1186      1.1  christos 	  DEST (result);
   1187      1.1  christos 	  FLAGS (result, uresult != ZX (uresult));
   1188      1.1  christos 	}
   1189      1.1  christos       break;
   1190      1.1  christos 
   1191      1.1  christos     case MSO_sub:
   1192      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1193      1.1  christos 	{
   1194      1.1  christos 	  u1 = DSRC;
   1195      1.1  christos 	  u2 = SRC;
   1196      1.1  christos 	  s1 = SX (u1);
   1197      1.1  christos 	  s2 = SX (u2);
   1198      1.1  christos 	  uresult = ZX (~u2) + u1 + 1;
   1199      1.1  christos 	  result = SX (uresult);
   1200  1.1.1.9  christos 	  TRACE_ALU (cpu, "SUB: %#x - %#x = %#x",
   1201  1.1.1.3  christos 		     u1, u2, uresult);
   1202      1.1  christos 	  DEST (result);
   1203      1.1  christos 	  FLAGS (result, uresult != ZX (uresult));
   1204      1.1  christos 	}
   1205      1.1  christos       break;
   1206      1.1  christos 
   1207      1.1  christos     case MSO_cmp:
   1208      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1209      1.1  christos 	{
   1210      1.1  christos 	  u1 = DSRC;
   1211      1.1  christos 	  u2 = SRC;
   1212      1.1  christos 	  s1 = SX (u1);
   1213      1.1  christos 	  s2 = SX (u2);
   1214      1.1  christos 	  uresult = ZX (~u2) + u1 + 1;
   1215      1.1  christos 	  result = s1 - s2;
   1216  1.1.1.9  christos 	  TRACE_ALU (cpu, "CMP: %#x - %#x = %x",
   1217  1.1.1.3  christos 		     u1, u2, uresult);
   1218      1.1  christos 	  FLAGS (result, uresult != ZX (uresult));
   1219      1.1  christos 	}
   1220      1.1  christos       break;
   1221      1.1  christos 
   1222      1.1  christos     case MSO_dadd:
   1223      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1224      1.1  christos 	{
   1225      1.1  christos 	  carry_to_use = (SR & MSP430_FLAG_C) ? 1 : 0;
   1226      1.1  christos 	  u1 = DSRC;
   1227      1.1  christos 	  u2 = SRC;
   1228      1.1  christos 	  uresult = bcd_to_binary (u1) + bcd_to_binary (u2) + carry_to_use;
   1229      1.1  christos 	  result = binary_to_bcd (uresult);
   1230  1.1.1.9  christos 	  TRACE_ALU (cpu, "DADD: %#x + %#x + %d = %#x",
   1231  1.1.1.3  christos 		     u1, u2, carry_to_use, result);
   1232      1.1  christos 	  DEST (result);
   1233      1.1  christos 	  FLAGS (result, uresult > ((opcode->size == 8) ? 99 : 9999));
   1234      1.1  christos 	}
   1235      1.1  christos       break;
   1236      1.1  christos 
   1237      1.1  christos     case MSO_and:
   1238      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1239      1.1  christos 	{
   1240      1.1  christos 	  u1 = DSRC;
   1241      1.1  christos 	  u2 = SRC;
   1242      1.1  christos 	  uresult = u1 & u2;
   1243  1.1.1.9  christos 	  TRACE_ALU (cpu, "AND: %#x & %#x = %#x",
   1244  1.1.1.3  christos 		     u1, u2, uresult);
   1245      1.1  christos 	  DEST (uresult);
   1246      1.1  christos 	  FLAGS (uresult, uresult != 0);
   1247      1.1  christos 	}
   1248      1.1  christos       break;
   1249      1.1  christos 
   1250      1.1  christos     case MSO_bit:
   1251      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1252      1.1  christos 	{
   1253      1.1  christos 	  u1 = DSRC;
   1254      1.1  christos 	  u2 = SRC;
   1255      1.1  christos 	  uresult = u1 & u2;
   1256  1.1.1.9  christos 	  TRACE_ALU (cpu, "BIT: %#x & %#x -> %#x",
   1257  1.1.1.3  christos 		     u1, u2, uresult);
   1258      1.1  christos 	  FLAGS (uresult, uresult != 0);
   1259      1.1  christos 	}
   1260      1.1  christos       break;
   1261      1.1  christos 
   1262      1.1  christos     case MSO_bic:
   1263      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1264      1.1  christos 	{
   1265      1.1  christos 	  u1 = DSRC;
   1266      1.1  christos 	  u2 = SRC;
   1267      1.1  christos 	  uresult = u1 & ~ u2;
   1268  1.1.1.9  christos 	  TRACE_ALU (cpu, "BIC: %#x & ~ %#x = %#x",
   1269  1.1.1.3  christos 		     u1, u2, uresult);
   1270      1.1  christos 	  DEST (uresult);
   1271      1.1  christos 	}
   1272      1.1  christos       break;
   1273      1.1  christos 
   1274      1.1  christos     case MSO_bis:
   1275      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1276      1.1  christos 	{
   1277      1.1  christos 	  u1 = DSRC;
   1278      1.1  christos 	  u2 = SRC;
   1279      1.1  christos 	  uresult = u1 | u2;
   1280  1.1.1.9  christos 	  TRACE_ALU (cpu, "BIS: %#x | %#x = %#x",
   1281  1.1.1.3  christos 		     u1, u2, uresult);
   1282      1.1  christos 	  DEST (uresult);
   1283      1.1  christos 	}
   1284      1.1  christos       break;
   1285      1.1  christos 
   1286      1.1  christos     case MSO_xor:
   1287      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1288      1.1  christos 	{
   1289      1.1  christos 	  s1 = 1 << (opcode->size - 1);
   1290      1.1  christos 	  u1 = DSRC;
   1291      1.1  christos 	  u2 = SRC;
   1292      1.1  christos 	  uresult = u1 ^ u2;
   1293  1.1.1.9  christos 	  TRACE_ALU (cpu, "XOR: %#x & %#x = %#x",
   1294  1.1.1.3  christos 		     u1, u2, uresult);
   1295      1.1  christos 	  DEST (uresult);
   1296      1.1  christos 	  FLAGSV (uresult, uresult != 0, (u1 & s1) && (u2 & s1));
   1297      1.1  christos 	}
   1298      1.1  christos       break;
   1299      1.1  christos 
   1300      1.1  christos     /* Single-operand instructions.  Note: the decoder puts the same
   1301      1.1  christos        operand in SRC as in DEST, for our convenience.  */
   1302      1.1  christos 
   1303      1.1  christos     case MSO_rrc:
   1304      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1305      1.1  christos 	{
   1306      1.1  christos 	  u1 = SRC;
   1307      1.1  christos 	  carry_to_use = u1 & 1;
   1308      1.1  christos 	  uresult = u1 >> 1;
   1309  1.1.1.7  christos 	  /* If the ZC bit of the opcode is set, it means we are synthesizing
   1310  1.1.1.7  christos 	     RRUX, so the carry bit must be ignored.  */
   1311  1.1.1.7  christos 	  if (opcode->zc == 0 && (SR & MSP430_FLAG_C))
   1312  1.1.1.7  christos 	    uresult |= (1 << (opcode->size - 1));
   1313  1.1.1.9  christos 	  TRACE_ALU (cpu, "RRC: %#x >>= %#x",
   1314  1.1.1.3  christos 		     u1, uresult);
   1315      1.1  christos 	  DEST (uresult);
   1316      1.1  christos 	  FLAGS (uresult, carry_to_use);
   1317      1.1  christos 	}
   1318      1.1  christos       break;
   1319      1.1  christos 
   1320      1.1  christos     case MSO_swpb:
   1321      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1322      1.1  christos 	{
   1323      1.1  christos 	  u1 = SRC;
   1324      1.1  christos 	  uresult = ((u1 >> 8) & 0x00ff) | ((u1 << 8) & 0xff00);
   1325  1.1.1.9  christos 	  TRACE_ALU (cpu, "SWPB: %#x -> %#x",
   1326  1.1.1.3  christos 		     u1, uresult);
   1327      1.1  christos 	  DEST (uresult);
   1328      1.1  christos 	}
   1329      1.1  christos       break;
   1330      1.1  christos 
   1331      1.1  christos     case MSO_rra:
   1332      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1333      1.1  christos 	{
   1334      1.1  christos 	  u1 = SRC;
   1335      1.1  christos 	  c = u1 & 1;
   1336      1.1  christos 	  s1 = 1 << (opcode->size - 1);
   1337      1.1  christos 	  uresult = (u1 >> 1) | (u1 & s1);
   1338  1.1.1.9  christos 	  TRACE_ALU (cpu, "RRA: %#x >>= %#x",
   1339  1.1.1.3  christos 		     u1, uresult);
   1340      1.1  christos 	  DEST (uresult);
   1341      1.1  christos 	  FLAGS (uresult, c);
   1342      1.1  christos 	}
   1343      1.1  christos       break;
   1344      1.1  christos 
   1345      1.1  christos     case MSO_rru:
   1346      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1347      1.1  christos 	{
   1348      1.1  christos 	  u1 = SRC;
   1349      1.1  christos 	  c = u1 & 1;
   1350      1.1  christos 	  uresult = (u1 >> 1);
   1351  1.1.1.9  christos 	  TRACE_ALU (cpu, "RRU: %#x >>= %#x",
   1352  1.1.1.3  christos 		     u1, uresult);
   1353      1.1  christos 	  DEST (uresult);
   1354      1.1  christos 	  FLAGS (uresult, c);
   1355      1.1  christos 	}
   1356      1.1  christos       break;
   1357      1.1  christos 
   1358      1.1  christos     case MSO_sxt:
   1359      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1360      1.1  christos 	{
   1361      1.1  christos 	  u1 = SRC;
   1362      1.1  christos 	  if (u1 & 0x80)
   1363      1.1  christos 	    uresult = u1 | 0xfff00;
   1364      1.1  christos 	  else
   1365      1.1  christos 	    uresult = u1 & 0x000ff;
   1366  1.1.1.9  christos 	  TRACE_ALU (cpu, "SXT: %#x -> %#x", u1, uresult);
   1367      1.1  christos 	  DEST (uresult);
   1368      1.1  christos 	  FLAGS (uresult, c);
   1369      1.1  christos 	}
   1370      1.1  christos       break;
   1371      1.1  christos 
   1372      1.1  christos     case MSO_push:
   1373      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1374      1.1  christos 	{
   1375      1.1  christos 	  int new_sp;
   1376      1.1  christos 
   1377      1.1  christos 	  new_sp = REG_GET (MSR_SP) - op_bytes;
   1378      1.1  christos 	  /* SP is always word-aligned.  */
   1379      1.1  christos 	  if (new_sp & 1)
   1380      1.1  christos 	    new_sp --;
   1381      1.1  christos 	  REG_PUT (MSR_SP, new_sp);
   1382      1.1  christos 	  u1 = SRC;
   1383      1.1  christos 	  mem_put_val (sd, SP, u1, op_bits);
   1384      1.1  christos 	  if (opcode->op[1].type == MSP430_Operand_Register)
   1385      1.1  christos 	    opcode->op[1].reg --;
   1386      1.1  christos 	}
   1387      1.1  christos       break;
   1388      1.1  christos 
   1389      1.1  christos     case MSO_pop:
   1390      1.1  christos       for (rept = 0; rept < n_repeats; rept ++)
   1391      1.1  christos 	{
   1392      1.1  christos 	  int new_sp;
   1393      1.1  christos 
   1394      1.1  christos 	  u1 = mem_get_val (sd, SP, op_bits);
   1395      1.1  christos 	  DEST (u1);
   1396      1.1  christos 	  if (opcode->op[0].type == MSP430_Operand_Register)
   1397      1.1  christos 	    opcode->op[0].reg ++;
   1398      1.1  christos 	  new_sp = REG_GET (MSR_SP) + op_bytes;
   1399      1.1  christos 	  /* SP is always word-aligned.  */
   1400      1.1  christos 	  if (new_sp & 1)
   1401      1.1  christos 	    new_sp ++;
   1402      1.1  christos 	  REG_PUT (MSR_SP, new_sp);
   1403      1.1  christos 	}
   1404      1.1  christos       break;
   1405      1.1  christos 
   1406      1.1  christos     case MSO_call:
   1407      1.1  christos       u1 = SRC;
   1408      1.1  christos 
   1409      1.1  christos       if (maybe_perform_syscall (sd, u1))
   1410      1.1  christos 	break;
   1411      1.1  christos 
   1412      1.1  christos       REG_PUT (MSR_SP, REG_GET (MSR_SP) - op_bytes);
   1413      1.1  christos       mem_put_val (sd, SP, PC, op_bits);
   1414  1.1.1.9  christos       TRACE_ALU (cpu, "CALL: func %#x ret %#x, sp %#x",
   1415  1.1.1.3  christos 	         u1, PC, SP);
   1416      1.1  christos       REG_PUT (MSR_PC, u1);
   1417      1.1  christos       break;
   1418      1.1  christos 
   1419      1.1  christos     case MSO_reti:
   1420  1.1.1.2  christos       u1 = mem_get_val (sd, SP, 16);
   1421  1.1.1.2  christos       SR = u1 & 0xFF;
   1422      1.1  christos       SP += 2;
   1423  1.1.1.2  christos       PC = mem_get_val (sd, SP, 16);
   1424      1.1  christos       SP += 2;
   1425  1.1.1.2  christos       /* Emulate the RETI action of the 20-bit CPUX architecure.
   1426  1.1.1.2  christos 	 This is safe for 16-bit CPU architectures as well, since the top
   1427  1.1.1.2  christos 	 8-bits of SR will have been written to the stack here, and will
   1428  1.1.1.2  christos 	 have been read as 0.  */
   1429  1.1.1.2  christos       PC |= (u1 & 0xF000) << 4;
   1430  1.1.1.9  christos       TRACE_ALU (cpu, "RETI: pc %#x sr %#x", PC, SR);
   1431      1.1  christos       break;
   1432      1.1  christos 
   1433      1.1  christos       /* Jumps.  */
   1434      1.1  christos 
   1435      1.1  christos     case MSO_jmp:
   1436      1.1  christos       i = SRC;
   1437      1.1  christos       switch (opcode->cond)
   1438      1.1  christos 	{
   1439      1.1  christos 	case MSC_nz:
   1440      1.1  christos 	  u1 = (SR & MSP430_FLAG_Z) ? 0 : 1;
   1441      1.1  christos 	  break;
   1442      1.1  christos 	case MSC_z:
   1443      1.1  christos 	  u1 = (SR & MSP430_FLAG_Z) ? 1 : 0;
   1444      1.1  christos 	  break;
   1445      1.1  christos 	case MSC_nc:
   1446      1.1  christos 	  u1 = (SR & MSP430_FLAG_C) ? 0 : 1;
   1447      1.1  christos 	  break;
   1448      1.1  christos 	case MSC_c:
   1449      1.1  christos 	  u1 = (SR & MSP430_FLAG_C) ? 1 : 0;
   1450      1.1  christos 	  break;
   1451      1.1  christos 	case MSC_n:
   1452      1.1  christos 	  u1 = (SR & MSP430_FLAG_N) ? 1 : 0;
   1453      1.1  christos 	  break;
   1454      1.1  christos 	case MSC_ge:
   1455      1.1  christos 	  u1 = (!!(SR & MSP430_FLAG_N) == !!(SR & MSP430_FLAG_V)) ? 1 : 0;
   1456      1.1  christos 	  break;
   1457      1.1  christos 	case MSC_l:
   1458      1.1  christos 	  u1 = (!!(SR & MSP430_FLAG_N) == !!(SR & MSP430_FLAG_V)) ? 0 : 1;
   1459      1.1  christos 	  break;
   1460      1.1  christos 	case MSC_true:
   1461      1.1  christos 	  u1 = 1;
   1462      1.1  christos 	  break;
   1463      1.1  christos 	}
   1464      1.1  christos 
   1465      1.1  christos       if (u1)
   1466      1.1  christos 	{
   1467  1.1.1.9  christos 	  TRACE_BRANCH (cpu, "J%s: pc %#x -> %#x sr %#x, taken",
   1468  1.1.1.3  christos 			cond_string (opcode->cond), PC, i, SR);
   1469      1.1  christos 	  PC = i;
   1470      1.1  christos 	  if (PC == opcode_pc)
   1471      1.1  christos 	    exit (0);
   1472      1.1  christos 	}
   1473      1.1  christos       else
   1474  1.1.1.9  christos 	TRACE_BRANCH (cpu, "J%s: pc %#x to %#x sr %#x, not taken",
   1475  1.1.1.3  christos 		      cond_string (opcode->cond), PC, i, SR);
   1476      1.1  christos       break;
   1477      1.1  christos 
   1478      1.1  christos     default:
   1479      1.1  christos       fprintf (stderr, "error: unexpected opcode id %d\n", opcode->id);
   1480      1.1  christos       exit (1);
   1481      1.1  christos     }
   1482      1.1  christos }
   1483      1.1  christos 
   1484      1.1  christos void
   1485      1.1  christos sim_engine_run (SIM_DESC sd,
   1486      1.1  christos 		int next_cpu_nr,
   1487      1.1  christos 		int nr_cpus,
   1488      1.1  christos 		int siggnal)
   1489      1.1  christos {
   1490      1.1  christos   while (1)
   1491      1.1  christos     {
   1492      1.1  christos       msp430_step_once (sd);
   1493      1.1  christos       if (sim_events_tick (sd))
   1494      1.1  christos 	sim_events_process (sd);
   1495      1.1  christos     }
   1496      1.1  christos }
   1497