Commit | Line | Data |
---|---|---|
fee8ec00 | 1 | /* Simulation code for the CR16 processor. |
ecd75fc8 | 2 | Copyright (C) 2008-2014 Free Software Foundation, Inc. |
fee8ec00 SR |
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 | |
dc3cf14f | 9 | the Free Software Foundation; either version 3, or (at your option) |
fee8ec00 SR |
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 | ||
8e26b0f4 SR |
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 | ||
fee8ec00 SR |
20 | |
21 | #include "config.h" | |
22 | #include <stdio.h> | |
23 | #include <ctype.h> | |
24 | #include <limits.h> | |
25 | #include "ansidecl.h" | |
26 | #include "gdb/callback.h" | |
27 | #include "opcode/cr16.h" | |
28 | #include "bfd.h" | |
29 | ||
30 | #define DEBUG_TRACE 0x00000001 | |
31 | #define DEBUG_VALUES 0x00000002 | |
32 | #define DEBUG_LINE_NUMBER 0x00000004 | |
33 | #define DEBUG_MEMSIZE 0x00000008 | |
34 | #define DEBUG_INSTRUCTION 0x00000010 | |
35 | #define DEBUG_TRAP 0x00000020 | |
36 | #define DEBUG_MEMORY 0x00000040 | |
37 | ||
38 | #ifndef DEBUG | |
39 | #define DEBUG (DEBUG_TRACE | DEBUG_VALUES | DEBUG_LINE_NUMBER) | |
40 | #endif | |
41 | ||
42 | extern int cr16_debug; | |
43 | ||
44 | #include "gdb/remote-sim.h" | |
45 | #include "sim-config.h" | |
46 | #include "sim-types.h" | |
47 | ||
48 | typedef unsigned8 uint8; | |
49 | typedef signed8 int8; | |
50 | typedef unsigned16 uint16; | |
51 | typedef signed16 int16; | |
52 | typedef unsigned32 uint32; | |
53 | typedef signed32 int32; | |
54 | typedef unsigned64 uint64; | |
55 | typedef signed64 int64; | |
56 | ||
57 | /* FIXME: CR16 defines */ | |
58 | typedef uint16 reg_t; | |
59 | typedef uint32 creg_t; | |
60 | ||
61 | struct simops | |
62 | { | |
8e26b0f4 SR |
63 | char mnimonic[12]; |
64 | uint32 size; | |
65 | uint32 mask; | |
66 | uint32 opcode; | |
fee8ec00 | 67 | int format; |
8e26b0f4 | 68 | char fname[12]; |
fee8ec00 SR |
69 | void (*func)(); |
70 | int numops; | |
8e26b0f4 | 71 | operand_desc operands[4]; |
fee8ec00 SR |
72 | }; |
73 | ||
74 | enum _ins_type | |
75 | { | |
76 | INS_UNKNOWN, /* unknown instruction */ | |
77 | INS_NO_TYPE_INS, | |
78 | INS_ARITH_INS, | |
79 | INS_LD_STOR_INS, | |
80 | INS_BRANCH_INS, | |
81 | INS_ARITH_BYTE_INS, | |
82 | INS_SHIFT_INS, | |
83 | INS_BRANCH_NEQ_INS, | |
84 | INS_STOR_IMM_INS, | |
85 | INS_CSTBIT_INS, | |
86 | INS_MAX | |
87 | }; | |
88 | ||
89 | extern unsigned long ins_type_counters[ (int)INS_MAX ]; | |
90 | ||
91 | enum { | |
92 | SP_IDX = 15, | |
93 | }; | |
94 | ||
95 | /* Write-back slots */ | |
96 | union slot_data { | |
97 | unsigned_1 _1; | |
98 | unsigned_2 _2; | |
99 | unsigned_4 _4; | |
100 | }; | |
101 | struct slot { | |
102 | void *dest; | |
103 | int size; | |
104 | union slot_data data; | |
105 | union slot_data mask; | |
106 | }; | |
107 | enum { | |
108 | NR_SLOTS = 16 | |
109 | }; | |
110 | #define SLOT (State.slot) | |
111 | #define SLOT_NR (State.slot_nr) | |
112 | #define SLOT_PEND_MASK(DEST, MSK, VAL) \ | |
113 | do \ | |
114 | { \ | |
115 | SLOT[SLOT_NR].dest = &(DEST); \ | |
116 | SLOT[SLOT_NR].size = sizeof (DEST); \ | |
117 | switch (sizeof (DEST)) \ | |
118 | { \ | |
119 | case 1: \ | |
120 | SLOT[SLOT_NR].data._1 = (unsigned_1) (VAL); \ | |
121 | SLOT[SLOT_NR].mask._1 = (unsigned_1) (MSK); \ | |
122 | break; \ | |
123 | case 2: \ | |
124 | SLOT[SLOT_NR].data._2 = (unsigned_2) (VAL); \ | |
125 | SLOT[SLOT_NR].mask._2 = (unsigned_2) (MSK); \ | |
126 | break; \ | |
127 | case 4: \ | |
128 | SLOT[SLOT_NR].data._4 = (unsigned_4) (VAL); \ | |
129 | SLOT[SLOT_NR].mask._4 = (unsigned_4) (MSK); \ | |
130 | break; \ | |
131 | } \ | |
132 | SLOT_NR = (SLOT_NR + 1); \ | |
133 | } \ | |
134 | while (0) | |
135 | #define SLOT_PEND(DEST, VAL) SLOT_PEND_MASK(DEST, 0, VAL) | |
136 | #define SLOT_DISCARD() (SLOT_NR = 0) | |
137 | #define SLOT_FLUSH() \ | |
138 | do \ | |
139 | { \ | |
140 | int i; \ | |
141 | for (i = 0; i < SLOT_NR; i++) \ | |
142 | { \ | |
143 | switch (SLOT[i].size) \ | |
144 | { \ | |
145 | case 1: \ | |
146 | *(unsigned_1*) SLOT[i].dest &= SLOT[i].mask._1; \ | |
147 | *(unsigned_1*) SLOT[i].dest |= SLOT[i].data._1; \ | |
148 | break; \ | |
149 | case 2: \ | |
150 | *(unsigned_2*) SLOT[i].dest &= SLOT[i].mask._2; \ | |
151 | *(unsigned_2*) SLOT[i].dest |= SLOT[i].data._2; \ | |
152 | break; \ | |
153 | case 4: \ | |
154 | *(unsigned_4*) SLOT[i].dest &= SLOT[i].mask._4; \ | |
155 | *(unsigned_4*) SLOT[i].dest |= SLOT[i].data._4; \ | |
156 | break; \ | |
157 | } \ | |
158 | } \ | |
159 | SLOT_NR = 0; \ | |
160 | } \ | |
161 | while (0) | |
162 | #define SLOT_DUMP() \ | |
163 | do \ | |
164 | { \ | |
165 | int i; \ | |
166 | for (i = 0; i < SLOT_NR; i++) \ | |
167 | { \ | |
168 | switch (SLOT[i].size) \ | |
169 | { \ | |
170 | case 1: \ | |
171 | printf ("SLOT %d *0x%08lx & 0x%02x | 0x%02x\n", i, \ | |
172 | (long) SLOT[i].dest, \ | |
173 | (unsigned) SLOT[i].mask._1, \ | |
174 | (unsigned) SLOT[i].data._1); \ | |
175 | break; \ | |
176 | case 2: \ | |
177 | printf ("SLOT %d *0x%08lx & 0x%04x | 0x%04x\n", i, \ | |
178 | (long) SLOT[i].dest, \ | |
179 | (unsigned) SLOT[i].mask._2, \ | |
180 | (unsigned) SLOT[i].data._2); \ | |
181 | break; \ | |
182 | case 4: \ | |
183 | printf ("SLOT %d *0x%08lx & 0x%08x | 0x%08x\n", i, \ | |
184 | (long) SLOT[i].dest, \ | |
185 | (unsigned) SLOT[i].mask._4, \ | |
186 | (unsigned) SLOT[i].data._4); \ | |
187 | break; \ | |
188 | case 8: \ | |
189 | printf ("SLOT %d *0x%08lx & 0x%08x%08x | 0x%08x%08x\n", i, \ | |
190 | (long) SLOT[i].dest, \ | |
191 | (unsigned) (SLOT[i].mask._8 >> 32), \ | |
192 | (unsigned) SLOT[i].mask._8, \ | |
193 | (unsigned) (SLOT[i].data._8 >> 32), \ | |
194 | (unsigned) SLOT[i].data._8); \ | |
195 | break; \ | |
196 | } \ | |
197 | } \ | |
198 | } \ | |
199 | while (0) | |
200 | ||
201 | /* cr16 memory: There are three separate cr16 memory regions IMEM, | |
202 | UMEM and DMEM. The IMEM and DMEM are further broken down into | |
203 | blocks (very like VM pages). */ | |
204 | ||
205 | enum | |
206 | { | |
207 | IMAP_BLOCK_SIZE = 0x2000000, | |
208 | DMAP_BLOCK_SIZE = 0x4000000 | |
209 | }; | |
210 | ||
211 | /* Implement the three memory regions using sparse arrays. Allocate | |
212 | memory using ``segments''. A segment must be at least as large as | |
213 | a BLOCK - ensures that an access that doesn't cross a block | |
214 | boundary can't cross a segment boundary */ | |
215 | ||
216 | enum | |
217 | { | |
218 | SEGMENT_SIZE = 0x2000000, /* 128KB - MAX(IMAP_BLOCK_SIZE,DMAP_BLOCK_SIZE) */ | |
219 | IMEM_SEGMENTS = 8, /* 1MB */ | |
220 | DMEM_SEGMENTS = 8, /* 1MB */ | |
221 | UMEM_SEGMENTS = 128 /* 16MB */ | |
222 | }; | |
223 | ||
224 | struct cr16_memory | |
225 | { | |
226 | uint8 *insn[IMEM_SEGMENTS]; | |
227 | uint8 *data[DMEM_SEGMENTS]; | |
228 | uint8 *unif[UMEM_SEGMENTS]; | |
229 | uint8 fault[16]; | |
230 | }; | |
231 | ||
232 | struct _state | |
233 | { | |
234 | creg_t regs[16]; /* general-purpose registers */ | |
235 | #define GPR(N) (State.regs[(N)] + 0) | |
236 | #define SET_GPR(N,VAL) (State.regs[(N)] = (VAL)) | |
237 | ||
238 | #define GPR32(N) \ | |
239 | (N < 12) ? \ | |
240 | ((((uint16) State.regs[(N) + 1]) << 16) | (uint16) State.regs[(N)]) \ | |
241 | : GPR (N) | |
242 | ||
243 | #define SET_GPR32(N,VAL) do { \ | |
244 | if (N < 11) \ | |
245 | { SET_GPR (N + 1, (VAL) >> 16); SET_GPR (N, ((VAL) & 0xffff));} \ | |
246 | else { if ( N == 11) \ | |
247 | { SET_GPR (N + 1, ((GPR32 (12)) & 0xffff0000)|((VAL) >> 16)); \ | |
248 | SET_GPR (N, ((VAL) & 0xffff));} \ | |
249 | else SET_GPR (N, (VAL));} \ | |
250 | } while (0) | |
251 | ||
252 | creg_t cregs[16]; /* control registers */ | |
253 | #define CREG(N) (State.cregs[(N)] + 0) | |
254 | #define SET_CREG(N,VAL) move_to_cr ((N), 0, (VAL), 0) | |
255 | #define SET_HW_CREG(N,VAL) move_to_cr ((N), 0, (VAL), 1) | |
256 | ||
257 | reg_t sp[2]; /* holding area for SPI(0)/SPU(1) */ | |
258 | #define HELD_SP(N) (State.sp[(N)] + 0) | |
259 | #define SET_HELD_SP(N,VAL) SLOT_PEND (State.sp[(N)], (VAL)) | |
260 | ||
261 | /* writeback info */ | |
262 | struct slot slot[NR_SLOTS]; | |
263 | int slot_nr; | |
264 | ||
265 | /* trace data */ | |
266 | struct { | |
267 | uint16 psw; | |
268 | } trace; | |
269 | ||
270 | uint8 exe; | |
271 | int exception; | |
272 | int pc_changed; | |
273 | ||
274 | /* NOTE: everything below this line is not reset by | |
275 | sim_create_inferior() */ | |
276 | ||
277 | struct cr16_memory mem; | |
278 | ||
279 | enum _ins_type ins_type; | |
280 | ||
281 | } State; | |
282 | ||
283 | ||
284 | extern host_callback *cr16_callback; | |
285 | extern uint32 OP[4]; | |
286 | extern uint32 sign_flag; | |
287 | extern struct simops Simops[]; | |
288 | extern asection *text; | |
289 | extern bfd_vma text_start; | |
290 | extern bfd_vma text_end; | |
291 | extern bfd *prog_bfd; | |
292 | ||
293 | enum | |
294 | { | |
295 | PC_CR = 0, | |
296 | BDS_CR = 1, | |
297 | BSR_CR = 2, | |
298 | DCR_CR = 3, | |
299 | CAR0_CR = 5, | |
300 | CAR1_CR = 7, | |
301 | CFG_CR = 9, | |
302 | PSR_CR = 10, | |
303 | INTBASE_CR = 11, | |
304 | ISP_CR = 13, | |
305 | USP_CR = 15 | |
306 | }; | |
307 | ||
308 | enum | |
309 | { | |
310 | PSR_I_BIT = 0x0800, | |
311 | PSR_P_BIT = 0x0400, | |
312 | PSR_E_BIT = 0x0200, | |
8e26b0f4 | 313 | PSR_N_BIT = 0x0080, |
fee8ec00 SR |
314 | PSR_Z_BIT = 0x0040, |
315 | PSR_F_BIT = 0x0020, | |
8e26b0f4 | 316 | PSR_U_BIT = 0x0008, |
fee8ec00 SR |
317 | PSR_L_BIT = 0x0004, |
318 | PSR_T_BIT = 0x0002, | |
8e26b0f4 | 319 | PSR_C_BIT = 0x0001 |
fee8ec00 SR |
320 | }; |
321 | ||
322 | #define PSR CREG (PSR_CR) | |
323 | #define SET_PSR(VAL) SET_CREG (PSR_CR, (VAL)) | |
324 | #define SET_HW_PSR(VAL) SET_HW_CREG (PSR_CR, (VAL)) | |
325 | #define SET_PSR_BIT(MASK,VAL) move_to_cr (PSR_CR, ~((creg_t) MASK), (VAL) ? (MASK) : 0, 1) | |
326 | ||
327 | #define PSR_SM ((PSR & PSR_SM_BIT) != 0) | |
328 | #define SET_PSR_SM(VAL) SET_PSR_BIT (PSR_SM_BIT, (VAL)) | |
329 | ||
330 | #define PSR_I ((PSR & PSR_I_BIT) != 0) | |
331 | #define SET_PSR_I(VAL) SET_PSR_BIT (PSR_I_BIT, (VAL)) | |
332 | ||
333 | #define PSR_DB ((PSR & PSR_DB_BIT) != 0) | |
334 | #define SET_PSR_DB(VAL) SET_PSR_BIT (PSR_DB_BIT, (VAL)) | |
335 | ||
336 | #define PSR_P ((PSR & PSR_P_BIT) != 0) | |
337 | #define SET_PSR_P(VAL) SET_PSR_BIT (PSR_P_BIT, (VAL)) | |
338 | ||
339 | #define PSR_E ((PSR & PSR_E_BIT) != 0) | |
340 | #define SET_PSR_E(VAL) SET_PSR_BIT (PSR_E_BIT, (VAL)) | |
341 | ||
342 | #define PSR_N ((PSR & PSR_N_BIT) != 0) | |
343 | #define SET_PSR_N(VAL) SET_PSR_BIT (PSR_N_BIT, (VAL)) | |
344 | ||
345 | #define PSR_Z ((PSR & PSR_Z_BIT) != 0) | |
346 | #define SET_PSR_Z(VAL) SET_PSR_BIT (PSR_Z_BIT, (VAL)) | |
347 | ||
348 | #define PSR_F ((PSR & PSR_F_BIT) != 0) | |
349 | #define SET_PSR_F(VAL) SET_PSR_BIT (PSR_F_BIT, (VAL)) | |
350 | ||
351 | #define PSR_U ((PSR & PSR_U_BIT) != 0) | |
352 | #define SET_PSR_U(VAL) SET_PSR_BIT (PSR_U_BIT, (VAL)) | |
353 | ||
354 | #define PSR_L ((PSR & PSR_L_BIT) != 0) | |
355 | #define SET_PSR_L(VAL) SET_PSR_BIT (PSR_L_BIT, (VAL)) | |
356 | ||
357 | #define PSR_T ((PSR & PSR_T_BIT) != 0) | |
358 | #define SET_PSR_T(VAL) SET_PSR_BIT (PSR_T_BIT, (VAL)) | |
359 | ||
360 | #define PSR_C ((PSR & PSR_C_BIT) != 0) | |
361 | #define SET_PSR_C(VAL) SET_PSR_BIT (PSR_C_BIT, (VAL)) | |
362 | ||
363 | /* See simopsc.:move_to_cr() for registers that can not be read-from | |
364 | or assigned-to directly */ | |
365 | ||
366 | #define PC CREG (PC_CR) | |
367 | #define SET_PC(VAL) SET_CREG (PC_CR, (VAL)) | |
368 | //#define SET_PC(VAL) (State.cregs[PC_CR] = (VAL)) | |
369 | ||
370 | #define BPSR CREG (BPSR_CR) | |
371 | #define SET_BPSR(VAL) SET_CREG (BPSR_CR, (VAL)) | |
372 | ||
373 | #define BPC CREG (BPC_CR) | |
374 | #define SET_BPC(VAL) SET_CREG (BPC_CR, (VAL)) | |
375 | ||
376 | #define DPSR CREG (DPSR_CR) | |
377 | #define SET_DPSR(VAL) SET_CREG (DPSR_CR, (VAL)) | |
378 | ||
379 | #define DPC CREG (DPC_CR) | |
380 | #define SET_DPC(VAL) SET_CREG (DPC_CR, (VAL)) | |
381 | ||
382 | #define RPT_C CREG (RPT_C_CR) | |
383 | #define SET_RPT_C(VAL) SET_CREG (RPT_C_CR, (VAL)) | |
384 | ||
385 | #define RPT_S CREG (RPT_S_CR) | |
386 | #define SET_RPT_S(VAL) SET_CREG (RPT_S_CR, (VAL)) | |
387 | ||
388 | #define RPT_E CREG (RPT_E_CR) | |
389 | #define SET_RPT_E(VAL) SET_CREG (RPT_E_CR, (VAL)) | |
390 | ||
391 | #define MOD_S CREG (MOD_S_CR) | |
392 | #define SET_MOD_S(VAL) SET_CREG (MOD_S_CR, (VAL)) | |
393 | ||
394 | #define MOD_E CREG (MOD_E_CR) | |
395 | #define SET_MOD_E(VAL) SET_CREG (MOD_E_CR, (VAL)) | |
396 | ||
397 | #define IBA CREG (IBA_CR) | |
398 | #define SET_IBA(VAL) SET_CREG (IBA_CR, (VAL)) | |
399 | ||
400 | ||
401 | #define SIG_CR16_STOP -1 | |
402 | #define SIG_CR16_EXIT -2 | |
403 | #define SIG_CR16_BUS -3 | |
404 | #define SIG_CR16_IAD -4 | |
405 | ||
406 | #define SEXT3(x) ((((x)&0x7)^(~3))+4) | |
407 | ||
408 | /* sign-extend a 4-bit number */ | |
409 | #define SEXT4(x) ((((x)&0xf)^(~7))+8) | |
410 | ||
411 | /* sign-extend an 8-bit number */ | |
412 | #define SEXT8(x) ((((x)&0xff)^(~0x7f))+0x80) | |
413 | ||
414 | /* sign-extend a 16-bit number */ | |
415 | #define SEXT16(x) ((((x)&0xffff)^(~0x7fff))+0x8000) | |
416 | ||
417 | /* sign-extend a 24-bit number */ | |
418 | #define SEXT24(x) ((((x)&0xffffff)^(~0x7fffff))+0x800000) | |
419 | ||
420 | /* sign-extend a 32-bit number */ | |
421 | #define SEXT32(x) ((((x)&0xffffffff)^(~0x7fffffff))+0x80000000) | |
422 | ||
423 | extern uint8 *dmem_addr (uint32 offset); | |
bdca5ee4 TT |
424 | extern uint8 *imem_addr (uint32); |
425 | extern bfd_vma decode_pc (void); | |
fee8ec00 SR |
426 | |
427 | #define RB(x) (*(dmem_addr(x))) | |
428 | #define SB(addr,data) ( RB(addr) = (data & 0xff)) | |
429 | ||
430 | #if defined(__GNUC__) && defined(__OPTIMIZE__) && !defined(NO_ENDIAN_INLINE) | |
431 | #define ENDIAN_INLINE static __inline__ | |
432 | #include "endian.c" | |
433 | #undef ENDIAN_INLINE | |
434 | ||
435 | #else | |
bdca5ee4 TT |
436 | extern uint32 get_longword (uint8 *); |
437 | extern uint16 get_word (uint8 *); | |
438 | extern int64 get_longlong (uint8 *); | |
439 | extern void write_word (uint8 *addr, uint16 data); | |
440 | extern void write_longword (uint8 *addr, uint32 data); | |
441 | extern void write_longlong (uint8 *addr, int64 data); | |
fee8ec00 SR |
442 | #endif |
443 | ||
444 | #define SW(addr,data) write_word(dmem_addr(addr),data) | |
445 | #define RW(x) get_word(dmem_addr(x)) | |
446 | #define SLW(addr,data) write_longword(dmem_addr(addr),data) | |
447 | #define RLW(x) get_longword(dmem_addr(x)) | |
448 | #define READ_16(x) get_word(x) | |
449 | #define WRITE_16(addr,data) write_word(addr,data) | |
450 | #define READ_64(x) get_longlong(x) | |
451 | #define WRITE_64(addr,data) write_longlong(addr,data) | |
452 | ||
453 | #define JMP(x) do { SET_PC (x); State.pc_changed = 1; } while (0) | |
454 | ||
455 | #define RIE_VECTOR_START 0xffc2 | |
456 | #define AE_VECTOR_START 0xffc3 | |
457 | #define TRAP_VECTOR_START 0xffc4 /* vector for trap 0 */ | |
458 | #define DBT_VECTOR_START 0xffd4 | |
459 | #define SDBT_VECTOR_START 0xffd5 | |
460 | ||
461 | #define INT_VECTOR_START 0xFFFE00 /*maskable interrupt - mapped to ICU */ | |
462 | #define NMI_VECTOR_START 0xFFFF00 /*non-maskable interrupt;for observability*/ | |
463 | #define ISE_VECTOR_START 0xFFFC00 /*in-system emulation trap */ | |
464 | #define ADBG_VECTOR_START 0xFFFC02 /*alternate debug trap */ | |
465 | #define ATRC_VECTOR_START 0xFFFC0C /*alternate trace trap */ | |
466 | #define ABPT_VECTOR_START 0xFFFC0E /*alternate break point trap */ | |
467 | ||
468 | ||
469 | /* Scedule a store of VAL into cr[CR]. MASK indicates the bits in | |
470 | cr[CR] that should not be modified (i.e. cr[CR] = (cr[CR] & MASK) | | |
471 | (VAL & ~MASK)). In addition, unless PSR_HW_P, a VAL intended for | |
472 | PSR is masked for zero bits. */ | |
473 | ||
474 | extern creg_t move_to_cr (int cr, creg_t mask, creg_t val, int psw_hw_p); | |
5a06d7c4 MF |
475 | |
476 | #ifndef SIGTRAP | |
477 | #define SIGTRAP 5 | |
478 | #endif | |
479 | /* Special purpose trap */ | |
480 | #define TRAP_BREAKPOINT 8 |