From c718062d44e439d12be267e724e681cd711d0d31 Mon Sep 17 00:00:00 2001 From: florian Date: Sat, 16 Sep 2023 23:23:50 +0200 Subject: [PATCH] * throw an error if instructions which needs an operand size is used with one operand being a reference without size --- compiler/x86/aasmcpu.pas | 28 ++++++++++++++++++++++++++++ compiler/x86/rax86.pas | 13 ++++++++++++- tests/webtbf/tw40399.pp | 10 ++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 tests/webtbf/tw40399.pp diff --git a/compiler/x86/aasmcpu.pas b/compiler/x86/aasmcpu.pas index ce4d28d8f6..eeb554ea3f 100644 --- a/compiler/x86/aasmcpu.pas +++ b/compiler/x86/aasmcpu.pas @@ -659,6 +659,8 @@ interface function get_ref_address_size(const ref:treference):byte; function get_default_segment_of_ref(const ref:treference):tregister; procedure optimize_ref(var ref:treference; inlineasm: boolean); + { returns true if opcode can be used with one memory operand without size } + function NoMemorySizeRequired(opcode : TAsmOp) : Boolean; function spilling_create_load(const ref:treference;r:tregister):Taicpu; function spilling_create_store(r:tregister; const ref:treference):Taicpu; @@ -5581,6 +5583,32 @@ implementation end; end; + + function NoMemorySizeRequired(opcode : TAsmOp) : Boolean; + var + i : LongInt; + insentry : PInsEntry; + begin + result:=false; + i:=instabcache^[opcode]; + if i=-1 then + begin + Message1(asmw_e_opcode_not_in_table,gas_op2str[opcode]); + exit; + end; + insentry:=@instab[i]; + while (insentry^.opcode=opcode) do + begin + if (insentry^.ops=1) and (insentry^.optypes[0]=OT_MEMORY) then + begin + result:=true; + exit; + end; + inc(insentry); + end; + end; + + procedure InitAsm; begin build_spilling_operation_type_table; diff --git a/compiler/x86/rax86.pas b/compiler/x86/rax86.pas index 6b9893088c..988ba2b1e2 100644 --- a/compiler/x86/rax86.pas +++ b/compiler/x86/rax86.pas @@ -436,10 +436,11 @@ begin Opsize:=S_NO; end; -procedure Tx86Instruction.AddReferenceSizes; { this will add the sizes for references like [esi] which do not have the size set yet, it will take only the size if the other operand is a register } +procedure Tx86Instruction.AddReferenceSizes; + var operand2,i,j,k : longint; s : tasmsymbol; @@ -1400,6 +1401,16 @@ begin begin if opsize<>S_NO then tx86operand(operands[i]).opsize:=opsize + else if not(NoMemorySizeRequired(opcode) or + (opcode=A_JMP) or (opcode=A_JCC) or (opcode=A_CALL) or (opcode=A_LCALL) or (opcode=A_LJMP)) then + begin + if (m_delphi in current_settings.modeswitches) then + Message(asmr_w_unable_to_determine_reference_size_using_dword) + else + Message(asmr_e_unable_to_determine_reference_size); + { recovery } + tx86operand(operands[i]).opsize:=S_L; + end; end; end; OPR_SYMBOL : diff --git a/tests/webtbf/tw40399.pp b/tests/webtbf/tw40399.pp new file mode 100644 index 0000000000..ce3de832ea --- /dev/null +++ b/tests/webtbf/tw40399.pp @@ -0,0 +1,10 @@ +{ %cpu=i386 } +{ %fail } +{$asmmode intel} + +begin + asm + fnstcw [esi] + imul [esi] + end; +end.