Browse Source

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 -

florian 5 years ago
parent
commit
a7c0fa0def

+ 1 - 0
.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

+ 17 - 0
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

+ 5 - 3
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
             ;

+ 7 - 3
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

+ 1 - 1
compiler/xtensa/aoptcpub.pas

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

+ 20 - 11
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));

+ 70 - 6
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,

+ 15 - 10
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;

+ 5 - 1
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;
 

+ 107 - 90
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;
+                    delete(hs, 1, j);
+                    break;
                   end;
               end;
-          end;
-        maxlen:=min(length(hs),7);
-        actopcode:=A_NONE;
-        j2:=maxlen;
-        hs2:=hs;
-        while j2>=1 do
+          end
+        else
           begin
-            hs:=hs2;
-            while j2>=1 do
+            j2:=min(length(hs),7);
+            hs2:=hs;
+            while (j2>=1) and (actopcode=A_NONE) do
               begin
-                actopcode:=tasmop(PtrUInt(iasmops.Find(copy(hs,1,j2))));
-                if actopcode<>A_NONE then
+                hs:=hs2;
+                while j2>=1 do
                   begin
-                    actasmtoken:=AS_OPCODE;
-                    { strip op code }
-                    delete(hs,1,j2);
+                    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);
+                        break;
+                      end;
                     dec(j2);
-                    break;
                   end;
-                dec(j2);
               end;
+            end;
 
-            if actopcode=A_NONE then
-              exit;
+        if actopcode=A_NONE then
+          exit;
 
+        { check for postfix }
+        if (length(hs)>0) then
+          begin
+            for j:=low(postfixsorted) to high(postfixsorted) do
               begin
-                { search for condition, conditions are always 2 chars }
-                if length(hs)>1 then
+                if copy(hs,2,length(postfix2strsorted[j]))=postfix2strsorted[j] then
                   begin
-                    for icond:=low(tasmcond) to high(tasmcond) do
-                      begin
-                        if copy(hs,1,2)=uppercond2str[icond] then
-                          begin
-                            actcondition:=icond;
-                            { strip condition }
-                            delete(hs,1,2);
-                            break;
-                          end;
-                      end;
+                    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;
 
 

+ 14 - 0
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.

+ 140 - 16
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'
 );
 
 

+ 141 - 17
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
 );
 
 

+ 31 - 0
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.
+