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