Browse Source

* use BLX instead of "mov r14, r15; mov r15, reg" for a_call_reg on ARMv6
and above, so this also works when calling thumb code (should actually
also be done for ARMv5T, but we don't have a monicker for that yet)
* use BX instead of "mov r15, r14" for simple returns from subroutines
on ARMv6+ to support returning to thumb code from ARM code (idem)

git-svn-id: trunk@14332 -

Jonas Maebe 15 years ago
parent
commit
fbebd87593
5 changed files with 95 additions and 17 deletions
  1. 18 6
      compiler/arm/cgcpu.pas
  2. 58 10
      rtl/arm/arm.inc
  3. 16 0
      rtl/arm/divide.inc
  4. 2 0
      rtl/arm/mathu.inc
  5. 1 1
      rtl/arm/setjump.inc

+ 18 - 6
compiler/arm/cgcpu.pas

@@ -527,8 +527,14 @@ unit cgcpu;
 
 
     procedure tcgarm.a_call_reg(list : TAsmList;reg: tregister);
     procedure tcgarm.a_call_reg(list : TAsmList;reg: tregister);
       begin
       begin
-        list.concat(taicpu.op_reg_reg(A_MOV,NR_R14,NR_PC));
-        list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,reg));
+        { check not really correct: should only be used for non-Thumb cpus }
+        if (current_settings.cputype<cpu_armv6) then
+          begin
+            list.concat(taicpu.op_reg_reg(A_MOV,NR_R14,NR_PC));
+            list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,reg));
+          end
+        else
+          list.concat(taicpu.op_reg(A_BLX, reg));
 {
 {
         the compiler does not properly set this flag anymore in pass 1, and
         the compiler does not properly set this flag anymore in pass 1, and
         for now we only need it after pass 2 (I hope) (JM)
         for now we only need it after pass 2 (I hope) (JM)
@@ -543,8 +549,7 @@ unit cgcpu;
       begin
       begin
         a_reg_alloc(list,NR_R12);
         a_reg_alloc(list,NR_R12);
         a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,NR_R12);
         a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,NR_R12);
-        list.concat(taicpu.op_reg_reg(A_MOV,NR_R14,NR_PC));
-        list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R12));
+        a_call_reg(list,NR_R12);
         a_reg_dealloc(list,NR_R12);
         a_reg_dealloc(list,NR_R12);
         include(current_procinfo.flags,pi_do_call);
         include(current_procinfo.flags,pi_do_call);
       end;
       end;
@@ -1653,7 +1658,12 @@ unit cgcpu;
                   end;
                   end;
 
 
                 if regs=[] then
                 if regs=[] then
-                  list.concat(taicpu.op_reg_reg(A_MOV,NR_R15,NR_R14))
+                  begin
+                    if (current_settings.cputype<cpu_armv6) then
+                      list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R14))
+                    else
+                      list.concat(taicpu.op_reg(A_BX,NR_R14))
+                  end
                 else
                 else
                   begin
                   begin
                     reference_reset(ref,4);
                     reference_reset(ref,4);
@@ -1670,8 +1680,10 @@ unit cgcpu;
                 list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,R_INTREGISTER,R_SUBWHOLE,regs),PF_EA));
                 list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,R_INTREGISTER,R_SUBWHOLE,regs),PF_EA));
               end;
               end;
           end
           end
+        else if (current_settings.cputype<cpu_armv6) then
+          list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R14))
         else
         else
-          list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R14));
+          list.concat(taicpu.op_reg(A_BX,NR_R14))
       end;
       end;
 
 
 
 

+ 58 - 10
rtl/arm/arm.inc

@@ -137,7 +137,11 @@ Procedure FillChar(var x;count:longint;value:byte);assembler;nostackframe;
 asm
 asm
         // less than 0?
         // less than 0?
         cmp r1,#0
         cmp r1,#0
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
         movlt pc,lr
         movlt pc,lr
+{$else}
+        bxlt  lr
+{$endif}
         mov     r3,r0
         mov     r3,r0
         cmp     r1,#8           // at least 8 bytes to do?
         cmp     r1,#8           // at least 8 bytes to do?
         blt     .LFillchar2
         blt     .LFillchar2
@@ -168,7 +172,11 @@ asm
         bge     .LFillchar1
         bge     .LFillchar1
 .LFillchar2:
 .LFillchar2:
         movs r1,r1              // anything left?
         movs r1,r1              // anything left?
-        moveq pc,lr
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+        moveq   pc,lr
+{$else}
+        bxeq    lr
+{$endif}
         rsb     r1,r1,#7
         rsb     r1,r1,#7
         add     pc,pc,r1,lsl #2
         add     pc,pc,r1,lsl #2
         mov     r0,r0
         mov     r0,r0
@@ -179,7 +187,11 @@ asm
         strb r2,[r3],#1
         strb r2,[r3],#1
         strb r2,[r3],#1
         strb r2,[r3],#1
         strb r2,[r3],#1
         strb r2,[r3],#1
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
         mov pc,lr
         mov pc,lr
+{$else}
+        bx  lr
+{$endif}
 end;
 end;
 {$endif FPC_SYSTEM_HAS_FILLCHAR}
 {$endif FPC_SYSTEM_HAS_FILLCHAR}
 
 
@@ -191,7 +203,11 @@ asm
   pld [r1]
   pld [r1]
   // count <=0 ?
   // count <=0 ?
   cmp r2,#0
   cmp r2,#0
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
   movle pc,lr
   movle pc,lr
+{$else}
+  bxle  lr
+{$endif}
   // overlap?
   // overlap?
   cmp r1,r0
   cmp r1,r0
   bls .Lnooverlap
   bls .Lnooverlap
@@ -204,7 +220,11 @@ asm
   ldrb r3,[r0,r2]
   ldrb r3,[r0,r2]
   strb r3,[r1,r2]
   strb r3,[r1,r2]
   bne .Loverlapped
   bne .Loverlapped
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
   mov pc,lr
   mov pc,lr
+{$else}
+  bx  lr
+{$endif}
 .Lnooverlap:
 .Lnooverlap:
   // less then 16 bytes to copy?
   // less then 16 bytes to copy?
   cmp r2,#8
   cmp r2,#8
@@ -247,20 +267,32 @@ asm
   str r3,[r1],#4
   str r3,[r1],#4
   bcs .Ldwordloop
   bcs .Ldwordloop
   cmp r2,#0
   cmp r2,#0
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
   moveq pc,lr
   moveq pc,lr
+{$else}
+  bxeq  lr
+{$endif}
 .Lbyteloop:
 .Lbyteloop:
   subs r2,r2,#1
   subs r2,r2,#1
   ldrb r3,[r0],#1
   ldrb r3,[r0],#1
   strb r3,[r1],#1
   strb r3,[r1],#1
   bne .Lbyteloop
   bne .Lbyteloop
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
   mov pc,lr
   mov pc,lr
+{$else}
+  bx  lr
+{$endif}
 end;
 end;
 
 
 procedure Move_blended(const source;var dest;count:longint);assembler;nostackframe;
 procedure Move_blended(const source;var dest;count:longint);assembler;nostackframe;
 asm
 asm
   // count <=0 ?
   // count <=0 ?
   cmp r2,#0
   cmp r2,#0
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
   movle pc,lr
   movle pc,lr
+{$else}
+  bxle  lr
+{$endif}
   // overlap?
   // overlap?
   cmp r1,r0
   cmp r1,r0
   bls .Lnooverlap
   bls .Lnooverlap
@@ -273,7 +305,11 @@ asm
   ldrb r3,[r0,r2]
   ldrb r3,[r0,r2]
   strb r3,[r1,r2]
   strb r3,[r1,r2]
   bne .Loverlapped
   bne .Loverlapped
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
   mov pc,lr
   mov pc,lr
+{$else}
+  bx  lr
+{$endif}
 .Lnooverlap:
 .Lnooverlap:
   // less then 16 bytes to copy?
   // less then 16 bytes to copy?
   cmp r2,#8
   cmp r2,#8
@@ -311,13 +347,21 @@ asm
   str r3,[r1],#4
   str r3,[r1],#4
   bcs .Ldwordloop
   bcs .Ldwordloop
   cmp r2,#0
   cmp r2,#0
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
   moveq pc,lr
   moveq pc,lr
+{$else}
+  bxeq  lr
+{$endif}
 .Lbyteloop:
 .Lbyteloop:
   subs r2,r2,#1
   subs r2,r2,#1
   ldrb r3,[r0],#1
   ldrb r3,[r0],#1
   strb r3,[r1],#1
   strb r3,[r1],#1
   bne .Lbyteloop
   bne .Lbyteloop
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
   mov pc,lr
   mov pc,lr
+{$else}
+  bx  lr
+{$endif}
 end;
 end;
 
 
 
 
@@ -492,7 +536,11 @@ asm
       terminating 0, due to the known carry flag sbc can do this.*)
       terminating 0, due to the known carry flag sbc can do this.*)
     sbc r0,r1,r0
     sbc r0,r1,r0
 .Ldone:
 .Ldone:
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
     mov pc,lr
     mov pc,lr
+{$else}
+    bx  lr
+{$endif}
 .L01010101:
 .L01010101:
     .long 0x01010101
     .long 0x01010101
 end;
 end;
@@ -512,7 +560,7 @@ asm
   cmp r2, #0
   cmp r2, #0
   bne .Lloop
   bne .Lloop
   mov r0, r1
   mov r0, r1
-  mov pc, lr
+  bx  lr
 {$else}
 {$else}
 // lock
 // lock
   ldr r3, .Lfpc_system_lock
   ldr r3, .Lfpc_system_lock
@@ -528,7 +576,7 @@ asm
   mov r0, r1
   mov r0, r1
 // unlock and return
 // unlock and return
   str r2, [r3]
   str r2, [r3]
-  mov pc, lr
+  bx  lr
 
 
 .Lfpc_system_lock:
 .Lfpc_system_lock:
   .long fpc_system_lock
   .long fpc_system_lock
@@ -546,7 +594,7 @@ asm
   cmp r2, #0
   cmp r2, #0
   bne .Lloop
   bne .Lloop
   mov r0, r1
   mov r0, r1
-  mov pc, lr
+  bx  lr
 {$else}
 {$else}
 // lock
 // lock
   ldr r3, .Lfpc_system_lock
   ldr r3, .Lfpc_system_lock
@@ -562,7 +610,7 @@ asm
   mov r0, r1
   mov r0, r1
 // unlock and return
 // unlock and return
   str r2, [r3]
   str r2, [r3]
-  mov pc, lr
+  bx  lr
 
 
 .Lfpc_system_lock:
 .Lfpc_system_lock:
   .long fpc_system_lock
   .long fpc_system_lock
@@ -580,7 +628,7 @@ asm
   cmp r3, #0
   cmp r3, #0
   bne .Lloop
   bne .Lloop
   mov r0, r2
   mov r0, r2
-  mov pc, lr
+  bx  lr
 {$else}
 {$else}
   swp r1, r1, [r0]
   swp r1, r1, [r0]
   mov r0,r1
   mov r0,r1
@@ -597,7 +645,7 @@ asm
   cmp r3, #0
   cmp r3, #0
   bne .Lloop
   bne .Lloop
   mov  r0, r2
   mov  r0, r2
-  mov pc, lr
+  bx  lr
 {$else}
 {$else}
 // lock
 // lock
   ldr r3, .Lfpc_system_lock
   ldr r3, .Lfpc_system_lock
@@ -614,7 +662,7 @@ asm
 // unlock and return
 // unlock and return
   mov r2, #0
   mov r2, #0
   str r2, [r3]
   str r2, [r3]
-  mov pc, lr
+  bx  lr
 
 
 .Lfpc_system_lock:
 .Lfpc_system_lock:
   .long fpc_system_lock
   .long fpc_system_lock
@@ -633,7 +681,7 @@ asm
   cmp      r12, #0
   cmp      r12, #0
   bne      .Lloop
   bne      .Lloop
   mov      r0, r3
   mov      r0, r3
-  mov      pc, lr
+  bx       lr
 {$else}
 {$else}
 // lock
 // lock
   ldr r12, .Lfpc_system_lock
   ldr r12, .Lfpc_system_lock
@@ -650,7 +698,7 @@ asm
 // unlock and return
 // unlock and return
   mov r3, #0
   mov r3, #0
   str r3, [r12]
   str r3, [r12]
-  mov pc, lr
+  bx  lr
 
 
 .Lfpc_system_lock:
 .Lfpc_system_lock:
   .long fpc_system_lock
   .long fpc_system_lock

+ 16 - 0
rtl/arm/divide.inc

@@ -107,12 +107,20 @@ asm
 .Ldiv_next:
 .Ldiv_next:
   bcs .Ldiv_loop
   bcs .Ldiv_loop
   mov r0, r3
   mov r0, r3
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
   mov pc, lr
   mov pc, lr
+{$else}
+  bx  lr
+{$endif}
 .Ldiv_by_0:
 .Ldiv_by_0:
   mov r0, #200
   mov r0, #200
   mov r1, r11
   mov r1, r11
   bl handleerrorframe
   bl handleerrorframe
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
   mov pc, lr
   mov pc, lr
+{$else}
+  bx  lr
+{$endif}
   {$endif}
   {$endif}
   {$else}
   {$else}
   mov r3, #0
   mov r3, #0
@@ -167,12 +175,20 @@ asm
 .Ldiv_next:
 .Ldiv_next:
   bcs .Ldiv_loop
   bcs .Ldiv_loop
   mov r0, r3
   mov r0, r3
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
   mov pc, lr
   mov pc, lr
+{$else}
+  bx  lr
+{$endif}
 .Ldiv_by_0:
 .Ldiv_by_0:
   mov r0, #200
   mov r0, #200
   mov r1, r11
   mov r1, r11
   bl handleerrorframe
   bl handleerrorframe
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
   mov pc, lr
   mov pc, lr
+{$else}
+  bx  lr
+{$endif}
   {$endif}
   {$endif}
 end;
 end;
 
 

+ 2 - 0
rtl/arm/mathu.inc

@@ -307,6 +307,7 @@ function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
   begin
   begin
     cw:=VFP_GetCW and not(_VFP_ENABLE_ALL);
     cw:=VFP_GetCW and not(_VFP_ENABLE_ALL);
 
 
+{$ifndef darwin}
     if exInvalidOp in Mask then
     if exInvalidOp in Mask then
       cw:=cw or _VFP_ENABLE_IM;
       cw:=cw or _VFP_ENABLE_IM;
 
 
@@ -324,6 +325,7 @@ function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
 
 
     if exPrecision in Mask then
     if exPrecision in Mask then
       cw:=cw or _VFP_ENABLE_PM;
       cw:=cw or _VFP_ENABLE_PM;
+{$endif}
     VFP_SetCW(cw);
     VFP_SetCW(cw);
     result:=Mask;
     result:=Mask;
 
 

+ 1 - 1
rtl/arm/setjump.inc

@@ -34,7 +34,7 @@ function setjmp(var S : jmp_buf) : longint;assembler;[Public, alias : 'FPC_SETJM
     {$else}
     {$else}
     stmia   r0,{v1-v6, sl, fp, sp, lr}
     stmia   r0,{v1-v6, sl, fp, sp, lr}
     mov     r0,#0
     mov     r0,#0
-    mov     pc,lr
+    bx      lr
     {$endif}
     {$endif}
   end;
   end;