if fromsize in [OS_64,OS_S64] then
begin
{ split into two 32 bit loads }
- hreg1:=makeregsize(register,OS_32);
+ hreg1:=getintregister(list,OS_32);
hreg2:=getintregister(list,OS_32);
if target_info.endian=endian_big then
begin
inc(href.offset,4);
a_load_ref_reg(list,OS_32,OS_32,href,hreg2);
end;
+ a_load_reg_reg(list,OS_32,OS_64,hreg1,register);
list.concat(taicpu.op_reg_reg_const_const(A_BFI,register,makeregsize(hreg2,OS_64),32,32));
end
else
if fromsize in [OS_64,OS_S64] then
begin
{ split into two 32 bit stores }
- hreg1:=makeregsize(register,OS_32);
+ hreg1:=getintregister(list,OS_32);
hreg2:=getintregister(list,OS_32);
+ a_load_reg_reg(list,OS_32,OS_32,makeregsize(register,OS_32),hreg1);
a_op_const_reg_reg(list,OP_SHR,OS_64,32,register,makeregsize(hreg2,OS_64));
if target_info.endian=endian_big then
begin
procedure tcgaarch64.a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: topcg; size: tcgsize; src1, src2, dst: tregister; setflags : boolean; var ovloc : tlocation);
var
- tmpreg1: tregister;
+ tmpreg1, tmpreg2: tregister;
begin
ovloc.loc:=LOC_VOID;
{ overflow can only occur with 64 bit calculations on 64 bit cpus }
ovloc.resflags:=F_CC
else
ovloc.resflags:=F_VS;
- { finished; since we won't call through to a_op_reg_reg_reg,
- adjust the result here if necessary }
- maybeadjustresult(list,op,size,dst);
+ { finished }
exit;
end;
OP_MUL:
end;
OP_IMUL:
begin
- { check whether the sign bit of the (128 bit) result is the
- same as "sign bit of src1" xor "signbit of src2" (if so, no
- overflow and the xor-product of all sign bits is 0) }
+ { check whether the upper 64 bits of the 128 bit multiplication
+ result have the same value as the replicated sign bit of the
+ lower 64 bits }
tmpreg1:=getintregister(list,OS_64);
list.concat(taicpu.op_reg_reg_reg(A_SMULH,tmpreg1,src2,src1));
- list.concat(taicpu.op_reg_reg_reg(A_EOR,tmpreg1,tmpreg1,src1));
- list.concat(taicpu.op_reg_reg_reg(A_EOR,tmpreg1,tmpreg1,src2));
- list.concat(taicpu.op_reg_const(A_TST,tmpreg1,$80000000));
+ { calculate lower 64 bits (afterwards, because dst may be
+ equal to src1 or src2) }
+ a_op_reg_reg_reg(list,op,size,src1,src2,dst);
+ { replicate sign bit }
+ tmpreg2:=getintregister(list,OS_64);
+ a_op_const_reg_reg(list,OP_SAR,OS_S64,63,dst,tmpreg2);
+ list.concat(taicpu.op_reg_reg(A_CMP,tmpreg1,tmpreg2));
ovloc.loc:=LOC_FLAGS;
ovloc.resflags:=F_NE;
- { still have to perform the actual multiplication }
+ { finished }
+ exit;
end;
OP_IDIV,
OP_DIV: