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
4fe12442
Commit
4fe12442
authored
May 03, 2000
by
Donald Lindsay
Committed by
Don Lindsay
May 03, 2000
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
change MIPS varargs ABI in config/mips/mips.c
From-SVN: r33621
parent
f4e79153
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
298 additions
and
104 deletions
+298
-104
gcc/ChangeLog
+9
-0
gcc/config/mips/mips.c
+289
-104
No files found.
gcc/ChangeLog
View file @
4fe12442
Tue
May
2
18
:
20
:
31
2000
Donald
Lindsay
<
dlindsay
@hound
.
cygnus
.
com
>
*
config
/
mips
/
mips
.
c
(
mips_build_va_list
,
mips_va_start
,
mips_va_arg
)
:
new
ABI
for
varargs
,
across
all
MIPS
.
This
is
incompatible
because
the
va_list
(
__builtin_va_list
)
structure
is
different
,
so
a
compilation
unit
passing
a
va_list
and
a
compilation
unit
being
passed
one
,
should
both
be
compiled
with
the
same
ABI
.
(
The
old
structure
had
two
pointers
,
now
it
has
three
.)
Tue
May
2
19
:
18
:
43
2000
Jason
Eckhardt
<
jle
@cygnus
.
com
>
Tue
May
2
19
:
18
:
43
2000
Jason
Eckhardt
<
jle
@cygnus
.
com
>
*
bb
-
reorder
.
c
(
struct
reorder_block_def
)
:
Remove
members
end
,
*
bb
-
reorder
.
c
(
struct
reorder_block_def
)
:
Remove
members
end
,
...
...
gcc/config/mips/mips.c
View file @
4fe12442
...
@@ -4138,41 +4138,71 @@ function_arg_partial_nregs (cum, mode, type, named)
...
@@ -4138,41 +4138,71 @@ function_arg_partial_nregs (cum, mode, type, named)
return
0
;
return
0
;
}
}
/* Create the va_list data type. */
/* Create the va_list data type.
We keep 3 pointers, and two offsets.
Two pointers are to the overflow area, which starts at the CFA.
One of these is constant, for addressing into the GPR save area below it.
The other is advanced up the stack through the overflow region.
The third pointer is to the GPR save area. Since the FPR save area
is just below it, we can address FPR slots off this pointer.
We also keep two one-byte offsets, which are to be subtracted from the
constant pointers to yield addresses in the GPR and FPR save areas.
These are downcounted as float or non-float arguments are used,
and when they get to zero, the argument must be obtained from the
overflow region.
If TARGET_SOFT_FLOAT or TARGET_SINGLE_FLOAT, then no FPR save area exists,
and a single pointer is enough. It's started at the GPR save area,
and is advanced, period.
Note that the GPR save area is not constant size, due to optimization
in the prologue. Hence, we can't use a design with two pointers
and two offsets, although we could have designed this with two pointers
and three offsets. */
tree
tree
mips_build_va_list
()
mips_build_va_list
()
{
{
if
(
mips_abi
==
ABI_EABI
&&
!
TARGET_SOFT_FLOAT
&&
!
TARGET_SINGLE_FLOAT
)
if
(
mips_abi
==
ABI_EABI
&&
!
TARGET_SOFT_FLOAT
&&
!
TARGET_SINGLE_FLOAT
)
{
{
tree
f_
fpr
,
f_rem
,
f_gpr
,
record
;
tree
f_
ovfl
,
f_gtop
,
f_ftop
,
f_goff
,
f_foff
,
record
;
record
=
make_node
(
RECORD_TYPE
);
record
=
make_node
(
RECORD_TYPE
);
f_fpr
=
build_decl
(
FIELD_DECL
,
get_identifier
(
"__fp_regs"
),
f_ovfl
=
build_decl
(
FIELD_DECL
,
get_identifier
(
"__overflow_argptr"
),
ptr_type_node
);
f_gtop
=
build_decl
(
FIELD_DECL
,
get_identifier
(
"__gpr_top"
),
ptr_type_node
);
ptr_type_node
);
f_rem
=
build_decl
(
FIELD_DECL
,
get_identifier
(
"__fp_left"
),
f_ftop
=
build_decl
(
FIELD_DECL
,
get_identifier
(
"__fpr_top"
),
integer_type_node
);
f_gpr
=
build_decl
(
FIELD_DECL
,
get_identifier
(
"__gp_regs"
),
ptr_type_node
);
ptr_type_node
);
f_goff
=
build_decl
(
FIELD_DECL
,
get_identifier
(
"__gpr_offset"
),
unsigned_char_type_node
);
f_foff
=
build_decl
(
FIELD_DECL
,
get_identifier
(
"__fpr_offset"
),
unsigned_char_type_node
);
DECL_FIELD_CONTEXT
(
f_fpr
)
=
record
;
DECL_FIELD_CONTEXT
(
f_rem
)
=
record
;
DECL_FIELD_CONTEXT
(
f_gpr
)
=
record
;
TYPE_FIELDS
(
record
)
=
f_fpr
;
DECL_FIELD_CONTEXT
(
f_ovfl
)
=
record
;
TREE_CHAIN
(
f_fpr
)
=
f_rem
;
DECL_FIELD_CONTEXT
(
f_gtop
)
=
record
;
TREE_CHAIN
(
f_rem
)
=
f_gpr
;
DECL_FIELD_CONTEXT
(
f_ftop
)
=
record
;
DECL_FIELD_CONTEXT
(
f_goff
)
=
record
;
DECL_FIELD_CONTEXT
(
f_foff
)
=
record
;
layout_type
(
record
);
TYPE_FIELDS
(
record
)
=
f_ovfl
;
TREE_CHAIN
(
f_ovfl
)
=
f_gtop
;
TREE_CHAIN
(
f_gtop
)
=
f_ftop
;
TREE_CHAIN
(
f_ftop
)
=
f_goff
;
TREE_CHAIN
(
f_goff
)
=
f_foff
;
layout_type
(
record
);
return
record
;
return
record
;
}
}
else
else
return
ptr_type_node
;
return
ptr_type_node
;
}
}
/* Implement va_start. */
/* Implement va_start. stdarg_p is 0 if implementing
__builtin_varargs_va_start, 1 if implementing __builtin_stdarg_va_start.
Note that this routine isn't called when compiling e.g. "_vfprintf_r".
(It doesn't have "...", so it inherits the pointers of its caller.) */
void
void
mips_va_start
(
stdarg_p
,
valist
,
nextarg
)
mips_va_start
(
stdarg_p
,
valist
,
nextarg
)
...
@@ -4180,82 +4210,139 @@ mips_va_start (stdarg_p, valist, nextarg)
...
@@ -4180,82 +4210,139 @@ mips_va_start (stdarg_p, valist, nextarg)
tree
valist
;
tree
valist
;
rtx
nextarg
;
rtx
nextarg
;
{
{
int
arg_words
;
int
int_
arg_words
;
tree
t
;
tree
t
;
arg_words
=
current_function_args_info
.
arg_words
;
/* Find out how many non-float named formals */
int_arg_words
=
current_function_args_info
.
arg_words
;
if
(
mips_abi
==
ABI_EABI
)
if
(
mips_abi
==
ABI_EABI
)
{
{
int
gpr_save_area_size
;
/* Note UNITS_PER_WORD is 4 bytes or 8, depending on TARGET_64BIT. */
if
(
int_arg_words
<
8
)
/* Adjust for the prologue's economy measure */
gpr_save_area_size
=
(
8
-
int_arg_words
)
*
UNITS_PER_WORD
;
else
gpr_save_area_size
=
0
;
if
(
!
TARGET_SOFT_FLOAT
&&
!
TARGET_SINGLE_FLOAT
)
if
(
!
TARGET_SOFT_FLOAT
&&
!
TARGET_SINGLE_FLOAT
)
{
{
tree
f_
fpr
,
f_rem
,
f_gpr
,
fpr
,
rem
,
gpr
;
tree
f_
ovfl
,
f_gtop
,
f_ftop
,
f_goff
,
f_foff
;
tree
gprv
,
fprv
;
tree
ovfl
,
gtop
,
ftop
,
goff
,
foff
;
int
gpro
,
fpro
;
tree
gprv
;
int
float_formals
,
fpr_offset
,
size_excess
,
floats_passed_in_regs
;
fpro
=
(
8
-
current_function_args_info
.
fp_arg_words
)
;
int
fpr_save_offset
;
float_formals
=
current_function_args_info
.
fp_arg_words
;
/* If mips2, the number of formals is half the reported # of words */
if
(
!
TARGET_64BIT
)
if
(
!
TARGET_64BIT
)
fpro
/=
2
;
float_formals
/=
2
;
floats_passed_in_regs
=
(
TARGET_64BIT
?
8
:
4
);
f_fpr
=
TYPE_FIELDS
(
va_list_type_node
);
f_rem
=
TREE_CHAIN
(
f_fpr
);
f_ovfl
=
TYPE_FIELDS
(
va_list_type_node
);
f_gpr
=
TREE_CHAIN
(
f_rem
);
f_gtop
=
TREE_CHAIN
(
f_ovfl
);
f_ftop
=
TREE_CHAIN
(
f_gtop
);
fpr
=
build
(
COMPONENT_REF
,
TREE_TYPE
(
f_fpr
),
valist
,
f_fpr
);
f_goff
=
TREE_CHAIN
(
f_ftop
);
rem
=
build
(
COMPONENT_REF
,
TREE_TYPE
(
f_rem
),
valist
,
f_rem
);
f_foff
=
TREE_CHAIN
(
f_goff
);
gpr
=
build
(
COMPONENT_REF
,
TREE_TYPE
(
f_gpr
),
valist
,
f_gpr
);
ovfl
=
build
(
COMPONENT_REF
,
TREE_TYPE
(
f_ovfl
),
valist
,
f_ovfl
);
gtop
=
build
(
COMPONENT_REF
,
TREE_TYPE
(
f_gtop
),
valist
,
f_gtop
);
ftop
=
build
(
COMPONENT_REF
,
TREE_TYPE
(
f_ftop
),
valist
,
f_ftop
);
goff
=
build
(
COMPONENT_REF
,
TREE_TYPE
(
f_goff
),
valist
,
f_goff
);
foff
=
build
(
COMPONENT_REF
,
TREE_TYPE
(
f_foff
),
valist
,
f_foff
);
/* Emit code setting a pointer into the overflow (shared-stack) area.
If there were more than 8 non-float formals, or more than 8
float formals, then this pointer isn't to the base of the area.
In that case, it must point to where the first vararg is. */
size_excess
=
0
;
if
(
float_formals
>
floats_passed_in_regs
)
size_excess
+=
(
float_formals
-
floats_passed_in_regs
)
*
8
;
if
(
int_arg_words
>
8
)
size_excess
+=
(
int_arg_words
-
8
)
*
UNITS_PER_WORD
;
/* FIXME: for mips2, the above size_excess can be wrong. Because the
overflow stack holds mixed size items, there can be alignments,
so that an 8 byte double following a 4 byte int will be on an
8 byte boundary. This means that the above calculation should
take into account the exact sequence of floats and non-floats
which make up the excess. That calculation should be rolled
into the code which sets the current_function_args_info struct.
The above then reduces to a fetch from that struct. */
t
=
make_tree
(
TREE_TYPE
(
ovfl
),
virtual_incoming_args_rtx
);
if
(
size_excess
)
t
=
build
(
PLUS_EXPR
,
TREE_TYPE
(
ovfl
),
t
,
build_int_2
(
size_excess
,
0
));
t
=
build
(
MODIFY_EXPR
,
TREE_TYPE
(
ovfl
),
ovfl
,
t
);
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
if
(
arg_words
<
8
)
/* Emit code setting a ptr to the base of the overflow area. */
gpro
=
(
8
-
arg_words
)
*
UNITS_PER_WORD
;
t
=
make_tree
(
TREE_TYPE
(
gtop
),
virtual_incoming_args_rtx
)
;
else
t
=
build
(
MODIFY_EXPR
,
TREE_TYPE
(
gtop
),
gtop
,
t
);
gpro
=
(
stdarg_p
?
0
:
UNITS_PER_WORD
);
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
gprv
=
make_tree
(
ptr_type_node
,
nextarg
);
/* Emit code setting a pointer to the GPR save area.
if
(
gpro
!=
0
)
More precisely, a pointer to off-the-end of the FPR save area.
If mips4, this is gpr_save_area_size below the overflow area.
If mips2, also round down to an 8-byte boundary, since the FPR
save area is 8-byte aligned, and GPR is 4-byte-aligned.
Therefore there can be a 4-byte gap between the save areas. */
gprv
=
make_tree
(
TREE_TYPE
(
ftop
),
virtual_incoming_args_rtx
);
fpr_save_offset
=
gpr_save_area_size
;
if
(
!
TARGET_64BIT
)
{
{
gprv
=
build
(
PLUS_EXPR
,
ptr_type_node
,
gprv
,
if
(
fpr_save_offset
&
7
)
build_int_2
(
-
gpro
,
-
1
))
;
fpr_save_offset
+=
4
;
}
}
if
(
fpr_save_offset
)
t
=
build
(
MODIFY_EXPR
,
ptr_type_node
,
gpr
,
gprv
);
gprv
=
build
(
PLUS_EXPR
,
TREE_TYPE
(
ftop
),
gprv
,
TREE_SIDE_EFFECTS
(
t
)
=
1
;
build_int_2
(
-
fpr_save_offset
,
-
1
));
t
=
build
(
MODIFY_EXPR
,
TREE_TYPE
(
ftop
),
ftop
,
gprv
);
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
t
=
build
(
MODIFY_EXPR
,
integer_type_node
,
rem
,
/* Emit code initting an offset to the size of the GPR save area */
build_int_2
(
fpro
,
0
));
t
=
build
(
MODIFY_EXPR
,
TREE_TYPE
(
goff
),
goff
,
TREE_SIDE_EFFECTS
(
t
)
=
1
;
build_int_2
(
gpr_save_area_size
,
0
))
;
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
if
(
fpro
==
0
)
/* Emit code initting an offset from ftop to the first float
fprv
=
gprv
;
vararg. This varies in size, since any float
else
varargs are put in the FPR save area after the formals.
fprv
=
fold
(
build
(
PLUS_EXPR
,
ptr_type_node
,
gprv
,
Note it's 8 bytes/formal regardless of TARGET_64BIT.
build_int_2
(
-
(
fpro
*
8
),
-
1
)));
However, mips2 stores 4 GPRs, mips4 stores 8 GPRs.
If there are 8 or more float formals, init to zero.
if
(
!
TARGET_64BIT
)
(In fact, the formals aren't stored in the bottom of the
fprv
=
fold
(
build
(
BIT_AND_EXPR
,
ptr_type_node
,
fprv
,
FPR save area: they are elsewhere, and the size of the FPR
build_int_2
(
-
8
,
-
1
)));
save area is economized by the prologue. But this code doesn't
care. This design is unaffected by that fact.) */
t
=
build
(
MODIFY_EXPR
,
ptr_type_node
,
fpr
,
fprv
);
if
(
float_formals
>=
floats_passed_in_regs
)
TREE_SIDE_EFFECTS
(
t
)
=
1
;
fpr_offset
=
0
;
else
fpr_offset
=
(
floats_passed_in_regs
-
float_formals
)
*
8
;
t
=
build
(
MODIFY_EXPR
,
TREE_TYPE
(
foff
),
foff
,
build_int_2
(
fpr_offset
,
0
));
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
}
}
else
else
{
{
int
ofs
;
/* TARGET_SOFT_FLOAT or TARGET_SINGLE_FLOAT */
if
(
arg_words
>=
8
)
/* Everything is in the GPR save area, or in the overflow
ofs
=
(
stdarg_p
?
0
:
UNITS_PER_WORD
);
area which is contiguous with it. */
else
ofs
=
(
8
-
arg_words
)
*
UNITS_PER_WORD
;
nextarg
=
plus_constant
(
nextarg
,
-
ofs
);
int
offset
=
-
gpr_save_area_size
;
if
(
gpr_save_area_size
==
0
)
offset
=
(
stdarg_p
?
0
:
-
UNITS_PER_WORD
);
nextarg
=
plus_constant
(
nextarg
,
offset
);
std_expand_builtin_va_start
(
1
,
valist
,
nextarg
);
std_expand_builtin_va_start
(
1
,
valist
,
nextarg
);
}
}
}
}
else
else
{
{
/* not EABI */
int
ofs
;
int
ofs
;
if
(
stdarg_p
)
if
(
stdarg_p
)
...
@@ -4266,7 +4353,7 @@ mips_va_start (stdarg_p, valist, nextarg)
...
@@ -4266,7 +4353,7 @@ mips_va_start (stdarg_p, valist, nextarg)
_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32
_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32
and both iris5.h and iris6.h define _MIPS_SIM. */
and both iris5.h and iris6.h define _MIPS_SIM. */
if
(
mips_abi
==
ABI_N32
||
mips_abi
==
ABI_64
)
if
(
mips_abi
==
ABI_N32
||
mips_abi
==
ABI_64
)
ofs
=
(
arg_words
>=
8
?
-
UNITS_PER_WORD
:
0
);
ofs
=
(
int_
arg_words
>=
8
?
-
UNITS_PER_WORD
:
0
);
else
else
ofs
=
-
UNITS_PER_WORD
;
ofs
=
-
UNITS_PER_WORD
;
}
}
...
@@ -4291,9 +4378,10 @@ mips_va_arg (valist, type)
...
@@ -4291,9 +4378,10 @@ mips_va_arg (valist, type)
if
(
mips_abi
==
ABI_EABI
)
if
(
mips_abi
==
ABI_EABI
)
{
{
tree
gpr
;
int
indirect
;
int
indirect
;
rtx
lab_over
=
NULL_RTX
,
lab_false
,
r
;
rtx
r
,
lab_over
=
NULL_RTX
,
lab_false
;
tree
f_ovfl
,
f_gtop
,
f_ftop
,
f_goff
,
f_foff
;
tree
ovfl
,
gtop
,
ftop
,
goff
,
foff
;
indirect
indirect
=
function_arg_pass_by_reference
(
NULL
,
TYPE_MODE
(
type
),
type
,
0
);
=
function_arg_pass_by_reference
(
NULL
,
TYPE_MODE
(
type
),
type
,
0
);
...
@@ -4302,75 +4390,172 @@ mips_va_arg (valist, type)
...
@@ -4302,75 +4390,172 @@ mips_va_arg (valist, type)
addr_rtx
=
gen_reg_rtx
(
Pmode
);
addr_rtx
=
gen_reg_rtx
(
Pmode
);
if
(
!
TARGET_SOFT_FLOAT
&&
!
TARGET_SINGLE_FLOAT
)
if
(
TARGET_SOFT_FLOAT
||
TARGET_SINGLE_FLOAT
)
{
/* Case of all args in a merged stack. No need to check bounds,
just advance valist along the stack. */
tree
gpr
=
valist
;
if
(
!
indirect
&&
!
TARGET_64BIT
&&
TYPE_ALIGN
(
type
)
>
(
unsigned
)
BITS_PER_WORD
)
{
{
tree
f_fpr
,
f_rem
,
f_gpr
,
fpr
,
rem
;
t
=
build
(
PLUS_EXPR
,
TREE_TYPE
(
gpr
),
gpr
,
build_int_2
(
2
*
UNITS_PER_WORD
-
1
,
0
));
t
=
build
(
BIT_AND_EXPR
,
TREE_TYPE
(
t
),
t
,
build_int_2
(
-
2
*
UNITS_PER_WORD
,
-
1
));
t
=
build
(
MODIFY_EXPR
,
TREE_TYPE
(
gpr
),
gpr
,
t
);
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
}
f_fpr
=
TYPE_FIELDS
(
va_list_type_node
);
t
=
build
(
POSTINCREMENT_EXPR
,
TREE_TYPE
(
gpr
),
gpr
,
f_rem
=
TREE_CHAIN
(
f_fpr
);
size_int
(
rsize
));
f_gpr
=
TREE_CHAIN
(
f_rem
);
r
=
expand_expr
(
t
,
addr_rtx
,
Pmode
,
EXPAND_NORMAL
);
if
(
r
!=
addr_rtx
)
emit_move_insn
(
addr_rtx
,
r
);
fpr
=
build
(
COMPONENT_REF
,
TREE_TYPE
(
f_fpr
),
valist
,
f_fpr
);
/* flush the POSTINCREMENT */
rem
=
build
(
COMPONENT_REF
,
TREE_TYPE
(
f_rem
),
valist
,
f_rem
);
emit_queue
();
gpr
=
build
(
COMPONENT_REF
,
TREE_TYPE
(
f_gpr
),
valist
,
f_gpr
);
if
(
TREE_CODE
(
type
)
==
REAL_TYPE
)
if
(
indirect
)
{
r
=
gen_rtx_MEM
(
Pmode
,
addr_rtx
);
MEM_ALIAS_SET
(
r
)
=
get_varargs_alias_set
();
emit_move_insn
(
addr_rtx
,
r
);
}
else
{
{
if
(
BYTES_BIG_ENDIAN
&&
rsize
!=
size
)
addr_rtx
=
plus_constant
(
addr_rtx
,
rsize
-
size
);
}
return
addr_rtx
;
}
/* Not a simple merged stack. Need ptrs and indexes left by va_start. */
f_ovfl
=
TYPE_FIELDS
(
va_list_type_node
);
f_gtop
=
TREE_CHAIN
(
f_ovfl
);
f_ftop
=
TREE_CHAIN
(
f_gtop
);
f_goff
=
TREE_CHAIN
(
f_ftop
);
f_foff
=
TREE_CHAIN
(
f_goff
);
ovfl
=
build
(
COMPONENT_REF
,
TREE_TYPE
(
f_ovfl
),
valist
,
f_ovfl
);
gtop
=
build
(
COMPONENT_REF
,
TREE_TYPE
(
f_gtop
),
valist
,
f_gtop
);
ftop
=
build
(
COMPONENT_REF
,
TREE_TYPE
(
f_ftop
),
valist
,
f_ftop
);
goff
=
build
(
COMPONENT_REF
,
TREE_TYPE
(
f_goff
),
valist
,
f_goff
);
foff
=
build
(
COMPONENT_REF
,
TREE_TYPE
(
f_foff
),
valist
,
f_foff
);
lab_false
=
gen_label_rtx
();
lab_false
=
gen_label_rtx
();
lab_over
=
gen_label_rtx
();
lab_over
=
gen_label_rtx
();
r
=
expand_expr
(
rem
,
NULL_RTX
,
TYPE_MODE
(
TREE_TYPE
(
rem
)),
if
(
TREE_CODE
(
type
)
==
REAL_TYPE
)
EXPAND_NORMAL
);
{
emit_cmp_and_jump_insns
(
r
,
const0_rtx
,
LE
,
const1_rtx
,
GET_MODE
(
r
),
1
,
1
,
lab_false
);
t
=
build
(
PLUS_EXPR
,
TREE_TYPE
(
rem
),
rem
,
/* Emit code to branch if foff == 0. */
build_int_2
(
-
1
,
-
1
));
r
=
expand_expr
(
foff
,
NULL_RTX
,
TYPE_MODE
(
TREE_TYPE
(
foff
)),
t
=
build
(
MODIFY_EXPR
,
TREE_TYPE
(
rem
),
rem
,
t
);
EXPAND_NORMAL
);
TREE_SIDE_EFFECTS
(
t
)
=
1
;
emit_cmp_and_jump_insns
(
r
,
const0_rtx
,
EQ
,
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
const1_rtx
,
GET_MODE
(
r
),
1
,
1
,
lab_false
);
t
=
build
(
POSTINCREMENT_EXPR
,
TREE_TYPE
(
fpr
),
fpr
,
/* Emit code for addr_rtx = ftop - foff */
build_int_2
(
8
,
0
));
t
=
build
(
MINUS_EXPR
,
TREE_TYPE
(
ftop
),
ftop
,
foff
);
TREE_SIDE_EFFECTS
(
t
)
=
1
;
r
=
expand_expr
(
t
,
addr_rtx
,
Pmode
,
EXPAND_NORMAL
);
r
=
expand_expr
(
t
,
addr_rtx
,
Pmode
,
EXPAND_NORMAL
);
if
(
r
!=
addr_rtx
)
if
(
r
!=
addr_rtx
)
emit_move_insn
(
addr_rtx
,
r
);
emit_move_insn
(
addr_rtx
,
r
);
/* Ensure that the POSTINCREMENT is emitted before lab_over */
/* Emit code for foff-=8.
emit_queue
();
Advances the offset up FPR save area by one double */
t
=
build
(
MINUS_EXPR
,
TREE_TYPE
(
foff
),
foff
,
build_int_2
(
8
,
0
));
t
=
build
(
MODIFY_EXPR
,
TREE_TYPE
(
foff
),
foff
,
t
);
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
emit_queue
();
emit_jump
(
lab_over
);
emit_jump
(
lab_over
);
emit_barrier
();
emit_barrier
();
emit_label
(
lab_false
);
emit_label
(
lab_false
);
if
(
!
TARGET_64BIT
)
{
/* For mips2, the overflow area contains mixed size items.
If a 4-byte int is followed by an 8-byte float, then
natural alignment causes a 4 byte gap.
So, dynamically adjust ovfl up to a multiple of 8. */
t
=
build
(
BIT_AND_EXPR
,
TREE_TYPE
(
ovfl
),
ovfl
,
build_int_2
(
7
,
0
));
t
=
build
(
PLUS_EXPR
,
TREE_TYPE
(
ovfl
),
ovfl
,
t
);
t
=
build
(
MODIFY_EXPR
,
TREE_TYPE
(
ovfl
),
ovfl
,
t
);
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
}
}
/* Emit code for addr_rtx = the ovfl pointer into overflow area.
Regardless of mips2, postincrement the ovfl pointer by 8. */
t
=
build
(
POSTINCREMENT_EXPR
,
TREE_TYPE
(
ovfl
),
ovfl
,
size_int
(
8
));
r
=
expand_expr
(
t
,
addr_rtx
,
Pmode
,
EXPAND_NORMAL
);
if
(
r
!=
addr_rtx
)
emit_move_insn
(
addr_rtx
,
r
);
emit_queue
();
emit_label
(
lab_over
);
return
addr_rtx
;
}
}
else
else
gpr
=
valist
;
{
/* not REAL_TYPE */
int
step_size
;
if
(
!
indirect
if
(
!
TARGET_64BIT
&&
!
TARGET_64BIT
&&
TREE_CODE
(
type
)
==
INTEGER_TYPE
&&
TYPE_ALIGN
(
type
)
>
(
unsigned
)
BITS_PER_WORD
)
&&
TYPE_PRECISION
(
type
)
==
64
)
{
{
t
=
build
(
PLUS_EXPR
,
TREE_TYPE
(
gpr
),
gpr
,
/* In mips2, int takes 32 bits of the GPR save area, but
build_int_2
(
2
*
UNITS_PER_WORD
-
1
,
0
));
longlong takes an aligned 64 bits. So, emit code
t
=
build
(
BIT_AND_EXPR
,
TREE_TYPE
(
t
),
t
,
to zero the low order bits of goff, thus aligning
build_int_2
(
-
2
*
UNITS_PER_WORD
,
-
1
));
the later calculation of (gtop-goff) upwards. */
t
=
build
(
MODIFY_EXPR
,
TREE_TYPE
(
gpr
),
gpr
,
t
);
t
=
build
(
BIT_AND_EXPR
,
TREE_TYPE
(
goff
),
goff
,
TREE_SIDE_EFFECTS
(
t
)
=
1
;
build_int_2
(
-
8
,
-
1
));
t
=
build
(
MODIFY_EXPR
,
TREE_TYPE
(
goff
),
goff
,
t
);
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
}
}
t
=
build
(
POSTINCREMENT_EXPR
,
TREE_TYPE
(
gpr
),
gpr
,
size_int
(
rsize
));
/* Emit code to branch if goff == 0. */
TREE_SIDE_EFFECTS
(
t
)
=
1
;
r
=
expand_expr
(
goff
,
NULL_RTX
,
TYPE_MODE
(
TREE_TYPE
(
goff
)),
EXPAND_NORMAL
);
emit_cmp_and_jump_insns
(
r
,
const0_rtx
,
EQ
,
const1_rtx
,
GET_MODE
(
r
),
1
,
1
,
lab_false
);
/* Emit code for addr_rtx = gtop - goff. */
t
=
build
(
MINUS_EXPR
,
TREE_TYPE
(
gtop
),
gtop
,
goff
);
r
=
expand_expr
(
t
,
addr_rtx
,
Pmode
,
EXPAND_NORMAL
);
r
=
expand_expr
(
t
,
addr_rtx
,
Pmode
,
EXPAND_NORMAL
);
if
(
r
!=
addr_rtx
)
if
(
r
!=
addr_rtx
)
emit_move_insn
(
addr_rtx
,
r
);
emit_move_insn
(
addr_rtx
,
r
);
/* Ensure that the above POSTINCREMENT is emitted before lab_over */
/* Note that mips2 int is 32 bit, but mips2 longlong is 64. */
if
(
!
TARGET_64BIT
&&
TYPE_PRECISION
(
type
)
==
64
)
step_size
=
8
;
else
step_size
=
UNITS_PER_WORD
;
/* Emit code for goff = goff - step_size.
Advances the offset up GPR save area over the item. */
t
=
build
(
MINUS_EXPR
,
TREE_TYPE
(
goff
),
goff
,
build_int_2
(
step_size
,
0
));
t
=
build
(
MODIFY_EXPR
,
TREE_TYPE
(
goff
),
goff
,
t
);
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
emit_queue
();
emit_queue
();
emit_jump
(
lab_over
);
emit_barrier
();
emit_label
(
lab_false
);
/* Emit code for addr_rtx -> overflow area, postinc by step_size */
t
=
build
(
POSTINCREMENT_EXPR
,
TREE_TYPE
(
ovfl
),
ovfl
,
size_int
(
step_size
));
r
=
expand_expr
(
t
,
addr_rtx
,
Pmode
,
EXPAND_NORMAL
);
if
(
r
!=
addr_rtx
)
emit_move_insn
(
addr_rtx
,
r
);
if
(
lab_over
)
emit_queue
();
emit_label
(
lab_over
);
emit_label
(
lab_over
);
if
(
indirect
)
if
(
indirect
)
...
@@ -4384,11 +4569,12 @@ mips_va_arg (valist, type)
...
@@ -4384,11 +4569,12 @@ mips_va_arg (valist, type)
if
(
BYTES_BIG_ENDIAN
&&
rsize
!=
size
)
if
(
BYTES_BIG_ENDIAN
&&
rsize
!=
size
)
addr_rtx
=
plus_constant
(
addr_rtx
,
rsize
-
size
);
addr_rtx
=
plus_constant
(
addr_rtx
,
rsize
-
size
);
}
}
return
addr_rtx
;
return
addr_rtx
;
}
}
}
else
else
{
{
/* Not EABI. */
int
align
;
int
align
;
/* ??? The original va-mips.h did always align, despite the fact
/* ??? The original va-mips.h did always align, despite the fact
...
@@ -4406,7 +4592,6 @@ mips_va_arg (valist, type)
...
@@ -4406,7 +4592,6 @@ mips_va_arg (valist, type)
build_int_2
(
align
-
1
,
0
));
build_int_2
(
align
-
1
,
0
));
t
=
build
(
BIT_AND_EXPR
,
TREE_TYPE
(
t
),
t
,
build_int_2
(
-
align
,
-
1
));
t
=
build
(
BIT_AND_EXPR
,
TREE_TYPE
(
t
),
t
,
build_int_2
(
-
align
,
-
1
));
t
=
build
(
MODIFY_EXPR
,
TREE_TYPE
(
valist
),
valist
,
t
);
t
=
build
(
MODIFY_EXPR
,
TREE_TYPE
(
valist
),
valist
,
t
);
TREE_SIDE_EFFECTS
(
t
)
=
1
;
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
expand_expr
(
t
,
const0_rtx
,
VOIDmode
,
EXPAND_NORMAL
);
/* Everything past the alignment is standard. */
/* Everything past the alignment is standard. */
...
...
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