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