Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
riscv-gcc-1
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
riscv-gcc-1
Commits
576182a3
Commit
576182a3
authored
Mar 23, 1993
by
Tom Wood
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
(untyped_call, untyped_return): New patterns.
From-SVN: r3837
parent
e9125c09
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
194 additions
and
0 deletions
+194
-0
gcc/config/i386/i386.md
+117
-0
gcc/config/sparc/sparc.md
+77
-0
No files found.
gcc/config/i386/i386.md
View file @
576182a3
...
@@ -4113,6 +4113,123 @@
...
@@ -4113,6 +4113,123 @@
"!HALF_PIC_P ()"
"!HALF_PIC_P ()"
"call %P1")
"call %P1")
(define_expand "untyped_call"
[(parallel [(call (match_operand:QI 0 "indirect_operand" "")
(const_int 0))
(match_operand:BLK 1 "memory_operand" "")
(match_operand 2 "" "")])]
""
"
{
rtx addr;
if (flag_pic)
current_function_uses_pic_offset_table = 1;
/* With half-pic, force the address into a register. */
addr = XEXP (operands[0], 0);
if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
XEXP (operands[0], 0) = force_reg (Pmode, addr);
operands[1] = change_address (operands[1], DImode, XEXP (operands[1], 0));
}")
(define_insn ""
[(call (match_operand:QI 0 "indirect_operand" "m")
(const_int 0))
(match_operand:DI 1 "memory_operand" "o")
(match_operand 2 "" "")]
""
"*
{
rtx addr = operands[1];
if (GET_CODE (operands[0]) == MEM
&& ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
{
operands[0] = XEXP (operands[0], 0);
output_asm_insn (AS1 (call,%*%0), operands);
}
else
output_asm_insn (AS1 (call,%P0), operands);
operands[2] = gen_rtx (REG, SImode, 0);
output_asm_insn (AS2 (mov%L2,%2,%1), operands);
operands[2] = gen_rtx (REG, SImode, 1);
operands[1] = adj_offsettable_operand (addr, 4);
output_asm_insn (AS2 (mov%L2,%2,%1), operands);
operands[1] = adj_offsettable_operand (addr, 8);
return AS1 (fnsave,%1);
}")
(define_insn ""
[(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
(const_int 0))
(match_operand:DI 1 "memory_operand" "o")
(match_operand 2 "" "")]
"!HALF_PIC_P ()"
"*
{
rtx addr = operands[1];
output_asm_insn (AS1 (call,%P0));
operands[2] = gen_rtx (REG, SImode, 0);
output_asm_insn (AS2 (mov%L2,%2,%1), operands);
operands[2] = gen_rtx (REG, SImode, 1);
operands[1] = adj_offsettable_operand (addr, 4);
output_asm_insn (AS2 (mov%L2,%2,%1), operands);
operands[1] = adj_offsettable_operand (addr, 8);
return AS1 (fnsave,%1);
}")
;; We use fnsave and frstor to save and restore the floating point result.
;; These are expensive instructions and require a large space to save the
;; FPU state. An more complicated alternative is to use fnstenv to store
;; the FPU environment and test whether the stack top is valid. Store the
;; result of the test, and if it is valid, pop and save the value. The
;; untyped_return would check the test and optionally push the saved value.
(define_expand "untyped_return"
[(match_operand:BLK 0 "memory_operand" "")
(match_operand 1 "" "")]
""
"
{
rtx valreg1 = gen_rtx (REG, SImode, 0);
rtx valreg2 = gen_rtx (REG, SImode, 1);
rtx result = operands[0];
/* Restore the FPU state. */
emit_insn (gen_update_return (change_address (result, SImode,
plus_constant (XEXP (result, 0),
8))));
/* Reload the function value registers. */
emit_move_insn (valreg1, change_address (result, SImode, XEXP (result, 0)));
emit_move_insn (valreg2,
change_address (result, SImode,
plus_constant (XEXP (result, 0), 4)));
/* Put USE insns before the return. */
emit_insn (gen_rtx (USE, VOIDmode, valreg1));
emit_insn (gen_rtx (USE, VOIDmode, valreg2));
/* Construct the return. */
expand_null_return ();
DONE;
}")
(define_insn "update_return"
[(unspec:SI [(match_operand:SI 0 "memory_operand" "m")] 0)]
""
"frstor %0")
;; Insn emitted into the body of a function to return from a function.
;; Insn emitted into the body of a function to return from a function.
;; This is only done if the function's epilogue is known to be simple.
;; This is only done if the function's epilogue is known to be simple.
;; See comments for simple_386_epilogue in i386.c.
;; See comments for simple_386_epilogue in i386.c.
...
...
gcc/config/sparc/sparc.md
View file @
576182a3
...
@@ -2749,6 +2749,83 @@
...
@@ -2749,6 +2749,83 @@
return
\"
call %a1,%2%#
\"
;
return
\"
call %a1,%2%#
\"
;
}"
}"
[
(set_attr "type" "call")
]
)
[
(set_attr "type" "call")
]
)
(define_expand "untyped_call"
[
(parallel
[
(call (match_operand:SI 0 "call_operand" "")
(const_int 0))
(match_operand:BLK 1 "memory_operand" "")
(match_operand 2 "" "")
(clobber (reg:SI 15))])]
""
"
{
operands
[
1
]
= change_address (operands
[
1
]
, DImode, XEXP (operands
[
1
]
, 0));
}")
;; Make a call followed by two nops in case the function being called
;; returns a structure value and expects to skip an unimp instruction.
(define_insn ""
[
(call (mem:SI (match_operand:SI 0 "call_operand_address" "rS"))
(const_int 0))
(match_operand:DI 1 "memory_operand" "o")
(match_operand 2 "" "")
(clobber (reg:SI 15))]
""
"
*
{
operands
[
2
]
= adj_offsettable_operand (operands
[
1
]
, 8);
return
\"
call %a0,0
\;
nop
\;
nop
\;
std %%o0,%1
\;
st %%f0,%2
\"
;
}"
[
(set_attr "type" "multi")
]
)
;; Prepare to return any type including a structure value.
(define_expand "untyped_return"
[
(match_operand:BLK 0 "memory_operand" "")
(match_operand 1 "" "")]
""
"
{
rtx valreg1 = gen_rtx (REG, DImode, 24);
rtx valreg2 = gen_rtx (REG, DFmode, 32);
rtx result = operands
[
0
]
;
rtx rtnreg = gen_rtx (REG, SImode, (leaf_function ? 15 : 31));
rtx value = gen_reg_rtx (SImode);
/
*
Fetch the instruction where we will return to and see if it's an unimp
instruction (the most significant 10 bits will be zero). If so,
update the return address to skip the unimp instruction.
*
/
emit_move_insn (value,
gen_rtx (MEM, SImode, plus_constant (rtnreg, 8)));
emit_insn (gen_lshrsi3 (value, value, GEN_INT (22)));
emit_insn (gen_update_return (rtnreg, value));
/
* Reload the function value registers. *
/
emit_move_insn (valreg1, change_address (result, DImode, XEXP (result, 0)));
emit_move_insn (valreg2,
change_address (result, DFmode,
plus_constant (XEXP (result, 0), 8)));
/
* Put USE insns before the return. *
/
emit_insn (gen_rtx (USE, VOIDmode, valreg1));
emit_insn (gen_rtx (USE, VOIDmode, valreg2));
/
* Construct the return. *
/
expand_null_return ();
DONE;
}")
;; This is a bit of a hack. We're incrementing a fixed register (%i7),
;; and parts of the compiler don't want to believe that the add is needed.
(define_insn "update_return"
[
(unspec:SI
[
(match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "register_operand" "r")] 0)]
""
"cmp %1,0
\;
be,a .+8
\;
add %0,4,%0"
[
(set_attr "type" "multi")
]
)
(define_insn "return"
(define_insn "return"
[
(return)
]
[
(return)
]
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment