* 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:
Jonas Maebe 2009-12-04 22:38:50 +00:00
parent fa42b022d2
commit fbebd87593
5 changed files with 95 additions and 17 deletions

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;