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