xref: /netbsd-src/external/gpl3/gdb/dist/sim/iq2000/iq2000.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /* IQ2000 simulator support code
2    Copyright (C) 2000, 2004, 2007, 2008, 2009, 2010, 2011
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       free (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       free (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       free (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 }
268