This seems to work, with a suitable extendhipsi2 pattern for m32c:
Index: expr.c =================================================================== --- expr.c (revision 140759) +++ expr.c (working copy) @@ -8455,12 +8459,34 @@ expand_expr_real_1 (tree exp, rtx target if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER) op0 = force_operand (op0, target); return REDUCE_BIT_FIELD (op0); } } + if (code == POINTER_PLUS_EXPR + || TYPE_PRECISION (TREE_OPERAND (exp, 1)) < TYPE_PRECISION (TREE_OPERAND (exp, 0))) + { + rtx reg; + enum machine_mode imode, omode; + + expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1), + subtarget, &op0, &op1, 0); + + if (op0 == const0_rtx) + return op1; + if (op1 == const0_rtx) + return op0; + + imode = GET_MODE (op1); + omode = GET_MODE (op0); + reg = gen_reg_rtx (omode); + emit_move_insn (reg, gen_rtx_fmt_e (SIGN_EXTEND, omode, op1)); + op1 = reg; + goto binop2; + } + /* No sense saving up arithmetic to be done if it's all in the wrong mode to form part of an address. And force_operand won't know whether to sign-extend or zero-extend. */ if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER) || mode != ptr_mode)