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