Skip to navigation

Lander on the Acorn Archimedes

Maths (Geometry): GetMouseInPolarCoordinates (Part 2 of 2)

Name: GetMouseInPolarCoordinates (Part 2 of 2) [Show more] Type: Subroutine Category: Maths (Geometry) Summary: Calculate the polar distance Deep dive: Flying by mouse
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file
LDMFD R13!, {R0, R2} \ Retrieve the values we put on the stack \ earlier, so: \ \ R0 = |xMouse| \ \ R2 = |yMouse| \ We now calculate R4 = R0 * R0 using the \ shift-and-add multiplication algorithm, \ which calculates: \ \ R4 = R0 ^ 2 \ = |xMouse| ^ 2 MOV R3, R0 \ Set R3 = 2 * R0 MOVS R3, R3, LSL #1 \ = 2 * |xMouse| \ \ So now we calculate R4 = R3 * R0 to get \ our result AND R3, R3, #&FE000000 \ Zero all but the top byte of R3, ensuring ORR R3, R3, #&01000000 \ that bit 0 of the top byte is set so the \ value of the fractional part is set to 0.5 MOV R4, #0 \ Set R4 = 0 to use for building the sum in \ our shift-and-add multiplication result .pole5 MOV R0, R0, LSR #1 \ If bit 0 of R0 is set, add R0 to the ADDHS R4, R4, R0 \ result in R4, shifting R0 to the right MOVS R3, R3, LSL #1 \ Shift R3 left by one place BNE pole5 \ Loop back if R3 is non-zero \ Next we calculate R14 = R2 * R2 using the \ shift-and-add multiplication algorithm, \ which calculates: \ \ R14 = R2 ^ 2 \ = |yMouse| ^ 2 MOV R3, R2 \ Set R3 = 2 * R2 MOVS R3, R3, LSL #1 \ = 2 * |yMouse| \ \ So now we calculate R14 = R3 * R2 to get \ our result AND R3, R3, #&FE000000 \ Zero all but the top byte of R3, ensuring ORR R3, R3, #&01000000 \ that bit 0 of the top byte is set so the \ value of the top byte is at least 1 MOV R14, #0 \ Set R14 = 0 to use for building the sum in \ our shift-and-add multiplication result .pole6 MOV R2, R2, LSR #1 \ If bit 0 of R2 is set, add R2 to the ADDHS R14, R14, R2 \ result in R14, shifting R2 to the right MOVS R3, R3, LSL #1 \ Shift R3 left by one place BNE pole6 \ Loop back if R3 is non-zero \ So by this point we have the following: \ \ R4 = |xMouse| ^ 2 \ \ R14 = |yMouse| ^ 2 \ \ So now we can apply Pythagoras to find the \ length of the hypotenuse, which is the \ distance in our polar coordinate, as in \ the example where x >= y: \ \ .| \ R0 .´ | \ .´ | y \ .´R1 | \ +´-------+ \ x \ \ We calculate the distance in R0 ADD R2, R14, R4 \ Set R2 = R14 + R4 \ \ = |xMouse| ^ 2 + |yMouse| ^ 2 LDR R14, squareRootTableAddr \ Set R14 to the address of the square root \ lookup table BIC R2, R2, #&00300000 \ Clear bits 20 and 21 of R2 so when we \ shift R2 to the right by 20 places in the \ following lookup, the address is aligned \ to the words in the lookup table LDR R0, [R14, R2, LSR #20] \ Set R0 = SQRT(R2) \ = SQRT(|xMouse| ^ 2 + |yMouse| ^ 2) \ \ which is the length of the hypotenuse and \ the distance in our polar coordinate LDMFD R13!, {PC} \ Return from the subroutine LDMIA R0, {R0-R2} \ This instruction appears to be unused