Browse Source

+ Xtensa: initial tcg64fxtensa.a_op64_const_reg_reg, still room for improvements

git-svn-id: trunk@44361 -
florian 5 years ago
parent
commit
65be647bbd
1 changed files with 88 additions and 1 deletions
  1. 88 1
      compiler/xtensa/cgcpu.pas

+ 88 - 1
compiler/xtensa/cgcpu.pas

@@ -928,8 +928,95 @@ implementation
 
 
     procedure tcg64fxtensa.a_op64_const_reg_reg(list : TAsmList; op : TOpCG; size : tcgsize; value : int64; regsrc,regdst : tregister64);
+      var
+        tmpreg,tmplo,carry,tmphi,hreg: tregister;
+        tmpreg64 : tregister64;
+        b : byte;
+        signed : Boolean;
+        no_carry : TAsmLabel;
+        instr : taicpu;
       begin
-        list.Concat(taicpu.op_none(A_NOP));
+        case op of
+          OP_NEG,
+          OP_NOT :
+            internalerror(2020030904);
+          else
+            ;
+        end;
+        case op of
+          OP_AND,OP_OR,OP_XOR:
+            begin
+              cg.a_op_const_reg_reg(list,op,OS_32,aint(lo(value)),regsrc.reglo,regdst.reglo);
+              cg.a_op_const_reg_reg(list,op,OS_32,aint(hi(value)),regsrc.reghi,regdst.reghi);
+            end;
+          OP_ADD:
+            begin
+              { could do better here (hi(value) in 248..2047), for now we support only the simple cases }
+              if (value>=-2048) and (value<=2047) then
+                begin
+                  signed:=(size in [OS_S64]);
+
+                  tmplo := cg.GetIntRegister(list,OS_S32);
+                  carry := cg.GetIntRegister(list,OS_S32);
+
+                  list.concat(taicpu.op_reg_reg_const(A_ADDI, tmplo, regsrc.reglo, value));
+                  if signed then
+                    begin
+                      list.concat(taicpu.op_reg_reg_const(A_ADDI, regdst.reghi, regsrc.reghi, 0));
+
+                      current_asmdata.getjumplabel(no_carry);
+                      instr:=taicpu.op_reg_reg_sym(A_Bcc,tmplo, regsrc.reglo, no_carry);
+                      instr.condition:=C_GEU;
+                      list.concat(instr);
+                      list.concat(taicpu.op_reg_reg_const(A_ADDI, regdst.reghi, regdst.reghi, 1));
+                      cg.a_label(list,no_carry);
+                    end
+                  else
+                    begin
+                      cg.a_load_const_reg(list,OS_INT,1,carry);
+                      current_asmdata.getjumplabel(no_carry);
+                      cg.a_cmp_reg_reg_label(list,OS_INT,OC_B,tmplo, regsrc.reglo,no_carry);
+                      cg.a_load_const_reg(list,OS_INT,0,carry);
+                      cg.a_label(list,no_carry);
+
+                      cg.a_load_reg_reg(list,OS_INT,OS_INT,tmplo,regdst.reglo);
+
+                      tmphi:=cg.GetIntRegister(list,OS_INT);
+                      hreg:=cg.GetIntRegister(list,OS_INT);
+                      cg.a_load_const_reg(list,OS_INT,$80000000,hreg);
+                      // first add carry to one of the addends
+                      list.concat(taicpu.op_reg_reg_reg(A_ADD, tmphi, regsrc.reghi, carry));
+
+                      cg.a_load_const_reg(list,OS_INT,1,carry);
+                      current_asmdata.getjumplabel(no_carry);
+                      cg.a_cmp_reg_reg_label(list,OS_INT,OC_B,tmphi, regsrc.reghi,no_carry);
+                      cg.a_load_const_reg(list,OS_INT,0,carry);
+                      cg.a_label(list,no_carry);
+
+                      list.concat(taicpu.op_reg_reg_reg(A_SUB, carry, hreg, carry));
+                      // then add another addend
+                      list.concat(taicpu.op_reg_reg_const(A_ADDI, regdst.reghi, tmphi, 0));
+                    end
+                  end
+                else
+                  begin
+                    tmpreg64.reglo := cg.GetIntRegister(list,OS_S32);
+                    tmpreg64.reghi := cg.GetIntRegister(list,OS_S32);
+                    a_load64_const_reg(list,value,tmpreg64);
+                    a_op64_reg_reg_reg(list,op,size,tmpreg64,regsrc,regdst);
+                  end;
+            end;
+          OP_SUB:
+            begin
+              { for now, we take the simple approach }
+              tmpreg64.reglo := cg.GetIntRegister(list,OS_S32);
+              tmpreg64.reghi := cg.GetIntRegister(list,OS_S32);
+              a_load64_const_reg(list,value,tmpreg64);
+              a_op64_reg_reg_reg(list,op,size,tmpreg64,regsrc,regdst);
+            end;
+          else
+            internalerror(2020030901);
+        end;
       end;