Browse Source

+ riscv32: trv32shlshrnode.second_64bit

florian 1 year ago
parent
commit
1737035501
1 changed files with 126 additions and 3 deletions
  1. 126 3
      compiler/riscv32/nrv32mat.pas

+ 126 - 3
compiler/riscv32/nrv32mat.pas

@@ -31,12 +31,14 @@ interface
 
 
     type
     type
       trv32moddivnode = class(tcgmoddivnode)
       trv32moddivnode = class(tcgmoddivnode)
-         procedure emit_div_reg_reg(signed: boolean; denum, num: tregister); override;
-         procedure emit_mod_reg_reg(signed: boolean; denum, num: tregister); override;
-         function first_moddivint: tnode; override;
+        procedure emit_div_reg_reg(signed: boolean; denum, num: tregister); override;
+        procedure emit_mod_reg_reg(signed: boolean; denum, num: tregister); override;
+        function first_moddivint: tnode; override;
       end;
       end;
 
 
       trv32shlshrnode = class(tcgshlshrnode)
       trv32shlshrnode = class(tcgshlshrnode)
+        function first_shlshr64bitint: tnode;override;
+        procedure second_64bit;override;
       end;
       end;
 
 
       trv32unaryminusnode = class(tcgunaryminusnode)
       trv32unaryminusnode = class(tcgunaryminusnode)
@@ -125,9 +127,130 @@ implementation
           result:=inherited;
           result:=inherited;
       end;
       end;
 
 
+
+    function trv32shlshrnode.first_shlshr64bitint: tnode;
+      begin
+        result := nil;
+      end;
+
+
+    procedure trv32shlshrnode.second_64bit;
+      var
+        v : TConstExprInt;
+        lreg, resreg: TRegister64;
+
+      procedure emit_instr(p: tai);
+        begin
+          current_asmdata.CurrAsmList.concat(p);
+        end;
+
+      var
+        tmpreg1, tmpreg2: TRegister;
+        less32, finished: TAsmLabel;
+
+      begin
+        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+        location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+        location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+
+        { load left operator in a register }
+        if not(left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or
+           (left.location.size<>OS_64) then
+          hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,true);
+
+        lreg:=left.location.register64;
+        resreg:=location.register64;
+
+        { shifting by a constant directly coded: }
+        if right.nodetype=ordconstn then
+          begin
+            v:=tordconstnode(right).value and 63;
+            if v >= 32 then
+              begin
+                if nodetype=shln then
+                  begin
+                    emit_instr(taicpu.op_reg_const(A_LI, resreg.reglo,0));
+                    emit_instr(taicpu.op_reg_reg_const(A_SLLI,resreg.reghi,lreg.reglo,v.uvalue-32));
+                  end
+                else
+                  begin
+                    emit_instr(taicpu.op_reg_const(A_LI, resreg.reghi,0));
+                    emit_instr(taicpu.op_reg_reg_const(A_SRLI,resreg.reglo,lreg.reghi,v.uvalue-32));
+                  end
+              end
+            else if (v < 32) then
+              if nodetype=shln then
+                begin
+                  tmpreg1:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+                  emit_instr(taicpu.op_reg_reg_const(A_SRLI,tmpreg1,lreg.reglo,32-v.uvalue));
+                  emit_instr(taicpu.op_reg_reg_const(A_SLLI,resreg.reglo,lreg.reglo,v.uvalue));
+                  emit_instr(taicpu.op_reg_reg_const(A_SLLI,resreg.reghi,lreg.reghi,v.uvalue));
+                  emit_instr(taicpu.op_reg_reg_reg(A_OR,resreg.reghi,resreg.reghi,tmpreg1));
+                end
+              else
+                begin
+                  tmpreg1:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+                  emit_instr(taicpu.op_reg_reg_const(A_SLLI,tmpreg1,lreg.reghi,32-v.uvalue));
+                  emit_instr(taicpu.op_reg_reg_const(A_SRLI,resreg.reglo,lreg.reglo,v.uvalue));
+                  emit_instr(taicpu.op_reg_reg_const(A_SRLI,resreg.reghi,lreg.reghi,v.uvalue));
+                  emit_instr(taicpu.op_reg_reg_reg(A_OR,resreg.reglo,resreg.reglo,tmpreg1));
+                end
+              else
+                Internalerror(2024072601);
+          end
+        else
+          begin
+            { force right operator into a register }
+            if not(right.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or
+               (right.location.size<>OS_32) then
+              hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,u32inttype,true);
+
+            current_asmdata.getjumplabel(less32);
+            current_asmdata.getjumplabel(finished);
+            tmpreg1:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+            tmpreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+
+            if nodetype = shln then
+              begin
+                emit_instr(taicpu.op_reg_reg_const(A_ADDI,tmpreg1,right.location.register64.reglo,-32));
+                emit_instr(taicpu.op_reg_sym(A_BLTZ,tmpreg1,less32));
+                emit_instr(taicpu.op_reg_const(A_LI,resreg.reglo,0));
+                emit_instr(taicpu.op_reg_reg_reg(A_SLL,resreg.reghi,lreg.reglo,tmpreg1));
+                cg.a_jmp_always(current_asmdata.CurrAsmList,finished);
+                cg.a_label(current_asmdata.CurrAsmList,less32);
+                emit_instr(taicpu.op_reg_const(A_LI,tmpreg1,31));
+                emit_instr(taicpu.op_reg_reg_const(A_SRLI,tmpreg2,lreg.reglo,1));
+                emit_instr(taicpu.op_reg_reg_reg(A_SUB,tmpreg1,tmpreg1,right.location.register64.reglo));
+                emit_instr(taicpu.op_reg_reg_reg(A_SLL,resreg.reglo,lreg.reglo,right.location.register64.reglo));
+                emit_instr(taicpu.op_reg_reg_reg(A_SRL,tmpreg2,tmpreg2,tmpreg1));
+                emit_instr(taicpu.op_reg_reg_reg(A_SLL,resreg.reghi,lreg.reghi,right.location.register64.reglo));
+                emit_instr(taicpu.op_reg_reg_reg(A_OR,resreg.reghi,resreg.reghi,tmpreg2));
+              end
+            else
+              begin
+                emit_instr(taicpu.op_reg_reg_const(A_ADDI,tmpreg1,right.location.register64.reglo,-32));
+                emit_instr(taicpu.op_reg_sym(A_BLTZ,tmpreg1,less32));
+                emit_instr(taicpu.op_reg_const(A_LI,resreg.reghi,0));
+                emit_instr(taicpu.op_reg_reg_reg(A_SRL,resreg.reglo,lreg.reghi,tmpreg1));
+                cg.a_jmp_always(current_asmdata.CurrAsmList,finished);
+                cg.a_label(current_asmdata.CurrAsmList,less32);
+                emit_instr(taicpu.op_reg_const(A_LI,tmpreg1,31));
+                emit_instr(taicpu.op_reg_reg_const(A_SLLI,tmpreg2,lreg.reghi,1));
+                emit_instr(taicpu.op_reg_reg_reg(A_SUB,tmpreg1,tmpreg1,right.location.register64.reglo));
+                emit_instr(taicpu.op_reg_reg_reg(A_SRL,resreg.reglo,lreg.reglo,right.location.register64.reglo));
+                emit_instr(taicpu.op_reg_reg_reg(A_SLL,tmpreg2,tmpreg2,tmpreg1));
+                emit_instr(taicpu.op_reg_reg_reg(A_SRL,resreg.reghi,lreg.reghi,right.location.register64.reglo));
+                emit_instr(taicpu.op_reg_reg_reg(A_OR,resreg.reglo,resreg.reglo,tmpreg2));
+              end;
+            cg.a_label(current_asmdata.CurrAsmList,finished);
+          end;
+      end;
+
+
 begin
 begin
    cmoddivnode:=trv32moddivnode;
    cmoddivnode:=trv32moddivnode;
    cshlshrnode:=trv32shlshrnode;
    cshlshrnode:=trv32shlshrnode;
    cunaryminusnode:=trv32unaryminusnode;
    cunaryminusnode:=trv32unaryminusnode;
    cnotnode:=trv32notnode;
    cnotnode:=trv32notnode;
 end.
 end.
+