Commit 72ed1126 by Nick Clifton Committed by Nick Clifton

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
parent 8a474dc5
2015-04-16 Nick Clifton <nickc@redhat.com>
* 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.
2015-04-16 Richard Biener <rguenther@suse.de>
* tree-ssa-ccp.c (likely_value): See if we have operands that
......@@ -75,6 +111,7 @@
* config/rx/t-rx (MULTILIB_OPTIONS): Add mno-allow-string-insns.
(MULTILIB_DIRNAMES): Add no-strings.
* doc/invoke.texi: Document -mno-allow-string-insns.
2015-04-15 Alan Modra <amodra@gmail.com>
PR target/65408
......
......@@ -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
......@@ -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"
......
......@@ -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;
......
......@@ -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 \
......
......@@ -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)
......
......@@ -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
......@@ -265,7 +265,7 @@ Objective-C and Objective-C++ Dialects}.
-Wmain -Wmaybe-uninitialized -Wmemset-transposed-args -Wmissing-braces @gol
-Wmissing-field-initializers -Wmissing-include-dirs @gol
-Wno-multichar -Wnonnull -Wnormalized=@r{[}none@r{|}id@r{|}nfc@r{|}nfkc@r{]} @gol
-Wodr -Wno-overflow -Wopenmp-simd @gol
-Wodr -Wno-overflow -Wopenmp-simd @gol
-Woverlength-strings -Wpacked -Wpacked-bitfield-compat -Wpadded @gol
-Wparentheses -Wpedantic-ms-format -Wno-pedantic-ms-format @gol
-Wpointer-arith -Wno-pointer-to-int-cast @gol
......@@ -277,7 +277,7 @@ Objective-C and Objective-C++ Dialects}.
-Wstack-protector -Wstack-usage=@var{len} -Wstrict-aliasing @gol
-Wstrict-aliasing=n @gol -Wstrict-overflow -Wstrict-overflow=@var{n} @gol
-Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{]} @gol
-Wsuggest-final-types @gol -Wsuggest-final-methods @gol -Wsuggest-override @gol
-Wsuggest-final-types @gol -Wsuggest-final-methods -Wsuggest-override @gol
-Wmissing-format-attribute @gol
-Wswitch -Wswitch-default -Wswitch-enum -Wswitch-bool -Wsync-nand @gol
-Wsystem-headers -Wtrampolines -Wtrigraphs -Wtype-limits -Wundef @gol
......@@ -405,7 +405,7 @@ Objective-C and Objective-C++ Dialects}.
-fisolate-erroneous-paths-dereference -fisolate-erroneous-paths-attribute @gol
-fivopts -fkeep-inline-functions -fkeep-static-consts @gol
-flive-range-shrinkage @gol
-floop-block -floop-interchange -floop-strip-mine @gol
-floop-block -floop-interchange -floop-strip-mine @gol
-floop-unroll-and-jam -floop-nest-optimize @gol
-floop-parallelize-all -flra-remat -flto -flto-compression-level @gol
-flto-partition=@var{alg} -flto-report -flto-report-wpa -fmerge-all-constants @gol
......@@ -870,7 +870,8 @@ Objective-C and Objective-C++ Dialects}.
See RS/6000 and PowerPC Options.
@emph{RL78 Options}
@gccoptlist{-msim -mmul=none -mmul=g13 -mmul=rl78 @gol
@gccoptlist{-msim -mmul=none -mmul=g13 -mmul=g14 -mallregs @gol
-mcpu=g10 -mcpu=g13 -mcpu=g14 -mg10 -mg13 -mg14 @gol
-m64bit-doubles -m32bit-doubles}
@emph{RS/6000 and PowerPC Options}
......@@ -1786,7 +1787,7 @@ Using this option is roughly equivalent to adding the
The option @option{-fno-gnu89-inline} explicitly tells GCC to use the
C99 semantics for @code{inline} when in C99 or gnu99 mode (i.e., it
specifies the default behavior).
specifies the default behavior).
This option is not supported in @option{-std=c90} or
@option{-std=gnu90} mode.
......@@ -2090,7 +2091,7 @@ Version 0 refers to the version conforming most closely to
the C++ ABI specification. Therefore, the ABI obtained using version 0
will change in different versions of G++ as ABI bugs are fixed.
Version 1 is the version of the C++ ABI that first appeared in G++ 3.2.
Version 1 is the version of the C++ ABI that first appeared in G++ 3.2.
Version 2 is the version of the C++ ABI that first appeared in G++
3.4, and was the default through G++ 4.9.
......@@ -4354,7 +4355,6 @@ pointers. This warning level may give a larger number of
false positives and is deactivated by default.
@end table
@item -Wbool-compare
@opindex Wno-bool-compare
@opindex Wbool-compare
......@@ -5890,7 +5890,7 @@ Bounds Checker builtins}, for more information.
@opindex fchkp-check-incomplete-type
@opindex fno-chkp-check-incomplete-type
Generate pointer bounds checks for variables with incomplete type.
Enabled by default.
Enabled by default.
@item -fchkp-narrow-bounds
@opindex fchkp-narrow-bounds
......@@ -18730,14 +18730,72 @@ Links in additional target libraries to support operation within a
simulator.
@item -mmul=none
@itemx -mmul=g10
@itemx -mmul=g13
@itemx -mmul=g14
@itemx -mmul=rl78
@opindex mmul
Specifies the type of hardware multiplication support to be used. The
default is @samp{none}, which uses software multiplication functions.
The @samp{g13} option is for the hardware multiply/divide peripheral
only on the RL78/G13 targets. The @samp{rl78} option is for the
standard hardware multiplication defined in the RL78 software manual.
Specifies the type of hardware multiplication and division support to
be used. The simplest is @code{none}, which uses software for both
multiplication and division. This is the default. The @code{g13}
value is for the hardware multiply/divide peripheral found on the
RL78/G13 (S2 core) targets. The @code{g14} value selects the use of
the multiplication and division instructions supported by the RL78/G14
(S3 core) parts. The value @code{rl78} is an alias for @code{g14} and
the value @code{mg10} is an alias for @code{none}.
In addition a C preprocessor macro is defined, based upon the setting
of this option. Possible values are: @code{__RL78_MUL_NONE__},
@code{__RL78_MUL_G13__} or @code{__RL78_MUL_G14__}.
@item -mcpu=g10
@itemx -mcpu=g13
@itemx -mcpu=g14
@itemx -mcpu=rl78
@opindex mcpu
Specifies the RL78 core to target. The default is the G14 core, also
known as an S3 core or just RL78. The G13 or S2 core does not have
multiply or divide instructions, instead it uses a hardware peripheral
for these operations. The G10 or S1 core does not have register
banks, so it uses a different calling convention.
If this option is set it also selects the type of hardware multiply
support to use, unless this is overridden by an explicit
@option{-mmul=none} option on the command line. Thus specifying
@option{-mcpu=g13} enables the use of the G13 hardware multiply
peripheral and specifying @option{-mcpu=g10} disables the use of
hardware multipications altogether.
Note, although the RL78/G14 core is the default target, specifying
@option{-mcpu=g14} or @option{-mcpu=rl78} on the command line does
change the behaviour of the toolchain since it also enables G14
hardware multiply support. If these options are not specified on the
command line then software multiplication routines will be used even
though the code targets the RL78 core. This is for backwards
compatibility with older toolchains which did not have hardware
multiply and divide support.
In addition a C preprocessor macro is defined, based upon the setting
of this option. Possible values are: @code{__RL78_G10__},
@code{__RL78_G13__} or @code{__RL78_G14__}.
@item -mg10
@itemx -mg13
@itemx -mg14
@itemx -mrl78
@opindex mg10
@opindex mg13
@opindex mg14
@opindex mrl78
These are aliases for the corresponding @option{-mcpu=} option. They
are provided for backwards compatibility.
@item -mallregs
@opindex mallregs
Allow the compiler to use all of the available registers. By default
registers @code{r24..r31} are reserved for use in interrupt handlers.
With this option enabled these registers can be used in ordinary
functions as well.
@item -m64bit-doubles
@itemx -m32bit-doubles
......
......@@ -12,6 +12,18 @@
#elif defined (__sh__)
/* On SH division by zero does not trap. */
# define DO_TEST 0
#elif defined (__v850__)
/* On V850 division by zero does not trap. */
# define DO_TEST 0
#elif defined (__MSP430__)
/* On MSP430 division by zero does not trap. */
# define DO_TEST 0
#elif defined (__RL78__)
/* On RL78 division by zero does not trap. */
# define DO_TEST 0
#elif defined (__RX__)
/* On RX division by zero does not trap. */
# define DO_TEST 0
#elif defined (__aarch64__)
/* On AArch64 integer division by zero does not trap. */
# define DO_TEST 0
......
2015-04-16 Nick Clifton <nickc@redhat.com>
* 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.
2015-04-15 Chen Gang <gang.chen.5i5j@gmail.com>
* gthr-single.h (__GTHREAD_MUTEX_INIT_FUNCTION): Use empty
......
......@@ -25,6 +25,360 @@
#include "vregs.h"
#if defined __RL78_MUL_G14__
START_FUNC ___divhi3
;; r8 = 4[sp] / 6[sp]
;; Test for a negative denumerator.
movw ax, [sp+6]
mov1 cy, a.7
movw de, ax
bc $__div_neg_den
;; Test for a negative numerator.
movw ax, [sp+4]
mov1 cy, a.7
bc $__div_neg_num
;; Neither are negative - we can use the unsigned divide instruction.
__div_no_convert:
push psw
di
divhu
pop psw
movw r8, ax
ret
__div_neg_den:
;; Negate the denumerator (which is in DE)
clrw ax
subw ax, de
movw de, ax
;; Test for a negative numerator.
movw ax, [sp+4]
mov1 cy, a.7
;; If it is not negative then we perform the division and then negate the result.
bnc $__div_then_convert
;; Otherwise we negate the numerator and then go with an unsigned division.
movw bc, ax
clrw ax
subw ax, bc
br $__div_no_convert
__div_neg_num:
;; Negate the numerator (which is in AX)
;; We know that the denumerator is positive.
movw bc, ax
clrw ax
subw ax, bc
__div_then_convert:
push psw
di
divhu
pop psw
;; Negate result and transfer into r8
movw bc, ax
clrw ax
subw ax, bc
movw r8, ax
ret
END_FUNC ___divhi3
;----------------------------------------------------------------------
START_FUNC ___modhi3
;; r8 = 4[sp] % 6[sp]
;; Test for a negative denumerator.
movw ax, [sp+6]
mov1 cy, a.7
movw de, ax
bc $__mod_neg_den
;; Test for a negative numerator.
movw ax, [sp+4]
mov1 cy, a.7
bc $__mod_neg_num
;; Neither are negative - we can use the unsigned divide instruction.
__mod_no_convert:
push psw
di
divhu
pop psw
movw ax, de
movw r8, ax
ret
__mod_neg_den:
;; Negate the denumerator (which is in DE)
clrw ax
subw ax, de
movw de, ax
;; Test for a negative numerator.
movw ax, [sp+4]
mov1 cy, a.7
;; If it is not negative then we perform the modulo operation without conversion.
bnc $__mod_no_convert
;; Otherwise we negate the numerator and then go with an unsigned modulo operation.
movw bc, ax
clrw ax
subw ax, bc
br $__mod_then_convert
__mod_neg_num:
;; Negate the numerator (which is in AX)
;; We know that the denumerator is positive.
movw bc, ax
clrw ax
subw ax, bc
__mod_then_convert:
push psw
di
divhu
pop psw
;; Negate result and transfer into r8
clrw ax
subw ax, de
movw r8, ax
ret
END_FUNC ___modhi3
;----------------------------------------------------------------------
#elif defined __RL78_MUL_G13__
;; The G13 S2 core does not have a 16 bit divide peripheral.
;; So instead we perform a 32-bit divide and twiddle the inputs
;; as necessary.
;; Hardware registers. Note - these values match the silicon, not the documentation.
MDAL = 0xffff0
MDAH = 0xffff2
MDBL = 0xffff6
MDBH = 0xffff4
MDCL = 0xf00e0
MDCH = 0xf00e2
MDUC = 0xf00e8
.macro _Negate src, dest
movw ax, !\src
movw bc, ax
clrw ax
subw ax, bc
movw \dest, ax
.endm
;----------------------------------------------------------------------
START_FUNC ___divhi3
;; r8 = 4[sp] / 6[sp] (signed division)
mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1
mov !MDUC, a ; This preps the peripheral for division without interrupt generation
clrw ax ; Clear the top 16-bits of the divisor and dividend
movw MDBH, ax
movw MDAH, ax
;; Load and test for a negative denumerator.
movw ax, [sp+6]
movw MDBL, ax
mov1 cy, a.7
bc $__div_neg_den
;; Load and test for a negative numerator.
movw ax, [sp+4]
mov1 cy, a.7
movw MDAL, ax
bc $__div_neg_num
;; Neither are negative - we can use the unsigned divide hardware.
__div_no_convert:
mov a, #0xC1 ; Set the DIVST bit in MDUC
mov !MDUC, a ; This starts the division op
1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
bt a.0, $1b
movw ax, MDAL ; Read the result
movw r8, ax
ret
__div_neg_den:
;; Negate the denumerator (which is in MDBL)
_Negate MDBL MDBL
;; Load and test for a negative numerator.
movw ax, [sp+4]
mov1 cy, a.7
movw MDAL, ax
;; If it is not negative then we perform the division and then negate the result.
bnc $__div_then_convert
;; Otherwise we negate the numerator and then go with a straightforward unsigned division.
_Negate MDAL MDAL
br $!__div_no_convert
__div_neg_num:
;; Negate the numerator (which is in MDAL)
;; We know that the denumerator is positive.
_Negate MDAL MDAL
__div_then_convert:
mov a, #0xC1 ; Set the DIVST bit in MDUC
mov !MDUC, a ; This starts the division op
1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
bt a.0, $1b
;; Negate result and transfer into r8
_Negate MDAL r8
ret
END_FUNC ___divhi3
;----------------------------------------------------------------------
START_FUNC ___modhi3
;; r8 = 4[sp] % 6[sp] (signed modulus)
mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1
mov !MDUC, a ; This preps the peripheral for division without interrupt generation
clrw ax ; Clear the top 16-bits of the divisor and dividend
movw MDBH, ax
movw MDAH, ax
;; Load and test for a negative denumerator.
movw ax, [sp+6]
movw MDBL, ax
mov1 cy, a.7
bc $__mod_neg_den
;; Load and test for a negative numerator.
movw ax, [sp+4]
mov1 cy, a.7
movw MDAL, ax
bc $__mod_neg_num
;; Neither are negative - we can use the unsigned divide hardware
__mod_no_convert:
mov a, #0xC1 ; Set the DIVST bit in MDUC
mov !MDUC, a ; This starts the division op
1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
bt a.0, $1b
movw ax, !MDCL ; Read the remainder
movw r8, ax
ret
__mod_neg_den:
;; Negate the denumerator (which is in MDBL)
_Negate MDBL MDBL
;; Load and test for a negative numerator.
movw ax, [sp+4]
mov1 cy, a.7
movw MDAL, ax
;; If it is not negative then we perform the modulo operation without conversion.
bnc $__mod_no_convert
;; Otherwise we negate the numerator and then go with a modulo followed by negation.
_Negate MDAL MDAL
br $!__mod_then_convert
__mod_neg_num:
;; Negate the numerator (which is in MDAL)
;; We know that the denumerator is positive.
_Negate MDAL MDAL
__mod_then_convert:
mov a, #0xC1 ; Set the DIVST bit in MDUC
mov !MDUC, a ; This starts the division op
1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
bt a.0, $1b
_Negate MDCL r8
ret
END_FUNC ___modhi3
;----------------------------------------------------------------------
START_FUNC ___udivhi3
;; r8 = 4[sp] / 6[sp] (unsigned division)
mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1
mov !MDUC, a ; This preps the peripheral for division without interrupt generation
movw ax, [sp+4] ; Load the divisor
movw MDAL, ax
movw ax, [sp+6] ; Load the dividend
movw MDBL, ax
clrw ax
movw MDAH, ax
movw MDBH, ax
mov a, #0xC1 ; Set the DIVST bit in MDUC
mov !MDUC, a ; This starts the division op
1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
bt a.0, $1b
movw ax, !MDAL ; Read the remainder
movw r8, ax
ret
END_FUNC ___udivhi3
;----------------------------------------------------------------------
START_FUNC ___umodhi3
;; r8 = 4[sp] % 6[sp] (unsigned modulus)
mov a, #0xC0 ; Set DIVMODE=1 and MACMODE=1
mov !MDUC, a ; This preps the peripheral for division without interrupt generation
movw ax, [sp+4] ; Load the divisor
movw MDAL, ax
movw ax, [sp+6] ; Load the dividend
movw MDBL, ax
clrw ax
movw MDAH, ax
movw MDBH, ax
mov a, #0xC1 ; Set the DIVST bit in MDUC
mov !MDUC, a ; This starts the division op
1: mov a, !MDUC ; Wait 16 clocks or until DIVST is clear
bt a.0, $1b
movw ax, !MDCL ; Read the remainder
movw r8, ax
ret
END_FUNC ___umodhi3
;----------------------------------------------------------------------
#elif defined __RL78_MUL_NONE__
.macro MAKE_GENERIC which,need_result
.if \need_result
......@@ -328,3 +682,11 @@ mod_no_neg:
mod_skip_restore_den:
ret
END_FUNC ___modhi3
;----------------------------------------------------------------------
#else
#error "Unknown RL78 hardware multiply/divide support"
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment