Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
b1d47c45
Commit
b1d47c45
authored
Aug 03, 2015
by
Christoph Mallon
Browse files
amd64, arm, ia32, sparc, template: Small cleanup in node specifications.
parent
c5940669
Changes
5
Hide whitespace changes
Inline
Side-by-side
ir/be/TEMPLATE/TEMPLATE_spec.pl
View file @
b1d47c45
# the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
$arch
=
"
TEMPLATE
";
#
# Modes
#
$mode_gp
=
"
mode_Iu
";
# mode used by general purpose registers
$mode_fp
=
"
mode_F
";
# mode used by floatingpoint registers
$mode_gp
=
"
mode_Iu
";
# mode used by general purpose registers
$mode_fp
=
"
mode_F
";
# mode used by floatingpoint registers
# The node description is done as a perl hash initializer with the
# following structure:
...
...
@@ -13,12 +11,12 @@ $mode_fp = "mode_F"; # mode used by floatingpoint registers
# %nodes = (
#
# <op-name> => {
# state => "floats|pinned|mem_pinned|exc_pinned", # optional
# state => "floats|pinned|mem_pinned|exc_pinned", # optional
, default floats
# comment => "any comment for constructor", # optional
# in_reqs => [ "reg_class|register" ] | "...",
# out_reqs => [ "reg_class|register|in_rX" ] | "...",
# outs => { "out1", "out2" },# optional, creates pn_op_out1, ... consts
# ins => { "in1", "in2" }, # optional, creates n_op_in1, ... consts
# outs => { "out1", "out2" },# optional, creates pn_op_out1, ... consts
# mode => "mode_Iu", # optional, predefines the mode
# emit => "emit code with templates", # optional for virtual nodes
# attr => "additional attribute arguments for constructor", # optional
...
...
@@ -29,28 +27,20 @@ $mode_fp = "mode_F"; # mode used by floatingpoint registers
#
# ... # (all nodes you need to describe)
#
# );
# close the %nodes initializer
# );
# state: state of the operation, OPTIONAL (default is "floats")
#
# arity: arity of the operation, MUST NOT BE OMITTED
#
# outs: if a node defines more than one output, the names of the projections
# nodes having outs having automatically the mode mode_T
#
# comment: OPTIONAL comment for the node constructor
%reg_classes
=
(
gp
=>
[
{
name
=>
"
r0
"
},
{
name
=>
"
r1
"
},
{
name
=>
"
r2
"
},
{
name
=>
"
r3
"
},
{
name
=>
"
r4
"
},
{
name
=>
"
r5
"
},
{
name
=>
"
r6
"
},
{
name
=>
"
r7
"
},
{
name
=>
"
r8
"
},
{
name
=>
"
r9
"
},
{
name
=>
"
r0
"
},
{
name
=>
"
r1
"
},
{
name
=>
"
r2
"
},
{
name
=>
"
r3
"
},
{
name
=>
"
r4
"
},
{
name
=>
"
r5
"
},
{
name
=>
"
r6
"
},
{
name
=>
"
r7
"
},
{
name
=>
"
r8
"
},
{
name
=>
"
r9
"
},
{
name
=>
"
r10
"
},
{
name
=>
"
r11
"
},
{
name
=>
"
r12
"
},
...
...
@@ -60,16 +50,16 @@ $mode_fp = "mode_F"; # mode used by floatingpoint registers
{
mode
=>
$mode_gp
}
],
fp
=>
[
{
name
=>
"
f0
"
},
{
name
=>
"
f1
"
},
{
name
=>
"
f2
"
},
{
name
=>
"
f3
"
},
{
name
=>
"
f4
"
},
{
name
=>
"
f5
"
},
{
name
=>
"
f6
"
},
{
name
=>
"
f7
"
},
{
name
=>
"
f8
"
},
{
name
=>
"
f9
"
},
{
name
=>
"
f0
"
},
{
name
=>
"
f1
"
},
{
name
=>
"
f2
"
},
{
name
=>
"
f3
"
},
{
name
=>
"
f4
"
},
{
name
=>
"
f5
"
},
{
name
=>
"
f6
"
},
{
name
=>
"
f7
"
},
{
name
=>
"
f8
"
},
{
name
=>
"
f9
"
},
{
name
=>
"
f10
"
},
{
name
=>
"
f11
"
},
{
name
=>
"
f12
"
},
...
...
ir/be/amd64/amd64_spec.pl
View file @
b1d47c45
...
...
@@ -537,7 +537,7 @@ xorpd_0 => {
mode
=>
$mode_xmm
,
},
xorp
=>
{
xorp
=>
{
template
=>
$binopx_commutative
,
emit
=>
"
xorp%MX %AM
",
},
...
...
@@ -546,7 +546,7 @@ movd_xmm_gp => {
state
=>
"
exc_pinned
",
ins
=>
[
"
operand
"
],
outs
=>
[
"
res
"
],
in_reqs
=>
[
"
xmm
"
],
in_reqs
=>
[
"
xmm
"
],
out_reqs
=>
[
"
gp
"
],
mode
=>
$mode_gp
,
attr_type
=>
"
amd64_addr_attr_t
",
...
...
ir/be/arm/arm_spec.pl
View file @
b1d47c45
...
...
@@ -3,14 +3,10 @@
$arch
=
"
arm
";
#
# Modes
#
$mode_gp
=
"
arm_mode_gp
";
$mode_flags
=
"
arm_mode_flags
";
$mode_fp
=
"
mode_F
";
# NOTE: Last entry of each class is the largest Firm-Mode a register can hold
%reg_classes
=
(
gp
=>
[
{
name
=>
"
r0
",
dwarf
=>
0
},
...
...
@@ -52,22 +48,26 @@ $default_attr_type = "arm_attr_t";
$default_copy_attr
=
"
arm_copy_attr
";
%init_attr
=
(
arm_attr_t
=>
"
\t
init_arm_attributes(res, irn_flags, in_reqs, n_res);
",
arm_Address_attr_t
=>
"
\t
init_arm_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
arm_attr_t
=>
"
init_arm_attributes(res, irn_flags, in_reqs, n_res);
",
arm_Address_attr_t
=>
"
init_arm_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
\t
init_arm_Address_attributes(res, entity, offset);
",
arm_CondJmp_attr_t
=>
"
\t
init_arm_attributes(res, irn_flags, in_reqs, n_res);
",
arm_SwitchJmp_attr_t
=>
"
\t
init_arm_attributes(res, irn_flags, in_reqs, n_res);
",
arm_fConst_attr_t
=>
"
\t
init_arm_attributes(res, irn_flags, in_reqs, n_res);
",
arm_CondJmp_attr_t
=>
"
init_arm_attributes(res, irn_flags, in_reqs, n_res);
",
arm_SwitchJmp_attr_t
=>
"
init_arm_attributes(res, irn_flags, in_reqs, n_res);
",
arm_fConst_attr_t
=>
"
init_arm_attributes(res, irn_flags, in_reqs, n_res);
",
arm_load_store_attr_t
=>
"
\t
init_arm_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
init_arm_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
\t
init_arm_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);
",
arm_shifter_operand_t
=>
"
\t
init_arm_attributes(res, irn_flags, in_reqs, n_res);
\n
",
"
init_arm_attributes(res, irn_flags, in_reqs, n_res);
",
arm_cmp_attr_t
=>
"
\t
init_arm_attributes(res, irn_flags, in_reqs, n_res);
\n
",
"
init_arm_attributes(res, irn_flags, in_reqs, n_res);
",
arm_farith_attr_t
=>
"
\t
init_arm_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
init_arm_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
\t
init_arm_farith_attributes(res, op_mode);
",
);
...
...
@@ -280,11 +280,11 @@ Mul => {
emit
=>
'
mul %D0, %S0, %S1
',
mode
=>
$mode_gp
,
constructors
=>
{
""
=>
{
out_reqs
=>
[
"
gp
"
]
},
# TODO: !in_r1 for out constrains the register allocator more than
""
=>
{
out_reqs
=>
[
"
gp
"
]
},
# TODO: !in_r1 for out constrain
t
s the register allocator more than
# necessary, as usually you can fix the problem by swapping the inputs. But
# for this scheme we would need a special if both inputs are the same value.
"
v5
"
=>
{
out_reqs
=>
[
"
!in_r1
"
]
},
v5
=>
{
out_reqs
=>
[
"
!in_r1
"
]
},
},
},
...
...
@@ -305,9 +305,9 @@ Mla => {
emit
=>
'
mla %D0, %S0, %S1, %S2
',
mode
=>
$mode_gp
,
constructors
=>
{
""
=>
{
out_reqs
=>
[
"
gp
"
]
},
""
=>
{
out_reqs
=>
[
"
gp
"
]
},
# See comments for Mul_v5 out register constraint
"
v5
"
=>
{
out_reqs
=>
[
"
!in_r1
"
]
},
v5
=>
{
out_reqs
=>
[
"
!in_r1
"
]
},
}
},
...
...
@@ -382,14 +382,14 @@ RsbS => {
},
Mov
=>
{
template
=>
$unop_shifter_operand
,
emit
=>
'
mov %D0, %O
',
ins
=>
[
"
Rm
",
"
Rs
"
],
template
=>
$unop_shifter_operand
,
emit
=>
'
mov %D0, %O
',
ins
=>
[
"
Rm
",
"
Rs
"
],
},
Mvn
=>
{
template
=>
$unop_shifter_operand
,
emit
=>
'
mvn %D0, %O
',
template
=>
$unop_shifter_operand
,
emit
=>
'
mvn %D0, %O
',
},
Pkhbt
=>
{
...
...
@@ -427,14 +427,14 @@ LinkMovPC => {
# mov lr, pc\n ldr pc, XXX -- This combination is used for calls to function
# pointers
LinkLdrPC
=>
{
state
=>
"
exc_pinned
",
irn_flags
=>
[
"
modify_flags
"
],
in_reqs
=>
"
...
",
out_reqs
=>
"
...
",
attr_type
=>
"
arm_load_store_attr_t
",
attr
=>
"
ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity
",
emit
=>
"
mov lr, pc
\n
"
.
"
ldr pc, %O
",
state
=>
"
exc_pinned
",
irn_flags
=>
[
"
modify_flags
"
],
in_reqs
=>
"
...
",
out_reqs
=>
"
...
",
attr_type
=>
"
arm_load_store_attr_t
",
attr
=>
"
ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity
",
emit
=>
"
mov lr, pc
\n
"
.
"
ldr pc, %O
",
},
Bl
=>
{
...
...
@@ -621,9 +621,7 @@ Stf => {
attr
=>
"
ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity
",
},
#
# floating point constants
#
fConst
=>
{
op_flags
=>
[
"
constlike
"
],
irn_flags
=>
[
"
rematerializable
"
],
...
...
@@ -698,4 +696,4 @@ OrPl_t => {
dump_func
=>
"
NULL
",
},
);
# end of %nodes
);
ir/be/ia32/ia32_spec.pl
View file @
b1d47c45
...
...
@@ -13,11 +13,11 @@
$arch
=
"
ia32
";
$mode_xmm
=
"
ia32_mode_float64
";
$mode_fp87
=
"
ia32_mode_E
";
$mode_gp
=
"
ia32_mode_gp
";
$mode_flags
=
"
ia32_mode_flags
";
$mode_fpcw
=
"
ia32_mode_fpcw
";
$mode_xmm
=
"
ia32_mode_float64
";
$mode_fp87
=
"
ia32_mode_E
";
$mode_gp
=
"
ia32_mode_gp
";
$mode_flags
=
"
ia32_mode_flags
";
$mode_fpcw
=
"
ia32_mode_fpcw
";
%reg_classes
=
(
gp
=>
[
...
...
@@ -64,33 +64,28 @@ $mode_fpcw = "ia32_mode_fpcw";
{
name
=>
"
eflags
",
dwarf
=>
9
},
{
mode
=>
"
ia32_mode_flags
",
flags
=>
"
manual_ra
"
}
],
);
# %reg_classes
);
$default_attr_type
=
"
ia32_attr_t
";
$default_copy_attr
=
"
ia32_copy_attr
";
sub
ia32_custom_init_attr
{
my
$constr
=
shift
;
my
$node
=
shift
;
my
$name
=
shift
;
my
$res
=
"";
if
(
defined
(
$node
->
{
am
}))
{
my
$am
=
$node
->
{
am
};
if
(
$am
eq
"
source,unary
")
{
my
(
$constr
,
$node
,
$name
)
=
@_
;
my
$res
=
"";
my
$am
=
$node
->
{
am
};
if
(
defined
(
$am
))
{
if
(
$am
eq
"
source,unary
")
{
$res
.=
"
\t
set_ia32_am_support(res, ia32_am_unary);
";
}
elsif
(
$am
eq
"
source,binary
")
{
}
elsif
(
$am
eq
"
source,binary
")
{
$res
.=
"
\t
set_ia32_am_support(res, ia32_am_binary);
";
}
elsif
(
$am
eq
"
none
")
{
}
elsif
(
$am
eq
"
none
")
{
# nothing to do
}
else
{
die
("
Invalid address mode '
$am
' specified on op
$name
");
}
if
(
$am
ne
"
none
")
{
if
(
$node
->
{
state
}
ne
"
exc_pinned
"
and
$node
->
{
state
}
ne
"
pinned
")
{
die
("
AM nodes must have pinned or AM pinned state (
$name
)
");
}
if
(
$am
ne
"
none
"
&&
$node
->
{
state
}
ne
"
exc_pinned
"
&&
$node
->
{
state
}
ne
"
pinned
")
{
die
("
AM nodes must have pinned or AM pinned state (
$name
)
");
}
}
return
$res
;
...
...
@@ -98,31 +93,31 @@ sub ia32_custom_init_attr {
$custom_init_attr_func
=
\
&ia32_custom_init_attr
;
%init_attr
=
(
ia32_attr_t
=>
"
\t
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
",
ia32_attr_t
=>
"
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
",
ia32_call_attr_t
=>
"
\t
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
\t
init_ia32_call_attributes(res, pop, call_tp);
",
ia32_condcode_attr_t
=>
"
\t
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
\t
init_ia32_condcode_attributes(res, condition_code);
",
ia32_switch_attr_t
=>
"
\t
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
\t
init_ia32_switch_attributes(res, switch_table);
",
ia32_copyb_attr_t
=>
"
\t
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
\t
init_ia32_copyb_attributes(res, size);
",
ia32_immediate_attr_t
=>
"
\t
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
\t
init_ia32_immediate_attributes(res, imm);
",
ia32_x87_attr_t
=>
"
\t
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
\t
init_ia32_x87_attributes(res);
",
ia32_climbframe_attr_t
=>
"
\t
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
\t
init_ia32_climbframe_attributes(res, count);
",
ia32_return_attr_t
=>
"
\t
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
init_ia32_attributes(res, irn_flags, in_reqs, n_res);
\n
"
.
"
\t
init_ia32_return_attributes(res, pop);
",
);
...
...
@@ -156,15 +151,15 @@ my $binop_flags = {
};
my
$binop_mem
=
{
irn_flags
=>
[
"
modify_flags
",
"
rematerializable
"
],
state
=>
"
exc_pinned
",
irn_flags
=>
[
"
modify_flags
",
"
rematerializable
"
],
state
=>
"
exc_pinned
",
constructors
=>
{
""
=>
{
in_reqs
=>
[
"
gp
",
"
gp
",
"
mem
",
"
gp
"
]
},
"
8bit
"
=>
{
in_reqs
=>
[
"
gp
",
"
gp
",
"
mem
",
"
eax ebx ecx edx
"
]
},
},
out_reqs
=>
[
"
none
",
"
flags
",
"
mem
"
],
ins
=>
[
"
base
",
"
index
",
"
mem
",
"
val
"
],
outs
=>
[
"
unused
",
"
flags
",
"
M
"
],
out_reqs
=>
[
"
none
",
"
flags
",
"
mem
"
],
ins
=>
[
"
base
",
"
index
",
"
mem
",
"
val
"
],
outs
=>
[
"
unused
",
"
flags
",
"
M
"
],
};
my
$shiftop
=
{
...
...
@@ -189,11 +184,11 @@ my $shiftop_double = {
irn_flags
=>
[
"
modify_flags
",
"
rematerializable
"
],
in_reqs
=>
[
"
gp
",
"
gp
",
"
ecx
"
],
constructors
=>
{
""
=>
{
out_reqs
=>
[
"
in_r1 !in_r2 !in_r3
",
"
flags
"
]
},
""
=>
{
out_reqs
=>
[
"
in_r1 !in_r2 !in_r3
",
"
flags
"
]
},
# With an immediate shift amount we can swap between ShlD/ShrD and negate
# the shift amount, if the output gets the same register as the second
# input.
"
imm
"
=>
{
out_reqs
=>
[
"
in_r1 in_r2
",
"
flags
"
]
},
imm
=>
{
out_reqs
=>
[
"
in_r1 in_r2
",
"
flags
"
]
},
},
ins
=>
[
"
val_high
",
"
val_low
",
"
count
"
],
outs
=>
[
"
res
",
"
flags
"
],
...
...
@@ -451,9 +446,9 @@ IMul => {
IMulImm
=>
{
template
=>
$binop_commutative
,
out_reqs
=>
[
"
gp
",
"
flags
",
"
mem
"
],
emit
=>
"
imul%M %#S4, %#AS3, %#D0
",
latency
=>
5
,
out_reqs
=>
[
"
gp
",
"
flags
",
"
mem
"
],
emit
=>
"
imul%M %#S4, %#AS3, %#D0
",
latency
=>
5
,
},
IMul1OP
=>
{
...
...
@@ -849,16 +844,16 @@ Jmp => {
},
IJmp
=>
{
state
=>
"
pinned
",
op_flags
=>
[
"
cfopcode
",
"
unknown_jump
"
],
in_reqs
=>
[
"
gp
",
"
gp
",
"
mem
",
"
gp
"
],
out_reqs
=>
[
"
exec
",
"
none
",
"
mem
"
],
ins
=>
[
"
base
",
"
index
",
"
mem
",
"
target
"
],
outs
=>
[
"
jmp
",
"
none
",
"
M
"
],
am
=>
"
source,unary
",
emit
=>
"
jmp %*AS3
",
latency
=>
1
,
mode
=>
"
mode_X
",
state
=>
"
pinned
",
op_flags
=>
[
"
cfopcode
",
"
unknown_jump
"
],
in_reqs
=>
[
"
gp
",
"
gp
",
"
mem
",
"
gp
"
],
out_reqs
=>
[
"
exec
",
"
none
",
"
mem
"
],
ins
=>
[
"
base
",
"
index
",
"
mem
",
"
target
"
],
outs
=>
[
"
jmp
",
"
none
",
"
M
"
],
am
=>
"
source,unary
",
emit
=>
"
jmp %*AS3
",
latency
=>
1
,
mode
=>
"
mode_X
",
},
Const
=>
{
...
...
@@ -870,9 +865,9 @@ Const => {
},
Unknown
=>
{
template
=>
$valueop
,
latency
=>
0
,
emit
=>
"",
template
=>
$valueop
,
latency
=>
0
,
emit
=>
"",
},
GetEIP
=>
{
...
...
@@ -920,36 +915,36 @@ ChangeCW => {
},
FldCW
=>
{
op_flags
=>
[
"
uses_memory
"
],
state
=>
"
pinned
",
in_reqs
=>
[
"
gp
",
"
gp
",
"
mem
"
],
out_reqs
=>
[
"
fpcw
"
],
ins
=>
[
"
base
",
"
index
",
"
mem
"
],
latency
=>
5
,
emit
=>
"
fldcw %AM
",
mode
=>
$mode_fpcw
,
op_flags
=>
[
"
uses_memory
"
],
state
=>
"
pinned
",
in_reqs
=>
[
"
gp
",
"
gp
",
"
mem
"
],
out_reqs
=>
[
"
fpcw
"
],
ins
=>
[
"
base
",
"
index
",
"
mem
"
],
latency
=>
5
,
emit
=>
"
fldcw %AM
",
mode
=>
$mode_fpcw
,
},
FnstCW
=>
{
op_flags
=>
[
"
uses_memory
"
],
state
=>
"
pinned
",
in_reqs
=>
[
"
gp
",
"
gp
",
"
mem
",
"
fp_cw
"
],
out_reqs
=>
[
"
mem
"
],
ins
=>
[
"
base
",
"
index
",
"
mem
",
"
fpcw
"
],
latency
=>
5
,
emit
=>
"
fnstcw %AM
",
mode
=>
"
mode_M
",
op_flags
=>
[
"
uses_memory
"
],
state
=>
"
pinned
",
in_reqs
=>
[
"
gp
",
"
gp
",
"
mem
",
"
fp_cw
"
],
out_reqs
=>
[
"
mem
"
],
ins
=>
[
"
base
",
"
index
",
"
mem
",
"
fpcw
"
],
latency
=>
5
,
emit
=>
"
fnstcw %AM
",
mode
=>
"
mode_M
",
},
FnstCWNOP
=>
{
op_flags
=>
[
"
uses_memory
"
],
state
=>
"
pinned
",
in_reqs
=>
[
"
fp_cw
"
],
out_reqs
=>
[
"
mem
"
],
ins
=>
[
"
fpcw
"
],
latency
=>
0
,
emit
=>
"",
mode
=>
"
mode_M
",
op_flags
=>
[
"
uses_memory
"
],
state
=>
"
pinned
",
in_reqs
=>
[
"
fp_cw
"
],
out_reqs
=>
[
"
mem
"
],
ins
=>
[
"
fpcw
"
],
latency
=>
0
,
emit
=>
"",
mode
=>
"
mode_M
",
},
Cltd
=>
{
...
...
@@ -969,28 +964,28 @@ Cltd => {
# lateny of 0 for load is correct
Load
=>
{
op_flags
=>
[
"
uses_memory
",
"
fragile
"
],
state
=>
"
exc_pinned
",
in_reqs
=>
[
"
gp
",
"
gp
",
"
mem
"
],
out_reqs
=>
[
"
gp
",
"
none
",
"
mem
",
"
exec
",
"
exec
"
],
ins
=>
[
"
base
",
"
index
",
"
mem
"
],
outs
=>
[
"
res
",
"
unused
",
"
M
",
"
X_regular
",
"
X_except
"
],
latency
=>
0
,
emit
=>
"
mov%#Ml %AM, %D0
",
op_flags
=>
[
"
uses_memory
",
"
fragile
"
],
state
=>
"
exc_pinned
",
in_reqs
=>
[
"
gp
",
"
gp
",
"
mem
"
],
out_reqs
=>
[
"
gp
",
"
none
",
"
mem
",
"
exec
",
"
exec
"
],
ins
=>
[
"
base
",
"
index
",
"
mem
"
],
outs
=>
[
"
res
",
"
unused
",
"
M
",
"
X_regular
",
"
X_except
"
],
latency
=>
0
,
emit
=>
"
mov%#Ml %AM, %D0
",
},
Store
=>
{
op_flags
=>
[
"
uses_memory
",
"
fragile
"
],
state
=>
"
exc_pinned
",
op_flags
=>
[
"
uses_memory
",
"
fragile
"
],
state
=>
"
exc_pinned
",
constructors
=>
{
""
=>
{
in_reqs
=>
[
"
gp
",
"
gp
",
"
mem
",
"
gp
"
]
},
"
8bit
"
=>
{
in_reqs
=>
[
"
gp
",
"
gp
",
"
mem
",
"
eax ebx ecx edx
"
]
}
},
out_reqs
=>
[
"
mem
",
"
exec
",
"
exec
"
],
ins
=>
[
"
base
",
"
index
",
"
mem
",
"
val
"
],
outs
=>
[
"
M
",
"
X_regular
",
"
X_except
"
],
emit
=>
"
mov%M %#S3, %AM
",
latency
=>
2
,
out_reqs
=>
[
"
mem
",
"
exec
",
"
exec
"
],
ins
=>
[
"
base
",
"
index
",
"
mem
",
"
val
"
],
outs
=>
[
"
M
",
"
X_regular
",
"
X_except
"
],
emit
=>
"
mov%M %#S3, %AM
",
latency
=>
2
,
},
Lea
=>
{
...
...
@@ -1033,12 +1028,8 @@ PushEax => {
Pop
=>
{
state
=>
"
exc_pinned
",
constructors
=>
{
""
=>
{
out_reqs
=>
[
"
gp
",
"
none
",
"
mem
",
"
esp:I
"
],
},
"
ebp
"
=>
{
out_reqs
=>
[
"
ebp:I
",
"
none
",
"
mem
",
"
esp:I
"
],
}
""
=>
{
out_reqs
=>
[
"
gp
",
"
none
",
"
mem
",
"
esp:I
"
]
},
ebp
=>
{
out_reqs
=>
[
"
ebp:I
",
"
none
",
"
mem
",
"
esp:I
"
]
}
},
in_reqs
=>
[
"
mem
",
"
esp
"
],
ins
=>
[
"
mem
",
"
stack
"
],
...
...
@@ -1060,21 +1051,21 @@ CopyEbpEsp => {
},
PopMem
=>
{
state
=>
"
exc_pinned
",
in_reqs
=>
[
"
gp
",
"
gp
",
"
mem
",
"
esp
"
],
out_reqs
=>
[
"
none
",
"
none
",
"
mem
",
"
esp:I
"
],
ins
=>
[
"
base
",
"
index
",
"
mem
",
"
stack
"
],
outs
=>
[
"
unused0
",
"
unused1
",
"
M
",
"
stack
"
],
emit
=>
"
pop%M %AM
",
latency
=>
3
,
# Pop is more expensive than Push on Athlon
state
=>
"
exc_pinned
",
in_reqs
=>
[
"
gp
",
"
gp
",
"
mem
",
"
esp
"
],
out_reqs
=>
[
"
none
",
"
none
",
"
mem
",
"
esp:I
"
],
ins
=>
[
"
base
",
"
index
",
"
mem
",
"
stack
"
],
outs
=>
[
"
unused0
",
"
unused1
",
"
M
",
"
stack
"
],
emit
=>
"
pop%M %AM
",
latency
=>
3
,
# Pop is more expensive than Push on Athlon
},
Enter
=>
{
in_reqs
=>
[
"
esp
"
],
out_reqs
=>
[
"
ebp
",
"
esp:I
",
"
mem
"
],
emit
=>
"
enter
",
outs
=>
[
"
frame
",
"
stack
",
"
M
"
],
latency
=>
15
,
in_reqs
=>
[
"
esp
"
],
out_reqs
=>
[
"
ebp
",
"
esp:I
",
"
mem
"
],
emit
=>
"
enter
",
outs
=>
[
"
frame
",
"
stack
",
"
M
"
],
latency
=>
15
,
},
Leave
=>
{
...
...
@@ -1112,14 +1103,12 @@ SubSP => {
},
LdTls
=>
{
template
=>
$valueop
,
emit
=>
"
movl %%gs:0, %D0
",
latency
=>
1
,
template
=>
$valueop
,
emit
=>
"
movl %%gs:0, %D0
",
latency
=>
1
,
},
#
# BT supports source address mode, but this is unused yet
#
Bt
=>
{
# only CF is set, but the other flags are undefined
irn_flags
=>
[
"
modify_flags
",
"
rematerializable
"
],
...
...
@@ -1144,9 +1133,7 @@ Bsr => {
latency
=>
1
,
},
#
# SSE4.2 or SSE4a popcnt instruction
#