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