Help Emitting Proper Immediates

Shivam Patel shivamp12@hotmail.com
Tue Nov 11 02:29:40 GMT 2025


Hi,

I'm working on a GCC backend for an extensible hobbyist ISA. I'm trying to start by targeting the version with no extensions, in which the largest immediate allowed for arithmetic and logical operations is 5 bits. When building libgcc for this target, I see that my predicates and patterns are not preventing GCC from emitting immediates outside the 5-bit range. Here's an example error caused by _muldi3:

...
mov %tq0, %aq1
...
andd %td0, 65535
...
mov [%s1], %td0


The andd %td0, 65535 instruction is attempting to use a 16-bit mask (0xFFFF) with a 32-bit instruction. -1 would be a valid immediate for this instruction, but would represent the mask 0xFFFF_FFFF instead. The mask 0x0000_FFFF needs to be moved into a register first. Here is the pattern for the and instruction in our backend:

(define_insn "and<mode>3"
  [(set (match_operand:SS 0 "register_operand" "=r")
    (and:SS
     (match_operand:SS 1 "register_operand" "%0")
     (match_operand:SS 2 "etca_arithmetic_operand_signed" "ri")))]
  ""
  "and<x>\\t\\t%<x>0, %<x>2"
)

and here is the etca_arithmetic_operand_signed predicate that we use:

(define_predicate "etca_arithmetic_operand_signed"
  (match_code "const_int,reg,subreg,const")
{
  if (CONST_INT_P (op)) {
    return IN_RANGE(INTVAL(op), -16, 15);
  }
  return general_operand (op, mode);
})

For this particular error, eventually GCC will need to use the zero-extension instruction in the ISA (movz). However I've seen this same immediate size issue with instructions like subd, where I don't think that would help. Is there a reason why immediates that are out of range are being emitted during the libgcc build process? Is there anything wrong with the way I've defined our predicate and pattern?

Best,
Shivam


More information about the Gcc-help mailing list