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