From a7c0fa0deffdb9341c31c45bd3f1918faa42bab5 Mon Sep 17 00:00:00 2001 From: florian Date: Sun, 21 Jun 2020 14:51:40 +0000 Subject: [PATCH] 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 - --- .gitattributes | 1 + compiler/raatt.pas | 17 +++ compiler/xtensa/aasmcpu.pas | 8 +- compiler/xtensa/agcpugas.pas | 10 +- compiler/xtensa/aoptcpub.pas | 2 +- compiler/xtensa/cgcpu.pas | 31 +++-- compiler/xtensa/cpubase.pas | 76 ++++++++++++- compiler/xtensa/ncpuadd.pas | 25 ++-- compiler/xtensa/ncpumat.pas | 6 +- compiler/xtensa/racpugas.pas | 207 ++++++++++++++++++---------------- compiler/xtensa/raxtensa.pas | 14 +++ compiler/xtensa/xtensaatt.inc | 156 ++++++++++++++++++++++--- compiler/xtensa/xtensaop.inc | 158 +++++++++++++++++++++++--- tests/webtbs/tw37099.pp | 31 +++++ 14 files changed, 579 insertions(+), 163 deletions(-) create mode 100644 tests/webtbs/tw37099.pp diff --git a/.gitattributes b/.gitattributes index bef85d4356..63764ac745 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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 diff --git a/compiler/raatt.pas b/compiler/raatt.pas index 8879694fed..5f02bb9b36 100644 --- a/compiler/raatt.pas +++ b/compiler/raatt.pas @@ -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 diff --git a/compiler/xtensa/aasmcpu.pas b/compiler/xtensa/aasmcpu.pas index 86897c7fdc..de4e30e9f4 100644 --- a/compiler/xtensa/aasmcpu.pas +++ b/compiler/xtensa/aasmcpu.pas @@ -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 ; diff --git a/compiler/xtensa/agcpugas.pas b/compiler/xtensa/agcpugas.pas index ad54b48abf..f6cc381962 100644 --- a/compiler/xtensa/agcpugas.pas +++ b/compiler/xtensa/agcpugas.pas @@ -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 diff --git a/compiler/xtensa/aoptcpub.pas b/compiler/xtensa/aoptcpub.pas index df5730d8ca..fb2b3615bf 100644 --- a/compiler/xtensa/aoptcpub.pas +++ b/compiler/xtensa/aoptcpub.pas @@ -97,7 +97,7 @@ Const StoreDst = 1; aopt_uncondjmp = A_J; - aopt_condjmp = A_Bcc; + aopt_condjmp = A_B; Implementation diff --git a/compiler/xtensa/cgcpu.pas b/compiler/xtensa/cgcpu.pas index b8c37b3486..caa6e9cac9 100644 --- a/compiler/xtensa/cgcpu.pas +++ b/compiler/xtensa/cgcpu.pas @@ -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)); diff --git a/compiler/xtensa/cpubase.pas b/compiler/xtensa/cpubase.pas index 405e8c5883..bf55374580 100644 --- a/compiler/xtensa/cpubase.pas +++ b/compiler/xtensa/cpubase.pas @@ -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, diff --git a/compiler/xtensa/ncpuadd.pas b/compiler/xtensa/ncpuadd.pas index 7e8861b493..d06262ad69 100644 --- a/compiler/xtensa/ncpuadd.pas +++ b/compiler/xtensa/ncpuadd.pas @@ -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; diff --git a/compiler/xtensa/ncpumat.pas b/compiler/xtensa/ncpumat.pas index c96614e40e..4e88b7e6f2 100644 --- a/compiler/xtensa/ncpumat.pas +++ b/compiler/xtensa/ncpumat.pas @@ -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; diff --git a/compiler/xtensa/racpugas.pas b/compiler/xtensa/racpugas.pas index 521ab2112e..040781fa7a 100644 --- a/compiler/xtensa/racpugas.pas +++ b/compiler/xtensa/racpugas.pas @@ -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; diff --git a/compiler/xtensa/raxtensa.pas b/compiler/xtensa/raxtensa.pas index dbe7c6602b..72b01f37a7 100644 --- a/compiler/xtensa/raxtensa.pas +++ b/compiler/xtensa/raxtensa.pas @@ -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. diff --git a/compiler/xtensa/xtensaatt.inc b/compiler/xtensa/xtensaatt.inc index 801caab32c..ec94dde298 100644 --- a/compiler/xtensa/xtensaatt.inc +++ b/compiler/xtensa/xtensaatt.inc @@ -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' ); diff --git a/compiler/xtensa/xtensaop.inc b/compiler/xtensa/xtensaop.inc index 5716f4ecb5..b03bd1408f 100644 --- a/compiler/xtensa/xtensaop.inc +++ b/compiler/xtensa/xtensaop.inc @@ -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 ); diff --git a/tests/webtbs/tw37099.pp b/tests/webtbs/tw37099.pp new file mode 100644 index 0000000000..e140e4a7cc --- /dev/null +++ b/tests/webtbs/tw37099.pp @@ -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. +