home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 2 / RISC_DISC_2.iso / pd_share / program / code / swiv / swivDoc
Encoding:
Text File  |  1995-02-28  |  9.1 KB  |  220 lines

  1.                 Y E T   A N O T H E R   S W I   V E N E E R
  2.                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  3.  
  4. Introduction
  5. ~~~~~~~~~~~~
  6.  
  7. This document is about another way of accessing SWIs from C.  It explains,
  8. in no particular order:
  9.  
  10. * Why I've rewritten it
  11. * How to use it
  12. * What's nicer about my one
  13.  
  14.  
  15. The story behind it
  16. ~~~~~~~~~~~~~~~~~~~
  17.  
  18. A while ago, Acorn wrote a couple of functions to call SWIs from C.  They
  19. were called _swi and _swix (_swix will return errors, _swi won't).  These
  20. routines actually have quite a nice programmer interface, which feels vaguely
  21. natural from C.  A copy of these routines is contained within the
  22. SharedCLibrary module in RISC OS 3.  The new CLib stubs will allow you to
  23. access these routines, at the cost of losing compatibility with RISC OS 2.
  24. There's nothing you can do about this; if you use the new stubs, you can't
  25. use the RISC OS 2 CLib.  And just to help, the new C compiler generates
  26. different names for the run-time support functions it needs (e.g. it tries to
  27. call __rt_stkovf_split_small instead of x$stack_overflow) and the old stubs
  28. don't declare these names.  (The routines are identical, it's just that
  29. they're called different names now.)
  30.  
  31. As many people will no doubt know, I've been working on a dynamic linking
  32. system for ages (the code is done -- I'm trying to get the documentation into
  33. a readable state still).  Part of this system is some replacement
  34. SharedCLibrary stubs, which interface neatly with the rest of the system so
  35. that things are handled automatically on startup.
  36.  
  37. My stubs are intended to be drop-in replacements for the Acorn ones.
  38. Actually, they're quite a bit smaller (almost as small as GSTStubs,
  39. apparently), so I tend to use them all the time.  The new versions contain
  40. the old and new names for the run-time support functions.  However, I was
  41. put into a bit of a dilemma by the new entry points, since if I include
  42. interfaces to the new routines, the stubs won't work under RISC OS 2, whereas
  43. if I don't include them, they won't be compatible with the Acorn ones any
  44. more.  My solution was to have two versions, one which included the new entry
  45. points and one which doesn't.  And so you *can* have your cake and eat it, I
  46. decided to write my own version of these new routines so I could give it
  47. away, for people who want to use them under RISC OS 2.
  48.  
  49. While I was testing my implementation, I came across a bug in the Acorn
  50. version.  My one doesn't have this bug (described below) -- another good
  51. reason for me to have replaced it.
  52.  
  53.  
  54. How to use the veneers
  55. ~~~~~~~~~~~~~~~~~~~~~~
  56.  
  57. The two functions are very similar to each other:
  58.  
  59.     int _swi(int swi_no,int flags,...);
  60.     _kernel_error *_swix(int swi_no,int flags,...);
  61.  
  62. The arguments are the same in both cases.
  63.  
  64. The interesting bit of these routines is the flags word.  A collection of
  65. macros is supplied (they've been augmented a bit by me and others since the
  66. original Acorn versions), to allow you to specify what to do with all the
  67. registers.  You just add together the values you want.
  68.  
  69.     _in(n)        Specify Rn as being an input register
  70.     _inr(m,n)    Specify Rm-Rn as being input registers
  71.     _out(n)        Specify Rn as being an output register
  72.     _outr(m,n)    Specify Rm-Rn as being output registers
  73.     _return(n)    Return the value of Rn as the value of the function
  74.     _block(n)    Point Rn at `local block' on entry to the SWI
  75.  
  76. _inr and _outr are nonstandard.  Also, the standard versions are upper case.
  77. My version allows both, and I prefer the lower, because I find that the call
  78. gets less cluttered.  The macros work on both versions of the routines -- you
  79. just use your favourite one.
  80.  
  81. _return is only allowed in calls to _swi -- the return value of _swix is
  82. always the error pointer (0 for no error, otherwise it's a pointer to the
  83. number and string of the error, as usual).
  84.  
  85. As well as register numbers, you can also specify the special value _flags to
  86. indicate that _swi or _swix should either output or return the processor
  87. flags.
  88.  
  89. If you don't want any flags at all, pass 0 as the flags value.
  90.  
  91. Both routines take an arbitrary number of arguments, from 2 upwards (if you
  92. give too many, the excess ones are just ignored).  The arguments you pass are
  93. as follows, in order:
  94.  
  95.     One word (int or pointer, usually) for each input (_in) register, in
  96.     ascending numerical order
  97.  
  98.     One address of a word (again, an int or pointer usually) for each
  99.     output (_out) register, again in ascending numerical order
  100.  
  101.     The address of a word in which to store the flags, if applicable
  102.  
  103.     Any values to build into the local block
  104.  
  105. The `local block' is just built from the excess arguments you pass.  You can
  106. set up a register to point to the block if you want; that way you can easily
  107. build a parameter block in the function call and let the compiler get on with
  108. the tedious business of storing all the values individually.
  109.  
  110. Some examples will probably help clear up any confusion:
  111.  
  112.     int currentTime=_swi(OS_ReadMonotonicTime,_return(0));
  113.                     /* Read current value of timer    */
  114.  
  115.     int taskh=_swi(Wimp_Initialise,_inr(0,2)+_return(1),
  116.                    200,0x4b534154,"MyTaskName");
  117.                                /* Initialise a WIMP task    */
  118.  
  119.     _swi(Wimp_SetIconState,_block(1),wind,icn,0,0);
  120.                     /* Prod an icon into redrawing    */
  121.  
  122.     _swi(OS_ReadC,0);        /* Wait for a keypress        */
  123.  
  124.     int x,y,b;
  125.     _swi(OS_Mouse,_outr(0,2),&x,&y,&b);
  126.                     /* Read current mouse position    */
  127.  
  128.     if (_swi(OS_ReadEscapeState,_return(_flags)) & _c)
  129.       /* Do something */        /* Check the escape state    */
  130.  
  131. As I hope you can see, it's actually rather a powerful design.  Full credit
  132. for this goes to Acorn on this one.  I just rewrote the code.  They'd already
  133. done the hard bit.
  134.  
  135. The _inr and _outr macros, put to good use above, are not mine either, and
  136. credit for them, and their implementations, goes to Brian Brunswick.
  137.  
  138. Blame for the contrived examples above is justifiably aimed at me, though,
  139. as are any bugs I've missed in the code.
  140.  
  141.  
  142. Differences between the implementations
  143. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  144.  
  145. The idea was to make the Straylight version identical to the Acorn one.  This
  146. is almost what has happened, although there are some differences you should
  147. be aware of:
  148.  
  149.  1. The Acorn implementation contains a bug which makes it set the address
  150.     of a local block argument incorrectly if R0 is one of the _out()
  151.     registers.  The Straylight version does not have this bug (or any others
  152.     that I know about).
  153.  
  154.  2. The Straylight implementation is 40 bytes smaller than the Acorn one.
  155.     However, to be fair, the Acorn version is actually embedded in the
  156.     SharedCLibrary under RISC OS 3, so you gain big here.  On the other
  157.     hand, it would be trivial for me to make the Straylight version
  158.     dynamically linkable to get the same advantage.  (It would be fairly
  159.     pointless too, really, but I could do it, just the same.)
  160.  
  161.  3. The Acorn implementation is slightly slower.  This is largely by
  162.     accident, actually.  For those interested, a breakdown of the timings is
  163.     given below.  For those who aren't, the differences are worth worrying
  164.     about in practice.
  165.  
  166.  4. The Straylight implementation of _swix will store register values even
  167.     if the SWI returned an error.  The Acorn version won't do this.  This
  168.     is intentional -- occasionally useful information is returned here.  If
  169.     anyone doesn't like this, let me know and I may change it.
  170.  
  171.  5. Source code to the Acorn version is available (see the Memphis
  172.     distribution, in FSLib.s.swiv).  Straylight don't release source, so
  173.     you'll have to give up there.
  174.  
  175.  
  176. Timing comparison
  177. ~~~~~~~~~~~~~~~~~
  178.  
  179. The timings are presented in terms of ARM2 S-cycles (so I've counted an N as
  180. 2S and so on).  It makes things simpler this way.  Neither tries to do
  181. anything really clever with N cycles, so it doesn't make a lot of difference.
  182.  
  183. Note that trying to read _out() values of registers greater than a certain
  184. threshhold (R3 for the Straylight version, R4 for the Acorn one) will cause
  185. the routine to take longer.  Trying to return the flags will pass this
  186. threshhold in both versions.  Note too that _swix is ever so slightly quicker
  187. than _swi in both cases.
  188.  
  189.                 Straylight        Acorn
  190.  
  191. Base time               102             108
  192.  
  193.   _swi rather than _swix        +1                    +4
  194.   Local block argument             +60                   +56
  195.   For each input register           +1                    +1
  196.   No input registers                +1                    +1
  197.   For each output register          +6                    +6
  198.   For outputting the flags          +9                    +9
  199.   For passing output threshhold    +16                   +13
  200.  
  201. Best case time                     103                   109
  202. Worst case time                    259                   261
  203.  
  204. I don't consider the speed difference to be terribly significant; I'm
  205. actually much more worried about the 40 bytes size difference here, since
  206. SWIs usually take a fairly long time anyway.
  207.  
  208.  
  209. I hope someone somewhere finds this useful.  Otherwise I've wasted a lot of
  210. time typing all this in.
  211.  
  212.  
  213.                         Mark Wooding
  214.                         Straylight
  215. --
  216.  ('  t  r  a  y  l  i  g  h  t  / `Clearly now the past mistakes
  217. ,_)  csuov@csv.warwick.ac.uk   / The giant steps we had to take
  218.                               / The path that ever promise made
  219.          Mark Wooding        / To die in dream, dissolve and fade'
  220.