From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id yPBQHuRaXGdfeRUAWB0awg (envelope-from ) for ; Fri, 13 Dec 2024 11:03:48 -0500 Authentication-Results: simark.ca; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=AiMiemTH; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 78E341E097; Fri, 13 Dec 2024 11:03:48 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-5.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=unavailable autolearn_force=no version=4.0.0 Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 5E65F1E092 for ; Fri, 13 Dec 2024 11:03:47 -0500 (EST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 71EF63858435 for ; Fri, 13 Dec 2024 16:03:46 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 71EF63858435 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=AiMiemTH Received: from mail-ed1-x52e.google.com (mail-ed1-x52e.google.com [IPv6:2a00:1450:4864:20::52e]) by sourceware.org (Postfix) with ESMTPS id B8E0B3858405 for ; Fri, 13 Dec 2024 15:57:43 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B8E0B3858405 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org B8E0B3858405 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::52e ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1734105464; cv=none; b=MlUZB9zwO2JzqLV26ShT868+l206ZQ+aDQ+AXuJpMXYzO/U1VsWGh+zPjnHv8XBfHzLEmCz1HmD5wqg7FctKPqu06PD0cROoqyRZ6mwQOprZan4q8mbEmXOxrXsGi4XLKUjBg58kNSsVwk/Hv81o1Ab0hRVzXHnIvoo1g+a4vBc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1734105464; c=relaxed/simple; bh=IMoOihW2eKPVTwB4106alRm3betKB2fE509HV4Ces+g=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=gWopVK6XVgitYdP4zFCBuMv4Izxaju8tGcon76cWIzkytT1woBNf49/YDRj5HnIRGUFYPqdwvotQikIogzZLLhG8Fx4VvmvTIU2xPZbnlNXWViUcRiCi2JdjCbJtQIQNFY28okdWa1if+7ytdvA62WI0PGnnFquEFP5BaxesMZo= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B8E0B3858405 Received: by mail-ed1-x52e.google.com with SMTP id 4fb4d7f45d1cf-5cec9609303so2590137a12.1 for ; Fri, 13 Dec 2024 07:57:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1734105462; x=1734710262; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=d4ELCtwBPBc03ikieWHN4FTzfpxdzoLCZRYlLWaQ7iM=; b=AiMiemTHSjLvkgLCcQmoFx05aOEiEOcbm6IwUgO3KrSiKemb4Pkf6Nb4zjebejA4Pm HpypvQGUyravB8/UfMb57b3F8B3VcQ6j5+NjcKpyYHStZqZuMwZjvhX1mY1jlBQBEl8S bwVNqfCmHCokvO0Nv++dwhaUa+890DhFFknd6tXFn6mXz1HawR4rnhbpG+407MPQf1E4 86YRXvuSF22bLeCDBO5/d6D4z5NbeFE3olQs1EUxUqhobEJELwzuAuEo0egrsn6aX6jM WHrVf30jpHn3mqqQCHIirzSB+aGGa90nH+CyC3+adUKVCNUSlkj0yKhtXRnT1eWk8G/3 89+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1734105462; x=1734710262; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=d4ELCtwBPBc03ikieWHN4FTzfpxdzoLCZRYlLWaQ7iM=; b=uJgPcqiDxkawt4JUVMzj4UWXiHFMXdFr4vYk69/WnrE6NknwL/kyKVABOL6hj78bnk 6sjEDchaK0eKXN9T37vYd1r7ZhY5aGa9nKlOg6Lj/Blc53Bhjwy92azARGGKxgqpxhwc FWfrfu0NWylrXmLmu2ExCviKixfJ8Pp+uuEt59wLtUlx3JxGglYc2Yt1yV2GL65XH4Yw EYaLJp2NmEFejZRy9iPFPQJjNPH3cgyE7ZjGp38hATwel39XB5PGDIbkFBA6OMSni1g6 4hHFiKVZhiTHQph8jRpBmj+Yd+t2WBQB18gD0xDZ2wHK0NWYJuUPa82DL3OwL9L7hyTx Q1Xg== X-Gm-Message-State: AOJu0YwnW3dD+1Ot5KU/zVT3f/g6RHgtWlJDH2bnbUa60kQ/g8YFlRFx FPhpB+DL6aDKu8AoWo/z/qDn2MTnvmtucUClDFzOFWuag7CUpNKVPVUtI5We X-Gm-Gg: ASbGncuWk3bTY8EdAksB6Md/muU0jFogtnzblZOpZn3ojsJknA3vZf+W6YKJxt6DI2l PHpoDnbnFu+/qi/C3u8BPPEIjyxrO/vtXmvvbNdmY9pZvPY4XpnHCS2Na+dELfjXUqXnWqRjDjB jIbCRyd+ILlhF4jK9sY2BNIK4q81dWaMsbfqSlVAM1NoykZXWxnDhhTjDLIfU40axZX2cIGzReO iqjklTXm0zk2tuh+OU3QgWGUZI7zY5Sk6Aw3/rEjggHFfypM67nXaf7UF0VfXtVwHMcBPDU X-Google-Smtp-Source: AGHT+IG/uJ+Y1PJxWNRj8O1w4FLtWdyhSL8FsthzyNPXSs+CHqrL6AptdYzFszPSm3YybBTF8M4OAw== X-Received: by 2002:a05:6402:430f:b0:5d2:7270:6125 with SMTP id 4fb4d7f45d1cf-5d63c304d75mr2620335a12.8.1734105461879; Fri, 13 Dec 2024 07:57:41 -0800 (PST) Received: from SYRN16-0224-L.. ([109.245.202.111]) by smtp.googlemail.com with ESMTPSA id 4fb4d7f45d1cf-5d6501d5863sm95355a12.76.2024.12.13.07.57.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Dec 2024 07:57:41 -0800 (PST) From: Milica Matic X-Google-Original-From: Milica Matic To: gdb-patches@sourceware.org Cc: milica.matic@htecgroup.com, simark@simark.ca, cfu@wavecomp.com, aburgess@redhat.com, kevinb@redhat.com, macro@orcam.me.uk, djordje.todorovic@htecgroup.com, Matthew Fortune , Matthew Fortune , Faraz Shahbazker Subject: [PATCH 06/21] Update branch relaxation Date: Fri, 13 Dec 2024 16:53:13 +0100 Message-Id: <20241213155328.406003-8-milica.matic@htecgroup.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241213155328.406003-1-milica.matic@htecgroup.com> References: <20241213155328.406003-1-milica.matic@htecgroup.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org From: Matthew Fortune Modification of opcode_descriptor Structure: The dst_opcode field has been added, allowing the specification of a target opcode for instructions undergoing relaxation. This enhances the instruction relaxation capabilities by enabling the relaxation to result in different target opcodes, rather than being limited to a binary mask. Addition of New Opcode Descriptions: New constants, such as micromips_bc_PC26 and micromips_bc_PC21, have been defined to include opcodes for instructions like bc, beqzc, and bnezc. These instructions now also include a target opcode (e.g., 0xcc00 for bc), enabling relaxation with optimization in mind. Expansion of Relaxation Logic: The logic in the _bfd_mips_elf_relax_section function has been extended to support new instructions and opcode relaxation based on the values in dst_opcode. This allows transitions from more complex opcodes (such as 32-bit opcodes) to simpler versions (e.g., 16-bit opcodes) wherever feasible. Benefits: Reduces instruction size through relaxation. Provides better control over relaxation within the microMIPS architecture. Adding dst_opcode enhances the ability to define relaxations for various groups of instructions. Cherry-picked eddaf9c from https://github.com/MIPS/binutils-gdb Signed-off-by: Matthew Fortune Signed-off-by: Faraz Shahbazker Signed-off-by: Milica Matic --- bfd/elfxx-mips.c | 192 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 134 insertions(+), 58 deletions(-) diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 1dfd877b210..6345e782776 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -13865,6 +13865,7 @@ mips_elf_relax_delete_bytes (bfd *abfd, struct opcode_descriptor { unsigned long match; unsigned long mask; + unsigned long dst_opcode; /* target opcode. */ }; /* The $ra register aka $31. */ @@ -13884,29 +13885,40 @@ struct opcode_descriptor { /* 32-bit and 16-bit branches. */ +static const struct opcode_descriptor micromips_bc_PC26[] = { + { 0x94000000, 0xfc000000, 0xcc00 }, /* bc */ + { 0, 0, 0 } /* End marker for find_match(). */ +}; + +static const struct opcode_descriptor micromips_bc_PC21[] = { + { 0x80000000, 0xfc000000, 0x8c00 }, /* beqzc */ + { 0xa0000000, 0xfc000000, 0xac00 }, /* bnezc */ + { 0, 0, 0 } /* End marker for find_match(). */ +}; + static const struct opcode_descriptor b_insns_32[] = { - { /* "b", "p", */ 0x40400000, 0xffff0000 }, /* bgez 0 */ - { /* "b", "p", */ 0x94000000, 0xffff0000 }, /* beq 0, 0 */ - { 0, 0 } /* End marker for find_match(). */ + { /* "b", "p", */ 0x40400000, 0xffff0000, 0 }, /* bgez 0 */ + { /* "b", "p", */ 0x94000000, 0xffff0000, 0 }, /* beq 0, 0 */ + { 0, 0, 0 } /* End marker for find_match(). */ }; static const struct opcode_descriptor bc_insn_32 = - { /* "bc(1|2)(ft)", "N,p", */ 0x42800000, 0xfec30000 }; + { /* "bc(1|2)(ft)", "N,p", */ 0x42800000, 0xfec30000, 0 }; static const struct opcode_descriptor bz_insn_32 = - { /* "b(g|l)(e|t)z", "s,p", */ 0x40000000, 0xff200000 }; + { /* "b(g|l)(e|t)z", "s,p", */ 0x40000000, 0xff200000, 0 }; static const struct opcode_descriptor bzal_insn_32 = - { /* "b(ge|lt)zal", "s,p", */ 0x40200000, 0xffa00000 }; + { /* "b(ge|lt)zal", "s,p", */ 0x40200000, 0xffa00000, 0 }; static const struct opcode_descriptor beq_insn_32 = - { /* "b(eq|ne)", "s,t,p", */ 0x94000000, 0xdc000000 }; + { /* "b(eq|ne)", "s,t,p", */ 0x94000000, 0xdc000000, 0 }; static const struct opcode_descriptor b_insn_16 = - { /* "b", "mD", */ 0xcc00, 0xfc00 }; + { /* "b", "mD", */ 0xcc00, 0xfc00, 0 }; static const struct opcode_descriptor bz_insn_16 = - { /* "b(eq|ne)z", "md,mE", */ 0x8c00, 0xdc00 }; + { /* "b(eq|ne)z", "md,mE", */ 0x8c00, 0xdc00, 0 }; /* 32-bit and 16-bit branch EQ and NE zero. */ @@ -13918,27 +13930,27 @@ static const struct opcode_descriptor bz_insn_16 = #define BZC32_REG_FIELD(r) (((r) & 0x1f) << 16) static const struct opcode_descriptor bz_rs_insns_32[] = { - { /* "beqz", "s,p", */ 0x94000000, 0xffe00000 }, - { /* "bnez", "s,p", */ 0xb4000000, 0xffe00000 }, - { 0, 0 } /* End marker for find_match(). */ + { /* "beqz", "s,p", */ 0x94000000, 0xffe00000, 0 }, + { /* "bnez", "s,p", */ 0xb4000000, 0xffe00000, 0 }, + { 0, 0, 0 } /* End marker for find_match(). */ }; static const struct opcode_descriptor bz_rt_insns_32[] = { - { /* "beqz", "t,p", */ 0x94000000, 0xfc01f000 }, - { /* "bnez", "t,p", */ 0xb4000000, 0xfc01f000 }, - { 0, 0 } /* End marker for find_match(). */ + { /* "beqz", "t,p", */ 0x94000000, 0xfc01f000, 0 }, + { /* "bnez", "t,p", */ 0xb4000000, 0xfc01f000, 0 }, + { 0, 0, 0 } /* End marker for find_match(). */ }; static const struct opcode_descriptor bzc_insns_32[] = { - { /* "beqzc", "s,p", */ 0x40e00000, 0xffe00000 }, - { /* "bnezc", "s,p", */ 0x40a00000, 0xffe00000 }, - { 0, 0 } /* End marker for find_match(). */ + { /* "beqzc", "s,p", */ 0x40e00000, 0xffe00000, 0 }, + { /* "bnezc", "s,p", */ 0x40a00000, 0xffe00000, 0 }, + { 0, 0, 0 } /* End marker for find_match(). */ }; static const struct opcode_descriptor bz_insns_16[] = { - { /* "beqz", "md,mE", */ 0x8c00, 0xfc00 }, - { /* "bnez", "md,mE", */ 0xac00, 0xfc00 }, - { 0, 0 } /* End marker for find_match(). */ + { /* "beqz", "md,mE", */ 0x8c00, 0xfc00, 0 }, + { /* "bnez", "md,mE", */ 0xac00, 0xfc00, 0 }, + { 0, 0, 0 } /* End marker for find_match(). */ }; /* Switch between a 5-bit register index and its 3-bit shorthand. */ @@ -13950,83 +13962,83 @@ static const struct opcode_descriptor bz_insns_16[] = { /* 32-bit instructions with a delay slot. */ static const struct opcode_descriptor jal_insn_32_bd16 = - { /* "jals", "a", */ 0x74000000, 0xfc000000 }; + { /* "jals", "a", */ 0x74000000, 0xfc000000, 0 }; static const struct opcode_descriptor jal_insn_32_bd32 = - { /* "jal", "a", */ 0xf4000000, 0xfc000000 }; + { /* "jal", "a", */ 0xf4000000, 0xfc000000, 0 }; static const struct opcode_descriptor jal_x_insn_32_bd32 = - { /* "jal[x]", "a", */ 0xf0000000, 0xf8000000 }; + { /* "jal[x]", "a", */ 0xf0000000, 0xf8000000, 0 }; static const struct opcode_descriptor j_insn_32 = - { /* "j", "a", */ 0xd4000000, 0xfc000000 }; + { /* "j", "a", */ 0xd4000000, 0xfc000000, 0 }; static const struct opcode_descriptor jalr_insn_32 = - { /* "jalr[.hb]", "t,s", */ 0x00000f3c, 0xfc00efff }; + { /* "jalr[.hb]", "t,s", */ 0x00000f3c, 0xfc00efff, 0 }; /* This table can be compacted, because no opcode replacement is made. */ static const struct opcode_descriptor ds_insns_32_bd16[] = { - { /* "jals", "a", */ 0x74000000, 0xfc000000 }, + { /* "jals", "a", */ 0x74000000, 0xfc000000, 0 }, - { /* "jalrs[.hb]", "t,s", */ 0x00004f3c, 0xfc00efff }, - { /* "b(ge|lt)zals", "s,p", */ 0x42200000, 0xffa00000 }, + { /* "jalrs[.hb]", "t,s", */ 0x00004f3c, 0xfc00efff, 0 }, + { /* "b(ge|lt)zals", "s,p", */ 0x42200000, 0xffa00000, 0 }, - { /* "b(g|l)(e|t)z", "s,p", */ 0x40000000, 0xff200000 }, - { /* "b(eq|ne)", "s,t,p", */ 0x94000000, 0xdc000000 }, - { /* "j", "a", */ 0xd4000000, 0xfc000000 }, - { 0, 0 } /* End marker for find_match(). */ + { /* "b(g|l)(e|t)z", "s,p", */ 0x40000000, 0xff200000, 0 }, + { /* "b(eq|ne)", "s,t,p", */ 0x94000000, 0xdc000000, 0 }, + { /* "j", "a", */ 0xd4000000, 0xfc000000, 0 }, + { 0, 0, 0 } /* End marker for find_match(). */ }; /* This table can be compacted, because no opcode replacement is made. */ static const struct opcode_descriptor ds_insns_32_bd32[] = { - { /* "jal[x]", "a", */ 0xf0000000, 0xf8000000 }, + { /* "jal[x]", "a", */ 0xf0000000, 0xf8000000, 0 }, - { /* "jalr[.hb]", "t,s", */ 0x00000f3c, 0xfc00efff }, - { /* "b(ge|lt)zal", "s,p", */ 0x40200000, 0xffa00000 }, - { 0, 0 } /* End marker for find_match(). */ + { /* "jalr[.hb]", "t,s", */ 0x00000f3c, 0xfc00efff, 0 }, + { /* "b(ge|lt)zal", "s,p", */ 0x40200000, 0xffa00000, 0 }, + { 0, 0, 0 } /* End marker for find_match(). */ }; /* 16-bit instructions with a delay slot. */ static const struct opcode_descriptor jalr_insn_16_bd16 = - { /* "jalrs", "my,mj", */ 0x45e0, 0xffe0 }; + { /* "jalrs", "my,mj", */ 0x45e0, 0xffe0, 0 }; static const struct opcode_descriptor jalr_insn_16_bd32 = - { /* "jalr", "my,mj", */ 0x45c0, 0xffe0 }; + { /* "jalr", "my,mj", */ 0x45c0, 0xffe0, 0 }; static const struct opcode_descriptor jr_insn_16 = - { /* "jr", "mj", */ 0x4580, 0xffe0 }; + { /* "jr", "mj", */ 0x4580, 0xffe0, 0 }; #define JR16_REG(opcode) ((opcode) & 0x1f) /* This table can be compacted, because no opcode replacement is made. */ static const struct opcode_descriptor ds_insns_16_bd16[] = { - { /* "jalrs", "my,mj", */ 0x45e0, 0xffe0 }, + { /* "jalrs", "my,mj", */ 0x45e0, 0xffe0, 0 }, - { /* "b", "mD", */ 0xcc00, 0xfc00 }, - { /* "b(eq|ne)z", "md,mE", */ 0x8c00, 0xdc00 }, - { /* "jr", "mj", */ 0x4580, 0xffe0 }, - { 0, 0 } /* End marker for find_match(). */ + { /* "b", "mD", */ 0xcc00, 0xfc00, 0 }, + { /* "b(eq|ne)z", "md,mE", */ 0x8c00, 0xdc00, 0 }, + { /* "jr", "mj", */ 0x4580, 0xffe0, 0 }, + { 0, 0, 0 } /* End marker for find_match(). */ }; /* LUI instruction. */ static const struct opcode_descriptor lui_insn = - { /* "lui", "s,u", */ 0x41a00000, 0xffe00000 }; + { /* "lui", "s,u", */ 0x41a00000, 0xffe00000, 0 }; /* ADDIU instruction. */ static const struct opcode_descriptor addiu_insn = - { /* "addiu", "t,r,j", */ 0x30000000, 0xfc000000 }; + { /* "addiu", "t,r,j", */ 0x30000000, 0xfc000000, 0 }; static const struct opcode_descriptor addiupc_insn = - { /* "addiu", "mb,$pc,mQ", */ 0x78000000, 0xfc000000 }; + { /* "addiu", "mb,$pc,mQ", */ 0x78000000, 0xfc000000, 0 }; #define ADDIUPC_REG_FIELD(r) \ (((2 <= (r) && (r) <= 7) ? (r) : ((r) - 16)) << 23) @@ -14043,22 +14055,22 @@ static const struct opcode_descriptor addiupc_insn = #define MOVE16_RS_FIELD(r) (((r) & 0x1f) ) static const struct opcode_descriptor move_insns_32[] = { - { /* "move", "d,s", */ 0x00000290, 0xffe007ff }, /* or d,s,$0 */ - { /* "move", "d,s", */ 0x00000150, 0xffe007ff }, /* addu d,s,$0 */ - { 0, 0 } /* End marker for find_match(). */ + { /* "move", "d,s", */ 0x00000290, 0xffe007ff, 0 }, /* or d,s,$0 */ + { /* "move", "d,s", */ 0x00000150, 0xffe007ff, 0 }, /* addu d,s,$0 */ + { 0, 0, 0 } /* End marker for find_match(). */ }; static const struct opcode_descriptor move_insn_16 = - { /* "move", "mp,mj", */ 0x0c00, 0xfc00 }; + { /* "move", "mp,mj", */ 0x0c00, 0xfc00, 0 }; /* NOP instructions. */ static const struct opcode_descriptor nop_insn_32 = - { /* "nop", "", */ 0x00000000, 0xffffffff }; + { /* "nop", "", */ 0x00000000, 0xffffffff, 0 }; static const struct opcode_descriptor nop_insn_16 = - { /* "nop", "", */ 0x0c00, 0xffff }; + { /* "nop", "", */ 0x0c00, 0xffff, 0 }; /* Instruction match support. */ @@ -14265,12 +14277,16 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, to delete these bytes starting at irel->r_offset. */ int delcnt = 0; int deloff = 0; + int opcidx = 0; /* If this isn't something that can be relaxed, then ignore this reloc. */ if (r_type != R_MICROMIPS_HI16 && r_type != R_MICROMIPS_PC16_S1 - && r_type != R_MICROMIPS_26_S1) + && r_type != R_MICROMIPS_26_S1 + && r_type != R_MICROMIPS_PC26_S1 + && r_type != R_MICROMIPS_PC21_S1 + && r_type != R_MICROMIPS_LO16) continue; /* Get the section contents if we haven't done so already. */ @@ -14363,10 +14379,70 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, - (sec->output_section->vma + sec->output_offset) - irel->r_offset); - /* R_MICROMIPS_HI16 / LUI relaxation to nil, performing relaxation - of corresponding R_MICROMIPS_LO16 to R_MICROMIPS_HI0_LO16 or - R_MICROMIPS_PC23_S2. The R_MICROMIPS_PC23_S2 condition is + /* R_MICROMIPS_PC26_S1 relaxation to R_MICROMIPS_PC10_S1. */ + if (!insn32 + && r_type == R_MICROMIPS_PC26_S1 + && (opcidx = find_match (opcode, micromips_bc_PC26)) >= 0) + { + bfd_vma addend = opcode & 0x03ffffff; + unsigned int new_opcode; + + addend = _bfd_mips_elf_sign_extend (addend << 1, 27); + new_opcode = micromips_bc_PC26[opcidx].dst_opcode; + + if (! mips_elf_overflow_p ((pcrval + addend), 11)) + { + /* Calculate new addend. */ + addend = (addend + 4 - 2) >> 1; + + /* Fix the relocation's type. */ + irel->r_info = ELF32_R_INFO (r_symndx, R_MICROMIPS_PC10_S1); + + /* Replace the 32-bit bc with a 16-bit bc16. */ + bfd_put_16 (abfd, new_opcode | (addend & 0x3ff), ptr); + + /* Delete 2 bytes from irel->r_offset + 2. */ + delcnt = 2; + deloff = 2; + } + } + + /* R_MICROMIPS_PC21_S1 relaxation to R_MICROMIPS_PC7_S1. */ + if (!insn32 + && r_type == R_MICROMIPS_PC21_S1 + && (opcidx = find_match (opcode, micromips_bc_PC21)) >= 0) + { + unsigned int reg, new_opcode; + bfd_vma addend = opcode & 0x001fffff; + + reg = OP32_TREG (opcode); + addend = _bfd_mips_elf_sign_extend (addend << 1, 22); + new_opcode = micromips_bc_PC21[opcidx].dst_opcode; + + if (! mips_elf_overflow_p ((pcrval + addend), 8) + && ((reg >= 2 && reg <= 7) || reg == 16 || reg == 17)) + { + /* Calculate new addend. */ + addend = (addend + 4 - 2) >> 1; + + /* Fix the relocation's type. */ + irel->r_info = ELF32_R_INFO (r_symndx, R_MICROMIPS_PC7_S1); + /* Replace the 32-bit bc with a 16-bit bc16. */ + bfd_put_16 (abfd, + (new_opcode + | BZ16_REG_FIELD (reg) + | (addend & 0x7f)), ptr); + + /* Delete 2 bytes from irel->r_offset + 2. */ + delcnt = 2; + deloff = 2; + } + } + + /* R_MICROMIPS_HI16 / LUI relaxation to nil, performing relaxation + of corresponding R_MICROMIPS_LO16 to R_MICROMIPS_HI0_LO16 or + R_MICROMIPS_PC23_S2. The R_MICROMIPS_PC23_S2 condition is (symval % 4 == 0 && IS_BITSIZE (pcrval, 25)) where pcrval has first to be adjusted to apply against the LO16 -- 2.34.1