mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-16 18:19:16 +02:00
* 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 -
This commit is contained in:
parent
fa42b022d2
commit
fbebd87593
@ -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));
|
{ check not really correct: should only be used for non-Thumb cpus }
|
||||||
list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,reg));
|
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));
|
a_call_reg(list,NR_R12);
|
||||||
list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,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;
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user