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