It's some time since I have used this, there are sub routines however, I believe you have to create your own parameter passing.
the subroutine is after the END instruction and in the version I had if you wished to create a function that took & returned parameters then you have to use temporary memory areas.
As I say it's some time ago but this might give you some idea as I cannot remember the proper instructions.
Function add 3 integers and divide by 4th output result.
main program
Mov VC100 to VC200 // move 1st value to temp 1
Mov VC101 to VC201 // Move 2nd value to temp2
Mov VC102 to VC202 // Move 3rd value to temp3
Mov VC103 to VC203 // Move 4th value to temp4
LD X0 JC P100 // When bit X0 true jump to pointer of function (sub routine)
LD VC203, T VC104 ...... // returned value from function
........ //Other logic of program
........
Mov VC150 to VC200 // move 1st value to temp 1
Mov VC151 to VC201 // Move 2nd value to temp2
Mov VC152 to VC202 // Move 3rd value to temp3
Mov VC153 to VC203 // Move 4th value to temp4
LD X1 JC P100 // When bit X true jump to pointer of function
LD VC 203, T VC154 ..... //Returned value from function.....
........
........ //other logic in main routine
END // end of main program
P100: //pointer to subroutine
ADD VC200, VC201, to VC203 //Add the two values
ADD VC202, VC203, VC203 // Add 3rd value
SUB VC 203, VC202, to VC203 // sub the 4th value and store in VC203
RETURN // Return from the sub
Basically what it does is pass the words or bits to temporary memory
jumps to the code and works on those words or bits
then puts the result(s) into the return temporary memory(ies) jumps back and loads the result into your addresses
Obviously there is no point in doing this for small subs as the coding to transfer var ins var outs or var in/outs takes more than writing it long hand.
I did a similar thing in SLC500 as this did not have user functions so wrote a standard block using memory areas i.e. bits & words then before the call of the block passed the input var to the temps put a call to the block then on return from the block passed the out or in/out back to memories.
This is exactly how siemens or others do it, however they probably use variables not exposed to the programmer.