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