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
8480102e
Commit
8480102e
authored
Jun 09, 1991
by
Charles Hannum
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
entered into RCS
From-SVN: r28
parent
acde64ae
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
299 additions
and
0 deletions
+299
-0
gcc/config/fx80/fx80.c
+299
-0
No files found.
gcc/config/fx80/fx80.c
0 → 100644
View file @
8480102e
/* Subroutines for insn-output.c for Alliant FX computers.
Copyright (C) 1989,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. */
/* Some output-actions in alliant.md need these. */
#include <stdio.h>
#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"
/* Index into this array by (register number >> 3) to find the
smallest class which contains that register. */
enum
reg_class
regno_reg_class
[]
=
{
DATA_REGS
,
ADDR_REGS
,
FP_REGS
};
static
rtx
find_addr_reg
();
char
*
output_btst
(
operands
,
countop
,
dataop
,
insn
,
signpos
)
rtx
*
operands
;
rtx
countop
,
dataop
;
rtx
insn
;
int
signpos
;
{
operands
[
0
]
=
countop
;
operands
[
1
]
=
dataop
;
if
(
GET_CODE
(
countop
)
==
CONST_INT
)
{
register
int
count
=
INTVAL
(
countop
);
/* If COUNT is bigger than size of storage unit in use,
advance to the containing unit of same size. */
if
(
count
>
signpos
)
{
int
offset
=
(
count
&
~
signpos
)
/
8
;
count
=
count
&
signpos
;
operands
[
1
]
=
dataop
=
adj_offsettable_operand
(
dataop
,
offset
);
}
if
(
count
==
signpos
)
cc_status
.
flags
=
CC_NOT_POSITIVE
|
CC_Z_IN_NOT_N
;
else
cc_status
.
flags
=
CC_NOT_NEGATIVE
|
CC_Z_IN_NOT_N
;
/* These three statements used to use next_insns_test_no...
but it appears that this should do the same job. */
if
(
count
==
31
&&
next_insn_tests_no_inequality
(
insn
))
return
"tst%.l %1"
;
if
(
count
==
15
&&
next_insn_tests_no_inequality
(
insn
))
return
"tst%.w %1"
;
if
(
count
==
7
&&
next_insn_tests_no_inequality
(
insn
))
return
"tst%.b %1"
;
cc_status
.
flags
=
CC_NOT_NEGATIVE
;
}
return
"btst %0,%1"
;
}
/* Return the best assembler insn template
for moving operands[1] into operands[0] as a fullword. */
static
char
*
singlemove_string
(
operands
)
rtx
*
operands
;
{
if
(
operands
[
1
]
!=
const0_rtx
)
return
"mov%.l %1,%0"
;
if
(
!
ADDRESS_REG_P
(
operands
[
0
]))
return
"clr%.l %0"
;
return
"sub%.l %0,%0"
;
}
/* 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
(
XEXP
(
operands
[
0
],
0
))
==
POST_INC
)
optype0
=
POPOP
;
else
if
(
GET_CODE
(
XEXP
(
operands
[
0
],
0
))
==
PRE_DEC
)
optype0
=
PUSHOP
;
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
(
XEXP
(
operands
[
1
],
0
))
==
POST_INC
)
optype1
=
POPOP
;
else
if
(
GET_CODE
(
XEXP
(
operands
[
1
],
0
))
==
PRE_DEC
)
optype1
=
PUSHOP
;
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 one operand is decrementing and one is incrementing
decrement the former register explicitly
and change that operand into ordinary indexing. */
if
(
optype0
==
PUSHOP
&&
optype1
==
POPOP
)
{
operands
[
0
]
=
XEXP
(
XEXP
(
operands
[
0
],
0
),
0
);
output_asm_insn
(
"subq%.l %#8,%0"
,
operands
);
operands
[
0
]
=
gen_rtx
(
MEM
,
DImode
,
operands
[
0
]);
optype0
=
OFFSOP
;
}
if
(
optype0
==
POPOP
&&
optype1
==
PUSHOP
)
{
operands
[
1
]
=
XEXP
(
XEXP
(
operands
[
1
],
0
),
0
);
output_asm_insn
(
"subq%.l %#8,%1"
,
operands
);
operands
[
1
]
=
gen_rtx
(
MEM
,
DImode
,
operands
[
1
]);
optype1
=
OFFSOP
;
}
/* 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
)
split_double
(
operands
[
1
],
&
operands
[
1
],
&
latehalf
[
1
]);
else
if
(
CONSTANT_P
(
operands
[
1
]))
{
latehalf
[
1
]
=
operands
[
1
];
operands
[
1
]
=
const0_rtx
;
}
}
else
latehalf
[
1
]
=
operands
[
1
];
/* If insn is effectively movd N(sp),-(sp) then we will do the
high word first. We should use the adjusted operand 1 (which is N+4(sp))
for the low word as well, to compensate for the first decrement of sp. */
if
(
optype0
==
PUSHOP
&&
REGNO
(
XEXP
(
XEXP
(
operands
[
0
],
0
),
0
))
==
STACK_POINTER_REGNUM
&&
reg_overlap_mentioned_p
(
stack_pointer_rtx
,
operands
[
1
]))
operands
[
1
]
=
latehalf
[
1
];
/* If one or both operands autodecrementing,
do the two words, high-numbered first. */
/* Likewise, 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
==
PUSHOP
||
optype1
==
PUSHOP
||
(
optype0
==
REGOP
&&
optype1
==
REGOP
&&
REGNO
(
operands
[
0
])
==
REGNO
(
latehalf
[
1
])))
{
/* Make any unoffsettable addresses point at high-numbered word. */
if
(
addreg0
)
output_asm_insn
(
"addql %#4,%0"
,
&
addreg0
);
if
(
addreg1
)
output_asm_insn
(
"addql %#4,%0"
,
&
addreg1
);
/* Do that word. */
output_asm_insn
(
singlemove_string
(
latehalf
),
latehalf
);
/* Undo the adds we just did. */
if
(
addreg0
)
output_asm_insn
(
"subql %#4,%0"
,
&
addreg0
);
if
(
addreg1
)
output_asm_insn
(
"subql %#4,%0"
,
&
addreg1
);
/* 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
(
"addql %#4,%0"
,
&
addreg0
);
if
(
addreg1
)
output_asm_insn
(
"addql %#4,%0"
,
&
addreg1
);
/* Do that word. */
output_asm_insn
(
singlemove_string
(
latehalf
),
latehalf
);
/* Undo the adds we just did. */
if
(
addreg0
)
output_asm_insn
(
"subql %#4,%0"
,
&
addreg0
);
if
(
addreg1
)
output_asm_insn
(
"subql %#4,%0"
,
&
addreg1
);
return
""
;
}
/* 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
();
}
int
standard_SunFPA_constant_p
(
x
)
rtx
x
;
{
return
(
0
);
}
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