Commit | Line | Data |
---|---|---|
a1dc3945 AC |
1 | /* This file is part of the program psim. |
2 | ||
3 | Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au> | |
4 | ||
5 | This program is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 2 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | This program is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this program; if not, write to the Free Software | |
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
18 | ||
19 | */ | |
20 | ||
21 | ||
69628a60 MM |
22 | #include "sim-main.h" |
23 | #include "sim-io.h" | |
24 | #include "targ-vals.h" | |
a1dc3945 AC |
25 | |
26 | /* See the file include/callbacks.h for a description */ | |
27 | ||
28 | ||
69628a60 | 29 | int |
fa21d299 | 30 | sim_io_init(SIM_DESC sd) |
a1dc3945 | 31 | { |
69628a60 | 32 | return STATE_CALLBACK (sd)->init (STATE_CALLBACK (sd)); |
a1dc3945 AC |
33 | } |
34 | ||
35 | ||
69628a60 | 36 | int |
fa21d299 | 37 | sim_io_shutdown(SIM_DESC sd) |
a1dc3945 | 38 | { |
69628a60 | 39 | return STATE_CALLBACK (sd)->shutdown (STATE_CALLBACK (sd)); |
a1dc3945 AC |
40 | } |
41 | ||
42 | ||
69628a60 | 43 | int |
fa21d299 | 44 | sim_io_unlink(SIM_DESC sd, |
a1dc3945 AC |
45 | const char *f1) |
46 | { | |
69628a60 | 47 | return STATE_CALLBACK (sd)->unlink (STATE_CALLBACK (sd), f1); |
a1dc3945 AC |
48 | } |
49 | ||
50 | ||
69628a60 | 51 | long |
fa21d299 | 52 | sim_io_time(SIM_DESC sd, |
a1dc3945 AC |
53 | long *t) |
54 | { | |
69628a60 | 55 | return STATE_CALLBACK (sd)->time (STATE_CALLBACK (sd), t); |
a1dc3945 AC |
56 | } |
57 | ||
58 | ||
69628a60 | 59 | int |
fa21d299 | 60 | sim_io_system(SIM_DESC sd, const char *s) |
a1dc3945 | 61 | { |
69628a60 | 62 | return STATE_CALLBACK (sd)->system (STATE_CALLBACK (sd), s); |
a1dc3945 AC |
63 | } |
64 | ||
65 | ||
69628a60 | 66 | int |
fa21d299 | 67 | sim_io_rename(SIM_DESC sd, |
a1dc3945 AC |
68 | const char *f1, |
69 | const char *f2) | |
70 | { | |
69628a60 | 71 | return STATE_CALLBACK (sd)->rename (STATE_CALLBACK (sd), f1, f2); |
a1dc3945 AC |
72 | } |
73 | ||
74 | ||
69628a60 | 75 | int |
fa21d299 | 76 | sim_io_write_stdout(SIM_DESC sd, |
a1dc3945 AC |
77 | const char *buf, |
78 | int len) | |
79 | { | |
80 | switch (CURRENT_STDIO) { | |
81 | case DO_USE_STDIO: | |
69628a60 | 82 | return STATE_CALLBACK (sd)->write_stdout (STATE_CALLBACK (sd), buf, len); |
a1dc3945 AC |
83 | break; |
84 | case DONT_USE_STDIO: | |
69628a60 | 85 | return STATE_CALLBACK (sd)->write (STATE_CALLBACK (sd), 1, buf, len); |
a1dc3945 AC |
86 | break; |
87 | default: | |
fa21d299 | 88 | sim_io_error (sd, "sim_io_write_stdout: unaccounted switch\n"); |
a1dc3945 AC |
89 | break; |
90 | } | |
91 | return 0; | |
92 | } | |
93 | ||
94 | ||
69628a60 | 95 | void |
fa21d299 | 96 | sim_io_flush_stdout(SIM_DESC sd) |
a1dc3945 AC |
97 | { |
98 | switch (CURRENT_STDIO) { | |
99 | case DO_USE_STDIO: | |
69628a60 | 100 | STATE_CALLBACK (sd)->flush_stdout (STATE_CALLBACK (sd)); |
a1dc3945 AC |
101 | break; |
102 | case DONT_USE_STDIO: | |
103 | break; | |
104 | default: | |
fa21d299 | 105 | sim_io_error (sd, "sim_io_flush_stdout: unaccounted switch\n"); |
a1dc3945 AC |
106 | break; |
107 | } | |
108 | } | |
109 | ||
110 | ||
69628a60 | 111 | int |
fa21d299 | 112 | sim_io_write_stderr(SIM_DESC sd, |
a1dc3945 AC |
113 | const char *buf, |
114 | int len) | |
115 | { | |
116 | switch (CURRENT_STDIO) { | |
117 | case DO_USE_STDIO: | |
69628a60 | 118 | return STATE_CALLBACK (sd)->write_stderr (STATE_CALLBACK (sd), buf, len); |
a1dc3945 AC |
119 | break; |
120 | case DONT_USE_STDIO: | |
69628a60 | 121 | return STATE_CALLBACK (sd)->write (STATE_CALLBACK (sd), 2, buf, len); |
a1dc3945 AC |
122 | break; |
123 | default: | |
fa21d299 | 124 | sim_io_error (sd, "sim_io_write_stderr: unaccounted switch\n"); |
a1dc3945 AC |
125 | break; |
126 | } | |
127 | return 0; | |
128 | } | |
129 | ||
130 | ||
69628a60 | 131 | void |
fa21d299 | 132 | sim_io_flush_stderr(SIM_DESC sd) |
a1dc3945 AC |
133 | { |
134 | switch (CURRENT_STDIO) { | |
135 | case DO_USE_STDIO: | |
69628a60 | 136 | STATE_CALLBACK (sd)->flush_stderr (STATE_CALLBACK (sd)); |
a1dc3945 AC |
137 | break; |
138 | case DONT_USE_STDIO: | |
139 | break; | |
140 | default: | |
fa21d299 | 141 | sim_io_error (sd, "sim_io_flush_stderr: unaccounted switch\n"); |
a1dc3945 AC |
142 | break; |
143 | } | |
144 | } | |
145 | ||
146 | ||
69628a60 | 147 | int |
fa21d299 | 148 | sim_io_write(SIM_DESC sd, |
a1dc3945 AC |
149 | int fd, |
150 | const char *buf, | |
151 | int len) | |
152 | { | |
69628a60 | 153 | return STATE_CALLBACK (sd)->write (STATE_CALLBACK (sd), fd, buf, len); |
a1dc3945 AC |
154 | } |
155 | ||
156 | ||
69628a60 | 157 | int |
fa21d299 | 158 | sim_io_read_stdin(SIM_DESC sd, |
a1dc3945 AC |
159 | char *buf, |
160 | int len) | |
161 | { | |
162 | switch (CURRENT_STDIO) { | |
163 | case DO_USE_STDIO: | |
69628a60 | 164 | return STATE_CALLBACK (sd)->read_stdin (STATE_CALLBACK (sd), buf, len); |
a1dc3945 AC |
165 | break; |
166 | case DONT_USE_STDIO: | |
69628a60 | 167 | return STATE_CALLBACK (sd)->read (STATE_CALLBACK (sd), 0, buf, len); |
a1dc3945 AC |
168 | break; |
169 | default: | |
fa21d299 | 170 | sim_io_error (sd, "sim_io_read_stdin: unaccounted switch\n"); |
a1dc3945 AC |
171 | break; |
172 | } | |
173 | return 0; | |
174 | } | |
175 | ||
176 | ||
69628a60 | 177 | int |
fa21d299 | 178 | sim_io_read(SIM_DESC sd, int fd, |
a1dc3945 AC |
179 | char *buf, |
180 | int len) | |
181 | { | |
69628a60 | 182 | return STATE_CALLBACK (sd)->read (STATE_CALLBACK (sd), fd, buf, len); |
a1dc3945 AC |
183 | } |
184 | ||
185 | ||
69628a60 | 186 | int |
fa21d299 | 187 | sim_io_open(SIM_DESC sd, |
a1dc3945 AC |
188 | const char *name, |
189 | int flags) | |
190 | { | |
69628a60 | 191 | return STATE_CALLBACK (sd)->open (STATE_CALLBACK (sd), name, flags); |
a1dc3945 AC |
192 | } |
193 | ||
194 | ||
69628a60 | 195 | int |
fa21d299 | 196 | sim_io_lseek(SIM_DESC sd, |
a1dc3945 AC |
197 | int fd, |
198 | long off, | |
199 | int way) | |
200 | { | |
69628a60 | 201 | return STATE_CALLBACK (sd)->lseek (STATE_CALLBACK (sd), fd, off, way); |
a1dc3945 AC |
202 | } |
203 | ||
204 | ||
69628a60 | 205 | int |
fa21d299 | 206 | sim_io_isatty(SIM_DESC sd, |
a1dc3945 AC |
207 | int fd) |
208 | { | |
69628a60 | 209 | return STATE_CALLBACK (sd)->isatty (STATE_CALLBACK (sd), fd); |
a1dc3945 AC |
210 | } |
211 | ||
212 | ||
69628a60 | 213 | int |
fa21d299 | 214 | sim_io_get_errno(SIM_DESC sd) |
a1dc3945 | 215 | { |
69628a60 | 216 | return STATE_CALLBACK (sd)->get_errno (STATE_CALLBACK (sd)); |
a1dc3945 AC |
217 | } |
218 | ||
219 | ||
69628a60 | 220 | int |
fa21d299 | 221 | sim_io_close(SIM_DESC sd, |
a1dc3945 AC |
222 | int fd) |
223 | { | |
69628a60 | 224 | return STATE_CALLBACK (sd)->close (STATE_CALLBACK (sd), fd); |
a1dc3945 AC |
225 | } |
226 | ||
227 | ||
69628a60 | 228 | void |
fa21d299 | 229 | sim_io_printf(SIM_DESC sd, |
a1dc3945 AC |
230 | const char *fmt, |
231 | ...) | |
232 | { | |
233 | va_list ap; | |
234 | va_start(ap, fmt); | |
69628a60 | 235 | STATE_CALLBACK (sd)->vprintf_filtered (STATE_CALLBACK (sd), fmt, ap); |
a1dc3945 AC |
236 | va_end(ap); |
237 | } | |
238 | ||
239 | ||
69628a60 | 240 | void |
fa21d299 | 241 | sim_io_vprintf(SIM_DESC sd, |
a1dc3945 AC |
242 | const char *fmt, |
243 | va_list ap) | |
244 | { | |
69628a60 | 245 | STATE_CALLBACK (sd)->vprintf_filtered (STATE_CALLBACK (sd), fmt, ap); |
a1dc3945 AC |
246 | } |
247 | ||
248 | ||
69628a60 | 249 | void |
fa21d299 | 250 | sim_io_eprintf(SIM_DESC sd, |
a1dc3945 AC |
251 | const char *fmt, |
252 | ...) | |
253 | { | |
254 | va_list ap; | |
255 | va_start(ap, fmt); | |
69628a60 | 256 | STATE_CALLBACK (sd)->evprintf_filtered (STATE_CALLBACK (sd), fmt, ap); |
a1dc3945 AC |
257 | va_end(ap); |
258 | } | |
259 | ||
260 | ||
69628a60 | 261 | void |
fa21d299 | 262 | sim_io_evprintf(SIM_DESC sd, |
a1dc3945 AC |
263 | const char *fmt, |
264 | va_list ap) | |
265 | { | |
69628a60 | 266 | STATE_CALLBACK (sd)->evprintf_filtered (STATE_CALLBACK (sd), fmt, ap); |
a1dc3945 AC |
267 | } |
268 | ||
269 | ||
69628a60 | 270 | void |
fa21d299 | 271 | sim_io_error(SIM_DESC sd, |
a1dc3945 AC |
272 | const char *fmt, |
273 | ...) | |
274 | { | |
69628a60 | 275 | if (sd == NULL || STATE_CALLBACK (sd) == NULL) { |
fa21d299 AC |
276 | va_list ap; |
277 | va_start(ap, fmt); | |
278 | vfprintf (stderr, fmt, ap); | |
279 | va_end(ap); | |
69628a60 | 280 | fprintf (stderr, "\n"); |
fa21d299 AC |
281 | abort (); |
282 | } | |
283 | else { | |
284 | va_list ap; | |
285 | va_start(ap, fmt); | |
69628a60 | 286 | STATE_CALLBACK (sd)->evprintf_filtered (STATE_CALLBACK (sd), fmt, ap); |
fa21d299 | 287 | va_end(ap); |
69628a60 | 288 | STATE_CALLBACK (sd)->error (STATE_CALLBACK (sd), ""); |
fa21d299 | 289 | } |
a1dc3945 AC |
290 | } |
291 | ||
69628a60 MM |
292 | |
293 | void | |
294 | sim_io_poll_quit(SIM_DESC sd) | |
295 | { | |
296 | if (STATE_CALLBACK (sd)->poll_quit != NULL) | |
297 | if (STATE_CALLBACK (sd)->poll_quit (STATE_CALLBACK (sd))) | |
298 | sim_stop (sd); | |
299 | } | |
300 | ||
301 | ||
302 | static char * | |
303 | sim_io_getstring(SIM_DESC sd, | |
304 | sim_cpu *cpu, | |
305 | address_word cia, | |
306 | address_word target_string) | |
307 | { | |
308 | int len = 0; | |
309 | int len2; | |
310 | char *buf; | |
311 | ||
312 | while (sim_core_read_1 (cpu, cia, sim_core_read_map, target_string+len) != 0) | |
313 | len++; | |
314 | ||
315 | buf = NZALLOC (char, len+1); | |
316 | buf[len] = '\0'; | |
317 | sim_core_read_buffer (sd, cpu, sim_core_read_map, buf, target_string, len); | |
318 | return buf; | |
319 | } | |
320 | ||
321 | void | |
322 | sim_io_syscalls(SIM_DESC sd, | |
323 | int syscall, | |
324 | address_word cia, | |
325 | address_word parm1, | |
326 | address_word parm2, | |
327 | address_word parm3, | |
328 | address_word parm4, | |
329 | address_word *syscall_return, | |
330 | address_word *errno_return) | |
331 | { | |
332 | sim_cpu *cpu = STATE_CPU (sd, 0); | |
333 | struct host_callback_struct *callback = STATE_CALLBACK (sd); | |
334 | int len, len2, len3; | |
335 | int ret; | |
336 | char *buf; | |
337 | int fd; | |
338 | int sys_errno = 0; | |
339 | ||
340 | *errno_return = 0; | |
341 | *syscall_return = 0; | |
342 | ||
343 | switch (syscall) | |
344 | { | |
345 | case 1: /* exit (status) */ | |
346 | sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, cia, sim_exited, parm1); | |
347 | break; | |
348 | ||
349 | case 2: /* open (filename, flags, mode) */ | |
350 | buf = sim_io_getstring (sd, cpu, cia, parm1); | |
351 | ret = *syscall_return = callback->open (callback, buf, parm2); | |
352 | if (ret < 0) | |
353 | *errno_return = callback->get_errno (callback); | |
354 | ||
355 | zfree (buf); | |
356 | break; | |
357 | ||
358 | case 3: /* close (filedes) */ | |
359 | ret = *syscall_return = callback->close (callback, parm1); | |
360 | if (ret < 0) | |
361 | *errno_return = callback->get_errno (callback); | |
362 | break; | |
363 | ||
364 | case 4: /* read (filedes, buffer, len) */ | |
365 | fd = parm1; | |
366 | len = parm3; | |
367 | buf = NZALLOC (char, len); | |
368 | ||
369 | if (fd == 0) | |
370 | len2 = sim_io_read_stdin (sd, buf, len); | |
371 | else | |
372 | len2 = sim_io_read (sd, fd, buf, len); | |
373 | ||
374 | if (len2 > 0) | |
375 | { | |
376 | len3 = sim_core_write_buffer (sd, cpu, sim_core_write_map, buf, parm2, | |
377 | len); | |
378 | ||
379 | if (len3 < len2) | |
380 | sim_engine_abort (sd, cpu, cia, | |
381 | "Could only write back %d bytes for read system call, wanted to write %d\n", | |
382 | len3, len2); | |
383 | ||
384 | *syscall_return = len2; | |
385 | } | |
386 | else | |
387 | *errno_return = callback->get_errno (callback); | |
388 | ||
389 | zfree (buf); | |
390 | break; | |
391 | ||
392 | case 5: /* write (filedes, buffer, len) */ | |
393 | fd = parm1; | |
394 | len = parm3; | |
395 | buf = NZALLOC (char, len); | |
396 | ||
397 | len = sim_core_read_buffer (sd, cpu, sim_core_read_map, buf, parm2, len); | |
398 | if (fd == 1) | |
399 | { | |
400 | len2 = sim_io_write_stdout (sd, buf, len); | |
401 | sim_io_flush_stdout (sd); | |
402 | } | |
403 | else if (fd == 2) | |
404 | { | |
405 | len2 = sim_io_write_stderr (sd, buf, len); | |
406 | sim_io_flush_stderr (sd); | |
407 | } | |
408 | else | |
409 | len2 = sim_io_write (sd, fd, buf, len); | |
410 | ||
411 | if (len2 > 0) | |
412 | *syscall_return = len2; | |
413 | else | |
414 | *errno_return = callback->get_errno (callback); | |
415 | ||
416 | zfree (buf); | |
417 | break; | |
418 | ||
419 | case 6: /* lseek (filedes, offset, whence) */ | |
420 | *errno_return = TARGET_ENOSYS; | |
421 | break; | |
422 | ||
423 | case 7: /* unlink (filename) */ | |
424 | buf = sim_io_getstring (sd, cpu, cia, parm1); | |
425 | ret = *syscall_return = callback->unlink (callback, buf); | |
426 | if (ret < 0) | |
427 | *errno_return = callback->get_errno (callback); | |
428 | ||
429 | zfree (buf); | |
430 | break; | |
431 | ||
432 | case 8: /* getpid () */ | |
433 | case 9: /* kill (signal, pid) */ | |
434 | case 10: /* fstat (filedes, packet) */ | |
435 | case 11: /* reserved for sbrk */ | |
436 | case 12: /* argvlen () */ | |
437 | case 13: /* argv () */ | |
438 | case 14: /* chdir (dir) */ | |
439 | case 15: /* stat (filename, packet) */ | |
440 | case 16: /* chmod (filename, mode) */ | |
441 | case 17: /* utime (filename, packet) */ | |
442 | case 18: /* time (time_t *) */ | |
443 | *errno_return = TARGET_ENOSYS; | |
444 | break; | |
445 | ||
446 | default: | |
447 | sim_engine_abort (sd, cpu, cia, "Unknown monitor call %d", syscall); | |
448 | break; | |
449 | } | |
450 | ||
451 | if (*errno_return) | |
452 | *syscall_return = -1; | |
453 | ||
454 | return; | |
455 | } | |
456 |