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