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