xref: /netbsd-src/external/gpl3/gdb.old/dist/sim/cr16/interp.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* Simulation code for the CR16 processor.
2    Copyright (C) 2008-2023 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 #include "sim-signal.h"
34 
35 #include "gdb/sim-cr16.h"
36 #include "gdb/signals.h"
37 #include "opcode/cr16.h"
38 
39 #include "target-newlib-syscall.h"
40 
41 struct _state State;
42 
43 int cr16_debug;
44 
45 uint32_t OP[4];
46 uint32_t sign_flag;
47 
48 static struct hash_entry *lookup_hash (SIM_DESC, SIM_CPU *, uint64_t ins, int size);
49 static void get_operands (operand_desc *s, uint64_t mcode, int isize, int nops);
50 
51 #define MAX_HASH  16
52 
53 struct hash_entry
54 {
55   struct hash_entry *next;
56   uint32_t opcode;
57   uint32_t mask;
58   int format;
59   int size;
60   struct simops *ops;
61 };
62 
63 struct hash_entry hash_table[MAX_HASH+1];
64 
65 INLINE static long
66 hash(unsigned long long insn, int format)
67 {
68   unsigned int i = 4, tmp;
69   if (format)
70     {
71       while ((insn >> i) != 0) i +=4;
72 
73       return ((insn >> (i-4)) & 0xf); /* Use last 4 bits as hask key.  */
74     }
75   return ((insn & 0xF)); /* Use last 4 bits as hask key.  */
76 }
77 
78 
79 INLINE static struct hash_entry *
80 lookup_hash (SIM_DESC sd, SIM_CPU *cpu, uint64_t ins, int size)
81 {
82   uint32_t mask;
83   struct hash_entry *h;
84 
85   h = &hash_table[hash(ins,1)];
86 
87 
88   mask = (((1 << (32 - h->mask)) -1) << h->mask);
89 
90  /* Adjuest mask for branch with 2 word instructions.  */
91   if (streq(h->ops->mnemonic,"b") && h->size == 2)
92     mask = 0xff0f0000;
93 
94 
95   while ((ins & mask) != (BIN(h->opcode, h->mask)))
96     {
97       if (h->next == NULL)
98 	sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, SIM_SIGILL);
99       h = h->next;
100 
101       mask = (((1 << (32 - h->mask)) -1) << h->mask);
102      /* Adjuest mask for branch with 2 word instructions.  */
103      if ((streq(h->ops->mnemonic,"b")) && h->size == 2)
104        mask = 0xff0f0000;
105 
106      }
107    return (h);
108 }
109 
110 INLINE static void
111 get_operands (operand_desc *s, uint64_t ins, int isize, int nops)
112 {
113   uint32_t i, opn = 0, start_bit = 0, op_type = 0;
114   int32_t op_size = 0, mask = 0;
115 
116   if (isize == 1) /* Trunkcate the extra 16 bits of INS.  */
117     ins = ins >> 16;
118 
119   for (i=0; i < 4; ++i,++opn)
120     {
121       if (s[opn].op_type == dummy) break;
122 
123       op_type = s[opn].op_type;
124       start_bit = s[opn].shift;
125       op_size = cr16_optab[op_type].bit_size;
126 
127       switch (op_type)
128         {
129           case imm3: case imm4: case imm5: case imm6:
130             {
131              if (isize == 1)
132                OP[i] = ((ins >> 4) & ((1 << op_size) -1));
133              else
134                OP[i] = ((ins >> (32 - start_bit)) & ((1 << op_size) -1));
135 
136              if (OP[i] & ((long)1 << (op_size -1)))
137                {
138                  sign_flag = 1;
139                  OP[i] = ~(OP[i]) + 1;
140                }
141              OP[i] = (unsigned long int)(OP[i] & (((long)1 << op_size) -1));
142             }
143             break;
144 
145           case uimm3: case uimm3_1: case uimm4_1:
146              switch (isize)
147                {
148               case 1:
149                OP[i] = ((ins >> 4) & ((1 << op_size) -1)); break;
150               case 2:
151                OP[i] = ((ins >> (32 - start_bit)) & ((1 << op_size) -1));break;
152               default: /* for case 3.  */
153                OP[i] = ((ins >> (16 + start_bit)) & ((1 << op_size) -1)); break;
154                break;
155                }
156             break;
157 
158           case uimm4:
159             switch (isize)
160               {
161               case 1:
162                  if (start_bit == 20)
163                    OP[i] = ((ins >> 4) & ((1 << op_size) -1));
164                  else
165                    OP[i] = (ins & ((1 << op_size) -1));
166                  break;
167               case 2:
168                  OP[i] = ((ins >> start_bit) & ((1 << op_size) -1));
169                  break;
170               case 3:
171                  OP[i] = ((ins >> (start_bit + 16)) & ((1 << op_size) -1));
172                  break;
173               default:
174                  OP[i] = ((ins >> start_bit) & ((1 << op_size) -1));
175                  break;
176               }
177             break;
178 
179           case imm16: case uimm16:
180             OP[i] = ins & 0xFFFF;
181             break;
182 
183           case uimm20: case imm20:
184             OP[i] = ins & (((long)1 << op_size) - 1);
185             break;
186 
187           case imm32: case uimm32:
188             OP[i] = ins & 0xFFFFFFFF;
189             break;
190 
191           case uimm5: break; /*NOT USED.  */
192             OP[i] = ins & ((1 << op_size) - 1); break;
193 
194           case disps5:
195             OP[i] = (ins >> 4) & ((1 << 4) - 1);
196             OP[i] = (OP[i] * 2) + 2;
197             if (OP[i] & ((long)1 << 5))
198               {
199                 sign_flag = 1;
200                 OP[i] = ~(OP[i]) + 1;
201                 OP[i] = (unsigned long int)(OP[i] & 0x1F);
202               }
203             break;
204 
205           case dispe9:
206             OP[i] = ((((ins >> 8) & 0xf) << 4) | (ins & 0xf));
207             OP[i] <<= 1;
208             if (OP[i] & ((long)1 << 8))
209               {
210                 sign_flag = 1;
211                 OP[i] = ~(OP[i]) + 1;
212                 OP[i] = (unsigned long int)(OP[i] & 0xFF);
213               }
214             break;
215 
216           case disps17:
217             OP[i] = (ins & 0xFFFF);
218             if (OP[i] & 1)
219               {
220                 OP[i] = (OP[i] & 0xFFFE);
221                 sign_flag = 1;
222                 OP[i] = ~(OP[i]) + 1;
223                 OP[i] = (unsigned long int)(OP[i] & 0xFFFF);
224               }
225             break;
226 
227           case disps25:
228             if (isize == 2)
229               OP[i] = (ins & 0xFFFFFF);
230             else
231               OP[i] = (ins & 0xFFFF) | (((ins >> 24) & 0xf) << 16) |
232                       (((ins >> 16) & 0xf) << 20);
233 
234             if (OP[i] & 1)
235               {
236                 OP[i] = (OP[i] & 0xFFFFFE);
237                 sign_flag = 1;
238                 OP[i] = ~(OP[i]) + 1;
239                 OP[i] = (unsigned long int)(OP[i] & 0xFFFFFF);
240               }
241             break;
242 
243           case abs20:
244             if (isize == 3)
245               OP[i] = (ins) & 0xFFFFF;
246             else
247               OP[i] = (ins >> start_bit) & 0xFFFFF;
248             break;
249           case abs24:
250             if (isize == 3)
251               OP[i] = ((ins & 0xFFFF) | (((ins >> 16) & 0xf) << 20)
252                        | (((ins >> 24) & 0xf) << 16));
253             else
254               OP[i] = (ins >> 16) & 0xFFFFFF;
255             break;
256 
257           case rra:
258           case rbase: break; /* NOT USED.  */
259           case rbase_disps20:  case rbase_dispe20:
260           case rpbase_disps20: case rpindex_disps20:
261             OP[i] = ((((ins >> 24)&0xf) << 16)|((ins) & 0xFFFF));
262             OP[++i] = (ins >> 16) & 0xF;     /* get 4 bit for reg.  */
263             break;
264           case rpbase_disps0:
265             OP[i] = 0;                       /* 4 bit disp const.  */
266             OP[++i] = (ins) & 0xF;           /* get 4 bit for reg.  */
267             break;
268           case rpbase_dispe4:
269             OP[i] = ((ins >> 8) & 0xF) * 2;  /* 4 bit disp const.   */
270             OP[++i] = (ins) & 0xF;           /* get 4 bit for reg.  */
271             break;
272           case rpbase_disps4:
273             OP[i] = ((ins >> 8) & 0xF);      /* 4 bit disp const.  */
274             OP[++i] = (ins) & 0xF;           /* get 4 bit for reg.  */
275             break;
276           case rpbase_disps16:
277             OP[i] = (ins) & 0xFFFF;
278             OP[++i] = (ins >> 16) & 0xF;     /* get 4 bit for reg.  */
279             break;
280           case rpindex_disps0:
281             OP[i] = 0;
282             OP[++i] = (ins >> 4) & 0xF;      /* get 4 bit for reg.  */
283             OP[++i] = (ins >> 8) & 0x1;      /* get 1 bit for index-reg.  */
284             break;
285           case rpindex_disps14:
286             OP[i] = (ins) & 0x3FFF;
287             OP[++i] = (ins >> 14) & 0x1;     /* get 1 bit for index-reg.  */
288             OP[++i] = (ins >> 16) & 0xF;     /* get 4 bit for reg.  */
289           case rindex7_abs20:
290           case rindex8_abs20:
291             OP[i] = (ins) & 0xFFFFF;
292             OP[++i] = (ins >> 24) & 0x1;     /* get 1 bit for index-reg.  */
293             OP[++i] = (ins >> 20) & 0xF;     /* get 4 bit for reg.  */
294             break;
295           case regr: case regp: case pregr: case pregrp:
296               switch(isize)
297                 {
298                   case 1:
299                     if (start_bit == 20) OP[i] = (ins >> 4) & 0xF;
300                     else if (start_bit == 16) OP[i] = ins & 0xF;
301                     break;
302                   case 2: OP[i] = (ins >>  start_bit) & 0xF; break;
303                   case 3: OP[i] = (ins >> (start_bit + 16)) & 0xF; break;
304                 }
305                break;
306           case cc:
307             {
308               if (isize == 1) OP[i] = (ins >> 4) & 0xF;
309               else if (isize == 2)  OP[i] = (ins >> start_bit)  & 0xF;
310               else  OP[i] = (ins >> (start_bit + 16)) & 0xF;
311               break;
312             }
313           default: break;
314         }
315 
316       /* For ESC on uimm4_1 operand.  */
317       if (op_type == uimm4_1)
318         if (OP[i] == 9)
319            OP[i] = -1;
320 
321       /* For increment by 1.  */
322       if ((op_type == pregr) || (op_type == pregrp))
323           OP[i] += 1;
324    }
325   /* FIXME: for tracing, update values that need to be updated each
326             instruction decode cycle */
327   State.trace.psw = PSR;
328 }
329 
330 static int
331 do_run (SIM_DESC sd, SIM_CPU *cpu, uint64_t mcode)
332 {
333   struct hash_entry *h;
334 
335 #ifdef DEBUG
336   if ((cr16_debug & DEBUG_INSTRUCTION) != 0)
337     sim_io_printf (sd, "do_long 0x%" PRIx64 "\n", mcode);
338 #endif
339 
340    h = lookup_hash (sd, cpu, mcode, 1);
341 
342   if ((h == NULL) || (h->opcode == 0))
343     return 0;
344 
345   if (h->size == 3)
346     mcode = (mcode << 16) | RW (PC + 4);
347 
348   /* Re-set OP list.  */
349   OP[0] = OP[1] = OP[2] = OP[3] = sign_flag = 0;
350 
351   /* for push/pop/pushrtn with RA instructions. */
352   if ((h->format & REG_LIST) && (mcode & 0x800000))
353     OP[2] = 1; /* Set 1 for RA operand.  */
354 
355   /* numops == 0 means, no operands.  */
356   if (((h->ops) != NULL) && (((h->ops)->numops) != 0))
357     get_operands ((h->ops)->operands, mcode, h->size, (h->ops)->numops);
358 
359   //State.ins_type = h->flags;
360 
361   (h->ops->func) (sd, cpu);
362 
363   return h->size;
364 }
365 
366 static sim_cia
367 cr16_pc_get (sim_cpu *cpu)
368 {
369   return PC;
370 }
371 
372 static void
373 cr16_pc_set (sim_cpu *cpu, sim_cia pc)
374 {
375   SIM_DESC sd = CPU_STATE (cpu);
376   SET_PC (pc);
377 }
378 
379 static void
380 free_state (SIM_DESC sd)
381 {
382   if (STATE_MODULES (sd) != NULL)
383     sim_module_uninstall (sd);
384   sim_cpu_free_all (sd);
385   sim_state_free (sd);
386 }
387 
388 static int cr16_reg_fetch (SIM_CPU *, int, void *, int);
389 static int cr16_reg_store (SIM_CPU *, int, const void *, int);
390 
391 SIM_DESC
392 sim_open (SIM_OPEN_KIND kind, struct host_callback_struct *cb,
393 	  struct bfd *abfd, char * const *argv)
394 {
395   struct simops *s;
396   struct hash_entry *h;
397   static int init_p = 0;
398   char **p;
399   int i;
400   SIM_DESC sd = sim_state_alloc (kind, cb);
401   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
402 
403   /* Set default options before parsing user options.  */
404   current_target_byte_order = BFD_ENDIAN_LITTLE;
405   cb->syscall_map = cb_cr16_syscall_map;
406 
407   /* The cpu data is kept in a separately allocated chunk of memory.  */
408   if (sim_cpu_alloc_all (sd, 1) != SIM_RC_OK)
409     {
410       free_state (sd);
411       return 0;
412     }
413 
414   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
415     {
416       free_state (sd);
417       return 0;
418     }
419 
420   /* The parser will print an error message for us, so we silently return.  */
421   if (sim_parse_args (sd, argv) != SIM_RC_OK)
422     {
423       free_state (sd);
424       return 0;
425     }
426 
427   /* Check for/establish the a reference program image.  */
428   if (sim_analyze_program (sd, STATE_PROG_FILE (sd), 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_t curr_ins_size = 0;
583   uint64_t 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%" PRIx64 "\n",
681 		   (uint64_t) 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_t
693 cr16_extract_unsigned_integer (const unsigned char *addr, int len)
694 {
695   uint32_t 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_t 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, void *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, const void *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 }
821