| I can answer you first question - not so sure about the second.
To call a macro routine from FORTRAN (this is a VAX, I assume...), you
have two choices. Depends on whether you want to call your routine
as a function or subroutine. Makes very little difference, except
how the value is returned. Since function call return values are limited to
atomic data types (value must fit in R0), I will demonstrate the other.
Example:
(from FORTRAN)
INTEGER*4 A, B, C !Arguments
INTEGER*4 WHATZIT !Function
.
.
.
CALL WHATZIT (A, B, C) !A = B XOR C
In a file, WHATZIT.MAR:
.TITLE WHATZIT
.PSECT $CODE
.ENTRY WHATZIT, ^M<>
; Upon entry, the argument pointer (AP) points to a list of arguments.
; This list consists of N+1 longwords, where N=number of arguments. The
; low order byte of the first longword contains N. The rest contain the
; addresses of the arguments.
;
; In order to move the address of the argument in a register, you use
; indexed addressing mode. Example :
;
; MOVL 8(AP), R1 ;Move the address of the second argument
; ; into register 1
;
; In order to get the value, use index deferred mode. Example:
;
; MOVL @8(AP), R1 ; Same as above, except gets value.
;
; Executable code starts (and ends) here:
;
XORL3 @8(AP), @12(AP), @4(AP) !A = B xor C
RET
.END
Things get a little hairy when you are dealing with FORTRAN CHRACTER data
types. These are passed by descriptor. Thus to put the address of the string
into R1 and the length into R2, do the following:
MOVL 4(AP), R0
MOVL 4(RO), R1
MOVL (R0), R2
If you know the length of the string already, you can pass the CHARACTER string
by reference and not worry about decoding the descriptor:
CHARACTER*99 ABC
CALL THING (%REF(ABC))
For a much better discussion and (I think) examples of how to do these things,
look in the FORTRAN users guide.
You second question is harder for me since I have never dealt with packed
decimal strings. FORTRAN does not support them as a data type, and it
is not clear from your note how you are reading them in or what data types
you are using to store them. You will need to store the length somehow, unless
they are fixed. The VAX-11 architecture reference manual explains how
this type is represented on page 2-13.
Also, if this is for a benchmark, you may need to be careful. If I am not
mistaken (it has been known to happen...) not all VAX processors implement
the decimal string instructions in firmware (uVAX, 82/8300??) but by
emulation. If you need to use any (it doesn't sound like it) a lot
on one of these processors, performance may not be too good.
|
| I'm having a difficult time understanding the problem; decimal 2043
equals hexadecimal 7FB, and hex 1F1 equals decimal 497.
Suppose that you have the sequence of bytes:
.BYTE ^X20, ^X43
and you want to convert this to the sequence of bytes:
.BYTE ^X02, ^X04, ^X3C
(note that VAXen store packed decimal this way -- the least significant
nibbles are in the highest-addressed locations).
To this end, I'll assume the things are passed in character strings:
CHARACTER*2 SRC
CHARACTER*3 DST
CALL CVT (SRC, DST)
The Macro-32 code is ...
.TITLE CVTMODULE
.PSECT $CODE
.ENTRY CVT, ^M<R2,R3,R4,R5> ; Save R2 thru R5
MOVQ @4(AP), R0 ; Load source descriptor
MOVQ @8(AP), R2 ; Load destination descriptor
MOVZWL R0, R0 ; Source length is a word
MOVZWL R2, R2 ; Ditto destination length
ADDL2 R0, R1 ; Point just past end of source
ADDL2 R2, R3 ; Point just past end of destination
MOVL #^X0C, R5 ; Initialize what we're 'adding in'
BRB 20$ ; Jump into the loop
;
10$: MOVZBL -(R1), R4 ; Fetch a source byte
ASHL #4, R4, R4 ; Shift left 4 places
DECL R2 ; Can we store it?
BLSS 50$ ; Branch if we run out of destination
ADDB3 R4, R5, -(R3) ; Add and store
ASHL #-4, R4, R5 ; Shift that nibble back down
20$: SOBGEQ R0, 10$ ; Another byte of source to grab?
BRB 40$ ; Go finish filling the destination
;
30$: MOVB R5, -(R3) ; Store it
ASHL #-4, R5, R5 ; Clears R5, but reuses above technique
40$: SOBGEQ R2, 30$ ; Can we store another byte?
;
50$: RET ; We've filled the destination
.END
|