,ll 6.6
,cs 10
,pl 66
,lm 0.2,0.5
,pn 5
,ju
,hd
,ce
OmegaSoft 6809 Cross Pascal Language Handbook (V1.0)
,,
,ft

,ce 1
7-##
,,
,ce
OmegaSoft 6809 Cross Pascal Language Handbook (V1.0)

,ce
PARAMETER PASSING

When any procedure or function is called there may be parameters that have to be passed. The parameters are passed on the data (U) stack using PSHU instructions. The parameters are passed in the order that they are declared.

Variable parameters are passed by pushing their address on the data stack.

Value parameters are passed in different ways depending on the data type : 

Boolean, character, and enumerated types are simply one byte pushed on the stack. 

Integer, hex, and pointer types are two bytes pushed on the stack, most significant byte at the lower address. 

Longinteger and real types are four bytes pushed on the stack, most significant (exponent) byte at the lowest address. 

Records and arrays are a group of bytes pushed on the stack and appearing just as they do when stored as a variable (the first byte of a record is at the lowest address). 

Sets and strings are passed by first pushing the set or string on the stack, with the dynamic length at the lowest address and using dynamic length + 1 bytes on the stack. A procedure is then called which adjusts this variable length structure into a fixed length structure by moving it down to take up as many bytes on the stack as are required by the formal parameter declaration of the called procedure or function. As an example, if the declaration is : string [5] and it is passed by value the string 'ABC' then initially the parameter will occupy 4 bytes on the stack :

   +--------------+
   |     'C'      |
   +--------------+
   |     'B'      |
   +--------------+
   |     'A'      |
   +--------------+
   |      3       |
   +--------------+ <- U 

After the stack adjustment routine is called the stack will look like :

   +--------------+
   |     'C'      |
   +--------------+
   |     'B'      |
   +--------------+
   |     'C'      |
   +--------------+
   |     'B'      |
   +--------------+
   |     'A'      |
   +--------------+
   |      3       |
   +--------------+ <- U
,ce
PARAMETER PASSING

To occupy 6 bytes on the stack. This is done so that for any type of variable and any combinations of parameters a procedure can access its parameter by using fixed offsets from its stack mark.

In the case of assembly language routines there is really no need for all that messing about with stack frames and it is convenient to access parameters referenced off of the U stack mark. Below are two examples of what the stack would look like when control was passed to an assembly language routine :

procedure test1 (var disk : text ; name : string[5]) ; external ;

function test2 (count : integer ; var xx : string) : boolean ;
                                                       external ;

stack frame when test1 is called :

   +--------------------------+ <- +8 from U
   | address of variable disk |
   +--------------------------+ <- +6 from U
   |   contents of name       |
   +--------------------------+ <- +1 from U
   |  dynamic length of name  |
   +--------------------------+ <- U stack pointer

to load X with the address of disk : LDX 6,U
to load X with the address of name : LEAX 0,U
to remove parameters from stack    : LEAU 8,U

stack frame when test2 is called :

   +--------------------------+ <- +4 from U
   |         count            | 
   +--------------------------+ <- +2 from U
   |  address of variable xx  |
   +--------------------------+ <- U stack pointer

to load D with the count           : LDD 2,U
to load x with the address of xx   : LDX 0,U
to remove parameter from stack     : LEAU 4,U

When an assembly language procedure returns (RTS) all parameters must be removed by moving the user stack pointer back up. When an assembly language function returns, the only thing on the stack should be the function return value. In the case of test2 above, the stack should look like this when returning :

   +---------------------------+ <- +1 from U
   | boolean value of function |
   +---------------------------+ <- U stack pointer

Function return values are in the same format on the stack as parameters are, except for sets and strings. When a set or string is returned from a function it is not to be adjusted. The set or string must occupy dynamic length + 1 bytes on the stack.

If a Pascal procedure is to be called from assembly language then the assembly language routine must use the same method of parameter passing.
,pg
,ce
PARAMETER PASSING

The base register must also be valid when calling Pascal procedures and in this case the base register (Y register) would be the same as the global base register (see Interrupt procedures).

,ce
INTERRUPT PROCEDURES

Interrupts can generally be handled using interrupt (or firq) procedures when working on your target system. 

Most operating systems do some pre-processing of interrupts and so you should also be familiar with how to call a pascal procedure under these conditions.

The procedure used to handle an interrupt (assuming it is not all done in assembly language) must be given the entry attribute and be at lexical level 2. As usual, register Y must be valid and then you call the pascal procedure. This is followed by a RTI assembly language instruction. As an example the following routine will read a port to clear the interrupt flag and update a timer to be used as a delay mechanism in the main Pascal program.
 
procedure rtcirq ; entry ;
  var
    dummy : byte ;
  begin
    dummy := port { read port to clear interrupt }
    if time <> 0
      then
        time := pred (time) { update timer if not zero }
  end ;
,pg
,ce
INTERRUPT PROCEDURES

It must be possible to obtain the value of the Y register THAT THE PASCAL PROGRAM USES, not the value used by the operating system.

Assembly language support :
 
irqvec ****obtain true value of Y register*****
       bsr rtcirq
       rti *****or other as required by operating system****

As you can see, running pascal interrupt procedures under an operating system can be a very tricky matter. The best suggestion is probably to find a safe area of RAM and save the Y register value there in the stack setup code so they can be accessed later in the above code. When using interrupt procedures on a target system, the stack setup code saves the global Y register in a location specified in the linkage creator.

