[fpc-devel] about freepascal for mips

Fuxin Zhang zhangfx at lemote.com
Mon May 28 18:21:47 CEST 2012


>>
>> I managed to remove the errors with the following patch, such that
>> everything compiled, but I haven't been able to test it:
>> http://j-software.dk/fpc-mipsel.patch

>All fixes of the patch are committed, I solved some things differently
though.

I am struggling with cpupara.pas. The use of framepoint register ($30) is
not right. Printing of floating point number will fail(segmentation fault
or deadloop), e.g. writeln(0.3). After some tracing, I've found that it
dies in fpc_shortstr_copy,
   the code is somewhat like this:

   caller:
         addiu   $2,$29,88
        sw      $2,($29)
        lui     $4,%hi(U_$P$PROGRAM_$$_S)
        addiu   $4,$4,%lo(U_$P$PROGRAM_$$_S)
        addiu   $6,$0,2
        addiu   $5,$0,1
        addiu   $29,$29,-4
        jal     my_fpc_shortstr_copy
        nop
        addiu   $29,$29,4
    callee:
        addiu   $29,$29,-104
        sw      $31,44($29)
        addiu   $2,$30,8
        addiu   $3,$29,96
        lw      $2,($2)    //this is wrong
        sw      $2,($3)

   $30 is not initialized properly, the use of $30 register will fail.
When looking at the code,
     cgcpu.pas    g_proc_entry (here we probably should initialize $30
like powerpc code, if needs_framepoint_ ...)
     cpupara.pas  I don't fully understand the code yet. The generated
code with $30 is not from g_proc_entry, instead they are inserted
later. Could you help show me the logic:
     1, where is the frame pointer code generated and inserted?
     2, when will it start to use frame pointer? I have tried that, if the
function return a string, $30 will be used; if return an integer, not
used. Is it depending on the return type?
     3, how is the return value related to parameter handling? It seems
that return value is handled as a special parameter?

    And the whole code seems totally incompatible with standard mips abi,
it use 6 registers to pass parameters, while o32 has 4.

BTW:
  I have fixed the boolean64 support use the following patch:
--- ncpucnv.pas	(版本 21420)
+++ ncpucnv.pas	(工作副本)
@@ -214,6 +214,8 @@
   hreg1, hreg2: tregister;
   opsize: tcgsize;
   hlabel, oldtruelabel, oldfalselabel: tasmlabel;
+  newsize  : tcgsize;
+  href: treference;
 begin
   oldtruelabel  := current_procinfo.CurrTrueLabel;
   oldfalselabel := current_procinfo.CurrFalseLabel;
@@ -223,17 +225,24 @@
   if codegenerror then
     exit;

-  { byte(boolean) or word(wordbool) or longint(longbool) must }
-  { be accepted for var parameters                            }
-  if (nf_explicit in flags) and
-    (left.resultdef.size = resultdef.size) and
-    (left.location.loc in [LOC_REFERENCE, LOC_CREFERENCE, LOC_CREGISTER])
then
-  begin
-    location_copy(location, left.location);
-    current_procinfo.CurrTrueLabel  := oldtruelabel;
-    current_procinfo.CurrFalseLabel := oldfalselabel;
-    exit;
-  end;
+         { Explicit typecasts from any ordinal type to a boolean type }
+         { must not change the ordinal value                          }
+         if (nf_explicit in flags) and
+            not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
+           begin
+              location_copy(location,left.location);
+              newsize:=def_cgsize(resultdef);
+              { change of size? change sign only if location is
LOC_(C)REGISTER? Then we have to sign/zero-extend }
+              if
(tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
+                 ((newsize<>left.location.size) and (location.loc in
[LOC_REGISTER,LOC_CREGISTER])) then
+               
hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,resultdef,true)
+              else
+                location.size:=newsize;
+              current_procinfo.CurrTrueLabel:=oldTrueLabel;
+              current_procinfo.CurrFalseLabel:=oldFalseLabel;
+              exit;
+           end;
+
   location_reset(location, LOC_REGISTER, def_cgsize(resultdef));
   opsize := def_cgsize(left.resultdef);
   case left.location.loc of
@@ -242,21 +251,35 @@
       if left.location.loc in [LOC_CREFERENCE, LOC_REFERENCE] then
       begin
         hreg2 := cg.getintregister(current_asmdata.CurrAsmList, opsize);
-        cg.a_load_ref_reg(current_asmdata.CurrAsmList, opsize, opsize,
left.location.reference, hreg2);
+{$ifndef cpu64bitalu}
+        if left.location.size in [OS_64,OS_S64] then
+          begin
+           
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,left.location.reference,hreg2);
+            hreg1:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+            href:=left.location.reference;
+            inc(href.offset,4);
+           
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,href,hreg1);
+           
cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,hreg1,hreg2,hreg2);
+          end
+          else
+{$endif not cpu64bitalu}
+            cg.a_load_ref_reg(current_asmdata.CurrAsmList, opsize,
opsize, left.location.reference, hreg2);
       end
       else
-        hreg2 := left.location.Register;
-{$ifndef cpu64bit}
-      if left.location.size in [OS_64, OS_S64] then
-      begin
-        hreg1 := cg.getintregister(current_asmdata.CurrAsmList, OS_32);
-        cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_32,
hreg2, tregister(succ(longint(hreg2))), hreg1);
-        hreg2  := hreg1;
-        opsize := OS_32;
-      end;
-{$endif cpu64bit}
-      hreg1 := cg.getintregister(current_asmdata.CurrAsmList, opsize);
-        current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SNE,
hreg1, hreg2, NR_R0));
+        begin
+          hreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+{$ifndef cpu64bitalu}
+          if left.location.size in [OS_64,OS_S64] then
+            begin
+              hreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+             
cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reghi,left.location.register64.reglo,hreg2);
+             end
+           else
+{$endif not cpu64bitalu}
+            
cg.a_load_reg_reg(current_asmdata.CurrAsmList,opsize,opsize,left.location.register,hreg2);
+         end;
+       hreg1 := cg.getintregister(current_asmdata.CurrAsmList, opsize);
+       current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SNE,
hreg1, hreg2, NR_R0));
     end;
     LOC_JUMP:
     begin
@@ -272,10 +295,26 @@
     else
       internalerror(10062);
   end;
-  location.Register := hreg1;
+{$ifndef cpu64bitalu}
+  if (location.size in [OS_64,OS_S64]) then
+    begin
+      location.register64.reglo:=hreg1;
+     
location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+      if (is_cbool(resultdef)) then
+       { reglo is either 0 or -1 -> reghi has to become the same }
+     
	cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,location.register64.reglo,location.register64.reghi)
+       else
+       { unsigned }
+        
cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,location.register64.reghi);
+       end
+       else
+{$endif not cpu64bitalu}
+         location.Register := hreg1;

+{zfx
   if location.size in [OS_64, OS_S64] then
     internalerror(200408241);
+}

   current_procinfo.CurrTrueLabel  := oldtruelabel;
   current_procinfo.CurrFalseLabel := oldfalselabel;



Best Regards
Fuxin Zhang




More information about the fpc-devel mailing list