Xinu7/src/lib/libeis/mul.s

Compare this file to the similar file:
Show the results in this format:

/
/ PDP-11 MULTIPLY ROUTINE
/
/ This routine will multiply two 16-bit signed numbers using two's complement
/ arithmetic. It also sets the condition codes properly upon exit in the lo-
/ cation psw.
/
/ DEFINITION:
/ Multiply              DO                                      070RSS
/ Operation:    R,Rv1 <- R x (src)
/ Condition     N: set if product < 0
/ Codes:        Z: set if product = 0
/               V: cleared
/               C: set if the result is less than -2^15 or greater than
/                  or equal to 2^15 - 1
/ Description:  The contents of the destination register and source taken
/               as 2's complement integers are multiplied and stored in
/               the destination register and the succeeding register if R
/               is even. If R is odd, only the low orede product is stored.
/               ...
/
/ (copied from MICROCOMPUTERS AND MEMORIES, c. 1981 by Digital Equipment
/ Corporation; pp. 111 - 112)
/
/ ALGORITHM:
/   The algorithm is the conventional add-and-shift one. The following C
/ version is meant to be a guide ONLY; the code below is a hand-compilation of
/ this program (essentially). (The given version ignores C parameter passing
/ conventions.)
/
/ mul(a, b, prod, psw)
/ int a;                /* multiplier */
/ long b;               /* multiplicand */
/ long prod;            /* product */
/ int psw;              /* processor status word */
/ {
/       prod = 0L;      /* initialize */
/       psw &= ~017;
/                       /* handle a <= 0 */
/       if (a < 0){ a = -a; psw |= 010; }
/       else if (a == 0){ psw &= ~017; psw |= 04; return; }
/                       /* handle b <= 0 */
/       if (b < 0L){ b = -b; psw ^= 010; }
/       else if (b == 0L){ psw &= ~017; psw |= 04; return; }
/                       /* do the multiply */
/       while(a > 0){
/               if (a&01) prod += b;    /* LSB of a is 1 so add in b */
/               a >>= 1;                /* halve a */
/               b <<= 1;                /* double b */
/       }
/                       /* check for overflow */
/       if (psw & 010){
/               if (prod > 0177777L) psw |= 01; /* overflow */
/               prod = -prod;
/       }
/       else if (prod >= 077777L) psw |= 01;    /* overflow */
/ }
/
/ CALLING SEQUENCE:
/ code to simulate the instruction "mul A,r2":
/       mfps    (sp)                    / get psw
/       mov     A,-(sp)                 / push multiplier onto the stack
/       mov     r2,-(sp)                / push multiplicand onto the stack
/       jsr     pc,times2               / call the simulation routine
/       mov     (sp)+,r2                / save the low word of the product
/       mov     (sp)+,r3                / save the high word of the product
/       mtps    (sp)                    / put in the new psw
/
/ code to simulate the instruction "mul A,r1":
/       mfps    (sp)                    / get psw
/       mov     A,-(sp)                 / push multiplier onto the stack
/       mov     r1,-(sp)                / push multiplicand onto the stack
/       jsr     pc,times2               / call the simulation routine
/       tst     (sp)+                   / throw away the high word of the product
/       mov     (sp)+,r1                / save the low word of the product
/       mtps    (sp)                    / put in the new psw
/
/ WARNING:
/ THIS ROUTINE DOES NOT FOLLOW THE CALLING CONVENTIONS OF C. DO NOT CALL THIS
/ USING THE USUAL C CONVENTIONS; USE THE CALLING SEQUENCE GIVEN ABOVE.
/
/ ASSUMPTIONS:
/ the stack must be set up correctly
/ the routine must be called via "jsr pc,over2" since it uses "rts pc"
/       to return
/
/ AUTHOR:
/ Matt Bishop
/ Department of Computer Sciences
/ Purdue University
/ West Lafayette, IN  47907
/
/ Version 1, October 30, 1981
/
/
/ CONSTANTS
lr=sp           / linkage register
                / stack allocation ... parameter variables
                /       position on stack after r0 - r5 are pushed
spsw=22                 / psw (on entry and exit)
sblow=20                / multiplicand (on entry)
splow=20                / low word of product (on exit)
sa=16                   / multiplier (on entry)
sphigh=16               / high word of product (on exit)
                / register allocation
rphigh=r0               / high word of product
rplow=r1                / low word of product
rbhigh=r2               / high word of multiplicand
rblow=r3                / low word of multiplicand
ra=r4                   / multiplier
rpsw=r5                 / psw
/
/*** declare the routine name to be global so anyone can use it
.globl  times2
.text
times2:
/*** push the registers onto the stack
        mov     r0,-(sp)
        mov     r1,-(sp)
        mov     r2,-(sp)
        mov     r3,-(sp)
        mov     r4,-(sp)
        mov     r5,-(sp)
/*** set up registers and initialize condition codes
        clr     rphigh                  / clear product
        clr     rplow
        clr     rbhigh                  / clear high word of multiplier
        mov     sblow(lr),rblow         / get low word of multiplier
        mov     spsw(lr),rpsw           / get psw, clobber present condition
        bic     $17,rpsw                /   codes
        mov     sa(lr),ra               / get multiplier
/*** handle cases where multiplier is negative or 0
        bgt     apos
        beq     zero
        bis     $10,rpsw                / set N in psw
        neg     ra                      / make it positive
/*** handle cases where multiplicand is negative or 0
apos:   tst     rblow                   / need only test low word (high one
        bgt     muloop                  /   is 0 here)
        beq     zero
        mov     $10,rbhigh              / exclusive-or a negative condition
        xor     rbhigh,rpsw             /   code with the current one; this
        clr     rbhigh                  /     sets it correctly
        neg     rblow                   / make multiplicand positive
/*** do the multiply
muloop: asr     ra                      / shift multiplier
        bcc     nxtbit                  / test bit shifted out; if 1, add
        add     rblow,rplow             /   multiplicand to product (double
        adc     rphigh                  /     precision add)
        add     rbhigh,rphigh
nxtbit: asl     rblow                   / shift multiplicand (double pre-
        rol     rbhigh                  /   cision shift)
        tst     ra                      / continue this until multiplier
        bne     muloop                  /   is 0
/*** set the sign of the product
        bit     $10,rpsw                / if positive, check for overflow
        beq     ovflo
/*** check for overflow from a negative number
        tst     rphigh                  / if high word 0, negative product
        beq     mpneg                   /   did not overflow
        bis     $1,rpsw
mpneg:  neg     rplow                   / negate the product (to conform to
        neg     rphigh                  /   the condition code; use a double
        sbc     rphigh                  /     precision negation)
        br      out                     / adios, amigo!
/*** handle a zero factor
zero:   bic     $17,rpsw                / clear all condition codes
        bis     $4,rpsw                 / set the Z bit
        br      out                     / au revoir, mon ami!
/*** check for overflow from a positive number
ovflo:  tst     rphigh                  / test positive product for overflow
        bne     setcc                   /   (note you have to test the high
        cmp     $77777,rplow            /     word and see if the low word is
        bhi     out                     /       <= 2^15 - 1 (sign bit)
setcc:  bis     $1,rpsw                 / on overflow, set the C bit
/*** restore the registers after saving results
out:    mov     rpsw,spsw(lr)           / save psw
        mov     rplow,splow(lr)         / save product
        mov     rphigh,sphigh(lr)
        mov     (lr)+,r5                / restore registers
        mov     (lr)+,r4
        mov     (lr)+,r3
        mov     (lr)+,r2
        mov     (lr)+,r1
        mov     (lr)+,r0
        rts     pc                      / do svidanya, tovarishch!
.data