xref: /netbsd/external/gpl3/gdb.old/dist/sim/cr16/interp.c (revision 184b2d41)
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