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