瀏覽代碼

* 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 年之前
父節點
當前提交
fbebd87593
共有 5 個文件被更改,包括 95 次插入17 次删除
  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);
       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
         for now we only need it after pass 2 (I hope) (JM)
@@ -543,8 +549,7 @@ unit cgcpu;
       begin
         a_reg_alloc(list,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);
         include(current_procinfo.flags,pi_do_call);
       end;
@@ -1653,7 +1658,12 @@ unit cgcpu;
                   end;
 
                 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
                   begin
                     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));
               end;
           end
+        else 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_reg(A_MOV,NR_PC,NR_R14));
+          list.concat(taicpu.op_reg(A_BX,NR_R14))
       end;
 
 

+ 58 - 10
rtl/arm/arm.inc

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

+ 16 - 0
rtl/arm/divide.inc

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

+ 2 - 0
rtl/arm/mathu.inc

@@ -307,6 +307,7 @@ function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
   begin
     cw:=VFP_GetCW and not(_VFP_ENABLE_ALL);
 
+{$ifndef darwin}
     if exInvalidOp in Mask then
       cw:=cw or _VFP_ENABLE_IM;
 
@@ -324,6 +325,7 @@ function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
 
     if exPrecision in Mask then
       cw:=cw or _VFP_ENABLE_PM;
+{$endif}
     VFP_SetCW(cw);
     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}
     stmia   r0,{v1-v6, sl, fp, sp, lr}
     mov     r0,#0
-    mov     pc,lr
+    bx      lr
     {$endif}
   end;