Lattice Mico32 port

Richard Henderson rth@redhat.com
Wed Sep 23 17:29:00 GMT 2009


> +#define PSEUDO_REG_P(X) ((X)>=FIRST_PSEUDO_REGISTER)

There's already a HARD_REGISTER_NUM_P that's the exact inverse.

> +#define G_REG_P(X)      ((X)<32)

I suppose you're planning to add floating point registers?

> +#define CONST_OK_FOR_LETTER_P(VALUE, C)                 \
> +(  (C) == 'J' ? (VALUE) == 0                            \
> + : (C) == 'K' ? MEDIUM_INT (VALUE)                      \
> + : (C) == 'L' ? MEDIUM_UINT (VALUE)                     \
> + : (C) == 'M' ? LARGE_INT (VALUE)                       \
> + : 0                                                    \
> +)
> +
> +#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C)  0

These defines are replaced by define_constraint,
typically in constraints.md.

> +/* FIXME - This is not yet supported.  */
> +#define STATIC_CHAIN_REGNUM 3

While you don't actually support this yet, you'd do well to
define it to one of the call-clobbered registers that isn't
an argument register -- r9 or r10 by the looks of it.

> +#define GO_IF_LEGITIMATE_ADDRESS(m,x,l)                 \

Use the TARGET_LEGITIMATE_ADDRESS_P target hook.

> +#define ARM_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)          \

Copy and paste?

> +#define MEDIUM_INT(X)  ((((HOST_WIDE_INT)(X)) >= -32768) && (((HOST_WIDE_INT)(X)) < 32768))
> +#define MEDIUM_UINT(X) (((unsigned HOST_WIDE_INT)(X)) < 65536)

Use the IN_RANGE macro.  And if you move these to define_constraints, as 
mentioned above, you won't need the cast to HOST_WIDE_INT.

 > +#define LARGE_INT(X)                                    \
 > +((X) >= (-(HOST_WIDE_INT) 0x7fffffff - 1)               \
 > + && (X) <= (unsigned HOST_WIDE_INT) 0xffffffff)

Did you really want a signed low and an unsigned high on this?  It would 
seem that at some point you're getting signed and unsigned values 
confused somewhere if you need this...

> +__ashlsi3:
> +        /* Only use 5 LSBs, as that's all the h/w shifter uses.  */
> +        andi    r2, r2, 0x1f
> +        /* Get address of offset into unrolled shift loop to jump to.  */
> +#ifdef __PIC__
> +        orhi    r3, r0, gotoffhi16(__ashlsi3_table)
> +        addi    r3, r3, gotofflo16(__ashlsi3_table)
> +        add     r3, r3, gp
> +#else
> +        mvhi    r3, hi(__ashlsi3_table)
> +        ori     r3, r3, lo(__ashlsi3_table)
> +#endif

Seems like avoiding the table and knowing that each entry is 4 bytes 
back would be a teeny bit faster.

	mvhi	r3, hi(__ashlsi3_0)
	add	r2, r2, r2
	ori	r3, r3, lo(__ashlsi3_0)
	add	r2, r2, r2
	sub	r3, r3, r2
	b	r3

Also, it would seem that you'd be able to arrange for these alternate 
entry points to be invoked directly.  Something like

(define_insn "*ashlsi3_const"
   [(set (match_operand:SI 0 "register_operand" "=R1")
         (ashift:SI (match_operand:SI 1 "register_operand" "0")
                    (match_operand:SI 2 "const_5bit_operand" "i")))
    (clobber (match_scratch:SI 3 "=RA"))]
   "!TARGET_BARREL_SHIFT_ENABLED"
   "calli	__ashlsi3_%2"
   [(set_attr "type" "call")])

Where R1 and RA are singleton register classes for those respective 
registers.  Obviously you can delay this as an improvement for later.

> +      /* Raise divide by zero exception.  */
> +      int eba;
> +      __asm__ __volatile__ ("rcsr %0, EBA":"=r" (eba));
> +      eba += 32 * 5;
> +      __asm__ __volatile__ ("mv ea, ra");
> +      __asm__ __volatile__ ("b %0"::"r" (eba));

You want to put __builtin_unreachable() there after the branch.

> +          emit_insn (gen_movsi_imm_lo (operands[0], operands[0], GEN_INT (INTVAL (operands[1]))));

Line wrap.  There are other instances too.

> +(define_insn "movsi_kimm"
> +(define_insn "movsi_limm"
> +(define_insn "movsi_imm_hi"
> +(define_insn "movsi_reloc_gprel"
> +(define_insn "movsi_reloc_hi"
> +(define_insn "*movsi_insn"

Having these as separate instruction patterns is an extremely bad idea. 
  All moves of a given mode should be in the same pattern, so that 
reload can have the freedom to do its spilling as needed.  While your 
unspecs are except from this, things that just use HIGH aren't.

Using HIGH and LO_SUM on integer constants is a bad idea.  Much better 
to just go ahead and create a constraint letter; see for instance 
Alpha's define_constraint "L".

> +(define_insn "*movqi_insn"
> +  [(set (match_operand:QI 0 "register_or_memory_operand" "=r,r,m")
> +        (match_operand:QI 1 "register_or_memory_operand" "m,r,r"))]

Not having QImode or HImode constants is a mistake.

> +static bool
> +lm32_frame_pointer_required (void)
> +{
> +  /* If the function contains dynamic stack allocations, we need to
> +     use the frame pointer to access the static parts of the frame.  */
> +  if (cfun->calls_alloca)
> +    return true;

alloca is handled for you by generic code.
You shouldn't need to define this hook at all.



r~



More information about the Gcc mailing list