Re: [PATCH v99,01/13] MIPS: microMIPS: Add support for microMIPS instructions.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Dec 6, 2012 at 9:05 PM, Steven J. Hill <sjhill@xxxxxxxx> wrote:
> @@ -267,6 +268,225 @@ struct b_format { /* BREAK and SYSCALL */
>  	unsigned int func:6;
>  };
>
> +struct fb_format {	/* FPU branch format */
> +	unsigned int opcode:6;
> +	unsigned int bc:5;
> +	unsigned int cc:3;
> +	unsigned int flag:2;
> +	unsigned int simmediate:16;
> +};

Some random thoughts/nitpicks on this section:

The microMIPS patch nearly quadruples the number of instruction
formats in the mips_instruction union, so it might be worth
considering questions like:

1) Is this the optimal way to represent this information, or have we
reached a point where it is worth adding more complex "infrastructure"
that would support a more compact instruction definition format?

2) Is there a better way to handle the LE/BE bitfield problem, than to
duplicate each of the 28+ structs?

On the nitpick front:

3) After "struct NAME_format {", are tabs or spaces used to offset the
comment?  Seems like a mix.  (The original code isn't entirely
consistent either, but this could be an opportunity to tidy it up.)

4) Spaces around ':' in e.g. "opcode:6" would be more consistent with
"most" of the other entries in inst.h

5) Should "FPU multipy" be "FPU multiply"?

6) The names of the special MIPS16e structs (rr, jal, i64, ri*) are a
little terse and may create a conflict someday.  If you don't want to
use "INSTR_format" for specific instruction names, you could use
something like "INSTR_instr" instead.

> +struct jal {
> +	unsigned int opcode:5;
> +	unsigned int x:1;
> +	unsigned int imm20_16:5;
> +	signed int imm25_21:5;
> +	/* unsigned int    imm20_15:0;  here is only first 16bits in first HW */

I'm assuming this meant to say: "there are only 16 bits in the first halfword"?

It might be clearer to just leave a comment like:

+	signed int imm25_21:5;
+	/* the subsequent [or previous] halfword contains imm15_0 */

> +/*
> + * This functions returns 1 if the microMIPS instr is a 16 bit instr.

Suggest "This function returns"

> + * Otherwise return 0.
> + */
> +#define MIPS_ISA_MODE   01
> +#define is16mode(regs)  (regs->cp0_epc & MIPS_ISA_MODE)
> +
> +static inline int mm_is16bit(u16 instr)

Does the comment refer to the is16mode() macro, or to mm_is16bit()?

Does is16mode(), which tests EPC during exception handling, belong in
the uasm header file?

You might want to indicate that the value passed into mm_is16bit() is
either a complete 16-bit MM (microMIPS) instruction, or the most
significant halfword of a 32-bit MM instruction.  i.e. it isn't
necessarily a complete instruction

> +	{ insn_bltzl, 0, 0 },
> +	{ insn_bne, M(mm_bne32_op, 0, 0, 0, 0, 0), RT | RS | BIMM },
> +	{ insn_cache, M(mm_pool32b_op, 0, 0, mm_cache_func, 0, 0), RT | RS | SIMM },
> +	{ insn_daddu, 0, 0 },
> +	{ insn_daddiu, 0, 0 },
> +	{ insn_dmfc0, 0, 0 },

Do the "{ insn_X, 0, 0 }" entries indicate that these instructions
(which were defined in MIPS mode) are unsupported in MM mode?

> +static inline __uasminit u32 build_bimm(s32 arg)
> +{
> +	if(arg > 0xffff || arg < -0x10000)

"if(" triggers a checkpatch violation (there are a few others too).

> +		printk(KERN_WARNING "Micro-assembler field overflow\n");

Consider pr_warning()

> +static inline __uasminit u32 build_jimm(u32 arg)
> +{
> +	if ((arg & ~(JIMM_MASK << 1)) - 1)
> +		printk(KERN_WARNING "Micro-assembler field overflow\n");

This expression evaluates to -1 (i.e. print a warning) for small
values of arg, like 0 or 4.

Would something like this work?

arg >>= 1;
if (arg & ~JIMM_MASK)
	pr_warning("Micro-assembler field overflow\n");
return arg & JIMM_MASK;

> +/*
> + * The order of opcode arguments is implicitly left to right,
> + * starting with RS and ending with FUNC or IMM.
> + */
> +static void __uasminit build_insn(u32 **buf, enum opcode opc, ...)

There are a lot of similarities between the MM and MIPS versions of
these functions.  Likewise for build_bimm() and build_jimm(), which
only differ because the shifts/ranges are not the same.  Is there a
way to make better reuse of the code?

> +#ifdef CONFIG_CPU_LITTLE_ENDIAN
> +	**buf = ((op & 0xffff) << 16) | (op >> 16);
> +#else
> +	**buf = op;
> +#endif

If the MM instruction stream can consist of either 16-bit or 32-bit
instructions, shouldn't this be a "u16 **" pointer?

And if it is, does that make the LE/BE test unnecessary?

> diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c
> new file mode 100644
> index 0000000..e86334b
> --- /dev/null
> +++ b/arch/mips/mm/uasm-mips.c

It would be good to have a separate commit that JUST splits uasm.c out
into uasm-mips.c (no other changes).  The commit message would ideally
explain the rationale.

> +/*
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License.  See the file "COPYING" in the main directory of this archive
> + * for more details.
> + *
> + * Copyright (C) 2012 MIPS Technologies, Inc.  All rights reserved.
> + */

Suggest leaving the original uasm.c authors' copyright info in the
uasm-mips.c header.

> +#ifdef CONFIG_CPU_MICROMIPS
> +#define RS_SH		16
> +#define RT_SH		21
> +#define SCIMM_MASK	0x3ff
> +#define SCIMM_SH	16

Can these be defined in a single place?

> -	WARN(arg & ~RS_MASK, KERN_WARNING "Micro-assembler field overflow\n");
> +	if (arg & ~RS_MASK)
> +		printk(KERN_WARNING "Micro-assembler RS field overflow\n");

Since this looks unrelated to MM support, it might be best to put it
in a separate commit.  What is the benefit of changing WARN() to
printk()?

Also, if printk() absolutely must be used, it might make sense to
consolidate the uasm warning prints into a single non-inlined
function, so that if somebody sees an overflow message and wants to
debug the problem, they can set one breakpoint instead of 10+
breakpoints.  WARN() may have helped indicate the source of the
failure but printk() won't.

> -	WARN(arg & ~RT_MASK, KERN_WARNING "Micro-assembler field overflow\n");
> +	if (arg & ~RT_MASK)
> +		printk(KERN_WARNING "Micro-assembler RT field overflow\n");

FWIW, using a unique string for each error case means the compiler can
no longer point all of these printk's to a single copy of the same
string...

> +#ifdef CONFIG_CPU_MICROMIPS
> +#include "uasm-micromips.c"
> +#else
> +#include "uasm-mips.c"
> +#endif

There's an awful lot of potential reuse between these two
configurations and I'm not sure if it makes sense to split them this
way.

If possible it would be good if we didn't have to enable
CONFIG_CPU_MICROMIPS to know that the MM code compiles.


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux