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