diff --git a/.gitattributes b/.gitattributes index 56b4696862..98e66ed863 100644 --- a/.gitattributes +++ b/.gitattributes @@ -16055,6 +16055,7 @@ tests/webtbs/tw3328a.pp svneol=native#text/plain tests/webtbs/tw3328b.pp svneol=native#text/plain tests/webtbs/tw3334.pp svneol=native#text/plain tests/webtbs/tw3340.pp svneol=native#text/plain +tests/webtbs/tw33417.pp svneol=native#text/pascal tests/webtbs/tw3348.pp svneol=native#text/plain tests/webtbs/tw3349.pp svneol=native#text/plain tests/webtbs/tw3351.pp svneol=native#text/plain diff --git a/compiler/avr/navrmat.pas b/compiler/avr/navrmat.pas index f63f96d7f9..20dd95ab6e 100644 --- a/compiler/avr/navrmat.pas +++ b/compiler/avr/navrmat.pas @@ -59,37 +59,71 @@ implementation var tmpreg,lreg : tregister; i : longint; + falselabel,truelabel,skiplabel: TAsmLabel; begin if not handle_locjump then begin secondpass(left); - case left.location.loc of - LOC_FLAGS : - begin - location_copy(location,left.location); - inverse_flags(location.resflags); - end; - LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE, - LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF : - begin - hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true); - current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CPI,left.location.register,0)); + { short code? } + if (left.location.loc in [LOC_SUBSETREG,LOC_CSUBSETREG]) and + (left.location.sreg.bitlen=1) then + begin + current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_SBRC,left.location.sreg.subsetreg,left.location.sreg.startbit)); + current_asmdata.getjumplabel(truelabel); + current_asmdata.getjumplabel(falselabel); + { sbrc does a jump without an explicit label, + if we do not insert skiplabel here and increase its reference count, the optimizer removes the whole true block altogether } + current_asmdata.getjumplabel(skiplabel); + skiplabel.increfs; + location_reset_jump(location,truelabel,falselabel); + cg.a_jmp_always(current_asmdata.CurrAsmList,falselabel); + cg.a_jmp_always(current_asmdata.CurrAsmList,truelabel); + end + else if (left.location.loc in [LOC_SUBSETREF,LOC_CSUBSETREF]) and + (left.location.sref.bitlen=1) and (left.location.sref.bitindexreg=NR_NO) then + begin + tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_8); + hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,u8inttype,osuinttype,left.location.sref.ref,tmpreg); + current_asmdata.CurrAsmList.Concat(taicpu.op_reg_const(A_SBRC,tmpreg,left.location.sref.startbit)); + current_asmdata.getjumplabel(truelabel); + current_asmdata.getjumplabel(falselabel); + { sbrc does a jump without an explicit label, + if we do not insert skiplabel here and increase its reference count, the optimizer removes the whole true block altogether } + current_asmdata.getjumplabel(skiplabel); + skiplabel.increfs; + location_reset_jump(location,truelabel,falselabel); + cg.a_jmp_always(current_asmdata.CurrAsmList,falselabel); + cg.a_label(current_asmdata.CurrAsmList,skiplabel); + cg.a_jmp_always(current_asmdata.CurrAsmList,truelabel); + end + else + case left.location.loc of + LOC_FLAGS : + begin + location_copy(location,left.location); + inverse_flags(location.resflags); + end; + LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF, + LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE : + begin + hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true); + current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CPI,left.location.register,0)); - tmpreg:=left.location.register; - for i:=2 to tcgsize2size[left.location.size] do - begin - if i=5 then - tmpreg:=left.location.registerhi - else - tmpreg:=cg.GetNextReg(tmpreg); - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,NR_R1,tmpreg)); - end; - location_reset(location,LOC_FLAGS,OS_NO); - location.resflags:=F_EQ; + tmpreg:=left.location.register; + for i:=2 to tcgsize2size[left.location.size] do + begin + if i=5 then + tmpreg:=left.location.registerhi + else + tmpreg:=cg.GetNextReg(tmpreg); + current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,NR_R1,tmpreg)); + end; + location_reset(location,LOC_FLAGS,OS_NO); + location.resflags:=F_EQ; + end; + else + internalerror(2003042401); end; - else - internalerror(2003042401); - end; end; end; diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas index 8df2869dda..da61719785 100644 --- a/compiler/ncgutil.pas +++ b/compiler/ncgutil.pas @@ -253,11 +253,38 @@ implementation begin opsize:=def_cgsize(p.resultdef); case p.location.loc of - LOC_SUBSETREG,LOC_CSUBSETREG, + LOC_SUBSETREG,LOC_CSUBSETREG: + begin + if p.location.sreg.bitlen=1 then + begin + tmpreg:=cg.getintregister(list,p.location.sreg.subsetregsize); + hlcg.a_op_const_reg_reg(list,OP_AND,cgsize_orddef(p.location.sreg.subsetregsize),1 shl p.location.sreg.startbit,p.location.sreg.subsetreg,tmpreg); + end + else + begin + tmpreg:=cg.getintregister(list,OS_INT); + hlcg.a_load_loc_reg(list,p.resultdef,osuinttype,p.location,tmpreg); + end; + cg.a_cmp_const_reg_label(list,OS_INT,OC_NE,0,tmpreg,truelabel); + cg.a_jmp_always(list,falselabel); + end; LOC_SUBSETREF,LOC_CSUBSETREF: begin - tmpreg := cg.getintregister(list,OS_INT); - hlcg.a_load_loc_reg(list,p.resultdef,osuinttype,p.location,tmpreg); + if (p.location.sref.bitindexreg=NR_NO) and (p.location.sref.bitlen=1) then + begin + tmpreg:=cg.getintregister(list,OS_INT); + hlcg.a_load_ref_reg(list,u8inttype,osuinttype,p.location.sref.ref,tmpreg); + + if target_info.endian=endian_big then + hlcg.a_op_const_reg_reg(list,OP_AND,osuinttype,1 shl (8-(p.location.sref.startbit+1)),tmpreg,tmpreg) + else + hlcg.a_op_const_reg_reg(list,OP_AND,osuinttype,1 shl p.location.sref.startbit,tmpreg,tmpreg); + end + else + begin + tmpreg:=cg.getintregister(list,OS_INT); + hlcg.a_load_loc_reg(list,p.resultdef,osuinttype,p.location,tmpreg); + end; cg.a_cmp_const_reg_label(list,OS_INT,OC_NE,0,tmpreg,truelabel); cg.a_jmp_always(list,falselabel); end; diff --git a/tests/webtbs/tw33417.pp b/tests/webtbs/tw33417.pp new file mode 100644 index 0000000000..10834a6257 --- /dev/null +++ b/tests/webtbs/tw33417.pp @@ -0,0 +1,31 @@ +type + tflags = bitpacked record // Flags + bit0,bit1,bit2,bit3,bit4,bit5,bit6,bit7 : boolean; + end; + +var + gflags : tflags; + +procedure p; + +var + flags : tflags; +begin + flags:=gflags; + if flags.bit5 then + halt(1); + if gflags.bit5 then + halt(1); + if not flags.bit6 then + halt(1); + if not gflags.bit6 then + halt(1); +end; + +begin + gflags.bit4:=false; + gflags.bit5:=false; + gflags.bit6:=true; + p; + writeln('ok'); +end.