From patchwork Mon Dec 16 11:39:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 103171 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 685F33858C32 for ; Mon, 16 Dec 2024 11:40:17 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 685F33858C32 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=suse.com header.i=@suse.com header.a=rsa-sha256 header.s=google header.b=IJjpOd8O X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-wr1-x42f.google.com (mail-wr1-x42f.google.com [IPv6:2a00:1450:4864:20::42f]) by sourceware.org (Postfix) with ESMTPS id 574FB3858D21 for ; Mon, 16 Dec 2024 11:39:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 574FB3858D21 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 574FB3858D21 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::42f ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1734349168; cv=none; b=HqCzoLMm8wjLyX+ogonNgfZZF6nUiuHt3BsSnJjXR1Pni+B8MW1mEet+x8Erfbo8UgJC60c98nHEFF9kSuebr0w6j7XrRHithw9QTMEd+K4QfIPqCrg+6+seVNLOAs7Vbm5bjRRbxiy1wMZBx59rDilQuhE4rRfQkn5tb+wfFNk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1734349168; c=relaxed/simple; bh=tFwG/xYwxCympPwfHeeeGRrPGIzy3qxCiMJAdPmxCME=; h=DKIM-Signature:Message-ID:Date:MIME-Version:To:From:Subject; b=i2halqkuPw/ujVjNSRcOi53xLLVRgPqaVcJlPhjgjM/Nrmr1QYC2BddINM9oDhdrDKaAP5GfqN2i50E4F7748PG4uXzJPmwb/wG9mxIGvo6jZqgNUNyPtoBycWVNs16airQMadd/IyyT4tMqFx8dUJ1ur5UkVjpYXglcKkRPAOo= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 574FB3858D21 Received: by mail-wr1-x42f.google.com with SMTP id ffacd0b85a97d-385d7b4da2bso3818956f8f.1 for ; Mon, 16 Dec 2024 03:39:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1734349167; x=1734953967; darn=sourceware.org; h=content-transfer-encoding:autocrypt:subject:from:to :content-language:user-agent:mime-version:date:message-id:from:to:cc :subject:date:message-id:reply-to; bh=5IGjsIWW/Pdve2cbWZxU3eqatObDekIjQ4fYauOBZn4=; b=IJjpOd8Ocui6o22C3/FOUeTnF4nczXhcBPUmwLl4gITC/6FerMUd4fKRxATO8L1olu nkYf8J6mKb+WVRYB57leoN7g04WyfgWB4OLWJqe7aSsPD500bdr+jAOK6PApSC6DlTOT pFESp+w2EknhS1A9m9SGCs9N5Ud6/79l468KWeNYCudMEzcTHy0tjCYXqWbKJ2i3OhR5 ewOgHVItbksIU9XRpucam1DNw0NzMgCJtOpN+Yq2QM3/ExYWE/x3qIhoHetsVBa7gw5a wvOu2N1FvHquabXvlRg0SqntuH76+Bn/d8CCnk22cVlzhtjLKQWDkC7s9JTMOkrMJoIt lz7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1734349167; x=1734953967; h=content-transfer-encoding:autocrypt:subject:from:to :content-language:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=5IGjsIWW/Pdve2cbWZxU3eqatObDekIjQ4fYauOBZn4=; b=wfXoBZn2YcCpF2IH9XeKmVSamjr7Ct0gayTpv1iW5O9m/XM1s9EdFvudQ2rlEPFQ5+ aJjq/nJum+ur+P8XfCGkHUOPoeGwg/EVtwStZWnIJGOdnu/+j2iaCwHRzaceS9YhMYT9 hSKC9nHgMSANkrFuNXXqLzGGhPaYY9+f7nAyREpSAuwnxg5k3SHRIswQznY3FazSjvr/ b7WXrit/ZBqdiTHd80nOp6rhpLzrpBaEU7oBBLOr6PLNdhwUh1j9GUDz4jV0lyUyrXXd OFX4mr8kLi/SeuJuMrMvKmdfxwvLBuG3pap6KMWGnNIzAzCy+0TX2kCFe4JnVSTKojx3 jjuA== X-Gm-Message-State: AOJu0YzWw7x2Tqb4XIM8wB08eJA+hN0d+jelH1Te7YthL0R9pkXyLRo7 vrwOQ9nF6u6YNw0ETbMco8Z3gmK7XL1Z4JunFTFSicn7OQgGmUD/coKHH6Cp4DUNJu27HEXC6qw = X-Gm-Gg: ASbGncsEBBSzic7mUz/NQb7LrDci/INWYhEeP7TsRlWvTtiKY/3S9n3Su5yFrMGYzYa oL1rBztvFOGV3vyu6q/sZU8smsWvmhXAPz+k79f5//Xkq4LJRZEOK0FCLg5zO9+LaDI7mI+amgs pXaRBqgE/ToCqPZd/WIB5I/kqLhbeBkIyhiHbf8S2PWVo8WKn7Rt8Jjmg8iEIp8jeODLsrfgbVc V5kDfSFgUs9QpJiVWAkipllb0TXbP1F0Vgwya8acPGPEa0DrPr1KMihIR39thF72ULfiDG1YyZ4 gadN9bb30FAqPR72VRQmvrdrZ97rVHoAYvjx+Ylm5w== X-Google-Smtp-Source: AGHT+IFQqSB+BG+e6TP4gTjLGyIhsIS+1YK4OsO9yeYa9Ua3Dh9hsemPAoVJSaEP/X1OE1HDAU+NXQ== X-Received: by 2002:a5d:6c65:0:b0:385:eb7c:5d0f with SMTP id ffacd0b85a97d-38880ae15a2mr9857774f8f.26.1734349166942; Mon, 16 Dec 2024 03:39:26 -0800 (PST) Received: from [10.156.60.236] (ip-037-024-206-209.um08.pools.vodafone-ip.de. [37.24.206.209]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-388c8012170sm7915160f8f.14.2024.12.16.03.39.26 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 16 Dec 2024 03:39:26 -0800 (PST) Message-ID: Date: Mon, 16 Dec 2024 12:39:25 +0100 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Content-Language: en-US To: Binutils From: Jan Beulich Subject: =?utf-8?q?=5BPATCH=5D_gas=3A_special-case_division_/_modulo_by_?= =?utf-8?q?=C2=B11?= Autocrypt: addr=jbeulich@suse.com; keydata= xsDiBFk3nEQRBADAEaSw6zC/EJkiwGPXbWtPxl2xCdSoeepS07jW8UgcHNurfHvUzogEq5xk hu507c3BarVjyWCJOylMNR98Yd8VqD9UfmX0Hb8/BrA+Hl6/DB/eqGptrf4BSRwcZQM32aZK 7Pj2XbGWIUrZrd70x1eAP9QE3P79Y2oLrsCgbZJfEwCgvz9JjGmQqQkRiTVzlZVCJYcyGGsD /0tbFCzD2h20ahe8rC1gbb3K3qk+LpBtvjBu1RY9drYk0NymiGbJWZgab6t1jM7sk2vuf0Py O9Hf9XBmK0uE9IgMaiCpc32XV9oASz6UJebwkX+zF2jG5I1BfnO9g7KlotcA/v5ClMjgo6Gl MDY4HxoSRu3i1cqqSDtVlt+AOVBJBACrZcnHAUSuCXBPy0jOlBhxPqRWv6ND4c9PH1xjQ3NP nxJuMBS8rnNg22uyfAgmBKNLpLgAGVRMZGaGoJObGf72s6TeIqKJo/LtggAS9qAUiuKVnygo 3wjfkS9A3DRO+SpU7JqWdsveeIQyeyEJ/8PTowmSQLakF+3fote9ybzd880fSmFuIEJldWxp Y2ggPGpiZXVsaWNoQHN1c2UuY29tPsJgBBMRAgAgBQJZN5xEAhsDBgsJCAcDAgQVAggDBBYC AwECHgECF4AACgkQoDSui/t3IH4J+wCfQ5jHdEjCRHj23O/5ttg9r9OIruwAn3103WUITZee e7Sbg12UgcQ5lv7SzsFNBFk3nEQQCACCuTjCjFOUdi5Nm244F+78kLghRcin/awv+IrTcIWF hUpSs1Y91iQQ7KItirz5uwCPlwejSJDQJLIS+QtJHaXDXeV6NI0Uef1hP20+y8qydDiVkv6l IreXjTb7DvksRgJNvCkWtYnlS3mYvQ9NzS9PhyALWbXnH6sIJd2O9lKS1Mrfq+y0IXCP10eS FFGg+Av3IQeFatkJAyju0PPthyTqxSI4lZYuJVPknzgaeuJv/2NccrPvmeDg6Coe7ZIeQ8Yj t0ARxu2xytAkkLCel1Lz1WLmwLstV30g80nkgZf/wr+/BXJW/oIvRlonUkxv+IbBM3dX2OV8 AmRv1ySWPTP7AAMFB/9PQK/VtlNUJvg8GXj9ootzrteGfVZVVT4XBJkfwBcpC/XcPzldjv+3 HYudvpdNK3lLujXeA5fLOH+Z/G9WBc5pFVSMocI71I8bT8lIAzreg0WvkWg5V2WZsUMlnDL9 mpwIGFhlbM3gfDMs7MPMu8YQRFVdUvtSpaAs8OFfGQ0ia3LGZcjA6Ik2+xcqscEJzNH+qh8V m5jjp28yZgaqTaRbg3M/+MTbMpicpZuqF4rnB0AQD12/3BNWDR6bmh+EkYSMcEIpQmBM51qM EKYTQGybRCjpnKHGOxG0rfFY1085mBDZCH5Kx0cl0HVJuQKC+dV2ZY5AqjcKwAxpE75MLFkr wkkEGBECAAkFAlk3nEQCGwwACgkQoDSui/t3IH7nnwCfcJWUDUFKdCsBH/E5d+0ZnMQi+G0A nAuWpQkjM1ASeQwSHEeAWPgskBQL X-Spam-Status: No, score=-3022.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, KAM_NUMSUBJECT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces~patchwork=sourceware.org@sourceware.org Dividing the largest possible negative value by -1 generally is UB, for the result not being representable at least in commonly used binary notation. This UB on x86, for example, is a Floating Point Exception on Linux, i.e. resulting in an internal error (albeit only when sizeof(valueT) == sizeof(void *); the library routine otherwise involved apparently deals with the inputs quite okay). Leave original values unaltered for division by 1; this may matter down the road, in case we start including X_unsigned and X_extrabit in arithmetic. For the same reason treat modulo by 1 the same as modulo by -1. The quad and octa tests have more relaxed expecations than intended, for X_unsigned and X_extrabit not being taken into account [yet]. The upper halves can wrongly end up as all ones (for .octa, when !BFD64, even the upper three quarters). Yet it makes little sense to address this just for div/mod by ±1. quad-div2 is yet more special, to cover for most 32-bit targets being unable to deal with forward-ref expressions in .quad even when BFD64; even ones being able to (like x86) then still don't get the values right. --- I'm surprised fuzzing didn't spot this yet, but perhaps the specific input values needed don't fit very well in how fuzzers determine new "interesting" values. --- a/gas/expr.c +++ b/gas/expr.c @@ -2015,8 +2015,32 @@ expr (int rankarg, /* Larger # is highe bits of the result. */ resultP->X_add_number *= (valueT) v; break; - case O_divide: resultP->X_add_number /= v; break; - case O_modulus: resultP->X_add_number %= v; break; + + case O_divide: + if (v == 1) + break; + if (v == -1) + { + /* Dividing the largest negative value representable in offsetT + by -1 has a non-representable result in common binary + notation. Treat it as negation instead, carried out as an + unsigned operation to avoid UB. */ + resultP->X_add_number = - (valueT) resultP->X_add_number; + } + else + resultP->X_add_number /= v; + break; + + case O_modulus: + /* See above for why in particular -1 needs special casing. + While the operation is UB in C, mathematically it has a well- + defined result. */ + if (v == 1 || v == -1) + resultP->X_add_number = 0; + else + resultP->X_add_number %= v; + break; + case O_left_shift: case O_right_shift: /* We always use unsigned shifts. According to the ISO @@ -2372,12 +2396,22 @@ resolve_expression (expressionS *express case O_divide: if (right == 0) return 0; - left = (offsetT) left / (offsetT) right; + /* See expr() for reasons of the special casing. */ + if (right == 1) + break; + if ((offsetT) right == -1) + left = -left; + else + left = (offsetT) left / (offsetT) right; break; case O_modulus: if (right == 0) return 0; - left = (offsetT) left % (offsetT) right; + /* Again, see expr() for reasons of the special casing. */ + if (right == 1 || (offsetT) right == -1) + left = 0; + else + left = (offsetT) left % (offsetT) right; break; case O_left_shift: if (right >= sizeof (left) * CHAR_BIT) --- a/gas/symbols.c +++ b/gas/symbols.c @@ -1723,8 +1723,27 @@ resolve_symbol_value (symbolS *symp) { /* See expr() for reasons of the use of valueT casts here. */ case O_multiply: left *= (valueT) right; break; - case O_divide: left /= right; break; - case O_modulus: left %= right; break; + + /* See expr() for reasons of the special casing. */ + case O_divide: + if (right == 1) + break; + if (right == -1) + { + left = -left; + break; + } + left /= right; + break; + + /* Again, see expr() for reasons of the special casing. */ + case O_modulus: + if (right == 1 || right == -1) + left = 0; + else + left %= right; + break; + case O_left_shift: left = (valueT) left << (valueT) right; break; case O_right_shift: --- a/gas/testsuite/gas/all/gas.exp +++ b/gas/testsuite/gas/all/gas.exp @@ -449,6 +449,22 @@ if { ![istarget "pdp11-*-*"] } { run_dump_test octa } +# Some x86 flavors use '/' as a comment char, yet that can be suppressed. +# Some other target use '/' or '%' as a comment char, without a way to +# suppress it. +if { [istarget "i?86-*-*"] || [istarget "x86_64-*-*"] } { + run_dump_test quad-div {{as --divide}} + run_dump_test quad-div2 {{as --divide}} + run_dump_test octa-div {{as --divide}} +} elseif { ![istarget "mcore-*-*"] + && ![istarget "mmix-*-*"] + && ![istarget "pdp11-*-*"] + && ![istarget "pj*-*-*"] } { + run_dump_test quad-div + run_dump_test quad-div2 + run_dump_test octa-div +} + # .set works differently on some targets. switch -glob $target_triplet { alpha*-*-* { } --- /dev/null +++ b/gas/testsuite/gas/all/octa-div.d @@ -0,0 +1,10 @@ +#objdump: -s -j .data +#name: .octa with division + +.*: +file format .* + +Contents of section .data: + [^ ]* (00000080 ........ ........ ........|........ ........ ........ 80000000) .* + [^ ]* (00000000 ........ ........ ........|........ ........ ........ 00000000) .* + [^ ]* (00000000 00000080 ........ ........|........ ........ 80000000 00000000) .* + [^ ]* (00000000 00000000 ........ ........|........ ........ 00000000 00000000) .* --- /dev/null +++ b/gas/testsuite/gas/all/octa-div.s @@ -0,0 +1,11 @@ + .data + .octa -0x80000000 / -1 + .octa -0x80000000 % -1 + .if ((1 << 16) << 16) <> 0 + .octa -0x8000000000000000 / -1 + .octa -0x8000000000000000 % -1 + .else + /* Not really useful fallback for non-BFD64 targets. */ + .octa 0x8000000000000000 + .octa 0x0000000000000000 + .endif --- /dev/null +++ b/gas/testsuite/gas/all/quad-div.d @@ -0,0 +1,9 @@ +#objdump : -s -j .data +#name : .quad with division + +.*: .* + +Contents of section (\.data|\$DATA\$): + 0000 (........ 80000000 ........ 00000000|00000080 ........ 00000000 ........) .* + 00.. (80000000 00000000 00000000 00000000|00000000 00000080 00000000 00000000) .* +#pass --- /dev/null +++ b/gas/testsuite/gas/all/quad-div.s @@ -0,0 +1,32 @@ + .data + + .eqv INT_MAX, 0x7fffffff + .eqv INT_MIN, -INT_MAX - 1 + + /* Note: Shifts are uniformly done as unsigned. */ + .rept (INT_MIN / -1) >> 31 + .quad -0x80000000 / -1 + .endr + .rept (INT_MIN % -1) + 1 + .quad -0x80000000 % -1 + .endr + + .if ((1 << 16) << 16) <> 0 + + .eqv LONG_MAX, 0x7fffffffffffffff + .eqv LONG_MIN, -LONG_MAX - 1 + + /* Note: Shifts are uniformly done as unsigned. */ + .rept (LONG_MIN / -1) >> 63 + .quad -0x8000000000000000 / -1 + .endr + .rept (LONG_MIN % -1) + 1 + .quad -0x8000000000000000 % -1 + .endr + + .else /* Not really useful fallback for non-BFD64 targets. */ + + .quad 0x8000000000000000 + .quad 0x0000000000000000 + + .endif --- /dev/null +++ b/gas/testsuite/gas/all/quad-div2.d @@ -0,0 +1,16 @@ +#objdump : -s -j .data +#name : .quad with division (fwdref) +# bfin doesn't support 'symbol = expression'. +# tic30 and tic4x have 4 octets per byte, tic54x has 2 octets per byte. +# v850 re-purposes .offset. +#notarget: bfin-*-* *c30-*-* *c4x-*-* *c54x-*-* v850*-*-* +# linkrelax targets don't handle equivalence expressions well (nor any +# other forward expression). mep uses complex relocs. +#xfail: crx-*-* h8300-*-* mn10200-*-* mn10300-*-* mep-*-* + +.*: .* + +Contents of section (\.data|\$DATA\$): + 0000 (00000000 80000000|80000000 00000000|00000080 00000000) 00000000 00000000 .* + 00.. (80000000 00000000 00000000 00000000|00000000 00000080 00000000 00000000) .* +#pass --- /dev/null +++ b/gas/testsuite/gas/all/quad-div2.s @@ -0,0 +1,27 @@ + .offset + .dc.a 0 + vasz = . + + .data + + .if vasz >= 8 + + .quad INT_MIN / -1 + .quad INT_MIN % -1 + .quad LONG_MIN / -1 + .quad LONG_MIN % -1 + + LONG_MIN = -0x8000000000000000 + + .else + + /* Use .long to cover at least !BFD64 targets. */ + .long INT_MIN / -1, 0 + .long INT_MIN % -1, 0 + /* Not really useful fallback for less-than-64-bit-VMA targets. */ + .quad 0x8000000000000000 + .quad 0x0000000000000000 + + .endif + + INT_MIN = -0x80000000