From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 121956 invoked by alias); 24 Jun 2019 12:19:41 -0000 Mailing-List: contact gcc-help-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-help-owner@gcc.gnu.org Received: (qmail 121948 invoked by uid 89); 24 Jun 2019 12:19:41 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-0.9 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,HTML_MESSAGE,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.1 spammy=H*RU:unknown, HX-Spam-Relays-External:unknown, H*r:ffff, UD:cz X-HELO: mxc2.seznam.cz Received: from mxc2.seznam.cz (HELO mxc2.seznam.cz) (77.75.77.23) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 24 Jun 2019 12:19:39 +0000 Received: from email.seznam.cz by email-smtpc6a.ng.seznam.cz (email-smtpc6a.ng.seznam.cz [10.23.10.165]) id 63bbd08573336ab963b1fdc4; Mon, 24 Jun 2019 14:19:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=seznam.cz; s=beta; t=1561378775; bh=vyj2NoNORKCSK+YMg/YMhSCy2fdO/mK8A/wXFRZFIng=; h=Received:From:To:Subject:Date:Message-Id:Mime-Version:X-Mailer: Content-Type; b=OpJsRVMMYvYNT/E4xGTIrLvoBBHfO6YvcbcfXHoUmducNftDCY4I5iOOx2GbemUAq FnTIDKyT8hfOYRX2IE5IpTW28FOa0/IDll3qahdbs8oe6lDEfH1NVSQwZ3J6cX4cOH b712sG3KENGJD7mbmOgB7uzJiGv8fB/kYA+G+3Ks= Received: from unknown ([::ffff:62.24.65.155]) by email.seznam.cz (szn-ebox-4.5.353) with HTTP; Mon, 24 Jun 2019 14:19:32 +0200 (CEST) From: "Zdenek Sojka" To: Subject: [x86 inline asm]: width of register arguments Date: Mon, 24 Jun 2019 12:19:00 -0000 Message-Id: Mime-Version: 1.0 (szn-mime-2.0.43) Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes X-SW-Source: 2019-06/txt/msg00082.txt.bz2 Hello, how does gcc choose the register arguments of an inline assembler and what can I assume about the "unused" bits? My questions target the 64bit x86 architecture; I assume the behavior is the same for all target triplets x86_64-*-* 1) does gcc always use register of size matching the size of the variable? eg. __asm__ ("mov %1, %0" : "=3Dr"(a) : "r"(b)); will always use 8bit registers (eg. al, bl) for "int8_t / uint8_t a, b", will always use 16bit registers (eg. ax, bx) for "int16_t / uint16_t a, b", will always use 32bit registers (eg. eax, ebx) for "int32_t / uint32_t a,=20 b", will always use 64bit registers (eg. rax, rbx) for "int64_t / uint64_t a,=20 b", will always fail due to operand size mismatch for other combination? 2) can I assume anything about the high-order bits of the register? can I=20 overwrite them freely? 2a) does gcc use the "high" 8bit registers (ah, bh, ch, dh) for variable=20 allocation? 2b) can gcc allocate different 8bit variables in the "low" and "high" registers (eg. al/ah, bl/bh, ...)? For variables of type: uint8_t a8, b8; uint16_t a16, b16; ... Enforcing same-sized arguments: a) __asm__ ("movb %b1, %b0" : "=3Dr"(a8) : "r"(b8)); or __asm__ ("movq %q1, %q0" : "=3Dr"(a8) : "r"(b8)); is always safe to do? (eg. moving 56bits of garbage won't hurt anything) OR might gcc assume something about the high-order 56bits (eg. zero, sign-/ zero-extension of the lower 8 bits), which might get broken by the move? b) __asm__ ("movw %w1, %w0" : "=3Dr"(a8) : "r"(b16)); or __asm__ ("movq %q1, %q0" : "=3Dr"(a8) : "r"(b16)); is always safe to do? (eg. moving 56bits of garbage won't hurt anything) Assuming zero-extension: __asm__ ("movw %w1, %w0" : "=3Dr"(a16) : "r"((uint8_t)b16)); or __asm__ ("movw %w1, %w0" : "=3Dr"(a16) : "r"(b8)); does not seem to work (high-order 8 bits of a16 are garbage) Thank you, Zdenek Sojka