aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/rl78
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2015-04-16 07:57:56 +0000
committerNick Clifton <nickc@gcc.gnu.org>2015-04-16 07:57:56 +0000
commit72ed1126861875a4fae0d75f994e35f1b79509bd (patch)
tree6058a55ad9abb695d0a8f4a9b314ab329d819ebc /gcc/config/rl78
parent8a474dc5d7d152653e90e960eff1852d1c7ff914 (diff)
downloadgcc-72ed1126861875a4fae0d75f994e35f1b79509bd.zip
gcc-72ed1126861875a4fae0d75f994e35f1b79509bd.tar.gz
gcc-72ed1126861875a4fae0d75f994e35f1b79509bd.tar.bz2
rl78-opts.h (enum rl78_mul_types): Add MUL_G14 and MUL_UNINIT.
* config/rl78/rl78-opts.h (enum rl78_mul_types): Add MUL_G14 and MUL_UNINIT. (enum rl78_cpu_type): New. * config/rl78/rl78-virt.md (attr valloc): Add divhi and divsi. (umulhi3_shift_virt): Remove m constraint from operand 1. (umulqihi3_virt): Likewise. * config/rl78/rl78.c (rl78_option_override): Add code to process -mcpu and -mmul options. (rl78_alloc_physical_registers): Add code to handle divhi and divsi valloc attributes. (set_origin): Likewise. * config/rl78/rl78.h (RL78_MUL_G14): Define. (TARGET_G10, TARGET_G13, TARGET_G14): Define. (TARGET_CPU_CPP_BUILTINS): Define __RL78_MUL_xxx__ and __RL78_Gxx__. (ASM_SPEC): Pass -mcpu on to assembler. * config/rl78/rl78.md (mulqi3): Add a clobber of AX. (mulqi3_rl78): Likewise. (mulhi3_g13): Likewise. (mulhi3): Generate the G13 or G14 versions of the insn directly. (mulsi3): Likewise. (mulhi3_g14): Add clobbers of AX and BC. (mulsi3_g14): Likewise. (mulsi3_g13): Likewise. (udivmodhi4, udivmodhi4_g14, udivmodsi4): New patterns. (udivmodsi4_g14, udivmodsi4_g13): New patterns. * config/rl78/rl78.opt (mmul): Initialise value to RL78_MUL_UNINIT. (mcpu): New option. (m13, m14, mrl78): New option aliases. * config/rl78/t-rl78 (MULTILIB_OPTIONS): Add mg13 and mg14. (MULTILIB_DIRNAMES): Add g13 and g14. * doc/invoke.texi: Document -mcpu and -mmul options. * config/rl78/divmodhi.S: Add G14 and G13 versions of the __divhi3 and __modhi3 functions. * config/rl78/divmodso.S: Add G14 and G13 versions of the __divsi3, __udivsi3, __modsi3 and __umodsi3 functions. From-SVN: r222142
Diffstat (limited to 'gcc/config/rl78')
-rw-r--r--gcc/config/rl78/rl78-opts.h12
-rw-r--r--gcc/config/rl78/rl78-virt.md6
-rw-r--r--gcc/config/rl78/rl78.c104
-rw-r--r--gcc/config/rl78/rl78.h35
-rw-r--r--gcc/config/rl78/rl78.md302
-rw-r--r--gcc/config/rl78/rl78.opt48
-rw-r--r--gcc/config/rl78/t-rl786
7 files changed, 466 insertions, 47 deletions
diff --git a/gcc/config/rl78/rl78-opts.h b/gcc/config/rl78/rl78-opts.h
index 8d98d8d..6fa54cc 100644
--- a/gcc/config/rl78/rl78-opts.h
+++ b/gcc/config/rl78/rl78-opts.h
@@ -24,7 +24,17 @@ enum rl78_mul_types
{
MUL_NONE,
MUL_RL78,
- MUL_G13
+ MUL_G13,
+ MUL_G14,
+ MUL_UNINIT
+};
+
+enum rl78_cpu_types
+{
+ CPU_G10,
+ CPU_G13,
+ CPU_G14,
+ CPU_UNINIT
};
#endif
diff --git a/gcc/config/rl78/rl78-virt.md b/gcc/config/rl78/rl78-virt.md
index e90e156..c70beae 100644
--- a/gcc/config/rl78/rl78-virt.md
+++ b/gcc/config/rl78/rl78-virt.md
@@ -28,7 +28,7 @@
;; instruction - op1 is of the form "a = op(b)", op2 is "a = b op c"
;; etc.
-(define_attr "valloc" "op1,op2,ro1,cmp,umul,macax"
+(define_attr "valloc" "op1,op2,ro1,cmp,umul,macax,divhi,divsi"
(const_string "op2"))
;;---------- Moving ------------------------
@@ -113,7 +113,7 @@
)
(define_insn "*umulhi3_shift_virt"
- [(set (match_operand:HI 0 "register_operand" "=vm")
+ [(set (match_operand:HI 0 "register_operand" "=v")
(mult:HI (match_operand:HI 1 "rl78_nonfar_operand" "%vim")
(match_operand:HI 2 "rl78_24_operand" "Ni")))]
"rl78_virt_insns_ok () && !TARGET_G10"
@@ -122,7 +122,7 @@
)
(define_insn "*umulqihi3_virt"
- [(set (match_operand:HI 0 "register_operand" "=vm")
+ [(set (match_operand:HI 0 "register_operand" "=v")
(mult:HI (zero_extend:HI (match_operand:QI 1 "rl78_nonfar_operand" "%vim"))
(zero_extend:HI (match_operand:QI 2 "general_operand" "vim"))))]
"rl78_virt_insns_ok () && !TARGET_G10"
diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c
index a9d5f5a..6469804 100644
--- a/gcc/config/rl78/rl78.c
+++ b/gcc/config/rl78/rl78.c
@@ -377,6 +377,48 @@ rl78_option_override (void)
&& strcmp (lang_hooks.name, "GNU GIMPLE"))
/* Address spaces are currently only supported by C. */
error ("-mes0 can only be used with C");
+
+ switch (rl78_cpu_type)
+ {
+ case CPU_UNINIT:
+ rl78_cpu_type = CPU_G14;
+ if (rl78_mul_type == MUL_UNINIT)
+ rl78_mul_type = MUL_NONE;
+ break;
+
+ case CPU_G10:
+ switch (rl78_mul_type)
+ {
+ case MUL_UNINIT: rl78_mul_type = MUL_NONE; break;
+ case MUL_NONE: break;
+ case MUL_G13: error ("-mmul=g13 cannot be used with -mcpu=g10"); break;
+ case MUL_G14: error ("-mmul=g14 cannot be used with -mcpu=g10"); break;
+ }
+ break;
+
+ case CPU_G13:
+ switch (rl78_mul_type)
+ {
+ case MUL_UNINIT: rl78_mul_type = MUL_G13; break;
+ case MUL_NONE: break;
+ case MUL_G13: break;
+ /* The S2 core does not have mul/div instructions. */
+ case MUL_G14: error ("-mmul=g14 cannot be used with -mcpu=g13"); break;
+ }
+ break;
+
+ case CPU_G14:
+ switch (rl78_mul_type)
+ {
+ case MUL_UNINIT: rl78_mul_type = MUL_G14; break;
+ case MUL_NONE: break;
+ case MUL_G14: break;
+ /* The G14 core does not have the hardware multiply peripheral used by the
+ G13 core, hence you cannot use G13 multipliy routines on G14 hardware. */
+ case MUL_G13: error ("-mmul=g13 cannot be used with -mcpu=g14"); break;
+ }
+ break;
+ }
}
/* Most registers are 8 bits. Some are 16 bits because, for example,
@@ -3514,6 +3556,18 @@ rl78_alloc_physical_registers (void)
record_content (BC, NULL_RTX);
record_content (DE, NULL_RTX);
}
+ else if (valloc_method == VALLOC_DIVHI)
+ {
+ record_content (AX, NULL_RTX);
+ record_content (BC, NULL_RTX);
+ }
+ else if (valloc_method == VALLOC_DIVSI)
+ {
+ record_content (AX, NULL_RTX);
+ record_content (BC, NULL_RTX);
+ record_content (DE, NULL_RTX);
+ record_content (HL, NULL_RTX);
+ }
if (insn_ok_now (insn))
continue;
@@ -3541,6 +3595,7 @@ rl78_alloc_physical_registers (void)
break;
case VALLOC_UMUL:
rl78_alloc_physical_registers_umul (insn);
+ record_content (AX, NULL_RTX);
break;
case VALLOC_MACAX:
/* Macro that clobbers AX. */
@@ -3549,6 +3604,18 @@ rl78_alloc_physical_registers (void)
record_content (BC, NULL_RTX);
record_content (DE, NULL_RTX);
break;
+ case VALLOC_DIVSI:
+ rl78_alloc_address_registers_div (insn);
+ record_content (AX, NULL_RTX);
+ record_content (BC, NULL_RTX);
+ record_content (DE, NULL_RTX);
+ record_content (HL, NULL_RTX);
+ break;
+ case VALLOC_DIVHI:
+ rl78_alloc_address_registers_div (insn);
+ record_content (AX, NULL_RTX);
+ record_content (BC, NULL_RTX);
+ break;
default:
gcc_unreachable ();
}
@@ -3863,6 +3930,37 @@ set_origin (rtx pat, rtx_insn * insn, int * origins, int * age)
age[i] = 0;
}
}
+ else if (get_attr_valloc (insn) == VALLOC_DIVHI)
+ {
+ if (dump_file)
+ fprintf (dump_file, "Resetting origin of AX/DE for DIVHI pattern.\n");
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (i == A_REG
+ || i == X_REG
+ || i == D_REG
+ || i == E_REG
+ || origins[i] == A_REG
+ || origins[i] == X_REG
+ || origins[i] == D_REG
+ || origins[i] == E_REG)
+ {
+ origins[i] = i;
+ age[i] = 0;
+ }
+ }
+ else if (get_attr_valloc (insn) == VALLOC_DIVSI)
+ {
+ if (dump_file)
+ fprintf (dump_file, "Resetting origin of AX/BC/DE/HL for DIVSI pattern.\n");
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (i <= 7 || origins[i] <= 7)
+ {
+ origins[i] = i;
+ age[i] = 0;
+ }
+ }
if (GET_CODE (src) == ASHIFT
|| GET_CODE (src) == ASHIFTRT
@@ -4087,7 +4185,7 @@ rl78_rtx_costs (rtx x,
switch (code)
{
case MULT:
- if (RL78_MUL_RL78)
+ if (RL78_MUL_G14)
*total = COSTS_N_INSNS (14);
else if (RL78_MUL_G13)
*total = COSTS_N_INSNS (29);
@@ -4407,7 +4505,7 @@ rl78_insert_attributes (tree decl, tree *attributes ATTRIBUTE_UNUSED)
tree type = TREE_TYPE (decl);
tree attr = TYPE_ATTRIBUTES (type);
int q = TYPE_QUALS_NO_ADDR_SPACE (type) | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_FAR);
-
+
TREE_TYPE (decl) = build_type_attribute_qual_variant (type, attr, q);
}
}
@@ -4503,7 +4601,7 @@ rl78_flags_already_set (rtx op, rtx operand)
{
if (LABEL_P (insn))
break;
-
+
if (! INSN_P (insn))
continue;
diff --git a/gcc/config/rl78/rl78.h b/gcc/config/rl78/rl78.h
index caa7f7f..066b0d1 100644
--- a/gcc/config/rl78/rl78.h
+++ b/gcc/config/rl78/rl78.h
@@ -20,20 +20,32 @@
#define RL78_MUL_NONE (rl78_mul_type == MUL_NONE)
-#define RL78_MUL_RL78 (rl78_mul_type == MUL_RL78)
#define RL78_MUL_G13 (rl78_mul_type == MUL_G13)
+#define RL78_MUL_G14 (rl78_mul_type == MUL_G14)
+
+#define TARGET_G10 (rl78_cpu_type == CPU_G10)
+#define TARGET_G13 (rl78_cpu_type == CPU_G13)
+#define TARGET_G14 (rl78_cpu_type == CPU_G14)
#define TARGET_CPU_CPP_BUILTINS() \
do \
{ \
builtin_define ("__RL78__"); \
builtin_assert ("cpu=RL78"); \
- if (RL78_MUL_RL78) \
- builtin_define ("__RL78_MUL_RL78__"); \
- if (RL78_MUL_G13) \
+ \
+ if (RL78_MUL_NONE) \
+ builtin_define ("__RL78_MUL_NONE__"); \
+ else if (RL78_MUL_G13) \
builtin_define ("__RL78_MUL_G13__"); \
+ else if (RL78_MUL_G14) \
+ builtin_define ("__RL78_MUL_G14__"); \
+ \
if (TARGET_G10) \
builtin_define ("__RL78_G10__"); \
+ else if (TARGET_G13) \
+ builtin_define ("__RL78_G13__"); \
+ else if (TARGET_G14) \
+ builtin_define ("__RL78_G14__"); \
} \
while (0)
@@ -46,7 +58,14 @@
#undef ASM_SPEC
#define ASM_SPEC "\
%{mrelax:-relax} \
-%{mg10} \
+%{mg10:--mg10} \
+%{mg13:--mg13} \
+%{mg14:--mg14} \
+%{mrl78:--mg14} \
+%{mcpu=g10:--mg10} \
+%{mcpu=g13:--mg13} \
+%{mcpu=g14:--mg14} \
+%{mcpu=rl78:--mg14} \
"
#undef LINK_SPEC
@@ -160,11 +179,11 @@
*/
#define REGISTER_NAMES \
{ \
- "x", "a", "c", "b", "e", "d", "l", "h", \
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
+ "x", "a", "c", "b", "e", "d", "l", "h", \
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \
- "sp", "ap", "psw", "es", "cs" \
+ "sp", "ap", "psw", "es", "cs" \
}
#define ADDITIONAL_REGISTER_NAMES \
diff --git a/gcc/config/rl78/rl78.md b/gcc/config/rl78/rl78.md
index 258c139..2ea788e 100644
--- a/gcc/config/rl78/rl78.md
+++ b/gcc/config/rl78/rl78.md
@@ -288,10 +288,13 @@
)
(define_expand "mulqi3"
- [(set (match_operand:QI 0 "register_operand")
- (mult:QI (match_operand:QI 1 "general_operand")
- (match_operand:QI 2 "nonmemory_operand")))
- ]
+ [(parallel
+ [(set (match_operand:QI 0 "register_operand")
+ (mult:QI (match_operand:QI 1 "general_operand")
+ (match_operand:QI 2 "nonmemory_operand")))
+ (clobber (reg:HI AX_REG))
+ ])
+ ]
"" ; mulu supported by all targets
""
)
@@ -302,7 +305,13 @@
(match_operand:HI 2 "nonmemory_operand")))
]
"! RL78_MUL_NONE"
- ""
+ {
+ if (RL78_MUL_G14)
+ emit_insn (gen_mulhi3_g14 (operands[0], operands[1], operands[2]));
+ else /* RL78_MUL_G13 */
+ emit_insn (gen_mulhi3_g13 (operands[0], operands[1], operands[2]));
+ DONE;
+ }
)
(define_expand "mulsi3"
@@ -311,14 +320,21 @@
(match_operand:SI 2 "nonmemory_operand")))
]
"! RL78_MUL_NONE"
- ""
+ {
+ if (RL78_MUL_G14)
+ emit_insn (gen_mulsi3_g14 (operands[0], operands[1], operands[2]));
+ else /* RL78_MUL_G13 */
+ emit_insn (gen_mulsi3_g13 (operands[0], operands[1], operands[2]));
+ DONE;
+ }
)
(define_insn "*mulqi3_rl78"
[(set (match_operand:QI 0 "register_operand" "=&v")
(mult:QI (match_operand:QI 1 "general_operand" "viU")
(match_operand:QI 2 "general_operand" "vi")))
- ]
+ (clobber (reg:HI AX_REG))
+ ]
"" ; mulu supported by all targets
"; mulqi macro %0 = %1 * %2
mov a, %h1
@@ -328,31 +344,34 @@
mov a, x
mov %h0, a
; end of mulqi macro"
-;; [(set_attr "valloc" "macax")]
+ [(set_attr "valloc" "macax")]
)
-(define_insn "*mulhi3_rl78"
+(define_insn "mulhi3_g14"
[(set (match_operand:HI 0 "register_operand" "=&v")
(mult:HI (match_operand:HI 1 "general_operand" "viU")
(match_operand:HI 2 "general_operand" "vi")))
- ]
- "RL78_MUL_RL78"
- "; mulhi macro %0 = %1 * %2
+ (clobber (reg:HI AX_REG))
+ (clobber (reg:HI BC_REG))
+ ]
+ "RL78_MUL_G14"
+ "; G14 mulhi macro %0 = %1 * %2
movw ax, %h1
movw bc, %h2
mulhu ; bcax = bc * ax
movw %h0, ax
; end of mulhi macro"
-;; [(set_attr "valloc" "macax")]
+ [(set_attr "valloc" "macax")]
)
-(define_insn "*mulhi3_g13"
+(define_insn "mulhi3_g13"
[(set (match_operand:HI 0 "register_operand" "=&v")
(mult:HI (match_operand:HI 1 "general_operand" "viU")
(match_operand:HI 2 "general_operand" "vi")))
- ]
+ (clobber (reg:HI AX_REG))
+ ]
"RL78_MUL_G13"
- "; mulhi macro %0 = %1 * %2
+ "; G13 mulhi macro %0 = %1 * %2
mov a, #0x00
mov !0xf00e8, a ; MDUC
movw ax, %h1
@@ -363,19 +382,21 @@
movw ax, 0xffff6 ; MDBL
movw %h0, ax
; end of mulhi macro"
-;; [(set_attr "valloc" "umul")]
+ [(set_attr "valloc" "macax")]
)
;; 0xFFFF0 is MACR(L). 0xFFFF2 is MACR(H) but we don't care about it
;; because we're only using the lower 16 bits (which is the upper 16
;; bits of the result).
-(define_insn "mulsi3_rl78"
+(define_insn "mulsi3_g14"
[(set (match_operand:SI 0 "register_operand" "=&v")
(mult:SI (match_operand:SI 1 "general_operand" "viU")
(match_operand:SI 2 "general_operand" "vi")))
- ]
- "RL78_MUL_RL78"
- "; mulsi macro %0 = %1 * %2
+ (clobber (reg:HI AX_REG))
+ (clobber (reg:HI BC_REG))
+ ]
+ "RL78_MUL_G14"
+ "; G14 mulsi macro %0 = %1 * %2
movw ax, %h1
movw bc, %h2
MULHU ; bcax = bc * ax
@@ -403,9 +424,11 @@
[(set (match_operand:SI 0 "register_operand" "=&v")
(mult:SI (match_operand:SI 1 "general_operand" "viU")
(match_operand:SI 2 "general_operand" "viU")))
- ]
+ (clobber (reg:HI AX_REG))
+ (clobber (reg:HI BC_REG))
+ ]
"RL78_MUL_G13"
- "; mulsi macro %0 = %1 * %2
+ "; G13 mulsi macro %0 = %1 * %2
mov a, #0x00
mov !0xf00e8, a ; MDUC
movw ax, %h1
@@ -441,3 +464,236 @@
; end of mulsi macro"
[(set_attr "valloc" "macax")]
)
+
+(define_expand "udivmodhi4"
+ [(parallel
+ [(set (match_operand:HI 0 "register_operand")
+ (udiv:HI (match_operand:HI 1 "register_operand")
+ (match_operand:HI 2 "register_operand")))
+ (set (match_operand:HI 3 "register_operand")
+ (umod:HI (match_dup 1) (match_dup 2)))
+ (clobber (reg:HI AX_REG))
+ (clobber (reg:HI DE_REG))
+ ])
+ ]
+ "RL78_MUL_G14"
+ ""
+)
+
+(define_insn "*udivmodhi4_g14"
+ [(set (match_operand:HI 0 "register_operand" "=v")
+ (udiv:HI (match_operand:HI 1 "register_operand" "v")
+ (match_operand:HI 2 "register_operand" "v")))
+ (set (match_operand:HI 3 "register_operand" "=v")
+ (umod:HI (match_dup 1) (match_dup 2)))
+ (clobber (reg:HI AX_REG))
+ (clobber (reg:HI DE_REG))
+ ]
+ "RL78_MUL_G14"
+ {
+ if (find_reg_note (insn, REG_UNUSED, operands[3]))
+ return "; G14 udivhi macro %0 = %1 / %2 \n\
+ movw ax, %h1 \n\
+ movw de, %h2 \n\
+ push psw ; Save the current interrupt status \n\
+ di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\
+ divhu ; ax = ax / de \n\
+ pop psw ; Restore saved interrupt status \n\
+ movw %h0, ax \n\
+ ; end of udivhi macro";
+ else if (find_reg_note (insn, REG_UNUSED, operands[0]))
+ return "; G14 umodhi macro %3 = %1 %% %2 \n\
+ movw ax, %h1 \n\
+ movw de, %h2 \n\
+ push psw ; Save the current interrupt status \n\
+ di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\
+ divhu ; de = ax %% de \n\
+ pop psw ; Restore saved interrupt status \n\
+ movw ax, de \n\
+ movw %h3, ax \n\
+ ; end of umodhi macro";
+ else
+ return "; G14 udivmodhi macro %0 = %1 / %2 and %3 = %1 %% %2 \n\
+ movw ax, %h1 \n\
+ movw de, %h2 \n\
+ push psw ; Save the current interrupt status \n\
+ di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\
+ divhu ; ax = ax / de, de = ax %% de \n\
+ pop psw ; Restore saved interrupt status \n\
+ movw %h0, ax \n\
+ movw ax, de \n\
+ movw %h3, ax \n\
+ ; end of udivmodhi macro";
+ }
+ [(set_attr "valloc" "divhi")]
+)
+
+(define_expand "udivmodsi4"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand")
+ (udiv:SI (match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "register_operand")))
+ (set (match_operand:SI 3 "register_operand")
+ (umod:SI (match_dup 1) (match_dup 2)))
+ ])
+ ]
+ "! RL78_MUL_NONE && ! optimize_size"
+ {
+ if (RL78_MUL_G14)
+ emit_insn (gen_udivmodsi4_g14 (operands[0], operands[1], operands[2], operands[3]));
+ else /* RL78_MUL_G13 */
+ emit_insn (gen_udivmodsi4_g13 (operands[0], operands[1], operands[2], operands[3]));
+ DONE;
+ }
+)
+
+(define_insn "udivmodsi4_g14"
+ [(set (match_operand:SI 0 "register_operand" "=v")
+ (udiv:SI (match_operand:SI 1 "register_operand" "v")
+ (match_operand:SI 2 "register_operand" "v")))
+ (set (match_operand:SI 3 "register_operand" "=v")
+ (umod:SI (match_dup 1) (match_dup 2)))
+ (clobber (reg:HI AX_REG))
+ (clobber (reg:HI BC_REG))
+ (clobber (reg:HI DE_REG))
+ (clobber (reg:HI HL_REG))
+ ]
+ "RL78_MUL_G14"
+ {
+ if (find_reg_note (insn, REG_UNUSED, operands[3]))
+ return "; G14 udivsi macro %0 = %1 / %2 \n\
+ movw ax, %h1 \n\
+ movw bc, %H1 \n\
+ movw de, %h2 \n\
+ movw hl, %H2 \n\
+ push psw ; Save the current interrupt status \n\
+ di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\
+ divwu ; bcax = bcax / hlde \n\
+ pop psw ; Restore saved interrupt status \n\
+ movw %h0, ax \n\
+ movw ax, bc \n\
+ movw %H0, ax \n\
+ ; end of udivsi macro";
+ else if (find_reg_note (insn, REG_UNUSED, operands[0]))
+ return "; G14 umodsi macro %3 = %1 %% %2 \n\
+ movw ax, %h1 \n\
+ movw bc, %H1 \n\
+ movw de, %h2 \n\
+ movw hl, %H2 \n\
+ push psw ; Save the current interrupt status \n\
+ di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\
+ divwu ; hlde = bcax %% hlde \n\
+ pop psw ; Restore saved interrupt status \n\
+ movw ax, de \n\
+ movw %h3, ax \n\
+ movw ax, hl \n\
+ movw %H3, ax \n\
+ ; end of umodsi macro";
+ else
+ return "; G14 udivmodsi macro %0 = %1 / %2 and %3 = %1 %% %2 \n\
+ movw ax, %h1 \n\
+ movw bc, %H1 \n\
+ movw de, %h2 \n\
+ movw hl, %H2 \n\
+ push psw ; Save the current interrupt status \n\
+ di ; Disable interrupts. See Renesas Technical update TN-RL*-A025B/E \n\
+ divwu ; bcax = bcax / hlde, hlde = bcax %% hlde \n\
+ pop psw ; Restore saved interrupt status \n\
+ movw %h0, ax \n\
+ movw ax, bc \n\
+ movw %H0, ax \n\
+ movw ax, de \n\
+ movw %h3, ax \n\
+ movw ax, hl \n\
+ movw %H3, ax \n\
+ ; end of udivmodsi macro";
+ }
+ [(set_attr "valloc" "divsi")]
+)
+
+;; Warning: these values match the silicon not the documentation.
+;; 0xFFFF0 is MDAL. 0xFFFF2 is MDAH.
+;; 0xFFFF6 is MDBL. 0xFFFF4 is MDBH.
+;; 0xF00E0 is MDCL. 0xF00E2 is MDCH.
+;; 0xF00E8 is MDUC.
+
+(define_insn "udivmodsi4_g13"
+ [(set (match_operand:SI 0 "register_operand" "=v")
+ (udiv:SI (match_operand:SI 1 "register_operand" "v")
+ (match_operand:SI 2 "register_operand" "v")))
+ (set (match_operand:SI 3 "register_operand" "=v")
+ (umod:SI (match_dup 1) (match_dup 2)))
+ (clobber (reg:HI AX_REG))
+ ]
+ "RL78_MUL_G13"
+ {
+ if (find_reg_note (insn, REG_UNUSED, operands[3]))
+ return "; G13 udivsi macro %0 = %1 / %2 \n\
+ mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1 \n\
+ mov !0xf00e8, a ; This preps the peripheral for division without interrupt generation \n\
+ movw ax, %H1 \n\
+ movw 0xffff2, ax ; MDAH \n\
+ movw ax, %h1 \n\
+ movw 0xffff0, ax ; MDAL \n\
+ movw ax, %H2 \n\
+ movw 0xffff4, ax ; MDBH \n\
+ movw ax, %h2 \n\
+ movw 0xffff6, ax ; MDBL \n\
+ mov a, #0xC1 ; Set the DIVST bit in MDUC \n\
+ mov !0xf00e8, a ; This starts the division op \n\
+1: mov a, !0xf00e8 ; Wait 16 clocks or until DIVST is clear \n\
+ bt a.0, $1b \n\
+ movw ax, 0xffff0 ; Read the quotient \n\
+ movw %h0, ax \n\
+ movw ax, 0xffff2 \n\
+ movw %H0, ax \n\
+ ; end of udivsi macro";
+ else if (find_reg_note (insn, REG_UNUSED, operands[0]))
+ return "; G13 umodsi macro %3 = %1 %% %2 \n\
+ mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1 \n\
+ mov !0xf00e8, a ; This preps the peripheral for division without interrupt generation \n\
+ movw ax, %H1 \n\
+ movw 0xffff2, ax ; MDAH \n\
+ movw ax, %h1 \n\
+ movw 0xffff0, ax ; MDAL \n\
+ movw ax, %H2 \n\
+ movw 0xffff4, ax ; MDBH \n\
+ movw ax, %h2 \n\
+ movw 0xffff6, ax ; MDBL \n\
+ mov a, #0xC1 ; Set the DIVST bit in MDUC \n\
+ mov !0xf00e8, a ; This starts the division op \n\
+1: mov a, !0xf00e8 ; Wait 16 clocks or until DIVST is clear \n\
+ bt a.0, $1b \n\
+ movw ax, !0xf00e0 ; Read the remainder \n\
+ movw %h3, ax \n\
+ movw ax, !0xf00e2 \n\
+ movw %H3, ax \n\
+ ; end of umodsi macro";
+ else
+ return "; G13 udivmodsi macro %0 = %1 / %2 and %3 = %1 %% %2 \n\
+ mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1 \n\
+ mov !0xf00e8, a ; This preps the peripheral for division without interrupt generation \n\
+ movw ax, %H1 \n\
+ movw 0xffff2, ax ; MDAH \n\
+ movw ax, %h1 \n\
+ movw 0xffff0, ax ; MDAL \n\
+ movw ax, %H2 \n\
+ movw 0xffff4, ax ; MDBH \n\
+ movw ax, %h2 \n\
+ movw 0xffff6, ax ; MDBL \n\
+ mov a, #0xC1 ; Set the DIVST bit in MDUC \n\
+ mov !0xf00e8, a ; This starts the division op \n\
+1: mov a, !0xf00e8 ; Wait 16 clocks or until DIVST is clear \n\
+ bt a.0, $1b \n\
+ movw ax, 0xffff0 ; Read the quotient \n\
+ movw %h0, ax \n\
+ movw ax, 0xffff2 \n\
+ movw %H0, ax \n\
+ movw ax, !0xf00e0 ; Read the remainder \n\
+ movw %h3, ax \n\
+ movw ax, !0xf00e2 \n\
+ movw %H3, ax \n\
+ ; end of udivmodsi macro";
+ }
+ [(set_attr "valloc" "macax")]
+)
diff --git a/gcc/config/rl78/rl78.opt b/gcc/config/rl78/rl78.opt
index 1e4c14c..80b894a 100644
--- a/gcc/config/rl78/rl78.opt
+++ b/gcc/config/rl78/rl78.opt
@@ -27,20 +27,23 @@ Target Report
Use the simulator runtime.
mmul=
-Target RejectNegative Joined Var(rl78_mul_type) Report Tolower Enum(rl78_mul_types) Init(MUL_NONE)
-Select hardware or software multiplication support.
+Target RejectNegative Joined Var(rl78_mul_type) Report Tolower Enum(rl78_mul_types) Init(MUL_UNINIT)
+Selects the type of hardware multiplication and division to use (none/g13/g14).
Enum
Name(rl78_mul_types) Type(enum rl78_mul_types)
EnumValue
-Enum(rl78_mul_types) String(none) Value(MUL_NONE)
+Enum(rl78_mul_types) String(g10) Value(MUL_NONE)
EnumValue
-Enum(rl78_mul_types) String(rl78) Value(MUL_RL78)
+Enum(rl78_mul_types) String(g13) Value(MUL_G13)
EnumValue
-Enum(rl78_mul_types) String(g13) Value(MUL_G13)
+Enum(rl78_mul_types) String(g14) Value(MUL_G14)
+
+EnumValue
+Enum(rl78_mul_types) String(rl78) Value(MUL_G14)
mallregs
Target Mask(ALLREGS) Report Optimization
@@ -50,9 +53,40 @@ mrelax
Target Report Optimization
Enable assembler and linker relaxation. Enabled by default at -Os.
+mcpu=
+Target RejectNegative Joined Var(rl78_cpu_type) Report ToLower Enum(rl78_cpu_types) Init(CPU_UNINIT)
+Selects the type of RL78 core being targeted (g10/g13/g14). The default is the G14. If set, also selects the hardware multiply support to be used.
+
+Enum
+Name(rl78_cpu_types) Type(enum rl78_cpu_types)
+
+EnumValue
+Enum(rl78_cpu_types) String(g10) Value(CPU_G10)
+
+EnumValue
+Enum(rl78_cpu_types) String(g13) Value(CPU_G13)
+
+EnumValue
+Enum(rl78_cpu_types) String(g14) Value(CPU_G14)
+
+EnumValue
+Enum(rl78_cpu_types) String(rl78) Value(CPU_G14)
+
mg10
-Target Mask(G10) Report
-Target the RL78/G10 series
+Target RejectNegative Report Alias(mcpu=, g10)
+Alias for -mcpu=g10
+
+mg13
+Target RejectNegative Report Alias(mcpu=, g13)
+Alias for -mcpu=g13
+
+mg14
+Target RejectNegative Report Alias(mcpu=, g14)
+Alias for -mcpu=g14
+
+mrl78
+Target RejectNegative Report Alias(mcpu=, g14)
+Alias for -mcpu=g14
mes0
Target Mask(ES0)
diff --git a/gcc/config/rl78/t-rl78 b/gcc/config/rl78/t-rl78
index 2628855..bd8fab4 100644
--- a/gcc/config/rl78/t-rl78
+++ b/gcc/config/rl78/t-rl78
@@ -23,5 +23,7 @@ rl78-c.o: $(srcdir)/config/rl78/rl78-c.c $(RTL_H) $(TREE_H) $(CONFIG_H) $(TM_H)
# Enable multilibs:
-MULTILIB_OPTIONS = mg10
-MULTILIB_DIRNAMES = g10
+MULTILIB_OPTIONS = mg10/mg13/mg14
+MULTILIB_DIRNAMES = g10 g13 g14
+
+MULTILIB_MATCHES = mg10=mcpu?g10 mg13=mcpu?g13 mg14=mcpu?g14 mg14=mcpu?rl78