Home | History | Annotate | Line # | Download | only in hppa
      1  1.2  riastrad /*	$NetBSD: execregs.c,v 1.2 2025/02/28 16:08:19 riastradh Exp $	*/
      2  1.1  riastrad 
      3  1.1  riastrad /*-
      4  1.1  riastrad  * Copyright (c) 2025 The NetBSD Foundation, Inc.
      5  1.1  riastrad  * All rights reserved.
      6  1.1  riastrad  *
      7  1.1  riastrad  * Redistribution and use in source and binary forms, with or without
      8  1.1  riastrad  * modification, are permitted provided that the following conditions
      9  1.1  riastrad  * are met:
     10  1.1  riastrad  * 1. Redistributions of source code must retain the above copyright
     11  1.1  riastrad  *    notice, this list of conditions and the following disclaimer.
     12  1.1  riastrad  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  riastrad  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  riastrad  *    documentation and/or other materials provided with the distribution.
     15  1.1  riastrad  *
     16  1.1  riastrad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  1.1  riastrad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  1.1  riastrad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  1.1  riastrad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  1.1  riastrad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  1.1  riastrad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  1.1  riastrad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  1.1  riastrad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  1.1  riastrad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  1.1  riastrad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  1.1  riastrad  * POSSIBILITY OF SUCH DAMAGE.
     27  1.1  riastrad  */
     28  1.1  riastrad 
     29  1.1  riastrad #include <sys/cdefs.h>
     30  1.2  riastrad __RCSID("$NetBSD: execregs.c,v 1.2 2025/02/28 16:08:19 riastradh Exp $");
     31  1.1  riastrad 
     32  1.1  riastrad #include "execregs.h"
     33  1.1  riastrad 
     34  1.1  riastrad #include <errno.h>
     35  1.1  riastrad #include <spawn.h>
     36  1.1  riastrad #include <stddef.h>
     37  1.2  riastrad #include <stdint.h>
     38  1.1  riastrad #include <unistd.h>
     39  1.1  riastrad 
     40  1.1  riastrad extern char **environ;
     41  1.1  riastrad 
     42  1.1  riastrad static unsigned long
     43  1.1  riastrad nonnull(unsigned long x)
     44  1.1  riastrad {
     45  1.1  riastrad 
     46  1.1  riastrad 	x |= x << 8;
     47  1.1  riastrad 	x |= x << 16;
     48  1.1  riastrad 	return x;
     49  1.1  riastrad }
     50  1.1  riastrad 
     51  1.2  riastrad /*
     52  1.2  riastrad  * setfpregs()
     53  1.2  riastrad  *
     54  1.2  riastrad  *	Set up all the floating-point registers with something nonzero
     55  1.2  riastrad  *	in each one.  We initialize the floating-point status register
     56  1.2  riastrad  *	to set various bits so it's not all zero, but nothing that
     57  1.2  riastrad  *	would trigger traps.
     58  1.2  riastrad  */
     59  1.2  riastrad static void
     60  1.2  riastrad setfpregs(void)
     61  1.2  riastrad {
     62  1.2  riastrad 	static const uint64_t fpe[] = {
     63  1.2  riastrad 		(__BITS(63,59)		/* all exception flags (VZOUI) set */
     64  1.2  riastrad 		    | __BIT(58)		/* C bit (comparison) set */
     65  1.2  riastrad 		    | __BITS(54,43)	/* CQ (comparison queue) all set */
     66  1.2  riastrad 		    | __SHIFTIN(1, __BITS(42,41))	/* round toward zero */
     67  1.2  riastrad 		    | __SHIFTIN(0, __BIT(38))	/* no delayed trap */
     68  1.2  riastrad 		    | __SHIFTIN(1, __BIT(37))	/* Denormalized As Zero */
     69  1.2  riastrad 		    | __SHIFTIN(0, __BITS(36,32))	/* exceptions masked */
     70  1.2  riastrad 		    | 0x10101010),
     71  1.2  riastrad 		0x9191919111111111,
     72  1.2  riastrad 		0x9292929212121212,
     73  1.2  riastrad 		0x9393939313131313,
     74  1.2  riastrad 	};
     75  1.2  riastrad 	const uint64_t *fpep = fpe;
     76  1.2  riastrad 
     77  1.2  riastrad 	static const double fr[28] = {
     78  1.2  riastrad 		0x1.04p0, 0x1.05p0, 0x1.06p0, 0x1.07p0,
     79  1.2  riastrad 		0x1.08p0, 0x1.09p0, 0x1.0ap0, 0x1.0bp0,
     80  1.2  riastrad 		0x1.0cp0, 0x1.0dp0, 0x1.0ep0, 0x1.0fp0,
     81  1.2  riastrad 		0x1.10p0, 0x1.11p0, 0x1.12p0, 0x1.13p0,
     82  1.2  riastrad 		0x1.14p0, 0x1.15p0, 0x1.16p0, 0x1.17p0,
     83  1.2  riastrad 		0x1.18p0, 0x1.19p0, 0x1.1ap0, 0x1.1bp0,
     84  1.2  riastrad 		0x1.1cp0, 0x1.1dp0, 0x1.1ep0, 0x1.1fp0,
     85  1.2  riastrad 	};
     86  1.2  riastrad 	const double *frp = fr;
     87  1.2  riastrad 
     88  1.2  riastrad 	__asm volatile(
     89  1.2  riastrad 		"fldds,ma	8(%0), %%fr0\n\t"
     90  1.2  riastrad 		"fldds,ma	8(%0), %%fr1\n\t"
     91  1.2  riastrad 		"fldds,ma	8(%0), %%fr2\n\t"
     92  1.2  riastrad 		"fldds		0(%0), %%fr3"
     93  1.2  riastrad 	    : "+r"(fpep)
     94  1.2  riastrad 	    : "m"(fpe));
     95  1.2  riastrad 
     96  1.2  riastrad 	__asm volatile(
     97  1.2  riastrad 		"fldds,ma	8(%0), %%fr4\n\t"
     98  1.2  riastrad 		"fldds,ma	8(%0), %%fr5\n\t"
     99  1.2  riastrad 		"fldds,ma	8(%0), %%fr6\n\t"
    100  1.2  riastrad 		"fldds,ma	8(%0), %%fr7\n\t"
    101  1.2  riastrad 		"fldds,ma	8(%0), %%fr8\n\t"
    102  1.2  riastrad 		"fldds,ma	8(%0), %%fr9\n\t"
    103  1.2  riastrad 		"fldds,ma	8(%0), %%fr10\n\t"
    104  1.2  riastrad 		"fldds,ma	8(%0), %%fr11\n\t"
    105  1.2  riastrad 		"fldds,ma	8(%0), %%fr12\n\t"
    106  1.2  riastrad 		"fldds,ma	8(%0), %%fr13\n\t"
    107  1.2  riastrad 		"fldds,ma	8(%0), %%fr14\n\t"
    108  1.2  riastrad 		"fldds,ma	8(%0), %%fr15\n\t"
    109  1.2  riastrad 		"fldds,ma	8(%0), %%fr16\n\t"
    110  1.2  riastrad 		"fldds,ma	8(%0), %%fr17\n\t"
    111  1.2  riastrad 		"fldds,ma	8(%0), %%fr18\n\t"
    112  1.2  riastrad 		"fldds,ma	8(%0), %%fr19\n\t"
    113  1.2  riastrad 		"fldds,ma	8(%0), %%fr20\n\t"
    114  1.2  riastrad 		"fldds,ma	8(%0), %%fr21\n\t"
    115  1.2  riastrad 		"fldds,ma	8(%0), %%fr22\n\t"
    116  1.2  riastrad 		"fldds,ma	8(%0), %%fr23\n\t"
    117  1.2  riastrad 		"fldds,ma	8(%0), %%fr24\n\t"
    118  1.2  riastrad 		"fldds,ma	8(%0), %%fr25\n\t"
    119  1.2  riastrad 		"fldds,ma	8(%0), %%fr26\n\t"
    120  1.2  riastrad 		"fldds,ma	8(%0), %%fr27\n\t"
    121  1.2  riastrad 		"fldds,ma	8(%0), %%fr28\n\t"
    122  1.2  riastrad 		"fldds,ma	8(%0), %%fr29\n\t"
    123  1.2  riastrad 		"fldds,ma	8(%0), %%fr30\n\t"
    124  1.2  riastrad 		"fldds		0(%0), %%fr31"
    125  1.2  riastrad 	    : "+r"(frp)
    126  1.2  riastrad 	    : "m"(fr));
    127  1.2  riastrad }
    128  1.2  riastrad 
    129  1.2  riastrad /*
    130  1.2  riastrad  * setpsw()
    131  1.2  riastrad  *
    132  1.2  riastrad  *	Set some bits in PSW, the processor status word.
    133  1.2  riastrad  */
    134  1.2  riastrad static void
    135  1.2  riastrad setpsw(void)
    136  1.2  riastrad {
    137  1.2  riastrad 	uint32_t x = 0xe0000000, y = 0xffffffff, sum;
    138  1.2  riastrad 
    139  1.2  riastrad 	/*
    140  1.2  riastrad 	 * Trigger some arithmetic that causes the carry/borrow
    141  1.2  riastrad 	 * (PSW[C/B]) bits to be set.
    142  1.2  riastrad 	 *
    143  1.2  riastrad 	 * XXX Also set PSW[V].
    144  1.2  riastrad 	 */
    145  1.2  riastrad 	__asm volatile("sh3add %[sum], %[x], %[y]"
    146  1.2  riastrad 	    : /* outputs */ [sum] "=r"(sum)
    147  1.2  riastrad 	    : /* inputs */ [x] "r"(x), [y] "r"(y));
    148  1.2  riastrad }
    149  1.2  riastrad 
    150  1.1  riastrad int
    151  1.1  riastrad execregschild(char *path)
    152  1.1  riastrad {
    153  1.1  riastrad 	register long t1 __asm("r22") = nonnull(22);
    154  1.1  riastrad 	register long t2 __asm("r21") = nonnull(21);
    155  1.1  riastrad 	/* r30/sp: stack pointer */
    156  1.1  riastrad 	register long t3 __asm("r20") = nonnull(20);
    157  1.1  riastrad 	/* cr17/iisq_head: privileged */
    158  1.1  riastrad 	/* cr17/iisq_tail: privileged */
    159  1.1  riastrad 	/* cr18/iioq_head: privileged */
    160  1.1  riastrad 	/* cr18/iioq_tail: privileged */
    161  1.1  riastrad 	/* cr15/eiem: privileged */
    162  1.1  riastrad 	/* cr22/ipsw: privileged */
    163  1.1  riastrad 	/* sr3: privileged(?) */
    164  1.1  riastrad 	/* cr8/pidr1: privileged */
    165  1.1  riastrad 	/* cr20/isr: privileged */
    166  1.1  riastrad 	/* cr21/ior: privileged */
    167  1.1  riastrad 	/* cr19/iir: privileged */
    168  1.1  riastrad 	/* flags: N/A(?) */
    169  1.1  riastrad 	long sar = nonnull(0x8a);	/* cr11 */
    170  1.1  riastrad 	/* r1: ADDIL (add immediate left) result, nonnull anyway */
    171  1.1  riastrad 	/* r2/rp: return pointer, nonnull anyway */
    172  1.1  riastrad 	/* r3: frame pointer, nonnull anyway */
    173  1.1  riastrad 	register long r4 __asm("r4") = nonnull(4);
    174  1.1  riastrad 	register long r5 __asm("r5") = nonnull(5);
    175  1.1  riastrad 	register long r6 __asm("r6") = nonnull(6);
    176  1.1  riastrad 	register long r7 __asm("r7") = nonnull(7);
    177  1.1  riastrad 	register long r8 __asm("r8") = nonnull(8);
    178  1.1  riastrad 	register long r9 __asm("r9") = nonnull(9);
    179  1.1  riastrad 	register long r10 __asm("r10") = nonnull(10);
    180  1.1  riastrad 	register long r11 __asm("r11") = nonnull(11);
    181  1.1  riastrad 	register long r12 __asm("r12") = nonnull(12);
    182  1.1  riastrad 	register long r13 __asm("r13") = nonnull(13);
    183  1.1  riastrad 	register long r14 __asm("r14") = nonnull(14);
    184  1.1  riastrad 	register long r15 __asm("r15") = nonnull(15);
    185  1.1  riastrad 	register long r16 __asm("r16") = nonnull(16);
    186  1.1  riastrad 	register long r17 __asm("r17") = nonnull(17);
    187  1.1  riastrad 	register long r18 __asm("r18") = nonnull(18);
    188  1.1  riastrad 	register long t4 __asm("r19") = nonnull(19);
    189  1.1  riastrad 	register long arg3 __asm("r23") = nonnull(23);
    190  1.1  riastrad 	/* r24/arg2: envp, nonnull anyway */
    191  1.1  riastrad 	/* r25/arg1: argv, nonnull anyway */
    192  1.1  riastrad 	/* r26/arg0: path, nonnull anyway */
    193  1.1  riastrad 	/* r27/dp: data pointer, nonnull anyway */
    194  1.1  riastrad 	register long ret0 __asm("r28") = nonnull(28);
    195  1.1  riastrad 	register long ret1 __asm("r29") = nonnull(29);
    196  1.1  riastrad 	register long r31 __asm("r31") = nonnull(31);
    197  1.1  riastrad 	/* sr0-sr7: space registers initialized by kernel */
    198  1.1  riastrad 	/* cr9/pidr2: privileged */
    199  1.1  riastrad 	/* cr12/pidr3: privileged */
    200  1.1  riastrad 	/* cr13/pidr4: privileged */
    201  1.1  riastrad 	/* cr0/rctr: privileged */
    202  1.1  riastrad 	/* cr10/ccr: privileged */
    203  1.1  riastrad 	/* cr23/eirr: privileged */
    204  1.1  riastrad 	/* cr24: privileged */
    205  1.1  riastrad 	/* cr25/vtop: privileged */
    206  1.1  riastrad 	/* cr27/tr3: _lwp_private, thread-local storage -- nonnull anyway */
    207  1.1  riastrad 	/* cr28: privileged */
    208  1.1  riastrad 	/* cr30/fpregs: privileged */
    209  1.1  riastrad 	/* cr31: privileged */
    210  1.1  riastrad 
    211  1.1  riastrad 	char *argv[] = {path, NULL};
    212  1.1  riastrad 	char **envp = environ;
    213  1.1  riastrad 
    214  1.2  riastrad 	setfpregs();
    215  1.2  riastrad 	setpsw();
    216  1.2  riastrad 
    217  1.1  riastrad 	/*
    218  1.1  riastrad 	 * Not perfect -- compiler might use some registers for
    219  1.1  riastrad 	 * stack/argument transfers, but all the arguments are nonnull
    220  1.1  riastrad 	 * so this is probably a good test anyway.
    221  1.1  riastrad 	 */
    222  1.1  riastrad 	__asm volatile("mtctl %[sar], %%sar"	/* cr11 */
    223  1.1  riastrad 	    : /* outputs */
    224  1.1  riastrad 	    : [sar] "r"(sar)
    225  1.1  riastrad 	    : "memory");
    226  1.1  riastrad 	__asm volatile("" :
    227  1.1  riastrad 	    "+r"(t1),
    228  1.1  riastrad 	    "+r"(t2),
    229  1.1  riastrad 	    "+r"(t3),
    230  1.1  riastrad 	    "+r"(r4),
    231  1.1  riastrad 	    "+r"(r5),
    232  1.1  riastrad 	    "+r"(r6),
    233  1.1  riastrad 	    "+r"(r7),
    234  1.1  riastrad 	    "+r"(r8),
    235  1.1  riastrad 	    "+r"(r9),
    236  1.1  riastrad 	    "+r"(r10),
    237  1.1  riastrad 	    "+r"(r11),
    238  1.1  riastrad 	    "+r"(r12)
    239  1.1  riastrad 	    :: "memory");
    240  1.1  riastrad 	/* pacify gcc error: more than 30 operands in 'asm' */
    241  1.1  riastrad 	__asm volatile("" :
    242  1.1  riastrad 	    "+r"(r13),
    243  1.1  riastrad 	    "+r"(r14),
    244  1.1  riastrad 	    "+r"(r15),
    245  1.1  riastrad 	    "+r"(r16),
    246  1.1  riastrad 	    "+r"(r17),
    247  1.1  riastrad 	    "+r"(r18),
    248  1.1  riastrad 	    "+r"(t4),
    249  1.1  riastrad 	    "+r"(arg3),
    250  1.1  riastrad 	    "+r"(ret0),
    251  1.1  riastrad 	    "+r"(ret1),
    252  1.1  riastrad 	    "+r"(r31)
    253  1.1  riastrad 	    :: "memory");
    254  1.1  riastrad 
    255  1.1  riastrad 	return execve(path, argv, envp);
    256  1.1  riastrad }
    257  1.1  riastrad 
    258  1.1  riastrad pid_t
    259  1.1  riastrad spawnregschild(char *path, int fd)
    260  1.1  riastrad {
    261  1.1  riastrad 	register long t1 __asm("r22") = nonnull(22);
    262  1.1  riastrad 	register long t2 __asm("r21") = nonnull(21);
    263  1.1  riastrad 	/* r30/sp: stack pointer */
    264  1.1  riastrad 	register long t3 __asm("r20") = nonnull(20);
    265  1.1  riastrad 	/* cr17/iisq_head: privileged */
    266  1.1  riastrad 	/* cr17/iisq_tail: privileged */
    267  1.1  riastrad 	/* cr18/iioq_head: privileged */
    268  1.1  riastrad 	/* cr18/iioq_tail: privileged */
    269  1.1  riastrad 	/* cr15/eiem: privileged */
    270  1.1  riastrad 	/* cr22/ipsw: privileged */
    271  1.1  riastrad 	/* sr3: privileged(?) */
    272  1.1  riastrad 	/* cr8/pidr1: privileged */
    273  1.1  riastrad 	/* cr20/isr: privileged */
    274  1.1  riastrad 	/* cr21/ior: privileged */
    275  1.1  riastrad 	/* cr19/iir: privileged */
    276  1.1  riastrad 	/* flags: N/A(?) */
    277  1.1  riastrad 	long sar = nonnull(0x8a);	/* cr11 */
    278  1.1  riastrad 	/* r1: ADDIL (add immediate left) result, nonnull anyway */
    279  1.1  riastrad 	/* r2/rp: return pointer, nonnull anyway */
    280  1.1  riastrad 	/* r3: frame pointer, nonnull anyway */
    281  1.1  riastrad 	register long r4 __asm("r4") = nonnull(4);
    282  1.1  riastrad 	register long r5 __asm("r5") = nonnull(5);
    283  1.1  riastrad 	register long r6 __asm("r6") = nonnull(6);
    284  1.1  riastrad 	register long r7 __asm("r7") = nonnull(7);
    285  1.1  riastrad 	register long r8 __asm("r8") = nonnull(8);
    286  1.1  riastrad 	register long r9 __asm("r9") = nonnull(9);
    287  1.1  riastrad 	register long r10 __asm("r10") = nonnull(10);
    288  1.1  riastrad 	register long r11 __asm("r11") = nonnull(11);
    289  1.1  riastrad 	register long r12 __asm("r12") = nonnull(12);
    290  1.1  riastrad 	register long r13 __asm("r13") = nonnull(13);
    291  1.1  riastrad 	register long r14 __asm("r14") = nonnull(14);
    292  1.1  riastrad 	register long r15 __asm("r15") = nonnull(15);
    293  1.1  riastrad 	register long r16 __asm("r16") = nonnull(16);
    294  1.1  riastrad 	register long r17 __asm("r17") = nonnull(17);
    295  1.1  riastrad 	register long r18 __asm("r18") = nonnull(18);
    296  1.1  riastrad 	register long t4 __asm("r19") = nonnull(19);
    297  1.1  riastrad 	/* r23/arg3: attrp, nonnull anyway */
    298  1.1  riastrad 	/* r24/arg2: fileactsp, nonnull anyway */
    299  1.1  riastrad 	/* r25/arg1: path, nonnull anyway */
    300  1.1  riastrad 	/* r26/arg0: pidp, nonnull anyway */
    301  1.1  riastrad 	/* r27/dp: data pointer, nonnull anyway */
    302  1.1  riastrad 	register long ret0 __asm("r28") = nonnull(28);
    303  1.1  riastrad 	register long ret1 __asm("r29") = nonnull(29);
    304  1.1  riastrad 	register long r31 __asm("r31") = nonnull(31);
    305  1.1  riastrad 	/* sr0-sr7: space registers initialized by kernel */
    306  1.1  riastrad 	/* cr9/pidr2: privileged */
    307  1.1  riastrad 	/* cr12/pidr3: privileged */
    308  1.1  riastrad 	/* cr13/pidr4: privileged */
    309  1.1  riastrad 	/* cr0/rctr: privileged */
    310  1.1  riastrad 	/* cr10/ccr: privileged */
    311  1.1  riastrad 	/* cr23/eirr: privileged */
    312  1.1  riastrad 	/* cr24: privileged */
    313  1.1  riastrad 	/* cr25/vtop: privileged */
    314  1.1  riastrad 	/* cr27/tr3: _lwp_private, thread-local storage -- nonnull anyway */
    315  1.1  riastrad 	/* cr28: privileged */
    316  1.1  riastrad 	/* cr30/fpregs: privileged */
    317  1.1  riastrad 	/* cr31: privileged */
    318  1.1  riastrad 
    319  1.1  riastrad 	char *argv[] = {path, NULL};
    320  1.1  riastrad 	char **envp = environ;
    321  1.1  riastrad 	posix_spawn_file_actions_t fileacts;
    322  1.1  riastrad 	posix_spawnattr_t attr;
    323  1.1  riastrad 	pid_t pid;
    324  1.1  riastrad 	int error;
    325  1.1  riastrad 
    326  1.1  riastrad 	error = posix_spawn_file_actions_init(&fileacts);
    327  1.1  riastrad 	if (error)
    328  1.1  riastrad 		goto out;
    329  1.1  riastrad 	error = posix_spawn_file_actions_adddup2(&fileacts, fd, STDOUT_FILENO);
    330  1.1  riastrad 	if (error)
    331  1.1  riastrad 		goto out;
    332  1.1  riastrad 	error = posix_spawnattr_init(&attr);
    333  1.1  riastrad 	if (error)
    334  1.1  riastrad 		goto out;
    335  1.1  riastrad 
    336  1.2  riastrad 	setfpregs();
    337  1.2  riastrad 	setpsw();
    338  1.2  riastrad 
    339  1.1  riastrad 	/*
    340  1.1  riastrad 	 * Not perfect -- compiler might use some registers for
    341  1.1  riastrad 	 * stack/argument transfers, but all the arguments are nonnull
    342  1.1  riastrad 	 * so this is probably a good test anyway.
    343  1.1  riastrad 	 */
    344  1.1  riastrad 	__asm volatile("mtctl %[sar], %%sar"	/* cr11 */
    345  1.1  riastrad 	    : /* outputs */
    346  1.1  riastrad 	    : [sar] "r"(sar)
    347  1.1  riastrad 	    : "memory");
    348  1.1  riastrad 	__asm volatile("" :
    349  1.1  riastrad 	    "+r"(t1),
    350  1.1  riastrad 	    "+r"(t2),
    351  1.1  riastrad 	    "+r"(t3),
    352  1.1  riastrad 	    "+r"(r4),
    353  1.1  riastrad 	    "+r"(r5),
    354  1.1  riastrad 	    "+r"(r6),
    355  1.1  riastrad 	    "+r"(r7),
    356  1.1  riastrad 	    "+r"(r8),
    357  1.1  riastrad 	    "+r"(r9),
    358  1.1  riastrad 	    "+r"(r10),
    359  1.1  riastrad 	    "+r"(r11),
    360  1.1  riastrad 	    "+r"(r12)
    361  1.1  riastrad 	    :: "memory");
    362  1.1  riastrad 	/* pacify gcc error: more than 30 operands in 'asm' */
    363  1.1  riastrad 	__asm volatile("" :
    364  1.1  riastrad 	    "+r"(r13),
    365  1.1  riastrad 	    "+r"(r14),
    366  1.1  riastrad 	    "+r"(r15),
    367  1.1  riastrad 	    "+r"(r16),
    368  1.1  riastrad 	    "+r"(r17),
    369  1.1  riastrad 	    "+r"(r18),
    370  1.1  riastrad 	    "+r"(t4),
    371  1.1  riastrad 	    "+r"(ret0),
    372  1.1  riastrad 	    "+r"(ret1),
    373  1.1  riastrad 	    "+r"(r31)
    374  1.1  riastrad 	    :: "memory");
    375  1.1  riastrad 
    376  1.1  riastrad 	error = posix_spawn(&pid, path, &fileacts, &attr, argv, envp);
    377  1.1  riastrad 	if (error)
    378  1.1  riastrad 		goto out;
    379  1.1  riastrad 
    380  1.1  riastrad out:	posix_spawnattr_destroy(&attr);
    381  1.1  riastrad 	posix_spawn_file_actions_destroy(&fileacts);
    382  1.1  riastrad 	if (error) {
    383  1.1  riastrad 		errno = error;
    384  1.1  riastrad 		return -1;
    385  1.1  riastrad 	}
    386  1.1  riastrad 	return 0;
    387  1.1  riastrad }
    388