Main Page | Modules | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages | Examples

ac_syscall.cpp

00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 
00003 /*  ArchC Syscall Library for the ArchC architecture simulators
00004     Copyright (C) 2002-2004  The ArchC Team
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Lesser General Public
00008     License as published by the Free Software Foundation; either
00009     version 2.1 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Lesser General Public License for more details.
00015 */
00016 
00017 /********************************************************/
00018 /* ArchC Syscalls implementation file.                  */
00019 /* Author:  Marcus Bartholomeu                          */
00020 /*                                                      */
00021 /*                                                      */
00022 /* The ArchC Team                                       */
00023 /* Computer Systems Laboratory (LSC)                    */
00024 /* IC-UNICAMP                                           */
00025 /* http://www.lsc.ic.unicamp.br                         */
00026 /********************************************************/
00027  
00028 
00029 #include "ac_syscall.H"
00030 #include "archc.H"
00031 #include "ac_resources.H"
00032 
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #include <string.h>
00036 
00037 #include <sys/types.h>
00038 #include <sys/stat.h>
00039 #include <fcntl.h>
00040 #include <unistd.h>
00041 #include <errno.h>
00042 
00043 #include <sys/times.h>
00044 #include <time.h>
00045 
00046 #ifdef DEBUG
00047 #  define DEBUG_SYSCALL(name) AC_RUN_MSG("@@@@@ syscall: " name " @@@@@\n")
00048 #else
00049 #  define DEBUG_SYSCALL(name)
00050 #endif
00051 
00052 
00053 // Fix incompatibility from NewLib flags and Linux flags
00054 
00055 #define NEWLIB_O_RDONLY          0x0000
00056 #define NEWLIB_O_WRONLY          0x0001
00057 #define NEWLIB_O_RDWR            0x0002
00058 #define NEWLIB_O_APPEND          0x0008
00059 #define NEWLIB_O_CREAT           0x0200
00060 #define NEWLIB_O_TRUNC           0x0400
00061 #define NEWLIB_O_EXCL            0x0800
00062 #define NEWLIB_O_NOCTTY          0x8000
00063 #define NEWLIB_O_NONBLOCK        0x4000
00064 
00065 #define CORRECT_O_RDONLY             00
00066 #define CORRECT_O_WRONLY             01
00067 #define CORRECT_O_RDWR               02
00068 #define CORRECT_O_CREAT            0100
00069 #define CORRECT_O_EXCL             0200
00070 #define CORRECT_O_NOCTTY           0400
00071 #define CORRECT_O_TRUNC           01000
00072 #define CORRECT_O_APPEND          02000
00073 #define CORRECT_O_NONBLOCK        04000
00074 
00075 void correct_flags( int* val )
00076 {
00077   int f = *val;
00078   int flags = 0;
00079 
00080   if( f &  NEWLIB_O_RDONLY )
00081     flags |= CORRECT_O_RDONLY;
00082   if( f &  NEWLIB_O_WRONLY )
00083     flags |= CORRECT_O_WRONLY;
00084   if( f &  NEWLIB_O_RDWR )
00085     flags |= CORRECT_O_RDWR;
00086   if( f & NEWLIB_O_CREAT )
00087     flags |= CORRECT_O_CREAT;
00088   if( f & NEWLIB_O_EXCL )
00089     flags |= CORRECT_O_EXCL;
00090   if( f & NEWLIB_O_NOCTTY )
00091     flags |= CORRECT_O_NOCTTY;
00092   if( f & NEWLIB_O_TRUNC )
00093     flags |= CORRECT_O_TRUNC;
00094   if( f & NEWLIB_O_APPEND )
00095     flags |= CORRECT_O_APPEND;
00096   if( f & NEWLIB_O_NONBLOCK )
00097     flags |= CORRECT_O_NONBLOCK;
00098 
00099   *val = flags;
00100 }
00101 
00102 
00104 
00105 void ac_syscall::open()
00106 {
00107   DEBUG_SYSCALL("open");
00108   unsigned char pathname[100];
00109   get_buffer(0, pathname, 100);
00110   int flags = get_int(1); correct_flags(&flags);
00111   int mode = get_int(2);
00112   int ret = ::open((char*)pathname, flags, mode);
00113   if (ret == -1) {
00114     AC_RUN_ERROR("System Call open (file '%s'): %s\n", pathname, strerror(errno));
00115     exit(EXIT_FAILURE);
00116   }
00117   set_int(0, ret);
00118   return_from_syscall();
00119 }
00120 
00121 
00122 void ac_syscall::creat()
00123 {
00124   DEBUG_SYSCALL("creat");
00125   unsigned char pathname[100];
00126   get_buffer(0, pathname, 100);
00127   int mode = get_int(1);
00128   int ret = ::creat((char*)pathname, mode);
00129   if (ret == -1) {
00130     AC_RUN_ERROR("System Call creat (file '%s'): %s\n", pathname,strerror(errno));
00131     exit(EXIT_FAILURE);
00132   }
00133   set_int(0, ret);
00134   return_from_syscall();
00135 }
00136 
00137 
00138 void ac_syscall::close()
00139 {
00140   DEBUG_SYSCALL("close");
00141   int fd = get_int(0);
00142   int ret = ::close(fd);
00143   if (ret == -1) {
00144     AC_RUN_ERROR("System Call close (fd %d): %s\n", fd, strerror(errno));
00145     exit(EXIT_FAILURE);
00146   }
00147   set_int(0, ret);
00148   return_from_syscall();
00149 }
00150 
00151 
00152 void ac_syscall::read()
00153 {
00154   DEBUG_SYSCALL("read");
00155   int fd = get_int(0);
00156   unsigned count = get_int(2);
00157   unsigned char *buf = (unsigned char*) malloc(count);
00158   int ret = ::read(fd, buf, count);
00159   if (ret == -1) {
00160     AC_RUN_ERROR("System Call read (fd %d): %s\n", fd, strerror(errno));
00161     exit(EXIT_FAILURE);
00162   }
00163   set_buffer(1, buf, ret);
00164   set_int(0, ret);
00165   return_from_syscall();
00166   free(buf);
00167 }
00168 
00169 
00170 void ac_syscall::write()
00171 {
00172   DEBUG_SYSCALL("write");
00173   int fd = get_int(0);
00174   unsigned count = get_int(2);
00175   unsigned char *buf = (unsigned char*) malloc(count);
00176   get_buffer(1, buf, count);
00177   int ret = ::write(fd, buf, count);
00178   if (ret == -1) {
00179     AC_RUN_ERROR("System Call write (fd %d): %s\n", fd, strerror(errno));
00180     exit(EXIT_FAILURE);
00181   }
00182   set_int(0, ret);
00183   return_from_syscall();
00184   free(buf);
00185 }
00186 
00187 
00188 void ac_syscall::isatty()
00189 {
00190   DEBUG_SYSCALL("isatty");
00191   int desc = get_int(0);
00192   int ret = ::isatty(desc);
00193   set_int(0, ret);
00194   return_from_syscall();
00195 }
00196 
00197 
00198 void ac_syscall::sbrk()
00199 {
00200   DEBUG_SYSCALL("sbrk");
00201   int base;
00202   extern unsigned int ac_heap_ptr;
00203 
00204   int increment = get_int(0);
00205   if ((AC_RAMSIZE - ac_heap_ptr - increment) >= 0) {
00206     base = ac_heap_ptr;
00207     ac_heap_ptr += increment;
00208   }
00209   else {
00210     AC_RUN_ERROR("System Call sbrk: Not enough memory left in the virtual machine to allocate %d bytes (ram size=%u, heap=%u)\n", increment, AC_RAMSIZE, ac_heap_ptr);
00211     exit(EXIT_FAILURE);
00212   }
00213 
00214   set_int(0, base);
00215   return_from_syscall();
00216 }
00217 
00218 
00219 void ac_syscall::lseek()
00220 {
00221   DEBUG_SYSCALL("lseek");
00222   int fd = get_int(0);
00223   int offset = get_int(1);
00224   int whence = get_int(2);
00225   int ret = ::lseek(fd, offset, whence);
00226   set_int(0, ret);
00227   return_from_syscall();
00228 }
00229 
00230 
00231 void ac_syscall::fstat()
00232 {
00233   DEBUG_SYSCALL("fstat");
00234   int fd = get_int(0);
00235   struct stat buf;
00236   int ret = ::fstat(fd, &buf);
00237   if (ret == -1) {
00238     AC_RUN_ERROR("System Call fstat (fd %d): %s\n", fd, strerror(errno));
00239     exit(EXIT_FAILURE);
00240   }
00241   set_int(0, ret);
00242   return_from_syscall();
00243 }
00244 
00245 
00246 void ac_syscall::_exit()
00247 {
00248   DEBUG_SYSCALL("_exit");
00249   int ac_exit_status = get_int(0);
00250 #ifdef USE_GDB
00251   if (gdbstub) gdbstub->exit(ac_exit_status);
00252 #endif /* USE_GDB */
00253   ac_stop(ac_exit_status);
00254 }
00255 
00256 
00257 void ac_syscall::times()
00258 {
00259   DEBUG_SYSCALL("times");
00260   unsigned char zeros[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
00261   set_buffer(0, zeros, 16);
00262   set_int(0, 0);
00263   return_from_syscall();
00264 }
00265 
00266 
00267 void ac_syscall::time()
00268 {
00269   DEBUG_SYSCALL("time");
00270   int t = get_int(0);
00271   int ret = ::time(0);
00272   if (t!=0) set_buffer(0, (unsigned char *) &ret, 4);
00273   set_int(0, ret);
00274   return_from_syscall();
00275 }
00276 
00277 
00278 void ac_syscall::random()
00279 {
00280   DEBUG_SYSCALL("random");
00281   int ret = ::random();
00282   set_int(0, ret);
00283   return_from_syscall();
00284 }
00285 
00286 
00287 #include <ac_syscall_codes.h>
00288 
00289 void ac_syscall::ac_syscall_wrapper()
00290 {
00291   int ret = -1;
00292   unsigned char pathname[100];
00293   int mode;
00294 
00295   int syscall_code = get_int(0);
00296 
00297   switch(syscall_code) {
00298 
00299   case __NR_getpid:
00300     DEBUG_SYSCALL("getpid");
00301     ret = 123;
00302     break;
00303 
00304   case __NR_chmod:
00305     DEBUG_SYSCALL("chmod");
00306     get_buffer(0, pathname, 100);
00307     mode = get_int(1);
00308     ret = ::chmod((char*)pathname, mode);
00309     break;
00310 
00311   default:
00312     AC_RUN_ERROR("System Call code %d not implemented yet.\n", syscall_code);
00313   }
00314     
00315   set_int(0, ret);
00316   return_from_syscall();
00317 }
00318 
00319 
00320 void ac_syscall::ac_syscall_geterrno()
00321 {
00322   set_int(0, errno);
00323   return_from_syscall();
00324 }
00325 
00326 
00327 void ac_syscall::ac_syscall_stat_mode()
00328 {
00329   AC_RUN_ERROR("System Call ac_syscall_geterrno not implemented yet.\n",0);
00330 }
00331 
00332 

Generated on Thu Jun 24 08:30:05 2004 for ArchC by doxygen 1.3.4