diff --git a/.gitattributes b/.gitattributes index b47d6f600b..b1f1df8c8b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10946,6 +10946,7 @@ tests/webtbs/tw1820.pp svneol=native#text/plain tests/webtbs/tw18222.pp svneol=native#text/pascal tests/webtbs/tw1825.pp svneol=native#text/plain tests/webtbs/tw18266.pp svneol=native#text/plain +tests/webtbs/tw18334.pp svneol=native#text/plain tests/webtbs/tw18443.pp svneol=native#text/pascal tests/webtbs/tw1850.pp svneol=native#text/plain tests/webtbs/tw1851.pp svneol=native#text/plain diff --git a/compiler/aasmtai.pas b/compiler/aasmtai.pas index f2fa6c1dc9..d836a8d546 100644 --- a/compiler/aasmtai.pas +++ b/compiler/aasmtai.pas @@ -179,6 +179,7 @@ interface ,top_regset ,top_shifterop ,top_conditioncode + ,top_modeflags {$endif arm} {$ifdef m68k} { m68k only } @@ -214,7 +215,8 @@ interface {$ifdef arm} top_regset : (regset:^tcpuregisterset; regtyp: tregistertype; subreg: tsubregister); top_shifterop : (shifterop : pshifterop); - top_conditioncode: (cc: TAsmCond); + top_conditioncode : (cc : TAsmCond); + top_modeflags : (modeflags : tcpumodeflags); {$endif arm} {$ifdef m68k} top_regset : (regset:^tcpuregisterset); diff --git a/compiler/arm/aasmcpu.pas b/compiler/arm/aasmcpu.pas index bca288868c..5ced8fc361 100644 --- a/compiler/arm/aasmcpu.pas +++ b/compiler/arm/aasmcpu.pas @@ -163,6 +163,7 @@ uses procedure loadshifterop(opidx:longint;const so:tshifterop); procedure loadregset(opidx:longint; regsetregtype: tregistertype; regsetsubregtype: tsubregister; const s:tcpuregisterset); procedure loadconditioncode(opidx:longint;const cond:tasmcond); + procedure loadmodeflags(opidx:longint;const flags:tcpumodeflags); constructor op_none(op : tasmop); constructor op_reg(op : tasmop;_op1 : tregister); @@ -187,6 +188,10 @@ uses { ITxxx } constructor op_cond(op: tasmop; cond: tasmcond); + { CPSxx } + constructor op_modeflags(op: tasmop; flags: tcpumodeflags); + constructor op_modeflags_const(op: tasmop; flags: tcpumodeflags; a: aint); + { *M*LL } constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister); @@ -328,6 +333,17 @@ implementation end; end; + procedure taicpu.loadmodeflags(opidx: longint; const flags: tcpumodeflags); + begin + allocate_oper(opidx+1); + with oper[opidx]^ do + begin + if typ<>top_modeflags then + clearop(opidx); + modeflags:=flags; + typ:=top_modeflags; + end; + end; {***************************************************************************** taicpu Constructors @@ -448,6 +464,21 @@ implementation condition := cond; end; + constructor taicpu.op_modeflags(op: tasmop; flags: tcpumodeflags); + begin + inherited create(op); + ops := 1; + loadmodeflags(0,flags); + end; + + constructor taicpu.op_modeflags_const(op: tasmop; flags: tcpumodeflags; a: aint); + begin + inherited create(op); + ops := 2; + loadmodeflags(0,flags); + loadconst(1,a); + end; + constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint); begin diff --git a/compiler/arm/agarmgas.pas b/compiler/arm/agarmgas.pas index 645700ec92..930538a1b6 100644 --- a/compiler/arm/agarmgas.pas +++ b/compiler/arm/agarmgas.pas @@ -204,6 +204,13 @@ unit agarmgas; end; top_conditioncode: getopstr:=cond2str[o.cc]; + top_modeflags: + begin + getopstr:=''; + if mfA in o.modeflags then getopstr:=getopstr+'a'; + if mfI in o.modeflags then getopstr:=getopstr+'i'; + if mfF in o.modeflags then getopstr:=getopstr+'f'; + end; top_ref: if o.ref^.refaddr=addr_full then begin diff --git a/compiler/arm/armatt.inc b/compiler/arm/armatt.inc index e986c73835..e030dd95d3 100644 --- a/compiler/arm/armatt.inc +++ b/compiler/arm/armatt.inc @@ -23,6 +23,9 @@ 'clz', 'cnf', 'cos', +'cps', +'cpsid', +'cpsie', 'dvf', 'eor', 'exp', diff --git a/compiler/arm/armatts.inc b/compiler/arm/armatts.inc index 3eea426e48..b5adf84b9a 100644 --- a/compiler/arm/armatts.inc +++ b/compiler/arm/armatts.inc @@ -199,5 +199,8 @@ attsufNONE, attsufNONE, attsufNONE, attsufNONE, +attsufNONE, +attsufNONE, +attsufNONE, attsufNONE ); diff --git a/compiler/arm/armins.dat b/compiler/arm/armins.dat index a40e6f5af1..3db632aaf7 100644 --- a/compiler/arm/armins.dat +++ b/compiler/arm/armins.dat @@ -162,6 +162,10 @@ reg32,reg32 \x27\x01\x01 ARM7 [COScc] +[CPS] +[CPSID] +[CPSIE] + [DVFcc] [EORcc] diff --git a/compiler/arm/armop.inc b/compiler/arm/armop.inc index 3d873fd257..e43d1231a1 100644 --- a/compiler/arm/armop.inc +++ b/compiler/arm/armop.inc @@ -23,6 +23,9 @@ A_CMP, A_CLZ, A_CNF, A_COS, +A_CPS, +A_CPSID, +A_CPSIE, A_DVF, A_EOR, A_EXP, diff --git a/compiler/arm/cpubase.pas b/compiler/arm/cpubase.pas index 276c42557d..7c167b0e7b 100644 --- a/compiler/arm/cpubase.pas +++ b/compiler/arm/cpubase.pas @@ -203,6 +203,9 @@ unit cpubase; shiftimm : byte; end; + tcpumodeflag = (mfA, mfI, mfF); + tcpumodeflags = set of tcpumodeflag; + {***************************************************************************** Constants *****************************************************************************} diff --git a/compiler/arm/raarmgas.pas b/compiler/arm/raarmgas.pas index 8aff410460..91030638e6 100644 --- a/compiler/arm/raarmgas.pas +++ b/compiler/arm/raarmgas.pas @@ -672,6 +672,38 @@ Unit raarmgas; end; end; + + function is_modeflag(hs : string): boolean; + var + i: longint; + flags: tcpumodeflags; + begin + is_modeflag := false; + + flags:=[]; + hs:=lower(hs); + + if (actopcode in [A_CPSID,A_CPSIE]) and (length(hs) >= 1) then + begin + for i:=1 to length(hs) do + begin + case hs[i] of + 'a': + Include(flags,mfA); + 'f': + Include(flags,mfF); + 'i': + Include(flags,mfI); + else + exit; + end; + end; + oper.opr.typ := OPR_MODEFLAGS; + oper.opr.flags := flags; + exit(true); + end; + end; + var tempreg : tregister; ireg : tsuperregister; @@ -716,11 +748,16 @@ Unit raarmgas; *) AS_ID: { A constant expression, or a Variable ref. } Begin + if is_modeflag(actasmpattern) then + begin + consume(AS_ID); + end + else { Condition code? } if is_conditioncode(actasmpattern) then - begin - consume(AS_ID); - end + begin + consume(AS_ID); + end else { Local Label ? } if is_locallabel(actasmpattern) then diff --git a/compiler/rautils.pas b/compiler/rautils.pas index e687489bf2..3134de1aed 100644 --- a/compiler/rautils.pas +++ b/compiler/rautils.pas @@ -65,7 +65,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_REFERENCE,OPR_REGISTER,OPR_REGLIST,OPR_COND,OPR_REGSET,OPR_SHIFTEROP,OPR_MODEFLAGS); TOprRec = record case typ:TOprType of @@ -88,6 +88,7 @@ type OPR_REGSET : (regset : tcpuregisterset; regtype: tregistertype; subreg: tsubregister); OPR_SHIFTEROP : (shifterop : tshifterop); OPR_COND : (cc : tasmcond); + OPR_MODEFLAGS : (flags : tcpumodeflags); {$endif arm} end; @@ -1067,6 +1068,8 @@ end; ai.loadshifterop(i-1,shifterop); OPR_COND: ai.loadconditioncode(i-1,cc); + OPR_MODEFLAGS: + ai.loadmodeflags(i-1,flags); {$endif ARM} { ignore wrong operand } OPR_NONE: diff --git a/tests/webtbs/tw18334.pp b/tests/webtbs/tw18334.pp new file mode 100644 index 0000000000..bf4202b6f3 --- /dev/null +++ b/tests/webtbs/tw18334.pp @@ -0,0 +1,14 @@ +{ %cpu=arm } +{ %norun } + +procedure test; assembler; + asm + cps #0 + cpsie aif, #0 + cpsid aif, #0 + cpsie aif + cpsid aif + end; + +begin +end.