OSDN Git Service

Updated copyright notices for most files.
[pf3gnuchains/pf3gnuchains3x.git] / sim / iq2000 / iq2000.c
1 /* IQ2000 simulator support code
2    Copyright (C) 2000, 2004, 2007, 2008 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       zfree (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       zfree (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       zfree (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 }