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