ARM7 16 bit LR move

Im trying to copy the LR to R0 to return the calling function's address to some other function, but Im coming with some issues. Im modifying my division libraries to detect a divide by zero and return the calling function's address back to another function to record the initial division's address I have two similar assembly functions, one 32 bit which works fine, and a 16 bit which does not. The 32 bit div function looks something like this:

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

.state32

.global U_DIV .global U_MOD .global _div_zero

dvs .set r2 ; WORK COPY OF THE DIVISOR (SHIFTED) quo .set lr ; WORK COPY OF THE QUOTIENT osp .set r3

U_DIV: U_MOD: STMFD sp!, {dvs, lr} ; SAVE CONTEXT

MOVS dvs, r1 ; CHECK FOR DIVISION BY ZERO BEQ div_by_zero

div_by_zero:

MOV a1, LR ; Copy LR to A1 to return to div_zero BL _div_zero ; Call to div_zero MOV r0, #0 ; LDMFD sp!, {dvs, pc} ;

.end

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

This works fine. My div_zero function gets the address stored in the LR and I can do what I want with it. I try to do something similar with the 16 bit and the same code crashes. Unfortunately, I dont have an emulator, so Im trying this blind :/

The 16 bit code looks something like this

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

.state16 .align ; REQUIRED SO ADD PC IS WORD ALIGNED BELOW

.global U$DIV .global U$MOD .global _div_zero

dvs .set r2 ; WORK COPY OF THE DIVISOR (SHIFTED) quo .set r3 ; WORK COPY OF THE QUOTIENT tmp .set r4

U$DIV: U$MOD: PUSH {r2-r4} ; SAVE CONTEXT

MOV dvs, r1 ; INITIALIZE THE DIVISOR (SHIFTED) BEQ div_by_zero

div_by_zero:

MOV A1, LR BL _div_zero MOV r0, #10 ; DIVIDE BY ZERO RETURNS ZERO POP {r2-r4} MOV pc, lr

.end

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D resulting list file =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 37 00000000 U$DIV: 38 00000000 B41C U$MOD: PUSH {r2-r4} 39 40 00000002 1C0A MOV dvs, r1 41 00000004 D044 BEQ div_by_zero 42

126 00000090 div_by_zero: 127 145 =3D=3D> 146 00000090 4670 MOV A1, LR =3D=3D> 147 =3D=3D> 148 00000092 F7FF! BL $div_zero =3D=3D> 00000094 FFB5 149 152 153 00000096 200A MOV r0, #10 154 00000098 BC1C POP {r2-r4} 155 157 158 0000009a 46F7 MOV pc, lr 159 160 .end

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

According to the PDF I have "TMS470R1x User=92s Guide"

A value may be transferred from a register in the range R0-R7 (a Lo register) to a Hi register, and from a Hi register to a Lo register, using special variants of the MOV instruction. Hi register values can also be compared against or added to Lo register values with the CMP and ADD instructions. See Section 5.5, Format 5: Hi register operations/branch exchange, 5-14.

Is this the proper usage of transferring a HI reg (LR/R14) to a LO reg (A1)? Am I going about this the right way? Is this how to pass the LR back to a function in 16 bit?

Reply to
luken8r
Loading thread data ...

... snipped long posting

You forgot to push LR in the Thumb code that handles division by zero or alternatively restore LR by copying r4 (a1) back to LR if your _div_zero function returns and doesn't corrupt r4. Note you should always return using bx lr, never mov pc,lr. You can also avoid pushing registers on the fast path - division doesn't need any registers besides R0-R3 and R12.

Wilco

Reply to
Wilco Dijkstra

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.