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