From 0316a7697f9b6c3782abf8c6188df983ca1e9f7d Mon Sep 17 00:00:00 2001 From: florian Date: Sun, 14 Feb 2021 17:52:26 +0000 Subject: [PATCH] * arm thumb1: several fixes for the internal assembler writer git-svn-id: trunk@48675 - --- compiler/arm/agarmgas.pas | 17 ++++++++++----- compiler/arm/armins.dat | 8 +++---- compiler/arm/armtab.inc | 8 +++---- compiler/arm/cgcpu.pas | 46 +++++++++++++++++++-------------------- compiler/arm/narmset.pas | 4 ++-- compiler/arm/raarm.pas | 5 +++++ 6 files changed, 50 insertions(+), 38 deletions(-) diff --git a/compiler/arm/agarmgas.pas b/compiler/arm/agarmgas.pas index 93053b4f9d..182ff8a5de 100644 --- a/compiler/arm/agarmgas.pas +++ b/compiler/arm/agarmgas.pas @@ -371,7 +371,7 @@ unit agarmgas; Procedure TArmInstrWriter.WriteInstruction(hp : tai); var op: TAsmOp; - postfix,s: string; + postfix,s,oppostfixstr: string; i: byte; sep: string[3]; begin @@ -382,17 +382,24 @@ unit agarmgas; if cf_wideformat in taicpu(hp).flags then postfix:='.w'; end; + { GNU AS does not like an S postfix for several instructions in thumb mode though it is the only + valid encoding of mvn in thumb mode according to the arm docs } + if GenerateThumbCode and (taicpu(hp).oppostfix=PF_S) and + ((op=A_MVN) or (op=A_ORR) or (op=A_AND) or (op=A_LSL) or (op=A_ADC) or (op=A_LSR) or (op=A_SBC) or (op=A_EOR) or (op=A_ROR)) then + oppostfixstr:='' + else + oppostfixstr:=oppostfix2str[taicpu(hp).oppostfix]; if unified_syntax then begin if taicpu(hp).ops = 0 then - s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition]+oppostfix2str[taicpu(hp).oppostfix] + s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition]+oppostfixstr else if taicpu(hp).oppostfix in [PF_8..PF_U32F64] then - s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition]+oppostfix2str[taicpu(hp).oppostfix] + s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition]+oppostfixstr else - s:=#9+gas_op2str[op]+oppostfix2str[taicpu(hp).oppostfix]+cond2str[taicpu(hp).condition]+postfix; // Conditional infixes are deprecated in unified syntax + s:=#9+gas_op2str[op]+oppostfixstr+cond2str[taicpu(hp).condition]+postfix; // Conditional infixes are deprecated in unified syntax end else - s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition]+oppostfix2str[taicpu(hp).oppostfix]; + s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition]+oppostfixstr; if taicpu(hp).ops<>0 then begin sep:=#9; diff --git a/compiler/arm/armins.dat b/compiler/arm/armins.dat index 3c97d9e43a..d0bfadafcc 100644 --- a/compiler/arm/armins.dat +++ b/compiler/arm/armins.dat @@ -215,7 +215,7 @@ reg32 \3\x01\x2F\xFF\x10 ARM32,ARMv4T reg8,reg8 \300\1\x10\101 ARM32,ARMv4 [CMNcc] -reglo,reglo \x6B\x42\xC0 THUMB,ARMv4T +reglo,reglo \x6F\x42\xC0 THUMB,ARMv4T reg32,immshifter \x80\xF1\x10\x0F\x00 THUMB32,ARMv6T2 reg32,reg32 \x80\xEB\x10\x0F\x00 THUMB32,WIDE,ARMv6T2 @@ -226,10 +226,10 @@ reg32,reg32,shifterop \xE\x1\x60 ARM32,ARMv4 reg32,immshifter \xF\x1\x60 ARM32,ARMv4 [CMPcc] -reglo,reglo \x6B\x42\x80 THUMB,ARMv4T +reglo,reglo \x6F\x42\x80 THUMB,ARMv4T reg32,reg32 \x61\x45\x0 THUMB,ARMv4T -reglo,immshifter \x6B\x28\x0 THUMB,ARMv4T +reglo,immshifter \x6F\x28\x0 THUMB,ARMv4T reg32,immshifter \x80\xF1\xB0\x0F\x00 THUMB32,WIDE,ARMv6T2 reg32,reg32 \x80\xEB\xB0\x0F\x00 THUMB32,WIDE,ARMv6T2 @@ -612,7 +612,7 @@ reg32,reg32,shifterop \xE\x1\x20 ARM32,ARMv4 reg32,immshifter \xF\x3\x20 ARM32,ARMv4 [TSTcc] -reglo,reglo \x6B\x42\x00 THUMB,ARMv4T +reglo,reglo \x6F\x42\x00 THUMB,ARMv4T reg32,immshifter \x80\xF0\x10\x0F\x00 THUMB32,ARMv6T2 reg32,reg32 \x80\xEA\x10\x0F\x00 THUMB32,WIDE,ARMv6T2 diff --git a/compiler/arm/armtab.inc b/compiler/arm/armtab.inc index cdd6b6cee9..b103851120 100644 --- a/compiler/arm/armtab.inc +++ b/compiler/arm/armtab.inc @@ -592,7 +592,7 @@ opcode : A_CMN; ops : 2; optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none); - code : #107#66#192; + code : #111#66#192; flags : if_thumb or if_armv4t ), ( @@ -641,7 +641,7 @@ opcode : A_CMP; ops : 2; optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none); - code : #107#66#128; + code : #111#66#128; flags : if_thumb or if_armv4t ), ( @@ -655,7 +655,7 @@ opcode : A_CMP; ops : 2; optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none); - code : #107#40#0; + code : #111#40#0; flags : if_thumb or if_armv4t ), ( @@ -2328,7 +2328,7 @@ opcode : A_TST; ops : 2; optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none); - code : #107#66#0; + code : #111#66#0; flags : if_thumb or if_armv4t ), ( diff --git a/compiler/arm/cgcpu.pas b/compiler/arm/cgcpu.pas index dd99aae197..cd608c5ace 100644 --- a/compiler/arm/cgcpu.pas +++ b/compiler/arm/cgcpu.pas @@ -746,9 +746,9 @@ unit cgcpu; (A_NONE,A_MOV,A_ADD,A_AND,A_NONE,A_NONE,A_MUL,A_MUL,A_NONE,A_NONE,A_ORR, A_ASR,A_LSL,A_LSR,A_SUB,A_EOR,A_NONE,A_ROR); - op_reg_postfix: array[TOpCG] of TOpPostfix = - (PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None, - PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None); + op_reg_postfix_thumb: array[TOpCG] of TOpPostfix = + (PF_None,PF_None,PF_None,PF_S,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_S, + PF_None,PF_S,PF_S,PF_None,PF_S,PF_None,PF_S); procedure tcgarm.a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister); @@ -3925,7 +3925,7 @@ unit cgcpu; a_internal_load_ref_reg(list,OS_S8,OS_S8,usedtmpref,tmpreg); list.concat(taicpu.op_reg_const(A_LSL,tmpreg,8)); - list.concat(taicpu.op_reg_reg(A_ORR,reg,tmpreg)); + list.concat(setoppostfix(taicpu.op_reg_reg(A_ORR,reg,tmpreg),PF_S)); end; OS_32,OS_S32: begin @@ -3955,7 +3955,7 @@ unit cgcpu; inc(usedtmpref.offset,dir*2); a_internal_load_ref_reg(list,OS_16,OS_16,usedtmpref,tmpreg); list.concat(taicpu.op_reg_const(A_LSL,tmpreg,16)); - list.concat(taicpu.op_reg_reg(A_ORR,reg,tmpreg)); + list.concat(setoppostfix(taicpu.op_reg_reg(A_ORR,reg,tmpreg),PF_S)); end else begin @@ -3965,15 +3965,15 @@ unit cgcpu; inc(usedtmpref.offset,dir); a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg); list.concat(taicpu.op_reg_const(A_LSL,tmpreg,8)); - list.concat(taicpu.op_reg_reg(A_ORR,reg,tmpreg)); + list.concat(setoppostfix(taicpu.op_reg_reg(A_ORR,reg,tmpreg),PF_S)); inc(usedtmpref.offset,dir); a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg); list.concat(taicpu.op_reg_const(A_LSL,tmpreg,16)); - list.concat(taicpu.op_reg_reg(A_ORR,reg,tmpreg)); + list.concat(setoppostfix(taicpu.op_reg_reg(A_ORR,reg,tmpreg),PF_S)); inc(usedtmpref.offset,dir); a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg); list.concat(taicpu.op_reg_const(A_LSL,tmpreg,24)); - list.concat(taicpu.op_reg_reg(A_ORR,reg,tmpreg)); + list.concat(setoppostfix(taicpu.op_reg_reg(A_ORR,reg,tmpreg),PF_S)); end; end else @@ -3996,7 +3996,7 @@ unit cgcpu; if not(size in [OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32]) then internalerror(2002090908); if is_thumb_imm(a) then - list.concat(taicpu.op_reg_const(A_MOV,reg,a)) + list.concat(setoppostfix(taicpu.op_reg_const(A_MOV,reg,a),PF_S)) else begin reference_reset(hr,4,[]); @@ -4157,7 +4157,7 @@ unit cgcpu; OP_NEG: list.concat(taicpu.op_reg_reg(A_NEG,dst,src)); OP_NOT: - list.concat(taicpu.op_reg_reg(A_MVN,dst,src)); + list.concat(setoppostfix(taicpu.op_reg_reg(A_MVN,dst,src),PF_S)); OP_DIV,OP_IDIV: internalerror(200308284); OP_ROL: @@ -4168,13 +4168,13 @@ unit cgcpu; tmpreg:=getintregister(list,OS_32); a_load_const_reg(list,OS_32,32,tmpreg); list.concat(taicpu.op_reg_reg(A_SUB,tmpreg,src)); - list.concat(taicpu.op_reg_reg(A_ROR,dst,src)); + list.concat(setoppostfix(taicpu.op_reg_reg(A_ROR,dst,src),PF_S)); end; else begin a_reg_alloc(list,NR_DEFAULTFLAGS); list.concat(setoppostfix( - taicpu.op_reg_reg(op_reg_opcg2asmop[op],dst,src),op_reg_postfix[op])); + taicpu.op_reg_reg(op_reg_opcg2asmop[op],dst,src),op_reg_postfix_thumb[op])); end; end; maybeadjustresult(list,op,size,dst); @@ -4210,7 +4210,7 @@ unit cgcpu; // if cgsetflags or setflags then a_reg_alloc(list,NR_DEFAULTFLAGS); list.concat(setoppostfix( - taicpu.op_reg_const(op_reg_opcg2asmop[op],dst,a),op_reg_postfix[op])); + taicpu.op_reg_const(op_reg_opcg2asmop[op],dst,a),op_reg_postfix_thumb[op])); if (cgsetflags {!!! or setflags }) and (size in [OS_8,OS_16,OS_32]) then begin @@ -4269,7 +4269,7 @@ unit cgcpu; { x := y and 0; just clears a register, this sometimes gets generated on 64bit ops. Just using mov x, #0 might allow some easier optimizations down the line. } else if (op = OP_AND) and (dword(a)=0) then - list.concat(taicpu.op_reg_const(A_MOV,dst,0)) + list.concat(setoppostfix(taicpu.op_reg_const(A_MOV,dst,0),PF_S)) { x := y AND $FFFFFFFF just copies the register, so use mov for better optimizations } else if (op = OP_AND) and (not(dword(a))=0) then // do nothing @@ -4325,10 +4325,10 @@ unit cgcpu; ai:=setcondition(taicpu.op_sym(A_B,l1),flags_to_cond(f)); ai.is_jmp:=true; list.concat(ai); - list.concat(taicpu.op_reg_const(A_MOV,reg,0)); + list.concat(setoppostfix(taicpu.op_reg_const(A_MOV,reg,0),PF_S)); list.concat(taicpu.op_sym(A_B,l2)); cg.a_label(list,l1); - list.concat(taicpu.op_reg_const(A_MOV,reg,1)); + list.concat(setoppostfix(taicpu.op_reg_const(A_MOV,reg,1),PF_S)); a_reg_dealloc(list,NR_DEFAULTFLAGS); cg.a_label(list,l2); end; @@ -5355,11 +5355,11 @@ unit cgcpu; case op of OP_NEG: begin - list.concat(taicpu.op_reg_const(A_MOV,regdst.reglo,0)); - list.concat(taicpu.op_reg_const(A_MOV,regdst.reghi,0)); + list.concat(setoppostfix(taicpu.op_reg_const(A_MOV,regdst.reglo,0),PF_S)); + list.concat(setoppostfix(taicpu.op_reg_const(A_MOV,regdst.reghi,0),PF_S)); cg.a_reg_alloc(list,NR_DEFAULTFLAGS); list.concat(taicpu.op_reg_reg(A_SUB,regdst.reglo,regsrc.reglo)); - list.concat(taicpu.op_reg_reg(A_SBC,regdst.reghi,regsrc.reghi)); + list.concat(setoppostfix(taicpu.op_reg_reg(A_SBC,regdst.reghi,regsrc.reghi),PF_S)); cg.a_reg_dealloc(list,NR_DEFAULTFLAGS); end; OP_NOT: @@ -5376,13 +5376,13 @@ unit cgcpu; begin cg.a_reg_alloc(list,NR_DEFAULTFLAGS); list.concat(taicpu.op_reg_reg(A_ADD,regdst.reglo,regsrc.reglo)); - list.concat(taicpu.op_reg_reg(A_ADC,regdst.reghi,regsrc.reghi)); + list.concat(setoppostfix(taicpu.op_reg_reg(A_ADC,regdst.reghi,regsrc.reghi),PF_S)); end; OP_SUB: begin cg.a_reg_alloc(list,NR_DEFAULTFLAGS); list.concat(taicpu.op_reg_reg(A_SUB,regdst.reglo,regsrc.reglo)); - list.concat(taicpu.op_reg_reg(A_SBC,regdst.reghi,regsrc.reghi)); + list.concat(setoppostfix(taicpu.op_reg_reg(A_SBC,regdst.reghi,regsrc.reghi),PF_S)); end; else internalerror(2003083105); @@ -5417,7 +5417,7 @@ unit cgcpu; tmpreg:=cg.getintregister(list,OS_32); cg.a_load_const_reg(list,OS_32,aint(hi(value)),tmpreg); - list.concat(taicpu.op_reg_reg(A_ADC,reg.reghi,tmpreg)); + list.concat(setoppostfix(taicpu.op_reg_reg(A_ADC,reg.reghi,tmpreg),PF_S)); end; OP_SUB: begin @@ -5436,7 +5436,7 @@ unit cgcpu; tmpreg:=cg.getintregister(list,OS_32); cg.a_load_const_reg(list,OS_32,hi(value),tmpreg); - list.concat(taicpu.op_reg_reg(A_SBC,reg.reghi,tmpreg)); + list.concat(setoppostfix(taicpu.op_reg_reg(A_SBC,reg.reghi,tmpreg),PF_S)); end; else internalerror(2003083106); diff --git a/compiler/arm/narmset.pas b/compiler/arm/narmset.pas index 434adf6dc5..4d0c2cb5ca 100644 --- a/compiler/arm/narmset.pas +++ b/compiler/arm/narmset.pas @@ -112,11 +112,11 @@ implementation right.resultdef, right.resultdef, true); hregister:=hlcg.getintregister(current_asmdata.CurrAsmList, opdef); - current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_MOV,hregister,1)); + hlcg.a_load_const_reg(current_asmdata.CurrAsmList,opdef,1,hregister); if GenerateThumbCode or GenerateThumb2Code then begin - current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_LSL,hregister,left.location.register)); + hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_SHL,opdef,left.location.register,hregister); cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS); current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_TST,right.location.register,hregister)); end diff --git a/compiler/arm/raarm.pas b/compiler/arm/raarm.pas index 563a70a9fb..e152f44c4a 100644 --- a/compiler/arm/raarm.pas +++ b/compiler/arm/raarm.pas @@ -43,6 +43,8 @@ unit raarm; implementation uses + globals, + cpuinfo, aasmcpu; function TARMInstruction.ConcatInstruction(p:TAsmList) : tai; @@ -53,6 +55,9 @@ unit raarm; include((result as taicpu).flags,cf_wideformat) else exclude((result as taicpu).flags,cf_wideformat); + { GNU As assumes implicit S postfix for some instructions in thumb mode } + if (current_settings.instructionset=is_thumb) and (((result as taicpu).oppostfix=PF_None) and ((opcode=A_MOV) and ((result as taicpu).oper[1]^.typ=top_const)) or (opcode=A_MVN)) then + (result as taicpu).oppostfix:=PF_S end;