]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/iq2000/iq2000.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / sim / iq2000 / iq2000.c
1 /* IQ2000 simulator support code
2 Copyright (C) 2000-2023 Free Software Foundation, Inc.
3 Contributed by Cygnus Support.
4
5 This file is part of the GNU simulators.
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 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 /* This must come before any other includes. */
21 #include "defs.h"
22
23 #define WANT_CPU
24 #define WANT_CPU_IQ2000BF
25
26 #include "sim-main.h"
27 #include "sim-signal.h"
28 #include "cgen-mem.h"
29 #include "cgen-ops.h"
30 #include "target-newlib-syscall.h"
31 #include <stdlib.h>
32
33 enum
34 {
35 GPR0_REGNUM = 0,
36 NR_GPR = 32,
37 PC_REGNUM = 32
38 };
39
40 /* Read a null terminated string from memory, return in a buffer */
41 static char *
42 fetch_str (SIM_CPU *current_cpu, PCADDR pc, DI addr)
43 {
44 char *buf;
45 int nr = 0;
46 while (sim_core_read_1 (current_cpu,
47 pc, read_map, CPU2DATA(addr + nr)) != 0)
48 nr++;
49 buf = NZALLOC (char, nr + 1);
50 sim_read (CPU_STATE (current_cpu), CPU2DATA(addr), buf, nr);
51 return buf;
52 }
53
54 void
55 do_syscall (SIM_CPU *current_cpu, PCADDR pc)
56 {
57 #if 0
58 int syscall = H2T_4 (iq2000bf_h_gr_get (current_cpu, 11));
59 #endif
60 int syscall_function = iq2000bf_h_gr_get (current_cpu, 4);
61 int i;
62 char *buf;
63 int PARM1 = iq2000bf_h_gr_get (current_cpu, 5);
64 int PARM2 = iq2000bf_h_gr_get (current_cpu, 6);
65 int PARM3 = iq2000bf_h_gr_get (current_cpu, 7);
66 const int ret_reg = 2;
67
68 switch (syscall_function)
69 {
70 case 0:
71 switch (H2T_4 (iq2000bf_h_gr_get (current_cpu, 11)))
72 {
73 case 0:
74 /* Pass. */
75 puts ("pass");
76 exit (0);
77 case 1:
78 /* Fail. */
79 puts ("fail");
80 exit (1);
81 }
82
83 case TARGET_NEWLIB_SYS_write:
84 buf = zalloc (PARM3);
85 sim_read (CPU_STATE (current_cpu), CPU2DATA(PARM2), buf, PARM3);
86 SET_H_GR (ret_reg,
87 sim_io_write (CPU_STATE (current_cpu),
88 PARM1, buf, PARM3));
89 free (buf);
90 break;
91
92 case TARGET_NEWLIB_SYS_lseek:
93 SET_H_GR (ret_reg,
94 sim_io_lseek (CPU_STATE (current_cpu),
95 PARM1, PARM2, PARM3));
96 break;
97
98 case TARGET_NEWLIB_SYS_exit:
99 sim_engine_halt (CPU_STATE (current_cpu), current_cpu,
100 NULL, pc, sim_exited, PARM1);
101 break;
102
103 case TARGET_NEWLIB_SYS_read:
104 buf = zalloc (PARM3);
105 SET_H_GR (ret_reg,
106 sim_io_read (CPU_STATE (current_cpu),
107 PARM1, buf, PARM3));
108 sim_write (CPU_STATE (current_cpu), CPU2DATA(PARM2),
109 (unsigned char *) buf, PARM3);
110 free (buf);
111 break;
112
113 case TARGET_NEWLIB_SYS_open:
114 buf = fetch_str (current_cpu, pc, PARM1);
115 SET_H_GR (ret_reg,
116 sim_io_open (CPU_STATE (current_cpu),
117 buf, PARM2));
118 free (buf);
119 break;
120
121 case TARGET_NEWLIB_SYS_close:
122 SET_H_GR (ret_reg,
123 sim_io_close (CPU_STATE (current_cpu), PARM1));
124 break;
125
126 case TARGET_NEWLIB_SYS_time:
127 SET_H_GR (ret_reg, time (0));
128 break;
129
130 default:
131 SET_H_GR (ret_reg, -1);
132 }
133 }
134
135 void
136 do_break (SIM_CPU *current_cpu, PCADDR pc)
137 {
138 SIM_DESC sd = CPU_STATE (current_cpu);
139 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
140 }
141
142 /* The semantic code invokes this for invalid (unrecognized) instructions. */
143
144 SEM_PC
145 sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc)
146 {
147 SIM_DESC sd = CPU_STATE (current_cpu);
148 sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL);
149
150 return vpc;
151 }
152
153
154 /* Process an address exception. */
155
156 void
157 iq2000_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia,
158 unsigned int map, int nr_bytes, address_word addr,
159 transfer_type transfer, sim_core_signals sig)
160 {
161 sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr,
162 transfer, sig);
163 }
164
165
166 /* Initialize cycle counting for an insn.
167 FIRST_P is non-zero if this is the first insn in a set of parallel
168 insns. */
169
170 void
171 iq2000bf_model_insn_before (SIM_CPU *cpu, int first_p)
172 {
173 /* Do nothing. */
174 }
175
176
177 /* Record the cycles computed for an insn.
178 LAST_P is non-zero if this is the last insn in a set of parallel insns,
179 and we update the total cycle count.
180 CYCLES is the cycle count of the insn. */
181
182 void
183 iq2000bf_model_insn_after(SIM_CPU *cpu, int last_p, int cycles)
184 {
185 /* Do nothing. */
186 }
187
188
189 int
190 iq2000bf_model_iq2000_u_exec (SIM_CPU *cpu, const IDESC *idesc,
191 int unit_num, int referenced)
192 {
193 return idesc->timing->units[unit_num].done;
194 }
195
196 PCADDR
197 get_h_pc (SIM_CPU *cpu)
198 {
199 return CPU_CGEN_HW(cpu)->h_pc;
200 }
201
202 void
203 set_h_pc (SIM_CPU *cpu, PCADDR addr)
204 {
205 CPU_CGEN_HW(cpu)->h_pc = addr | IQ2000_INSN_MASK;
206 }
207
208 int
209 iq2000bf_fetch_register (SIM_CPU *cpu, int nr, void *buf, int len)
210 {
211 if (nr >= GPR0_REGNUM
212 && nr < (GPR0_REGNUM + NR_GPR)
213 && len == 4)
214 {
215 *((uint32_t*)buf) =
216 H2T_4 (iq2000bf_h_gr_get (cpu, nr - GPR0_REGNUM));
217 return 4;
218 }
219 else if (nr == PC_REGNUM
220 && len == 4)
221 {
222 *((uint32_t*)buf) = H2T_4 (get_h_pc (cpu));
223 return 4;
224 }
225 else
226 return 0;
227 }
228
229 int
230 iq2000bf_store_register (SIM_CPU *cpu, int nr, const void *buf, int len)
231 {
232 if (nr >= GPR0_REGNUM
233 && nr < (GPR0_REGNUM + NR_GPR)
234 && len == 4)
235 {
236 iq2000bf_h_gr_set (cpu, nr - GPR0_REGNUM, T2H_4 (*((uint32_t*)buf)));
237 return 4;
238 }
239 else if (nr == PC_REGNUM
240 && len == 4)
241 {
242 set_h_pc (cpu, T2H_4 (*((uint32_t*)buf)));
243 return 4;
244 }
245 else
246 return 0;
247 }