Commit 0256a844 by Matthew Fortune Committed by Robert Suchanek

Support new interrupt handler options.

gcc/
	* config/mips/mips.c (mips_int_mask): New enum.
	(mips_shadow_set): Likewise.
	(int_mask): New variable.
	(use_shadow_register_set_p): Change type to enum mips_shadow_set.
	(machine_function): Add int_mask and use_shadow_register_set.
	(mips_attribute_table): Add attribute handlers for interrupt and
	use_shadow_register_set.
	(mips_interrupt_mask): New static function.
	(mips_handle_interrupt_attr): Likewise.
	(mips_handle_use_shadow_register_set_attr): Likewise.
	(mips_use_shadow_register_set): Change return type to enum
	mips_shadow_set.  Add argument handling for use_shadow_register_set
	attribute.
	(mips_interrupt_extra_called_saved_reg_p): Update the conditional to
	compare with mips_shadow_set enum.
	(mips_compute_frame_info): Add interrupt mask and
	use_shadow_register_set to per-function information structure.
	Add a stack slot for EPC unconditionally.
	(mips_expand_prologue): Compare use_shadow_register_set value
	with mips_shadow_set enum.  Save EPC always in K1, clobber only K1 for
	masked interrupt register but in EIC mode use K0 and save Cause in K0.
	EPC saved and restored unconditionally.  Use PMODE_INSN macro when
	copying the stack pointer from the shadow register set.
	* config/mips/mips.h (SR_IM0): New define.
	* config/mips/mips.md (mips_rdpgpr): Rename to...
	(mips_rdpgpr_<mode>): ...this.  Use the Pmode iterator.
	* doc/extend.texi (Declaring Attributes of Functions): Document
	optional arguments for interrupt and use_shadow_register_set
	attributes.

gcc/testsuite/
	* gcc.target/mips/interrupt_handler-4.c: New test.

Co-Authored-By: Robert Suchanek <robert.suchanek@imgtec.com>

From-SVN: r225819
parent 6a2b848b
2015-07-15 Matthew Fortune <matthew.fortune@imgtec.com>
Robert Suchanek <robert.suchanek@imgtec.com>
* config/mips/mips.c (mips_int_mask): New enum.
(mips_shadow_set): Likewise.
(int_mask): New variable.
(use_shadow_register_set_p): Change type to enum mips_shadow_set.
(machine_function): Add int_mask and use_shadow_register_set.
(mips_attribute_table): Add attribute handlers for interrupt and
use_shadow_register_set.
(mips_interrupt_mask): New static function.
(mips_handle_interrupt_attr): Likewise.
(mips_handle_use_shadow_register_set_attr): Likewise.
(mips_use_shadow_register_set): Change return type to enum
mips_shadow_set. Add argument handling for use_shadow_register_set
attribute.
(mips_interrupt_extra_called_saved_reg_p): Update the conditional to
compare with mips_shadow_set enum.
(mips_compute_frame_info): Add interrupt mask and
use_shadow_register_set to per-function information structure.
Add a stack slot for EPC unconditionally.
(mips_expand_prologue): Compare use_shadow_register_set value
with mips_shadow_set enum. Save EPC always in K1, clobber only K1 for
masked interrupt register but in EIC mode use K0 and save Cause in K0.
EPC saved and restored unconditionally. Use PMODE_INSN macro when
copying the stack pointer from the shadow register set.
* config/mips/mips.h (SR_IM0): New define.
* config/mips/mips.md (mips_rdpgpr): Rename to...
(mips_rdpgpr_<mode>): ...this. Use the Pmode iterator.
* doc/extend.texi (Declaring Attributes of Functions): Document
optional arguments for interrupt and use_shadow_register_set
attributes.
2015-07-15 Robert Suchanek <robert.suchanek@imgtec.com>
* config/mips/mips.c (mips_compute_frame_info): Allow -mhard-float in
......
......@@ -1811,6 +1811,9 @@ FP_ASM_SPEC "\
#define SR_COP1 29
/* Interrupt Priority Level is from bit 10 to bit 15 of the status register. */
#define SR_IPL 10
/* Interrupt masks start with IM0 at bit 8 to IM7 at bit 15 of the status
register. */
#define SR_IM0 8
/* Exception Level is at bit 1 of the status register. */
#define SR_EXL 1
/* Interrupt Enable is at bit 0 of the status register. */
......
......@@ -6564,14 +6564,14 @@
(set_attr "mode" "none")])
;; Read GPR from previous shadow register set.
(define_insn "mips_rdpgpr"
[(set (match_operand:SI 0 "register_operand" "=d")
(unspec_volatile:SI [(match_operand:SI 1 "register_operand" "d")]
UNSPEC_RDPGPR))]
(define_insn "mips_rdpgpr_<mode>"
[(set (match_operand:P 0 "register_operand" "=d")
(unspec_volatile:P [(match_operand:P 1 "register_operand" "d")]
UNSPEC_RDPGPR))]
""
"rdpgpr\t%0,%1"
[(set_attr "type" "move")
(set_attr "mode" "SI")])
(set_attr "mode" "<MODE>")])
;; Move involving COP0 registers.
(define_insn "cop0_move"
......
......@@ -4090,10 +4090,18 @@ These function attributes are supported by the MIPS back end:
@table @code
@item interrupt
@cindex @code{interrupt} function attribute, MIPS
Use this attribute to indicate
that the specified function is an interrupt handler. The compiler generates
function entry and exit sequences suitable for use in an interrupt handler
when this attribute is present.
Use this attribute to indicate that the specified function is an interrupt
handler. The compiler generates function entry and exit sequences suitable
for use in an interrupt handler when this attribute is present.
An optional argument is supported for the interrupt attribute which allows
the interrupt mode to be described. By default GCC assumes the external
interrupt controller (EIC) mode is in use, this can be explicitly set using
@code{eic}. When interrupts are non-masked then the requested Interrupt
Priority Level (IPL) is copied to the current IPL which has the effect of only
enabling higher priority interrupts. To use vectored interrupt mode use
the argument @code{vector=[sw0|sw1|hw0|hw1|hw2|hw3|hw4|hw5]}, this will change
the behaviour of the non-masked interrupt support and GCC will arrange to mask
all interrupts from sw0 up to and including the specified interrupt vector.
You can use the following attributes to modify the behavior
of an interrupt handler:
......@@ -4101,7 +4109,9 @@ of an interrupt handler:
@item use_shadow_register_set
@cindex @code{use_shadow_register_set} function attribute, MIPS
Assume that the handler uses a shadow register set, instead of
the main general-purpose registers.
the main general-purpose registers. An optional argument @code{intstack} is
supported to indicate that the shadow register set contains a valid stack
pointer.
@item keep_interrupts_masked
@cindex @code{keep_interrupts_masked} function attribute, MIPS
......@@ -4129,6 +4139,8 @@ void __attribute__ ((interrupt, keep_interrupts_masked,
void __attribute__ ((interrupt, use_shadow_register_set,
keep_interrupts_masked,
use_debug_exception_return)) v7 ();
void __attribute__ ((interrupt("eic"))) v8 ();
void __attribute__ ((interrupt("vector=hw3"))) v9 ();
@end smallexample
@item long_call
......
2015-07-15 Matthew Fortune <matthew.fortune@imgtec.com>
Robert Suchanek <robert.suchanek@imgtec.com>
* gcc.target/mips/interrupt_handler-4.c: New test.
2015-07-15 Ilya Enkovich <enkovich.gnu@gmail.com>
PR testsuite/66734
......
/* Test optional argument for interrupt and use_shadow_register_set
attributes. */
/* { dg-do compile } */
/* { dg-options "isa_rev>=2" } */
/* { dg-final { scan-assembler "e0:.*ins\t\\\$27,\\\$26,10,6.*\.end\te0" } } */
/* { dg-final { scan-assembler-times "mfc0\t\\\$26,\\\$13" 3 } } */
/* { dg-final { scan-assembler-times "mfc0\t\\\$27,\\\$14" 11 } } */
/* { dg-final { scan-assembler "v0:.*ins\t\\\$27,\\\$0,8,1.*\.end\tv0" } } */
/* { dg-final { scan-assembler "v1:.*ins\t\\\$27,\\\$0,8,2.*\.end\tv1" } } */
/* { dg-final { scan-assembler "v2:.*ins\t\\\$27,\\\$0,8,3.*\.end\tv2" } } */
/* { dg-final { scan-assembler "v3:.*ins\t\\\$27,\\\$0,8,4.*\.end\tv3" } } */
/* { dg-final { scan-assembler "v4:.*ins\t\\\$27,\\\$0,8,5.*\.end\tv4" } } */
/* { dg-final { scan-assembler "v5:.*ins\t\\\$27,\\\$0,8,6.*\.end\tv5" } } */
/* { dg-final { scan-assembler "v6:.*ins\t\\\$27,\\\$0,8,7.*\.end\tv6" } } */
/* { dg-final { scan-assembler "v7:.*ins\t\\\$27,\\\$0,8,8.*\.end\tv7" } } */
/* { dg-final { scan-assembler-times "rdpgpr\t\\\$sp,\\\$sp" 1 } } */
/* { dg-final { scan-assembler-not "s1:.*rdpgpr\t\\\$sp,\\\$sp.*\.end\ts1" } } */
NOMIPS16 void __attribute__ ((interrupt("eic"))) e0 () { }
NOMIPS16 void __attribute__ ((interrupt("vector=sw0"))) v0 () { }
NOMIPS16 void __attribute__ ((interrupt("vector=sw1"))) v1 () { }
NOMIPS16 void __attribute__ ((interrupt("vector=hw0"))) v2 () { }
NOMIPS16 void __attribute__ ((interrupt("vector=hw1"))) v3 () { }
NOMIPS16 void __attribute__ ((interrupt("vector=hw2"))) v4 () { }
NOMIPS16 void __attribute__ ((interrupt("vector=hw3"))) v5 () { }
NOMIPS16 void __attribute__ ((interrupt("vector=hw4"))) v6 () { }
NOMIPS16 void __attribute__ ((interrupt("vector=hw5"))) v7 () { }
NOMIPS16 void __attribute__ ((interrupt, use_shadow_register_set)) s0 () { }
NOMIPS16 void __attribute__ ((interrupt, use_shadow_register_set("intstack"))) s1 () { }
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