Commit 82cd9a96 by Claudiu Zissulescu

[ARC] Save mlo/mhi registers when ISR.

ARC600 when configured with mul64 instructions uses mlo and mhi
registers to store the 64 result of the multiplication. In the ARC600
ISA documentation we have the next register configuration when ARC600
is configured only with mul64 extension:

Register | Name | Use
---------+------+------------------------------------
r57      | mlo  | Multiply low 32 bits, read only
r58      | mmid | Multiply middle 32 bits, read only
r59      | mhi  | Multiply high 32 bits, read only
-----------------------------------------------------

When used for Co-existence configurations we have for mul64 the next
registers used:

Register | Name | Use
---------+------+------------------------------------
r58      | mlo  | Multiply low 32 bits, read only
r59      | mhi  | Multiply high 32 bits, read only
-----------------------------------------------------

Note that mlo/mhi assignment doesn't swap when bigendian CPU
configuration is used.

The compiler will always use r58 for mlo, regardless of the
configuration choosen to ensure mlo/mhi correct splitting. Fixing mlo
to the right register number is done at assembly time. The dwarf info
is also notified via DBX_... macro. Both mlo/mhi registers needs to
saved when ISR happens using a custom sequence.

gcc/
xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>

	* config/arc/arc-protos.h (gen_mlo): Remove.
	(gen_mhi): Likewise.
	* config/arc/arc.c (AUX_MULHI): Define.
	(arc_must_save_reister): Special handling for r58/59.
	(arc_compute_frame_size): Consider mlo/mhi registers.
	(arc_save_callee_saves): Emit fp/sp move only when emit_move
	paramter is true.
	(arc_conditional_register_usage): Remove TARGET_BIG_ENDIAN from
	mlo/mhi name selection.
	(arc_restore_callee_saves): Don't early restore blink when ISR.
	(arc_expand_prologue): Add mlo/mhi saving.
	(arc_expand_epilogue): Add mlo/mhi restoring.
	(gen_mlo): Remove.
	(gen_mhi): Remove.
	* config/arc/arc.h (DBX_REGISTER_NUMBER): Correct register
	numbering when MUL64 option is used.
	(DWARF2_FRAME_REG_OUT): Define.
	* config/arc/arc.md (arc600_stall): New pattern.
	(VUNSPEC_ARC_ARC600_STALL): Define.
	(mulsi64): Use correct mlo/mhi registers.
	(mulsi_600): Clean it up.
	* config/arc/predicates.md (mlo_operand): Remove any dependency on
	TARGET_BIG_ENDIAN.
	(mhi_operand): Likewise.

testsuite/
xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>

	* gcc.target/arc/interrupt-6.c: Update test.
parent 62a715c7
2020-01-27 Claudiu Zissulescu <claziss@synopsys.com>
* config/arc/arc-protos.h (gen_mlo): Remove.
(gen_mhi): Likewise.
* config/arc/arc.c (AUX_MULHI): Define.
(arc_must_save_reister): Special handling for r58/59.
(arc_compute_frame_size): Consider mlo/mhi registers.
(arc_save_callee_saves): Emit fp/sp move only when emit_move
paramter is true.
(arc_conditional_register_usage): Remove TARGET_BIG_ENDIAN from
mlo/mhi name selection.
(arc_restore_callee_saves): Don't early restore blink when ISR.
(arc_expand_prologue): Add mlo/mhi saving.
(arc_expand_epilogue): Add mlo/mhi restoring.
(gen_mlo): Remove.
(gen_mhi): Remove.
* config/arc/arc.h (DBX_REGISTER_NUMBER): Correct register
numbering when MUL64 option is used.
(DWARF2_FRAME_REG_OUT): Define.
* config/arc/arc.md (arc600_stall): New pattern.
(VUNSPEC_ARC_ARC600_STALL): Define.
(mulsi64): Use correct mlo/mhi registers.
(mulsi_600): Clean it up.
* config/arc/predicates.md (mlo_operand): Remove any dependency on
TARGET_BIG_ENDIAN.
(mhi_operand): Likewise.
2020-01-27 Claudiu Zissulescu <claziss@synopsys.com>
Petro Karashchenko <petro.karashchenko@ring.com>
* config/arc/arc.c (arc_is_uncached_mem_p): Check struct
......
......@@ -75,8 +75,6 @@ extern int arc_hazard (rtx_insn *, rtx_insn *);
extern int arc_write_ext_corereg (rtx);
extern rtx gen_acc1 (void);
extern rtx gen_acc2 (void);
extern rtx gen_mlo (void);
extern rtx gen_mhi (void);
extern bool arc_branch_size_unknown_p (void);
struct arc_ccfsm;
extern void arc_ccfsm_record_condition (rtx, bool, rtx_insn *,
......
......@@ -1342,19 +1342,30 @@ do { \
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
/* How to renumber registers for dbx and gdb. */
#define DBX_REGISTER_NUMBER(REGNO) \
#define DBX_REGISTER_NUMBER(REGNO) \
((TARGET_MULMAC_32BY16_SET && (REGNO) >= 56 && (REGNO) <= 57) \
? ((REGNO) ^ !TARGET_BIG_ENDIAN) \
: (TARGET_MUL64_SET && (REGNO) >= 57 && (REGNO) <= 59) \
? ((REGNO) == 57 \
? 58 /* MMED */ \
: ((REGNO) & 1) ^ TARGET_BIG_ENDIAN \
? 59 /* MHI */ \
: 57 + !!TARGET_MULMAC_32BY16_SET) /* MLO */ \
? ((REGNO) ^ !TARGET_BIG_ENDIAN) \
: (TARGET_MUL64_SET && (REGNO) >= 57 && (REGNO) <= 58) \
? (((REGNO) == 57) \
? 58 /* MMED */ \
: 57 + !!TARGET_MULMAC_32BY16_SET) /* MLO */ \
: (REGNO))
/* Use gcc hard register numbering for eh_frame. */
#define DWARF_FRAME_REGNUM(REG) (REG)
/* Map register numbers held in the call frame info that gcc has
collected using DWARF_FRAME_REGNUM to those that should be output
in .debug_frame and .eh_frame. */
#define DWARF2_FRAME_REG_OUT(REGNO, FOR_EH) \
((TARGET_MULMAC_32BY16_SET && (REGNO) >= 56 && (REGNO) <= 57) \
? ((REGNO) ^ !TARGET_BIG_ENDIAN) \
: (TARGET_MUL64_SET && (REGNO) >= 57 && (REGNO) <= 58) \
? (((REGNO) == 57) \
? 58 /* MMED */ \
: 57 + !!TARGET_MULMAC_32BY16_SET) /* MLO */ \
: (REGNO))
#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (31)
#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, 31)
......
......@@ -164,6 +164,7 @@
VUNSPEC_ARC_BLOCKAGE
VUNSPEC_ARC_EH_RETURN
VUNSPEC_ARC_ARC600_RTIE
VUNSPEC_ARC_ARC600_STALL
VUNSPEC_ARC_LDDI
VUNSPEC_ARC_STDI
])
......@@ -2238,6 +2239,9 @@ core_3, archs4x, archs4xd, archs4xd_slow"
(set_attr "predicable" "no, no, yes")
(set_attr "cond" "nocond, canuse_limm, canuse")])
; The gcc-internal representation may differ from the hardware
; register number in order to allow the generic code to correctly
; split the concatenation of mhi and mlo.
(define_insn_and_split "mulsi64"
[(set (match_operand:SI 0 "register_operand" "=w")
(mult:SI (match_operand:SI 1 "register_operand" "%c")
......@@ -2247,12 +2251,13 @@ core_3, archs4x, archs4xd, archs4xd_slow"
"#"
"TARGET_MUL64_SET && reload_completed"
[(const_int 0)]
{
emit_insn (gen_mulsi_600 (operands[1], operands[2],
gen_mlo (), gen_mhi ()));
emit_move_insn (operands[0], gen_mlo ());
DONE;
}
{
rtx mhi = gen_rtx_REG (SImode, R59_REG);
rtx mlo = gen_rtx_REG (SImode, R58_REG);
emit_insn (gen_mulsi_600 (operands[1], operands[2], mlo, mhi));
emit_move_insn (operands[0], mlo);
DONE;
}
[(set_attr "type" "multi")
(set_attr "length" "8")])
......@@ -2262,23 +2267,7 @@ core_3, archs4x, archs4xd, archs4xd_slow"
(match_operand:SI 1 "nonmemory_operand" "Rcq#q,cL,I,Cal")))
(clobber (match_operand:SI 3 "mhi_operand" ""))]
"TARGET_MUL64_SET"
; The assembler mis-assembles mul64 / mulu64 with "I" constraint constants,
; using a machine code pattern that only allows "L" constraint constants.
; "mul64%? \t0, %0, %1%&"
{
if (satisfies_constraint_I (operands[1])
&& !satisfies_constraint_L (operands[1]))
{
/* MUL64 <0,>b,s12 00101bbb10000100 0BBBssssssSSSSSS */
int n = true_regnum (operands[0]);
int i = INTVAL (operands[1]);
asm_fprintf (asm_out_file, "\t.short %d`", 0x2884 + ((n & 7) << 8));
asm_fprintf (asm_out_file, "\t.short %d`",
((i & 0x3f) << 6) + ((i >> 6) & 0x3f) + ((n & 070) << 9));
return "; mul64%? \t0, %0, %1%&";
}
return "mul64%? \t0, %0, %1%&";
}
"mul64%?\\t0,%0,%1"
[(set_attr "length" "*,4,4,8")
(set_attr "iscompact" "maybe,false,false,false")
(set_attr "type" "multi,multi,multi,multi")
......@@ -4298,6 +4287,14 @@ core_3, archs4x, archs4xd, archs4xd_slow"
(set_attr "type" "block")]
)
(define_insn "arc600_stall"
[(unspec_volatile [(const_int 0)] VUNSPEC_ARC_ARC600_STALL)]
"TARGET_MUL64_SET"
"mov\\t0,mlo\t;wait until multiply complete."
[(set_attr "length" "4")
(set_attr "type" "move")]
)
;; Split up troublesome insns for better scheduling.
;; Peepholes go at the end.
......
......@@ -688,11 +688,11 @@
(define_predicate "mlo_operand"
(and (match_code "reg")
(match_test "REGNO (op) == (TARGET_BIG_ENDIAN ? 59 : 58)")))
(match_test "REGNO (op) == R58_REG")))
(define_predicate "mhi_operand"
(and (match_code "reg")
(match_test "REGNO (op) == (TARGET_BIG_ENDIAN ? 58 : 59)")))
(match_test "REGNO (op) == R59_REG")))
(define_predicate "accl_operand"
(and (match_code "reg")
......
2020-01-27 Claudiu Zissulescu <claziss@synopsys.com>
* gcc.target/arc/interrupt-6.c: Update test.
2020-01-27 Claudiu Zissulescu <claziss@synopsys.com>
Petro Karashchenko <petro.karashchenko@ring.com>
* gcc.target/arc/uncached-3.c: New test.
......
......@@ -17,5 +17,5 @@ foo(void)
bar (p);
}
/* { dg-final { scan-assembler-not ".*fp,\\\[sp" } } */
/* { dg-final { scan-assembler "ld.*blink,\\\[sp" } } */
/* { dg-final { scan-assembler "pop_s.*blink" } } */
/* { dg-final { scan-assembler "push_s.*blink" } } */
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