ia32_spec.pl 52.9 KB
Newer Older
1
2
3
4
# Creation: 2005/10/19
# $Id$
# This is the specification for the ia32 assembler Firm-operations

Andreas Schösser's avatar
Andreas Schösser committed
5
6
use File::Basename;

7
$new_emit_syntax = 1;
Andreas Schösser's avatar
Andreas Schösser committed
8
my $myname = $0;
9

10
11
12
13
14
15
16
17
18
# the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
$arch = "ia32";

# The node description is done as a perl hash initializer with the
# following structure:
#
# %nodes = (
#
# <op-name> => {
19
20
21
22
23
24
25
#   op_flags  => "N|L|C|X|I|F|Y|H|c|K",
#   irn_flags => "R|N|I|S"
#   arity     => "0|1|2|3 ... |variable|dynamic|any",
#   state     => "floats|pinned|mem_pinned|exc_pinned",
#   args      => [
#                    { type => "type 1", name => "name 1" },
#                    { type => "type 2", name => "name 2" },
26
27
#                    ...
#                  ],
28
29
30
31
32
33
34
35
#   comment   => "any comment for constructor",
#   reg_req   => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
#   cmp_attr  => "c source code for comparing node attributes",
#   emit      => "emit code with templates",
#   attr      => "attitional attribute arguments for constructor"
#   init_attr => "emit attribute initialization template"
#   rd_constructor => "c source code which constructs an ir_node"
#   latency   => "latency of this operation (can be float)"
36
37
38
39
40
41
# },
#
# ... # (all nodes you need to describe)
#
# ); # close the %nodes initializer

42
# op_flags: flags for the operation, OPTIONAL (default is "N")
43
44
45
46
47
48
49
50
51
52
# the op_flags correspond to the firm irop_flags:
#   N   irop_flag_none
#   L   irop_flag_labeled
#   C   irop_flag_commutative
#   X   irop_flag_cfopcode
#   I   irop_flag_ip_cfopcode
#   F   irop_flag_fragile
#   Y   irop_flag_forking
#   H   irop_flag_highlevel
#   c   irop_flag_constlike
Michael Beck's avatar
Michael Beck committed
53
#   K   irop_flag_keep
54
#
55
56
57
58
59
# irn_flags: special node flags, OPTIONAL (default is 0)
# following irn_flags are supported:
#   R   rematerializeable
#   N   not spillable
#   I   ignore for register allocation
60
#   S   modifies stack pointer
Christian Würdig's avatar
Christian Würdig committed
61
#
Christian Würdig's avatar
Christian Würdig committed
62
# state: state of the operation, OPTIONAL (default is "floats")
Christian Würdig's avatar
Christian Würdig committed
63
64
65
66
#
# arity: arity of the operation, MUST NOT BE OMITTED
#
# args:  the OPTIONAL arguments of the node constructor (debug, irg and block
67
68
#        are always the first 3 arguments and are always autmatically
#        created)
Christian Würdig's avatar
Christian Würdig committed
69
#        If this key is missing the following arguments will be created:
70
71
#        for i = 1 .. arity: ir_node *op_i
#        ir_mode *mode
Christian Würdig's avatar
Christian Würdig committed
72
#
Michael Beck's avatar
Michael Beck committed
73
74
# outs:  if a node defines more than one output, the names of the projections
#        nodes having outs having automatically the mode mode_T
75
76
77
78
#        One can also annotate some flags for each out, additional to irn_flags.
#        They are separated from name with a colon ':', and concatenated by pipe '|'
#        Only I and S are available at the moment (same meaning as in irn_flags).
#        example: [ "frame:I", "stack:I|S", "M" ]
Michael Beck's avatar
Michael Beck committed
79
#
Christian Würdig's avatar
Christian Würdig committed
80
81
# comment: OPTIONAL comment for the node constructor
#
82
83
84
85
86
# rd_constructor: for every operation there will be a
#      new_rd_<arch>_<op-name> function with the arguments from above
#      which creates the ir_node corresponding to the defined operation
#      you can either put the complete source code of this function here
#
Christian Würdig's avatar
Christian Würdig committed
87
88
#      This key is OPTIONAL. If omitted, the following constructor will
#      be created:
89
90
91
92
#      if (!op_<arch>_<op-name>) assert(0);
#      for i = 1 to arity
#         set in[i] = op_i
#      done
Christian Würdig's avatar
Christian Würdig committed
93
#      res = new_ir_node(db, irg, block, op_<arch>_<op-name>, mode, arity, in)
94
95
#      return res
#
Christian Würdig's avatar
Christian Würdig committed
96
# NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3
Christian Würdig's avatar
Christian Würdig committed
97
98
99
#
# latency: the latency of the operation, default is 1
#
100

Christian Würdig's avatar
Christian Würdig committed
101
102
# register types:
#   0 - no special type
103
104
#   1 - caller save (register must be saved by the caller of a function)
#   2 - callee save (register must be saved by the called function)
Christian Würdig's avatar
Christian Würdig committed
105
#   4 - ignore (do not assign this register)
106
107
#   8 - emitter can choose an arbitrary register of this class
#  16 - the register is a virtual one
Christian Würdig's avatar
Christian Würdig committed
108
# NOTE: Last entry of each class is the largest Firm-Mode a register can hold
109
%reg_classes = (
110
111
112
113
114
115
116
117
118
119
120
121
	gp => [
		{ name => "eax", type => 1 },
		{ name => "edx", type => 1 },
		{ name => "ebx", type => 2 },
		{ name => "ecx", type => 1 },
		{ name => "esi", type => 2 },
		{ name => "edi", type => 2 },
		{ name => "ebp", type => 2 },
		{ name => "esp", type => 4 },
		{ name => "gp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
		{ name => "gp_UKNWN", type => 4 | 8 | 16 },  # we need a dummy register for Unknown nodes
		{ mode => "mode_Iu" }
122
	],
123
124
125
126
127
128
129
130
131
132
133
134
	xmm => [
		{ name => "xmm0", type => 1 },
		{ name => "xmm1", type => 1 },
		{ name => "xmm2", type => 1 },
		{ name => "xmm3", type => 1 },
		{ name => "xmm4", type => 1 },
		{ name => "xmm5", type => 1 },
		{ name => "xmm6", type => 1 },
		{ name => "xmm7", type => 1 },
		{ name => "xmm_NOREG", type => 4 | 16 },     # we need a dummy register for NoReg nodes
		{ name => "xmm_UKNWN", type => 4 | 8 | 16},  # we need a dummy register for Unknown nodes
		{ mode => "mode_E" }
135
	],
136
137
138
139
140
141
142
143
144
145
146
147
	vfp => [
		{ name => "vf0", type => 1 | 16 },
		{ name => "vf1", type => 1 | 16 },
		{ name => "vf2", type => 1 | 16 },
		{ name => "vf3", type => 1 | 16 },
		{ name => "vf4", type => 1 | 16 },
		{ name => "vf5", type => 1 | 16 },
		{ name => "vf6", type => 1 | 16 },
		{ name => "vf7", type => 1 | 16 },
		{ name => "vfp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
		{ name => "vfp_UKNWN", type => 4 | 8 | 16 },  # we need a dummy register for Unknown nodes
		{ mode => "mode_E" }
148
	],
149
150
151
152
153
154
155
156
157
158
	st => [
		{ name => "st0", type => 1 },
		{ name => "st1", type => 1 },
		{ name => "st2", type => 1 },
		{ name => "st3", type => 1 },
		{ name => "st4", type => 1 },
		{ name => "st5", type => 1 },
		{ name => "st6", type => 1 },
		{ name => "st7", type => 1 },
		{ mode => "mode_E" }
159
	],
160
161
	fp_cw => [	# the floating point control word
		{ name => "fpcw", type => 0 },
162
 	{ mode => "mode_Hu" },
163
	],
164

165
166
); # %reg_classes

167
%cpu = (
168
169
170
171
	GP     => [ 1, "GP_EAX", "GP_EBX", "GP_ECX", "GP_EDX", "GP_ESI", "GP_EDI", "GP_EBP" ],
	SSE    => [ 1, "SSE_XMM0", "SSE_XMM1", "SSE_XMM2", "SSE_XMM3", "SSE_XMM4", "SSE_XMM5", "SSE_XMM6", "SSE_XMM7" ],
	VFP    => [ 1, "VFP_VF0", "VFP_VF1", "VFP_VF2", "VFP_VF3", "VFP_VF4", "VFP_VF5", "VFP_VF6", "VFP_VF7" ],
	BRANCH => [ 1, "BRANCH1", "BRANCH2" ],
172
173
); # %cpu

174
%vliw = (
175
176
	bundle_size       => 1,
	bundels_per_cycle => 1
177
178
); # vliw

179
%emit_templates = (
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
	S1 => "${arch}_emit_source_register(env, node, 0);",
	S2 => "${arch}_emit_source_register(env, node, 1);",
	S3 => "${arch}_emit_source_register(env, node, 2);",
	S4 => "${arch}_emit_source_register(env, node, 3);",
	S5 => "${arch}_emit_source_register(env, node, 4);",
	S6 => "${arch}_emit_source_register(env, node, 5);",
	D1 => "${arch}_emit_dest_register(env, node, 0);",
	D2 => "${arch}_emit_dest_register(env, node, 1);",
	D3 => "${arch}_emit_dest_register(env, node, 2);",
	D4 => "${arch}_emit_dest_register(env, node, 3);",
	D5 => "${arch}_emit_dest_register(env, node, 4);",
	D6 => "${arch}_emit_dest_register(env, node, 5);",
	A1 => "${arch}_emit_in_node_name(env, node, 0);",
	A2 => "${arch}_emit_in_node_name(env, node, 1);",
	A3 => "${arch}_emit_in_node_name(env, node, 2);",
	A4 => "${arch}_emit_in_node_name(env, node, 3);",
	A5 => "${arch}_emit_in_node_name(env, node, 4);",
	A6 => "${arch}_emit_in_node_name(env, node, 5);",
	X1 => "${arch}_emit_x87_name(env, node, 0);",
	X2 => "${arch}_emit_x87_name(env, node, 1);",
	X3 => "${arch}_emit_x87_name(env, node, 2);",
	C  => "${arch}_emit_immediate(env, node);",
	SE => "${arch}_emit_extend_suffix(env, get_ia32_ls_mode(node));",
	ME => "if(get_mode_size_bits(get_ia32_ls_mode(node)) != 32)\n
Matthias Braun's avatar
Matthias Braun committed
204
	ia32_emit_mode_suffix(env, get_ia32_ls_mode(node));",
205
206
207
208
209
210
211
212
	M  => "${arch}_emit_mode_suffix(env, get_ia32_ls_mode(node));",
	XM => "${arch}_emit_x87_mode_suffix(env, node);",
	XXM => "${arch}_emit_xmm_mode_suffix(env, node);",
	XSD => "${arch}_emit_xmm_mode_suffix_s(env, node);",
	AM => "${arch}_emit_am(env, node);",
	unop => "${arch}_emit_unop(env, node);",
	binop => "${arch}_emit_binop(env, node);",
	x87_binop => "${arch}_emit_x87_binop(env, node);",
213
214
);

215
216
217
218
219
220
221
222
223
224
225
#--------------------------------------------------#
#                        _                         #
#                       (_)                        #
#  _ __   _____      __  _ _ __    ___  _ __  ___  #
# | '_ \ / _ \ \ /\ / / | | '__|  / _ \| '_ \/ __| #
# | | | |  __/\ V  V /  | | |    | (_) | |_) \__ \ #
# |_| |_|\___| \_/\_/   |_|_|     \___/| .__/|___/ #
#                                      | |         #
#                                      |_|         #
#--------------------------------------------------#

226
$default_cmp_attr = "return ia32_compare_attr(attr_a, attr_b);";
227

Michael Beck's avatar
Michael Beck committed
228
229
230
%operands = (
);

231
232
%nodes = (

Christian Würdig's avatar
Christian Würdig committed
233
234
235
236
237
238
239
240
241
242
#-----------------------------------------------------------------#
#  _       _                                         _            #
# (_)     | |                                       | |           #
#  _ _ __ | |_ ___  __ _  ___ _ __   _ __   ___   __| | ___  ___  #
# | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| #
# | | | | | ||  __/ (_| |  __/ |    | | | | (_) | (_| |  __/\__ \ #
# |_|_| |_|\__\___|\__, |\___|_|    |_| |_|\___/ \__,_|\___||___/ #
#                   __/ |                                         #
#                  |___/                                          #
#-----------------------------------------------------------------#
Christian Würdig's avatar
Christian Würdig committed
243

244
245
# commutative operations

246
247
248
249
250
251
252
# NOTE:
# All nodes supporting Addressmode have 5 INs:
# 1 - base    r1 == NoReg in case of no AM or no base
# 2 - index   r2 == NoReg in case of no AM or no index
# 3 - op1     r3 == always present
# 4 - op2     r4 == NoReg in case of immediate operation
# 5 - mem     NoMem in case of no AM otherwise it takes the mem from the Load
253

254
Add => {
255
256
257
258
259
260
	irn_flags => "R",
	comment   => "construct Add: Add(a, b) = Add(b, a) = a + b",
	reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
	emit      => '. addl %binop',
	units     => [ "GP" ],
	mode      => "mode_Iu",
261
262
263
},

Adc => {
264
265
266
267
268
	comment   => "construct Add with Carry: Adc(a, b) = Add(b, a) = a + b + carry",
	reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
	emit      => '. adcl %binop',
	units     => [ "GP" ],
	mode      => "mode_Iu",
269
270
271
},

Add64Bit => {
272
273
274
275
276
	irn_flags => "R",
	comment   => "construct 64Bit Add: Add(a_l, a_h, b_l, b_h) = a_l + b_l; a_h + b_h + carry",
	arity     => 4,
	reg_req   => { in => [ "gp", "gp", "gp", "gp" ], out => [ "!in", "!in" ] },
	emit      => '
277
278
279
280
. movl %S1, %D1
. movl %S2, %D2
. addl %S3, %D1
. adcl %S4, %D2
281
',
282
283
	outs      => [ "low_res", "high_res" ],
	units     => [ "GP" ],
284
285
},

286
l_Add => {
287
288
289
290
291
	op_flags  => "C",
	irn_flags => "R",
	cmp_attr  => "return 1;",
	comment   => "construct lowered Add: Add(a, b) = Add(b, a) = a + b",
	arity     => 2,
292
293
},

294
l_Adc => {
295
296
297
298
	op_flags  => "C",
	cmp_attr  => "return 1;",
	comment   => "construct lowered Add with Carry: Adc(a, b) = Adc(b, a) = a + b + carry",
	arity     => 2,
299
300
},

301
Mul => {
302
303
304
305
306
307
308
309
	# we should not rematrialize this node. It produces 2 results and has
	# very strict constrains
	comment   => "construct MulS: MulS(a, b) = MulS(b, a) = a * b",
	reg_req   => { in => [ "gp", "gp", "eax", "gp", "none" ], out => [ "eax", "edx", "none" ] },
	emit      => '. mull %unop',
	outs      => [ "EAX", "EDX", "M" ],
	latency   => 10,
	units     => [ "GP" ],
310
311
},

312
l_Mul => {
313
314
315
316
317
318
319
	# we should not rematrialize this node. It produces 2 results and has
	# very strict constrains
	op_flags  => "C",
	cmp_attr  => "return 1;",
	comment   => "construct lowered MulS: Mul(a, b) = Mul(b, a) = a * b",
	outs      => [ "EAX", "EDX", "M" ],
	arity     => 2
320
321
322
},

IMul => {
323
324
325
326
327
328
329
	irn_flags => "R",
	comment   => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
	reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
	emit      => '. imull %binop',
	latency   => 5,
	units     => [ "GP" ],
	mode      => "mode_Iu",
330
331
332
},

IMul1OP => {
333
334
335
336
337
338
339
	irn_flags => "R",
	comment   => "construct Mul (1 operand format): Mul(a, b) = Mul(b, a) = a * b",
	reg_req   => { in => [ "gp", "gp", "eax", "gp", "none" ], out => [ "eax", "edx", "none" ] },
	emit      => '. imull %unop',
	outs      => [ "EAX", "EDX", "M" ],
	latency   => 5,
	units     => [ "GP" ],
340
341
342
},

l_IMul => {
343
344
345
346
	op_flags  => "C",
	cmp_attr  => "return 1;",
	comment   => "construct lowered IMul: IMul(a, b) = IMul(b, a) = a * b",
	arity     => 2
347
348
349
},

And => {
350
351
352
353
354
355
	irn_flags => "R",
	comment   => "construct And: And(a, b) = And(b, a) = a AND b",
	reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
	emit      => '. andl %binop',
	units     => [ "GP" ],
	mode      => "mode_Iu",
356
357
358
},

Or => {
359
360
361
362
363
364
	irn_flags => "R",
	comment   => "construct Or: Or(a, b) = Or(b, a) = a OR b",
	reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
	emit      => '. orl %binop',
	units     => [ "GP" ],
	mode      => "mode_Iu",
365
366
367
},

Xor => {
368
369
370
371
372
373
	irn_flags => "R",
	comment   => "construct Xor: Xor(a, b) = Xor(b, a) = a EOR b",
	reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
	emit      => '. xorl %binop',
	units     => [ "GP" ],
	mode      => "mode_Iu",
374
375
376
},

l_Xor => {
377
378
379
380
	op_flags  => "C",
	cmp_attr  => "return 1;",
	comment   => "construct lowered Xor: Xor(a, b) = Xor(b, a) = a XOR b",
	arity     => 2
381
382
},

383
384
# not commutative operations

385
Sub => {
386
387
388
389
390
391
	irn_flags => "R",
	comment   => "construct Sub: Sub(a, b) = a - b",
	reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
	emit      => '. subl %binop',
	units     => [ "GP" ],
	mode      => "mode_Iu",
392
393
394
},

Sbb => {
395
396
397
398
399
	comment   => "construct Sub with Carry: SubC(a, b) = a - b - carry",
	reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3 !in_r4" ] },
	emit      => '. sbbl %binop',
	units     => [ "GP" ],
	mode      => "mode_Iu",
400
401
402
},

Sub64Bit => {
403
404
405
406
407
	irn_flags => "R",
	comment   => "construct 64Bit Sub: Sub(a_l, a_h, b_l, b_h) = a_l - b_l; a_h - b_h - borrow",
	arity     => 4,
	reg_req   => { in => [ "gp", "gp", "gp", "gp" ], out => [ "!in", "!in" ] },
	emit      => '
408
409
410
411
. movl %S1, %D1
. movl %S2, %D2
. subl %S3, %D1
. sbbl %S4, %D2
412
',
413
414
	outs      => [ "low_res", "high_res" ],
	units     => [ "GP" ],
415
416
},

417
l_Sub => {
418
419
420
421
	irn_flags => "R",
	cmp_attr  => "return 1;",
	comment   => "construct lowered Sub: Sub(a, b) = a - b",
	arity     => 2,
422
423
},

424
l_Sbb => {
425
426
427
	cmp_attr  => "return 1;",
	comment   => "construct lowered Sub with Carry: SubC(a, b) = a - b - carry",
	arity     => 2,
428
429
},

430
IDiv => {
431
432
433
434
435
436
437
438
439
	op_flags  => "F|L",
	state     => "exc_pinned",
	reg_req   => { in => [ "gp", "gp", "eax", "edx", "gp", "none" ], out => [ "eax", "edx", "none" ] },
	attr      => "ia32_op_flavour_t dm_flav",
	init_attr => "attr->data.op_flav = dm_flav;",
	emit      => ". idivl %unop",
	outs      => [ "div_res", "mod_res", "M" ],
	latency   => 25,
	units     => [ "GP" ],
440
441
},

442
Div => {
443
444
445
446
447
448
449
450
451
	op_flags  => "F|L",
	state     => "exc_pinned",
	reg_req   => { in => [ "gp", "gp", "eax", "edx", "gp", "none" ], out => [ "eax", "edx", "none" ] },
	attr      => "ia32_op_flavour_t dm_flav",
	init_attr => "attr->data.op_flav = dm_flav;",
	emit      => ". divl %unop",
	outs      => [ "div_res", "mod_res", "M" ],
	latency   => 25,
	units     => [ "GP" ],
452
453
},

454
Shl => {
455
456
457
458
459
460
	irn_flags => "R",
	comment   => "construct Shl: Shl(a, b) = a << b",
	reg_req   => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] },
	emit      => '. shll %binop',
	units     => [ "GP" ],
	mode      => "mode_Iu",
461
462
},

463
l_Shl => {
464
465
466
	cmp_attr  => "return 1;",
	comment   => "construct lowered Shl: Shl(a, b) = a << b",
	arity     => 2
467
468
},

469
ShlD => {
470
471
472
473
474
475
476
477
478
479
480
481
	irn_flags => "R",
	comment   => "construct ShlD: ShlD(a, b, c) = a, b << count (shift left count bits from b into a)",
	# Out requirements is: different from all in
	# This is because, out must be different from LowPart and ShiftCount.
	# We could say "!ecx !in_r4" but it can occur, that all values live through
	# this Shift and the only value dying is the ShiftCount. Then there would be a
	# register missing, as result must not be ecx and all other registers are
	# occupied. What we should write is "!in_r4 !in_r5", but this is not supported
	# (and probably never will). So we create artificial interferences of the result
	# with all inputs, so the spiller can always assure a free register.
	reg_req   => { in => [ "gp", "gp", "gp", "gp", "ecx", "none" ], out => [ "!in" ] },
	emit      =>
482
'
483
484
485
486
487
488
489
490
491
492
493
494
if (get_ia32_immop_type(node) == ia32_ImmNone) {
	if (get_ia32_op_type(node) == ia32_AddrModeD) {
		. shldl %%cl, %S4, %AM
	} else {
		. shldl %%cl, %S4, %S3
	}
} else {
	if (get_ia32_op_type(node) == ia32_AddrModeD) {
		. shldl $%C, %S4, %AM
	} else {
		. shldl $%C, %S4, %S3
	}
495
496
}
',
497
498
499
	latency   => 6,
	units     => [ "GP" ],
	mode      => "mode_Iu",
500
501
},

502
l_ShlD => {
503
504
505
	cmp_attr  => "return 1;",
	comment   => "construct lowered ShlD: ShlD(a, b, c) = a, b << count (shift left count bits from b into a)",
	arity     => 3,
506
507
},

508
Shr => {
509
510
511
512
513
514
	irn_flags => "R",
	comment   => "construct Shr: Shr(a, b) = a >> b",
	reg_req   => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] },
	emit      => '. shrl %binop',
	units     => [ "GP" ],
	mode      => "mode_Iu",
515
516
},

517
l_Shr => {
518
519
520
	cmp_attr  => "return 1;",
	comment   => "construct lowered Shr: Shr(a, b) = a << b",
	arity     => 2
521
522
},

523
ShrD => {
524
525
526
527
528
529
530
531
532
533
534
535
	irn_flags => "R",
	comment   => "construct ShrD: ShrD(a, b, c) = a, b >> count (shift rigth count bits from a into b)",
	# Out requirements is: different from all in
	# This is because, out must be different from LowPart and ShiftCount.
	# We could say "!ecx !in_r4" but it can occur, that all values live through
	# this Shift and the only value dying is the ShiftCount. Then there would be a
	# register missing, as result must not be ecx and all other registers are
	# occupied. What we should write is "!in_r4 !in_r5", but this is not supported
	# (and probably never will). So we create artificial interferences of the result
	# with all inputs, so the spiller can always assure a free register.
	reg_req   => { in => [ "gp", "gp", "gp", "gp", "ecx", "none" ], out => [ "!in" ] },
	emit      => '
536
537
538
539
540
541
542
543
544
545
546
547
if (get_ia32_immop_type(node) == ia32_ImmNone) {
	if (get_ia32_op_type(node) == ia32_AddrModeD) {
		. shrdl %%cl, %S4, %AM
	} else {
		. shrdl %%cl, %S4, %S3
	}
} else {
	if (get_ia32_op_type(node) == ia32_AddrModeD) {
		. shrdl $%C, %S4, %AM
	} else {
		. shrdl $%C, %S4, %S3
	}
548
549
}
',
550
551
552
	latency   => 6,
	units     => [ "GP" ],
	mode      => "mode_Iu",
553
554
},

555
l_ShrD => {
556
557
558
	cmp_attr  => "return 1;",
	comment   => "construct lowered ShrD: ShrD(a, b, c) = a, b >> count (shift rigth count bits from a into b)",
	arity     => 3
559
560
},

561
Sar => {
562
563
564
565
566
567
	irn_flags => "R",
	comment   => "construct Shrs: Shrs(a, b) = a >> b",
	reg_req   => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] },
	emit      => '. sarl %binop',
	units     => [ "GP" ],
	mode      => "mode_Iu",
568
569
},

570
l_Sar => {
571
572
573
	cmp_attr  => "return 1;",
	comment   => "construct lowered Sar: Sar(a, b) = a << b",
	arity     => 2
574
575
},

576
Ror => {
577
578
579
580
581
582
	irn_flags => "R",
	comment   => "construct Ror: Ror(a, b) = a ROR b",
	reg_req   => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] },
	emit      => '. rorl %binop',
	units     => [ "GP" ],
	mode      => "mode_Iu",
583
584
},

585
Rol => {
586
587
588
589
590
591
	irn_flags => "R",
	comment   => "construct Rol: Rol(a, b) = a ROL b",
	reg_req   => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] },
	emit      => '. roll %binop',
	units     => [ "GP" ],
	mode      => "mode_Iu",
592
593
},

594
# unary operations
Christian Würdig's avatar
Christian Würdig committed
595

596
Neg => {
597
598
599
600
601
602
	irn_flags => "R",
	comment   => "construct Minus: Minus(a) = -a",
	reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
	emit      => '. negl %unop',
	units     => [ "GP" ],
	mode      => "mode_Iu",
603
604
605
},

Minus64Bit => {
606
607
608
609
610
	irn_flags => "R",
	comment   => "construct 64Bit Minus: Minus(a_l, a_h, 0) = 0 - a_l; 0 - a_h - borrow",
	arity     => 4,
	reg_req   => { in => [ "gp", "gp", "gp" ], out => [ "!in", "!in" ] },
	emit      => '
611
612
613
614
. movl %S1, %D1
. movl %S1, %D2
. subl %S2, %D1
. sbbl %S3, %D2
615
',
616
617
	outs      => [ "low_res", "high_res" ],
	units     => [ "GP" ],
618
619
620
},


621
l_Neg => {
622
623
624
	cmp_attr  => "return 1;",
	comment   => "construct lowered Minus: Minus(a) = -a",
	arity     => 1,
625
626
},

627
Inc => {
628
629
630
631
632
633
	irn_flags => "R",
	comment   => "construct Increment: Inc(a) = a++",
	reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
	emit      => '. incl %unop',
	units     => [ "GP" ],
	mode      => "mode_Iu",
Christian Würdig's avatar
Christian Würdig committed
634
635
},

636
Dec => {
637
638
639
640
641
642
	irn_flags => "R",
	comment   => "construct Decrement: Dec(a) = a--",
	reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
	emit      => '. decl %unop',
	units     => [ "GP" ],
	mode      => "mode_Iu",
643
644
},

645
Not => {
646
647
648
649
650
651
	irn_flags => "R",
	comment   => "construct Not: Not(a) = !a",
	reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
	emit      => '. notl %unop',
	units     => [ "GP" ],
	mode      => "mode_Iu",
Christian Würdig's avatar
Christian Würdig committed
652
653
},

Christian Würdig's avatar
Christian Würdig committed
654
655
# other operations

656
CondJmp => {
657
	state     => "pinned",
658
659
660
661
662
663
	op_flags  => "L|X|Y",
	comment   => "construct conditional jump: CMP A, B && JMPxx LABEL",
	reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ] },
	outs      => [ "false", "true" ],
	latency   => 3,
	units     => [ "BRANCH" ],
664
665
666
},

TestJmp => {
667
	state     => "pinned",
668
669
670
671
672
673
	op_flags  => "L|X|Y",
	comment   => "construct conditional jump: TEST A, B && JMPxx LABEL",
	reg_req  => { in => [ "gp", "gp" ] },
	outs      => [ "false", "true" ],
	latency   => 3,
	units     => [ "BRANCH" ],
674
675
676
},

CJmpAM => {
677
	state     => "pinned",
678
679
680
681
682
	op_flags  => "L|X|Y",
	comment   => "construct conditional jump without CMP (replaces CondJmp): JMPxx LABEL",
	reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "none", "none" ] },
	outs      => [ "false", "true" ],
	units     => [ "BRANCH" ],
683
684
685
},

CJmp => {
686
	state     => "pinned",
687
688
689
690
	op_flags  => "L|X|Y",
	comment   => "construct conditional jump without CMP (replaces TestJmp): JMPxx LABEL",
	reg_req   => { in => [ "gp", "gp" ] },
	units     => [ "BRANCH" ],
691
692
693
},

SwitchJmp => {
694
	state     => "pinned",
695
696
697
698
699
	op_flags  => "L|X|Y",
	comment   => "construct switch",
	reg_req   => { in => [ "gp" ], out => [ "none" ] },
	latency   => 3,
	units     => [ "BRANCH" ],
700
701
702
},

Const => {
703
704
705
706
707
708
	op_flags  => "c",
	irn_flags => "R",
	comment   => "represents an integer constant",
	reg_req   => { out => [ "gp" ] },
	units     => [ "GP" ],
	mode      => "mode_Iu",
709
710
711
},

Unknown_GP => {
712
713
714
715
716
717
718
	op_flags  => "c",
	irn_flags => "I",
	comment   => "unknown value",
	reg_req   => { out => [ "gp_UKNWN" ] },
	units     => [],
	emit      => "",
	mode      => "mode_Iu"
719
720
721
},

Unknown_VFP => {
722
723
724
725
726
727
728
	op_flags  => "c",
	irn_flags => "I",
	comment   => "unknown value",
	reg_req   => { out => [ "vfp_UKNWN" ] },
	units     => [],
	emit      => "",
	mode      => "mode_E"
729
730
731
},

Unknown_XMM => {
732
733
734
735
736
737
738
	op_flags  => "c",
	irn_flags => "I",
	comment   => "unknown value",
	reg_req   => { out => [ "xmm_UKNWN" ] },
	units     => [],
	emit      => "",
	mode      => "mode_E"
739
740
741
},

NoReg_GP => {
742
743
744
745
746
747
748
	op_flags  => "c",
	irn_flags => "I",
	comment   => "unknown GP value",
	reg_req   => { out => [ "gp_NOREG" ] },
	units     => [],
	emit      => "",
	mode      => "mode_Iu"
749
750
751
},

NoReg_VFP => {
752
753
754
755
756
757
758
	op_flags  => "c",
	irn_flags => "I",
	comment   => "unknown VFP value",
	reg_req   => { out => [ "vfp_NOREG" ] },
	units     => [],
	emit      => "",
	mode      => "mode_E"
759
760
761
},

NoReg_XMM => {
762
763
764
765
766
767
768
	op_flags  => "c",
	irn_flags => "I",
	comment   => "unknown XMM value",
	reg_req   => { out => [ "xmm_NOREG" ] },
	units     => [],
	emit      => "",
	mode      => "mode_E"
769
770
771
},

ChangeCW => {
772
773
774
775
776
777
	irn_flags => "R",
	comment   => "change floating point control word",
	reg_req   => { out => [ "fp_cw" ] },
	mode      => "mode_Hu",
	latency   => 3,
	units     => [ "GP" ],
778
779
780
},

FldCW => {
781
782
783
784
785
786
787
788
	op_flags  => "L|F",
	state     => "exc_pinned",
	comment   => "load floating point control word FldCW(ptr, mem) = LD ptr -> reg",
	reg_req   => { in => [ "gp", "gp", "none" ], out => [ "fp_cw" ] },
	latency   => 5,
	emit      => ". fldcw %AM",
	mode      => "mode_Hu",
	units     => [ "GP" ],
789
790
791
},

FstCW => {
792
793
794
795
796
797
798
799
	op_flags  => "L|F",
	state     => "exc_pinned",
	comment   => "store floating point control word: FstCW(ptr, mem) = ST ptr -> reg",
	reg_req   => { in => [ "gp", "gp", "fp_cw", "none" ] },
	latency   => 5,
	emit      => ". fstcw %AM",
	mode      => "mode_M",
	units     => [ "GP" ],
800
801
802
},

Cltd => {
803
804
805
806
807
808
809
	# we should not rematrialize this node. It produces 2 results and has
	# very strict constrains
	comment   => "construct CDQ: sign extend EAX -> EDX:EAX",
	reg_req   => { in => [ "gp" ], out => [ "eax in_r1", "edx" ] },
	emit      => '. cltd',
	outs      => [ "EAX", "EDX" ],
	units     => [ "GP" ],
810
811
},

Christian Würdig's avatar
Christian Würdig committed
812
813
# Load / Store

814
Load => {
815
816
817
818
819
820
821
822
	op_flags  => "L|F",
	state     => "exc_pinned",
	comment   => "construct Load: Load(ptr, mem) = LD ptr -> reg",
	reg_req   => { in => [ "gp", "gp", "none" ], out => [ "gp", "none" ] },
	latency   => 3,
	emit      => ". mov%SE%ME%.l %AM, %D1",
	outs      => [ "res", "M" ],
	units     => [ "GP" ],
823
824
825
},

l_Load => {
826
827
828
829
830
	op_flags  => "L|F",
	cmp_attr  => "return 1;",
	comment   => "construct lowered Load: Load(ptr, mem) = LD ptr -> reg",
	outs      => [ "res", "M" ],
	arity     => 2,
831
832
833
},

l_Store => {
834
835
836
837
838
839
	op_flags  => "L|F",
	cmp_attr  => "return 1;",
	state     => "exc_pinned",
	comment   => "construct lowered Store: Store(ptr, val, mem) = ST ptr,val",
	arity     => 3,
	mode      => "mode_M",
840
841
842
},

Store => {
843
844
845
846
847
848
849
850
	op_flags  => "L|F",
	state     => "exc_pinned",
	comment   => "construct Store: Store(ptr, val, mem) = ST ptr,val",
	reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "none" ] },
	emit      => '. mov%M %binop',
	latency   => 3,
	units     => [ "GP" ],
	mode      => "mode_M",
851
852
853
},

Store8Bit => {
854
855
856
857
858
859
860
861
	op_flags  => "L|F",
	state     => "exc_pinned",
	comment   => "construct 8Bit Store: Store(ptr, val, mem) = ST ptr,val",
	reg_req   => { in => [ "gp", "gp", "eax ebx ecx edx", "none" ], out => ["none" ] },
	emit      => '. mov%M %binop',
	latency   => 3,
	units     => [ "GP" ],
	mode      => "mode_M",
862
863
864
},

Lea => {
865
866
867
868
869
870
871
	irn_flags => "R",
	comment   => "construct Lea: Lea(a,b) = lea [a+b*const+offs] | res = a + b * const + offs with const = 0,1,2,4,8",
	reg_req   => { in => [ "gp", "gp" ], out => [ "in_r1" ] },
	emit      => '. leal %AM, %D1',
	latency   => 2,
	units     => [ "GP" ],
	mode      => "mode_Iu",
872
873
874
},

Push => {
875
876
877
878
879
880
	comment   => "push on the stack",
	reg_req   => { in => [ "gp", "gp", "gp", "esp", "none" ], out => [ "esp", "none" ] },
	emit      => '. pushl %unop',
	outs      => [ "stack:I|S", "M" ],
	latency   => 3,
	units     => [ "GP" ],
881
882
883
},

Pop => {
884
885
886
887
888
889
	comment   => "pop a gp register from the stack",
	reg_req   => { in => [ "gp", "gp", "esp", "none" ], out => [ "esp", "gp", "none" ] },
	emit      => '. popl %unop',
	outs      => [ "stack:I|S", "res", "M" ],
	latency   => 4,
	units     => [ "GP" ],
890
891
892
},

Enter => {
893
894
895
896
897
898
	comment   => "create stack frame",
	reg_req   => { in => [ "esp" ], out => [ "ebp", "esp" ] },
	emit      => '. enter',
	outs      => [ "frame:I", "stack:I|S", "M" ],
	latency   => 15,
	units     => [ "GP" ],
899
900
901
},

Leave => {
902
903
904
905
906
907
	comment   => "destroy stack frame",
	reg_req   => { in => [ "esp", "ebp" ], out => [ "ebp", "esp" ] },
	emit      => '. leave',
	outs      => [ "frame:I", "stack:I|S" ],
	latency   => 3,
	units     => [ "GP" ],
908
909
910
},

AddSP => {
911
912
913
914
915
916
	irn_flags => "I",
	comment   => "allocate space on stack",
	reg_req   => { in => [ "gp", "gp", "esp", "gp", "none" ], out => [ "in_r3", "none" ] },
	emit      => '. addl %binop',
	outs      => [ "stack:S", "M" ],
	units     => [ "GP" ],
917
918
919
},

SubSP => {
920
921
922
923
924
925
	irn_flags => "I",
	comment   => "free space on stack",
	reg_req   => { in => [ "gp", "gp", "esp", "gp", "none" ], out => [ "in_r3", "none" ] },
	emit      => '. subl %binop',
	outs      => [ "stack:S", "M" ],
	units     => [ "GP" ],
926
927
928
},

LdTls => {
929
930
931
932
	irn_flags => "R",
	comment   => "get the TLS base address",
	reg_req   => { out => [ "gp" ] },
	units     => [ "GP" ],
Michael Beck's avatar
Michael Beck committed
933
934
935
936
},



Michael Beck's avatar
Michael Beck committed
937
938
939
940
941
942
943
944
#-----------------------------------------------------------------------------#
#   _____ _____ ______    __ _             _                     _            #
#  / ____/ ____|  ____|  / _| |           | |                   | |           #
# | (___| (___ | |__    | |_| | ___   __ _| |_   _ __   ___   __| | ___  ___  #
#  \___ \\___ \|  __|   |  _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
#  ____) |___) | |____  | | | | (_) | (_| | |_  | | | | (_) | (_| |  __/\__ \ #
# |_____/_____/|______| |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
#-----------------------------------------------------------------------------#
Christian Würdig's avatar
Christian Würdig committed
945
946
947

# commutative operations

948
xAdd => {
949
950
951
952
953
954
955
	irn_flags => "R",
	comment   => "construct SSE Add: Add(a, b) = Add(b, a) = a + b",
	reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
	emit      => '. add%XXM %binop',
	latency   => 4,
	units     => [ "SSE" ],
	mode      => "mode_E",
956
957
958
},

xMul => {
959
960
961
962
963
964
965
	irn_flags => "R",
	comment   => "construct SSE Mul: Mul(a, b) = Mul(b, a) = a * b",
	reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
	emit      => '. mul%XXM %binop',
	latency   => 4,
	units     => [ "SSE" ],
	mode      => "mode_E",
966
967
968
},

xMax => {
969
970
971
972
973
974
975
	irn_flags => "R",
	comment   => "construct SSE Max: Max(a, b) = Max(b, a) = a > b ? a : b",
	reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
	emit      => '. max%XXM %binop',
	latency   => 2,
	units     => [ "SSE" ],
	mode      => "mode_E",
976
977
978
},

xMin => {
979
980
981
982
983
984
985
	irn_flags => "R",
	comment   => "construct SSE Min: Min(a, b) = Min(b, a) = a < b ? a : b",
	reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
	emit      => '. min%XXM %binop',
	latency   => 2,
	units     => [ "SSE" ],
	mode      => "mode_E",
986
987
988
},

xAnd => {
989
990
991
992
993
994
995
	irn_flags => "R",
	comment   => "construct SSE And: And(a, b) = a AND b",
	reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
	emit      => '. andp%XSD %binop',
	latency   => 3,
	units     => [ "SSE" ],
	mode      => "mode_E",
996
997
998
},

xOr => {
999
1000
	irn_flags => "R",
	comment   => "construct SSE Or: Or(a, b) = a OR b",