diff --git a/compiler/mips/cgcpu.pas b/compiler/mips/cgcpu.pas index b5a97a966b..811bb5bc91 100644 --- a/compiler/mips/cgcpu.pas +++ b/compiler/mips/cgcpu.pas @@ -803,9 +803,24 @@ end; procedure TCGMIPS.a_op_reg_reg_reg(list: tasmlist; op: TOpCg; size: tcgsize; src1, src2, dst: tregister); +var + hreg: tregister; begin if (TOpcg2AsmOp[op]=A_NONE) then InternalError(2013070305); + if (op=OP_SAR) then + begin + if (size in [OS_S8,OS_S16]) then + begin + { Shift left by 16/24 bits and increase amount of right shift by same value } + list.concat(taicpu.op_reg_reg_const(A_SLL, dst, src2, 32-(tcgsize2size[size]*8))); + hreg:=GetIntRegister(list,OS_INT); + a_op_const_reg_reg(list,OP_ADD,OS_INT,32-(tcgsize2size[size]*8),src1,dst); + src1:=hreg; + end + else if not (size in [OS_32,OS_S32]) then + InternalError(2013070306); + end; list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op], dst, src2, src1)); maybeadjustresult(list,op,size,dst); end; @@ -885,8 +900,17 @@ begin list.concat(taicpu.op_reg_reg_const(A_SRL,dst,src,a)); OP_SAR: - list.concat(taicpu.op_reg_reg_const(A_SRA,dst,src,a)); - + begin + if (size in [OS_S8,OS_S16]) then + begin + list.concat(taicpu.op_reg_reg_const(A_SLL,dst,src,32-(tcgsize2size[size]*8))); + inc(a,32-tcgsize2size[size]*8); + src:=dst; + end + else if not (size in [OS_32,OS_S32]) then + InternalError(2013070303); + list.concat(taicpu.op_reg_reg_const(A_SRA,dst,src,a)); + end; else internalerror(2007012601); end; diff --git a/rtl/inc/systemh.inc b/rtl/inc/systemh.inc index 95b56afd9b..03a1e238c2 100644 --- a/rtl/inc/systemh.inc +++ b/rtl/inc/systemh.inc @@ -861,10 +861,10 @@ function RolQWord(Const AValue : QWord;const Dist : Byte): QWord;{$ifdef SYSTEMI {$ifdef FPC_HAS_INTERNAL_SAR} -{$if defined(cpux86_64) or defined(cpui386)} +{$if defined(cpux86_64) or defined(cpui386) or defined(mips) or defined(mipsel)} {$define FPC_HAS_INTERNAL_SAR_BYTE} {$define FPC_HAS_INTERNAL_SAR_WORD} -{$endif defined(cpux86_64) or defined(cpui386)} +{$endif defined(cpux86_64) or defined(cpui386) or defined(mips) or defined(mipsel)} { currently, all supported CPUs have an internal 32 bit sar implementation } { $if defined(cpux86_64) or defined(cpui386) or defined(arm) or defined(powerpc) or defined(powerpc64) or defined(mips) or defined(mipsel)}