/*
 * swiv.h
 *
 * Interface to SWI veneer
 *
 *  1997, 1998 Straylight
 */

/*----- Licensing note ----------------------------------------------------*
 *
 * This file is part of Straylight's core library (corelib).
 *
 * Corelib is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * Corelib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Corelib.  If not, write to the Free Software Foundation,
 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifndef ___swis_h
#define ___swis_h

#ifdef __cplusplus
  extern "C" {
#endif

#ifndef __kernel_h
  #include "kernel.h"
#endif

/* --- SWI veneer functions --- *
 *
 * Arguments:	int swi == the SWI to call
 *		unsigned flags == a definition of the SWIs registers
 *
 * Returns:	_swi returns the value of the `return' register in the flags
 *		_swix returns 0, or a pointer to an error block
 *
 * Use:		Calls a SWI, passing it a collection of registers, and
 *		filling in the registers as given in the function call.
 *
 *		Order of arguments is as follows:
 *
 *		Input registers:	One word for each input register
 *		Output registers:	Address to store each reg value
 *		Flags address:		Address to store PC+flags value
 *		Block contents:		Build contents of local block at end
 */

extern int _swi(int /*swi*/, unsigned /*flags*/,...);
extern _kernel_oserror *_swix(int /*swi*/, unsigned /*flags*/,...);

/* --- Various flags settings --- *
 *
 * _in(n) -- declare Rn as an input register
 * _inr(m, n) -- declare Rm--Rn as input registers
 * _out(n) -- declare Rn as an output register
 * _outr(m, n) -- declare Rm--Rn as output registers
 * _return(n) -- return Rn from _swi
 * _block(n) -- point Rn at block containing remaining arguments
 */

#ifndef _FLAGS

  /* --- _flags -- return or output processor flags --- */

  #define _flags	(0x10)

  /* --- _in and _inr -- input a register, or a range of registers --- */

  #define _in(r)	(1u << (r))
  #define _inr(ra,rb)	(((~0) << (ra)) ^ ((~0) << ((rb)+1)))

  /* --- _out and _outr -- output a register, or a range of registers --- */

  #define _out(r)	(1u << (31-((r) == _flags ? 10 : (r))))
  #define _outr(ra,rb)	(((~0) << (31-(rb))) ^ ((~0) << (32-(ra))))

  /* --- _block -- point a register at block built from arguments --- */

  #define _block(r)	(((r) << 12) | 0x800)

  /* --- _return -- return register from _swi (not _swix) --- */

  #define _return(r)	((r) == _flags ? 0xF0000 : (r) << 16)

  /* --- Constants for ARM processor flags --- */

  #define _n		(0x80000000u)
  #define _z		(0x40000000u)
  #define _c		(0x20000000u)
  #define _v		(0x10000000u)

  /* --- Acorn style capital-letter macros --- */

  #define _FLAGS	_flags
  #define _IN(x)	_in(x)
  #define _INR(x,y)	_inr(x,y)
  #define _OUT(x)	_out(x)
  #define _OUTR(x,y)	_outr(x,y)
  #define _BLOCK(x)	_block(x)
  #define _RETURN(x)	_return(x)
  #define _N		_n
  #define _Z		_z
  #define _C		_c
  #define _V		_v

#endif

#ifdef __cplusplus
  }
#endif

#endif
