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