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?