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