1 /* Simulation code for the CR16 processor.
2 Copyright (C) 2008-2020 Free Software Foundation, Inc.
3 Contributed by M Ranga Swami Reddy <MR.Swami.Reddy@nsc.com>
4
5 This file is part of GDB, the GNU debugger.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "config.h"
21 #include <inttypes.h>
22 #include <signal.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include "bfd.h"
26 #include "gdb/callback.h"
27 #include "gdb/remote-sim.h"
28
29 #include "sim-main.h"
30 #include "sim-options.h"
31
32 #include "gdb/sim-cr16.h"
33 #include "gdb/signals.h"
34 #include "opcode/cr16.h"
35
36 int cr16_debug;
37
38 uint32 OP[4];
39 uint32 sign_flag;
40
41 static struct hash_entry *lookup_hash (SIM_DESC, SIM_CPU *, uint64 ins, int size);
42 static void get_operands (operand_desc *s, uint64 mcode, int isize, int nops);
43
44 #define MAX_HASH 16
45
46 struct hash_entry
47 {
48 struct hash_entry *next;
49 uint32 opcode;
50 uint32 mask;
51 int format;
52 int size;
53 struct simops *ops;
54 };
55
56 struct hash_entry hash_table[MAX_HASH+1];
57
58 INLINE static long
hash(unsigned long long insn,int format)59 hash(unsigned long long insn, int format)
60 {
61 unsigned int i = 4, tmp;
62 if (format)
63 {
64 while ((insn >> i) != 0) i +=4;
65
66 return ((insn >> (i-4)) & 0xf); /* Use last 4 bits as hask key. */
67 }
68 return ((insn & 0xF)); /* Use last 4 bits as hask key. */
69 }
70
71
72 INLINE static struct hash_entry *
lookup_hash(SIM_DESC sd,SIM_CPU * cpu,uint64 ins,int size)73 lookup_hash (SIM_DESC sd, SIM_CPU *cpu, uint64 ins, int size)
74 {
75 uint32 mask;
76 struct hash_entry *h;
77
78 h = &hash_table[hash(ins,1)];
79
80
81 mask = (((1 << (32 - h->mask)) -1) << h->mask);
82
83 /* Adjuest mask for branch with 2 word instructions. */
84 if ((h->ops->mnimonic != NULL) &&
85 ((streq(h->ops->mnimonic,"b") && h->size == 2)))
86 mask = 0xff0f0000;
87
88
89 while ((ins & mask) != (BIN(h->opcode, h->mask)))
90 {
91 if (h->next == NULL)
92 sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, SIM_SIGILL);
93 h = h->next;
94
95 mask = (((1 << (32 - h->mask)) -1) << h->mask);
96 /* Adjuest mask for branch with 2 word instructions. */
97 if ((streq(h->ops->mnimonic,"b")) && h->size == 2)
98 mask = 0xff0f0000;
99
100 }
101 return (h);
102 }
103
104 INLINE static void
get_operands(operand_desc * s,uint64 ins,int isize,int nops)105 get_operands (operand_desc *s, uint64 ins, int isize, int nops)
106 {
107 uint32 i, opn = 0, start_bit = 0, op_type = 0;
108 int32 op_size = 0, mask = 0;
109
110 if (isize == 1) /* Trunkcate the extra 16 bits of INS. */
111 ins = ins >> 16;
112
113 for (i=0; i < 4; ++i,++opn)
114 {
115 if (s[opn].op_type == dummy) break;
116
117 op_type = s[opn].op_type;
118 start_bit = s[opn].shift;
119 op_size = cr16_optab[op_type].bit_size;
120
121 switch (op_type)
122 {
123 case imm3: case imm4: case imm5: case imm6:
124 {
125 if (isize == 1)
126 OP[i] = ((ins >> 4) & ((1 << op_size) -1));
127 else
128 OP[i] = ((ins >> (32 - start_bit)) & ((1 << op_size) -1));
129
130 if (OP[i] & ((long)1 << (op_size -1)))
131 {
132 sign_flag = 1;
133 OP[i] = ~(OP[i]) + 1;
134 }
135 OP[i] = (unsigned long int)(OP[i] & (((long)1 << op_size) -1));
136 }
137 break;
138
139 case uimm3: case uimm3_1: case uimm4_1:
140 switch (isize)
141 {
142 case 1:
143 OP[i] = ((ins >> 4) & ((1 << op_size) -1)); break;
144 case 2:
145 OP[i] = ((ins >> (32 - start_bit)) & ((1 << op_size) -1));break;
146 default: /* for case 3. */
147 OP[i] = ((ins >> (16 + start_bit)) & ((1 << op_size) -1)); break;
148 break;
149 }
150 break;
151
152 case uimm4:
153 switch (isize)
154 {
155 case 1:
156 if (start_bit == 20)
157 OP[i] = ((ins >> 4) & ((1 << op_size) -1));
158 else
159 OP[i] = (ins & ((1 << op_size) -1));
160 break;
161 case 2:
162 OP[i] = ((ins >> start_bit) & ((1 << op_size) -1));
163 break;
164 case 3:
165 OP[i] = ((ins >> (start_bit + 16)) & ((1 << op_size) -1));
166 break;
167 default:
168 OP[i] = ((ins >> start_bit) & ((1 << op_size) -1));
169 break;
170 }
171 break;
172
173 case imm16: case uimm16:
174 OP[i] = ins & 0xFFFF;
175 break;
176
177 case uimm20: case imm20:
178 OP[i] = ins & (((long)1 << op_size) - 1);
179 break;
180
181 case imm32: case uimm32:
182 OP[i] = ins & 0xFFFFFFFF;
183 break;
184
185 case uimm5: break; /*NOT USED. */
186 OP[i] = ins & ((1 << op_size) - 1); break;
187
188 case disps5:
189 OP[i] = (ins >> 4) & ((1 << 4) - 1);
190 OP[i] = (OP[i] * 2) + 2;
191 if (OP[i] & ((long)1 << 5))
192 {
193 sign_flag = 1;
194 OP[i] = ~(OP[i]) + 1;
195 OP[i] = (unsigned long int)(OP[i] & 0x1F);
196 }
197 break;
198
199 case dispe9:
200 OP[i] = ((((ins >> 8) & 0xf) << 4) | (ins & 0xf));
201 OP[i] <<= 1;
202 if (OP[i] & ((long)1 << 8))
203 {
204 sign_flag = 1;
205 OP[i] = ~(OP[i]) + 1;
206 OP[i] = (unsigned long int)(OP[i] & 0xFF);
207 }
208 break;
209
210 case disps17:
211 OP[i] = (ins & 0xFFFF);
212 if (OP[i] & 1)
213 {
214 OP[i] = (OP[i] & 0xFFFE);
215 sign_flag = 1;
216 OP[i] = ~(OP[i]) + 1;
217 OP[i] = (unsigned long int)(OP[i] & 0xFFFF);
218 }
219 break;
220
221 case disps25:
222 if (isize == 2)
223 OP[i] = (ins & 0xFFFFFF);
224 else
225 OP[i] = (ins & 0xFFFF) | (((ins >> 24) & 0xf) << 16) |
226 (((ins >> 16) & 0xf) << 20);
227
228 if (OP[i] & 1)
229 {
230 OP[i] = (OP[i] & 0xFFFFFE);
231 sign_flag = 1;
232 OP[i] = ~(OP[i]) + 1;
233 OP[i] = (unsigned long int)(OP[i] & 0xFFFFFF);
234 }
235 break;
236
237 case abs20:
238 if (isize == 3)
239 OP[i] = (ins) & 0xFFFFF;
240 else
241 OP[i] = (ins >> start_bit) & 0xFFFFF;
242 break;
243 case abs24:
244 if (isize == 3)
245 OP[i] = ((ins & 0xFFFF) | (((ins >> 16) & 0xf) << 20)
246 | (((ins >> 24) & 0xf) << 16));
247 else
248 OP[i] = (ins >> 16) & 0xFFFFFF;
249 break;
250
251 case rra:
252 case rbase: break; /* NOT USED. */
253 case rbase_disps20: case rbase_dispe20:
254 case rpbase_disps20: case rpindex_disps20:
255 OP[i] = ((((ins >> 24)&0xf) << 16)|((ins) & 0xFFFF));
256 OP[++i] = (ins >> 16) & 0xF; /* get 4 bit for reg. */
257 break;
258 case rpbase_disps0:
259 OP[i] = 0; /* 4 bit disp const. */
260 OP[++i] = (ins) & 0xF; /* get 4 bit for reg. */
261 break;
262 case rpbase_dispe4:
263 OP[i] = ((ins >> 8) & 0xF) * 2; /* 4 bit disp const. */
264 OP[++i] = (ins) & 0xF; /* get 4 bit for reg. */
265 break;
266 case rpbase_disps4:
267 OP[i] = ((ins >> 8) & 0xF); /* 4 bit disp const. */
268 OP[++i] = (ins) & 0xF; /* get 4 bit for reg. */
269 break;
270 case rpbase_disps16:
271 OP[i] = (ins) & 0xFFFF;
272 OP[++i] = (ins >> 16) & 0xF; /* get 4 bit for reg. */
273 break;
274 case rpindex_disps0:
275 OP[i] = 0;
276 OP[++i] = (ins >> 4) & 0xF; /* get 4 bit for reg. */
277 OP[++i] = (ins >> 8) & 0x1; /* get 1 bit for index-reg. */
278 break;
279 case rpindex_disps14:
280 OP[i] = (ins) & 0x3FFF;
281 OP[++i] = (ins >> 14) & 0x1; /* get 1 bit for index-reg. */
282 OP[++i] = (ins >> 16) & 0xF; /* get 4 bit for reg. */
283 case rindex7_abs20:
284 case rindex8_abs20:
285 OP[i] = (ins) & 0xFFFFF;
286 OP[++i] = (ins >> 24) & 0x1; /* get 1 bit for index-reg. */
287 OP[++i] = (ins >> 20) & 0xF; /* get 4 bit for reg. */
288 break;
289 case regr: case regp: case pregr: case pregrp:
290 switch(isize)
291 {
292 case 1:
293 if (start_bit == 20) OP[i] = (ins >> 4) & 0xF;
294 else if (start_bit == 16) OP[i] = ins & 0xF;
295 break;
296 case 2: OP[i] = (ins >> start_bit) & 0xF; break;
297 case 3: OP[i] = (ins >> (start_bit + 16)) & 0xF; break;
298 }
299 break;
300 case cc:
301 {
302 if (isize == 1) OP[i] = (ins >> 4) & 0xF;
303 else if (isize == 2) OP[i] = (ins >> start_bit) & 0xF;
304 else OP[i] = (ins >> (start_bit + 16)) & 0xF;
305 break;
306 }
307 default: break;
308 }
309
310 /* For ESC on uimm4_1 operand. */
311 if (op_type == uimm4_1)
312 if (OP[i] == 9)
313 OP[i] = -1;
314
315 /* For increment by 1. */
316 if ((op_type == pregr) || (op_type == pregrp))
317 OP[i] += 1;
318 }
319 /* FIXME: for tracing, update values that need to be updated each
320 instruction decode cycle */
321 State.trace.psw = PSR;
322 }
323
324 static int
do_run(SIM_DESC sd,SIM_CPU * cpu,uint64 mcode)325 do_run (SIM_DESC sd, SIM_CPU *cpu, uint64 mcode)
326 {
327 struct hash_entry *h;
328
329 #ifdef DEBUG
330 if ((cr16_debug & DEBUG_INSTRUCTION) != 0)
331 sim_io_printf (sd, "do_long 0x%x\n", mcode);
332 #endif
333
334 h = lookup_hash (sd, cpu, mcode, 1);
335
336 if ((h == NULL) || (h->opcode == 0))
337 return 0;
338
339 if (h->size == 3)
340 mcode = (mcode << 16) | RW (PC + 4);
341
342 /* Re-set OP list. */
343 OP[0] = OP[1] = OP[2] = OP[3] = sign_flag = 0;
344
345 /* for push/pop/pushrtn with RA instructions. */
346 if ((h->format & REG_LIST) && (mcode & 0x800000))
347 OP[2] = 1; /* Set 1 for RA operand. */
348
349 /* numops == 0 means, no operands. */
350 if (((h->ops) != NULL) && (((h->ops)->numops) != 0))
351 get_operands ((h->ops)->operands, mcode, h->size, (h->ops)->numops);
352
353 //State.ins_type = h->flags;
354
355 (h->ops->func) (sd, cpu);
356
357 return h->size;
358 }
359
360 static sim_cia
cr16_pc_get(sim_cpu * cpu)361 cr16_pc_get (sim_cpu *cpu)
362 {
363 return PC;
364 }
365
366 static void
cr16_pc_set(sim_cpu * cpu,sim_cia pc)367 cr16_pc_set (sim_cpu *cpu, sim_cia pc)
368 {
369 SIM_DESC sd = CPU_STATE (cpu);
370 SET_PC (pc);
371 }
372
373 static void
free_state(SIM_DESC sd)374 free_state (SIM_DESC sd)
375 {
376 if (STATE_MODULES (sd) != NULL)
377 sim_module_uninstall (sd);
378 sim_cpu_free_all (sd);
379 sim_state_free (sd);
380 }
381
382 static int cr16_reg_fetch (SIM_CPU *, int, unsigned char *, int);
383 static int cr16_reg_store (SIM_CPU *, int, unsigned char *, int);
384
385 SIM_DESC
sim_open(SIM_OPEN_KIND kind,struct host_callback_struct * cb,struct bfd * abfd,char * const * argv)386 sim_open (SIM_OPEN_KIND kind, struct host_callback_struct *cb,
387 struct bfd *abfd, char * const *argv)
388 {
389 struct simops *s;
390 struct hash_entry *h;
391 static int init_p = 0;
392 char **p;
393 int i;
394 SIM_DESC sd = sim_state_alloc (kind, cb);
395 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
396
397 /* The cpu data is kept in a separately allocated chunk of memory. */
398 if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
399 {
400 free_state (sd);
401 return 0;
402 }
403
404 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
405 {
406 free_state (sd);
407 return 0;
408 }
409
410 /* The parser will print an error message for us, so we silently return. */
411 if (sim_parse_args (sd, argv) != SIM_RC_OK)
412 {
413 free_state (sd);
414 return 0;
415 }
416
417 /* Check for/establish the a reference program image. */
418 if (sim_analyze_program (sd,
419 (STATE_PROG_ARGV (sd) != NULL
420 ? *STATE_PROG_ARGV (sd)
421 : NULL), abfd) != SIM_RC_OK)
422 {
423 free_state (sd);
424 return 0;
425 }
426
427 /* Configure/verify the target byte order and other runtime
428 configuration options. */
429 if (sim_config (sd) != SIM_RC_OK)
430 {
431 sim_module_uninstall (sd);
432 return 0;
433 }
434
435 if (sim_post_argv_init (sd) != SIM_RC_OK)
436 {
437 /* Uninstall the modules to avoid memory leaks,
438 file descriptor leaks, etc. */
439 sim_module_uninstall (sd);
440 return 0;
441 }
442
443 /* CPU specific initialization. */
444 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
445 {
446 SIM_CPU *cpu = STATE_CPU (sd, i);
447
448 CPU_REG_FETCH (cpu) = cr16_reg_fetch;
449 CPU_REG_STORE (cpu) = cr16_reg_store;
450 CPU_PC_FETCH (cpu) = cr16_pc_get;
451 CPU_PC_STORE (cpu) = cr16_pc_set;
452 }
453
454 /* The CR16 has an interrupt controller at 0xFC00, but we don't currently
455 handle that. Revisit if anyone ever implements operating mode. */
456 /* cr16 memory: There are three separate cr16 memory regions IMEM,
457 UMEM and DMEM. The IMEM and DMEM are further broken down into
458 blocks (very like VM pages). This might not match the hardware,
459 but it matches what the toolchain currently expects. Ugh. */
460 sim_do_commandf (sd, "memory-size %#x", 20 * 1024 * 1024);
461
462 /* put all the opcodes in the hash table. */
463 if (!init_p++)
464 {
465 for (s = Simops; s->func; s++)
466 {
467 switch(32 - s->mask)
468 {
469 case 0x4:
470 h = &hash_table[hash(s->opcode, 0)];
471 break;
472
473 case 0x7:
474 if (((s->opcode << 1) >> 4) != 0)
475 h = &hash_table[hash((s->opcode << 1) >> 4, 0)];
476 else
477 h = &hash_table[hash((s->opcode << 1), 0)];
478 break;
479
480 case 0x8:
481 if ((s->opcode >> 4) != 0)
482 h = &hash_table[hash(s->opcode >> 4, 0)];
483 else
484 h = &hash_table[hash(s->opcode, 0)];
485 break;
486
487 case 0x9:
488 if (((s->opcode >> 1) >> 4) != 0)
489 h = &hash_table[hash((s->opcode >>1) >> 4, 0)];
490 else
491 h = &hash_table[hash((s->opcode >> 1), 0)];
492 break;
493
494 case 0xa:
495 if ((s->opcode >> 8) != 0)
496 h = &hash_table[hash(s->opcode >> 8, 0)];
497 else if ((s->opcode >> 4) != 0)
498 h = &hash_table[hash(s->opcode >> 4, 0)];
499 else
500 h = &hash_table[hash(s->opcode, 0)];
501 break;
502
503 case 0xc:
504 if ((s->opcode >> 8) != 0)
505 h = &hash_table[hash(s->opcode >> 8, 0)];
506 else if ((s->opcode >> 4) != 0)
507 h = &hash_table[hash(s->opcode >> 4, 0)];
508 else
509 h = &hash_table[hash(s->opcode, 0)];
510 break;
511
512 case 0xd:
513 if (((s->opcode >> 1) >> 8) != 0)
514 h = &hash_table[hash((s->opcode >>1) >> 8, 0)];
515 else if (((s->opcode >> 1) >> 4) != 0)
516 h = &hash_table[hash((s->opcode >>1) >> 4, 0)];
517 else
518 h = &hash_table[hash((s->opcode >>1), 0)];
519 break;
520
521 case 0x10:
522 if ((s->opcode >> 0xc) != 0)
523 h = &hash_table[hash(s->opcode >> 12, 0)];
524 else if ((s->opcode >> 8) != 0)
525 h = &hash_table[hash(s->opcode >> 8, 0)];
526 else if ((s->opcode >> 4) != 0)
527 h = &hash_table[hash(s->opcode >> 4, 0)];
528 else
529 h = &hash_table[hash(s->opcode, 0)];
530 break;
531
532 case 0x14:
533 if ((s->opcode >> 16) != 0)
534 h = &hash_table[hash(s->opcode >> 16, 0)];
535 else if ((s->opcode >> 12) != 0)
536 h = &hash_table[hash(s->opcode >> 12, 0)];
537 else if ((s->opcode >> 8) != 0)
538 h = &hash_table[hash(s->opcode >> 8, 0)];
539 else if ((s->opcode >> 4) != 0)
540 h = &hash_table[hash(s->opcode >> 4, 0)];
541 else
542 h = &hash_table[hash(s->opcode, 0)];
543 break;
544 default:
545 break;
546 }
547
548 /* go to the last entry in the chain. */
549 while (h->next)
550 h = h->next;
551
552 if (h->ops)
553 {
554 h->next = (struct hash_entry *) calloc(1,sizeof(struct hash_entry));
555 if (!h->next)
556 perror ("malloc failure");
557
558 h = h->next;
559 }
560 h->ops = s;
561 h->mask = s->mask;
562 h->opcode = s->opcode;
563 h->format = s->format;
564 h->size = s->size;
565 }
566 }
567
568 return sd;
569 }
570
571 static void
step_once(SIM_DESC sd,SIM_CPU * cpu)572 step_once (SIM_DESC sd, SIM_CPU *cpu)
573 {
574 uint32 curr_ins_size = 0;
575 uint64 mcode = RLW (PC);
576
577 State.pc_changed = 0;
578
579 curr_ins_size = do_run (sd, cpu, mcode);
580
581 #if CR16_DEBUG
582 sim_io_printf (sd, "INS: PC=0x%X, mcode=0x%X\n", PC, mcode);
583 #endif
584
585 if (curr_ins_size == 0)
586 sim_engine_halt (sd, cpu, NULL, PC, sim_exited, GPR (2));
587 else if (!State.pc_changed)
588 SET_PC (PC + (curr_ins_size * 2)); /* For word instructions. */
589
590 #if 0
591 /* Check for a breakpoint trap on this instruction. This
592 overrides any pending branches or loops */
593 if (PSR_DB && PC == DBS)
594 {
595 SET_BPC (PC);
596 SET_BPSR (PSR);
597 SET_PC (SDBT_VECTOR_START);
598 }
599 #endif
600
601 /* Writeback all the DATA / PC changes */
602 SLOT_FLUSH ();
603 }
604
605 void
sim_engine_run(SIM_DESC sd,int next_cpu_nr,int nr_cpus,int siggnal)606 sim_engine_run (SIM_DESC sd,
607 int next_cpu_nr, /* ignore */
608 int nr_cpus, /* ignore */
609 int siggnal)
610 {
611 sim_cpu *cpu;
612
613 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
614
615 cpu = STATE_CPU (sd, 0);
616
617 switch (siggnal)
618 {
619 case 0:
620 break;
621 case GDB_SIGNAL_BUS:
622 case GDB_SIGNAL_SEGV:
623 SET_PC (PC);
624 SET_PSR (PSR);
625 JMP (AE_VECTOR_START);
626 SLOT_FLUSH ();
627 break;
628 case GDB_SIGNAL_ILL:
629 SET_PC (PC);
630 SET_PSR (PSR);
631 SET_HW_PSR ((PSR & (PSR_C_BIT)));
632 JMP (RIE_VECTOR_START);
633 SLOT_FLUSH ();
634 break;
635 default:
636 /* just ignore it */
637 break;
638 }
639
640 while (1)
641 {
642 step_once (sd, cpu);
643 if (sim_events_tick (sd))
644 sim_events_process (sd);
645 }
646 }
647
648 SIM_RC
sim_create_inferior(SIM_DESC sd,struct bfd * abfd,char * const * argv,char * const * env)649 sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
650 char * const *argv, char * const *env)
651 {
652 bfd_vma start_address;
653
654 /* reset all state information */
655 memset (&State, 0, sizeof (State));
656
657 /* There was a hack here to copy the values of argc and argv into r0
658 and r1. The values were also saved into some high memory that
659 won't be overwritten by the stack (0x7C00). The reason for doing
660 this was to allow the 'run' program to accept arguments. Without
661 the hack, this is not possible anymore. If the simulator is run
662 from the debugger, arguments cannot be passed in, so this makes
663 no difference. */
664
665 /* set PC */
666 if (abfd != NULL)
667 start_address = bfd_get_start_address (abfd);
668 else
669 start_address = 0x0;
670 #ifdef DEBUG
671 if (cr16_debug)
672 sim_io_printf (sd, "sim_create_inferior: PC=0x%lx\n", (long) start_address);
673 #endif
674 {
675 SIM_CPU *cpu = STATE_CPU (sd, 0);
676 SET_CREG (PC_CR, start_address);
677 }
678
679 SLOT_FLUSH ();
680 return SIM_RC_OK;
681 }
682
683 static uint32
cr16_extract_unsigned_integer(unsigned char * addr,int len)684 cr16_extract_unsigned_integer (unsigned char *addr, int len)
685 {
686 uint32 retval;
687 unsigned char * p;
688 unsigned char * startaddr = (unsigned char *)addr;
689 unsigned char * endaddr = startaddr + len;
690
691 retval = 0;
692
693 for (p = endaddr; p > startaddr;)
694 retval = (retval << 8) | *--p;
695
696 return retval;
697 }
698
699 static void
cr16_store_unsigned_integer(unsigned char * addr,int len,uint32 val)700 cr16_store_unsigned_integer (unsigned char *addr, int len, uint32 val)
701 {
702 unsigned char *p;
703 unsigned char *startaddr = addr;
704 unsigned char *endaddr = startaddr + len;
705
706 for (p = startaddr; p < endaddr;)
707 {
708 *p++ = val & 0xff;
709 val >>= 8;
710 }
711 }
712
713 static int
cr16_reg_fetch(SIM_CPU * cpu,int rn,unsigned char * memory,int length)714 cr16_reg_fetch (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
715 {
716 int size;
717 switch ((enum sim_cr16_regs) rn)
718 {
719 case SIM_CR16_R0_REGNUM:
720 case SIM_CR16_R1_REGNUM:
721 case SIM_CR16_R2_REGNUM:
722 case SIM_CR16_R3_REGNUM:
723 case SIM_CR16_R4_REGNUM:
724 case SIM_CR16_R5_REGNUM:
725 case SIM_CR16_R6_REGNUM:
726 case SIM_CR16_R7_REGNUM:
727 case SIM_CR16_R8_REGNUM:
728 case SIM_CR16_R9_REGNUM:
729 case SIM_CR16_R10_REGNUM:
730 case SIM_CR16_R11_REGNUM:
731 cr16_store_unsigned_integer (memory, 2, GPR (rn - SIM_CR16_R0_REGNUM));
732 size = 2;
733 break;
734 case SIM_CR16_R12_REGNUM:
735 case SIM_CR16_R13_REGNUM:
736 case SIM_CR16_R14_REGNUM:
737 case SIM_CR16_R15_REGNUM:
738 cr16_store_unsigned_integer (memory, 4, GPR (rn - SIM_CR16_R0_REGNUM));
739 size = 4;
740 break;
741 case SIM_CR16_PC_REGNUM:
742 case SIM_CR16_ISP_REGNUM:
743 case SIM_CR16_USP_REGNUM:
744 case SIM_CR16_INTBASE_REGNUM:
745 case SIM_CR16_PSR_REGNUM:
746 case SIM_CR16_CFG_REGNUM:
747 case SIM_CR16_DBS_REGNUM:
748 case SIM_CR16_DCR_REGNUM:
749 case SIM_CR16_DSR_REGNUM:
750 case SIM_CR16_CAR0_REGNUM:
751 case SIM_CR16_CAR1_REGNUM:
752 cr16_store_unsigned_integer (memory, 4, CREG (rn - SIM_CR16_PC_REGNUM));
753 size = 4;
754 break;
755 default:
756 size = 0;
757 break;
758 }
759 return size;
760 }
761
762 static int
cr16_reg_store(SIM_CPU * cpu,int rn,unsigned char * memory,int length)763 cr16_reg_store (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
764 {
765 SIM_DESC sd = CPU_STATE (cpu);
766 int size;
767 switch ((enum sim_cr16_regs) rn)
768 {
769 case SIM_CR16_R0_REGNUM:
770 case SIM_CR16_R1_REGNUM:
771 case SIM_CR16_R2_REGNUM:
772 case SIM_CR16_R3_REGNUM:
773 case SIM_CR16_R4_REGNUM:
774 case SIM_CR16_R5_REGNUM:
775 case SIM_CR16_R6_REGNUM:
776 case SIM_CR16_R7_REGNUM:
777 case SIM_CR16_R8_REGNUM:
778 case SIM_CR16_R9_REGNUM:
779 case SIM_CR16_R10_REGNUM:
780 case SIM_CR16_R11_REGNUM:
781 SET_GPR (rn - SIM_CR16_R0_REGNUM, cr16_extract_unsigned_integer (memory, 2));
782 size = 2;
783 break;
784 case SIM_CR16_R12_REGNUM:
785 case SIM_CR16_R13_REGNUM:
786 case SIM_CR16_R14_REGNUM:
787 case SIM_CR16_R15_REGNUM:
788 SET_GPR32 (rn - SIM_CR16_R0_REGNUM, cr16_extract_unsigned_integer (memory, 2));
789 size = 4;
790 break;
791 case SIM_CR16_PC_REGNUM:
792 case SIM_CR16_ISP_REGNUM:
793 case SIM_CR16_USP_REGNUM:
794 case SIM_CR16_INTBASE_REGNUM:
795 case SIM_CR16_PSR_REGNUM:
796 case SIM_CR16_CFG_REGNUM:
797 case SIM_CR16_DBS_REGNUM:
798 case SIM_CR16_DCR_REGNUM:
799 case SIM_CR16_DSR_REGNUM:
800 case SIM_CR16_CAR0_REGNUM:
801 case SIM_CR16_CAR1_REGNUM:
802 SET_CREG (rn - SIM_CR16_PC_REGNUM, cr16_extract_unsigned_integer (memory, 4));
803 size = 4;
804 break;
805 default:
806 size = 0;
807 break;
808 }
809 SLOT_FLUSH ();
810 return size;
811 }
812