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