浏览代码

* fixed record regvar code generation for ppc64 for now

git-svn-id: trunk@3787 -
tom_at_work 19 年之前
父节点
当前提交
a24a329d1c
共有 2 个文件被更改,包括 98 次插入61 次删除
  1. 60 32
      compiler/powerpc64/cgcpu.pas
  2. 38 29
      compiler/powerpc64/nppcadd.pas

+ 60 - 32
compiler/powerpc64/cgcpu.pas

@@ -866,17 +866,21 @@ const
 );
 
 var
-  instr: taicpu;
-  op : tasmop;
+  instr: TAiCpu;
+  op : TAsmOp;
+  bytesize : byte;
 begin
+  op := movemap[fromsize, tosize];
   {$ifdef extdebug}
-  list.concat(tai_comment.create(strpnew('a_load_reg_reg from : ' + cgsize2string(fromsize) + ' to ' + cgsize2string(tosize))));
+  list.concat(tai_comment.create(strpnew('a_load_reg_reg from : ' + cgsize2string(fromsize) + ' to ' + cgsize2string(tosize) + ' ' + inttostr(ord(op)) + ' ' + inttostr(ord(A_RLDICL)))));
   {$endif}
-  op := movemap[fromsize, tosize];
   case op of
     A_MR, A_EXTSB, A_EXTSH, A_EXTSW : instr := taicpu.op_reg_reg(op, reg2, reg1);
-    // note: have a look at this ([fromsize] shouldn't that be [tosize]??)
-    A_RLDICL : instr := taicpu.op_reg_reg_const_const(A_RLDICL, reg2, reg1, 0, (8-tcgsize2size[fromsize])*8);
+    A_RLDICL : begin
+      // always use the smaller size, extending to the larger
+      bytesize := min(tcgsize2size[fromsize], tcgsize2size[tosize]);
+      instr := taicpu.op_reg_reg_const_const(A_RLDICL, reg2, reg1, 0, (8-bytesize)*8);
+    end;
   else
     internalerror(2002090901);
   end;
@@ -894,14 +898,15 @@ begin
   {$endif}
   // calculate the correct startbit for the extrdi instruction, do the extraction if required and then
   // extend the sign correctly. (The latter is actually required only for signed subsets and if that
-  // subset is not >= the tosize.
+  // subset is not >= the tosize).
   extrdi_startbit := 64 - (tcgsize2size[subsetsize]*8 + startbit);
   if (startbit <> 0) then begin
     list.concat(taicpu.op_reg_reg_const_const(A_EXTRDI, destreg, subsetreg, tcgsize2size[subsetsize]*8, extrdi_startbit));
-    a_load_reg_reg(list, tcgsize2unsigned[subsetsize], tosize, destreg, destreg);
-    a_load_reg_reg(list, subsetsize, tosize, destreg, destreg);
-  end else
-    a_load_reg_reg(list, subsetsize, tosize, subsetreg, destreg);
+    a_load_reg_reg(list, tcgsize2unsigned[subsetregsize], tosize, destreg, destreg);
+  end else begin
+    a_load_reg_reg(list, tcgsize2unsigned[subsetregsize], tosize, subsetreg, destreg);
+  end;
+  a_load_reg_reg(list, subsetsize, tosize, destreg, destreg);
 end;
 
 procedure tcgppc.a_load_reg_subsetreg(list : TAsmList; fromsize: tcgsize; subsetregsize, 
@@ -1247,37 +1252,56 @@ end;
 
 procedure tcgppc.a_cmp_const_reg_label(list: TAsmList; size: tcgsize;
   cmp_op: topcmp; a: aint; reg: tregister; l: tasmlabel);
+const
+  //                  unsigned  useconst  32bit-op
+  cmpop_table : array[boolean, boolean, boolean] of TAsmOp = (
+    ((A_CMPD, A_CMPW), (A_CMPDI, A_CMPWI)),
+    ((A_CMPLD, A_CMPLW), (A_CMPLDI, A_CMPLWI))
+   );
+
 var
-  scratch_register: TRegister;
-  signed: boolean;
+  tmpreg : TRegister;
+  signed, useconst : boolean;
+  opsize : TCgSize;
+  op : TAsmOp;
 begin
-
   {$IFDEF EXTDEBUG}
-  list.concat(tai_comment.create(strpnew('a_cmp_const_reg_label ' + inttostr(ord(size)) + ' ' + inttostr(tcgsize2size[size]))));
+  list.concat(tai_comment.create(strpnew('a_cmp_const_reg_label ' + cgsize2string(size) + ' ' + booltostr(cmp_op in [OC_GT, OC_LT, OC_GTE, OC_LTE]) + ' ' + inttostr(a) )));
   {$ENDIF EXTDEBUG}
 
   signed := cmp_op in [OC_GT, OC_LT, OC_GTE, OC_LTE];
-  { in the following case, we generate more efficient code when }
-  { signed is true                                              }
+  // in the following case, we generate more efficient code when
+  // signed is true
   if (cmp_op in [OC_EQ, OC_NE]) and
     (aword(a) > $FFFF) then
     signed := true;
-  if signed then
-    if (a >= low(smallint)) and (a <= high(smallint)) then
-      list.concat(taicpu.op_reg_reg_const(A_CMPDI, NR_CR0, reg, a))
-    else begin
-      scratch_register := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
-      a_load_const_reg(list, OS_INT, a, scratch_register);
-      list.concat(taicpu.op_reg_reg_reg(A_CMPD, NR_CR0, reg, scratch_register));
-    end
-  else if (aword(a) <= $FFFF) then
-    list.concat(taicpu.op_reg_reg_const(A_CMPLDI, NR_CR0, reg, aword(a)))
-  else begin
-    scratch_register := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
-    a_load_const_reg(list, OS_INT, a, scratch_register);
-    list.concat(taicpu.op_reg_reg_reg(A_CMPLD, NR_CR0, reg,
-      scratch_register));
+
+  opsize := size;
+
+  // do we need to change the operand size because ppc64 only supports 32 and
+  // 64 bit compares?
+  if (not (size in [OS_32, OS_S32, OS_64, OS_S64])) then begin
+    if (signed) then
+      opsize := OS_S32
+    else
+      opsize := OS_32;
+    a_load_reg_reg(current_asmdata.CurrAsmList, size, opsize, reg, reg); 
   end;
+
+  // can we use immediate compares?
+  useconst := (signed and ( (a >= low(smallint)) and (a <= high(smallint)))) or
+    ((not signed) and (aword(a) <= $FFFF));
+
+  op := cmpop_table[not signed, useconst, opsize in [OS_32, OS_S32]];
+
+  if (useconst) then begin
+    list.concat(taicpu.op_reg_reg_const(op, NR_CR0, reg, a));
+  end else begin
+    tmpreg := getintregister(current_asmdata.CurrAsmList, OS_INT);
+    a_load_const_reg(current_asmdata.CurrAsmList, opsize, a, tmpreg);
+    list.concat(taicpu.op_reg_reg_reg(op, NR_CR0, reg, tmpreg));
+  end;
+
   a_jmp(list, A_BC, TOpCmp2AsmCond[cmp_op], 0, l);
 end;
 
@@ -1290,6 +1314,10 @@ begin
   list.concat(tai_comment.create(strpnew('a_cmp_reg_reg_label, size ' + cgsize2string(size) + ' op ' + inttostr(ord(cmp_op)))));
   {$ENDIF extdebug}
 
+  {$note Commented out below check because of compiler weirdness}
+//  if (not (size in [OS_32, OS_S32, OS_64, OS_S64])) then
+//    internalerror(200606041);
+
   if cmp_op in [OC_GT, OC_LT, OC_GTE, OC_LTE] then
     if (size in [OS_64, OS_S64]) then
       op := A_CMPD

+ 38 - 29
compiler/powerpc64/nppcadd.pas

@@ -159,48 +159,64 @@ begin
 end;
 
 procedure tppcaddnode.emit_compare(unsigned: boolean);
+const
+  //                  unsigned  useconst  32bit-op
+  cmpop_table : array[boolean, boolean, boolean] of TAsmOp = (
+    ((A_CMPD, A_CMPW), (A_CMPDI, A_CMPWI)),
+    ((A_CMPLD, A_CMPLW), (A_CMPLDI, A_CMPLWI))
+   );
+
 var
-  op: tasmop;
-  tmpreg: tregister;
+  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);
+
+  {$IFDEF EXTDEBUG}
   current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew('tppcaddnode.emit_compare ' + inttostr(ord(opsize)) + ' ' + inttostr(tcgsize2size[opsize]))));
   {$ENDIF EXTDEBUG}
 
-  // can we use an immediate, or do we have to load the
-  // constant in a register first?
-  if (right.location.loc = LOC_CONSTANT) then begin
-    if (nodetype in [equaln, unequaln]) then
-      if (unsigned and
-        (aword(right.location.value) > high(word))) or
-        (not unsigned and
-        (aint(right.location.value) < low(smallint)) or
+  // can we use a signed comparison or not? In case of equal/unequal comparison
+  // we can check whether this is possible because it does not matter.
+  if (right.location.loc = LOC_CONSTANT) then
+    if (nodetype in [equaln,unequaln]) then
+      if (unsigned and (aword(right.location.value) > high(word))) or
+        (not unsigned and (aint(right.location.value) < low(smallint)) or
         (aint(right.location.value) > high(smallint))) then
         { we can then maybe use a constant in the 'othersigned' case
-         (the sign doesn't matter for // equal/unequal)}
+        (the sign doesn't matter for // equal/unequal)}
         unsigned := not unsigned;
 
+  // calculate the size of the comparison because ppc64 only has 32 and 64
+  // bit comparison opcodes; prefer 32 bits
+  if (not (opsize in [OS_32, OS_S32, OS_64, OS_S64])) then begin
+    if (unsigned) then
+      opsize := OS_32
+    else
+      opsize := OS_S32;
+    cg.a_load_reg_reg(current_asmdata.CurrAsmList, def_cgsize(left.resulttype.def), opsize, 
+      left.location.register, left.location.register); 
+  end;
+
+  // can we use an immediate, or do we have to load the
+  // constant in a register first?
+  if (right.location.loc = LOC_CONSTANT) then begin
     if (unsigned and
       (aword(right.location.value) <= high(word))) or
       (not (unsigned) and
-      (aint(right.location.value) >= low(smallint)) and
-      (aint(right.location.value) <= high(smallint))) then
+      (aint(right.location.value) >= low(smallint)) and (aint(right.location.value) <= high(smallint))) then
       useconst := true
     else begin
       useconst := false;
       tmpreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
-      cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, right.location.value, tmpreg);
+      cg.a_load_const_reg(current_asmdata.CurrAsmList, opsize, right.location.value, tmpreg);
     end
   end else
     useconst := false;
@@ -208,16 +224,9 @@ begin
   location.loc := LOC_FLAGS;
   location.resflags := getresflags;
 
-  if not unsigned then
-    if useconst then
-      op := A_CMPDI
-    else
-      op := A_CMPD
-  else if useconst then
-    op := A_CMPLDI
-  else
-    op := A_CMPLD;
+  op := cmpop_table[unsigned, useconst, opsize in [OS_S32, OS_32]];
 
+  // actually do the operation
   if (right.location.loc = LOC_CONSTANT) then begin
     if useconst then
       current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(op, left.location.register,
@@ -225,8 +234,8 @@ begin
     else
       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.register, tmpreg));
   end else
-    current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,
-      left.location.register, right.location.register));
+    current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.register,
+      right.location.register));
 end;
 
 {*****************************************************************************