1 /* syscalls.c --- implement system calls for the M32C simulator. 2 3 Copyright (C) 2005-2024 Free Software Foundation, Inc. 4 Contributed by Red Hat, Inc. 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 /* This must come before any other includes. */ 22 #include "defs.h" 23 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <fcntl.h> 27 #include <unistd.h> 28 #include <sys/time.h> 29 30 #include "sim/callback.h" 31 32 #include "cpu.h" 33 #include "mem.h" 34 #include "syscalls.h" 35 #include "target-newlib-syscall.h" 36 37 /* The current syscall callbacks we're using. */ 38 static struct host_callback_struct *callbacks; 39 40 void 41 set_callbacks (struct host_callback_struct *cb) 42 { 43 callbacks = cb; 44 } 45 46 47 /* A16 ABI: arg1 in r1l (QI) or r1 (HI) or stack 48 arg2 in r2 (HI) or stack 49 arg3..N on stack 50 padding: none 51 52 A24 ABI: arg1 in r0l (QI) or r0 (HI) or stack 53 arg2..N on stack 54 padding: qi->hi 55 56 return value in r0l (QI) r0 (HI) r2r0 (SI) 57 structs: pointer pushed on stack last 58 59 */ 60 61 int argp, stackp; 62 63 static int 64 arg (int bytes) 65 { 66 int rv = 0; 67 argp++; 68 if (A16) 69 { 70 switch (argp) 71 { 72 case 1: 73 if (bytes == 1) 74 return get_reg (r1l); 75 if (bytes == 2) 76 return get_reg (r1); 77 break; 78 case 2: 79 if (bytes == 2) 80 return get_reg (r2); 81 break; 82 } 83 } 84 else 85 { 86 switch (argp) 87 { 88 case 1: 89 if (bytes == 1) 90 return get_reg (r0l); 91 if (bytes == 2) 92 return get_reg (r0); 93 break; 94 } 95 } 96 if (bytes == 0) 97 bytes = 2; 98 switch (bytes) 99 { 100 case 1: 101 rv = mem_get_qi (get_reg (sp) + stackp); 102 if (A24) 103 stackp++; 104 break; 105 case 2: 106 rv = mem_get_hi (get_reg (sp) + stackp); 107 break; 108 case 3: 109 rv = mem_get_psi (get_reg (sp) + stackp); 110 if (A24) 111 stackp++; 112 break; 113 case 4: 114 rv = mem_get_si (get_reg (sp) + stackp); 115 break; 116 } 117 stackp += bytes; 118 return rv; 119 } 120 121 static void 122 read_target (char *buffer, int address, int count, int asciiz) 123 { 124 char byte; 125 while (count > 0) 126 { 127 byte = mem_get_qi (address++); 128 *buffer++ = byte; 129 if (asciiz && (byte == 0)) 130 return; 131 count--; 132 } 133 } 134 135 static void 136 write_target (char *buffer, int address, int count, int asciiz) 137 { 138 char byte; 139 while (count > 0) 140 { 141 byte = *buffer++; 142 mem_put_qi (address++, byte); 143 if (asciiz && (byte == 0)) 144 return; 145 count--; 146 } 147 } 148 149 #define PTRSZ (A16 ? 2 : 3) 150 151 static char *callnames[] = { 152 "SYS_zero", 153 "SYS_exit", 154 "SYS_open", 155 "SYS_close", 156 "SYS_read", 157 "SYS_write", 158 "SYS_lseek", 159 "SYS_unlink", 160 "SYS_getpid", 161 "SYS_kill", 162 "SYS_fstat", 163 "SYS_sbrk", 164 "SYS_argvlen", 165 "SYS_argv", 166 "SYS_chdir", 167 "SYS_stat", 168 "SYS_chmod", 169 "SYS_utime", 170 "SYS_time", 171 "SYS_gettimeofday", 172 "SYS_times", 173 "SYS_link" 174 }; 175 176 void 177 m32c_syscall (int id) 178 { 179 static char buf[256]; 180 int rv; 181 182 argp = 0; 183 stackp = A16 ? 3 : 4; 184 if (trace) 185 printf ("\033[31m/* SYSCALL(%d) = %s */\033[0m\n", id, callnames[id]); 186 switch (id) 187 { 188 case TARGET_NEWLIB_SYS_exit: 189 { 190 int ec = arg (2); 191 if (verbose) 192 printf ("[exit %d]\n", ec); 193 step_result = M32C_MAKE_EXITED (ec); 194 } 195 break; 196 197 case TARGET_NEWLIB_SYS_open: 198 { 199 int path = arg (PTRSZ); 200 int oflags = arg (2); 201 int cflags = arg (2); 202 203 read_target (buf, path, 256, 1); 204 if (trace) 205 printf ("open(\"%s\",0x%x,%#o) = ", buf, oflags, cflags); 206 207 if (callbacks) 208 /* The callback vector ignores CFLAGS. */ 209 rv = callbacks->open (callbacks, buf, oflags); 210 else 211 { 212 int h_oflags = 0; 213 214 if (oflags & 0x0001) 215 h_oflags |= O_WRONLY; 216 if (oflags & 0x0002) 217 h_oflags |= O_RDWR; 218 if (oflags & 0x0200) 219 h_oflags |= O_CREAT; 220 if (oflags & 0x0008) 221 h_oflags |= O_APPEND; 222 if (oflags & 0x0400) 223 h_oflags |= O_TRUNC; 224 rv = open (buf, h_oflags, cflags); 225 } 226 if (trace) 227 printf ("%d\n", rv); 228 put_reg (r0, rv); 229 } 230 break; 231 232 case TARGET_NEWLIB_SYS_close: 233 { 234 int fd = arg (2); 235 236 if (callbacks) 237 rv = callbacks->close (callbacks, fd); 238 else if (fd > 2) 239 rv = close (fd); 240 else 241 rv = 0; 242 if (trace) 243 printf ("close(%d) = %d\n", fd, rv); 244 put_reg (r0, rv); 245 } 246 break; 247 248 case TARGET_NEWLIB_SYS_read: 249 { 250 int fd = arg (2); 251 int addr = arg (PTRSZ); 252 int count = arg (2); 253 254 if (count > sizeof (buf)) 255 count = sizeof (buf); 256 if (callbacks) 257 rv = callbacks->read (callbacks, fd, buf, count); 258 else 259 rv = read (fd, buf, count); 260 if (trace) 261 printf ("read(%d,%d) = %d\n", fd, count, rv); 262 if (rv > 0) 263 write_target (buf, addr, rv, 0); 264 put_reg (r0, rv); 265 } 266 break; 267 268 case TARGET_NEWLIB_SYS_write: 269 { 270 int fd = arg (2); 271 int addr = arg (PTRSZ); 272 int count = arg (2); 273 274 if (count > sizeof (buf)) 275 count = sizeof (buf); 276 if (trace) 277 printf ("write(%d,0x%x,%d)\n", fd, addr, count); 278 read_target (buf, addr, count, 0); 279 if (trace) 280 fflush (stdout); 281 if (callbacks) 282 rv = callbacks->write (callbacks, fd, buf, count); 283 else 284 rv = write (fd, buf, count); 285 if (trace) 286 printf ("write(%d,%d) = %d\n", fd, count, rv); 287 put_reg (r0, rv); 288 } 289 break; 290 291 case TARGET_NEWLIB_SYS_getpid: 292 put_reg (r0, 42); 293 break; 294 295 case TARGET_NEWLIB_SYS_gettimeofday: 296 { 297 int tvaddr = arg (PTRSZ); 298 struct timeval tv; 299 300 rv = gettimeofday (&tv, 0); 301 if (trace) 302 printf ("gettimeofday: %" PRId64 " sec %" PRId64 " usec to 0x%x\n", 303 (int64_t)tv.tv_sec, (int64_t)tv.tv_usec, tvaddr); 304 mem_put_si (tvaddr, tv.tv_sec); 305 mem_put_si (tvaddr + 4, tv.tv_usec); 306 put_reg (r0, rv); 307 } 308 break; 309 310 case TARGET_NEWLIB_SYS_kill: 311 { 312 int pid = arg (2); 313 int sig = arg (2); 314 if (pid == 42) 315 { 316 if (verbose) 317 printf ("[signal %d]\n", sig); 318 step_result = M32C_MAKE_STOPPED (sig); 319 } 320 } 321 break; 322 323 case 11: 324 { 325 int heaptop_arg = arg (PTRSZ); 326 if (trace) 327 printf ("sbrk: heap top set to %x\n", heaptop_arg); 328 heaptop = heaptop_arg; 329 if (heapbottom == 0) 330 heapbottom = heaptop_arg; 331 } 332 break; 333 334 } 335 } 336