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>
5 This file is part of GDB, the GNU debugger.
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)
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.
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/>. */
20 /* This must come before any other includes. */
28 #include "sim/callback.h"
32 #include "sim-options.h"
33 #include "sim-signal.h"
35 #include "sim/sim-cr16.h"
36 #include "gdb/signals.h"
37 #include "opcode/cr16.h"
39 #include "target-newlib-syscall.h"
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
);
57 struct hash_entry
*next
;
65 struct hash_entry hash_table
[MAX_HASH
+1];
68 hash(unsigned long long insn
, int format
)
73 while ((insn
>> i
) != 0) i
+=4;
75 return ((insn
>> (i
-4)) & 0xf); /* Use last 4 bits as hask key. */
77 return ((insn
& 0xF)); /* Use last 4 bits as hask key. */
81 INLINE
static struct hash_entry
*
82 lookup_hash (SIM_DESC sd
, SIM_CPU
*cpu
, uint64_t ins
, int size
)
87 h
= &hash_table
[hash(ins
,1)];
90 mask
= (((1 << (32 - h
->mask
)) -1) << h
->mask
);
92 /* Adjuest mask for branch with 2 word instructions. */
93 if (streq(h
->ops
->mnemonic
,"b") && h
->size
== 2)
97 while ((ins
& mask
) != (BIN(h
->opcode
, h
->mask
)))
100 sim_engine_halt (sd
, cpu
, NULL
, PC
, sim_stopped
, SIM_SIGILL
);
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)
113 get_operands (operand_desc
*s
, uint64_t ins
, int isize
, int nops
)
115 uint32_t i
, opn
= 0, start_bit
= 0, op_type
= 0;
118 if (isize
== 1) /* Trunkcate the extra 16 bits of INS. */
121 for (i
=0; i
< 4; ++i
,++opn
)
123 if (s
[opn
].op_type
== dummy
) break;
125 op_type
= s
[opn
].op_type
;
126 start_bit
= s
[opn
].shift
;
127 op_size
= cr16_optab
[op_type
].bit_size
;
131 case imm3
: case imm4
: case imm5
: case imm6
:
134 OP
[i
] = ((ins
>> 4) & ((1 << op_size
) -1));
136 OP
[i
] = ((ins
>> (32 - start_bit
)) & ((1 << op_size
) -1));
138 if (OP
[i
] & ((long)1 << (op_size
-1)))
141 OP
[i
] = ~(OP
[i
]) + 1;
143 OP
[i
] = (unsigned long int)(OP
[i
] & (((long)1 << op_size
) -1));
147 case uimm3
: case uimm3_1
: case uimm4_1
:
151 OP
[i
] = ((ins
>> 4) & ((1 << op_size
) -1)); break;
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;
165 OP
[i
] = ((ins
>> 4) & ((1 << op_size
) -1));
167 OP
[i
] = (ins
& ((1 << op_size
) -1));
170 OP
[i
] = ((ins
>> start_bit
) & ((1 << op_size
) -1));
173 OP
[i
] = ((ins
>> (start_bit
+ 16)) & ((1 << op_size
) -1));
176 OP
[i
] = ((ins
>> start_bit
) & ((1 << op_size
) -1));
181 case imm16
: case uimm16
:
182 OP
[i
] = ins
& 0xFFFF;
185 case uimm20
: case imm20
:
186 OP
[i
] = ins
& (((long)1 << op_size
) - 1);
189 case imm32
: case uimm32
:
190 OP
[i
] = ins
& 0xFFFFFFFF;
193 case uimm5
: break; /*NOT USED. */
194 OP
[i
] = ins
& ((1 << op_size
) - 1); break;
197 OP
[i
] = (ins
>> 4) & ((1 << 4) - 1);
198 OP
[i
] = (OP
[i
] * 2) + 2;
199 if (OP
[i
] & ((long)1 << 5))
202 OP
[i
] = ~(OP
[i
]) + 1;
203 OP
[i
] = (unsigned long int)(OP
[i
] & 0x1F);
208 OP
[i
] = ((((ins
>> 8) & 0xf) << 4) | (ins
& 0xf));
210 if (OP
[i
] & ((long)1 << 8))
213 OP
[i
] = ~(OP
[i
]) + 1;
214 OP
[i
] = (unsigned long int)(OP
[i
] & 0xFF);
219 OP
[i
] = (ins
& 0xFFFF);
222 OP
[i
] = (OP
[i
] & 0xFFFE);
224 OP
[i
] = ~(OP
[i
]) + 1;
225 OP
[i
] = (unsigned long int)(OP
[i
] & 0xFFFF);
231 OP
[i
] = (ins
& 0xFFFFFF);
233 OP
[i
] = (ins
& 0xFFFF) | (((ins
>> 24) & 0xf) << 16) |
234 (((ins
>> 16) & 0xf) << 20);
238 OP
[i
] = (OP
[i
] & 0xFFFFFE);
240 OP
[i
] = ~(OP
[i
]) + 1;
241 OP
[i
] = (unsigned long int)(OP
[i
] & 0xFFFFFF);
247 OP
[i
] = (ins
) & 0xFFFFF;
249 OP
[i
] = (ins
>> start_bit
) & 0xFFFFF;
253 OP
[i
] = ((ins
& 0xFFFF) | (((ins
>> 16) & 0xf) << 20)
254 | (((ins
>> 24) & 0xf) << 16));
256 OP
[i
] = (ins
>> 16) & 0xFFFFFF;
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. */
267 OP
[i
] = 0; /* 4 bit disp const. */
268 OP
[++i
] = (ins
) & 0xF; /* get 4 bit for reg. */
271 OP
[i
] = ((ins
>> 8) & 0xF) * 2; /* 4 bit disp const. */
272 OP
[++i
] = (ins
) & 0xF; /* get 4 bit for reg. */
275 OP
[i
] = ((ins
>> 8) & 0xF); /* 4 bit disp const. */
276 OP
[++i
] = (ins
) & 0xF; /* get 4 bit for reg. */
279 OP
[i
] = (ins
) & 0xFFFF;
280 OP
[++i
] = (ins
>> 16) & 0xF; /* get 4 bit for reg. */
284 OP
[++i
] = (ins
>> 4) & 0xF; /* get 4 bit for reg. */
285 OP
[++i
] = (ins
>> 8) & 0x1; /* get 1 bit for index-reg. */
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. */
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. */
298 case regr
: case regp
: case pregr
: case pregrp
:
302 if (start_bit
== 20) OP
[i
] = (ins
>> 4) & 0xF;
303 else if (start_bit
== 16) OP
[i
] = ins
& 0xF;
305 case 2: OP
[i
] = (ins
>> start_bit
) & 0xF; break;
306 case 3: OP
[i
] = (ins
>> (start_bit
+ 16)) & 0xF; break;
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;
319 /* For ESC on uimm4_1 operand. */
320 if (op_type
== uimm4_1
)
324 /* For increment by 1. */
325 if ((op_type
== pregr
) || (op_type
== pregrp
))
328 /* FIXME: for tracing, update values that need to be updated each
329 instruction decode cycle */
330 State
.trace
.psw
= PSR
;
334 do_run (SIM_DESC sd
, SIM_CPU
*cpu
, uint64_t mcode
)
336 struct hash_entry
*h
;
339 if ((cr16_debug
& DEBUG_INSTRUCTION
) != 0)
340 sim_io_printf (sd
, "do_long 0x%" PRIx64
"\n", mcode
);
343 h
= lookup_hash (sd
, cpu
, mcode
, 1);
345 if ((h
== NULL
) || (h
->opcode
== 0))
349 mcode
= (mcode
<< 16) | RW (PC
+ 4);
351 /* Re-set OP list. */
352 OP
[0] = OP
[1] = OP
[2] = OP
[3] = sign_flag
= 0;
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. */
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
);
362 //State.ins_type = h->flags;
364 (h
->ops
->func
) (sd
, cpu
);
370 cr16_pc_get (sim_cpu
*cpu
)
376 cr16_pc_set (sim_cpu
*cpu
, sim_cia pc
)
378 SIM_DESC sd
= CPU_STATE (cpu
);
383 free_state (SIM_DESC sd
)
385 if (STATE_MODULES (sd
) != NULL
)
386 sim_module_uninstall (sd
);
387 sim_cpu_free_all (sd
);
391 static int cr16_reg_fetch (SIM_CPU
*, int, void *, int);
392 static int cr16_reg_store (SIM_CPU
*, int, const void *, int);
395 sim_open (SIM_OPEN_KIND kind
, struct host_callback_struct
*cb
,
396 struct bfd
*abfd
, char * const *argv
)
399 struct hash_entry
*h
;
400 static int init_p
= 0;
402 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
403 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
405 /* Set default options before parsing user options. */
406 current_target_byte_order
= BFD_ENDIAN_LITTLE
;
407 cb
->syscall_map
= cb_cr16_syscall_map
;
409 /* The cpu data is kept in a separately allocated chunk of memory. */
410 if (sim_cpu_alloc_all (sd
, 0) != SIM_RC_OK
)
416 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
422 /* The parser will print an error message for us, so we silently return. */
423 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
429 /* Check for/establish the a reference program image. */
430 if (sim_analyze_program (sd
, STATE_PROG_FILE (sd
), abfd
) != SIM_RC_OK
)
436 /* Configure/verify the target byte order and other runtime
437 configuration options. */
438 if (sim_config (sd
) != SIM_RC_OK
)
440 sim_module_uninstall (sd
);
444 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
446 /* Uninstall the modules to avoid memory leaks,
447 file descriptor leaks, etc. */
448 sim_module_uninstall (sd
);
452 /* CPU specific initialization. */
453 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
455 SIM_CPU
*cpu
= STATE_CPU (sd
, i
);
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
;
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);
471 /* put all the opcodes in the hash table. */
474 for (s
= Simops
; s
->func
; s
++)
479 h
= &hash_table
[hash(s
->opcode
, 0)];
483 if (((s
->opcode
<< 1) >> 4) != 0)
484 h
= &hash_table
[hash((s
->opcode
<< 1) >> 4, 0)];
486 h
= &hash_table
[hash((s
->opcode
<< 1), 0)];
490 if ((s
->opcode
>> 4) != 0)
491 h
= &hash_table
[hash(s
->opcode
>> 4, 0)];
493 h
= &hash_table
[hash(s
->opcode
, 0)];
497 if (((s
->opcode
>> 1) >> 4) != 0)
498 h
= &hash_table
[hash((s
->opcode
>>1) >> 4, 0)];
500 h
= &hash_table
[hash((s
->opcode
>> 1), 0)];
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)];
509 h
= &hash_table
[hash(s
->opcode
, 0)];
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)];
518 h
= &hash_table
[hash(s
->opcode
, 0)];
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)];
527 h
= &hash_table
[hash((s
->opcode
>>1), 0)];
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)];
538 h
= &hash_table
[hash(s
->opcode
, 0)];
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)];
551 h
= &hash_table
[hash(s
->opcode
, 0)];
558 /* go to the last entry in the chain. */
564 h
->next
= (struct hash_entry
*) calloc(1,sizeof(struct hash_entry
));
566 perror ("malloc failure");
572 h
->opcode
= s
->opcode
;
573 h
->format
= s
->format
;
582 step_once (SIM_DESC sd
, SIM_CPU
*cpu
)
584 uint32_t curr_ins_size
= 0;
585 uint64_t mcode
= RLW (PC
);
587 State
.pc_changed
= 0;
589 curr_ins_size
= do_run (sd
, cpu
, mcode
);
592 sim_io_printf (sd
, "INS: PC=0x%X, mcode=0x%X\n", PC
, mcode
);
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. */
601 /* Check for a breakpoint trap on this instruction. This
602 overrides any pending branches or loops */
603 if (PSR_DB
&& PC
== DBS
)
607 SET_PC (SDBT_VECTOR_START
);
611 /* Writeback all the DATA / PC changes */
616 sim_engine_run (SIM_DESC sd
,
617 int next_cpu_nr
, /* ignore */
618 int nr_cpus
, /* ignore */
623 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
625 cpu
= STATE_CPU (sd
, 0);
632 case GDB_SIGNAL_SEGV
:
635 JMP (AE_VECTOR_START
);
641 SET_HW_PSR ((PSR
& (PSR_C_BIT
)));
642 JMP (RIE_VECTOR_START
);
653 if (sim_events_tick (sd
))
654 sim_events_process (sd
);
659 sim_create_inferior (SIM_DESC sd
, struct bfd
*abfd
,
660 char * const *argv
, char * const *env
)
662 bfd_vma start_address
;
664 /* reset all state information */
665 memset (&State
, 0, sizeof (State
));
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
677 start_address
= bfd_get_start_address (abfd
);
682 sim_io_printf (sd
, "sim_create_inferior: PC=0x%" PRIx64
"\n",
683 (uint64_t) start_address
);
686 SIM_CPU
*cpu
= STATE_CPU (sd
, 0);
687 SET_CREG (PC_CR
, start_address
);
695 cr16_extract_unsigned_integer (const unsigned char *addr
, int len
)
699 unsigned char * startaddr
= (unsigned char *)addr
;
700 unsigned char * endaddr
= startaddr
+ len
;
704 for (p
= endaddr
; p
> startaddr
;)
705 retval
= (retval
<< 8) | *--p
;
711 cr16_store_unsigned_integer (unsigned char *addr
, int len
, uint32_t val
)
714 unsigned char *startaddr
= addr
;
715 unsigned char *endaddr
= startaddr
+ len
;
717 for (p
= startaddr
; p
< endaddr
;)
725 cr16_reg_fetch (SIM_CPU
*cpu
, int rn
, void *memory
, int length
)
728 switch ((enum sim_cr16_regs
) rn
)
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
));
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
));
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
));
774 cr16_reg_store (SIM_CPU
*cpu
, int rn
, const void *memory
, int length
)
776 SIM_DESC sd
= CPU_STATE (cpu
);
778 switch ((enum sim_cr16_regs
) rn
)
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));
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));
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));