From: David Daney <ddaney.cavm@gmail.com>
To: "Steven J. Hill" <sjhill@mips.com>
Cc: linux-mips@linux-mips.org, ralf@linux-mips.org, cernekee@gmail.com
Subject: Re: [PATCH][RFC] MIPS: microMIPS: Add support to micro-assembler.
Date: Wed, 30 Jan 2013 10:04:41 -0800 [thread overview]
Message-ID: <510960B9.1060800@gmail.com> (raw)
In-Reply-To: <1359514228-2161-1-git-send-email-sjhill@mips.com>
On 01/29/2013 06:50 PM, Steven J. Hill wrote:
> From: "Steven J. Hill" <sjhill@mips.com>
>
> This adds microMIPS instruction support to the micro-assembler.
>
> Signed-off-by: Steven J. Hill <sjhill@mips.com>
> ---
> arch/mips/mm/uasm.c | 121 +++++++++++++++++++++++++++++++++------------------
> 1 file changed, 78 insertions(+), 43 deletions(-)
>
> diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c
> index 942ff6c..13f0ca7 100644
> --- a/arch/mips/mm/uasm.c
> +++ b/arch/mips/mm/uasm.c
> @@ -10,6 +10,7 @@
> * Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer
> * Copyright (C) 2005, 2007 Maciej W. Rozycki
> * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
> + * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
> */
>
> #include <linux/kernel.h>
> @@ -35,27 +36,6 @@ enum fields {
> SCIMM = 0x400
> };
>
> -#define OP_MASK 0x3f
> -#define OP_SH 26
> -#define RS_MASK 0x1f
> -#define RS_SH 21
> -#define RT_MASK 0x1f
> -#define RT_SH 16
> -#define RD_MASK 0x1f
> -#define RD_SH 11
> -#define RE_MASK 0x1f
> -#define RE_SH 6
> -#define IMM_MASK 0xffff
> -#define IMM_SH 0
> -#define JIMM_MASK 0x3ffffff
> -#define JIMM_SH 0
> -#define FUNC_MASK 0x3f
> -#define FUNC_SH 0
> -#define SET_MASK 0x7
> -#define SET_SH 0
> -#define SCIMM_MASK 0xfffff
> -#define SCIMM_SH 6
> -
> enum opcode {
> insn_invalid,
> insn_addiu, insn_addu, insn_and, insn_andi, insn_bbit0, insn_bbit1,
> @@ -77,14 +57,17 @@ struct insn {
> enum fields fields;
> };
>
> +/* Register length mask. */
> +#define RX_MASK 0x1f
> +
> /* This macro sets the non-variable bits of an instruction. */
> #define M(a, b, c, d, e, f) \
> - ((a) << OP_SH \
> - | (b) << RS_SH \
> - | (c) << RT_SH \
> - | (d) << RD_SH \
> - | (e) << RE_SH \
> - | (f) << FUNC_SH)
> + ((a) << 26 \
> + | (b) << 21 \
> + | (c) << 16 \
> + | (d) << 11 \
> + | (e) << 6 \
> + | (f) << 0)
>
> static struct insn insn_table[] __uasminitdata = {
> { insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
> @@ -158,30 +141,46 @@ static struct insn insn_table[] __uasminitdata = {
>
> static inline __uasminit u32 build_rs(u32 arg)
> {
> - WARN(arg & ~RS_MASK, KERN_WARNING "Micro-assembler field overflow\n");
> +#ifdef CONFIG_CPU_MICROMIPS
> +#define RS_SH 16
> +#else
> +#define RS_SH 21
> +#endif
I wonder if we could get rid of most of these #ifdefs by taking the
approach used in scripts/recordmcount.{c,h} or scripts/sortextable.{c,h}
That is, move all the code that varies between microMIPS and MIPS to an
included file. At the top of that file have a single
#if...#else...#endif block that defines the constants for each variety.
Then include this file as many times as needed (once or twice) to
produce the definitions required.
This would allow both a MIPS and microMIPS uasm to exist in the same kernel.
Use Case: Synthesizing VDSO code in a microMIPS kernel. The kernel
might be build for microMIPS, but the user space code in the VDSO must
(by the kernel ABI) be standard MIPS instructions.
>
> - return (arg & RS_MASK) << RS_SH;
> + WARN(arg & ~RX_MASK, KERN_WARNING "Micro-assembler field overflow\n");
> +
> + return (arg & RX_MASK) << RS_SH;
> }
>
> static inline __uasminit u32 build_rt(u32 arg)
> {
> - WARN(arg & ~RT_MASK, KERN_WARNING "Micro-assembler field overflow\n");
> +#ifdef CONFIG_CPU_MICROMIPS
> +#define RT_SH 21
> +#else
> +#define RT_SH 16
> +#endif
> +
> + WARN(arg & ~RX_MASK, KERN_WARNING "Micro-assembler field overflow\n");
>
> - return (arg & RT_MASK) << RT_SH;
> + return (arg & RX_MASK) << RT_SH;
> }
>
> static inline __uasminit u32 build_rd(u32 arg)
> {
> - WARN(arg & ~RD_MASK, KERN_WARNING "Micro-assembler field overflow\n");
> +#define RD_SH 11
>
> - return (arg & RD_MASK) << RD_SH;
> + WARN(arg & ~RX_MASK, KERN_WARNING "Micro-assembler field overflow\n");
> +
> + return (arg & RX_MASK) << RD_SH;
> }
>
> static inline __uasminit u32 build_re(u32 arg)
> {
> - WARN(arg & ~RE_MASK, KERN_WARNING "Micro-assembler field overflow\n");
> +#define RE_SH 6
>
> - return (arg & RE_MASK) << RE_SH;
> + WARN(arg & ~RX_MASK, KERN_WARNING "Micro-assembler field overflow\n");
> +
> + return (arg & RX_MASK) << RE_SH;
> }
>
> static inline __uasminit u32 build_simm(s32 arg)
> @@ -194,6 +193,8 @@ static inline __uasminit u32 build_simm(s32 arg)
>
> static inline __uasminit u32 build_uimm(u32 arg)
> {
> +#define IMM_MASK 0xffff
> +
> WARN(arg & ~IMM_MASK, KERN_WARNING "Micro-assembler field overflow\n");
>
> return arg & IMM_MASK;
> @@ -201,32 +202,54 @@ static inline __uasminit u32 build_uimm(u32 arg)
>
> static inline __uasminit u32 build_bimm(s32 arg)
> {
> - WARN(arg > 0x1ffff || arg < -0x20000,
> +#ifdef CONFIG_CPU_MICROMIPS
> +#define BIMM_SHIFT 1
> +#else
> +#define BIMM_SHIFT 2
> +#endif
> +
> + WARN(arg > (0x1ffff >> (2 - BIMM_SHIFT)) ||
> + arg < (-0x20000 >> (2 - BIMM_SHIFT)),
> KERN_WARNING "Micro-assembler field overflow\n");
>
> WARN(arg & 0x3, KERN_WARNING "Invalid micro-assembler branch target\n");
>
> - return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff);
> + return ((arg < 0) ? (1 << 15) : 0) | ((arg >> BIMM_SHIFT) & 0x7fff);
> }
>
> static inline __uasminit u32 build_jimm(u32 arg)
> {
> - WARN(arg & ~(JIMM_MASK << 2),
> +#define JIMM_MASK 0x3ffffff
> +#ifdef CONFIG_CPU_MICROMIPS
> + arg >>= 1;
> +#else
> + arg >>= 2;
> +#endif
> +
> + WARN(arg & ~JIMM_MASK,
> KERN_WARNING "Micro-assembler field overflow\n");
>
> - return (arg >> 2) & JIMM_MASK;
> + return (arg & JIMM_MASK);
> }
>
> static inline __uasminit u32 build_scimm(u32 arg)
> {
> - WARN(arg & ~SCIMM_MASK,
> +#ifdef CONFIG_CPU_MICROMIPS
> +#define SCIMM_SH 6
> +#else
> +#define SCIMM_SH 0
> +#endif
> +
> + WARN(arg & ~(0xfffff >> SCIMM_SH),
> KERN_WARNING "Micro-assembler field overflow\n");
>
> - return (arg & SCIMM_MASK) << SCIMM_SH;
> + return (arg & ((0xfffff >> SCIMM_SH) << (SCIMM_SH + 10)));
> }
>
> static inline __uasminit u32 build_func(u32 arg)
> {
> +#define FUNC_MASK 0x3f
> +
> WARN(arg & ~FUNC_MASK, KERN_WARNING "Micro-assembler field overflow\n");
>
> return arg & FUNC_MASK;
> @@ -234,6 +257,8 @@ static inline __uasminit u32 build_func(u32 arg)
>
> static inline __uasminit u32 build_set(u32 arg)
> {
> +#define SET_MASK 0x7
> +
> WARN(arg & ~SET_MASK, KERN_WARNING "Micro-assembler field overflow\n");
>
> return arg & SET_MASK;
> @@ -245,6 +270,11 @@ static inline __uasminit u32 build_set(u32 arg)
> */
> static void __uasminit build_insn(u32 **buf, enum opcode opc, ...)
> {
> +#if defined(CONFIG_CPU_MICROMIPS) && defined(CONFIG_CPU_LITTLE_ENDIAN)
> +#define OP_SHIFT 16
> +#else
> +#define OP_SHIFT 0
> +#endif
> struct insn *ip = NULL;
> unsigned int i;
> va_list ap;
> @@ -285,7 +315,7 @@ static void __uasminit build_insn(u32 **buf, enum opcode opc, ...)
> op |= build_scimm(va_arg(ap, u32));
> va_end(ap);
>
> - **buf = op;
> + **buf = ((op & 0xffff) << OP_SHIFT) | (op >> OP_SHIFT);
> (*buf)++;
> }
>
> @@ -555,12 +585,17 @@ UASM_EXPORT_SYMBOL(uasm_r_mips_pc16);
> static inline void __uasminit
> __resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab)
> {
> +#if defined(CONFIG_CPU_MICROMIPS) && defined(CONFIG_CPU_LITTLE_ENDIAN)
> +#define REL_SHIFT 16
> +#else
> +#define REL_SHIFT 0
> +#endif
> long laddr = (long)lab->addr;
> long raddr = (long)rel->addr;
>
> switch (rel->type) {
> case R_MIPS_PC16:
> - *rel->addr |= build_bimm(laddr - (raddr + 4));
> + *rel->addr |= (build_bimm(laddr - (raddr + 4)) << REL_SHIFT);
> break;
>
> default:
>
next prev parent reply other threads:[~2013-01-30 18:04 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-01-30 2:50 [PATCH][RFC] MIPS: microMIPS: Add support to micro-assembler Steven J. Hill
2013-01-30 2:52 ` Hill, Steven
2013-01-30 18:04 ` David Daney [this message]
2013-02-04 16:06 ` Hill, Steven
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=510960B9.1060800@gmail.com \
--to=ddaney.cavm@gmail.com \
--cc=cernekee@gmail.com \
--cc=linux-mips@linux-mips.org \
--cc=ralf@linux-mips.org \
--cc=sjhill@mips.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox