FORTRAN 77 on PDP-11

der Mouse mouse at Rodents.Montreal.QC.CA
Thu Jul 28 23:23:40 CDT 2005


> ;assuming A[0] = MSW, and that each "number"
> ;is 7 bytes long
...
> 		movw	#7,r3
> 		clrw	r6		; clear carry over
> .loop:		clrw	r4		; clear tmp registers
> 		clrw	r5
> 		movb	(r0)[r3],r4	; get unsigned byte into signed word
> 		movb	(r1)[r3],r5
> 		mulw	r4,r5		; do signed multiplication
> 		addw	r6,r5		; add in previous "carry over"
> 		movb	r5,(r2)[r3]	; save result
> 		rotl	-8,r5,r6	; save "carry over"
> 		bitcw	#00FF,r6	; make sure "carry over" is between 0 - 255
> 		sobgeq	r3,.loop	; loop

* The comment says 7 bytes long; the code actually does 8 (7..0)
* Why not use movzbw instead of clrw-and-movb?
* It's canonically bicw, not bitcw.
* You need bicw #ff00,r6, not #00ff.
* movzbw r6,r6 does what your bi[t]cw tries to, and is shorter.
* If you'd store the numbevrs little-endian, the VAX way, instead of
  big-endian, you could do it much more cheaply with emul - especially
  if you do use a multiple of 4 bytes.

> Get's around the fact that the MUL instruction is signed only, even
> though the longer number is unsigned.

Provided you have integer overflow traps turned off, the difference
doesn't matter; the only difference between signed and unsigned
multiply is what constitutes arithmetic overflow.

Here's what I'd do, which rolls all the above suggestions together:

; All numbers are 8 bytes long, unsigned, LSB-first (native-endian)
; Overflow is ignored (high 64 bits of the 128-bit product are lost)
; r0 - points to first byte of multiplier A
; r1 - points to first byte of multiplier B
; r2 - points to first byte of result
; r3,r4,r5 - ignored on input and garbaged on output
	emul	(r0),(r1),$0,r3
	emul	(r0),4(r1),r4,r4
	emul	4(r0),(r1),r4,r4
	movq	r3,(r2)

If you want the whole 128-bit product, then

; r0 - input A, 8 bytes
; r1 - input B, 8 bytes
; r2 - output, 16 bytes
; r3-r9 - scratch
	emul	(r0),(r1),$0,r3
	emul	(r0),4(r1),r4,r4
	emul	4(r0),4(r1),r5,r5
	emul	4(r0),(r1),r4,r8
	addl2	r9,r5
	adwc	$0,r6
	movl	r3,(r2)
	movl	r8,4(r2)
	movq	r5,8(r2)

> If you do have a DIV instruction,

What VAX doesn't?

> and for printing out the result, it's easy to divide through the
> large number by 10 (as long as you get both the quotient and
> remainder from the DIV instruction).

Except you don't.  You probably want EDIV, which does give both.

/~\ The ASCII				der Mouse
\ / Ribbon Campaign
 X  Against HTML	       mouse at rodents.montreal.qc.ca
/ \ Email!	     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B


More information about the cctalk mailing list