Reply by Wilco Dijkstra●October 29, 20082008-10-29
<luken8r@gmail.com> wrote in message news:a91c3ce2-9fcb-4c1f-a524-96b49436379a@u75g2000hsf.googlegroups.com...
... 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 by ●October 29, 20082008-10-29
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
<rest of code>
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
<rest of code>
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?