[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