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