;----------------------------------------------------------------- ; EX76.ASM Computing Powers. ; Parameter Passing via Reserved Memory. ; ; C.P. Diduch 2001 ; ; This program calls procedure POWER() to compute Z = Y**N where ; Z, Y and N are passed as reserved memory (or global) variables. ; POWER() calls procedure MULT() N-times. Y is loaded from ; input port 0x0000, N is loaded from input port 0x0001 and Z is ; written to output port 0x0002. ; ; Author(s): ; Signature(s): Date: ; ;----------------------------------------------------------------- ; STACK and VARIABLES ; .ORG 0x0000 ; // Variable assignments in RAM. .DS 10 ; // Reserve RAM for the stack. TOS: .DS 1 ; Z: .DS 1 ; unsigned Z, Y, N, OVFLOW ; Y: .DS 1 ; N: .DS 1 ; OVFLOW: .DS 1 ; ;----------------------------------------------------------------- ; MAIN PROGRAM ; void main(void) { ; .ORG 0x8000 ; "assign the following to ROM" ; ADDL SP, NULL, TOS ; "initialize stack pointer" ; do { M0: LOADP R0, 0x0000 ; Y = inport(0x0000); STOREM Y, R0 ; ; LOADP R0, 0x0001 ; N = inport(0x0001); STOREM N, R0 ; ; CALL POWER, RA ; Z = POWER(Y, N); LOADM R0, Z ; STOREP 0x0002, R0 ; outport(0x0002, Z); JMP M0 ; } ; } ;----------------------------------------------------------------- ; PROCEDURE void POWER(void) ; ; POWER() computes Z = Y**N where Z, Y and N are passed as ; unsigned global variables. The unsigned global variable OVFLOW ; is set to 1 if an overflow occurs otherwise it is reset to 0. ; ; Typical CALL/LINKAGE sequence ; ; STOREM Y, VALUE0 ; STOREM N, VALUE1 ; CALL POWER, RA ; LOADM DEST, Z ; ; Calls : MULT(). ; Called by : main(). ; Registers affected : R0, R1, R2, R3, R4, R5, R6 and FL. ; Stack depth : 2 words. ;----------------------------------------------------------------- POWER: ; POWER() { SUBL SP, SP, 1 ; "save status" : push RA DSTOREM (SP), RA ; ; ADDL R0, NULL, 0 ; OVFLOW = 0 ; STOREM OVFLOW, R0 ; ADDL R0, NULL, 1 ; Z = 1 ; STOREM Z, R0 ; ; P0: LOADM R0, N ; while ((N != 0) SUBL NULL, R0, 0 ; && (OVFLOW != 1)) { JMPZ P2 ; ; LOADM R0, OVFLOW ; SUBL NULL, R0, 1 ; JMPZ P2 ; ; LOADM R0, N ; N = N - 1 ; SUBL R0, R0, 1 ; STOREM N, R0 ; ; LOADM R0, Z ; [R4, R3] = MULT(Z, Y) ; LOADM R1, Y ; CALL MULT, RA ; STOREM Z, R3; ; Z = R3 ; // LSB's of product. ; SUBL NULL, R4, 0 ; if (R4 != 0) { JMPZ P1 ; OVFLOW = 1; ADDL R0, NULL, 1 ; STOREM OVFLOW, R0 ; ADDL R0, NULL, 0xFFFF; Z = 0xFFFF; STOREM Z, R0; ; } P1: JMP P0 ; } ; P2: DLOADM RA, (SP) ; // Restore Status: Pop RA ADDL SP, SP, 1 ; DJMP (RA) ; } ;----------------------------------------------------------------- ; PROCEDURE unsigned long MULT(unsigned R0, unsigned R1) ; ; MULT() computes the 32-bit product [R4, R3] = R0 * R1. R1 and ; R2 are passed as unsigned register variables. The 16-MSB's of ; the product are returned in register R4 and the 16-LSB's of ; the product are returned in register R3. ; ; Typical CALL/LINKAGE sequence ; ; ADDL R0, NULL, multiplier ; ADDL R1, NULL, multiplicand ; CALL MULT, RA ; STOREM MSB, R4 ; STOREM LSB, R3 ; ; Calls : no procedures. ; Called by : POWER(). ; Registers affected : R6, R5, R4, R3, R2 and FL. ; Stack depth : 1 word. ;----------------------------------------------------------------- MULT: ; unsigned long MULT(unsigned R0, unsigned R1) { ; SUBL SP, SP, 1 ; "save status" : push RA DSTOREM (SP), RA ; XOR R5, R5, R5 ; i = 0 ; // Reg, var. in R5. XOR R4, R4, R4 ; [R4, R3] = 0 ; XOR R3, R3, R3 ; XOR R2, R2, R2 ; R2 = 0 ; ADDL R6, NULL, 1 ; MASK = 0x0001 ; ; MU1: SUBL NULL, R5, 16 ; while (i < 16) { JMPNC MU4 ; AND NULL, R6, R0 ; if(Bit-i of R0 == 1) { JMPZ MU2 ; ADD R4, R4, R2 ; R4 = R4 + R2 ; ADD R3, R3, R1 ; R3 = R3 + R1 ; JMPNC MU2 ; if (CY) {R4 = R4 + 1 ; } ADDL R4, R4, 1 ; } ; MU2: SHIFTU R2, R2, 1(NULL) ; [R2, R1] = [R2, R1] << 1; SHIFTU R1, R1, 1(NULL) ; JMPNC MU3 ; ADDL R2, R2, 1 ; ; MU3: ADDL R5, R5, 1 ; i = i + 1; SHIFTU R6, R6, 1(NULL) ; MASK = MASK << 1; JMP MU1 ; } ; MU4: DLOADM RA, (SP) ; "restore status" : pop RA ADDL SP, SP, 1 ; DJMP (RA) ; }