* fix handling of register sets on m68k: it is required that they are stored as two tcpuregistersets because address registers and data registers have different register types

git-svn-id: trunk@25726 -
This commit is contained in:
florian 2013-10-09 18:15:06 +00:00
parent 6f474e525c
commit babbc21afd
5 changed files with 102 additions and 64 deletions

View File

@ -273,7 +273,7 @@ interface
top_shifterop : (shifterop : pshifterop);
{$endif defined(arm) or defined(aarch64)}
{$ifdef m68k}
top_regset : (regset:^tcpuregisterset);
top_regset : (dataregset,addrregset:^tcpuregisterset);
{$endif m68k}
{$ifdef jvm}
top_single : (sval:single);
@ -2626,6 +2626,13 @@ implementation
top_regset:
dispose(regset);
{$endif ARM}
{$ifdef m68k}
top_regset:
begin
dispose(dataregset);
dispose(addrregset);
end;
{$endif m68k}
{$ifdef jvm}
top_string:
freemem(pcval);

View File

@ -40,6 +40,9 @@ type
taicpu = class(tai_cpu_abstract_sym)
opsize : topsize;
procedure loadregset(opidx:longint; const dataregs,addrregs:tcpuregisterset);
constructor op_none(op : tasmop);
constructor op_none(op : tasmop;_size : topsize);
@ -65,11 +68,11 @@ type
constructor op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister; _op3 : treference);
constructor op_const_reg_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : treference);
constructor op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2: tcpuregisterset);
constructor op_regset_reg(op: tasmop; _size : topsize;const _op1: tcpuregisterset; _op2: tregister);
constructor op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2data,_op2addr: tcpuregisterset);
constructor op_regset_reg(op: tasmop; _size : topsize;const _op1data,_op1addr: tcpuregisterset; _op2: tregister);
constructor op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2: tcpuregisterset);
constructor op_regset_ref(op: tasmop; _size : topsize;const _op1: tcpuregisterset; _op2: treference);
constructor op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2data,_op2addr: tcpuregisterset);
constructor op_regset_ref(op: tasmop; _size : topsize;const _op1data,_op1addr: tcpuregisterset; _op2: treference);
{ this is for Jmp instructions }
constructor op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
@ -86,7 +89,6 @@ type
function spilling_get_operation_type(opnr: longint): topertype;override;
private
procedure loadregset(opidx:longint;const s:tcpuregisterset);
procedure init(_size : topsize); { this need to be called by all constructor }
end;
@ -168,7 +170,7 @@ type
procedure taicpu.loadregset(opidx:longint;const s:tcpuregisterset);
procedure taicpu.loadregset(opidx:longint; const dataregs,addrregs:tcpuregisterset);
var
i : byte;
begin
@ -177,17 +179,19 @@ type
begin
if typ<>top_regset then
clearop(opidx);
new(regset);
regset^:=s;
new(dataregset);
new(addrregset);
dataregset^:=dataregs;
addrregset^:=addrregs;
typ:=top_regset;
for i:=RS_D0 to RS_D7 do
begin
if assigned(add_reg_instruction_hook) and (i in regset^) then
if assigned(add_reg_instruction_hook) and (i in dataregset^) then
add_reg_instruction_hook(self,newreg(R_INTREGISTER,i,R_SUBWHOLE));
end;
for i:=RS_A0 to RS_SP do
begin
if assigned(add_reg_instruction_hook) and (i in regset^) then
if assigned(add_reg_instruction_hook) and (i in addrregset^) then
add_reg_instruction_hook(self,newreg(R_ADDRESSREGISTER,i,R_SUBWHOLE));
end;
end;
@ -377,42 +381,43 @@ type
end;
constructor taicpu.op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2: tcpuregisterset);
constructor taicpu.op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2data,_op2addr: tcpuregisterset);
Begin
inherited create(op);
init(_size);
ops:=2;
loadref(0,_op1);
loadregset(1,_op2);
loadregset(1,_op2data,_op2addr);
end;
constructor taicpu.op_regset_ref(op: tasmop; _size : topsize;const _op1: tcpuregisterset; _op2: treference);
constructor taicpu.op_regset_ref(op: tasmop; _size : topsize;const _op1data,_op1addr: tcpuregisterset; _op2: treference);
Begin
inherited create(op);
init(_size);
ops:=2;
loadregset(0,_op1);
loadregset(0,_op1data,_op1addr);
loadref(1,_op2);
End;
constructor taicpu.op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2: tcpuregisterset);
constructor taicpu.op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2data,_op2addr: tcpuregisterset);
Begin
inherited create(op);
init(_size);
ops:=2;
loadreg(0,_op1);
loadregset(1,_op2);
loadregset(1,_op2data,_op2addr);
end;
constructor taicpu.op_regset_reg(op: tasmop; _size : topsize;const _op1: tcpuregisterset; _op2: tregister);
constructor taicpu.op_regset_reg(op: tasmop; _size : topsize;const _op1data,_op1addr: tcpuregisterset; _op2: tregister);
Begin
inherited create(op);
init(_size);
ops:=2;
loadregset(0,_op1);
loadregset(0,_op1data,_op1addr);
loadreg(1,_op2);
End;

View File

@ -229,12 +229,12 @@ interface
hs:='';
for i:=RS_D0 to RS_D7 do
begin
if i in o.regset^ then
if i in o.dataregset^ then
hs:=hs+gas_regname(newreg(R_INTREGISTER,i,R_SUBWHOLE))+'/';
end;
for i:=RS_A0 to RS_SP do
begin
if i in o.regset^ then
if i in o.addrregset^ then
hs:=hs+gas_regname(newreg(R_INTREGISTER,i,R_SUBWHOLE))+'/';
end;
delete(hs,length(hs),1);

View File

@ -1283,10 +1283,11 @@ const
r:Tregister;
hl: tasmlabel;
reg_one, reg_two: tregister;
regset: tcpuregisterset;
addrregset,dataregset: tcpuregisterset;
p: pointer;
begin
regset := [];
dataregset := [];
addrregset := [];
tempstr := '';
case actasmtoken of
{ // Memory reference // }
@ -1477,21 +1478,28 @@ const
if (actasmtoken = AS_SLASH) then
begin
r:=actasmregister;
if getregtype(r)<>R_INTREGISTER then
if getregtype(r)=R_ADDRESSREGISTER then
include(addrregset,getsupreg(r))
else if getregtype(r)=R_INTREGISTER then
include(dataregset,getsupreg(r))
else
internalerror(200302191);
include(regset,getsupreg(r));
Consume(AS_SLASH);
if actasmtoken = AS_REGISTER then
begin
While not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
begin
case actasmtoken of
AS_REGISTER: begin
if getregtype(r)<>R_INTREGISTER then
internalerror(200302191);
include(regset,getsupreg(r));
Consume(AS_REGISTER);
end;
AS_REGISTER:
begin
if getregtype(r)=R_ADDRESSREGISTER then
include(addrregset,getsupreg(r))
else if getregtype(r)=R_INTREGISTER then
include(dataregset,getsupreg(r))
else
Message(asmr_e_invalid_reg_list_in_movem);
Consume(AS_REGISTER);
end;
AS_SLASH: Consume(AS_SLASH);
AS_SEPARATOR,AS_COMMA: break;
else
@ -1502,14 +1510,15 @@ const
end; { end case }
end; { end while }
oper.opr.typ:= OPR_regset;
oper.opr.regset := regset;
oper.opr.regsetdata := dataregset;
oper.opr.regsetaddr := addrregset;
end
else
{ error recovery ... }
begin
Message(asmr_e_invalid_reg_list_in_movem);
while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
Consume(actasmtoken);
Message(asmr_e_invalid_reg_list_in_movem);
while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
Consume(actasmtoken);
end;
end
else
@ -1519,34 +1528,47 @@ const
Consume(AS_MINUS);
reg_one:=actasmregister;
if actasmtoken <> AS_REGISTER then
begin
Message(asmr_e_invalid_reg_list_in_movem);
while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
Consume(actasmtoken);
end
begin
Message(asmr_e_invalid_reg_list_in_movem);
while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
Consume(actasmtoken);
end
else
begin
{ determine the register range ... }
reg_two:=actasmregister;
if getregtype(reg_two)<>R_INTREGISTER then
internalerror(200302191);
if getsupreg(reg_one) > getsupreg(reg_two) then
for i:=getsupreg(reg_two) to getsupreg(reg_one) do
include(regset,i)
else
for i:=getsupreg(reg_one) to getsupreg(reg_two) do
include(regset,i);
Consume(AS_REGISTER);
if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
begin
Message(asmr_e_invalid_reg_list_in_movem);
while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
Consume(actasmtoken);
end;
{ set up instruction }
oper.opr.typ:= OPR_regset;
oper.opr.regset := regset;
end;
begin
{ determine the register range ... }
reg_two:=actasmregister;
if getregtype(r)=R_ADDRESSREGISTER then
begin
if getsupreg(reg_one) > getsupreg(reg_two) then
for i:=getsupreg(reg_two) to getsupreg(reg_one) do
include(addrregset,i)
else
for i:=getsupreg(reg_one) to getsupreg(reg_two) do
include(addrregset,i);
end
else if getregtype(r)=R_INTREGISTER then
begin
if getsupreg(reg_one) > getsupreg(reg_two) then
for i:=getsupreg(reg_two) to getsupreg(reg_one) do
include(dataregset,i)
else
for i:=getsupreg(reg_one) to getsupreg(reg_two) do
include(dataregset,i);
end
else
Message(asmr_e_invalid_reg_list_in_movem);
Consume(AS_REGISTER);
if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
begin
Message(asmr_e_invalid_reg_list_in_movem);
while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
Consume(actasmtoken);
end;
{ set up instruction }
oper.opr.typ:= OPR_regset;
oper.opr.regsetdata := dataregset;
oper.opr.regsetaddr := addrregset;
end;
end
else
{ DIVSL/DIVS/MULS/MULU with long for MC68020 only }

View File

@ -72,7 +72,7 @@ Function SearchLabel(const s: string; var hl: tasmlabel;emit:boolean): boolean;
type
TOprType=(OPR_NONE,OPR_CONSTANT,OPR_SYMBOL,OPR_LOCAL,
OPR_REFERENCE,OPR_REGISTER,OPR_REGLIST,OPR_COND,OPR_REGSET,OPR_SHIFTEROP,OPR_MODEFLAGS,OPR_SPECIALREG);
OPR_REFERENCE,OPR_REGISTER,OPR_COND,OPR_REGSET,OPR_SHIFTEROP,OPR_MODEFLAGS,OPR_SPECIALREG);
TOprRec = record
case typ:TOprType of
@ -83,7 +83,7 @@ type
OPR_LOCAL : (localvarsize, localconstoffset: asizeint;localsym:tabstractnormalvarsym;localsymofs:aint;localindexreg:tregister;localscale:byte;localgetoffset,localforceref:boolean);
OPR_REGISTER : (reg:tregister);
{$ifdef m68k}
OPR_REGLIST : (regset : tcpuregisterset);
OPR_REGSET : (regsetdata,regsetaddr : tcpuregisterset);
{$endif m68k}
{$ifdef powerpc}
OPR_COND : (cond : tasmcond);
@ -1115,6 +1115,10 @@ end;
localscale,localgetoffset,localforceref);
OPR_REFERENCE:
ai.loadref(i-1,ref);
{$ifdef m68k}
OPR_REGSET:
ai.loadregset(i-1,regsetdata,regsetaddr);
{$endif}
{$ifdef ARM}
OPR_REGSET:
ai.loadregset(i-1,regtype,subreg,regset,usermode);