1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Doing syscalls.                                  m_syscall.c ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2000-2013 Julian Seward
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      jseward@acm.org
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02111-1307, USA.
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h"
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h"
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h"
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vkiscnums.h"
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syscall.h"
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------------
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Building syscall return values.
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make a SysRes value from a syscall return value.  This is
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Linux-specific.
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   From:
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   linux/i386/sysdep.h?
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Linux uses a negative return value to indicate syscall errors,
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unlike most Unices, which use the condition codes' carry flag.
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Since version 2.1 the return value of a system call might be
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   negative even if the call succeeded.  E.g., the 'lseek' system call
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   might return a large offset.  Therefore we must not anymore test
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for < 0, but test for a real error by making sure the value in %eax
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is a real error number.  Linus said he will make sure the no
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   syscall returns a value in -1 .. -4095 as a valid result so we can
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   safely test with -4095.
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(mk_SysRes_x86_linux) ( Int val ) {
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes res;
65663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   res._valEx   = 0; /* unused except on mips-linux */
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res._isError = val >= -4095 && val <= -1;
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (res._isError) {
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res._val = (UInt)(-val);
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res._val = (UInt)val;
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Similarly .. */
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(mk_SysRes_amd64_linux) ( Long val ) {
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes res;
78663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   res._valEx   = 0; /* unused except on mips-linux */
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res._isError = val >= -4095 && val <= -1;
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (res._isError) {
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res._val = (ULong)(-val);
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res._val = (ULong)val;
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* PPC uses the CR7.SO bit to flag an error (CR0 in IBM-speak) */
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Note this must be in the bottom bit of the second arg */
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) {
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes res;
92663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   res._valEx   = 0; /* unused except on mips-linux */
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res._isError = (cr0so & 1) != 0;
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res._val     = val;
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* As per ppc32 version, cr0.so must be in l.s.b. of 2nd arg */
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ) {
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes res;
101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   res._valEx   = 0; /* unused except on mips-linux */
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res._isError = (cr0so & 1) != 0;
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res._val     = val;
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovSysRes VG_(mk_SysRes_s390x_linux) ( Long val ) {
108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SysRes res;
109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   res._valEx   = 0; /* unused except on mips-linux */
110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   res._isError = val >= -4095 && val <= -1;
111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (res._isError) {
112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      res._val = -val;
113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      res._val = val;
115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return res;
117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(mk_SysRes_arm_linux) ( Int val ) {
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes res;
121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   res._valEx   = 0; /* unused except on mips-linux */
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res._isError = val >= -4095 && val <= -1;
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (res._isError) {
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res._val = (UInt)(-val);
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res._val = (UInt)val;
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
131436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovSysRes VG_(mk_SysRes_arm64_linux) ( Long val ) {
132436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   SysRes res;
133436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   res._valEx   = 0; /* unused except on mips-linux */
134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   res._isError = val >= -4095 && val <= -1;
135436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (res._isError) {
136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      res._val = (ULong)(-val);
137436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   } else {
138436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      res._val = (ULong)val;
139436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return res;
141436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
142436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* MIPS uses a3 != 0 to flag an error */
144663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengSysRes VG_(mk_SysRes_mips32_linux) ( UWord v0, UWord v1, UWord a3 ) {
145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   SysRes res;
146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   res._isError = (a3 != (UWord)0);
147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   res._val     = v0;
148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   res._valEx   = v1;
149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return res;
150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
152436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* MIPS uses a3 != 0 to flag an error */
153436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovSysRes VG_(mk_SysRes_mips64_linux) ( ULong v0, ULong v1, ULong a3 ) {
154436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   SysRes res;
155436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   res._isError = (a3 != (ULong)0);
156436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   res._val     = v0;
157436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   res._valEx   = v1;
158436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return res;
159436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
160436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generic constructors. */
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(mk_SysRes_Error) ( UWord err ) {
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes r;
164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   r._valEx   = 0; /* unused except on mips-linux */
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r._isError = True;
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r._val     = err;
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(mk_SysRes_Success) ( UWord res ) {
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes r;
172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   r._valEx   = 0; /* unused except on mips-linux */
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r._isError = False;
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r._val     = res;
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Darwin: Some syscalls return a double-word result. */
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(mk_SysRes_x86_darwin) ( UChar scclass, Bool isErr,
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   UInt wHI, UInt wLO )
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes res;
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res._wHI  = 0;
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res._wLO  = 0;
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res._mode = 0; /* invalid */
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(isErr == False || isErr == True);
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(sizeof(UWord) == sizeof(UInt));
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (scclass) {
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VG_DARWIN_SYSCALL_CLASS_UNIX:
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res._wLO  = wLO;
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res._wHI  = wHI;
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK;
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VG_DARWIN_SYSCALL_CLASS_MACH:
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(!isErr);
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(wHI == 0);
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res._wLO  = wLO;
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res._mode = SysRes_MACH;
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VG_DARWIN_SYSCALL_CLASS_MDEP:
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(!isErr);
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(wHI == 0);
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res._wLO  = wLO;
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res._mode = SysRes_MDEP;
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(0);
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(mk_SysRes_amd64_darwin) ( UChar scclass, Bool isErr,
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     ULong wHI, ULong wLO )
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes res;
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res._wHI  = 0;
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res._wLO  = 0;
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res._mode = 0; /* invalid */
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(isErr == False || isErr == True);
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(sizeof(UWord) == sizeof(ULong));
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (scclass) {
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VG_DARWIN_SYSCALL_CLASS_UNIX:
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res._wLO  = wLO;
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res._wHI  = wHI;
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK;
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VG_DARWIN_SYSCALL_CLASS_MACH:
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(!isErr);
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(wHI == 0);
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res._wLO  = wLO;
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res._mode = SysRes_MACH;
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VG_DARWIN_SYSCALL_CLASS_MDEP:
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(!isErr);
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(wHI == 0);
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res._wLO  = wLO;
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res._mode = SysRes_MDEP;
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(0);
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generic constructors.  We assume (without checking if this makes
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   any sense, from the caller's point of view) that these are for the
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UNIX style of syscall. */
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(mk_SysRes_Error) ( UWord err ) {
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes r;
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r._wHI  = 0;
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r._wLO  = err;
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r._mode = SysRes_UNIX_ERR;
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(mk_SysRes_Success) ( UWord res ) {
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes r;
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r._wHI  = 0;
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r._wLO  = res;
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r._mode = SysRes_UNIX_OK;
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unknown OS"
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------------
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(do_syscall): A function for doing syscalls.
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_x86_linux)
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Incoming args (syscall number + up to 6 args) come on the stack.
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (ie. the C calling convention).
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The syscall number goes in %eax.  The args are passed to the syscall in
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the regs %ebx, %ecx, %edx, %esi, %edi, %ebp, ie. the kernel's syscall
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   calling convention.
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   %eax gets the return value.  Not sure which registers the kernel
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clobbers, so we preserve all the callee-save regs (%esi, %edi, %ebx,
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   %ebp).
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern UWord do_syscall_WRK (
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          UWord syscall_no,
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          UWord a1, UWord a2, UWord a3,
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          UWord a4, UWord a5, UWord a6
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       );
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm(
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".text\n"
296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng".globl do_syscall_WRK\n"
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"do_syscall_WRK:\n"
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	push	%esi\n"
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	push	%edi\n"
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	push	%ebx\n"
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	push	%ebp\n"
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	movl	16+ 4(%esp),%eax\n"
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	movl	16+ 8(%esp),%ebx\n"
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	movl	16+12(%esp),%ecx\n"
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	movl	16+16(%esp),%edx\n"
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	movl	16+20(%esp),%esi\n"
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	movl	16+24(%esp),%edi\n"
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	movl	16+28(%esp),%ebp\n"
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	int	$0x80\n"
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	popl	%ebp\n"
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	popl	%ebx\n"
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	popl	%edi\n"
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	popl	%esi\n"
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	ret\n"
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".previous\n"
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown);
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_linux)
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Incoming args (syscall number + up to 6 args) come in %rdi, %rsi,
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   %rdx, %rcx, %r8, %r9, and the last one on the stack (ie. the C
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   calling convention).
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The syscall number goes in %rax.  The args are passed to the syscall in
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the regs %rdi, %rsi, %rdx, %r10, %r8, %r9 (yes, really %r10, not %rcx),
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ie. the kernel's syscall calling convention.
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   %rax gets the return value.  %rcx and %r11 are clobbered by the syscall;
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   no matter, they are caller-save (the syscall clobbers no callee-save
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   regs, so we don't have to do any register saving/restoring).
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern UWord do_syscall_WRK (
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          UWord syscall_no,
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          UWord a1, UWord a2, UWord a3,
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          UWord a4, UWord a5, UWord a6
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       );
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm(
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".text\n"
338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng".globl do_syscall_WRK\n"
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"do_syscall_WRK:\n"
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* Convert function calling convention --> syscall calling
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           convention */
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	movq	%rdi, %rax\n"
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	movq	%rsi, %rdi\n"
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	movq	%rdx, %rsi\n"
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	movq	%rcx, %rdx\n"
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	movq	%r8,  %r10\n"
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	movq	%r9,  %r8\n"
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	movq    8(%rsp), %r9\n"	 /* last arg from stack */
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	syscall\n"
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"	ret\n"
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".previous\n"
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown);
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc32_linux)
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Incoming args (syscall number + up to 6 args) come in %r3:%r9.
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The syscall number goes in %r0.  The args are passed to the syscall in
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the regs %r3:%r8, i.e. the kernel's syscall calling convention.
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The %cr0.so bit flags an error.
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   We return the syscall return value in %r3, and the %cr0.so in
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the lowest bit of %r4.
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   We return a ULong, of which %r3 is the high word, and %r4 the low.
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   No callee-save regs are clobbered, so no saving/restoring is needed.
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern ULong do_syscall_WRK (
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          UWord syscall_no,
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          UWord a1, UWord a2, UWord a3,
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          UWord a4, UWord a5, UWord a6
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       );
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm(
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".text\n"
373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng".globl do_syscall_WRK\n"
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"do_syscall_WRK:\n"
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        mr      0,3\n"
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        mr      3,4\n"
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        mr      4,5\n"
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        mr      5,6\n"
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        mr      6,7\n"
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        mr      7,8\n"
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        mr      8,9\n"
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        sc\n"                  /* syscall: sets %cr0.so on error         */
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        mfcr    4\n"           /* %cr -> low word of return var          */
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        rlwinm  4,4,4,31,31\n" /* rotate flag bit so to lsb, and mask it */
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        blr\n"                 /* and return                             */
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".previous\n"
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown);
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc64_linux)
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Due to the need to return 65 bits of result, this is completely
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   different from the ppc32 case.  The single arg register points to a
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   7-word block containing the syscall # and the 6 args.  The syscall
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   result proper is put in [0] of the block, and %cr0.so is in the
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bottom bit of [1]. */
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern void do_syscall_WRK ( ULong* argblock );
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm(
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".align   2\n"
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".globl   do_syscall_WRK\n"
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".section \".opd\",\"aw\"\n"
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".align   3\n"
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"do_syscall_WRK:\n"
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".quad    .do_syscall_WRK,.TOC.@tocbase,0\n"
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".previous\n"
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".type    .do_syscall_WRK,@function\n"
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".globl   .do_syscall_WRK\n"
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".do_syscall_WRK:\n"
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        std  3,-16(1)\n"  /* stash arg */
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        ld   8, 48(3)\n"  /* sc arg 6 */
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        ld   7, 40(3)\n"  /* sc arg 5 */
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        ld   6, 32(3)\n"  /* sc arg 4 */
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        ld   5, 24(3)\n"  /* sc arg 3 */
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        ld   4, 16(3)\n"  /* sc arg 2 */
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        ld   0,  0(3)\n"  /* sc number */
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        ld   3,  8(3)\n"  /* sc arg 1 */
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        sc\n"             /* result in r3 and cr0.so */
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        ld   5,-16(1)\n"  /* reacquire argblock ptr (r5 is caller-save) */
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        std  3,0(5)\n"    /* argblock[0] = r3 */
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        mfcr 3\n"
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        srwi 3,3,28\n"
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        andi. 3,3,1\n"
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        std  3,8(5)\n"    /* argblock[1] = cr0.s0 & 1 */
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        blr\n"
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown);
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_arm_linux)
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* I think the conventions are:
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   args  in r0 r1 r2 r3 r4 r5
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sysno in r7
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return value in r0, w/ same conventions as x86-linux, viz r0 in
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   -4096 .. -1 is an error value.  All other values are success
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   values.
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern UWord do_syscall_WRK (
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          UWord a1, UWord a2, UWord a3,
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          UWord a4, UWord a5, UWord a6,
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          UWord syscall_no
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       );
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm(
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".text\n"
440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng".globl do_syscall_WRK\n"
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"do_syscall_WRK:\n"
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"         push    {r4, r5, r7}\n"
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"         ldr     r4, [sp, #12]\n"
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"         ldr     r5, [sp, #16]\n"
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"         ldr     r7, [sp, #20]\n"
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"         svc     0x0\n"
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"         pop     {r4, r5, r7}\n"
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"         bx      lr\n"
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".previous\n"
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown);
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
452436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGP_arm64_linux)
453436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* I think the conventions are:
454436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   args  in r0 r1 r2 r3 r4 r5
455436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   sysno in r8
456436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return value in r0, w/ same conventions as x86-linux, viz r0 in
457436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   -4096 .. -1 is an error value.  All other values are success
458436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   values.
459436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
460436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   r0 to r5 remain unchanged, but syscall_no is in r6 and needs
461436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   to be moved to r8 (??)
462436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov*/
463436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovextern UWord do_syscall_WRK (
464436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          UWord a1, UWord a2, UWord a3,
465436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          UWord a4, UWord a5, UWord a6,
466436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          UWord syscall_no
467436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       );
468436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovasm(
469436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov".text\n"
470436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov".globl do_syscall_WRK\n"
471436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"do_syscall_WRK:\n"
472436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"        mov x8, x6\n"
473436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"        mov x6, 0\n"
474436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"        mov x7, 0\n"
475436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"        svc 0\n"
476436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"        ret\n"
477436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov".previous\n"
478436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov);
479436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_x86_darwin)
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Incoming args (syscall number + up to 8 args) come in on the stack
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The kernel's syscall calling convention is:
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * the syscall number goes in eax
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * the args are passed to the syscall on the stack,
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     pushed onto the stack R->L (that is, the usual x86
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     calling conventions, with the leftmost arg at the lowest
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     address)
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Call instruction:
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * UNIX: sysenter
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * UNIX: int $0x80
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * MACH: int $0x81
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * MDEP: int $0x82
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Note that the call type can be determined from the syscall number;
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   there is no need to inspect the actual instruction.  Although obviously
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the instruction must match.
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Return value:
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * MACH,MDEP: the return value comes back in eax
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * UNIX: the return value comes back in edx:eax (hi32:lo32)
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Error:
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * MACH,MDEP: no error is returned
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * UNIX: the carry flag indicates success or failure
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   nb here, sizeof(UWord) == sizeof(UInt)
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__private_extern__ ULong
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browndo_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      UWord a7, UWord a8, /* 28(esp)..32(esp) */
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      UWord syscall_no, /* 36(esp) */
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      /*OUT*/UInt* errflag /* 40(esp) */ );
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Unix syscall: 64-bit return in edx:eax, with LSB in eax
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// error indicated by carry flag: clear=good, set=bad
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm(".private_extern _do_syscall_unix_WRK\n"
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "_do_syscall_unix_WRK:\n"
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        movl    40(%esp), %ecx   \n"  /* assume syscall success */
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        movl    $0, (%ecx)       \n"
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        movl    36(%esp), %eax   \n"
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        int     $0x80            \n"
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        jnc     1f               \n"  /* jump if success */
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        movl    40(%esp), %ecx   \n"  /* syscall failed - set *errflag */
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        movl    $1, (%ecx)       \n"
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "    1:  ret                      \n"
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    );
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__private_extern__ UInt
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browndo_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      UWord a7, UWord a8, /* 28(esp)..32(esp) */
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      UWord syscall_no /* 36(esp) */ );
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Mach trap: 32-bit result in %eax, no error flag
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm(".private_extern _do_syscall_mach_WRK\n"
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "_do_syscall_mach_WRK:\n"
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        movl    36(%esp), %eax   \n"
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        int     $0x81            \n"
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        ret                      \n"
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    );
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__private_extern__ UInt
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browndo_syscall_mdep_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      UWord a7, UWord a8, /* 28(esp)..32(esp) */
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      UWord syscall_no /* 36(esp) */ );
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// mdep trap: 32-bit result in %eax, no error flag
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm(
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ".private_extern _do_syscall_mdep_WRK\n"
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "_do_syscall_mdep_WRK:\n"
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        movl    36(%esp), %eax   \n"
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        int     $0x82            \n"
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        ret                      \n"
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    );
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_darwin)
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Incoming args (syscall number + up to 8 args) come in registers and stack
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The kernel's syscall calling convention is:
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * the syscall number goes in rax
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * the args are passed to the syscall in registers and the stack
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * the call instruction is 'syscall'
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Return value:
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * MACH,MDEP: the return value comes back in rax
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * UNIX: the return value comes back in rdx:rax (hi64:lo64)
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Error:
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * MACH,MDEP: no error is returned
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * UNIX: the carry flag indicates success or failure
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   nb here, sizeof(UWord) == sizeof(ULong)
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__private_extern__ UWord
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browndo_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      UWord a4, UWord a5, UWord a6, /* rcx, r8,  r9 */
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      UWord a7, UWord a8,           /* 8(rsp), 16(rsp) */
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      UWord syscall_no,             /* 24(rsp) */
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      /*OUT*/ULong* errflag,        /* 32(rsp) */
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      /*OUT*/ULong* res2 );         /* 40(rsp) */
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Unix syscall: 128-bit return in rax:rdx, with LSB in rax
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// error indicated by carry flag: clear=good, set=bad
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm(".private_extern _do_syscall_unix_WRK\n"
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "_do_syscall_unix_WRK:\n"
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        movq    %rcx, %r10       \n"  /* pass rcx in r10 instead */
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        movq    32(%rsp), %rax   \n"  /* assume syscall success */
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        movq    $0, (%rax)       \n"
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        movq    24(%rsp), %rax   \n"  /* load syscall_no */
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        syscall                  \n"
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        jnc     1f               \n"  /* jump if success */
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        movq    32(%rsp), %rcx   \n"  /* syscall failed - set *errflag */
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        movq    $1, (%rcx)       \n"
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "    1:  movq    40(%rsp), %rcx   \n"  /* save 2nd result word */
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        movq    %rdx, (%rcx)     \n"
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        retq                     \n"  /* return 1st result word */
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    );
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__private_extern__ UWord
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browndo_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      UWord a4, UWord a5, UWord a6, /* rcx, r8,  r9 */
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      UWord a7, UWord a8,           /* 8(rsp), 16(rsp) */
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      UWord syscall_no );           /* 24(rsp) */
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Mach trap: 64-bit result, no error flag
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm(".private_extern _do_syscall_mach_WRK\n"
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "_do_syscall_mach_WRK:\n"
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        movq    %rcx, %r10       \n"  /* pass rcx in r10 instead */
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        movq    24(%rsp), %rax   \n"  /* load syscall_no */
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        syscall                  \n"
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "        retq                     \n"
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    );
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGP_s390x_linux)
613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UWord do_syscall_WRK (
615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UWord syscall_no,
616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UWord arg1, UWord arg2, UWord arg3,
617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UWord arg4, UWord arg5, UWord arg6
618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   )
619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   register UWord __arg1 asm("2") = arg1;
621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   register UWord __arg2 asm("3") = arg2;
622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   register UWord __arg3 asm("4") = arg3;
623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   register UWord __arg4 asm("5") = arg4;
624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   register UWord __arg5 asm("6") = arg5;
625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   register UWord __arg6 asm("7") = arg6;
626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   register ULong __svcres asm("2");
627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   __asm__ __volatile__ (
629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 "lgr %%r1,%1\n\t"
630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 "svc 0\n\t"
631b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		: "=d" (__svcres)
632b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		: "a" (syscall_no),
633b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		  "0" (__arg1),
634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		  "d" (__arg2),
635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		  "d" (__arg3),
636b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		  "d" (__arg4),
637b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		  "d" (__arg5),
638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		  "d" (__arg6)
639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		: "1", "cc", "memory");
640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return (UWord) (__svcres);
642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGP_mips32_linux)
645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Incoming args (syscall number + up to 6 args) come in a0 - a3 and stack.
646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   The syscall number goes in v0.  The args are passed to the syscall in
648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   the regs a0 - a3 and stack, i.e. the kernel's syscall calling convention.
649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (a3 != 0) flags an error.
651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   We return the syscall return value in v0.
652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   MIPS version
653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengextern int do_syscall_WRK (
655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          int a1, int a2, int a3,
656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          int a4, int a5, int a6, int syscall_no, UWord *err,
657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          UWord *valHi, UWord* valLo
658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       );
659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengasm(
660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng".globl do_syscall_WRK\n"
661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng".ent do_syscall_WRK\n"
662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng".text\n"
663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng"do_syscall_WRK:\n"
664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng"   lw $2, 24($29)\n"
665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng"   syscall\n"
666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng"   lw $8, 28($29)\n"
667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng"   sw $7, ($8)\n"
668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng"   lw $8, 32($29)\n"
669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng"   sw $3, ($8)\n"   // store valHi
670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng"   lw $8, 36($29)\n"
671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng"   sw $2, ($8)\n"   // store valLo
672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng"   jr $31\n"
673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng"   nop\n"
674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng".previous\n"
675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng".end do_syscall_WRK\n"
676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng);
677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
678436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGP_mips64_linux)
679436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovextern UWord do_syscall_WRK ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5,
680436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              UWord a6, UWord syscall_no, ULong* V1_val );
681436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovasm (
682436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov".text\n"
683436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov".globl do_syscall_WRK\n"
684436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"do_syscall_WRK:\n"
685436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"   daddiu $29, $29, -8\n"
686436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"   sd $11, 0($29)\n"
687436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"   move $2, $10\n"
688436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"   syscall\n"
689436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"   ld $11, 0($29)\n"
690436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"   daddiu $29, $29, 8\n"
691436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"   sd $3, 0($11)\n"  /* store vale of v1 in last param */
692436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"   sd $7, 8($11)\n"  /* store vale of a3 in last param */
693436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov"   jr $31\n"
694436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov".previous\n"
695436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov);
696436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error Unknown platform
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Finally, the generic code.  This sends the call to the right
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   helper. */
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3,
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      UWord a4, UWord a5, UWord a6,
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      UWord a7, UWord a8 )
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(VGP_x86_linux)
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(mk_SysRes_x86_linux)( val );
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  elif defined(VGP_amd64_linux)
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(mk_SysRes_amd64_linux)( val );
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  elif defined(VGP_ppc32_linux)
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong ret     = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  val     = (UInt)(ret>>32);
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  cr0so   = (UInt)(ret);
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(mk_SysRes_ppc32_linux)( val, cr0so );
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  elif defined(VGP_ppc64_linux)
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong argblock[7];
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argblock[0] = sysno;
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argblock[1] = a1;
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argblock[2] = a2;
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argblock[3] = a3;
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argblock[4] = a4;
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argblock[5] = a5;
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argblock[6] = a6;
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_syscall_WRK( &argblock[0] );
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(mk_SysRes_ppc64_linux)( argblock[0], argblock[1] );
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  elif defined(VGP_arm_linux)
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno);
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(mk_SysRes_arm_linux)( val );
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
739436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  elif defined(VGP_arm64_linux)
740436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno);
741436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return VG_(mk_SysRes_arm64_linux)( val );
742436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  elif defined(VGP_x86_darwin)
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  wLO = 0, wHI = 0, err = 0;
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong u64;
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno);
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (scclass) {
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VG_DARWIN_SYSCALL_CLASS_UNIX:
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         u64 = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err);
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         wLO = (UInt)u64;
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         wHI = (UInt)(u64 >> 32);
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VG_DARWIN_SYSCALL_CLASS_MACH:
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         err = 0;
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VG_DARWIN_SYSCALL_CLASS_MDEP:
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         wLO = do_syscall_mdep_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         err = 0;
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(0);
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(mk_SysRes_x86_darwin)( scclass, err ? True : False, wHI, wLO );
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  elif defined(VGP_amd64_darwin)
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong wLO = 0, wHI = 0, err = 0;
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno);
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (scclass) {
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VG_DARWIN_SYSCALL_CLASS_UNIX:
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         wLO = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err, &wHI);
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VG_DARWIN_SYSCALL_CLASS_MACH:
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VG_DARWIN_SYSCALL_CLASS_MDEP:
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8,
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   VG_DARWIN_SYSNO_FOR_KERNEL(sysno));
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         err = 0;
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(0);
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(mk_SysRes_amd64_darwin)( scclass, err ? True : False, wHI, wLO );
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
790b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGP_s390x_linux)
791b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UWord val;
792b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
793b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (sysno == __NR_mmap) {
794b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     ULong argbuf[6];
795b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
796b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     argbuf[0] = a1;
797b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     argbuf[1] = a2;
798b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     argbuf[2] = a3;
799b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     argbuf[3] = a4;
800b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     argbuf[4] = a5;
801b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     argbuf[5] = a6;
802b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     val = do_syscall_WRK(sysno,(UWord)&argbuf[0],0,0,0,0,0);
803b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
804b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
805b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
806b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
807b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return VG_(mk_SysRes_s390x_linux)( val );
808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#elif defined(VGP_mips32_linux)
810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UWord err   = 0;
811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UWord valHi = 0;
812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UWord valLo = 0;
813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (void) do_syscall_WRK(a1,a2,a3,a4,a5,a6, sysno,&err,&valHi,&valLo);
814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return VG_(mk_SysRes_mips32_linux)( valLo, valHi, (ULong)err );
815436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
816436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGP_mips64_linux)
817436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ULong v1_a3[2];
818436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   v1_a3[0] = 0xFF00;
819436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   v1_a3[1] = 0xFF00;
820436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ULong V0 = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno,v1_a3);
821436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ULong V1 = (ULong)v1_a3[0];
822436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ULong A3 = (ULong)v1_a3[1];
823436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return VG_(mk_SysRes_mips64_linux)( V0, V1, A3 );
824436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error Unknown platform
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------------
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Names of errors.
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return a string which gives the name of an error value.  Note,
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unlike the standard C syserror fn, the returned string is not
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   malloc-allocated or writable -- treat it as a constant.
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TODO: implement this properly. */
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst HChar* VG_(strerror) ( UWord errnum )
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (errnum) {
842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EPERM:       return "Operation not permitted";
843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_ENOENT:      return "No such file or directory";
844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_ESRCH:       return "No such process";
845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EINTR:       return "Interrupted system call";
846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EIO:         return "Input/output error";
847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_ENXIO:       return "No such device or address";
848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_E2BIG:       return "Argument list too long";
849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_ENOEXEC:     return "Exec format error";
850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EBADF:       return "Bad file descriptor";
851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_ECHILD:      return "No child processes";
852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EAGAIN:      return "Resource temporarily unavailable";
853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_ENOMEM:      return "Cannot allocate memory";
854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EACCES:      return "Permission denied";
855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EFAULT:      return "Bad address";
856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_ENOTBLK:     return "Block device required";
857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EBUSY:       return "Device or resource busy";
858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EEXIST:      return "File exists";
859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EXDEV:       return "Invalid cross-device link";
860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_ENODEV:      return "No such device";
861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_ENOTDIR:     return "Not a directory";
862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EISDIR:      return "Is a directory";
863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EINVAL:      return "Invalid argument";
864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_ENFILE:      return "Too many open files in system";
865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EMFILE:      return "Too many open files";
866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_ENOTTY:      return "Inappropriate ioctl for device";
867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_ETXTBSY:     return "Text file busy";
868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EFBIG:       return "File too large";
869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_ENOSPC:      return "No space left on device";
870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_ESPIPE:      return "Illegal seek";
871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EROFS:       return "Read-only file system";
872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EMLINK:      return "Too many links";
873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EPIPE:       return "Broken pipe";
874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EDOM:        return "Numerical argument out of domain";
875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_ERANGE:      return "Numerical result out of range";
876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_ENOSYS:      return "Function not implemented";
878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case VKI_EOVERFLOW:   return "Value too large for defined data type";
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     if defined(VKI_ERESTARTSYS)
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VKI_ERESTARTSYS: return "ERESTARTSYS";
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     endif
882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:              return "VG_(strerror): unknown error";
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- end                                                          ---*/
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
890