From 628d46f2d3f49dac4002946006c4e2b7ff5b5105 Mon Sep 17 00:00:00 2001 From: Jeppe Johansen Date: Sun, 21 Oct 2012 19:13:59 +0000 Subject: [PATCH] Fixed Bsf* functions on platforms that support RBIT Fixed stackframe epilogue code for Thumb2 to allow proper processing of interrupts git-svn-id: branches/laksen/arm-embedded@22813 - --- compiler/arm/cgcpu.pas | 81 ++++++++++++++-------------------------- compiler/arm/cpuinfo.pas | 8 ++-- rtl/inc/systemh.inc | 2 +- 3 files changed, 33 insertions(+), 58 deletions(-) diff --git a/compiler/arm/cgcpu.pas b/compiler/arm/cgcpu.pas index 0f9cbe4845..95d94267d5 100644 --- a/compiler/arm/cgcpu.pas +++ b/compiler/arm/cgcpu.pas @@ -160,8 +160,6 @@ unit cgcpu; procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override; procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override; - procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override; - function handle_load_store(list:TAsmList;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference):treference; override; procedure a_loadmm_reg_reg(list: TAsmList; fromsize, tosize : tcgsize;reg1, reg2: tregister;shuffle : pmmshuffle); override; @@ -1487,6 +1485,12 @@ unit cgcpu; list.Concat(taicpu.op_reg_reg_const(A_RSB,dst,dst,31)); list.Concat(taicpu.op_reg_reg_const(A_AND,dst,dst,255)); end + else if CPUARM_HAS_RBIT in cpu_capabilities[current_settings.cputype] then + begin + list.Concat(taicpu.op_reg_reg(A_RBIT,dst,src)); + list.Concat(taicpu.op_reg_reg(A_CLZ,dst,dst)); + list.Concat(taicpu.op_reg_reg(A_UXTB,dst,dst)); + end else internalerror(201209041); end; @@ -3782,71 +3786,42 @@ unit cgcpu; inc(stackmisalignment,4); stackmisalignment:=stackmisalignment mod current_settings.alignment.localalignmax; - if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then - begin - LocalSize:=current_procinfo.calc_stackframe_size; - if (LocalSize<>0) or - ((stackmisalignment<>0) and - ((pi_do_call in current_procinfo.flags) or - (po_assembler in current_procinfo.procdef.procoptions))) then - begin - localsize:=align(localsize+stackmisalignment,current_settings.alignment.localalignmax)-stackmisalignment; - if not(is_shifter_const(LocalSize,shift)) then - begin - a_reg_alloc(list,NR_R12); - a_load_const_reg(list,OS_ADDR,LocalSize,NR_R12); - list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R12)); - a_reg_dealloc(list,NR_R12); - end - else - begin - list.concat(taicpu.op_reg_reg_const(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize)); - end; - end; - if regs=[] then - list.concat(taicpu.op_reg_reg(A_MOV,NR_R15,NR_R14)) + LocalSize:=current_procinfo.calc_stackframe_size; + if (LocalSize<>0) or + ((stackmisalignment<>0) and + ((pi_do_call in current_procinfo.flags) or + (po_assembler in current_procinfo.procdef.procoptions))) then + begin + localsize:=align(localsize+stackmisalignment,current_settings.alignment.localalignmax)-stackmisalignment; + if not(is_shifter_const(LocalSize,shift)) then + begin + a_reg_alloc(list,NR_R12); + a_load_const_reg(list,OS_ADDR,LocalSize,NR_R12); + list.concat(taicpu.op_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_R12)); + a_reg_dealloc(list,NR_R12); + end else begin - reference_reset(ref,4); - ref.index:=NR_STACK_POINTER_REG; - ref.addressmode:=AM_PREINDEXED; - list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,R_INTREGISTER,R_SUBWHOLE,regs),PF_FD)); + a_reg_dealloc(list,NR_R12); + list.concat(taicpu.op_reg_const(A_ADD,NR_STACK_POINTER_REG,LocalSize)); end; - end + end; + + if regs=[] then + list.concat(taicpu.op_reg_reg(A_MOV,NR_R15,NR_R14)) else begin - { restore int registers and return } - list.concat(taicpu.op_reg_reg(A_MOV, NR_STACK_POINTER_REG, NR_FRAME_POINTER_REG)); - { Add 4 to SP to make it point to an "imaginary PC" which the paramanager assumes is there(for normal ARM) } - list.concat(taicpu.op_reg_const(A_ADD, NR_STACK_POINTER_REG, 4)); - reference_reset(ref,4); ref.index:=NR_STACK_POINTER_REG; - list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,R_INTREGISTER,R_SUBWHOLE,regs),PF_DB)); + ref.addressmode:=AM_PREINDEXED; + list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,R_INTREGISTER,R_SUBWHOLE,regs),PF_FD)); end; end else list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R14)); end; - procedure Tthumb2cgarm.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); - begin - if reverse then - begin - list.Concat(taicpu.op_reg_reg(A_CLZ,dst,src)); - list.Concat(taicpu.op_reg_reg_const(A_RSB,dst,dst,31)); - list.Concat(taicpu.op_reg_reg(A_UXTB,dst,dst)); - end - else - begin - list.Concat(taicpu.op_reg_reg(A_RBIT,dst,src)); - list.Concat(taicpu.op_reg_reg(A_CLZ,dst,dst)); - list.Concat(taicpu.op_reg_reg_const(A_RSB,dst,dst,31)); - list.Concat(taicpu.op_reg_reg(A_UXTB,dst,dst)); - end - end; - function Tthumb2cgarm.handle_load_store(list:TAsmList;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference):treference; var tmpreg : tregister; diff --git a/compiler/arm/cpuinfo.pas b/compiler/arm/cpuinfo.pas index 2ace88bd8d..e918717890 100644 --- a/compiler/arm/cpuinfo.pas +++ b/compiler/arm/cpuinfo.pas @@ -1083,12 +1083,12 @@ Const { cpu_armv5tej } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP], { cpu_armv6 } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_LDREX], { cpu_armv6k } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_LDREX], - { cpu_armv6t2 } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_LDREX], + { cpu_armv6t2 } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX], { cpu_armv6z } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_LDREX], { the identifier armv7 is should not be used, it is considered being equal to armv7a } - { cpu_armv7 } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_LDREX], - { cpu_armv7a } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_LDREX], - { cpu_armv7r } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_LDREX], + { cpu_armv7 } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX], + { cpu_armv7a } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX], + { cpu_armv7r } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_BLX_LABEL,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX], { cpu_armv7m } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX,CPUARM_HAS_IDIV], { cpu_armv7em } [CPUARM_HAS_BX,CPUARM_HAS_BLX,CPUARM_HAS_CLZ,CPUARM_HAS_EDSP,CPUARM_HAS_REV,CPUARM_HAS_RBIT,CPUARM_HAS_LDREX,CPUARM_HAS_IDIV] ); diff --git a/rtl/inc/systemh.inc b/rtl/inc/systemh.inc index d971ca76d7..53e2144e77 100644 --- a/rtl/inc/systemh.inc +++ b/rtl/inc/systemh.inc @@ -818,7 +818,7 @@ function SarInt64(Const AValue : Int64;const Shift : Byte = 1): Int64; [external {$endif FPC_HAS_INTERNAL_SAR_QWORD} {$ifdef FPC_HAS_INTERNAL_BSF} -{$if defined(cpui386) or defined(cpux86_64)} +{$if defined(cpui386) or defined(cpux86_64) or defined(cpuarm)} {$define FPC_HAS_INTERNAL_BSF_BYTE} {$define FPC_HAS_INTERNAL_BSF_WORD} {$define FPC_HAS_INTERNAL_BSF_DWORD}