o patch for Xtensa by Christo Crause, resolves #37099

+ Added postfix parsing in tattreader.GetToken
    - Removed all postfixed versions of OpCodes from the instruction list
    + Added all missing OpCodes from Xtensa ISA
    * Changed branch OpCode to A_B, similar to ARM
    + Added missing branch condition flags BCI and BSI
    * Updated existing compiler code that referred to the old postfixed instructions
    + Added prefix and postfix handling in TxtensaInstrWriter.WriteInstruction
    * Updated TCPUAddNode.second_addfloat to specify .S postfix
    * Updated tcpuunaryminusnode.second_float to specify .S postfix
    + Implemented prefix and postfix identification in txtensaattreader.is_asmopcode
    * Adapted branch condition extraction to respect postfixes
    * Changed itcpugas to call findreg_by_name_table from raatt.pas (same as issue #0037121, difficult to test these changes without including a fix for the register name search problem)

git-svn-id: trunk@45672 -
This commit is contained in:
florian 2020-06-21 14:51:40 +00:00
parent cc7b6d0b05
commit a7c0fa0def
14 changed files with 579 additions and 163 deletions

1
.gitattributes vendored
View File

@ -18326,6 +18326,7 @@ tests/webtbs/tw3708.pp svneol=native#text/plain
tests/webtbs/tw37085.pp svneol=native#text/pascal
tests/webtbs/tw37095.pp svneol=native#text/plain
tests/webtbs/tw37095d/uw37095.pp svneol=native#text/plain
tests/webtbs/tw37099.pp svneol=native#text/pascal
tests/webtbs/tw37107.pp svneol=native#text/pascal
tests/webtbs/tw37136.pp svneol=native#text/pascal
tests/webtbs/tw37154.pp svneol=native#text/pascal

View File

@ -346,6 +346,23 @@ unit raatt;
end;
end;
{$endif riscv}
{$ifdef xtensa}
{
Xtensa can have multiple postfixes
MULA.DD.LL.LDDEC
or postfixes with numbers
RSR.CCOMPARE2
}
case c of
'.':
begin
repeat
actasmpattern:=actasmpattern+c;
c:=current_scanner.asmgetchar;
until not(c in ['a'..'z','A'..'Z', '0'..'9', '.']);
end;
end;
{$endif xtensa}
{ Opcode ? }
If is_asmopcode(upper(actasmpattern)) then
Begin

View File

@ -39,6 +39,8 @@ uses
type
taicpu = class(tai_cpu_abstract_sym)
oppostfix : TOpPostfix;
opIsPrefixed : boolean;
constructor op_none(op : tasmop);
constructor op_reg(op : tasmop;_op1 : tregister);
@ -420,11 +422,11 @@ uses cutils, cclasses;
case regtype of
R_INTREGISTER:
result:=
(opcode=A_MOV) and
(opcode=A_MOV) and (oppostfix in [PF_None, PF_N]) and
(oper[0]^.reg=oper[1]^.reg);
R_FPUREGISTER:
result:=
(opcode=A_MOV_S) and
(opcode=A_MOV) and (oppostfix=PF_S) and
(oper[0]^.reg=oper[1]^.reg);
else
result:=false;
@ -443,7 +445,7 @@ uses cutils, cclasses;
A_S16I,
A_S32I,
A_SSI,
A_Bcc:
A_B:
result := operand_read;
else
;

View File

@ -140,15 +140,19 @@ unit agcpugas;
Procedure TXtensaInstrWriter.WriteInstruction(hp : tai);
var op: TAsmOp;
postfix,s: string;
s: string;
i: byte;
sep: string[3];
begin
op:=taicpu(hp).opcode;
postfix:='';
s:=#9+gas_op2str[op];
if taicpu(hp).opIsPrefixed then
s:=#9'_'+gas_op2str[op]
else
s:=#9+gas_op2str[op];
if taicpu(hp).condition<>C_None then
s:=s+cond2str[taicpu(hp).condition];
if taicpu(hp).oppostfix <> PF_None then
s:=s+'.'+oppostfix2str[taicpu(hp).oppostfix];
if taicpu(hp).ops<>0 then
begin
if length(s)<5 then

View File

@ -97,7 +97,7 @@ Const
StoreDst = 1;
aopt_uncondjmp = A_J;
aopt_condjmp = A_Bcc;
aopt_condjmp = A_B;
Implementation

View File

@ -597,7 +597,8 @@ implementation
tmpreg: TRegister;
begin
{ for now, we use A15 here, however, this is not save as it might contain an argument }
ai:=TAiCpu.op_sym_reg(A_J_L,current_asmdata.RefAsmSymbol(s,AT_FUNCTION),NR_A15);
ai:=TAiCpu.op_sym_reg(A_J,current_asmdata.RefAsmSymbol(s,AT_FUNCTION),NR_A15);
ai.oppostfix := PF_L; // if destination is too far for J then assembler can convert to JX
ai.is_jmp:=true;
list.Concat(ai);
end;
@ -607,7 +608,7 @@ implementation
var
instr: taicpu;
begin
instr:=taicpu.op_reg_sym(A_Bcc,f.register,l);
instr:=taicpu.op_reg_sym(A_B,f.register,l);
instr.condition:=flags_to_cond(f.flag);
list.concat(instr);
end;
@ -787,7 +788,7 @@ implementation
else
Internalerror(2020030801);
end;
instr:=taicpu.op_reg_sym(A_Bcc,reg,l);
instr:=taicpu.op_reg_sym(A_B,reg,l);
instr.condition:=op;
list.concat(instr);
end
@ -803,7 +804,7 @@ implementation
Internalerror(2020030801);
end;
instr:=taicpu.op_reg_const_sym(A_Bcc,reg,a,l);
instr:=taicpu.op_reg_const_sym(A_B,reg,a,l);
instr.condition:=op;
list.concat(instr);
end
@ -817,7 +818,7 @@ implementation
Internalerror(2020030801);
end;
instr:=taicpu.op_reg_const_sym(A_Bcc,reg,a,l);
instr:=taicpu.op_reg_const_sym(A_B,reg,a,l);
instr.condition:=op;
list.concat(instr);
end
@ -840,7 +841,7 @@ implementation
reg2:=tmpreg;
end;
instr:=taicpu.op_reg_reg_sym(A_Bcc,reg2,reg1,l);
instr:=taicpu.op_reg_reg_sym(A_B,reg2,reg1,l);
instr.condition:=TOpCmp2AsmCond[cmp_op];
list.concat(instr);
end;
@ -851,9 +852,12 @@ implementation
ai : taicpu;
begin
if l.bind in [AB_GLOBAL] then
begin
{ for now, we use A15 here, however, this is not save as it might contain an argument, I have not figured out a
solution yet }
ai:=taicpu.op_sym_reg(A_J_L,l,NR_A15)
ai:=taicpu.op_sym_reg(A_J,l,NR_A15);
ai.oppostfix := PF_L;
end
else
ai:=taicpu.op_sym(A_J,l);
ai.is_jmp:=true;
@ -1020,10 +1024,15 @@ implementation
procedure tcgcpu.a_loadfpu_reg_reg(list: TAsmList; fromsize,tosize: tcgsize; reg1, reg2: tregister);
var
ai: taicpu;
begin
if not(fromsize in [OS_32,OS_F32]) then
InternalError(2020032603);
list.concat(taicpu.op_reg_reg(A_MOV_S,reg2,reg1));
ai := taicpu.op_reg_reg(A_MOV,reg2,reg1);
ai.oppostfix := PF_S;
list.concat(ai);
end;
@ -1111,7 +1120,7 @@ implementation
list.concat(taicpu.op_reg_reg_reg(A_ADD, regdst.reghi, regsrc2.reghi, regsrc1.reghi));
current_asmdata.getjumplabel(no_carry);
instr:=taicpu.op_reg_reg_sym(A_Bcc,tmplo, regsrc2.reglo, no_carry);
instr:=taicpu.op_reg_reg_sym(A_B,tmplo, regsrc2.reglo, no_carry);
instr.condition:=C_GEU;
list.concat(instr);
list.concat(taicpu.op_reg_reg_const(A_ADDI, regdst.reghi, regdst.reghi, 1));
@ -1157,7 +1166,7 @@ implementation
list.concat(taicpu.op_reg_reg_reg(A_SUB, regdst.reghi, regsrc2.reghi, regsrc1.reghi));
current_asmdata.getjumplabel(no_carry);
instr:=taicpu.op_reg_reg_sym(A_Bcc, regsrc2.reglo, tmplo, no_carry);
instr:=taicpu.op_reg_reg_sym(A_B, regsrc2.reglo, tmplo, no_carry);
instr.condition:=C_GEU;
list.concat(instr);
list.concat(taicpu.op_reg_reg_const(A_ADDI, regdst.reghi, regdst.reghi, -1));
@ -1261,7 +1270,7 @@ implementation
list.concat(taicpu.op_reg_reg_const(A_ADDI, regdst.reghi, regsrc.reghi, 0));
current_asmdata.getjumplabel(no_carry);
instr:=taicpu.op_reg_reg_sym(A_Bcc,tmplo, regsrc.reglo, no_carry);
instr:=taicpu.op_reg_reg_sym(A_B,tmplo, regsrc.reglo, no_carry);
instr.condition:=C_GEU;
list.concat(instr);
list.concat(taicpu.op_reg_reg_const(A_ADDI, regdst.reghi, regdst.reghi, 1));

View File

@ -46,7 +46,7 @@ unit cpubase;
TAsmOp= {$i xtensaop.inc}
{ This should define the array of instructions as string }
op2strtable=array[tasmop] of string[11];
op2strtable=array[tasmop] of string[7];
const
{ First value of opcode enumeration }
@ -99,6 +99,70 @@ unit cpubase;
{$i rxtensadwa.inc}
);
{*****************************************************************************
Instruction post fixes
*****************************************************************************}
type
{ Xtensa instructions can have several instruction post fixes }
TOpPostfix = (PF_None,
{ On big-endian processors, convert encoded immediate value to little-endian.
For J.L, assembler tries to convert into J if target is within reach, else convert to JX }
PF_L,
{ Assembler to generate narrow version of instruction if possible }
PF_N,
{ Opcode operates on single precision floating point register(s)}
PF_S,
{ Indicate MUL operations involving MAC16 accumulator option }
PF_AA_LL, PF_AA_HL, PF_AA_LH, PF_AA_HH, PF_AD_LL, PF_AD_HL,
PF_AD_LH, PF_AD_HH, PF_DA_LL, PF_DA_HL, PF_DA_LH, PF_DA_HH,
PF_DD_LL, PF_DD_HL, PF_DD_LH, PF_DD_HH,
PF_DA_LL_LDDEC, PF_DA_HL_LDDEC, PF_DA_LH_LDDEC, PF_DA_HH_LDDEC,
PF_DA_LL_LDINC, PF_DA_HL_LDINC, PF_DA_LH_LDINC, PF_DA_HH_LDINC,
PF_DD_LL_LDDEC, PF_DD_HL_LDDEC, PF_DD_LH_LDDEC, PF_DD_HH_LDDEC,
PF_DD_LL_LDINC, PF_DD_HL_LDINC, PF_DD_LH_LDINC, PF_DD_HH_LDINC,
{ Special registers accessible via RSR, WSR & XSR instructions }
PF_ACCHI, PF_ACCLO, PF_ATOMCTL, PF_BR, PF_CCOMPARE0, PF_CCOMPARE1,
PF_CCOMPARE2, PF_CCOUNT, PF_CPENABLE, PF_DBREAKA0, PF_DBREAKA1,
PF_DBREAKC0, PF_DBREAKC1, PF_DDR, PF_DEBUGCAUSE, PF_DEPC,
PF_DTLBCFG, PF_EPC1, PF_EPC2, PF_EPC3, PF_EPC4, PF_EPC5, PF_EPC6,
PF_EPC7, PF_EPS2, PF_EPS3, PF_EPS4, PF_EPS5, PF_EPS6, PF_EPS7,
PF_EXCCAUSE, PF_EXCSAVE1, PF_EXCSAVE2, PF_EXCSAVE3, PF_EXCSAVE4,
PF_EXCSAVE5, PF_EXCSAVE6, PF_EXCSAVE7, PF_EXCVADDR, PF_IBREAKA0,
PF_IBREAKA1, PF_IBREAKENABLE, PF_ICOUNT, PF_ICOUNTLEVEL,
PF_INTCLEAR, PF_INTENABLE, PF_INTERRUPT, PF_INTSET, PF_ITLBCFG,
PF_LBEG, PF_LCOUNT, PF_LEND, PF_LITBASE, PF_M0, PF_M1, PF_M2,
PF_M3, PF_MECR, PF_MEPC, PF_MEPS, PF_MESAVE, PF_MESR, PF_MEVADDR,
PF_MISC0, PF_MISC1, PF_MISC2, PF_MISC3, PF_MMID, PF_PRID, PF_PS,
PF_PTEVADDR, PF_RASID, PF_SAR, PF_SCOMPARE1, PF_VECBASE,
PF_WINDOWBASE, PF_WINDOWSTART);
TOpPostfixes = set of TOpPostfix;
const
oppostfix2str : array[TOpPostfix] of string[12] = ('',
'l', 'n', 's',
'aa.ll', 'aa.hl', 'aa.lh', 'aa.hh', 'ad.ll', 'ad.hl',
'ad.lh', 'ad.hh', 'da.ll', 'da.hl', 'da.lh', 'da.hh',
'dd.ll', 'dd.hl', 'dd.lh', 'dd.hh', 'da.ll.lddec',
'da.hl.lddec', 'da.lh.lddec', 'da.hh.lddec', 'da.ll.ldinc',
'da.hl.ldinc', 'da.lh.ldinc', 'da.hh.ldinc', 'dd.ll.lddec',
'dd.hl.lddec', 'dd.lh.lddec', 'dd.hh.lddec', 'dd.ll.ldinc',
'dd.hl.ldinc', 'dd.lh.ldinc', 'dd.hh.ldinc',
'acchi', 'acclo', 'atomctl', 'br', 'ccompare0', 'ccompare1',
'ccompare2', 'ccount', 'cpenable', 'dbreaka0', 'dbreaka1',
'dbreakc0', 'dbreakc1', 'ddr', 'debugcause', 'depc',
'dtlbcfg', 'epc1', 'epc2', 'epc3', 'epc4', 'epc5', 'epc6',
'epc7', 'eps2', 'eps3', 'eps4', 'eps5', 'eps6', 'eps7',
'exccause', 'excsave1', 'excsave2', 'excsave3', 'excsave4',
'excsave5', 'excsave6', 'excsave7', 'excvaddr', 'ibreaka0',
'ibreaka1', 'ibreakenable', 'icount', 'icountlevel',
'intclear', 'intenable', 'interrupt', 'intset', 'itlbcfg',
'lbeg', 'lcount', 'lend', 'litbase', 'm0', 'm1', 'm2',
'm3', 'mecr', 'mepc', 'meps', 'mesave', 'mesr', 'mevaddr',
'misc0', 'misc1', 'misc2', 'misc3', 'mmid', 'prid', 'ps',
'ptevaddr', 'rasid', 'sar', 'scompare1', 'vecbase',
'windowbase', 'windowstart');
{*****************************************************************************
Conditions
*****************************************************************************}
@ -107,7 +171,7 @@ unit cpubase;
TAsmCond=(C_None,
C_EQ,C_NE,
C_GE,C_LT,C_GEU,C_LTU,
C_ANY,C_BNONE,C_ALL,C_NALL,C_BC,C_BS,
C_ANY,C_BNONE,C_ALL,C_NALL,C_BC,C_BS,C_BCI,C_BSI,
C_EQZ,C_NEZ,C_LTZ,C_GEZ,
C_EQI,C_NEI,C_LTI,C_GEI,C_LTUI,C_GEUI,
C_F,C_T
@ -126,7 +190,7 @@ unit cpubase;
cond2str : array[TAsmCond] of string[4]=('',
'eq','ne',
'ge','lt','geu','ltu',
'any','none','all','nall','bc','bs',
'any','none','all','nall','bc','bs','bci','bsi',
'eqz','nez','ltz','gez',
'eqi','nei','lti','gei','ltui','geui',
'f','t'
@ -135,7 +199,7 @@ unit cpubase;
uppercond2str : array[TAsmCond] of string[4]=('',
'EQ','NE',
'GE','LT','GEU','LTU',
'ANY','NONE','ALL','NALL','BC','BS',
'ANY','NONE','ALL','NALL','BC','BS', 'BCI','BSI',
'EQZ','NEZ','LTZ','GEZ',
'EQI','NEI','LTI','GEI','LTUI','GEUI',
'F','T'
@ -326,7 +390,7 @@ unit cpubase;
begin
{ This isn't 100% perfect because the arm allows jumps also by writing to PC=R15.
To overcome this problem we simply forbid that FPC generates jumps by loading R15 }
is_calljmp:= o in [A_Bcc,A_BT,A_CALL0,A_CALL4,A_CALL8,A_CALL12,A_CALLX0,A_CALLX4,A_CALLX8,A_CALLX12];
is_calljmp:= o in [A_B,A_CALL0,A_CALL4,A_CALL8,A_CALL12,A_CALLX0,A_CALLX4,A_CALLX8,A_CALLX12];
end;
@ -359,7 +423,7 @@ unit cpubase;
inverse: array[TAsmCond] of TAsmCond=(C_None,
C_NE,C_EQ,
C_LT,C_GE,C_LTU,C_GEU,
C_BNONE,C_ANY,C_NALL,C_BNONE,C_BS,C_BC,
C_BNONE,C_ANY,C_NALL,C_BNONE,C_BS,C_BC,C_BSI,C_BCI,
C_NEZ,C_EQZ,C_GEZ,C_LTZ,
C_NEI,C_EQI,C_GEI,C_LTI,C_GEUI,C_LTUI,

View File

@ -222,6 +222,7 @@ interface
op : TAsmOp;
cmpop,
singleprec , inv: boolean;
ai : taicpu;
begin
pass_left_and_right;
if (nf_swapped in flags) then
@ -234,36 +235,36 @@ interface
inv:=false;
case nodetype of
addn :
op:=A_ADD_S;
op:=A_ADD;
muln :
op:=A_MUL_S;
op:=A_MUL;
subn :
op:=A_SUB_S;
op:=A_SUB;
unequaln,
equaln:
begin
op:=A_OEQ_S;
op:=A_OEQ;
cmpop:=true;
end;
ltn:
begin
op:=A_OLT_S;
op:=A_OLT;
cmpop:=true;
end;
lten:
begin
op:=A_OLE_S;
op:=A_OLE;
cmpop:=true;
end;
gtn:
begin
op:=A_OLT_S;
op:=A_OLT;
swapleftright;
cmpop:=true;
end;
gten:
begin
op:=A_OLE_S;
op:=A_OLE;
swapleftright;
cmpop:=true;
end;
@ -288,7 +289,9 @@ interface
if cmpop then
begin
cg.getcpuregister(current_asmdata.CurrAsmList,location.resflags.register);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.resflags.register,left.location.register,right.location.register));
ai:=taicpu.op_reg_reg_reg(op,location.resflags.register,left.location.register,right.location.register);
ai.oppostfix:=PF_S;
current_asmdata.CurrAsmList.concat(ai);
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
if inv then
@ -296,7 +299,9 @@ interface
end
else
begin
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,left.location.register,right.location.register));
ai:=taicpu.op_reg_reg_reg(op,location.register,left.location.register,right.location.register);
ai.oppostfix := PF_S;
current_asmdata.CurrAsmList.concat(ai);
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end;
end;

View File

@ -119,6 +119,8 @@ implementation
end;
procedure tcpuunaryminusnode.second_float;
var
ai : taicpu;
begin
secondpass(left);
if (current_settings.fputype=fpu_soft) or (tfloatdef(left.resultdef).floattype<>s32real) or
@ -150,7 +152,9 @@ implementation
hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,false);
location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_NEG_S,location.register,left.location.register));
ai:=taicpu.op_reg_reg(A_NEG,location.register,left.location.register);
ai.oppostfix := PF_S;
current_asmdata.CurrAsmList.Concat(ai);
end;
end;

View File

@ -32,6 +32,9 @@ Unit racpugas;
type
txtensaattreader = class(tattreader)
actoppostfix : TOpPostfix;
actIsPrefixed: boolean;
function is_asmopcode(const s: string):boolean;override;
function is_register(const s:string):boolean;override;
// function is_targetdirective(const s: string): boolean; override;
@ -763,6 +766,8 @@ Unit racpugas;
begin
Opcode:=ActOpcode;
condition:=ActCondition;
oppostfix:=actoppostfix;
opIsPrefixed:=actIsPrefixed;
end;
{ We are reading operands, so opcode will be an AS_ID }
@ -800,32 +805,57 @@ Unit racpugas;
function txtensaattreader.is_asmopcode(const s: string):boolean;
//const
// { sorted by length so longer postfixes will match first }
// postfix2strsorted : array[1..70] of string[9] = (
// '.F32.S32','.F32.U32','.S32.F32','.U32.F32','.F64.S32','.F64.U32','.S32.F64','.U32.F64',
// '.F32.S16','.F32.U16','.S16.F32','.U16.F32','.F64.S16','.F64.U16','.S16.F64','.U16.F64',
// '.F32.F64','.F64.F32',
// '.I16','.I32','.I64','.S16','.S32','.S64','.U16','.U32','.U64','.F32','.F64',
// 'IAD','DBD','FDD','EAD','IAS','DBS','FDS','EAS','IAX','DBX','FDX','EAX',
// '.16','.32','.64','.I8','.S8','.U8','.P8',
// 'EP','SB','BT','SH','IA','IB','DA','DB','FD','FA','ED','EA',
// '.8','S','D','E','P','X','R','B','H','T');
//
// postfixsorted : array[1..70] of TOpPostfix = (
// PF_F32S32,PF_F32U32,PF_S32F32,PF_U32F32,PF_F64S32,PF_F64U32,PF_S32F64,PF_U32F64,
// PF_F32S16,PF_F32U16,PF_S16F32,PF_U16F32,PF_F64S16,PF_F64U16,PF_S16F64,PF_U16F64,
// PF_F32F64,PF_F64F32,
// PF_I16,PF_I32,
// PF_I64,PF_S16,PF_S32,PF_S64,PF_U16,PF_U32,PF_U64,PF_F32,
// PF_F64,PF_IAD,PF_DBD,PF_FDD,PF_EAD,
// PF_IAS,PF_DBS,PF_FDS,PF_EAS,PF_IAX,
// PF_DBX,PF_FDX,PF_EAX,PF_16,PF_32,
// PF_64,PF_I8,PF_S8,PF_U8,PF_P8,
// PF_EP,PF_SB,PF_BT,PF_SH,PF_IA,
// PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,
// PF_ED,PF_EA,PF_8,PF_S,PF_D,PF_E,
// PF_P,PF_X,PF_R,PF_B,PF_H,PF_T);
const
{ sorted by length so longer postfixes will match first }
postfix2strsorted : array[1..112] of string[13] = (
'IBREAKENABLE', 'DA.HH.LDDEC', 'DA.HH.LDINC', 'DA.HL.LDDEC', 'DA.HL.LDINC',
'DA.LH.LDDEC', 'DA.LH.LDINC', 'DA.LL.LDDEC', 'DA.LL.LDINC', 'DD.HH.LDDEC',
'DD.HH.LDINC', 'DD.HL.LDDEC', 'DD.HL.LDINC', 'DD.LH.LDDEC', 'DD.LH.LDINC',
'DD.LL.LDDEC', 'DD.LL.LDINC', 'ICOUNTLEVEL', 'WINDOWSTART', 'DEBUGCAUSE',
'WINDOWBASE', 'CCOMPARE0', 'CCOMPARE1', 'CCOMPARE2', 'INTENABLE',
'INTERRUPT', 'SCOMPARE1', 'CPENABLE', 'DBREAKA0', 'DBREAKA1',
'DBREAKC0', 'DBREAKC1', 'EXCCAUSE', 'EXCSAVE1', 'EXCSAVE2',
'EXCSAVE3', 'EXCSAVE4', 'EXCSAVE5', 'EXCSAVE6', 'EXCSAVE7',
'EXCVADDR', 'IBREAKA0', 'IBREAKA1', 'INTCLEAR', 'PTEVADDR',
'ATOMCTL', 'DTLBCFG', 'ITLBCFG', 'LITBASE', 'MEVADDR',
'VECBASE', 'CCOUNT', 'ICOUNT', 'INTSET', 'LCOUNT',
'MESAVE', 'AA.HH', 'AA.HL', 'AA.LH', 'AA.LL',
'ACCHI', 'ACCLO', 'AD.HH', 'AD.HL', 'AD.LH',
'AD.LL', 'DA.HH', 'DA.HL', 'DA.LH', 'DA.LL',
'DD.HH', 'DD.HL', 'DD.LH', 'DD.LL', 'MISC0',
'MISC1', 'MISC2', 'MISC3', 'RASID', 'DEPC',
'EPC1', 'EPC2', 'EPC3', 'EPC4', 'EPC5',
'EPC6', 'EPC7', 'EPS2', 'EPS3', 'EPS4',
'EPS5', 'EPS6', 'EPS7', 'LBEG', 'LEND',
'MECR', 'MEPC', 'MEPS', 'MESR', 'MMID',
'PRID', 'DDR', 'SAR', 'BR', 'M0',
'M1', 'M2', 'M3', 'PS', 'L',
'N', 'S');
postfixsorted : array[1..112] of TOpPostfix = (
PF_IBREAKENABLE, PF_DA_HH_LDDEC, PF_DA_HH_LDINC, PF_DA_HL_LDDEC, PF_DA_HL_LDINC,
PF_DA_LH_LDDEC, PF_DA_LH_LDINC, PF_DA_LL_LDDEC, PF_DA_LL_LDINC, PF_DD_HH_LDDEC,
PF_DD_HH_LDINC, PF_DD_HL_LDDEC, PF_DD_HL_LDINC, PF_DD_LH_LDDEC, PF_DD_LH_LDINC,
PF_DD_LL_LDDEC, PF_DD_LL_LDINC, PF_ICOUNTLEVEL, PF_WINDOWSTART, PF_DEBUGCAUSE,
PF_WINDOWBASE, PF_CCOMPARE0, PF_CCOMPARE1, PF_CCOMPARE2, PF_INTENABLE,
PF_INTERRUPT, PF_SCOMPARE1, PF_CPENABLE, PF_DBREAKA0, PF_DBREAKA1,
PF_DBREAKC0, PF_DBREAKC1, PF_EXCCAUSE, PF_EXCSAVE1, PF_EXCSAVE2,
PF_EXCSAVE3, PF_EXCSAVE4, PF_EXCSAVE5, PF_EXCSAVE6, PF_EXCSAVE7,
PF_EXCVADDR, PF_IBREAKA0, PF_IBREAKA1, PF_INTCLEAR, PF_PTEVADDR,
PF_ATOMCTL, PF_DTLBCFG, PF_ITLBCFG, PF_LITBASE, PF_MEVADDR,
PF_VECBASE, PF_CCOUNT, PF_ICOUNT, PF_INTSET, PF_LCOUNT,
PF_MESAVE, PF_AA_HH, PF_AA_HL, PF_AA_LH, PF_AA_LL,
PF_ACCHI, PF_ACCLO, PF_AD_HH, PF_AD_HL, PF_AD_LH,
PF_AD_LL, PF_DA_HH, PF_DA_HL, PF_DA_LH, PF_DA_LL,
PF_DD_HH, PF_DD_HL, PF_DD_LH, PF_DD_LL, PF_MISC0,
PF_MISC1, PF_MISC2, PF_MISC3, PF_RASID, PF_DEPC,
PF_EPC1, PF_EPC2, PF_EPC3, PF_EPC4, PF_EPC5,
PF_EPC6, PF_EPC7, PF_EPS2, PF_EPS3, PF_EPS4,
PF_EPS5, PF_EPS6, PF_EPS7, PF_LBEG, PF_LEND,
PF_MECR, PF_MEPC, PF_MEPS, PF_MESR, PF_MMID,
PF_PRID, PF_DDR, PF_SAR, PF_BR, PF_M0,
PF_M1, PF_M2, PF_M3, PF_PS, PF_L,
PF_N, PF_S);
var
j, j2 : longint;
@ -836,94 +866,81 @@ Unit racpugas;
{ making s a value parameter would break other assembler readers }
hs:=s;
is_asmopcode:=false;
{ clear op code }
actopcode:=A_None;
actopcode:=A_NONE;
actcondition:=C_None;
if hs[1]='B' then
actoppostfix := PF_None;
actIsPrefixed := false;
if hs[1]='_' then
begin
actIsPrefixed := true;
delete(hs, 1, 1);
end;
if (hs[1]='B') and not(hs='BREAK') then
begin
{ Branch condition can be followed by a postfix, e.g. BEQZ.N or BBSI.L }
j:=pos('.', hs);
if j < 2 then
j:=length(hs)
else
dec(j);
hs2:=copy(hs, 2, j-1);
for icond:=low(tasmcond) to high(tasmcond) do
begin
if copy(hs,2,length(hs)-1)=uppercond2str[icond] then
if hs2=uppercond2str[icond] then
begin
actopcode:=A_Bcc;
actopcode:=A_B;
actasmtoken:=AS_OPCODE;
actcondition:=icond;
is_asmopcode:=true;
exit;
end;
end;
end;
maxlen:=min(length(hs),7);
actopcode:=A_NONE;
j2:=maxlen;
hs2:=hs;
while j2>=1 do
begin
hs:=hs2;
while j2>=1 do
begin
actopcode:=tasmop(PtrUInt(iasmops.Find(copy(hs,1,j2))));
if actopcode<>A_NONE then
begin
actasmtoken:=AS_OPCODE;
{ strip op code }
delete(hs,1,j2);
dec(j2);
delete(hs, 1, j);
break;
end;
dec(j2);
end;
if actopcode=A_NONE then
exit;
end
else
begin
j2:=min(length(hs),7);
hs2:=hs;
while (j2>=1) and (actopcode=A_NONE) do
begin
{ search for condition, conditions are always 2 chars }
if length(hs)>1 then
hs:=hs2;
while j2>=1 do
begin
for icond:=low(tasmcond) to high(tasmcond) do
actopcode:=tasmop(PtrUInt(iasmops.Find(copy(hs,1,j2))));
if actopcode<>A_NONE then
begin
if copy(hs,1,2)=uppercond2str[icond] then
begin
actcondition:=icond;
{ strip condition }
delete(hs,1,2);
break;
end;
actasmtoken:=AS_OPCODE;
{ strip op code }
delete(hs,1,j2);
dec(j2);
break;
end;
dec(j2);
end;
end;
end;
if actopcode=A_NONE then
exit;
{ check for postfix }
if (length(hs)>0) then
begin
for j:=low(postfixsorted) to high(postfixsorted) do
begin
if copy(hs,2,length(postfix2strsorted[j]))=postfix2strsorted[j] then
begin
actoppostfix:=postfixsorted[j];
{ strip postfix }
delete(hs,1,length(postfix2strsorted[j])+1);
break;
end;
{ check for postfix }
//if (length(hs)>0) and (actoppostfix=PF_None) then
// begin
// for j:=low(postfixsorted) to high(postfixsorted) do
// begin
// if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
// begin
// actoppostfix:=postfixsorted[j];
// { strip postfix }
// delete(hs,1,length(postfix2strsorted[j]));
// break;
// end;
// end;
// end;
end;
{ check for format postfix }
//if length(hs)>0 then
// begin
// if copy(hs,1,2) = '.W' then
// begin
// actwideformat:=true;
// delete(hs,1,2);
// end;
// end;
{ if we stripped all postfixes, it's a valid opcode }
is_asmopcode:=length(hs)=0;
if is_asmopcode = true then
break;
end;
{ if we stripped all postfixes, it's a valid opcode }
is_asmopcode:=length(hs)=0;
end;

View File

@ -34,7 +34,12 @@ unit raxtensa;
TXtensaOperand=class(TOperand)
end;
{ TXtensaInstruction }
TXtensaInstruction=class(TInstruction)
oppostfix : toppostfix;
opIsPrefixed : boolean;
function ConcatInstruction(p:TAsmList) : tai;override;
end;
implementation
@ -42,4 +47,13 @@ unit raxtensa;
uses
aasmcpu;
{ TXtensaInstruction }
function TXtensaInstruction.ConcatInstruction(p:TAsmList) : tai;
begin
result:=inherited ConcatInstruction(p);
(result as taicpu).oppostfix:=oppostfix;
(result as taicpu).opIsPrefixed:=opIsPrefixed;
end;
end.

View File

@ -2,15 +2,20 @@
'',
'abs',
'add',
'addi',
'addmi',
'addx2',
'addx4',
'addx8',
'add.s',
'addi',
'addmi',
'all4',
'all8',
'and',
'andb',
'andbc',
'any4',
'any8',
'b',
'bt',
'break',
'call0',
'call4',
'call8',
@ -19,50 +24,169 @@
'callx4',
'callx8',
'callx12',
'ceil',
'clamps',
'dhi',
'dhu',
'dhwb',
'dhwbi',
'dii',
'diu',
'diwb',
'diwbi',
'dpfl',
'dpfr',
'dpfro',
'dpw',
'dpwo',
'dsync',
'entry',
'esync',
'excw',
'extui',
'extw',
'float',
'floor',
'idtlb',
'ihi',
'ihu',
'iii',
'iitlb',
'iiu',
'ill',
'ipf',
'ipfl',
'isync',
'j',
'jx',
'l8ui',
'l16si',
'l16ui',
'l32ai',
'l32e',
'l32i',
'l32r',
'ldct',
'lddec',
'ldinc',
'lict',
'licw',
'loop',
'loopgtz',
'loopnez',
'lsi',
'j',
'j.l',
'lsiu',
'lsx',
'lsxu',
'madd',
'max',
'maxu',
'memw',
'min',
'minu',
'mov',
'movsp',
'mov.s',
'movnez',
'moveqz',
'movf',
'movgez',
'movi',
'mul.s',
'movltz',
'movnez',
'movsp',
'movt',
'msub',
'mul',
'mul16',
'mula',
'mull',
'muls',
'mulsh',
'muluh',
'neg',
'neg.s',
'nop',
'oeq.s',
'ole.s',
'olt.s',
'nsa',
'nsau',
'oeq',
'ole',
'olt',
'or',
'orb',
'orbc',
'pdtlb',
'pitlb',
'quos',
'quou',
'rdtlb0',
'rdtlb1',
'rems',
'remu',
'ret',
'retw',
'rfdd',
'rfde',
'rfe',
'rfi',
'rfme',
'rfr',
'rfue',
'rfwo',
'rfwu',
'ritlb0',
'ritlb1',
'rotw',
'round',
'rsil',
'rsr',
'rur',
's8i',
's16i',
's32c1i',
's32e',
's32i',
's32ri',
'sdct',
'sext',
'sict',
'sicw',
'simcall',
'sll',
'slli',
'sra',
'srai',
'src',
'srl',
'srli',
'ssa8b',
'ssa8l',
'ssai',
'ssi',
'ssiu',
'ssl',
'ssr',
'ssx',
'ssxu',
'sub',
'sub.s',
'subx2',
'subx4',
'subx8',
'syscall',
'xor'
'trunc',
'ueq',
'ufloat',
'ule',
'ult',
'umul',
'un',
'utrunc',
'waiti',
'wdtlb',
'wer',
'wfr',
'witlb',
'wsr',
'wur',
'xor',
'xorb',
'xsr'
);

View File

@ -2,15 +2,20 @@
A_NONE,
A_ABS,
A_ADD,
A_ADDI,
A_ADDMI,
A_ADDX2,
A_ADDX4,
A_ADDX8,
A_ADD_S,
A_ADDI,
A_ADDMI,
A_ALL4,
A_ALL8,
A_AND,
A_Bcc,
A_BT,
A_ANDB,
A_ANDBC,
A_ANY4,
A_ANY8,
A_B,
A_BREAK,
A_CALL0,
A_CALL4,
A_CALL8,
@ -19,50 +24,169 @@ A_CALLX0,
A_CALLX4,
A_CALLX8,
A_CALLX12,
A_CEIL,
A_CLAMPS,
A_DHI,
A_DHU,
A_DHWB,
A_DHWBI,
A_DII,
A_DIU,
A_DIWB,
A_DIWBI,
A_DPFL,
A_DPFR,
A_DPFRO,
A_DPW,
A_DPWO,
A_DSYNC,
A_ENTRY,
A_ESYNC,
A_EXCW,
A_EXTUI,
A_EXTW,
A_FLOAT,
A_FLOOR,
A_IDTLB,
A_IHI,
A_IHU,
A_III,
A_IITLB,
A_IIU,
A_ILL,
A_IPF,
A_IPFL,
A_ISYNC,
A_J,
A_JX,
A_L8UI,
A_L16SI,
A_L16UI,
A_L32AI,
A_L32E,
A_L32I,
A_L32R,
A_LDCT,
A_LDDEC,
A_LDINC,
A_LICT,
A_LICW,
A_LOOP,
A_LOOPGTZ,
A_LOOPNEZ,
A_LSI,
A_J,
A_J_L,
A_LSIU,
A_LSX,
A_LSXU,
A_MADD,
A_MAX,
A_MAXU,
A_MEMW,
A_MIN,
A_MINU,
A_MOV,
A_MOVSP,
A_MOV_S,
A_MOVNEZ,
A_MOVEQZ,
A_MOVF,
A_MOVGEZ,
A_MOVI,
A_MUL_S,
A_MOVLTZ,
A_MOVNEZ,
A_MOVSP,
A_MOVT,
A_MSUB,
A_MUL,
A_MUL16,
A_MULA,
A_MULL,
A_MULS,
A_MULSH,
A_MULUH,
A_NEG,
A_NEG_S,
A_NOP,
A_OEQ_S,
A_OLE_S,
A_OLT_S,
A_NSA,
A_NSAU,
A_OEQ,
A_OLE,
A_OLT,
A_OR,
A_ORB,
A_ORBC,
A_PDTLB,
A_PITLB,
A_QUOS,
A_QUOU,
A_RDTLB0,
A_RDTLB1,
A_REMS,
A_REMU,
A_RET,
A_RETW,
A_RFDD,
A_RFDE,
A_RFE,
A_RFI,
A_RFME,
A_RFR,
A_RFUE,
A_RFWO,
A_RFWU,
A_RITLB0,
A_RITLB1,
A_ROTW,
A_ROUND,
A_RSIL,
A_RSR,
A_RUR,
A_S8I,
A_S16I,
A_S32C1I,
A_S32E,
A_S32I,
A_S32RI,
A_SDCT,
A_SEXT,
A_SICT,
A_SICW,
A_SIMCALL,
A_SLL,
A_SLLI,
A_SRA,
A_SRAI,
A_SRC,
A_SRL,
A_SRLI,
A_SSA8B,
A_SSA8L,
A_SSAI,
A_SSI,
A_SSIU,
A_SSL,
A_SSR,
A_SSX,
A_SSXU,
A_SUB,
A_SUB_S,
A_SUBX2,
A_SUBX4,
A_SUBX8,
A_SYSCALL,
A_XOR
A_TRUNC,
A_UEQ,
A_UFLOAT,
A_ULE,
A_ULT,
A_UMUL,
A_UN,
A_UTRUNC,
A_WAITI,
A_WDTLB,
A_WER,
A_WFR,
A_WITLB,
A_WSR,
A_WUR,
A_XOR,
A_XORB,
A_XSR
);

31
tests/webtbs/tw37099.pp Normal file
View File

@ -0,0 +1,31 @@
{ %cpu=xtensa }
{ %norun }
unit asmtest;
interface
procedure test;
implementation
procedure test; assembler;
label
lbl, lbl2;
asm
bbci.l a4, 7, lbl2
_bnez.n a4, lbl2
loopnez a5, lbl
beqz.n a2, lbl
add a4, a5, a6
lbl:
bt b9, lbl
sub.s f1, f9, f13
_loopgtz a3, lbl2
rsr.prid a2
extui a4, a3, 2, 1
lbl2:
mula.aa.ll a3, a4
end;
end.