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
3ce15347
Commit
3ce15347
authored
Oct 01, 1998
by
Nick Clifton
Committed by
Nick Clifton
Oct 01, 1998
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add support for v850 special data areas.
From-SVN: r22716
parent
e6e86071
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
1091 additions
and
129 deletions
+1091
-129
gcc/ChangeLog
+5
-0
gcc/config/v850/v850.c
+825
-57
gcc/config/v850/v850.h
+261
-72
No files found.
gcc/ChangeLog
View file @
3ce15347
...
...
@@ -13,6 +13,11 @@ Thu Oct 1 15:56:01 1998 Gavin Romig-Koch <gavin@cygnus.com>
Thu
Oct
1
10
:
42
:
27
1998
Nick
Clifton
<
nickc
@cygnus
.
com
>
*
config
/
v850
/
v850
.
c
:
Add
function
prototypes
.
Add
support
for
v850
special
data
areas
.
*
config
/
v850
/
v850
.
h
:
Add
support
for
v850
special
data
areas
.
*
c
-
pragma
.
c
:
Add
support
for
HANDLE_PRAGMA_PACK
and
HANDLE_PRAGMA_PACK_PUSH_POP
.
(
push_alignment
)
:
New
function
:
Cache
an
alignment
requested
...
...
gcc/config/v850/v850.c
View file @
3ce15347
/* Subroutines for insn-output.c for NEC V850 series
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
Copyright (C) 1996, 1997
, 1998
Free Software Foundation, Inc.
Contributed by Jeff Law (law@cygnus.com).
This file is part of GNU CC.
...
...
@@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA. */
#include <stdio.h>
#include <ctype.h>
#include "config.h"
#include "tree.h"
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
...
...
@@ -34,8 +35,64 @@ Boston, MA 02111-1307, USA. */
#include "flags.h"
#include "recog.h"
#include "expr.h"
#include "tree.h"
#include "obstack.h"
#include "toplev.h"
#ifndef streq
#define streq(a,b) (strcmp (a, b) == 0)
#endif
/* Function prototypes that cannot exist in v850.h due to dependency
compilcations. */
extern
rtx
function_arg
PROTO
((
CUMULATIVE_ARGS
*
,
enum
machine_mode
,
tree
,
int
));
extern
int
function_arg_partial_nregs
PROTO
((
CUMULATIVE_ARGS
*
,
enum
machine_mode
,
tree
,
int
));
extern
void
asm_file_start
PROTO
((
FILE
*
));
extern
void
print_operand
PROTO
((
FILE
*
,
rtx
,
int
));
extern
void
print_operand_address
PROTO
((
FILE
*
,
rtx
));
extern
void
v850_output_aligned_bss
PROTO
((
FILE
*
,
tree
,
char
*
,
int
,
int
));
extern
void
v850_output_common
PROTO
((
FILE
*
,
tree
,
char
*
,
int
,
int
));
extern
void
v850_output_local
PROTO
((
FILE
*
,
tree
,
char
*
,
int
,
int
));
extern
int
const_costs
PROTO
((
rtx
,
enum
rtx_code
));
extern
char
*
output_move_double
PROTO
((
rtx
*
));
extern
char
*
output_move_single
PROTO
((
rtx
*
));
extern
int
ep_memory_operand
PROTO
((
rtx
,
enum
machine_mode
,
int
));
extern
int
reg_or_0_operand
PROTO
((
rtx
,
enum
machine_mode
));
extern
int
reg_or_int5_operand
PROTO
((
rtx
,
enum
machine_mode
));
extern
int
call_address_operand
PROTO
((
rtx
,
enum
machine_mode
));
extern
int
movsi_source_operand
PROTO
((
rtx
,
enum
machine_mode
));
extern
int
power_of_two_operand
PROTO
((
rtx
,
enum
machine_mode
));
extern
int
not_power_of_two_operand
PROTO
((
rtx
,
enum
machine_mode
));
extern
int
special_symbolref_operand
PROTO
((
rtx
,
enum
machine_mode
));
extern
void
v850_reorg
PROTO
((
rtx
));
extern
void
notice_update_cc
PROTO
((
rtx
,
rtx
));
extern
int
v850_valid_machine_decl_attribute
PROTO
((
tree
,
tree
,
tree
));
extern
int
v850_interrupt_function_p
PROTO
((
tree
));
extern
int
pattern_is_ok_for_prologue
PROTO
((
rtx
,
enum
machine_mode
));
extern
int
pattern_is_ok_for_epilogue
PROTO
((
rtx
,
enum
machine_mode
));
extern
int
register_is_ok_for_epilogue
PROTO
((
rtx
,
enum
machine_mode
));
extern
char
*
construct_save_jarl
PROTO
((
rtx
));
extern
char
*
construct_restore_jr
PROTO
((
rtx
));
extern
void
v850_encode_data_area
PROTO
((
tree
));
extern
void
v850_set_default_decl_attr
PROTO
((
tree
));
/* Function prototypes for stupid compilers: */
static
void
const_double_split
PROTO
((
rtx
,
HOST_WIDE_INT
*
,
HOST_WIDE_INT
*
));
static
int
const_costs_int
PROTO
((
HOST_WIDE_INT
,
int
));
static
void
substitute_ep_register
PROTO
((
rtx
,
rtx
,
int
,
int
,
rtx
*
,
rtx
*
));
static
int
push_data_area
PROTO
((
v850_data_area
));
static
int
pop_data_area
PROTO
((
v850_data_area
));
static
int
parse_ghs_pragma_token
PROTO
((
char
*
));
static
int
ep_memory_offset
PROTO
((
enum
machine_mode
,
int
));
static
int
mark_current_function_as_interrupt
PROTO
((
void
));
static
void
v850_set_data_area
PROTO
((
tree
,
v850_data_area
));
/* True if the current function has anonymous arguments. */
int
current_function_anonymous_args
;
...
...
@@ -70,7 +127,7 @@ void
override_options
()
{
int
i
;
extern
int
atoi
(
);
extern
int
atoi
PROTO
((
const
char
*
)
);
/* Parse -m{s,t,z}da=nnn switches */
for
(
i
=
0
;
i
<
(
int
)
SMALL_MEMORY_max
;
i
++
)
...
...
@@ -235,6 +292,9 @@ const_double_split (x, p_high, p_low)
*
p_high
=
CONST_DOUBLE_HIGH
(
x
);
*
p_low
=
CONST_DOUBLE_LOW
(
x
);
return
;
default
:
break
;
}
}
...
...
@@ -437,13 +497,16 @@ print_operand (file, x, code)
case
'R'
:
/* 2nd word of a double. */
switch
(
GET_CODE
(
x
))
{
case
REG
:
fprintf
(
file
,
reg_names
[
REGNO
(
x
)
+
1
]);
break
;
case
MEM
:
print_operand_address
(
file
,
XEXP
(
adj_offsettable_operand
(
x
,
4
),
0
));
break
;
case
REG
:
fprintf
(
file
,
reg_names
[
REGNO
(
x
)
+
1
]);
break
;
case
MEM
:
print_operand_address
(
file
,
XEXP
(
adj_offsettable_operand
(
x
,
4
),
0
));
break
;
default
:
break
;
}
break
;
case
'S'
:
...
...
@@ -724,7 +787,8 @@ output_move_single (operands)
}
/* Return appropriate code to load up an 8 byte integer or floating point value */
/* Return appropriate code to load up an 8 byte integer or
floating point value */
char
*
output_move_double
(
operands
)
...
...
@@ -805,10 +869,10 @@ output_move_double (operands)
/* Return maximum offset supported for a short EP memory reference of mode
MODE and signedness UNSIGNEDP. */
int
static
int
ep_memory_offset
(
mode
,
unsignedp
)
enum
machine_mode
mode
;
int
unsignedp
;
int
ATTRIBUTE_UNUSED
unsignedp
;
{
int
max_offset
=
0
;
...
...
@@ -826,6 +890,9 @@ ep_memory_offset (mode, unsignedp)
case
SFmode
:
max_offset
=
(
1
<<
8
);
break
;
default
:
break
;
}
return
max_offset
;
...
...
@@ -920,7 +987,7 @@ reg_or_int5_operand (op, mode)
int
call_address_operand
(
op
,
mode
)
rtx
op
;
enum
machine_mode
mode
;
enum
machine_mode
ATTRIBUTE_UNUSED
mode
;
{
/* Only registers are valid call operands if TARGET_LONG_CALLS. */
if
(
TARGET_LONG_CALLS
)
...
...
@@ -931,7 +998,7 @@ call_address_operand (op, mode)
int
special_symbolref_operand
(
op
,
mode
)
rtx
op
;
enum
machine_mode
mode
;
enum
machine_mode
ATTRIBUTE_UNUSED
mode
;
{
if
(
GET_CODE
(
op
)
==
SYMBOL_REF
)
return
ENCODED_NAME_P
(
XSTR
(
op
,
0
));
...
...
@@ -968,7 +1035,7 @@ movsi_source_operand (op, mode)
int
power_of_two_operand
(
op
,
mode
)
rtx
op
;
enum
machine_mode
mode
;
enum
machine_mode
ATTRIBUTE_UNUSED
mode
;
{
if
(
GET_CODE
(
op
)
!=
CONST_INT
)
return
0
;
...
...
@@ -1017,7 +1084,6 @@ substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
{
rtx
reg
=
gen_rtx
(
REG
,
Pmode
,
regno
);
rtx
insn
;
int
i
;
if
(
!*
p_r1
)
{
...
...
@@ -1027,7 +1093,8 @@ substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
}
if
(
TARGET_DEBUG
)
fprintf
(
stderr
,
"Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, ending at %d
\n
"
,
fprintf
(
stderr
,
"\
Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, ending at %d
\n
"
,
2
*
(
uses
-
3
),
uses
,
reg_names
[
regno
],
IDENTIFIER_POINTER
(
DECL_NAME
(
current_function_decl
)),
INSN_UID
(
first_insn
),
INSN_UID
(
last_insn
));
...
...
@@ -1073,7 +1140,7 @@ substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
&&
GET_CODE
(
XEXP
(
addr
,
0
))
==
REG
&&
REGNO
(
XEXP
(
addr
,
0
))
==
regno
&&
GET_CODE
(
XEXP
(
addr
,
1
))
==
CONST_INT
&&
((
(
unsigned
)
INTVAL
(
XEXP
(
addr
,
1
)))
&&
((
INTVAL
(
XEXP
(
addr
,
1
)))
<
ep_memory_offset
(
GET_MODE
(
*
p_mem
),
unsignedp
)))
*
p_mem
=
change_address
(
*
p_mem
,
VOIDmode
,
...
...
@@ -1110,11 +1177,13 @@ substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
void
v850_reorg
(
start_insn
)
rtx
start_insn
;
{
struct
{
struct
{
int
uses
;
rtx
first_insn
;
rtx
last_insn
;
}
regs
[
FIRST_PSEUDO_REGISTER
];
}
regs
[
FIRST_PSEUDO_REGISTER
];
int
i
;
int
use_ep
=
FALSE
;
...
...
@@ -1215,7 +1284,7 @@ void v850_reorg (start_insn)
else
if
(
GET_CODE
(
addr
)
==
PLUS
&&
GET_CODE
(
XEXP
(
addr
,
0
))
==
REG
&&
GET_CODE
(
XEXP
(
addr
,
1
))
==
CONST_INT
&&
((
(
unsigned
)
INTVAL
(
XEXP
(
addr
,
1
)))
&&
((
INTVAL
(
XEXP
(
addr
,
1
)))
<
ep_memory_offset
(
GET_MODE
(
mem
),
unsignedp
)))
{
short_p
=
TRUE
;
...
...
@@ -1274,7 +1343,8 @@ void v850_reorg (start_insn)
{
substitute_ep_register
(
regs
[
max_regno
].
first_insn
,
regs
[
max_regno
].
last_insn
,
max_uses
,
max_regno
,
&
r1
,
&
ep
);
max_uses
,
max_regno
,
&
r1
,
&
ep
);
/* Since we made a substitution, zap all remembered
registers. */
...
...
@@ -1397,8 +1467,8 @@ expand_prologue ()
unsigned
int
init_stack_alloc
=
0
;
rtx
save_regs
[
32
];
rtx
save_all
;
int
num_save
;
int
default_stack
;
unsigned
int
num_save
;
unsigned
int
default_stack
;
int
code
;
int
interrupt_handler
=
v850_interrupt_function_p
(
current_function_decl
);
long
reg_saved
=
0
;
...
...
@@ -1476,7 +1546,8 @@ expand_prologue ()
stack space is allocated. */
if
(
save_func_len
<
save_normal_len
)
{
save_all
=
gen_rtx
(
PARALLEL
,
VOIDmode
,
rtvec_alloc
(
num_save
+
(
TARGET_V850
?
2
:
1
)));
save_all
=
gen_rtx
(
PARALLEL
,
VOIDmode
,
rtvec_alloc
(
num_save
+
(
TARGET_V850
?
2
:
1
)));
XVECEXP
(
save_all
,
0
,
0
)
=
gen_rtx
(
SET
,
VOIDmode
,
stack_pointer_rtx
,
gen_rtx
(
PLUS
,
Pmode
,
...
...
@@ -1508,7 +1579,8 @@ expand_prologue ()
actual_fsize
-=
alloc_stack
;
if
(
TARGET_DEBUG
)
fprintf
(
stderr
,
"Saved %d bytes via prologue function (%d vs. %d) for function %s
\n
"
,
fprintf
(
stderr
,
"\
Saved %d bytes via prologue function (%d vs. %d) for function %s
\n
"
,
save_normal_len
-
save_func_len
,
save_normal_len
,
save_func_len
,
IDENTIFIER_POINTER
(
DECL_NAME
(
current_function_decl
)));
...
...
@@ -1518,8 +1590,8 @@ expand_prologue ()
}
}
/* If no prolog save function is available, store the registers the old
fashioned
way (one by one). */
/* If no prolog save function is available, store the registers the old
fashioned
way (one by one). */
if
(
!
save_all
)
{
/* Special case interrupt functions that save all registers for a call. */
...
...
@@ -1600,8 +1672,8 @@ expand_epilogue ()
unsigned
int
init_stack_free
=
0
;
rtx
restore_regs
[
32
];
rtx
restore_all
;
int
num_restore
;
int
default_stack
;
unsigned
int
num_restore
;
unsigned
int
default_stack
;
int
code
;
int
interrupt_handler
=
v850_interrupt_function_p
(
current_function_decl
);
...
...
@@ -1637,7 +1709,8 @@ expand_epilogue ()
/* See if we have an insn that restores the particular registers we
want to. */
restore_all
=
NULL_RTX
;
if
(
TARGET_PROLOG_FUNCTION
&&
num_restore
>
0
&&
actual_fsize
>=
default_stack
if
(
TARGET_PROLOG_FUNCTION
&&
num_restore
>
0
&&
actual_fsize
>=
default_stack
&&
!
interrupt_handler
)
{
int
alloc_stack
=
(
4
*
num_restore
)
+
default_stack
;
...
...
@@ -1675,7 +1748,8 @@ expand_epilogue ()
=
gen_rtx
(
SET
,
VOIDmode
,
restore_regs
[
i
],
gen_rtx
(
MEM
,
Pmode
,
plus_constant
(
stack_pointer_rtx
,
offset
)));
plus_constant
(
stack_pointer_rtx
,
offset
)));
offset
-=
4
;
}
...
...
@@ -1705,7 +1779,8 @@ expand_epilogue ()
INSN_CODE
(
insn
)
=
code
;
if
(
TARGET_DEBUG
)
fprintf
(
stderr
,
"Saved %d bytes via epilogue function (%d vs. %d) in function %s
\n
"
,
fprintf
(
stderr
,
"\
Saved %d bytes via epilogue function (%d vs. %d) in function %s
\n
"
,
restore_normal_len
-
restore_func_len
,
restore_normal_len
,
restore_func_len
,
IDENTIFIER_POINTER
(
DECL_NAME
(
current_function_decl
)));
...
...
@@ -1727,9 +1802,13 @@ expand_epilogue ()
/* Deallocate the rest of the stack if it is > 32K or if extra stack
was allocated for an interrupt handler that makes a call. */
if
(
actual_fsize
>
init_stack_free
||
(
interrupt_handler
&&
actual_fsize
))
if
(
actual_fsize
>
init_stack_free
||
(
interrupt_handler
&&
actual_fsize
))
{
int
diff
=
actual_fsize
-
((
interrupt_handler
)
?
0
:
init_stack_free
);
int
diff
;
diff
=
actual_fsize
-
((
interrupt_handler
)
?
0
:
init_stack_free
);
if
(
CONST_OK_FOR_K
(
diff
))
emit_insn
(
gen_addsi3
(
stack_pointer_rtx
,
stack_pointer_rtx
,
...
...
@@ -1843,24 +1922,59 @@ notice_update_cc (body, insn)
break
;
}
}
/* Return nonzero if ATTR is a valid attribute for DECL.
ATTRIBUTES are any existing attributes and ARGS are the arguments
supplied with ATTR.
/* Retrieve the data area that has been chosen for the given decl. */
Supported attributes:
v850_data_area
v850_get_data_area
(
decl
)
tree
decl
;
{
if
(
lookup_attribute
(
"sda"
,
DECL_MACHINE_ATTRIBUTES
(
decl
))
!=
NULL_TREE
)
return
DATA_AREA_SDA
;
if
(
lookup_attribute
(
"tda"
,
DECL_MACHINE_ATTRIBUTES
(
decl
))
!=
NULL_TREE
)
return
DATA_AREA_TDA
;
if
(
lookup_attribute
(
"zda"
,
DECL_MACHINE_ATTRIBUTES
(
decl
))
!=
NULL_TREE
)
return
DATA_AREA_ZDA
;
return
DATA_AREA_NORMAL
;
}
interrupt_handler or interrupt: output a prologue and epilogue suitable
for an interrupt handler. */
/* Store the indicated data area in the decl's attributes. */
static
void
v850_set_data_area
(
decl
,
data_area
)
tree
decl
;
v850_data_area
data_area
;
{
tree
name
;
switch
(
data_area
)
{
case
DATA_AREA_SDA
:
name
=
get_identifier
(
"sda"
);
break
;
case
DATA_AREA_TDA
:
name
=
get_identifier
(
"tda"
);
break
;
case
DATA_AREA_ZDA
:
name
=
get_identifier
(
"zda"
);
break
;
default
:
return
;
}
DECL_MACHINE_ATTRIBUTES
(
decl
)
=
tree_cons
(
name
,
NULL
,
DECL_MACHINE_ATTRIBUTES
(
decl
));
}
/* Return nonzero if ATTR is a valid attribute for DECL.
ARGS are the arguments supplied with ATTR. */
int
v850_valid_machine_decl_attribute
(
decl
,
attr
ibutes
,
attr
,
args
)
v850_valid_machine_decl_attribute
(
decl
,
attr
,
args
)
tree
decl
;
tree
attributes
;
tree
attr
;
tree
args
;
{
v850_data_area
data_area
;
v850_data_area
area
;
if
(
args
!=
NULL_TREE
)
return
0
;
...
...
@@ -1868,6 +1982,37 @@ v850_valid_machine_decl_attribute (decl, attributes, attr, args)
||
is_attribute_p
(
"interrupt"
,
attr
))
return
TREE_CODE
(
decl
)
==
FUNCTION_DECL
;
/* Implement data area attribute. */
if
(
is_attribute_p
(
"sda"
,
attr
))
data_area
=
DATA_AREA_SDA
;
else
if
(
is_attribute_p
(
"tda"
,
attr
))
data_area
=
DATA_AREA_TDA
;
else
if
(
is_attribute_p
(
"zda"
,
attr
))
data_area
=
DATA_AREA_ZDA
;
else
return
0
;
switch
(
TREE_CODE
(
decl
))
{
case
VAR_DECL
:
if
(
current_function_decl
!=
NULL_TREE
)
error_with_decl
(
decl
,
"\
a data area attribute cannot be specified for local variables"
);
/* Drop through. */
case
FUNCTION_DECL
:
area
=
v850_get_data_area
(
decl
);
if
(
area
!=
DATA_AREA_NORMAL
&&
data_area
!=
area
)
error_with_decl
(
decl
,
"\
data area of '%s' conflicts with previous declaration"
);
return
1
;
default
:
break
;
}
return
0
;
}
...
...
@@ -1907,18 +2052,67 @@ v850_interrupt_function_p (func)
}
extern
struct
obstack
*
saveable_obstack
;
extern
struct
obstack
*
saveable_obstack
;
void
v850_encode_data_area
(
decl
)
tree
decl
;
{
char
*
str
=
XSTR
(
XEXP
(
DECL_RTL
(
decl
),
0
),
0
);
int
len
=
strlen
(
str
);
char
*
newstr
;
char
*
str
=
XSTR
(
XEXP
(
DECL_RTL
(
decl
),
0
),
0
);
int
len
=
strlen
(
str
);
char
*
newstr
;
/* Map explict sections into the appropriate attribute */
if
(
v850_get_data_area
(
decl
)
==
DATA_AREA_NORMAL
)
{
if
(
DECL_SECTION_NAME
(
decl
))
{
char
*
name
=
TREE_STRING_POINTER
(
DECL_SECTION_NAME
(
decl
));
if
(
streq
(
name
,
".zdata"
)
||
streq
(
name
,
".zbss"
))
v850_set_data_area
(
decl
,
DATA_AREA_ZDA
);
else
if
(
streq
(
name
,
".sdata"
)
||
streq
(
name
,
".sbss"
))
v850_set_data_area
(
decl
,
DATA_AREA_SDA
);
else
if
(
streq
(
name
,
".tdata"
))
v850_set_data_area
(
decl
,
DATA_AREA_TDA
);
}
/* If no attribute, support -m{zda,sda,tda}=n */
else
{
int
size
=
int_size_in_bytes
(
TREE_TYPE
(
decl
));
if
(
size
<=
0
)
;
else
if
(
size
<=
small_memory
[(
int
)
SMALL_MEMORY_TDA
].
max
)
v850_set_data_area
(
decl
,
DATA_AREA_TDA
);
else
if
(
size
<=
small_memory
[(
int
)
SMALL_MEMORY_SDA
].
max
)
v850_set_data_area
(
decl
,
DATA_AREA_SDA
);
else
if
(
size
<=
small_memory
[(
int
)
SMALL_MEMORY_ZDA
].
max
)
v850_set_data_area
(
decl
,
DATA_AREA_ZDA
);
}
if
(
v850_get_data_area
(
decl
)
==
DATA_AREA_NORMAL
)
return
;
}
newstr
=
obstack_alloc
(
saveable_obstack
,
len
+
2
);
/* In the Cygnus sources we actually do something; this is just
here to make merges easier. */
return
;
strcpy
(
newstr
+
1
,
str
);
switch
(
v850_get_data_area
(
decl
))
{
case
DATA_AREA_ZDA
:
*
newstr
=
ZDA_NAME_FLAG_CHAR
;
break
;
case
DATA_AREA_TDA
:
*
newstr
=
TDA_NAME_FLAG_CHAR
;
break
;
case
DATA_AREA_SDA
:
*
newstr
=
SDA_NAME_FLAG_CHAR
;
break
;
default
:
abort
();
}
XSTR
(
XEXP
(
DECL_RTL
(
decl
),
0
),
0
)
=
newstr
;
}
/* Return true if the given RTX is a register which can be restored
...
...
@@ -1926,7 +2120,7 @@ v850_encode_data_area (decl)
int
register_is_ok_for_epilogue
(
op
,
mode
)
rtx
op
;
enum
machine_mode
mode
;
enum
machine_mode
ATTRIBUTE_UNUSED
mode
;
{
/* The save/restore routines can only cope with registers 2, and 20 - 31 */
return
(
GET_CODE
(
op
)
==
REG
)
...
...
@@ -1939,7 +2133,7 @@ register_is_ok_for_epilogue (op, mode)
int
pattern_is_ok_for_epilogue
(
op
,
mode
)
rtx
op
;
enum
machine_mode
mode
;
enum
machine_mode
ATTRIBUTE_UNUSED
mode
;
{
int
count
=
XVECLEN
(
op
,
0
);
int
i
;
...
...
@@ -2085,7 +2279,7 @@ construct_restore_jr (op)
/* Note, it is possible to have gaps in the register mask.
We ignore this here, and generate a JR anyway. We will
be popping more registers tha
t
n is strictly necessary, but
be popping more registers than is strictly necessary, but
it does save code space. */
if
(
first
==
last
)
...
...
@@ -2102,7 +2296,7 @@ construct_restore_jr (op)
int
pattern_is_ok_for_prologue
(
op
,
mode
)
rtx
op
;
enum
machine_mode
mode
;
enum
machine_mode
ATTRIBUTE_UNUSED
mode
;
{
int
count
=
XVECLEN
(
op
,
0
);
int
i
;
...
...
@@ -2271,7 +2465,7 @@ construct_save_jarl (op)
/* Note, it is possible to have gaps in the register mask.
We ignore this here, and generate a JARL anyway. We will
be pushing more registers tha
t
n is strictly necessary, but
be pushing more registers than is strictly necessary, but
it does save code space. */
if
(
first
==
last
)
...
...
@@ -2283,3 +2477,577 @@ construct_save_jarl (op)
return
buff
;
}
extern
tree
last_assemble_variable_decl
;
extern
int
size_directive_output
;
/* A version of asm_output_aligned_bss() that copes with the special
data areas of the v850. */
void
v850_output_aligned_bss
(
file
,
decl
,
name
,
size
,
align
)
FILE
*
file
;
tree
decl
;
char
*
name
;
int
size
;
int
align
;
{
ASM_GLOBALIZE_LABEL
(
file
,
name
);
switch
(
v850_get_data_area
(
decl
))
{
case
DATA_AREA_ZDA
:
zbss_section
();
break
;
case
DATA_AREA_SDA
:
sbss_section
();
break
;
case
DATA_AREA_TDA
:
tdata_section
();
default
:
bss_section
();
break
;
}
ASM_OUTPUT_ALIGN
(
file
,
floor_log2
(
align
/
BITS_PER_UNIT
));
#ifdef ASM_DECLARE_OBJECT_NAME
last_assemble_variable_decl
=
decl
;
ASM_DECLARE_OBJECT_NAME
(
file
,
name
,
decl
);
#else
/* Standard thing is just output label for the object. */
ASM_OUTPUT_LABEL
(
file
,
name
);
#endif
/* ASM_DECLARE_OBJECT_NAME */
ASM_OUTPUT_SKIP
(
file
,
size
?
size
:
1
);
}
/* Called via the macro ASM_OUTPUT_DECL_COMMON */
void
v850_output_common
(
file
,
decl
,
name
,
size
,
align
)
FILE
*
file
;
tree
decl
;
char
*
name
;
int
size
;
int
align
;
{
if
(
decl
==
NULL_TREE
)
{
fprintf
(
file
,
"
\t
%s
\t
"
,
COMMON_ASM_OP
);
}
else
{
switch
(
v850_get_data_area
(
decl
))
{
case
DATA_AREA_ZDA
:
fprintf
(
file
,
"
\t
%s
\t
"
,
ZCOMMON_ASM_OP
);
break
;
case
DATA_AREA_SDA
:
fprintf
(
file
,
"
\t
%s
\t
"
,
SCOMMON_ASM_OP
);
break
;
case
DATA_AREA_TDA
:
fprintf
(
file
,
"
\t
%s
\t
"
,
TCOMMON_ASM_OP
);
break
;
default
:
fprintf
(
file
,
"
\t
%s
\t
"
,
COMMON_ASM_OP
);
break
;
}
}
assemble_name
(
file
,
name
);
fprintf
(
file
,
",%u,%u
\n
"
,
size
,
align
/
BITS_PER_UNIT
);
}
/* Called via the macro ASM_OUTPUT_DECL_LOCAL */
void
v850_output_local
(
file
,
decl
,
name
,
size
,
align
)
FILE
*
file
;
tree
decl
;
char
*
name
;
int
size
;
int
align
;
{
fprintf
(
file
,
"
\t
%s
\t
"
,
LOCAL_ASM_OP
);
assemble_name
(
file
,
name
);
fprintf
(
file
,
"
\n
"
);
ASM_OUTPUT_ALIGNED_DECL_COMMON
(
file
,
decl
,
name
,
size
,
align
);
}
/* The following code is for handling pragmas supported by the
v850 compiler produced by Green Hills Software. This is at
the specific request of a customer. */
/* Track the current data area set by the data area pragma (which
can be nested). Tested by check_default_data_area. */
typedef
struct
data_area_stack_element
{
struct
data_area_stack_element
*
prev
;
v850_data_area
data_area
;
/* current default data area. */
}
data_area_stack_element
;
static
data_area_stack_element
*
data_area_stack
=
NULL
;
/* Names of the various data areas used on the v850. */
static
tree
GHS_default_section_names
[(
int
)
COUNT_OF_GHS_SECTION_KINDS
];
static
tree
GHS_current_section_names
[(
int
)
COUNT_OF_GHS_SECTION_KINDS
];
/* Push a data area onto the stack. */
static
int
push_data_area
(
data_area
)
v850_data_area
data_area
;
{
data_area_stack_element
*
elem
;
elem
=
(
data_area_stack_element
*
)
xmalloc
(
sizeof
(
*
elem
));
if
(
elem
==
NULL
)
return
0
;
elem
->
prev
=
data_area_stack
;
elem
->
data_area
=
data_area
;
data_area_stack
=
elem
;
return
1
;
}
/* Remove a data area from the stack. */
static
int
pop_data_area
(
data_area
)
v850_data_area
data_area
;
{
if
(
data_area_stack
==
NULL
)
warning
(
"#pragma GHS endXXXX found without previous startXXX"
);
else
if
(
data_area
!=
data_area_stack
->
data_area
)
warning
(
"#pragma GHS endXXX does not match previous startXXX"
);
else
{
data_area_stack_element
*
elem
;
elem
=
data_area_stack
;
data_area_stack
=
data_area_stack
->
prev
;
free
(
elem
);
return
1
;
}
return
0
;
}
/* Set the machine specific 'interrupt' attribute on the current function. */
static
int
mark_current_function_as_interrupt
()
{
tree
name
;
if
(
current_function_decl
==
NULL_TREE
)
{
warning
(
"Cannot set interrupt attribute: no current function"
);
return
0
;
}
name
=
get_identifier
(
"interrupt"
);
if
(
name
==
NULL_TREE
||
TREE_CODE
(
name
)
!=
IDENTIFIER_NODE
)
{
warning
(
"Cannot set interrupt attribute: no such identifier"
);
return
0
;
}
return
valid_machine_attribute
(
name
,
NULL_TREE
,
current_function_decl
,
NULL_TREE
);
}
/* Parse STRING as part of a GHS pragma.
Returns 0 if the pragma has been parsed and there was a problem,
non-zero in all other cases. */
static
int
parse_ghs_pragma_token
(
string
)
char
*
string
;
{
static
enum
v850_pragma_state
state
=
V850_PS_START
;
static
enum
v850_pragma_type
type
=
V850_PT_UNKNOWN
;
static
v850_data_area
data_area
=
DATA_AREA_NORMAL
;
static
char
*
data_area_name
;
static
enum
GHS_section_kind
GHS_section_kind
=
GHS_SECTION_KIND_DEFAULT
;
/* If the string is NULL then we have reached the end of the
#pragma construct. Make sure that we are in an end state, and
then implement the pragma's directive. */
if
(
string
==
NULL
)
{
int
ret_val
=
1
;
if
(
state
!=
V850_PS_SHOULD_BE_DONE
&&
state
!=
V850_PS_MAYBE_COMMA
&&
state
!=
V850_PS_MAYBE_SECTION_NAME
)
{
if
(
state
!=
V850_PS_BAD
)
warning
(
"Incomplete #pragma ghs"
);
ret_val
=
0
;
}
else
switch
(
type
)
{
case
V850_PT_UNKNOWN
:
warning
(
"Nothing follows #pragma ghs"
);
ret_val
=
0
;
break
;
case
V850_PT_INTERRUPT
:
ret_val
=
mark_current_function_as_interrupt
();
break
;
case
V850_PT_SECTION
:
/* If a section kind has not been specified, then reset
all section names back to their defaults. */
if
(
GHS_section_kind
==
GHS_SECTION_KIND_DEFAULT
)
{
int
i
;
for
(
i
=
COUNT_OF_GHS_SECTION_KINDS
;
i
--
;)
GHS_current_section_names
[
i
]
=
NULL
;
}
/* If a section has been specified, then this will be handled
by check_default_section_name (). */
break
;
case
V850_PT_START_SECTION
:
ret_val
=
push_data_area
(
data_area
);
break
;
case
V850_PT_END_SECTION
:
ret_val
=
pop_data_area
(
data_area
);
break
;
}
state
=
V850_PS_START
;
type
=
V850_PT_UNKNOWN
;
return
ret_val
;
}
switch
(
state
)
{
case
V850_PS_START
:
data_area
=
DATA_AREA_NORMAL
;
data_area_name
=
NULL
;
if
(
streq
(
string
,
"interrupt"
))
{
type
=
V850_PT_INTERRUPT
;
state
=
V850_PS_SHOULD_BE_DONE
;
}
else
if
(
streq
(
string
,
"section"
))
{
type
=
V850_PT_SECTION
;
state
=
V850_PS_MAYBE_SECTION_NAME
;
GHS_section_kind
=
GHS_SECTION_KIND_DEFAULT
;
}
else
if
(
streq
(
string
,
"starttda"
))
{
type
=
V850_PT_START_SECTION
;
state
=
V850_PS_SHOULD_BE_DONE
;
data_area
=
DATA_AREA_TDA
;
}
else
if
(
streq
(
string
,
"endtda"
))
{
type
=
V850_PT_END_SECTION
;
state
=
V850_PS_SHOULD_BE_DONE
;
data_area
=
DATA_AREA_TDA
;
}
else
if
(
streq
(
string
,
"startsda"
))
{
type
=
V850_PT_START_SECTION
;
state
=
V850_PS_SHOULD_BE_DONE
;
data_area
=
DATA_AREA_SDA
;
}
else
if
(
streq
(
string
,
"endsda"
))
{
type
=
V850_PT_END_SECTION
;
state
=
V850_PS_SHOULD_BE_DONE
;
data_area
=
DATA_AREA_SDA
;
}
else
if
(
streq
(
string
,
"startzda"
))
{
type
=
V850_PT_START_SECTION
;
state
=
V850_PS_SHOULD_BE_DONE
;
data_area
=
DATA_AREA_ZDA
;
}
else
if
(
streq
(
string
,
"endzda"
))
{
type
=
V850_PT_END_SECTION
;
state
=
V850_PS_SHOULD_BE_DONE
;
data_area
=
DATA_AREA_ZDA
;
}
else
{
warning
(
"Unrecognised GHS pragma: '%s'
\n
"
,
string
);
state
=
V850_PS_BAD
;
}
break
;
case
V850_PS_SHOULD_BE_DONE
:
warning
(
"Extra text after valid #pragma: '%s'"
,
string
);
state
=
V850_PS_BAD
;
break
;
case
V850_PS_BAD
:
/* Ignore tokens in a pragma that has been diagnosed as being corrupt. */
break
;
case
V850_PS_MAYBE_SECTION_NAME
:
state
=
V850_PS_EXPECTING_EQUALS
;
if
(
streq
(
string
,
"data"
))
GHS_section_kind
=
GHS_SECTION_KIND_DATA
;
else
if
(
streq
(
string
,
"text"
))
GHS_section_kind
=
GHS_SECTION_KIND_TEXT
;
else
if
(
streq
(
string
,
"rodata"
))
GHS_section_kind
=
GHS_SECTION_KIND_RODATA
;
else
if
(
streq
(
string
,
"const"
))
GHS_section_kind
=
GHS_SECTION_KIND_RODATA
;
else
if
(
streq
(
string
,
"rosdata"
))
GHS_section_kind
=
GHS_SECTION_KIND_ROSDATA
;
else
if
(
streq
(
string
,
"rozdata"
))
GHS_section_kind
=
GHS_SECTION_KIND_ROZDATA
;
else
if
(
streq
(
string
,
"sdata"
))
GHS_section_kind
=
GHS_SECTION_KIND_SDATA
;
else
if
(
streq
(
string
,
"tdata"
))
GHS_section_kind
=
GHS_SECTION_KIND_TDATA
;
else
if
(
streq
(
string
,
"zdata"
))
GHS_section_kind
=
GHS_SECTION_KIND_ZDATA
;
/* According to GHS beta documentation, the following should not be allowed! */
else
if
(
streq
(
string
,
"bss"
))
GHS_section_kind
=
GHS_SECTION_KIND_BSS
;
else
if
(
streq
(
string
,
"zbss"
))
GHS_section_kind
=
GHS_SECTION_KIND_ZDATA
;
else
{
warning
(
"Unrecognised section name '%s' in GHS section pragma"
,
string
);
state
=
V850_PS_BAD
;
}
break
;
case
V850_PS_EXPECTING_EQUALS
:
if
(
streq
(
string
,
"="
))
state
=
V850_PS_EXPECTING_SECTION_ALIAS
;
else
{
warning
(
"Missing '=' in GHS section pragma"
);
state
=
V850_PS_BAD
;
}
break
;
case
V850_PS_EXPECTING_SECTION_ALIAS
:
if
(
streq
(
string
,
"default"
))
GHS_current_section_names
[
GHS_section_kind
]
=
NULL
;
else
GHS_current_section_names
[
GHS_section_kind
]
=
build_string
(
strlen
(
string
)
+
1
,
string
);
state
=
V850_PS_MAYBE_COMMA
;
break
;
case
V850_PS_MAYBE_COMMA
:
if
(
streq
(
string
,
","
))
state
=
V850_PS_MAYBE_SECTION_NAME
;
else
{
warning
(
"Malformed GHS section pragma: found '%s' instead of a comma"
,
string
);
state
=
V850_PS_BAD
;
}
break
;
}
return
1
;
}
/* Handle the parsing of an entire GHS pragma. */
int
v850_handle_pragma
(
p_getc
,
p_ungetc
,
name
)
int
(
*
p_getc
)
PROTO
((
void
));
void
(
*
p_ungetc
)
PROTO
((
int
));
char
*
name
;
{
/* Parse characters in the input stream until:
* end of line
* end of file
* a complete GHS pragma has been parsed
* a corrupted GHS pragma has been parsed
* an unknown pragma is encountered.
If an unknown pragma is encountered, we must return with
the input stream in the same state as upon entry to this function.
The first token in the input stream has already been parsed
for us, and is passed as 'name'. */
if
(
!
streq
(
name
,
"ghs"
))
return
0
;
/* We now know that we are parsing a GHS pragma, so we do
not need to preserve the original input stream state. */
for
(;;)
{
static
char
buffer
[
128
];
int
c
;
char
*
buff
;
/* Skip white space. */
do
c
=
p_getc
();
while
(
c
==
' '
||
c
==
'\t'
);
p_ungetc
(
c
);
if
(
c
==
'\n'
||
c
==
EOF
||
c
==
'\r'
)
return
parse_ghs_pragma_token
(
NULL
);
/* Read next word. We have to do the parsing ourselves, rather
than calling yylex() because we can be built with front ends
that do not provide such functions. */
buff
=
buffer
;
*
buff
++
=
(
c
=
p_getc
());
switch
(
c
)
{
case
','
:
case
'='
:
*
buff
++
=
(
c
=
p_getc
());
break
;
case
'"'
:
/* Skip opening double parenthesis. */
--
buff
;
/* Read string. */
do
*
buff
++
=
(
c
=
p_getc
());
while
(
c
!=
EOF
&&
isascii
(
c
)
&&
(
isalnum
(
c
)
||
c
==
'_'
||
c
==
'.'
||
c
==
' '
)
&&
(
buff
<
buffer
+
126
));
if
(
c
!=
'"'
)
warning
(
"Missing trailing
\"
in #pragma ghs"
);
else
c
=
p_getc
();
break
;
default
:
while
(
c
!=
EOF
&&
isascii
(
c
)
&&
(
isalnum
(
c
)
||
c
==
'_'
||
c
==
'.'
)
&&
(
buff
<
buffer
+
126
))
*
buff
++
=
(
c
=
p_getc
());
break
;
}
p_ungetc
(
c
);
/* If nothing was read then terminate the parsing. */
if
(
buff
==
buffer
+
1
)
return
parse_ghs_pragma_token
(
NULL
);
/* Parse and continue. */
*
--
buff
=
0
;
parse_ghs_pragma_token
(
buffer
);
}
}
/* Add data area to the given declaration if a ghs data area pragma is
currently in effect (#pragma ghs startXXX/endXXX). */
void
v850_set_default_decl_attr
(
decl
)
tree
decl
;
{
if
(
data_area_stack
&&
data_area_stack
->
data_area
&&
current_function_decl
==
NULL_TREE
&&
(
TREE_CODE
(
decl
)
==
VAR_DECL
||
TREE_CODE
(
decl
)
==
CONST_DECL
)
&&
v850_get_data_area
(
decl
)
==
DATA_AREA_NORMAL
)
v850_set_data_area
(
decl
,
data_area_stack
->
data_area
);
/* Initialise the default names of the v850 specific sections,
if this has not been done before. */
if
(
GHS_default_section_names
[(
int
)
GHS_SECTION_KIND_SDATA
]
==
NULL
)
{
GHS_default_section_names
[(
int
)
GHS_SECTION_KIND_SDATA
]
=
build_string
(
sizeof
(
".sdata"
)
-
1
,
".sdata"
);
GHS_default_section_names
[(
int
)
GHS_SECTION_KIND_ROSDATA
]
=
build_string
(
sizeof
(
".rosdata"
)
-
1
,
".rosdata"
);
GHS_default_section_names
[(
int
)
GHS_SECTION_KIND_TDATA
]
=
build_string
(
sizeof
(
".tdata"
)
-
1
,
".tdata"
);
GHS_default_section_names
[(
int
)
GHS_SECTION_KIND_ZDATA
]
=
build_string
(
sizeof
(
".zdata"
)
-
1
,
".zdata"
);
GHS_default_section_names
[(
int
)
GHS_SECTION_KIND_ROZDATA
]
=
build_string
(
sizeof
(
".rozdata"
)
-
1
,
".rozdata"
);
}
if
(
current_function_decl
==
NULL_TREE
&&
(
TREE_CODE
(
decl
)
==
VAR_DECL
||
TREE_CODE
(
decl
)
==
CONST_DECL
||
TREE_CODE
(
decl
)
==
FUNCTION_DECL
)
&&
(
!
DECL_EXTERNAL
(
decl
)
||
DECL_INITIAL
(
decl
))
&&
!
DECL_SECTION_NAME
(
decl
))
{
enum
GHS_section_kind
kind
=
GHS_SECTION_KIND_DEFAULT
;
tree
chosen_section
;
if
(
TREE_CODE
(
decl
)
==
FUNCTION_DECL
)
kind
=
GHS_SECTION_KIND_TEXT
;
else
{
/* First choose a section kind based on the data area of the decl. */
switch
(
v850_get_data_area
(
decl
))
{
default
:
abort
();
case
DATA_AREA_SDA
:
kind
=
((
TREE_READONLY
(
decl
))
?
GHS_SECTION_KIND_ROSDATA
:
GHS_SECTION_KIND_SDATA
);
break
;
case
DATA_AREA_TDA
:
kind
=
GHS_SECTION_KIND_TDATA
;
break
;
case
DATA_AREA_ZDA
:
kind
=
((
TREE_READONLY
(
decl
))
?
GHS_SECTION_KIND_ROZDATA
:
GHS_SECTION_KIND_ZDATA
);
break
;
case
DATA_AREA_NORMAL
:
/* default data area */
if
(
TREE_READONLY
(
decl
))
kind
=
GHS_SECTION_KIND_RODATA
;
else
if
(
DECL_INITIAL
(
decl
))
kind
=
GHS_SECTION_KIND_DATA
;
else
kind
=
GHS_SECTION_KIND_BSS
;
}
}
/* Now, if the section kind has been explicitly renamed,
then attach a section attribute. */
chosen_section
=
GHS_current_section_names
[(
int
)
kind
];
/* Otherwise, if this kind of section needs an explicit section
attribute, then also attach one. */
if
(
chosen_section
==
NULL
)
chosen_section
=
GHS_default_section_names
[(
int
)
kind
];
if
(
chosen_section
)
{
/* Only set the section name if specified by a pragma, because
otherwise it will force those variables to get allocated storage
in this module, rather than by the linker. */
DECL_SECTION_NAME
(
decl
)
=
chosen_section
;
}
}
}
gcc/config/v850/v850.h
View file @
3ce15347
...
...
@@ -20,6 +20,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "svr4.h"
/* Automatically does #undef CPP_PREDEFINES */
#include "gansidecl.h"
/* For the PROTO macro */
#undef ASM_SPEC
#define ASM_SPEC "%{mv*:-mv%*}"
...
...
@@ -78,7 +79,7 @@ extern int target_flags;
* Doubles are normally 4 byte aligned, except in argument
lists where they are 8 byte aligned. Is the alignment
in the argument list based on the first parameter,
first stack parameter, etc
.,
etc.
first stack parameter, etc etc.
* Passing/returning of large structures probably isn't the same
as GHS. We don't have enough documentation on their conventions
...
...
@@ -112,21 +113,27 @@ extern int target_flags;
An empty string NAME is used to identify the default VALUE. */
#define TARGET_SWITCHES \
{{ "ghs", MASK_GHS }, \
{ "no-ghs", -MASK_GHS }, \
{ "long-calls", MASK_LONG_CALLS }, \
{ "no-long-calls", -MASK_LONG_CALLS }, \
{ "ep", MASK_EP }, \
{ "no-ep", -MASK_EP }, \
{ "prolog-function", MASK_PROLOG_FUNCTION }, \
{ "no-prolog-function", -MASK_PROLOG_FUNCTION }, \
{ "space", MASK_EP | MASK_PROLOG_FUNCTION }, \
{ "debug", MASK_DEBUG }, \
{ "v850", MASK_V850 }, \
{ "v850", -(MASK_V850 ^ MASK_CPU) }, \
{ "big-switch", MASK_BIG_SWITCH }, \
{{ "ghs", MASK_GHS, "Support Green Hills ABI" }, \
{ "no-ghs", -MASK_GHS, "" }, \
{ "long-calls", MASK_LONG_CALLS, \
"Prohibit PC relative function calls" },\
{ "no-long-calls", -MASK_LONG_CALLS, "" }, \
{ "ep", MASK_EP, \
"Reuse r30 on a per function basis" }, \
{ "no-ep", -MASK_EP, "" }, \
{ "prolog-function", MASK_PROLOG_FUNCTION, \
"Use stubs for function prologues" }, \
{ "no-prolog-function", -MASK_PROLOG_FUNCTION, "" }, \
{ "space", MASK_EP | MASK_PROLOG_FUNCTION, \
"Same as: -mep -mprolog-function" }, \
{ "debug", MASK_DEBUG, "Enable backend debugging" }, \
{ "v850", MASK_V850, \
"Compile for the v850 processor" }, \
{ "v850", -(MASK_V850 ^ MASK_CPU), "" }, \
{ "big-switch", MASK_BIG_SWITCH, \
"Use 4 byte entries in switch tables" },\
EXTRA_SWITCHES \
{ "", TARGET_DEFAULT}}
{ "", TARGET_DEFAULT
, ""
}}
#ifndef EXTRA_SWITCHES
#define EXTRA_SWITCHES
...
...
@@ -176,12 +183,15 @@ extern struct small_memory_info small_memory[(int)SMALL_MEMORY_max];
#define TARGET_OPTIONS \
{ \
{ "tda=", &small_memory[ (int)SMALL_MEMORY_TDA ].value }, \
{ "tda-", &small_memory[ (int)SMALL_MEMORY_TDA ].value }, \
{ "sda=", &small_memory[ (int)SMALL_MEMORY_SDA ].value }, \
{ "sda-", &small_memory[ (int)SMALL_MEMORY_SDA ].value }, \
{ "zda=", &small_memory[ (int)SMALL_MEMORY_ZDA ].value }, \
{ "zda-", &small_memory[ (int)SMALL_MEMORY_ZDA ].value }, \
{ "tda=", &small_memory[ (int)SMALL_MEMORY_TDA ].value, \
"Set the max size of data eligible for the TDA area" }, \
{ "tda-", &small_memory[ (int)SMALL_MEMORY_TDA ].value, "" }, \
{ "sda=", &small_memory[ (int)SMALL_MEMORY_SDA ].value, \
"Set the max size of data eligible for the SDA area" }, \
{ "sda-", &small_memory[ (int)SMALL_MEMORY_SDA ].value, "" }, \
{ "zda=", &small_memory[ (int)SMALL_MEMORY_ZDA ].value, \
"Set the max size of data eligible for the ZDA area" }, \
{ "zda-", &small_memory[ (int)SMALL_MEMORY_ZDA ].value, "" }, \
}
/* Sometimes certain combinations of command options do not make
...
...
@@ -405,7 +415,8 @@ extern struct small_memory_info small_memory[(int)SMALL_MEMORY_max];
For any two classes, it is very desirable that there be another
class that represents their union. */
enum
reg_class
{
enum
reg_class
{
NO_REGS
,
GENERAL_REGS
,
ALL_REGS
,
LIM_REG_CLASSES
};
...
...
@@ -581,13 +592,14 @@ enum reg_class {
Do not define this macro if it would be the same as
`FRAME_POINTER_REGNUM'. */
#undef HARD_FRAME_POINTER_REGNUM
#define HARD_FRAME_POINTER_REGNUM 29
/* Base register for access to arguments of the function. */
#define ARG_POINTER_REGNUM 33
/* Register in which static-chain is passed to a function. */
#define STATIC_CHAIN_REGNUM
5
#define STATIC_CHAIN_REGNUM
20
/* Value should be nonzero if functions must have frame pointers.
Zero means the frame pointer need not be set up (and parms
...
...
@@ -690,7 +702,6 @@ struct cum_arg { int nbytes; };
NAMED is nonzero if this argument is a named parameter
(otherwise it is an extra parameter matching an ellipsis). */
struct
rtx_def
*
function_arg
();
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
function_arg (&CUM, MODE, TYPE, NAMED)
...
...
@@ -1035,17 +1046,29 @@ do { \
into an indirect call. */
#define NO_FUNCTION_CSE
/* The four different data regions on the v850. */
typedef
enum
{
DATA_AREA_NORMAL
,
DATA_AREA_SDA
,
DATA_AREA_TDA
,
DATA_AREA_ZDA
}
v850_data_area
;
/* A list of names for sections other than the standard two, which are
`in_text' and `in_data'. You need not define this macro on a
system with no other sections (that GCC needs to use). */
#undef EXTRA_SECTIONS
#define EXTRA_SECTIONS in_tdata, in_sdata, in_zdata, in_const, in_ctors, in_dtors
#define EXTRA_SECTIONS in_tdata, in_sdata, in_zdata, in_const, in_ctors, \
in_dtors, in_rozdata, in_rosdata, in_sbss, in_zbss, in_zcommon, in_scommon
/* One or more functions to be defined in `varasm.c'. These
functions should do jobs analogous to those of `text_section' and
`data_section', for your additional sections. Do not define this
macro if you do not define `EXTRA_SECTIONS'. */
#undef EXTRA_SECTION_FUNCTIONS
/* This could be done a lot more cleanly using ANSI C ... */
#define EXTRA_SECTION_FUNCTIONS \
CONST_SECTION_FUNCTION \
CTORS_SECTION_FUNCTION \
...
...
@@ -1062,6 +1085,26 @@ sdata_section () \
} \
\
void \
rosdata_section () \
{ \
if (in_section != in_rosdata) \
{ \
fprintf (asm_out_file, "%s\n", ROSDATA_SECTION_ASM_OP); \
in_section = in_sdata; \
} \
} \
\
void \
sbss_section () \
{ \
if (in_section != in_sbss) \
{ \
fprintf (asm_out_file, "%s\n", SBSS_SECTION_ASM_OP); \
in_section = in_sbss; \
} \
} \
\
void \
tdata_section () \
{ \
if (in_section != in_tdata) \
...
...
@@ -1079,16 +1122,42 @@ zdata_section () \
fprintf (asm_out_file, "%s\n", ZDATA_SECTION_ASM_OP); \
in_section = in_zdata; \
} \
} \
\
void \
rozdata_section () \
{ \
if (in_section != in_rozdata) \
{ \
fprintf (asm_out_file, "%s\n", ROZDATA_SECTION_ASM_OP); \
in_section = in_rozdata; \
} \
} \
\
void \
zbss_section () \
{ \
if (in_section != in_zbss) \
{ \
fprintf (asm_out_file, "%s\n", ZBSS_SECTION_ASM_OP); \
in_section = in_zbss; \
} \
}
#define TEXT_SECTION_ASM_OP "\t.section .text"
#define DATA_SECTION_ASM_OP "\t.section .data"
#define BSS_SECTION_ASM_OP "\t.section .bss"
#define TEXT_SECTION_ASM_OP
"\t.section .text"
#define DATA_SECTION_ASM_OP
"\t.section .data"
#define BSS_SECTION_ASM_OP
"\t.section .bss"
#define SDATA_SECTION_ASM_OP "\t.section .sdata,\"aw\""
#define SBSS_SECTION_ASM_OP "\t.section .sbss,\"aw\""
#define SBSS_SECTION_ASM_OP
"\t.section .sbss,\"aw\""
#define ZDATA_SECTION_ASM_OP "\t.section .zdata,\"aw\""
#define ZBSS_SECTION_ASM_OP "\t.section .zbss,\"aw\""
#define ZBSS_SECTION_ASM_OP
"\t.section .zbss,\"aw\""
#define TDATA_SECTION_ASM_OP "\t.section .tdata,\"aw\""
#define ROSDATA_SECTION_ASM_OP "\t.section .rosdata,\"a\""
#define ROZDATA_SECTION_ASM_OP "\t.section .rozdata,\"a\""
#define SCOMMON_ASM_OP ".scomm"
#define ZCOMMON_ASM_OP ".zcomm"
#define TCOMMON_ASM_OP ".tcomm"
/* A C statement or statements to switch to the appropriate section
for output of EXP. You can assume that EXP is either a `VAR_DECL'
...
...
@@ -1099,18 +1168,48 @@ zdata_section () \
Do not define this macro if you put all read-only variables and
constants in the read-only data section (usually the text section). */
#undef
SELECT_SECTION
#undef
SELECT_SECTION
#define SELECT_SECTION(EXP, RELOC) \
do { \
if (TREE_CODE (EXP) == VAR_DECL) \
{ \
if (!TREE_READONLY (EXP) || TREE_SIDE_EFFECTS (EXP) \
int is_const; \
if (!TREE_READONLY (EXP) \
|| TREE_SIDE_EFFECTS (EXP) \
|| !DECL_INITIAL (EXP) \
|| (DECL_INITIAL (EXP) != error_mark_node \
&& !TREE_CONSTANT (DECL_INITIAL (EXP)))) \
data_section ()
; \
is_const = FALSE
; \
else \
const_section (); \
is_const = TRUE; \
\
switch (v850_get_data_area (EXP)) \
{ \
case DATA_AREA_ZDA: \
if (is_const) \
rozdata_section (); \
else \
zdata_section (); \
break; \
\
case DATA_AREA_TDA: \
tdata_section (); \
break; \
\
case DATA_AREA_SDA: \
if (is_const) \
rosdata_section (); \
else \
sdata_section (); \
break; \
\
default: \
if (is_const) \
const_section (); \
else \
data_section (); \
break; \
} \
} \
else if (TREE_CODE (EXP) == STRING_CST) \
{ \
...
...
@@ -1203,6 +1302,24 @@ do { char dstr[30]; \
#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
asm_output_aligned_bss ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
#undef ASM_OUTPUT_ALIGNED_BSS
#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
v850_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
/* This says how to output the assembler to define a global
uninitialized, common symbol. */
#undef ASM_OUTPUT_ALIGNED_COMMON
#undef ASM_OUTPUT_COMMON
#define ASM_OUTPUT_ALIGNED_DECL_COMMON(FILE, DECL, NAME, SIZE, ALIGN) \
v850_output_common (FILE, DECL, NAME, SIZE, ALIGN)
/* This says how to output the assembler to define a local
uninitialized symbol. */
#undef ASM_OUTPUT_ALIGNED_LOCAL
#undef ASM_OUTPUT_LOCAL
#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
v850_output_local (FILE, DECL, NAME, SIZE, ALIGN)
/* This is how to output the definition of a user-level label named NAME,
such as the label on a static function or variable NAME. */
...
...
@@ -1266,7 +1383,7 @@ do { char dstr[30]; \
/* Print an instruction operand X on file FILE.
look in v850.c for details */
#define PRINT_OPERAND(FILE, X, CODE) print_operand
(FILE,X,
CODE)
#define PRINT_OPERAND(FILE, X, CODE) print_operand
(FILE, X,
CODE)
#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
((CODE) == '.')
...
...
@@ -1377,15 +1494,69 @@ do { char dstr[30]; \
is a valid machine specific attribute for DECL.
The attributes in ATTRIBUTES have previously been assigned to DECL. */
#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
v850_valid_machine_decl_attribute (DECL, ATTRIBUTES
, IDENTIFIER, ARGS)
v850_valid_machine_decl_attribute (DECL
, IDENTIFIER, ARGS)
/* Tell compiler we have {ZDA,TDA,SDA} small data regions */
#define HAVE_ZDA 1
#define HAVE_SDA 1
#define HAVE_TDA 1
/* A C statement that assigns default attributes to a newly created DECL. */
#define SET_DEFAULT_DECL_ATTRIBUTES(decl, attr) \
v850_set_default_decl_attr (decl)
/* Tell compiler we want to support GHS pragmas */
#define HANDLE_GHS_PRAGMA
#define HANDLE_PRAGMA(get, unget, name) v850_handle_pragma (get, unget, name)
enum
v850_pragma_state
{
V850_PS_START
,
V850_PS_SHOULD_BE_DONE
,
V850_PS_BAD
,
V850_PS_MAYBE_SECTION_NAME
,
V850_PS_EXPECTING_EQUALS
,
V850_PS_EXPECTING_SECTION_ALIAS
,
V850_PS_MAYBE_COMMA
};
enum
v850_pragma_type
{
V850_PT_UNKNOWN
,
V850_PT_INTERRUPT
,
V850_PT_SECTION
,
V850_PT_START_SECTION
,
V850_PT_END_SECTION
};
/* enum GHS_SECTION_KIND is an enumeration of the kinds of sections that
can appear in the "ghs section" pragma. These names are used to index
into the GHS_default_section_names[] and GHS_current_section_names[]
that are defined in v850.c, and so the ordering of each must remain
consistant.
These arrays give the default and current names for each kind of
section defined by the GHS pragmas. The current names can be changed
by the "ghs section" pragma. If the current names are null, use
the default names. Note that the two arrays have different types.
For the *normal* section kinds (like .data, .text, etc.) we do not
want to explicitly force the name of these sections, but would rather
let the linker (or at least the back end) choose the name of the
section, UNLESS the user has force a specific name for these section
kinds. To accomplish this set the name in ghs_default_section_names
to null. */
enum
GHS_section_kind
{
GHS_SECTION_KIND_DEFAULT
,
GHS_SECTION_KIND_TEXT
,
GHS_SECTION_KIND_DATA
,
GHS_SECTION_KIND_RODATA
,
GHS_SECTION_KIND_BSS
,
GHS_SECTION_KIND_SDATA
,
GHS_SECTION_KIND_ROSDATA
,
GHS_SECTION_KIND_TDATA
,
GHS_SECTION_KIND_ZDATA
,
GHS_SECTION_KIND_ROZDATA
,
COUNT_OF_GHS_SECTION_KINDS
/* must be last */
};
/* The assembler op to start the file. */
...
...
@@ -1444,34 +1615,52 @@ do { \
{ "register_is_ok_for_epilogue",{ REG }}, \
{ "not_power_of_two_operand", { CONST_INT }},
extern
void
override_options
();
extern
void
asm_file_start
();
extern
int
function_arg_partial_nregs
();
extern
int
const_costs
();
extern
void
print_operand
();
extern
void
print_operand_address
();
extern
char
*
output_move_double
();
extern
char
*
output_move_single
();
extern
int
ep_operand
();
extern
int
reg_or_0_operand
();
extern
int
reg_or_int5_operand
();
extern
int
call_address_operand
();
extern
int
movsi_source_operand
();
extern
int
power_of_two_operand
();
extern
int
not_power_of_two_operand
();
extern
void
v850_reorg
();
extern
int
compute_register_save_size
();
extern
int
compute_frame_size
();
extern
void
expand_prologue
();
extern
void
expand_epilogue
();
extern
void
notice_update_cc
();
extern
int
v850_valid_machine_decl_attribute
();
extern
int
v850_interrupt_function_p
();
extern
int
pattern_is_ok_for_prologue
();
extern
int
pattern_is_ok_for_epilogue
();
extern
int
register_is_ok_for_epilogue
();
extern
char
*
construct_save_jarl
();
extern
char
*
construct_restore_jr
();
/* Note, due to dependency and search path conflicts, prototypes
involving the FILE, rtx or tree types cannot be included here.
They are included at the start of v850.c */
extern
void
asm_file_start
();
extern
void
print_operand
();
extern
void
print_operand_address
();
extern
int
function_arg_partial_nregs
();
extern
int
const_costs
();
extern
char
*
output_move_double
();
extern
char
*
output_move_single
();
extern
int
ep_memory_operand
();
extern
int
reg_or_0_operand
();
extern
int
reg_or_int5_operand
();
extern
int
call_address_operand
();
extern
int
movsi_source_operand
();
extern
int
power_of_two_operand
();
extern
int
not_power_of_two_operand
();
extern
int
special_symbolref_operand
();
extern
void
v850_reorg
();
extern
void
notice_update_cc
();
extern
int
v850_valid_machine_decl_attribute
();
extern
int
v850_interrupt_function_p
();
extern
int
pattern_is_ok_for_prologue
();
extern
int
pattern_is_ok_for_epilogue
();
extern
int
register_is_ok_for_epilogue
();
extern
char
*
construct_save_jarl
();
extern
char
*
construct_restore_jr
();
extern
void
override_options
PROTO
((
void
));
extern
int
compute_register_save_size
PROTO
((
long
*
));
extern
int
compute_frame_size
PROTO
((
int
,
long
*
));
extern
void
expand_prologue
PROTO
((
void
));
extern
void
expand_epilogue
PROTO
((
void
));
extern
void
v850_output_aligned_bss
();
extern
void
v850_output_common
();
extern
void
v850_output_local
();
extern
void
sdata_section
PROTO
((
void
));
extern
void
rosdata_section
PROTO
((
void
));
extern
void
sbss_section
PROTO
((
void
));
extern
void
tdata_section
PROTO
((
void
));
extern
void
zdata_section
PROTO
((
void
));
extern
void
rozdata_section
PROTO
((
void
));
extern
void
zbss_section
PROTO
((
void
));
extern
int
v850_handle_pragma
PROTO
((
int
(
*
)(
void
),
void
(
*
)(
int
),
char
*
));
extern
void
v850_encode_data_area
();
extern
void
v850_set_default_decl_attr
();
extern
v850_data_area
v850_get_data_area
();
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