[comp.sys.mac.programmer] Inline routines for Turbo Pascal

d88-cbr@dront.nada.kth.se (Christian Beijner) (01/04/91)

{ This contains code for the some of the newest missing traps on the Mac not
included in Turbo 1.1. In the end is a test program.

It also includes code for Inc and Dec.
Also a function sgn who returns -1 for negative numbers 1 for positive and
0 for zero numbers
Ex:

Sgn(-100)=-1
Sgn(0)   = 0
Sgn(100) = 1

These last three procedure might be useful to you Snailspeed, sorry thats
Lightspeed Pascal users, but be careful since LSP might not handle inlines
the same way as Turbo does. (The PROBABLY do. I tried INC and DEC and could
see no problem, except that I could not find the actual execution in
Macsbug, since LSP adds so much own debugging code.)

You may use or modify
 this code freely as long as the "Code by" row remains unchanged,
 and if you pick out any part of the code this line is present in the
 part you selected.
If you change any of the inline code, add a "Modified by" line.
If you do use this code I would appreciate a thank you or even a
friendly flame (should you find any errors or ways to improve)
at the following adress.

email:  d88-cbr@nada.kth.se

Mail:   Christian Beijner
        Vikbyvagen 58
        181 43 Lidingo
        Sweden

Now some discussion on the routines.

INLINE generally. The inline is a macro, not a procedure. The exact code
following inline will be added as is whenever a call to the 
inline-"procedure" is done. The computer only pushes the parameters onto the
stack before the macro and pops any results after, if it is a function.
There is no return address or such.
If you want to look at the execution of a routine, add $A9FF (_debugger)
first in the inline and you will enter Macsbug before the actual execution,
so you can observe the execution.

SYSENV this is the routine as outlined in IM V except that the parameter
is NOT a ptr-type. The var declaration turn makes the program put the
adress on the stack.
I cannot check this routine on all machines so please check the results
on your machine.

DEBUGGER, calling this procedure put you into Macsbug or whatever.
Continue running by typing g and then return.

DEBUGSTR, like the above, but you can define a string to be typed out
by Macsbug instead of user break. You can also define commands to be
executed. If your programs crash, try debugging by adding lines like
this: 
  debugstr('Now at "somewhere";g');
 
The g makes execution continue, just as if you had pressed g and return.
When the computer crashes, unless its REALLY fatal you can look at the
output in Macsbug.

INC & DEC is a three-instruction implementation of
  x:=x11;
  
  The computer adds a PEA instruction before to push the address of
  the variable used.

x:=x+1 is also only 3 instructions in Turbo,(see below) but I found inc(x) to be 
be slightly faster.
MOVE nn(A5),D0
ADDQ #1,D0
MOVE DO,nn(A5)
nn is the offset of the variable x compared to A5.

SGN is a lot faster than the pascal variety I used to use.
I challenge anyone to make it shorter. It might very well be done.

}
unit traps(1);
interface

{ Code by Christian Beijner 31 dec 1990 }

uses memtypes,quickdraw,osintf;
const envmachunknown=0;
      env512KE=1;
      envmacplus=2;
      envse=3;
      envmacII=4;
      envMacIIx=5;
      envMacIIcx=6;
      envSE30=7;
      envPortable=8;
      envMacIIci=9;
      
      envmac=-1;
      envxl=-2;
      
      envcpuunknown=0;
      env68000=1;
      env68010=2;
      env68020=3;
      env68030=4;
      
      envunknownkdb=0;
      envmackbd=1;
      envmacandpad=2;
      envmacpluskbd=3;
      envaetendedkbd=4;
      envstandadbkbd=5;
      envPortADBKbd=6;
      envPortISOADBKbd=7;
      envStdISOADBKbd=8;
      envExtISOADBKbd=9;
      
      
type sysenvrec=record
        environsversion:integer;
        machinetype:integer;
        systemversion:integer;
        processor:integer;
        hasfpu:boolean;
        hascolorqd:boolean;
        keyboardtype:integer;
        atdrvrversnum:integer;
        sysvrefnum:integer;
     end;
     
     sysenvrecptr=^sysenvrec;
     
function sysenvirons(versrequested:integer;var theworld:sysenvrec):oserr;
inline $205f,$301f,$a090,$3e80;

procedure debugger;
inline $a9ff;
{ _debugger }

procedure inc(var x:integer);
inline $205f,$5250;
{ MOVE (A7)+,A0
  ADDQ 1,(A0) }

procedure dec(var x:integer);
inline $205f,$5350;
{ MOVE (A7)+,A0
  SUBQ 1,(A0) }
  
procedure debugstr(s:Str255);
inline $ABFF;
{ _Debugstr }
        
function sgn(x:longint):integer;
inline $201F,$6708,$6D04,$7001,$6002,$70FF,$548F,$3F00;
      
{       MOVE.L (A7)+,D0
        BEQ.S   THEEND
        BLT.S   MINUS
        MOVEQ   #1,D0
        BRA.S   THEEND
MINUS   MOVEQ   #-1,D0
THEEND  ADDQ    #2,A7
        MOVE.W  D0,-(A7) }
  
  

implementation
{ There is no implementation }
begin
  { Nor is there any initing }

end.

program trapstest;
{ Written to illustrate the "Traps"-unit }
{Code by Christian Beijner 2 jan 1991 }
{$U HD:asssembler:Traps}
uses memtypes,quickdraw,osintf,toolintf,traps;
const maxmachines=envMacIIci;
      maxcpus=env68030;
var machines:array(.envmachunknown..maxmachines.) of string (.15.);
    processors:array(.envcpuunknown..maxcpus.) of string(.8.);
    theworld:sysenvrec;
    thesyserr:longint;
    x,i:integer;
begin
  debugstr('Now initializing;g');
  machines(.envmachunknown.):='Unknown machine';
  machines(.env512KE.):='Mac 512KE';
  machines(.envmacplus.):='Mac Plus';
  machines(.envse.):='Mac SE';
  machines(.envmacII.):='Mac II';
  machines(.envMacIIx.):='Mac IIx';
  machines(.envMacIIcx.):='Mac IIcx';
  machines(.envSE30.):='Mac SE30';
  machines(.envPortable.):='Mac Portable';
  machines(.envMacIIci.):='Mac IIci';
  processors(.envcpuunknown.):='Unknown';
  processors(.env68000.):='env68000';
  processors(.env68010.):='68010';
  processors(.env68020.):='68020';
  processors(.env68030.):='68030';
  debugstr('Now calling sysenv;g');
  writeln('Sysenv ',sysenvirons(2,theworld));
  thesyserr:=sysenvirons(2,theworld);
  debugstr('Will now write theworld;g');
  writeln('Systemerror ',thesyserr);
  writeln('This program is run on a ',machines(.theworld.machinetype.));
  writeln('with a ',processors(.theworld.processor.));
  writeln('The systemversion is nr ',theworld.systemversion);
  write('The machine is ');
  if not theworld.hascolorqd then write('not');
  writeln(' a color machine');
  writeln('Press return');
  readln;
  
  debugstr('Will now test sgn;g');
  x:=-1;
  dec(x);
  writeln('SGN(',x,')=',sgn(x));
  inc(x);
  inc(x);
   writeln('SGN(',x,')=',sgn(x));
  inc(x);
  inc(x);
   writeln('SGN(',x,')=',sgn(x));
  
  debugstr('Press g and then return to continue;g');
  debugger;
  writeln('Press return');
  readln;
end.