rtl.h (REG_NREGS): New macro

gcc/
	* rtl.h (REG_NREGS): New macro
	* alias.c (record_set): Use it.
	* cfgcleanup.c (mark_effect): Likewise.
	* combine.c (likely_spilled_retval_1): Likewise.
	(likely_spilled_retval_p, can_change_dest_mode): Likewise.
	(move_deaths, distribute_notes): Likewise.
	* cselib.c (cselib_record_set): Likewise.
	* df-problems.c (df_simulate_one_insn_forwards): Likewise.
	* df-scan.c (df_mark_reg): Likewise.
	* dse.c (look_for_hardregs): Likewise.
	* dwarf2out.c (reg_loc_descriptor): Likewise.
	(multiple_reg_loc_descriptor): Likewise.
	* expr.c (write_complex_part, read_complex_part): Likewise.
	(emit_move_complex): Likewise.
	* haifa-sched.c (setup_ref_regs): Likewise.
	* ira-lives.c (mark_hard_reg_live): Likewise.
	* lra.c (lra_set_insn_recog_data): Likewise.
	* mode-switching.c (create_pre_exit): Likewise.
	* postreload.c (reload_combine_recognize_const_pattern): Likewise.
	(reload_combine_recognize_pattern): Likewise.
	(reload_combine_note_use, move2add_record_mode): Likewise.
	(reload_cse_move2add): Likewise.
	* reg-stack.c (subst_stack_regs_pat): Likewise.
	* regcprop.c (kill_value, copy_value): Likewise.
	(copyprop_hardreg_forward_1): Likewise.
	* regrename.c (verify_reg_in_set, scan_rtx_reg): Likewise.
	(build_def_use): Likewise.
	* sched-deps.c (mark_insn_reg_birth, mark_reg_death): Likewise.
	(deps_analyze_insn): Likewise.
	* sched-rgn.c (check_live_1, update_live_1): Likewise.
	* sel-sched.c (count_occurrences_equiv): Likewise.
	* valtrack.c (dead_debug_insert_temp): Likewise.

From-SVN: r223337
This commit is contained in:
Richard Sandiford 2015-05-19 07:09:06 +00:00 committed by Richard Sandiford
parent 53d1bae901
commit dc8afb709d
23 changed files with 89 additions and 88 deletions

View File

@ -1,3 +1,38 @@
2015-05-19 Richard Sandiford <richard.sandiford@arm.com>
* rtl.h (REG_NREGS): New macro
* alias.c (record_set): Use it.
* cfgcleanup.c (mark_effect): Likewise.
* combine.c (likely_spilled_retval_1): Likewise.
(likely_spilled_retval_p, can_change_dest_mode): Likewise.
(move_deaths, distribute_notes): Likewise.
* cselib.c (cselib_record_set): Likewise.
* df-problems.c (df_simulate_one_insn_forwards): Likewise.
* df-scan.c (df_mark_reg): Likewise.
* dse.c (look_for_hardregs): Likewise.
* dwarf2out.c (reg_loc_descriptor): Likewise.
(multiple_reg_loc_descriptor): Likewise.
* expr.c (write_complex_part, read_complex_part): Likewise.
(emit_move_complex): Likewise.
* haifa-sched.c (setup_ref_regs): Likewise.
* ira-lives.c (mark_hard_reg_live): Likewise.
* lra.c (lra_set_insn_recog_data): Likewise.
* mode-switching.c (create_pre_exit): Likewise.
* postreload.c (reload_combine_recognize_const_pattern): Likewise.
(reload_combine_recognize_pattern): Likewise.
(reload_combine_note_use, move2add_record_mode): Likewise.
(reload_cse_move2add): Likewise.
* reg-stack.c (subst_stack_regs_pat): Likewise.
* regcprop.c (kill_value, copy_value): Likewise.
(copyprop_hardreg_forward_1): Likewise.
* regrename.c (verify_reg_in_set, scan_rtx_reg): Likewise.
(build_def_use): Likewise.
* sched-deps.c (mark_insn_reg_birth, mark_reg_death): Likewise.
(deps_analyze_insn): Likewise.
* sched-rgn.c (check_live_1, update_live_1): Likewise.
* sel-sched.c (count_occurrences_equiv): Likewise.
* valtrack.c (dead_debug_insert_temp): Likewise.
2015-05-19 Richard Sandiford <richard.sandiford@arm.com>
* cfgcleanup.c (mentions_nonequal_regs): Use END_REGNO.

View File

@ -1298,12 +1298,7 @@ record_set (rtx dest, const_rtx set, void *data ATTRIBUTE_UNUSED)
gcc_checking_assert (regno < reg_base_value->length ());
/* If this spans multiple hard registers, then we must indicate that every
register has an unusable value. */
if (regno < FIRST_PSEUDO_REGISTER)
n = hard_regno_nregs[regno][GET_MODE (dest)];
else
n = 1;
n = REG_NREGS (dest);
if (n != 1)
{
while (--n >= 0)

View File

@ -234,8 +234,7 @@ mark_effect (rtx exp, regset nonequal)
dest = XEXP (exp, 0);
regno = REGNO (dest);
if (HARD_REGISTER_NUM_P (regno))
bitmap_clear_range (nonequal, regno,
hard_regno_nregs[regno][GET_MODE (dest)]);
bitmap_clear_range (nonequal, regno, REG_NREGS (dest));
else
bitmap_clear_bit (nonequal, regno);
}
@ -251,8 +250,7 @@ mark_effect (rtx exp, regset nonequal)
return true;
regno = REGNO (dest);
if (HARD_REGISTER_NUM_P (regno))
bitmap_set_range (nonequal, regno,
hard_regno_nregs[regno][GET_MODE (dest)]);
bitmap_set_range (nonequal, regno, REG_NREGS (dest));
else
bitmap_set_bit (nonequal, regno);
return false;

View File

@ -2364,7 +2364,7 @@ likely_spilled_retval_1 (rtx x, const_rtx set, void *data)
regno = REGNO (x);
if (regno >= info->regno + info->nregs)
return;
nregs = hard_regno_nregs[regno][GET_MODE (x)];
nregs = REG_NREGS (x);
if (regno + nregs <= info->regno)
return;
new_mask = (2U << (nregs - 1)) - 1;
@ -2399,7 +2399,7 @@ likely_spilled_retval_p (rtx_insn *insn)
if (!REG_P (reg) || !targetm.calls.function_value_regno_p (REGNO (reg)))
return 0;
regno = REGNO (reg);
nregs = hard_regno_nregs[regno][GET_MODE (reg)];
nregs = REG_NREGS (reg);
if (nregs == 1)
return 0;
mask = (2U << (nregs - 1)) - 1;
@ -2471,8 +2471,7 @@ can_change_dest_mode (rtx x, int added_sets, machine_mode mode)
registers than the old mode. */
if (regno < FIRST_PSEUDO_REGISTER)
return (HARD_REGNO_MODE_OK (regno, mode)
&& (hard_regno_nregs[regno][GET_MODE (x)]
>= hard_regno_nregs[regno][mode]));
&& REG_NREGS (x) >= hard_regno_nregs[regno][mode]);
/* Or a pseudo that is only used once. */
return (regno < reg_n_sets_max
@ -13474,7 +13473,7 @@ move_deaths (rtx x, rtx maybe_kill_insn, int from_luid, rtx_insn *to_insn,
&& (GET_MODE_SIZE (GET_MODE (XEXP (note, 0)))
< GET_MODE_SIZE (GET_MODE (x)))))
&& regno < FIRST_PSEUDO_REGISTER
&& hard_regno_nregs[regno][GET_MODE (x)] > 1)
&& REG_NREGS (x) > 1)
{
unsigned int ourend = END_HARD_REGNO (x);
unsigned int i, offset;
@ -14069,8 +14068,7 @@ distribute_notes (rtx notes, rtx_insn *from_insn, rtx_insn *i3, rtx_insn *i2,
be dead; so we recourse, and the recursive call then finds
the previous insn that used this register. */
if (place && regno < FIRST_PSEUDO_REGISTER
&& hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))] > 1)
if (place && REG_NREGS (XEXP (note, 0)) > 1)
{
unsigned int endregno = END_HARD_REGNO (XEXP (note, 0));
bool all_used = true;

View File

@ -2371,16 +2371,15 @@ cselib_invalidate_rtx_note_stores (rtx dest, const_rtx ignore ATTRIBUTE_UNUSED,
static void
cselib_record_set (rtx dest, cselib_val *src_elt, cselib_val *dest_addr_elt)
{
int dreg = REG_P (dest) ? (int) REGNO (dest) : -1;
if (src_elt == 0 || side_effects_p (dest))
return;
if (dreg >= 0)
if (REG_P (dest))
{
unsigned int dreg = REGNO (dest);
if (dreg < FIRST_PSEUDO_REGISTER)
{
unsigned int n = hard_regno_nregs[dreg][GET_MODE (dest)];
unsigned int n = REG_NREGS (dest);
if (n > max_value_regs)
max_value_regs = n;

View File

@ -3576,8 +3576,7 @@ df_simulate_one_insn_forwards (basic_block bb, rtx_insn *insn, bitmap live)
rtx reg = XEXP (link, 0);
int regno = REGNO (reg);
if (HARD_REGISTER_NUM_P (regno))
bitmap_clear_range (live, regno,
hard_regno_nregs[regno][GET_MODE (reg)]);
bitmap_clear_range (live, regno, REG_NREGS (reg));
else
bitmap_clear_bit (live, regno);
}

View File

@ -3516,10 +3516,7 @@ df_mark_reg (rtx reg, void *vset)
gcc_assert (GET_MODE (reg) != BLKmode);
if (regno < FIRST_PSEUDO_REGISTER)
{
int n = hard_regno_nregs[regno][GET_MODE (reg)];
bitmap_set_range (set, regno, n);
}
bitmap_set_range (set, regno, REG_NREGS (reg));
else
bitmap_set_bit (set, regno);
}

View File

@ -1876,11 +1876,7 @@ look_for_hardregs (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
if (REG_P (x)
&& HARD_REGISTER_P (x))
{
unsigned int regno = REGNO (x);
bitmap_set_range (regs_set, regno,
hard_regno_nregs[regno][GET_MODE (x)]);
}
bitmap_set_range (regs_set, REGNO (x), REG_NREGS (x));
}
/* Helper function for replace_read and record_store.

View File

@ -11147,7 +11147,7 @@ reg_loc_descriptor (rtx rtl, enum var_init_status initialized)
regs = targetm.dwarf_register_span (rtl);
if (hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)] > 1 || regs)
if (REG_NREGS (rtl) > 1 || regs)
return multiple_reg_loc_descriptor (rtl, regs, initialized);
else
{
@ -11204,7 +11204,7 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs,
#endif
gcc_assert ((unsigned) DBX_REGISTER_NUMBER (reg) == dbx_reg_number (rtl));
nregs = hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)];
nregs = REG_NREGS (rtl);
size = GET_MODE_SIZE (GET_MODE (rtl)) / nregs;

View File

@ -3051,7 +3051,7 @@ write_complex_part (rtx cplx, rtx val, bool imag_p)
where the natural size of floating-point regs is 32-bit. */
|| (REG_P (cplx)
&& REGNO (cplx) < FIRST_PSEUDO_REGISTER
&& hard_regno_nregs[REGNO (cplx)][cmode] % 2 == 0))
&& REG_NREGS (cplx) % 2 == 0))
{
rtx part = simplify_gen_subreg (imode, cplx, cmode,
imag_p ? GET_MODE_SIZE (imode) : 0);
@ -3116,7 +3116,7 @@ read_complex_part (rtx cplx, bool imag_p)
where the natural size of floating-point regs is 32-bit. */
|| (REG_P (cplx)
&& REGNO (cplx) < FIRST_PSEUDO_REGISTER
&& hard_regno_nregs[REGNO (cplx)][cmode] % 2 == 0))
&& REG_NREGS (cplx) % 2 == 0))
{
rtx ret = simplify_gen_subreg (imode, cplx, cmode,
imag_p ? GET_MODE_SIZE (imode) : 0);
@ -3346,10 +3346,10 @@ emit_move_complex (machine_mode mode, rtx x, rtx y)
&& optab_handler (mov_optab, GET_MODE_INNER (mode)) != CODE_FOR_nothing
&& !(REG_P (x)
&& HARD_REGISTER_P (x)
&& hard_regno_nregs[REGNO (x)][mode] == 1)
&& REG_NREGS (x) == 1)
&& !(REG_P (y)
&& HARD_REGISTER_P (y)
&& hard_regno_nregs[REGNO (y)][mode] == 1))
&& REG_NREGS (y) == 1))
try_int = false;
/* Not possible if the values are inherently not adjacent. */
else if (GET_CODE (x) == CONCAT || GET_CODE (y) == CONCAT)

View File

@ -1040,8 +1040,7 @@ setup_ref_regs (rtx x)
{
regno = REGNO (x);
if (HARD_REGISTER_NUM_P (regno))
bitmap_set_range (region_ref_regs, regno,
hard_regno_nregs[regno][GET_MODE (x)]);
bitmap_set_range (region_ref_regs, regno, REG_NREGS (x));
else
bitmap_set_bit (region_ref_regs, REGNO (x));
return;

View File

@ -352,7 +352,7 @@ mark_hard_reg_live (rtx reg)
if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
{
int last = regno + hard_regno_nregs[regno][GET_MODE (reg)];
int last = END_REGNO (reg);
enum reg_class aclass, pclass;
while (regno < last)

View File

@ -1104,10 +1104,7 @@ lra_set_insn_recog_data (rtx_insn *insn)
regno = REGNO (XEXP (XEXP (link, 0), 0));
lra_assert (regno < FIRST_PSEUDO_REGISTER);
/* It is an argument register. */
for (i = (hard_regno_nregs
[regno][GET_MODE (XEXP (XEXP (link, 0), 0))]) - 1;
i >= 0;
i--)
for (i = REG_NREGS (XEXP (XEXP (link, 0), 0)) - 1; i >= 0; i--)
arg_hard_regs[n_hard_regs++] = regno + i;
}
if (n_hard_regs != 0)

View File

@ -267,7 +267,7 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
&& GET_CODE ((ret_reg = XEXP (PATTERN (last_insn), 0))) == REG)
{
int ret_start = REGNO (ret_reg);
int nregs = hard_regno_nregs[ret_start][GET_MODE (ret_reg)];
int nregs = REG_NREGS (ret_reg);
int ret_end = ret_start + nregs;
bool short_block = false;
bool multi_reg_return = false;

View File

@ -971,7 +971,7 @@ reload_combine_recognize_const_pattern (rtx_insn *insn)
reg = SET_DEST (set);
src = SET_SRC (set);
if (!REG_P (reg)
|| hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] != 1
|| REG_NREGS (reg) != 1
|| GET_MODE (reg) != Pmode
|| reg == stack_pointer_rtx)
return false;
@ -1106,8 +1106,7 @@ reload_combine_recognize_pattern (rtx_insn *insn)
reg = SET_DEST (set);
src = SET_SRC (set);
if (!REG_P (reg)
|| hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] != 1)
if (!REG_P (reg) || REG_NREGS (reg) != 1)
return false;
regno = REGNO (reg);
@ -1563,7 +1562,7 @@ reload_combine_note_use (rtx *xp, rtx_insn *insn, int ruid, rtx containing_mem)
/* No spurious USEs of pseudo registers may remain. */
gcc_assert (regno < FIRST_PSEUDO_REGISTER);
nregs = hard_regno_nregs[regno][GET_MODE (x)];
nregs = REG_NREGS (x);
/* We can't substitute into multi-hard-reg uses. */
if (nregs > 1)
@ -1695,7 +1694,7 @@ move2add_record_mode (rtx reg)
else if (REG_P (reg))
{
regno = REGNO (reg);
nregs = hard_regno_nregs[regno][mode];
nregs = REG_NREGS (reg);
}
else
gcc_unreachable ();
@ -2135,7 +2134,7 @@ reload_cse_move2add (rtx_insn *first)
number of calls to gen_rtx_SET to avoid memory
allocation if possible. */
&& SCALAR_INT_MODE_P (GET_MODE (XEXP (cnd, 0)))
&& hard_regno_nregs[REGNO (XEXP (cnd, 0))][GET_MODE (XEXP (cnd, 0))] == 1
&& REG_NREGS (XEXP (cnd, 0)) == 1
&& CONST_INT_P (XEXP (cnd, 1)))
{
rtx implicit_set =

View File

@ -1470,8 +1470,7 @@ subst_stack_regs_pat (rtx_insn *insn, stack_ptr regstack, rtx pat)
case CALL:
{
int count;
for (count = hard_regno_nregs[REGNO (*dest)][GET_MODE (*dest)];
--count >= 0;)
for (count = REG_NREGS (*dest); --count >= 0;)
{
regstack->reg[++regstack->top] = REGNO (*dest) + count;
SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest) + count);

View File

@ -207,12 +207,7 @@ kill_value (const_rtx x, struct value_data *vd)
x = tmp ? tmp : SUBREG_REG (x);
}
if (REG_P (x))
{
unsigned int regno = REGNO (x);
unsigned int n = hard_regno_nregs[regno][GET_MODE (x)];
kill_value_regno (regno, n, vd);
}
kill_value_regno (REGNO (x), REG_NREGS (x), vd);
}
/* Remember that REGNO is valid in MODE. */
@ -333,8 +328,8 @@ copy_value (rtx dest, rtx src, struct value_data *vd)
return;
/* If SRC and DEST overlap, don't record anything. */
dn = hard_regno_nregs[dr][GET_MODE (dest)];
sn = hard_regno_nregs[sr][GET_MODE (dest)];
dn = REG_NREGS (dest);
sn = REG_NREGS (src);
if ((dr > sr && dr < sr + sn)
|| (sr > dr && sr < dr + dn))
return;
@ -1035,8 +1030,7 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
copy_value (dest, SET_SRC (x), vd);
ksvd.ignore_set_reg = dest;
set_regno = REGNO (dest);
set_nregs
= hard_regno_nregs[set_regno][GET_MODE (dest)];
set_nregs = REG_NREGS (dest);
break;
}
}

View File

@ -983,7 +983,7 @@ verify_reg_in_set (rtx op, HARD_REG_SET *pset)
return false;
regno = REGNO (op);
nregs = hard_regno_nregs[regno][GET_MODE (op)];
nregs = REG_NREGS (op);
all_live = all_dead = true;
while (nregs-- > 0)
if (TEST_HARD_REG_BIT (*pset, regno + nregs))
@ -1036,9 +1036,8 @@ scan_rtx_reg (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions act
{
struct du_head **p;
rtx x = *loc;
machine_mode mode = GET_MODE (x);
unsigned this_regno = REGNO (x);
int this_nregs = hard_regno_nregs[this_regno][mode];
int this_nregs = REG_NREGS (x);
if (action == mark_write)
{
@ -1624,13 +1623,8 @@ build_def_use (basic_block bb)
&& !(untracked_operands & (1 << i))
&& REG_P (op)
&& !verify_reg_tracked (op))
{
machine_mode mode = GET_MODE (op);
unsigned this_regno = REGNO (op);
unsigned this_nregs = hard_regno_nregs[this_regno][mode];
create_new_chain (this_regno, this_nregs, NULL, NULL,
NO_REGS);
}
create_new_chain (REGNO (op), REG_NREGS (op), NULL, NULL,
NO_REGS);
}
if (fail_current_block)

View File

@ -1697,6 +1697,14 @@ inline rtx_insn *JUMP_LABEL_AS_INSN (const rtx_insn *insn)
(df_ref_change_reg_with_loc (REGNO (RTX), N, RTX), XCUINT (RTX, 0, REG) = N)
#define SET_REGNO_RAW(RTX,N) (XCUINT (RTX, 0, REG) = N)
/* Return the number of consecutive registers in a REG. This is always
1 for pseudo registers and is determined by HARD_REGNO_NREGS for
hard registers. */
#define REG_NREGS(RTX) \
(REGNO (RTX) < FIRST_PSEUDO_REGISTER \
? (unsigned int) hard_regno_nregs[REGNO (RTX)][GET_MODE (RTX)] \
: 1)
/* ORIGINAL_REGNO holds the number the register originally had; for a
pseudo register turned into a hard reg this will hold the old pseudo
register number. */

View File

@ -2125,8 +2125,7 @@ mark_insn_reg_birth (rtx insn, rtx reg, bool clobber_p, bool unused_p)
regno = REGNO (reg);
if (regno < FIRST_PSEUDO_REGISTER)
mark_insn_hard_regno_birth (insn, regno,
hard_regno_nregs[regno][GET_MODE (reg)],
mark_insn_hard_regno_birth (insn, regno, REG_NREGS (reg),
clobber_p, unused_p);
else
mark_insn_pseudo_birth (insn, regno, clobber_p, unused_p);
@ -2185,7 +2184,7 @@ mark_reg_death (rtx reg)
regno = REGNO (reg);
if (regno < FIRST_PSEUDO_REGISTER)
mark_hard_regno_death (regno, hard_regno_nregs[regno][GET_MODE (reg)]);
mark_hard_regno_death (regno, REG_NREGS (reg));
else
mark_pseudo_death (regno);
}
@ -3645,7 +3644,7 @@ deps_analyze_insn (struct deps_desc *deps, rtx_insn *insn)
rtx_insn_list *cond_deps = NULL;
t = XEXP (t, 0);
regno = REGNO (t);
nregs = hard_regno_nregs[regno][GET_MODE (t)];
nregs = REG_NREGS (t);
while (nregs-- > 0)
{
struct deps_reg *reg_last = &deps->reg_last[regno + nregs];

View File

@ -1720,7 +1720,7 @@ check_live_1 (int src, rtx x)
if (regno < FIRST_PSEUDO_REGISTER)
{
/* Check for hard registers. */
int j = hard_regno_nregs[regno][GET_MODE (reg)];
int j = REG_NREGS (reg);
while (--j >= 0)
{
for (i = 0; i < candidate_table[src].split_bbs.nr_members; i++)
@ -1803,8 +1803,7 @@ update_live_1 (int src, rtx x)
basic_block b = candidate_table[src].update_bbs.first_member[i];
if (HARD_REGISTER_NUM_P (regno))
bitmap_set_range (df_get_live_in (b), regno,
hard_regno_nregs[regno][GET_MODE (reg)]);
bitmap_set_range (df_get_live_in (b), regno, REG_NREGS (reg));
else
bitmap_set_bit (df_get_live_in (b), regno);
}

View File

@ -825,9 +825,7 @@ count_occurrences_equiv (const_rtx what, const_rtx where)
{
/* Bail out if mode is different or more than one register is
used. */
if (GET_MODE (x) != GET_MODE (what)
|| (HARD_REGISTER_P (x)
&& hard_regno_nregs[REGNO (x)][GET_MODE (x)] > 1))
if (GET_MODE (x) != GET_MODE (what) || REG_NREGS (x) > 1)
return 0;
count += 1;
}

View File

@ -671,9 +671,7 @@ dead_debug_insert_temp (struct dead_debug_local *debug, unsigned int uregno,
the debug temp to. ??? We could bind the debug_expr to a
CONCAT or PARALLEL with the split multi-registers, and
replace them as we found the corresponding sets. */
else if (REGNO (reg) < FIRST_PSEUDO_REGISTER
&& (hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]
!= hard_regno_nregs[REGNO (reg)][GET_MODE (dest)]))
else if (REG_NREGS (reg) != REG_NREGS (dest))
breg = NULL;
/* Ok, it's the same (hardware) REG, but with a different
mode, so SUBREG it. */
@ -695,7 +693,7 @@ dead_debug_insert_temp (struct dead_debug_local *debug, unsigned int uregno,
setting REG in its mode would, we won't know what to bind
the debug temp to. */
else if (REGNO (reg) < FIRST_PSEUDO_REGISTER
&& (hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]
&& (REG_NREGS (reg)
!= hard_regno_nregs[REGNO (reg)][GET_MODE (dest)]))
breg = NULL;
/* Yay, we can use SRC, just adjust its mode. */