|
@@ -35,6 +35,8 @@ unit cgppc;
|
|
tcgppcgen = class(tcg)
|
|
tcgppcgen = class(tcg)
|
|
procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara); override;
|
|
procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara); override;
|
|
|
|
|
|
|
|
+ procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tcgsize; src, dst: TRegister); override;
|
|
|
|
+
|
|
procedure a_call_reg(list : TAsmList;reg: tregister); override;
|
|
procedure a_call_reg(list : TAsmList;reg: tregister); override;
|
|
|
|
|
|
{ stores the contents of register reg to the memory location described by
|
|
{ stores the contents of register reg to the memory location described by
|
|
@@ -216,6 +218,54 @@ unit cgppc;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
+ procedure tcgppcgen.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tcgsize; src, dst: TRegister);
|
|
|
|
+ var
|
|
|
|
+ tmpreg: tregister;
|
|
|
|
+ cntlzop: tasmop;
|
|
|
|
+ bitsizem1: longint;
|
|
|
|
+ begin
|
|
|
|
+ { we only have a cntlz(w|d) instruction, which corresponds to bsr(x)
|
|
|
|
+ (well, regsize_in_bits - bsr(x), as x86 numbers bits in reverse).
|
|
|
|
+ Fortunately, bsf(x) can be calculated easily based on that, see
|
|
|
|
+ "Figure 5-13. Number of Powers of 2 Code Sequence" in the PowerPC
|
|
|
|
+ Compiler Writer's Guide
|
|
|
|
+ }
|
|
|
|
+ if srcsize in [OS_64,OS_S64] then
|
|
|
|
+ begin
|
|
|
|
+{$ifdef powerpc64}
|
|
|
|
+ cntlzop:=A_CNTLZD;
|
|
|
|
+{$else}
|
|
|
|
+ internalerror(2015022601);
|
|
|
|
+{$endif}
|
|
|
|
+ bitsizem1:=63;
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ cntlzop:=A_CNTLZW;
|
|
|
|
+ bitsizem1:=31;
|
|
|
|
+ end;
|
|
|
|
+ if not reverse then
|
|
|
|
+ begin
|
|
|
|
+ { cntlzw(src and -src) }
|
|
|
|
+ tmpreg:=getintregister(list,srcsize);
|
|
|
|
+ { don't use a_op_reg_reg, as this will adjust the result
|
|
|
|
+ after the neg in case of a non-32/64 bit operation, which
|
|
|
|
+ is not necessary since we're only using it as an
|
|
|
|
+ AND-mask }
|
|
|
|
+ list.concat(taicpu.op_reg_reg(A_NEG,tmpreg,src));
|
|
|
|
+ a_op_reg_reg(list,OP_AND,srcsize,src,tmpreg);
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ tmpreg:=src;
|
|
|
|
+ { count leading zeroes }
|
|
|
|
+ list.concat(taicpu.op_reg_reg(cntlzop,dst,tmpreg));
|
|
|
|
+ { (bitsize-1) - cntlz (which is 32/64 in case src was 0) }
|
|
|
|
+ list.concat(taicpu.op_reg_reg_const(A_SUBFIC,dst,dst,bitsizem1));
|
|
|
|
+ { set to 255 is source was 0 }
|
|
|
|
+ a_op_const_reg(list,OP_AND,dstsize,255,dst);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
procedure tcgppcgen.g_maybe_got_init(list: TAsmList);
|
|
procedure tcgppcgen.g_maybe_got_init(list: TAsmList);
|
|
var
|
|
var
|
|
instr: taicpu;
|
|
instr: taicpu;
|