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