diff --git a/compiler/powerpc64/cgcpu.pas b/compiler/powerpc64/cgcpu.pas index 6d35239f93..b97ddd74ae 100644 --- a/compiler/powerpc64/cgcpu.pas +++ b/compiler/powerpc64/cgcpu.pas @@ -75,6 +75,13 @@ type procedure a_load_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override; + procedure a_load_subsetreg_reg(list : TAsmList; subsetregsize, subsetsize: tcgsize; + startbit: byte; tosize: tcgsize; subsetreg, destreg: tregister); override; + procedure a_load_reg_subsetreg(list : TAsmList; fromsize: tcgsize; subsetregsize, + subsetsize: tcgsize; startbit: byte; fromreg, subsetreg: tregister); override; + procedure a_load_const_subsetreg(list: TAsmlist; subsetregsize, subsetsize: tcgsize; + startbit: byte; a: aint; subsetreg: tregister); override; + { fpu move instructions } procedure a_loadfpu_reg_reg(list: TAsmList; size: tcgsize; reg1, reg2: tregister); override; @@ -206,6 +213,16 @@ begin result := cgsize_strings[size]; end; +function cgop2string(const op : TOpCg) : String; +const + opcg_strings : array[TOpCg] of string[6] = ( + 'None', 'Move', 'Add', 'And', 'Div', 'IDiv', 'IMul', 'Mul', + 'Neg', 'Not', 'Or', 'Sar', 'Shl', 'Shr', 'Sub', 'Xor' + ); +begin + result := opcg_strings[op]; +end; + function is_signed_cgsize(const size : TCgSize) : Boolean; begin case size of @@ -736,7 +753,7 @@ var begin {$IFDEF EXTDEBUG} - astring := 'a_load_const_reg ' + inttostr(hi(a)) + ' ' + inttostr(lo(a)) + ' ' + inttostr(ord(size)) + ' ' + inttostr(tcgsize2size[size]); + astring := 'a_load_const_reg ' + inttostr(hi(a)) + ' ' + inttostr(lo(a)) + ' ' + inttostr(ord(size)) + ' ' + inttostr(tcgsize2size[size]) + ' ' + hexstr(a, 16); list.concat(tai_comment.create(strpnew(astring))); {$ENDIF EXTDEBUG} if not (size in [OS_8, OS_S8, OS_16, OS_S16, OS_32, OS_S32, OS_64, OS_S64]) then @@ -852,6 +869,9 @@ var instr: taicpu; op : tasmop; begin + {$ifdef extdebug} + list.concat(tai_comment.create(strpnew('a_load_reg_reg from : ' + cgsize2string(fromsize) + ' to ' + cgsize2string(tosize)))); + {$endif} op := movemap[fromsize, tosize]; case op of A_MR, A_EXTSB, A_EXTSH, A_EXTSW : instr := taicpu.op_reg_reg(op, reg2, reg1); @@ -863,6 +883,43 @@ begin rg[R_INTREGISTER].add_move_instruction(instr); end; +procedure tcgppc.a_load_subsetreg_reg(list : TAsmList; subsetregsize, subsetsize: tcgsize; + startbit: byte; tosize: tcgsize; subsetreg, destreg: tregister); +var + total : byte; +begin + {$ifdef extdebug} + list.concat(tai_comment.create(strpnew('a_load_subsetreg_reg subsetregsize = ' + cgsize2string(subsetregsize) + ' subsetsize = ' + cgsize2string(subsetsize) + ' startbit = ' + intToStr(startbit) + ' tosize = ' + cgsize2string(tosize)))); + {$endif} + total := tcgsize2size[subsetsize]*8 + startbit and 63; + if (total <> 64) then begin + list.concat(taicpu.op_reg_reg_const_const(A_EXTRDI, destreg, subsetreg, tcgsize2size[subsetsize]*8, startbit and 63)); + end else + a_load_reg_reg(list, subsetsize, tosize, subsetreg, destreg); + + // extend sign (actually only required for signed subsets...) and if that subset isn't >= real size + a_load_reg_reg(list, subsetsize, tosize, destreg, destreg); +end; + +procedure tcgppc.a_load_reg_subsetreg(list : TAsmList; fromsize: tcgsize; subsetregsize, + subsetsize: tcgsize; startbit: byte; fromreg, subsetreg: tregister); +begin + {$ifdef extdebug} + list.concat(tai_comment.create(strpnew('a_load_reg_subsetreg'))); + {$endif} + list.concat(taicpu.op_reg_reg_const_const(A_INSRDI, subsetreg, fromreg, tcgsize2size[subsetsize]*8, startbit and 63)); +end; + +procedure tcgppc.a_load_const_subsetreg(list: TAsmlist; subsetregsize, subsetsize: tcgsize; + startbit: byte; a: aint; subsetreg: tregister); +begin + {$ifdef extdebug} + list.concat(tai_comment.create(strpnew('a_load_const_subsetreg subsetregsize = ' + cgsize2string(subsetregsize) + ' subsetsize = ' + cgsize2string(subsetsize) + ' startbit = ' + intToStr(startbit) + ' a = ' + intToStr(a)))); + {$endif} + // use the default method because it is optimal anyway + inherited; +end; + procedure tcgppc.a_loadfpu_reg_reg(list: TAsmList; size: tcgsize; reg1, reg2: tregister); var @@ -1055,6 +1112,10 @@ begin a_op_const_reg_reg(list, OP_ADD, size, -a, src, dst); exit; end; + {$IFDEF EXTDEBUG} + list.concat(tai_comment.create(strpnew('a_op_const_reg_reg ' + cgop2string(op)))); + {$ENDIF EXTDEBUG} + { This case includes some peephole optimizations for the various operations, (e.g. AND, OR, XOR, ..) - can't this be done at some higher level, independent of architecture? } diff --git a/compiler/powerpc64/cpubase.pas b/compiler/powerpc64/cpubase.pas index 30eb604ba9..664f4a733c 100644 --- a/compiler/powerpc64/cpubase.pas +++ b/compiler/powerpc64/cpubase.pas @@ -102,7 +102,8 @@ type A_LVX, A_STVX, A_MULLDO, A_MULLDO_, A_MULHDU, A_MULHDU_, A_MFXER, - A_FCTID, A_FCTID_, A_FCTIDZ, A_FCTIDZ_); + A_FCTID, A_FCTID_, A_FCTIDZ, A_FCTIDZ_, + A_EXTRDI, A_EXTRDI_, A_INSRDI, A_INSRDI_); {# This should define the array of instructions as string } op2strtable = array[tasmop] of string[8]; diff --git a/compiler/powerpc64/itcpugas.pas b/compiler/powerpc64/itcpugas.pas index de5d9a3ac5..343e0eba82 100644 --- a/compiler/powerpc64/itcpugas.pas +++ b/compiler/powerpc64/itcpugas.pas @@ -92,7 +92,8 @@ const 'lvx', 'stvx', 'mulldo', 'mulldo.', 'mulhdu', 'mulhdu.', 'mfxer', - 'fctid', 'fctid.', 'fctidz', 'fctidz.'); + 'fctid', 'fctid.', 'fctidz', 'fctidz.', + 'extrdi', 'extrdi.', 'insrdi', 'insrdi.'); function gas_regnum_search(const s: string): Tregister; function gas_regname(r: Tregister): string; diff --git a/compiler/powerpc64/nppcadd.pas b/compiler/powerpc64/nppcadd.pas index 9920d1f1cd..a260fbb33e 100644 --- a/compiler/powerpc64/nppcadd.pas +++ b/compiler/powerpc64/nppcadd.pas @@ -163,12 +163,18 @@ var op: tasmop; tmpreg: tregister; useconst: boolean; + + {$IFDEF EXTDEBUG} + opsize : TCgSize; + {$ENDIF EXTDEBUG} + begin // get the constant on the right if there is one if (left.location.loc = LOC_CONSTANT) then swapleftright; {$IFDEF EXTDEBUG} + opsize := def_cgsize(left.resulttype.def); current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew('tppcaddnode.emit_compare ' + inttostr(ord(opsize)) + ' ' + inttostr(tcgsize2size[opsize])))); {$ENDIF EXTDEBUG}