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
581cc66c
Commit
581cc66c
authored
May 31, 1991
by
Charles Hannum
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
entered into RCS
From-SVN: r24
parent
8763cbe8
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
326 additions
and
0 deletions
+326
-0
gcc/config/spur/spur.c
+326
-0
No files found.
gcc/config/spur/spur.c
0 → 100644
View file @
581cc66c
/* Subroutines for insn-output.c for SPUR. Adapted from routines for
the Motorola 68000 family.
Copyright (C) 1988, 1991 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
static
rtx
find_addr_reg
();
char
*
output_compare
(
operands
,
opcode
,
exchange_opcode
,
neg_opcode
,
neg_exchange_opcode
)
rtx
*
operands
;
char
*
opcode
;
char
*
exchange_opcode
;
char
*
neg_opcode
;
char
*
neg_exchange_opcode
;
{
static
char
buf
[
100
];
operands
[
2
]
=
operands
[
0
];
if
(
GET_CODE
(
cc_prev_status
.
value1
)
==
CONST_INT
)
{
operands
[
1
]
=
cc_prev_status
.
value1
;
operands
[
0
]
=
cc_prev_status
.
value2
;
opcode
=
exchange_opcode
,
neg_opcode
=
neg_exchange_opcode
;
}
else
{
operands
[
0
]
=
cc_prev_status
.
value1
;
operands
[
1
]
=
cc_prev_status
.
value2
;
}
if
(
TARGET_LONG_JUMPS
)
sprintf
(
buf
,
"cmp_br_delayed %s,%%0,%%1,1f
\n\t
nop
\n\t
jump %%l2
\n\t
nop
\n
1:"
,
neg_opcode
);
else
sprintf
(
buf
,
"cmp_br_delayed %s,%%0,%%1,%%l2
\n\t
nop"
,
opcode
);
return
buf
;
}
/* Return the best assembler insn template
for moving operands[1] into operands[0] as a fullword. */
static
char
*
singlemove_string
(
operands
)
rtx
*
operands
;
{
if
(
GET_CODE
(
operands
[
0
])
==
MEM
)
return
"st_32 %r1,%0"
;
if
(
GET_CODE
(
operands
[
1
])
==
MEM
)
return
"ld_32 %0,%1
\n\t
nop"
;
if
(
GET_CODE
(
operands
[
1
])
==
REG
)
return
"add_nt %0,%1,$0"
;
return
"add_nt %0,r0,%1"
;
}
/* Output assembler code to perform a doubleword move insn
with operands OPERANDS. */
char
*
output_move_double
(
operands
)
rtx
*
operands
;
{
enum
{
REGOP
,
OFFSOP
,
MEMOP
,
PUSHOP
,
POPOP
,
CNSTOP
,
RNDOP
}
optype0
,
optype1
;
rtx
latehalf
[
2
];
rtx
addreg0
=
0
,
addreg1
=
0
;
/* First classify both operands. */
if
(
REG_P
(
operands
[
0
]))
optype0
=
REGOP
;
else
if
(
offsettable_memref_p
(
operands
[
0
]))
optype0
=
OFFSOP
;
else
if
(
GET_CODE
(
operands
[
0
])
==
MEM
)
optype0
=
MEMOP
;
else
optype0
=
RNDOP
;
if
(
REG_P
(
operands
[
1
]))
optype1
=
REGOP
;
else
if
(
CONSTANT_P
(
operands
[
1
]))
optype1
=
CNSTOP
;
else
if
(
offsettable_memref_p
(
operands
[
1
]))
optype1
=
OFFSOP
;
else
if
(
GET_CODE
(
operands
[
1
])
==
MEM
)
optype1
=
MEMOP
;
else
optype1
=
RNDOP
;
/* Check for the cases that the operand constraints are not
supposed to allow to happen. Abort if we get one,
because generating code for these cases is painful. */
if
(
optype0
==
RNDOP
||
optype1
==
RNDOP
)
abort
();
/* If an operand is an unoffsettable memory ref, find a register
we can increment temporarily to make it refer to the second word. */
if
(
optype0
==
MEMOP
)
addreg0
=
find_addr_reg
(
XEXP
(
operands
[
0
],
0
));
if
(
optype1
==
MEMOP
)
addreg1
=
find_addr_reg
(
XEXP
(
operands
[
1
],
0
));
/* Ok, we can do one word at a time.
Normally we do the low-numbered word first,
but if either operand is autodecrementing then we
do the high-numbered word first.
In either case, set up in LATEHALF the operands to use
for the high-numbered word and in some cases alter the
operands in OPERANDS to be suitable for the low-numbered word. */
if
(
optype0
==
REGOP
)
latehalf
[
0
]
=
gen_rtx
(
REG
,
SImode
,
REGNO
(
operands
[
0
])
+
1
);
else
if
(
optype0
==
OFFSOP
)
latehalf
[
0
]
=
adj_offsettable_operand
(
operands
[
0
],
4
);
else
latehalf
[
0
]
=
operands
[
0
];
if
(
optype1
==
REGOP
)
latehalf
[
1
]
=
gen_rtx
(
REG
,
SImode
,
REGNO
(
operands
[
1
])
+
1
);
else
if
(
optype1
==
OFFSOP
)
latehalf
[
1
]
=
adj_offsettable_operand
(
operands
[
1
],
4
);
else
if
(
optype1
==
CNSTOP
)
{
if
(
GET_CODE
(
operands
[
1
])
==
CONST_DOUBLE
)
{
latehalf
[
1
]
=
gen_rtx
(
CONST_INT
,
VOIDmode
,
CONST_DOUBLE_HIGH
(
operands
[
1
]));
operands
[
1
]
=
gen_rtx
(
CONST_INT
,
VOIDmode
,
CONST_DOUBLE_LOW
(
operands
[
1
]));
}
else
if
(
CONSTANT_P
(
operands
[
1
]))
latehalf
[
1
]
=
const0_rtx
;
}
else
latehalf
[
1
]
=
operands
[
1
];
/* If the first move would clobber the source of the second one,
do them in the other order. This happens only for registers;
such overlap can't happen in memory unless the user explicitly
sets it up, and that is an undefined circumstance. */
if
(
optype0
==
REGOP
&&
optype1
==
REGOP
&&
REGNO
(
operands
[
0
])
==
REGNO
(
latehalf
[
1
]))
{
/* Make any unoffsettable addresses point at high-numbered word. */
if
(
addreg0
)
output_asm_insn
(
"add_nt %0,%0,$4"
,
&
addreg0
);
if
(
addreg1
)
output_asm_insn
(
"add_nt %0,%0,$4"
,
&
addreg1
);
/* Do that word. */
output_asm_insn
(
singlemove_string
(
latehalf
),
latehalf
);
/* Undo the adds we just did. */
if
(
addreg0
)
output_asm_insn
(
"add_nt %0,%0,$-4"
,
&
addreg0
);
if
(
addreg1
)
output_asm_insn
(
"add_nt %0,%0,$-4"
,
&
addreg0
);
/* Do low-numbered word. */
return
singlemove_string
(
operands
);
}
/* Normal case: do the two words, low-numbered first. */
output_asm_insn
(
singlemove_string
(
operands
),
operands
);
/* Make any unoffsettable addresses point at high-numbered word. */
if
(
addreg0
)
output_asm_insn
(
"add_nt %0,%0,$4"
,
&
addreg0
);
if
(
addreg1
)
output_asm_insn
(
"add_nt %0,%0,$4"
,
&
addreg1
);
/* Do that word. */
output_asm_insn
(
singlemove_string
(
latehalf
),
latehalf
);
/* Undo the adds we just did. */
if
(
addreg0
)
output_asm_insn
(
"add_nt %0,%0,$-4"
,
&
addreg0
);
if
(
addreg1
)
output_asm_insn
(
"add_nt %0,%0,$-4"
,
&
addreg1
);
return
""
;
}
static
char
*
output_fp_move_double
(
operands
)
rtx
*
operands
;
{
if
(
FP_REG_P
(
operands
[
0
]))
{
if
(
FP_REG_P
(
operands
[
1
]))
return
"fmov %0,%1"
;
if
(
GET_CODE
(
operands
[
1
])
==
REG
)
{
rtx
xoperands
[
2
];
int
offset
=
-
get_frame_size
()
-
8
;
xoperands
[
1
]
=
gen_rtx
(
REG
,
SImode
,
REGNO
(
operands
[
1
])
+
1
);
xoperands
[
0
]
=
gen_rtx
(
CONST_INT
,
VOIDmode
,
offset
+
4
);
output_asm_insn
(
"st_32 %1,r25,%0"
,
xoperands
);
xoperands
[
1
]
=
operands
[
1
];
xoperands
[
0
]
=
gen_rtx
(
CONST_INT
,
VOIDmode
,
offset
);
output_asm_insn
(
"st_32 %1,r25,%0"
,
xoperands
);
xoperands
[
1
]
=
operands
[
0
];
output_asm_insn
(
"ld_dbl %1,r25,%0
\n\t
nop"
,
xoperands
);
return
""
;
}
return
"ld_dbl %0,%1
\n\t
nop"
;
}
else
if
(
FP_REG_P
(
operands
[
1
]))
{
if
(
GET_CODE
(
operands
[
0
])
==
REG
)
{
rtx
xoperands
[
2
];
int
offset
=
-
get_frame_size
()
-
8
;
xoperands
[
0
]
=
gen_rtx
(
CONST_INT
,
VOIDmode
,
offset
);
xoperands
[
1
]
=
operands
[
1
];
output_asm_insn
(
"st_dbl %1,r25,%0"
,
xoperands
);
xoperands
[
1
]
=
operands
[
0
];
output_asm_insn
(
"ld_32 %1,r25,%0
\n\t
nop"
,
xoperands
);
xoperands
[
1
]
=
gen_rtx
(
REG
,
SImode
,
REGNO
(
operands
[
0
])
+
1
);
xoperands
[
0
]
=
gen_rtx
(
CONST_INT
,
VOIDmode
,
offset
+
4
);
output_asm_insn
(
"ld_32 %1,r25,%0
\n\t
nop"
,
xoperands
);
return
""
;
}
return
"st_dbl %1,%0"
;
}
}
/* Return a REG that occurs in ADDR with coefficient 1.
ADDR can be effectively incremented by incrementing REG. */
static
rtx
find_addr_reg
(
addr
)
rtx
addr
;
{
while
(
GET_CODE
(
addr
)
==
PLUS
)
{
if
(
GET_CODE
(
XEXP
(
addr
,
0
))
==
REG
)
addr
=
XEXP
(
addr
,
0
);
else
if
(
GET_CODE
(
XEXP
(
addr
,
1
))
==
REG
)
addr
=
XEXP
(
addr
,
1
);
else
if
(
CONSTANT_P
(
XEXP
(
addr
,
0
)))
addr
=
XEXP
(
addr
,
1
);
else
if
(
CONSTANT_P
(
XEXP
(
addr
,
1
)))
addr
=
XEXP
(
addr
,
0
);
else
abort
();
}
if
(
GET_CODE
(
addr
)
==
REG
)
return
addr
;
abort
();
}
/* Generate code to add a large integer constant to register, reg, storing
* the result in a register, target. Offset must be 27-bit signed quantity */
static
char
*
output_add_large_offset
(
target
,
reg
,
offset
)
rtx
target
,
reg
;
int
offset
;
{
rtx
operands
[
3
];
int
high
,
n
,
i
;
operands
[
0
]
=
target
,
operands
[
1
]
=
reg
;
for
(
high
=
offset
,
n
=
0
;
(
unsigned
)
(
high
+
0x2000
)
>=
0x4000
;
high
>>=
1
,
n
+=
1
)
;
operands
[
2
]
=
gen_rtx
(
CONST_INT
,
VOIDmode
,
high
);
output_asm_insn
(
"add_nt r2,r0,%2"
,
operands
);
i
=
n
;
while
(
i
>=
3
)
output_asm_insn
(
"sll r2,r2,$3"
,
operands
),
i
-=
3
;
if
(
i
==
2
)
output_asm_insn
(
"sll r2,r2,$2"
,
operands
);
else
if
(
i
==
1
)
output_asm_insn
(
"sll r2,r2,$1"
,
operands
);
output_asm_insn
(
"add_nt %0,r2,%1"
,
operands
);
if
(
offset
-
(
high
<<
n
)
!=
0
)
{
operands
[
2
]
=
gen_rtx
(
CONST_INT
,
VOIDmode
,
offset
-
(
high
<<
n
));
output_asm_insn
(
"add_nt %0,%0,%2"
,
operands
);
}
return
""
;
}
/* Additional TESTFN for matching. Like immediate_operand, but matches big
* constants */
int
big_immediate_operand
(
op
,
mode
)
rtx
op
;
enum
machine_mode
mode
;
{
return
(
GET_CODE
(
op
)
==
CONST_INT
);
}
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