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
108
#  32 - register represents a state
Christian Würdig's avatar
Christian Würdig committed
109
# NOTE: Last entry of each class is the largest Firm-Mode a register can hold
110
%reg_classes = (
111
112
113
114
115
116
117
118
119
120
121
122
	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" }
123
	],
124
125
126
127
128
129
130
131
132
133
134
135
	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" }
136
	],
137
138
139
140
141
142
143
144
145
146
147
148
	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" }
149
	],
150
151
152
153
154
155
156
157
158
159
	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" }
160
	],
161
	fp_cw => [	# the floating point control word
162
163
		{ name => "fpcw", type => 32 },
		{ mode => "mode_Hu" },
164
	],
165

166
167
); # %reg_classes

168
%cpu = (
169
170
171
172
	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" ],
173
174
); # %cpu

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

180
%emit_templates = (
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
	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
205
	ia32_emit_mode_suffix(env, get_ia32_ls_mode(node));",
206
207
208
209
210
211
212
213
	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);",
214
215
);

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

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

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

232
233
%nodes = (

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

245
246
# commutative operations

247
248
249
250
251
252
253
# 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
254

255
Add => {
256
257
258
259
260
261
	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",
262
263
264
},

Adc => {
265
266
267
268
269
	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",
270
271
272
},

Add64Bit => {
273
274
275
276
277
	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      => '
278
279
280
281
. movl %S1, %D1
. movl %S2, %D2
. addl %S3, %D1
. adcl %S4, %D2
282
',
283
284
	outs      => [ "low_res", "high_res" ],
	units     => [ "GP" ],
285
286
},

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

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

302
Mul => {
303
304
305
306
307
308
309
310
	# 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" ],
311
312
},

313
l_Mul => {
314
315
316
317
318
319
320
	# 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
321
322
323
},

IMul => {
324
325
326
327
328
329
330
	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",
331
332
333
},

IMul1OP => {
334
335
336
337
338
339
340
	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" ],
341
342
343
},

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

And => {
351
352
353
354
355
356
	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",
357
358
359
},

Or => {
360
361
362
363
364
365
	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",
366
367
368
},

Xor => {
369
370
371
372
373
374
	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",
375
376
377
},

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

384
385
# not commutative operations

386
Sub => {
387
388
389
390
391
392
	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",
393
394
395
},

Sbb => {
396
397
398
399
400
	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",
401
402
403
},

Sub64Bit => {
404
405
406
407
408
	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      => '
409
410
411
412
. movl %S1, %D1
. movl %S2, %D2
. subl %S3, %D1
. sbbl %S4, %D2
413
',
414
415
	outs      => [ "low_res", "high_res" ],
	units     => [ "GP" ],
416
417
},

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

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

431
IDiv => {
432
433
434
435
436
437
438
439
440
	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" ],
441
442
},

443
Div => {
444
445
446
447
448
449
450
451
452
	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" ],
453
454
},

455
Shl => {
456
457
458
459
460
461
	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",
462
463
},

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

470
ShlD => {
471
472
473
474
475
476
477
478
479
480
481
482
	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      =>
483
'
484
485
486
487
488
489
490
491
492
493
494
495
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
	}
496
497
}
',
498
499
500
	latency   => 6,
	units     => [ "GP" ],
	mode      => "mode_Iu",
501
502
},

503
l_ShlD => {
504
505
506
	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,
507
508
},

509
Shr => {
510
511
512
513
514
515
	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",
516
517
},

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

524
ShrD => {
525
526
527
528
529
530
531
532
533
534
535
536
	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      => '
537
538
539
540
541
542
543
544
545
546
547
548
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
	}
549
550
}
',
551
552
553
	latency   => 6,
	units     => [ "GP" ],
	mode      => "mode_Iu",
554
555
},

556
l_ShrD => {
557
558
559
	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
560
561
},

562
Sar => {
563
564
565
566
567
568
	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",
569
570
},

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

577
Ror => {
578
579
580
581
582
583
	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",
584
585
},

586
Rol => {
587
588
589
590
591
592
	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",
593
594
},

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

597
Neg => {
598
599
600
601
602
603
	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",
604
605
606
},

Minus64Bit => {
607
608
609
610
611
	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      => '
612
613
614
615
. movl %S1, %D1
. movl %S1, %D2
. subl %S2, %D1
. sbbl %S3, %D2
616
',
617
618
	outs      => [ "low_res", "high_res" ],
	units     => [ "GP" ],
619
620
621
},


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

628
Inc => {
629
630
631
632
633
634
	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
635
636
},

637
Dec => {
638
639
640
641
642
643
	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",
644
645
},

646
Not => {
647
648
649
650
651
652
	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
653
654
},

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

657
CondJmp => {
658
	state     => "pinned",
659
660
661
662
663
664
	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" ],
665
666
667
},

TestJmp => {
668
	state     => "pinned",
669
670
671
672
673
674
	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" ],
675
676
677
},

CJmpAM => {
678
	state     => "pinned",
679
680
681
682
683
	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" ],
684
685
686
},

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

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

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

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

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

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

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

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

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

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

FldCW => {
782
783
784
785
786
787
788
789
	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" ],
790
791
792
},

FstCW => {
793
794
795
796
797
798
799
800
	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" ],
801
802
803
},

Cltd => {
804
805
806
807
808
809
810
	# 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" ],
811
812
},

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

815
Load => {
816
817
818
819
820
821
822
823
	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" ],
824
825
826
},

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

l_Store => {
835
836
837
838
839
840
	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",
841
842
843
},

Store => {
844
845
846
847
848
849
850
851
	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",
852
853
854
},

Store8Bit => {
855
856
857
858
859
860
861
862
	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",
863
864
865
},

Lea => {
866
867
868
869
870
871
872
	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",
873
874
875
},

Push => {
876
877
878
879
880
881
	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" ],
882
883
884
},

Pop => {
885
886
887
888
889
890
	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" ],
891
892
893
},

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

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

AddSP => {
912
913
914
915
916
917
	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" ],
918
919
920
},

SubSP => {
921
922
923
924
925
926
	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" ],
927
928
929
},

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



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

# commutative operations

949
xAdd => {
950
951
952
953
954
955
956
	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",
957
958
959
},

xMul => {
960
961
962
963
964
965
966
	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",
967
968
969
},

xMax => {
970
971
972
973
974
975
976
	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",
977
978
979
},

xMin => {
980
981
982
983
984
985
986
	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",
987
988
989
},

xAnd => {
990
991
992
993
994
995
996
	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",
997
998
999
},

xOr => {
1000
	irn_flags => "R",