xref: /netbsd-src/external/gpl3/gdb/dist/sim/iq2000/iq2000.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /* IQ2000 simulator support code
2    Copyright (C) 2000-2014 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 }
267