powerpc: added support for 64bit explicit locations in legacy MorphOS syscalls. improved error handling of various corner cases or explicit paraloc handling

git-svn-id: trunk@47104 -
This commit is contained in:
Károly Balogh 2020-10-14 01:45:14 +00:00
parent 637976e83f
commit f489858855
4 changed files with 764 additions and 700 deletions

View File

@ -1075,8 +1075,9 @@ parser_e_paraloc_only_one_para=03197_E_Each argument must have its own location
parser_e_paraloc_all_paras=03198_E_Each argument must have an explicit location
% If one argument has an explicit argument location, all arguments of a procedure
% must have one.
parser_e_illegal_explicit_paraloc=03199_E_Unknown argument location
% The location specified for an argument isn't recognized by the compiler.
parser_e_illegal_explicit_paraloc=03199_E_Invalid explicit parameter location specified
% Syscalls specific: the specified explicit location string for this parameter cannot be parsed, invalid,
% or The location specified for an argument isn't recognized by the compiler.
parser_e_32bitint_or_pointer_variable_expected=03200_E_32 Bit-Integer or pointer variable expected
% The libbase for MorphOS/AmigaOS can be given only as \var{longint}, \var{dword} or any pointer variable.
parser_e_goto_outside_proc=03201_E_Goto statements are not allowed between different procedures
@ -1612,6 +1613,14 @@ parser_e_method_for_type_in_other_unit=03354_E_Implementing a method for type "$
parser_e_generic_constraints_not_allowed_here=03355_E_Generic constraint not allowed here
% At the current location specifying a constraint is not allowed. For example
% in delphi mode, a constraint might not be specified in the header of the implementation.
parser_e_location_size_too_small=03356_E_Explicit location is too small for parameter
% AmigaOS/MorphOS syscall specific: for int64/qword parameter only a single register location is specified
parser_w_location_size_too_large=03357_W_Explicit location size is larger than required by parameter
% AmigaOS/MorphOS syscall specific: for a parameter which is smaller than 64bit, a register pair is specified
parser_e_location_regpair_only_data=03358_E_Only data registers are supported for explicit location register pairs
% AmigaOS/MorphOS syscall specific: for 64bit register pairs, only data registers are supported
parser_e_location_regpair_only_consecutive=03359_E_Only consecutive registers are supported for explicit location register pairs
% MorphOS syscall specific: only consecutive (f.e.: d1-d2) registers are supported for 64bit register pairs
%
% \end{description}
%

View File

@ -466,6 +466,10 @@ const
parser_w_enumeration_out_of_range=03353;
parser_e_method_for_type_in_other_unit=03354;
parser_e_generic_constraints_not_allowed_here=03355;
parser_e_location_size_too_small=03356;
parser_w_location_size_too_large=03357;
parser_e_location_regpair_only_data=03358;
parser_e_location_regpair_only_consecutive=03359;
type_e_mismatch=04000;
type_e_incompatible_types=04001;
type_e_not_equal_types=04002;
@ -1127,9 +1131,9 @@ const
option_info=11024;
option_help_pages=11025;
MsgTxtSize = 85795;
MsgTxtSize = 86101;
MsgIdxMax : array[1..20] of longint=(
28,106,356,130,99,63,143,36,223,68,
28,106,360,130,99,63,143,36,223,68,
62,20,30,1,1,1,1,1,1,1
);

File diff suppressed because it is too large Load Diff

View File

@ -663,10 +663,22 @@ unit cpupara;
var
paraloc : pcgparalocation;
paracgsize : tcgsize;
offset : aint;
offset_lo: aint;
offset_hi: aint;
function parse68kregname(idx: longint): longint;
begin
result:=-1;
if (lowercase(s[idx]) = 'd') and (s[idx+1] in ['0'..'7']) then
result:=(ord(s[idx+1]) - ord('0')) * sizeof(pint)
else if (lowercase(s[idx]) = 'a') and (s[idx+1] in ['0'..'6']) then
result:=(ord(s[idx+1]) - ord('0') + 8) * sizeof(pint);
end;
begin
result:=false;
offset:=-1;
offset_hi:=-1;
offset_lo:=-1;
case target_info.system of
system_powerpc_morphos:
begin
@ -683,30 +695,60 @@ unit cpupara;
paraloc^.size:=OS_ADDR;
paraloc^.def:=p.vardef;
{ convert d0-d7/a0-a6 virtual 68k reg patterns into offsets }
if length(s) = 2 then
begin
if (lowercase(s[1]) = 'd') and (s[2] in ['0'..'7']) then
offset:=(ord(s[2]) - ord('0')) * sizeof(pint)
else if (lowercase(s[1]) = 'a') and (s[2] in ['0'..'6']) then
offset:=(ord(s[2]) - ord('0') + 8) * sizeof(pint);
{ convert virtual 68k reg patterns into offsets }
case length(s) of
2: begin
{ single register }
offset_lo:=parse68kregname(1);
if offset_lo<0 then
message(parser_e_illegal_explicit_paraloc);
if offset < 0 then
exit;
if tcgsize2size[paracgsize]>4 then
message(parser_e_location_size_too_small);
paraloc^.loc:=LOC_REFERENCE;
paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
paraloc^.reference.offset:=offset;
end
{ 'R12' is special, used internally to support regbase and nobase
calling convention }
else if lowercase(s)='r12' then
begin
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_R12;
end
paraloc^.loc:=LOC_REFERENCE;
paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
paraloc^.reference.offset:=offset_lo;
end;
5: begin
{ 64bit register pair, used by AmiSSL 68k for example }
offset_hi:=parse68kregname(1);
offset_lo:=parse68kregname(4);
if (not (s[3] in [':','-'])) or
(offset_lo<0) or (offset_hi<0) then
message(parser_e_illegal_explicit_paraloc);
if offset_lo>=(8*sizeof(pint)) then
message(parser_e_location_regpair_only_data);
if (offset_lo-offset_hi)<>4 then
message(parser_e_location_regpair_only_consecutive);
if tcgsize2size[paracgsize]<=4 then
message(parser_w_location_size_too_large);
if tcgsize2size[paracgsize]>8 then
message(parser_e_location_size_too_small);
paraloc^.loc:=LOC_REFERENCE;
paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
paraloc^.reference.offset:=offset_hi;
paraloc^.size:=OS_64;
end;
else
exit;
begin
{ 'R12' is special, used internally to support regbase and nobase
calling convention }
if lowercase(s)='r12' then
begin
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=NR_R12;
end
else
exit; { error, cannot parse }
end;
end;
{ copy to callee side }
p.paraloc[calleeside].add_location^:=paraloc^;