]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/iq2000/iq2000.c
Update years in copyright notice for the GDB files.
[thirdparty/binutils-gdb.git] / sim / iq2000 / iq2000.c
1 /* IQ2000 simulator support code
2 Copyright (C) 2000-2013 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 #define WANT_CPU
21 #define WANT_CPU_IQ2000BF
22
23 #include "sim-main.h"
24 #include "cgen-mem.h"
25 #include "cgen-ops.h"
26
27 enum
28 {
29 GPR0_REGNUM = 0,
30 NR_GPR = 32,
31 PC_REGNUM = 32
32 };
33
34 enum libgloss_syscall
35 {
36 SYS_exit = 1,
37 SYS_open = 2,
38 SYS_close = 3,
39 SYS_read = 4,
40 SYS_write = 5,
41 SYS_lseek = 6,
42 SYS_unlink = 7,
43 SYS_getpid = 8,
44 SYS_kill = 9,
45 SYS_fstat = 10,
46 SYS_argvlen = 12,
47 SYS_argv = 13,
48 SYS_chdir = 14,
49 SYS_stat = 15,
50 SYS_chmod = 16,
51 SYS_utime = 17,
52 SYS_time = 18,
53 SYS_gettimeofday = 19,
54 SYS_times = 20
55 };
56
57 /* Read a null terminated string from memory, return in a buffer */
58 static char *
59 fetch_str (current_cpu, pc, addr)
60 SIM_CPU *current_cpu;
61 PCADDR pc;
62 DI addr;
63 {
64 char *buf;
65 int nr = 0;
66 while (sim_core_read_1 (current_cpu,
67 pc, read_map, CPU2DATA(addr + nr)) != 0)
68 nr++;
69 buf = NZALLOC (char, nr + 1);
70 sim_read (CPU_STATE (current_cpu), CPU2DATA(addr), buf, nr);
71 return buf;
72 }
73
74 void
75 do_syscall (SIM_CPU *current_cpu, PCADDR pc)
76 {
77 #if 0
78 int syscall = H2T_4 (iq2000bf_h_gr_get (current_cpu, 11));
79 #endif
80 int syscall_function = iq2000bf_h_gr_get (current_cpu, 4);
81 int i;
82 char *buf;
83 int PARM1 = iq2000bf_h_gr_get (current_cpu, 5);
84 int PARM2 = iq2000bf_h_gr_get (current_cpu, 6);
85 int PARM3 = iq2000bf_h_gr_get (current_cpu, 7);
86 const int ret_reg = 2;
87
88 switch (syscall_function)
89 {
90 case 0:
91 switch (H2T_4 (iq2000bf_h_gr_get (current_cpu, 11)))
92 {
93 case 0:
94 /* Pass. */
95 puts ("pass");
96 exit (0);
97 case 1:
98 /* Fail. */
99 puts ("fail");
100 exit (1);
101 }
102
103 case SYS_write:
104 buf = zalloc (PARM3);
105 sim_read (CPU_STATE (current_cpu), CPU2DATA(PARM2), buf, PARM3);
106 SET_H_GR (ret_reg,
107 sim_io_write (CPU_STATE (current_cpu),
108 PARM1, buf, PARM3));
109 free (buf);
110 break;
111
112 case SYS_lseek:
113 SET_H_GR (ret_reg,
114 sim_io_lseek (CPU_STATE (current_cpu),
115 PARM1, PARM2, PARM3));
116 break;
117
118 case SYS_exit:
119 sim_engine_halt (CPU_STATE (current_cpu), current_cpu,
120 NULL, pc, sim_exited, PARM1);
121 break;
122
123 case SYS_read:
124 buf = zalloc (PARM3);
125 SET_H_GR (ret_reg,
126 sim_io_read (CPU_STATE (current_cpu),
127 PARM1, buf, PARM3));
128 sim_write (CPU_STATE (current_cpu), CPU2DATA(PARM2), buf, PARM3);
129 free (buf);
130 break;
131
132 case SYS_open:
133 buf = fetch_str (current_cpu, pc, PARM1);
134 SET_H_GR (ret_reg,
135 sim_io_open (CPU_STATE (current_cpu),
136 buf, PARM2));
137 free (buf);
138 break;
139
140 case SYS_close:
141 SET_H_GR (ret_reg,
142 sim_io_close (CPU_STATE (current_cpu), PARM1));
143 break;
144
145 case SYS_time:
146 SET_H_GR (ret_reg, time (0));
147 break;
148
149 default:
150 SET_H_GR (ret_reg, -1);
151 }
152 }
153
154 void
155 do_break (SIM_CPU *current_cpu, PCADDR pc)
156 {
157 SIM_DESC sd = CPU_STATE (current_cpu);
158 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
159 }
160
161 /* The semantic code invokes this for invalid (unrecognized) instructions. */
162
163 SEM_PC
164 sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc)
165 {
166 SIM_DESC sd = CPU_STATE (current_cpu);
167 sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL);
168
169 return vpc;
170 }
171
172
173 /* Process an address exception. */
174
175 void
176 iq2000_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia,
177 unsigned int map, int nr_bytes, address_word addr,
178 transfer_type transfer, sim_core_signals sig)
179 {
180 sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr,
181 transfer, sig);
182 }
183
184
185 /* Initialize cycle counting for an insn.
186 FIRST_P is non-zero if this is the first insn in a set of parallel
187 insns. */
188
189 void
190 iq2000bf_model_insn_before (SIM_CPU *cpu, int first_p)
191 {
192 /* Do nothing. */
193 }
194
195
196 /* Record the cycles computed for an insn.
197 LAST_P is non-zero if this is the last insn in a set of parallel insns,
198 and we update the total cycle count.
199 CYCLES is the cycle count of the insn. */
200
201 void
202 iq2000bf_model_insn_after(SIM_CPU *cpu, int last_p, int cycles)
203 {
204 /* Do nothing. */
205 }
206
207
208 int
209 iq2000bf_model_iq2000_u_exec (SIM_CPU *cpu, const IDESC *idesc,
210 int unit_num, int referenced)
211 {
212 return idesc->timing->units[unit_num].done;
213 }
214
215 PCADDR
216 get_h_pc (SIM_CPU *cpu)
217 {
218 return CPU_CGEN_HW(cpu)->h_pc;
219 }
220
221 void
222 set_h_pc (SIM_CPU *cpu, PCADDR addr)
223 {
224 CPU_CGEN_HW(cpu)->h_pc = addr | IQ2000_INSN_MASK;
225 }
226
227 int
228 iq2000bf_fetch_register (SIM_CPU *cpu, int nr, unsigned char *buf, int len)
229 {
230 if (nr >= GPR0_REGNUM
231 && nr < (GPR0_REGNUM + NR_GPR)
232 && len == 4)
233 {
234 *((unsigned32*)buf) =
235 H2T_4 (iq2000bf_h_gr_get (cpu, nr - GPR0_REGNUM));
236 return 4;
237 }
238 else if (nr == PC_REGNUM
239 && len == 4)
240 {
241 *((unsigned32*)buf) = H2T_4 (get_h_pc (cpu));
242 return 4;
243 }
244 else
245 return 0;
246 }
247
248 int
249 iq2000bf_store_register (SIM_CPU *cpu, int nr, unsigned char *buf, int len)
250 {
251 if (nr >= GPR0_REGNUM
252 && nr < (GPR0_REGNUM + NR_GPR)
253 && len == 4)
254 {
255 iq2000bf_h_gr_set (cpu, nr - GPR0_REGNUM, T2H_4 (*((unsigned32*)buf)));
256 return 4;
257 }
258 else if (nr == PC_REGNUM
259 && len == 4)
260 {
261 set_h_pc (cpu, T2H_4 (*((unsigned32*)buf)));
262 return 4;
263 }
264 else
265 return 0;
266 }