xref: /illumos-gate/usr/src/uts/sparc/v9/fpu/uword.c (revision aad98a6d)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23*aad98a6dSmathue  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /* Read/write user memory procedures for Sparc9 FPU simulator. */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <sys/param.h>
337c478bd9Sstevel@tonic-gate #include <sys/fpu/fpu_simulator.h>
347c478bd9Sstevel@tonic-gate #include <sys/fpu/globals.h>
357c478bd9Sstevel@tonic-gate #include <sys/systm.h>
367c478bd9Sstevel@tonic-gate #include <vm/seg.h>
377c478bd9Sstevel@tonic-gate #include <sys/privregs.h>
387c478bd9Sstevel@tonic-gate #include <sys/stack.h>
397c478bd9Sstevel@tonic-gate #include <sys/debug.h>
407c478bd9Sstevel@tonic-gate #include <sys/model.h>
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate /* read the user instruction */
437c478bd9Sstevel@tonic-gate enum ftt_type
_fp_read_inst(const uint32_t * address,uint32_t * pvalue,fp_simd_type * pfpsd)447c478bd9Sstevel@tonic-gate _fp_read_inst(
457c478bd9Sstevel@tonic-gate 	const uint32_t *address,	/* FPU instruction address. */
467c478bd9Sstevel@tonic-gate 	uint32_t *pvalue,		/* Place for instruction value. */
477c478bd9Sstevel@tonic-gate 	fp_simd_type *pfpsd)		/* Pointer to fpu simulator data. */
487c478bd9Sstevel@tonic-gate {
497c478bd9Sstevel@tonic-gate 	if (((uintptr_t)address & 0x3) != 0)
507c478bd9Sstevel@tonic-gate 		return (ftt_alignment);	/* Must be word-aligned. */
517c478bd9Sstevel@tonic-gate 
52*aad98a6dSmathue 	if (get_udatamodel() == DATAMODEL_ILP32) {
53*aad98a6dSmathue 		/*
54*aad98a6dSmathue 		 * If this is a 32-bit program, chop the address accordingly.
55*aad98a6dSmathue 		 * The intermediate uintptr_t casts prevent warnings under a
56*aad98a6dSmathue 		 * certain compiler, and the temporary 32 bit storage is
57*aad98a6dSmathue 		 * intended to force proper code generation and break up what
58*aad98a6dSmathue 		 * would otherwise be a quadruple cast.
59*aad98a6dSmathue 		 */
60*aad98a6dSmathue 		caddr32_t address32 = (caddr32_t)(uintptr_t)address;
61*aad98a6dSmathue 		address = (uint32_t *)(uintptr_t)address32;
62*aad98a6dSmathue 	}
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate 	if (fuword32(address, pvalue) == -1) {
657c478bd9Sstevel@tonic-gate 		pfpsd->fp_trapaddr = (caddr_t)address;
667c478bd9Sstevel@tonic-gate 		pfpsd->fp_traprw = S_READ;
677c478bd9Sstevel@tonic-gate 		return (ftt_fault);
687c478bd9Sstevel@tonic-gate 	}
697c478bd9Sstevel@tonic-gate 	return (ftt_none);
707c478bd9Sstevel@tonic-gate }
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate enum ftt_type
_fp_read_extword(const uint64_t * address,uint64_t * pvalue,fp_simd_type * pfpsd)737c478bd9Sstevel@tonic-gate _fp_read_extword(
747c478bd9Sstevel@tonic-gate 	const uint64_t *address,	/* FPU data address. */
757c478bd9Sstevel@tonic-gate 	uint64_t *pvalue,		/* Place for extended word value. */
767c478bd9Sstevel@tonic-gate 	fp_simd_type *pfpsd)		/* Pointer to fpu simulator data. */
777c478bd9Sstevel@tonic-gate {
787c478bd9Sstevel@tonic-gate 	if (((uintptr_t)address & 0x7) != 0)
797c478bd9Sstevel@tonic-gate 		return (ftt_alignment);	/* Must be extword-aligned. */
807c478bd9Sstevel@tonic-gate 
81*aad98a6dSmathue 	if (get_udatamodel() == DATAMODEL_ILP32) {
82*aad98a6dSmathue 		/*
83*aad98a6dSmathue 		 * If this is a 32-bit program, chop the address accordingly.
84*aad98a6dSmathue 		 * The intermediate uintptr_t casts prevent warnings under a
85*aad98a6dSmathue 		 * certain compiler, and the temporary 32 bit storage is
86*aad98a6dSmathue 		 * intended to force proper code generation and break up what
87*aad98a6dSmathue 		 * would otherwise be a quadruple cast.
88*aad98a6dSmathue 		 */
89*aad98a6dSmathue 		caddr32_t address32 = (caddr32_t)(uintptr_t)address;
90*aad98a6dSmathue 		address = (uint64_t *)(uintptr_t)address32;
91*aad98a6dSmathue 	}
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	if (fuword64(address, pvalue) == -1) {
947c478bd9Sstevel@tonic-gate 		pfpsd->fp_trapaddr = (caddr_t)address;
957c478bd9Sstevel@tonic-gate 		pfpsd->fp_traprw = S_READ;
967c478bd9Sstevel@tonic-gate 		return (ftt_fault);
977c478bd9Sstevel@tonic-gate 	}
987c478bd9Sstevel@tonic-gate 	return (ftt_none);
997c478bd9Sstevel@tonic-gate }
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate enum ftt_type
_fp_read_word(const uint32_t * address,uint32_t * pvalue,fp_simd_type * pfpsd)1027c478bd9Sstevel@tonic-gate _fp_read_word(
1037c478bd9Sstevel@tonic-gate 	const uint32_t *address,	/* FPU data address. */
1047c478bd9Sstevel@tonic-gate 	uint32_t *pvalue,		/* Place for word value. */
1057c478bd9Sstevel@tonic-gate 	fp_simd_type *pfpsd)		/* Pointer to fpu simulator data. */
1067c478bd9Sstevel@tonic-gate {
1077c478bd9Sstevel@tonic-gate 	if (((uintptr_t)address & 0x3) != 0)
1087c478bd9Sstevel@tonic-gate 		return (ftt_alignment);	/* Must be word-aligned. */
1097c478bd9Sstevel@tonic-gate 
110*aad98a6dSmathue 	if (get_udatamodel() == DATAMODEL_ILP32) {
111*aad98a6dSmathue 		/*
112*aad98a6dSmathue 		 * If this is a 32-bit program, chop the address accordingly.
113*aad98a6dSmathue 		 * The intermediate uintptr_t casts prevent warnings under a
114*aad98a6dSmathue 		 * certain compiler, and the temporary 32 bit storage is
115*aad98a6dSmathue 		 * intended to force proper code generation and break up what
116*aad98a6dSmathue 		 * would otherwise be a quadruple cast.
117*aad98a6dSmathue 		 */
118*aad98a6dSmathue 		caddr32_t address32 = (caddr32_t)(uintptr_t)address;
119*aad98a6dSmathue 		address = (uint32_t *)(uintptr_t)address32;
120*aad98a6dSmathue 	}
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	if (fuword32(address, pvalue) == -1) {
1237c478bd9Sstevel@tonic-gate 		pfpsd->fp_trapaddr = (caddr_t)address;
1247c478bd9Sstevel@tonic-gate 		pfpsd->fp_traprw = S_READ;
1257c478bd9Sstevel@tonic-gate 		return (ftt_fault);
1267c478bd9Sstevel@tonic-gate 	}
1277c478bd9Sstevel@tonic-gate 	return (ftt_none);
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate enum ftt_type
_fp_write_extword(uint64_t * address,uint64_t value,fp_simd_type * pfpsd)1317c478bd9Sstevel@tonic-gate _fp_write_extword(
1327c478bd9Sstevel@tonic-gate 	uint64_t *address,		/* FPU data address. */
1337c478bd9Sstevel@tonic-gate 	uint64_t value,			/* Extended word value to write. */
1347c478bd9Sstevel@tonic-gate 	fp_simd_type *pfpsd)		/* Pointer to fpu simulator data. */
1357c478bd9Sstevel@tonic-gate {
1367c478bd9Sstevel@tonic-gate 	if (((uintptr_t)address & 0x7) != 0)
1377c478bd9Sstevel@tonic-gate 		return (ftt_alignment);	/* Must be extword-aligned. */
1387c478bd9Sstevel@tonic-gate 
139*aad98a6dSmathue 	if (get_udatamodel() == DATAMODEL_ILP32) {
140*aad98a6dSmathue 		/*
141*aad98a6dSmathue 		 * If this is a 32-bit program, chop the address accordingly.
142*aad98a6dSmathue 		 * The intermediate uintptr_t casts prevent warnings under a
143*aad98a6dSmathue 		 * certain compiler, and the temporary 32 bit storage is
144*aad98a6dSmathue 		 * intended to force proper code generation and break up what
145*aad98a6dSmathue 		 * would otherwise be a quadruple cast.
146*aad98a6dSmathue 		 */
147*aad98a6dSmathue 		caddr32_t address32 = (caddr32_t)(uintptr_t)address;
148*aad98a6dSmathue 		address = (uint64_t *)(uintptr_t)address32;
149*aad98a6dSmathue 	}
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	if (suword64(address, value) == -1) {
1527c478bd9Sstevel@tonic-gate 		pfpsd->fp_trapaddr = (caddr_t)address;
1537c478bd9Sstevel@tonic-gate 		pfpsd->fp_traprw = S_WRITE;
1547c478bd9Sstevel@tonic-gate 		return (ftt_fault);
1557c478bd9Sstevel@tonic-gate 	}
1567c478bd9Sstevel@tonic-gate 	return (ftt_none);
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate enum ftt_type
_fp_write_word(uint32_t * address,uint32_t value,fp_simd_type * pfpsd)1607c478bd9Sstevel@tonic-gate _fp_write_word(
1617c478bd9Sstevel@tonic-gate 	uint32_t *address,		/* FPU data address. */
1627c478bd9Sstevel@tonic-gate 	uint32_t value,			/* Word value to write. */
1637c478bd9Sstevel@tonic-gate 	fp_simd_type *pfpsd)		/* Pointer to fpu simulator data. */
1647c478bd9Sstevel@tonic-gate {
1657c478bd9Sstevel@tonic-gate 	if (((uintptr_t)address & 0x3) != 0)
1667c478bd9Sstevel@tonic-gate 		return (ftt_alignment);	/* Must be word-aligned. */
1677c478bd9Sstevel@tonic-gate 
168*aad98a6dSmathue 	if (get_udatamodel() == DATAMODEL_ILP32) {
169*aad98a6dSmathue 		/*
170*aad98a6dSmathue 		 * If this is a 32-bit program, chop the address accordingly.
171*aad98a6dSmathue 		 * The intermediate uintptr_t casts prevent warnings under a
172*aad98a6dSmathue 		 * certain compiler, and the temporary 32 bit storage is
173*aad98a6dSmathue 		 * intended to force proper code generation and break up what
174*aad98a6dSmathue 		 * would otherwise be a quadruple cast.
175*aad98a6dSmathue 		 */
176*aad98a6dSmathue 		caddr32_t address32 = (caddr32_t)(uintptr_t)address;
177*aad98a6dSmathue 		address = (uint32_t *)(uintptr_t)address32;
178*aad98a6dSmathue 	}
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	if (suword32(address, value) == -1) {
1817c478bd9Sstevel@tonic-gate 		pfpsd->fp_trapaddr = (caddr_t)address;
1827c478bd9Sstevel@tonic-gate 		pfpsd->fp_traprw = S_WRITE;
1837c478bd9Sstevel@tonic-gate 		return (ftt_fault);
1847c478bd9Sstevel@tonic-gate 	}
1857c478bd9Sstevel@tonic-gate 	return (ftt_none);
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate /*
1897c478bd9Sstevel@tonic-gate  * Reads integer unit's register n.
1907c478bd9Sstevel@tonic-gate  */
1917c478bd9Sstevel@tonic-gate enum ftt_type
read_iureg(fp_simd_type * pfpsd,uint_t n,struct regs * pregs,void * prw,uint64_t * pvalue)1927c478bd9Sstevel@tonic-gate read_iureg(
1937c478bd9Sstevel@tonic-gate 	fp_simd_type	*pfpsd,		/* Pointer to fpu simulator data */
1947c478bd9Sstevel@tonic-gate 	uint_t		n,		/* IU register n */
1957c478bd9Sstevel@tonic-gate 	struct regs	*pregs,		/* Pointer to PCB image of registers. */
1967c478bd9Sstevel@tonic-gate 	void		*prw,		/* Pointer to locals and ins. */
1977c478bd9Sstevel@tonic-gate 	uint64_t	*pvalue)	/* Place for extended word value. */
1987c478bd9Sstevel@tonic-gate {
1997c478bd9Sstevel@tonic-gate 	enum ftt_type ftt;
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	if (n == 0) {
2027c478bd9Sstevel@tonic-gate 		*pvalue = 0;
2037c478bd9Sstevel@tonic-gate 		return (ftt_none);	/* Read global register 0. */
2047c478bd9Sstevel@tonic-gate 	} else if (n < 16) {
2057c478bd9Sstevel@tonic-gate 		long long *preg;
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 		preg = &pregs->r_ps;		/* globals and outs */
2087c478bd9Sstevel@tonic-gate 		*pvalue = preg[n];
2097c478bd9Sstevel@tonic-gate 		return (ftt_none);
2107c478bd9Sstevel@tonic-gate 	} else if (USERMODE(pregs->r_tstate)) { /* locals and ins */
2117c478bd9Sstevel@tonic-gate 		if (lwp_getdatamodel(curthread->t_lwp) == DATAMODEL_ILP32) {
2127c478bd9Sstevel@tonic-gate 			uint32_t res, *addr, *rw;
213*aad98a6dSmathue 			caddr32_t rw32;
214*aad98a6dSmathue 
215*aad98a6dSmathue 			/*
216*aad98a6dSmathue 			 * If this is a 32-bit program, chop the address
217*aad98a6dSmathue 			 * accordingly.  The intermediate uintptr_t casts
218*aad98a6dSmathue 			 * prevent warnings under a certain compiler, and the
219*aad98a6dSmathue 			 * temporary 32 bit storage is intended to force proper
220*aad98a6dSmathue 			 * code generation and break up what would otherwise be
221*aad98a6dSmathue 			 * a quadruple cast.
222*aad98a6dSmathue 			 */
223*aad98a6dSmathue 			rw32 = (caddr32_t)(uintptr_t)prw;
224*aad98a6dSmathue 			rw = (uint32_t *)(uintptr_t)rw32;
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 			addr = (uint32_t *)&rw[n - 16];
2277c478bd9Sstevel@tonic-gate 			ftt = _fp_read_word(addr, &res, pfpsd);
2287c478bd9Sstevel@tonic-gate 			*pvalue = (uint64_t)res;
2297c478bd9Sstevel@tonic-gate 		} else {
2307c478bd9Sstevel@tonic-gate 			uint64_t res, *addr, *rw = (uint64_t *)
2317c478bd9Sstevel@tonic-gate 					((uintptr_t)prw + STACK_BIAS);
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 			addr = (uint64_t *)&rw[n - 16];
2347c478bd9Sstevel@tonic-gate 			ftt = _fp_read_extword(addr, &res, pfpsd);
2357c478bd9Sstevel@tonic-gate 			*pvalue = res;
2367c478bd9Sstevel@tonic-gate 		}
2377c478bd9Sstevel@tonic-gate 		return (ftt);
2387c478bd9Sstevel@tonic-gate 	} else {
2397c478bd9Sstevel@tonic-gate 		ulong_t *addr, *rw = (ulong_t *)((uintptr_t)prw + STACK_BIAS);
2407c478bd9Sstevel@tonic-gate 		ulong_t res;
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 		addr = (ulong_t *)&rw[n - 16];
2437c478bd9Sstevel@tonic-gate 		res = *addr;
2447c478bd9Sstevel@tonic-gate 		*pvalue = res;
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 		return (ftt_none);
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate /*
2517c478bd9Sstevel@tonic-gate  * Writes integer unit's register n.
2527c478bd9Sstevel@tonic-gate  */
2537c478bd9Sstevel@tonic-gate enum ftt_type
write_iureg(fp_simd_type * pfpsd,uint_t n,struct regs * pregs,void * prw,uint64_t * pvalue)2547c478bd9Sstevel@tonic-gate write_iureg(
2557c478bd9Sstevel@tonic-gate 	fp_simd_type	*pfpsd,		/* Pointer to fpu simulator data. */
2567c478bd9Sstevel@tonic-gate 	uint_t		n,		/* IU register n. */
2577c478bd9Sstevel@tonic-gate 	struct regs	*pregs,		/* Pointer to PCB image of registers. */
2587c478bd9Sstevel@tonic-gate 	void		*prw,		/* Pointer to locals and ins. */
2597c478bd9Sstevel@tonic-gate 	uint64_t	*pvalue)	/* Extended word value to write. */
2607c478bd9Sstevel@tonic-gate {
2617c478bd9Sstevel@tonic-gate 	long long *preg;
2627c478bd9Sstevel@tonic-gate 	enum ftt_type ftt;
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 	if (n == 0) {
2657c478bd9Sstevel@tonic-gate 		return (ftt_none);	/* Read global register 0. */
2667c478bd9Sstevel@tonic-gate 	} else if (n < 16) {
2677c478bd9Sstevel@tonic-gate 		preg = &pregs->r_ps;		/* globals and outs */
2687c478bd9Sstevel@tonic-gate 		preg[n] = *pvalue;
2697c478bd9Sstevel@tonic-gate 		return (ftt_none);
2707c478bd9Sstevel@tonic-gate 	} else if (USERMODE(pregs->r_tstate)) { /* locals and ins */
2717c478bd9Sstevel@tonic-gate 		if (lwp_getdatamodel(curthread->t_lwp) == DATAMODEL_ILP32) {
2727c478bd9Sstevel@tonic-gate 			uint32_t res, *addr, *rw;
273*aad98a6dSmathue 			caddr32_t rw32;
274*aad98a6dSmathue 
275*aad98a6dSmathue 			/*
276*aad98a6dSmathue 			 * If this is a 32-bit program, chop the address
277*aad98a6dSmathue 			 * accordingly.  The intermediate uintptr_t casts
278*aad98a6dSmathue 			 * prevent warnings under a certain compiler, and the
279*aad98a6dSmathue 			 * temporary 32 bit storage is intended to force proper
280*aad98a6dSmathue 			 * code generation and break up what would otherwise be
281*aad98a6dSmathue 			 * a quadruple cast.
282*aad98a6dSmathue 			 */
283*aad98a6dSmathue 			rw32 = (caddr32_t)(uintptr_t)prw;
284*aad98a6dSmathue 			rw = (uint32_t *)(uintptr_t)rw32;
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 			addr = &rw[n - 16];
2877c478bd9Sstevel@tonic-gate 			res = (uint_t)*pvalue;
2887c478bd9Sstevel@tonic-gate 			ftt = _fp_write_word(addr, res, pfpsd);
2897c478bd9Sstevel@tonic-gate 		} else {
2907c478bd9Sstevel@tonic-gate 			uint64_t *addr, *rw = (uint64_t *)
2917c478bd9Sstevel@tonic-gate 				((uintptr_t)prw + STACK_BIAS);
2927c478bd9Sstevel@tonic-gate 			uint64_t res;
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 			addr = &rw[n - 16];
2957c478bd9Sstevel@tonic-gate 			res = *pvalue;
2967c478bd9Sstevel@tonic-gate 			ftt = _fp_write_extword(addr, res, pfpsd);
2977c478bd9Sstevel@tonic-gate 		}
2987c478bd9Sstevel@tonic-gate 		return (ftt);
2997c478bd9Sstevel@tonic-gate 	} else {
3007c478bd9Sstevel@tonic-gate 		ulong_t *addr, *rw = (ulong_t *)((uintptr_t)prw + STACK_BIAS);
3017c478bd9Sstevel@tonic-gate 		ulong_t res = *pvalue;
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 		addr = &rw[n - 16];
3047c478bd9Sstevel@tonic-gate 		*addr = res;
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 		return (ftt_none);
3077c478bd9Sstevel@tonic-gate 	}
3087c478bd9Sstevel@tonic-gate }
309