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