Skip to navigation

Lander on the Acorn Archimedes

Maths (Geometry): MultiplyVectorByConstant

Name: MultiplyVectorByConstant [Show more] Type: Subroutine Category: Maths (Geometry) Summary: An unused routine that multiplies a vector by a constant value Deep dive: Unused code in Lander
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file

Arguments: R0 The constant value to multiply the vector by R1 The address of the three-word vector, plus a counter word
Returns: xVertexRotated The result of the multiplication, followed by the incremented counter
.MultiplyVectorByConstant STMFD R13!, {R5-R8, R14} \ Store the registers that we want to use on \ the stack so they can be preserved LDMIA R1, {R1-R3, R14} \ Fetch R1, R2, R3 and R14 from address R1 MOV R8, R0 \ Set R8 = R0 \ We now calculate R5 = R8 * R1 using the \ shift-and-add multiplication algorithm EOR R4, R8, R1 \ Set the sign of the result in R4 TEQ R8, #0 \ Set R8 = 4 * |R8| RSBMI R8, R8, #0 MOVS R8, R8, LSL #2 TEQ R1, #0 \ Set R1 = 2 * |R1| RSBMI R1, R1, #0 MOV R1, R1, LSL #1 AND R8, R8, #&FE000000 \ Zero all but the top byte of R8, ensuring ORR R8, R8, #&01000000 \ that bit 0 of the top byte is set so the \ value of the fractional part is set to 0.5 MOV R5, #0 \ Set R5 = 0 to use for building the sum in \ our shift-and-add multiplication result .vcon1 MOV R1, R1, LSR #1 \ If bit 0 of R1 is set, add R1 to the ADDCS R5, R5, R1 \ result in R5, shifting R1 to the right MOVS R8, R8, LSL #1 \ Shift R8 left by one place BNE vcon1 \ Loop back if R8 is non-zero MOV R5, R5, LSR #1 \ Set R5 = R5 / 2 TEQ R4, #0 \ Apply the sign from R4 to R5 to get the RSBMI R5, R5, #0 \ final result, so: \ \ R5 = R8 * R1 \ = R0 * R1 MOV R8, R0 \ Set R8 = R0 EOR R4, R8, R2 \ Set R6 = R8 * R2 using the same algorithm TEQ R8, #0 \ as above RSBMI R8, R8, #0 \ MOVS R8, R8, LSL #2 \ This is the first part of the algorithm TEQ R2, #0 RSBMI R2, R2, #0 MOV R2, R2, LSL #1 AND R8, R8, #&FE000000 ORR R8, R8, #&01000000 MOV R6, #0 .vcon2 MOV R2, R2, LSR #1 \ This is the second part of the algorithm, ADDCS R6, R6, R2 \ so we now have: MOVS R8, R8, LSL #1 \ BNE vcon2 \ R4 = R8 * R2 MOV R6, R6, LSR #1 \ = R0 * R2 TEQ R4, #0 RSBMI R6, R6, #0 MOV R8, R0 \ Set R8 = R0 EOR R4, R8, R3 \ Set R7 = R8 * R3 using the same algorithm TEQ R8, #0 \ as above RSBMI R8, R8, #0 \ MOVS R8, R8, LSL #2 \ This is the first part of the algorithm TEQ R3, #0 RSBMI R3, R3, #0 MOV R3, R3, LSL #1 AND R8, R8, #&FE000000 ORR R8, R8, #&01000000 MOV R7, #0 .vcon3 MOV R3, R3, LSR #1 \ This is the second part of the algorithm, ADDCS R7, R7, R3 \ so we now have: MOVS R8, R8, LSL #1 \ BNE vcon3 \ R7 = R8 * R3 MOV R7, R7, LSR #1 \ = R0 * R3 TEQ R4, #0 RSBMI R7, R7, #0 ADD R14, R14, #2 \ Set R14 = R14 + 2 ADD R8, R11, #xVertexRotated \ Store (R5, R6, R7) and the updated R14 in STMIA R8, {R5-R7, R14} \ xVertexRotated LDMFD R13!, {R5-R8, PC} \ Retrieve the registers that we stored on \ the stack and return from the subroutine