===================================================================
@@ -37,6 +37,55 @@
;;---------- Moving ------------------------
+(define_insn "movqi_from_mduc"
+ [(set (match_operand:QI 0 "register_operand" "=a")
+ (unspec_volatile:QI [(match_operand:QI 1 "" "")] UNS_BUILTIN_MDUC))]
+ ""
+ "mov\t%0, !0xf00e8"
+)
+
+(define_insn "movhi_from_mdal"
+ [(set (match_operand:HI 0 "register_operand" "=A")
+ (unspec_volatile:HI [(match_operand:HI 1 "" "")] UNS_BUILTIN_MDAL))]
+ ""
+ "movw\t%0, !0xffff0"
+)
+
+(define_insn "movhi_from_mdah"
+ [(set (match_operand:HI 0 "register_operand" "=A")
+ (unspec_volatile:HI [(match_operand:HI 1 "" "")] UNS_BUILTIN_MDAH))]
+ ""
+ "movw\t%0, !0xffff2"
+)
+
+(define_insn "movhi_from_mdbl"
+ [(set (match_operand:HI 0 "register_operand" "=A")
+ (unspec_volatile:HI [(match_operand 1)] UNS_BUILTIN_MDBL))]
+ ""
+ "movw\t%0, !0xffff4"
+)
+
+(define_insn "movhi_from_mdbh"
+ [(set (match_operand:HI 0 "register_operand" "=A")
+ (unspec_volatile:HI [(match_operand 1)] UNS_BUILTIN_MDBH))]
+ ""
+ "movw\t%0, !0xffff6"
+)
+
+(define_insn "movhi_from_mdcl"
+ [(set (match_operand:HI 0 "register_operand" "=A")
+ (unspec_volatile:HI [(match_operand 1)] UNS_BUILTIN_MDCL))]
+ ""
+ "movw\t%0, !0xf00e0"
+)
+
+(define_insn "movhi_from_mdch"
+ [(set (match_operand:HI 0 "register_operand" "=A")
+ (unspec_volatile:HI [(match_operand 1)] UNS_BUILTIN_MDCH))]
+ ""
+ "movw\t%0, !0xf00e2"
+)
+
(define_insn "movqi_to_es"
[(set (reg:QI ES_REG)
(match_operand:QI 0 "register_operand" "a"))]
@@ -51,6 +100,62 @@
"mov\t%0, es"
)
+(define_insn "movqi_to_mduc"
+ [(set (reg:QI 0 )
+ (unspec_volatile:QI [(match_operand:QI 0)] UNS_BUILTIN_MDUC))
+ (match_operand:QI 1 "register_operand" "A")]
+ ""
+ "mov\t!0xf00e8, %1"
+)
+
+(define_insn "movhi_to_mdal"
+ [(set (reg:HI 0 )
+ (unspec_volatile:HI [(match_operand:HI 0)] UNS_BUILTIN_MDAL))
+ (match_operand:HI 1 "register_operand" "A")]
+ ""
+ "movw\t!0xffff0, %1"
+)
+
+(define_insn "movhi_to_mdah"
+ [(set (reg:HI 0 )
+ (unspec_volatile:HI [(match_operand:HI 0)] UNS_BUILTIN_MDAH))
+ (match_operand:HI 1 "register_operand" "A")]
+ ""
+ "movw\t!0xffff2, %1"
+)
+
+(define_insn "movhi_to_mdbl"
+ [(set (reg:HI 0 )
+ (unspec_volatile:HI [(match_operand:HI 0)] UNS_BUILTIN_MDBL))
+ (match_operand:HI 1 "register_operand" "A")]
+ ""
+ "movw\t!0xffff4, %1"
+)
+
+(define_insn "movhi_to_mdbh"
+ [(set (reg:HI 0 )
+ (unspec_volatile:HI [(match_operand:HI 0)] UNS_BUILTIN_MDBH))
+ (match_operand:HI 1 "register_operand" "A")]
+ ""
+ "movw\t!0xffff6, %1"
+)
+
+(define_insn "movhi_to_mdcl"
+ [(set (reg:HI 0 )
+ (unspec_volatile:HI [(match_operand:HI 0)] UNS_BUILTIN_MDCL))
+ (match_operand:HI 1 "register_operand" "A")]
+ ""
+ "movw\t!0xf00e0, %1"
+)
+
+(define_insn "movhi_to_mdch"
+ [(set (reg:HI 0 )
+ (unspec_volatile:HI [(match_operand:HI 0)] UNS_BUILTIN_MDCH))
+ (match_operand:HI 1 "register_operand" "A")]
+ ""
+ "movw\t!0xf00e2, %1"
+)
+
(define_insn "movqi_cs"
[(set (reg:QI CS_REG)
(match_operand:QI 0 "register_operand" "a"))]
===================================================================
@@ -338,6 +338,10 @@
#undef TARGET_OPTION_OVERRIDE
#define TARGET_OPTION_OVERRIDE rl78_option_override
+#define MUST_SAVE_MDUC_REGISTER \
+ (TARGET_SAVE_MDUC_REGISTER \
+ && (is_interrupt_func (NULL_TREE)) && RL78_MUL_G13)
+
static void
rl78_option_override (void)
{
@@ -365,6 +369,9 @@
/* Address spaces are currently only supported by C. */
error ("-mes0 can only be used with C");
+ if (TARGET_SAVE_MDUC_REGISTER && !(TARGET_G13 || RL78_MUL_G13))
+ warning (0, "mduc registers only saved for G13 target");
+
switch (rl78_cpu_type)
{
case CPU_UNINIT:
@@ -1273,6 +1280,7 @@
int i, fs;
rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
rtx ax = gen_rtx_REG (HImode, AX_REG);
+ rtx operand1;
int rb = 0;
if (rl78_is_naked_func ())
@@ -1330,6 +1338,39 @@
F (emit_insn (gen_push (ax)));
}
+ /* Save MDUC register from interrupt routine. */
+ if (MUST_SAVE_MDUC_REGISTER)
+ {
+ emit_insn (gen_movqi_from_mduc (gen_rtx_REG (QImode, A_REG),
+ gen_rtx_UNSPEC_VOLATILE (QImode, gen_rtvec (1, operand1),
+ UNS_BUILTIN_MDUC)));
+ F (emit_insn (gen_push (ax)));
+ emit_insn (gen_movhi_from_mdal (gen_rtx_REG (HImode, AX_REG),
+ gen_rtx_UNSPEC_VOLATILE (HImode, gen_rtvec (1, operand1),
+ UNS_BUILTIN_MDAL)));
+ F (emit_insn (gen_push (ax)));
+ emit_insn (gen_movhi_from_mdah (gen_rtx_REG (HImode, AX_REG),
+ gen_rtx_UNSPEC_VOLATILE (HImode, gen_rtvec (1, operand1),
+ UNS_BUILTIN_MDAH)));
+ F (emit_insn (gen_push (ax)));
+ emit_insn (gen_movhi_from_mdbl (gen_rtx_REG (HImode, AX_REG),
+ gen_rtx_UNSPEC_VOLATILE (HImode, gen_rtvec (1, operand1),
+ UNS_BUILTIN_MDBL)));
+ F (emit_insn (gen_push (ax)));
+ emit_insn (gen_movhi_from_mdbh (gen_rtx_REG (HImode, AX_REG),
+ gen_rtx_UNSPEC_VOLATILE (HImode, gen_rtvec (1, operand1),
+ UNS_BUILTIN_MDBH)));
+ F (emit_insn (gen_push (ax)));
+ emit_insn (gen_movhi_from_mdcl (gen_rtx_REG (HImode, AX_REG),
+ gen_rtx_UNSPEC_VOLATILE (HImode, gen_rtvec (1, operand1),
+ UNS_BUILTIN_MDCL)));
+ F (emit_insn (gen_push (ax)));
+ emit_insn (gen_movhi_from_mdch (gen_rtx_REG (HImode, AX_REG),
+ gen_rtx_UNSPEC_VOLATILE (HImode, gen_rtvec (1, operand1),
+ UNS_BUILTIN_MDCH)));
+ F (emit_insn (gen_push (ax)));
+ }
+
if (frame_pointer_needed)
{
F (emit_move_insn (ax, sp));
@@ -1372,6 +1413,7 @@
int i, fs;
rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
rtx ax = gen_rtx_REG (HImode, AX_REG);
+ rtx operand1;
int rb = 0;
if (rl78_is_naked_func ())
@@ -1403,6 +1445,39 @@
}
}
+ /* Restore MDUC register from interrupt routine */
+ if (MUST_SAVE_MDUC_REGISTER)
+ {
+ emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
+ emit_insn (gen_movhi_to_mdch (gen_rtx_UNSPEC_VOLATILE (HImode,
+ gen_rtvec (1, operand1),UNS_BUILTIN_MDCH),
+ gen_rtx_REG (HImode, AX_REG)));
+ emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
+ emit_insn (gen_movhi_to_mdcl (gen_rtx_UNSPEC_VOLATILE (HImode,
+ gen_rtvec (1, operand1),UNS_BUILTIN_MDCL),
+ gen_rtx_REG (HImode, AX_REG)));
+ emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
+ emit_insn (gen_movhi_to_mdbh (gen_rtx_UNSPEC_VOLATILE (HImode,
+ gen_rtvec (1, operand1),UNS_BUILTIN_MDBH),
+ gen_rtx_REG (HImode, AX_REG)));
+ emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
+ emit_insn (gen_movhi_to_mdbl (gen_rtx_UNSPEC_VOLATILE (HImode,
+ gen_rtvec (1, operand1),UNS_BUILTIN_MDBL),
+ gen_rtx_REG (HImode, AX_REG)));
+ emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
+ emit_insn (gen_movhi_to_mdah (gen_rtx_UNSPEC_VOLATILE (HImode,
+ gen_rtvec (1, operand1),UNS_BUILTIN_MDAH),
+ gen_rtx_REG (HImode, AX_REG)));
+ emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
+ emit_insn (gen_movhi_to_mdal (gen_rtx_UNSPEC_VOLATILE (HImode,
+ gen_rtvec (1, operand1),UNS_BUILTIN_MDAL),
+ gen_rtx_REG (HImode, AX_REG)));
+ emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
+ emit_insn (gen_movqi_to_mduc (gen_rtx_UNSPEC_VOLATILE (QImode,
+ gen_rtvec (1, operand1),UNS_BUILTIN_MDUC),
+ gen_rtx_REG (QImode, A_REG)));
+ }
+
if (is_interrupt_func (cfun->decl) && cfun->machine->uses_es)
{
emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG)));
@@ -1498,6 +1573,9 @@
if (cfun->machine->uses_es)
fprintf (file, "\t; uses ES register\n");
+
+ if (MUST_SAVE_MDUC_REGISTER)
+ fprintf (file, "\t; uses MDUC register\n");
}
/* Return an RTL describing where a function return value of type RET_TYPE
===================================================================
@@ -50,6 +50,13 @@
(UNS_TRAMPOLINE_INIT 20)
(UNS_TRAMPOLINE_UNINIT 21)
(UNS_NONLOCAL_GOTO 22)
+ (UNS_BUILTIN_MDUC 35)
+ (UNS_BUILTIN_MDAL 36)
+ (UNS_BUILTIN_MDAH 37)
+ (UNS_BUILTIN_MDBL 38)
+ (UNS_BUILTIN_MDBH 39)
+ (UNS_BUILTIN_MDCL 40)
+ (UNS_BUILTIN_MDCH 41)
])
===================================================================
@@ -91,3 +91,7 @@
mes0
Target Mask(ES0)
Assume ES is zero throughout program execution, use ES: for read-only data.
+
+msave-mduc-in-interrupts
+Target Mask(SAVE_MDUC_REGISTER)
+Specifies whether interrupt functions should save and restore the MDUC register.
===================================================================
@@ -19026,6 +19026,14 @@
or 32 bits (@option{-m32bit-doubles}) in size. The default is
@option{-m32bit-doubles}.
+@item -msave-mduc-in-interrupts
+@opindex msave-mduc-in-interrupts
+Specifies that interrupt handler functions should preserve the
+MDUC registers. This is only necessary if normal code might use
+the MDUC register, for example because it performs multiplication
+and division operations. The default is to ignore the MDUC registers
+as this makes the interrupt handlers faster. The target option -mg13
+
@end table
@node RS/6000 and PowerPC Options