ia32_spec.pl 42.8 KB
Newer Older
1
2
# This is the specification for the ia32 assembler Firm-operations

3
4
5
6
7
8
9
10
11
12
13
# Note on Proj numbers:
# If possible, Nodes should follow these rules for assigning proj numbers:
# "Normal" instructions:
#  0 => result
#  1 => flags
#  2 => memory
# instructions with destination address mode:
#  0 => unused
#  1 => flags
#  2 => memory

14
15
$arch = "ia32";

16
17
18
19
20
$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";
21

22
%reg_classes = (
23
	gp => [
24
25
26
27
28
29
30
		{ name => "edx", encoding => 2, dwarf => 2 },
		{ name => "ecx", encoding => 1, dwarf => 1 },
		{ name => "eax", encoding => 0, dwarf => 0 },
		{ name => "ebx", encoding => 3, dwarf => 3 },
		{ name => "esi", encoding => 6, dwarf => 6 },
		{ name => "edi", encoding => 7, dwarf => 7 },
		{ name => "ebp", encoding => 5, dwarf => 5 },
31
32
		{ name => "esp", encoding => 4, dwarf => 4 },
		{ name => "gp_NOREG", type => "virtual" }, # we need a dummy register for NoReg nodes
33
		{ mode => $mode_gp }
34
	],
35
	xmm => [
36
37
38
39
40
41
42
43
		{ name => "xmm0", dwarf => 21 },
		{ name => "xmm1", dwarf => 22 },
		{ name => "xmm2", dwarf => 23 },
		{ name => "xmm3", dwarf => 24 },
		{ name => "xmm4", dwarf => 25 },
		{ name => "xmm5", dwarf => 26 },
		{ name => "xmm6", dwarf => 27 },
		{ name => "xmm7", dwarf => 28 },
44
		{ name => "xmm_NOREG", type => "virtual" }, # we need a dummy register for NoReg nodes
45
		{ mode => $mode_xmm }
46
	],
47
	fp => [
48
49
50
51
52
53
54
55
		{ name => "st0", realname => "st",    encoding => 0, dwarf => 11 },
		{ name => "st1", realname => "st(1)", encoding => 1, dwarf => 12 },
		{ name => "st2", realname => "st(2)", encoding => 2, dwarf => 13 },
		{ name => "st3", realname => "st(3)", encoding => 3, dwarf => 14 },
		{ name => "st4", realname => "st(4)", encoding => 4, dwarf => 15 },
		{ name => "st5", realname => "st(5)", encoding => 5, dwarf => 16 },
		{ name => "st6", realname => "st(6)", encoding => 6, dwarf => 17 },
		{ name => "st7", realname => "st(7)", encoding => 7, dwarf => 18 },
56
		{ name => "fp_NOREG", type => "virtual" }, # we need a dummy register for NoReg nodes
57
		{ mode => $mode_fp87 }
58
	],
59
	fp_cw => [	# the floating point control word
60
		{ name => "fpcw", dwarf => 37 },
61
		{ mode => $mode_fpcw, flags => "manual_ra" }
62
	],
63
	flags => [
64
		{ name => "eflags", dwarf => 9 },
65
		{ mode => "ia32_mode_flags", flags => "manual_ra" }
66
	],
67
);
68

69
70
$default_attr_type = "ia32_attr_t";
$default_copy_attr = "ia32_copy_attr";
71

72
sub ia32_custom_init_attr {
73
74
75
76
77
78
	my ($constr, $node, $name) = @_;

	my $res = "";
	my $am  = $node->{am};
	if (defined($am)) {
		if ($am eq "source,unary") {
79
			$res .= "\tset_ia32_am_support(res, ia32_am_unary);";
80
		} elsif ($am eq "source,binary") {
81
			$res .= "\tset_ia32_am_support(res, ia32_am_binary);";
82
		} elsif ($am eq "none") {
83
84
85
86
			# nothing to do
		} else {
			die("Invalid address mode '$am' specified on op $name");
		}
87
88
		if ($am ne "none" && $node->{state} ne "exc_pinned" && $node->{state} ne "pinned") {
			die("AM nodes must have pinned or AM pinned state ($name)");
89
		}
90
91
92
93
94
	}
	return $res;
}
$custom_init_attr_func = \&ia32_custom_init_attr;

95
%init_attr = (
96
97
	ia32_attr_t =>
		"init_ia32_attributes(res, irn_flags, in_reqs, n_res);",
98
	ia32_call_attr_t =>
99
		"init_ia32_attributes(res, irn_flags, in_reqs, n_res);\n".
100
		"\tinit_ia32_call_attributes(res, pop, call_tp);",
Christoph Mallon's avatar
Christoph Mallon committed
101
	ia32_condcode_attr_t =>
102
		"init_ia32_attributes(res, irn_flags, in_reqs, n_res);\n".
103
104
		"\tinit_ia32_condcode_attributes(res, condition_code);",
	ia32_switch_attr_t =>
105
		"init_ia32_attributes(res, irn_flags, in_reqs, n_res);\n".
Matthias Braun's avatar
Matthias Braun committed
106
		"\tinit_ia32_switch_attributes(res, switch_table);",
Michael Beck's avatar
Michael Beck committed
107
	ia32_copyb_attr_t =>
108
		"init_ia32_attributes(res, irn_flags, in_reqs, n_res);\n".
Michael Beck's avatar
Michael Beck committed
109
		"\tinit_ia32_copyb_attributes(res, size);",
Christoph Mallon's avatar
Christoph Mallon committed
110
	ia32_immediate_attr_t =>
111
		"init_ia32_attributes(res, irn_flags, in_reqs, n_res);\n".
112
		"\tinit_ia32_immediate_attributes(res, imm);",
Christoph Mallon's avatar
Christoph Mallon committed
113
	ia32_x87_attr_t =>
114
		"init_ia32_attributes(res, irn_flags, in_reqs, n_res);\n".
Christoph Mallon's avatar
Christoph Mallon committed
115
		"\tinit_ia32_x87_attributes(res);",
116
	ia32_climbframe_attr_t =>
117
		"init_ia32_attributes(res, irn_flags, in_reqs, n_res);\n".
118
		"\tinit_ia32_climbframe_attributes(res, count);",
119
	ia32_return_attr_t =>
120
		"init_ia32_attributes(res, irn_flags, in_reqs, n_res);\n".
121
		"\tinit_ia32_return_attributes(res, pop);",
122
123
);

124
125
my $x87sim = "ia32_request_x87_sim(irg);";

126
my $binop_commutative = {
127
128
	irn_flags => [ "modify_flags", "rematerializable" ],
	state     => "exc_pinned",
129
130
	in_reqs   => [ "gp", "gp", "mem", "gp", "gp" ],
	out_reqs  => [ "in_r4 in_r5", "flags", "mem" ],
131
132
133
	ins       => [ "base", "index", "mem", "left", "right" ],
	outs      => [ "res", "flags", "M" ],
	am        => "source,binary",
134
	mode      => "first",
135
136
};

137
my $binop_flags = {
138
	irn_flags => [ "modify_flags", "rematerializable" ],
139
140
	state     => "exc_pinned",
	constructors => {
141
142
		""     => { in_reqs => [ "gp", "gp", "mem", "gp", "gp" ], },
		"8bit" => { in_reqs => [ "gp", "gp", "mem", "eax ebx ecx edx", "eax ebx ecx edx" ], }
143
	},
144
	out_reqs  => [ "flags", "none", "mem" ],
145
146
147
148
	ins       => [ "base", "index", "mem", "left", "right" ],
	outs      => [ "eflags", "unused", "M" ],
	am        => "source,binary",
	attr      => "bool ins_permuted",
149
	init      => "attr->ins_permuted = ins_permuted;",
150
	mode      => "first",
151
};
152

153
my $binop_mem = {
154
155
	irn_flags => [ "modify_flags", "rematerializable" ],
	state     => "exc_pinned",
156
	constructors => {
157
158
		""     => { in_reqs => [ "gp", "gp", "mem", "gp" ] },
		"8bit" => { in_reqs => [ "gp", "gp", "mem", "eax ebx ecx edx" ] },
159
	},
160
161
162
	out_reqs  => [ "none", "flags", "mem" ],
	ins       => [ "base", "index", "mem", "val" ],
	outs      => [ "unused", "flags", "M" ],
163
};
164

165
my $shiftop = {
166
167
168
169
170
	irn_flags => [ "modify_flags", "rematerializable" ],
	in_reqs   => [ "gp", "ecx" ],
	out_reqs  => [ "in_r1 !in_r2", "flags" ],
	ins       => [ "val", "count" ],
	outs      => [ "res", "flags" ],
171
	mode      => "first",
172
173
174
};

my $shiftop_mem = {
175
176
	irn_flags => [ "modify_flags", "rematerializable" ],
	state     => "exc_pinned",
177
178
	in_reqs   => [ "gp", "gp", "mem", "ecx" ],
	out_reqs  => [ "none", "flags", "mem" ],
179
180
	ins       => [ "base", "index", "mem", "count" ],
	outs      => [ "unused", "flags", "M" ],
181
182
183
};

my $shiftop_double = {
184
185
	irn_flags => [ "modify_flags", "rematerializable" ],
	in_reqs   => [ "gp", "gp", "ecx" ],
186
	constructors => {
187
		""  => { out_reqs  => [ "in_r1 !in_r2 !in_r3", "flags" ] },
188
189
190
		# 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.
191
		imm => { out_reqs  => [ "in_r1 in_r2",         "flags" ] },
192
	},
193
194
	ins       => [ "val_high", "val_low", "count" ],
	outs      => [ "res", "flags" ],
195
	mode      => "first",
196
197
198
};

my $divop = {
199
200
201
	op_flags  => [ "fragile", "uses_memory" ],
	irn_flags => [ "modify_flags" ],
	state     => "exc_pinned",
202
	in_reqs   => [ "gp", "gp", "mem", "gp", "eax", "edx" ],
203
	out_reqs  => [ "eax", "flags", "mem", "edx", "exec", "exec" ],
204
205
206
	ins       => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
	outs      => [ "div_res", "flags", "M", "mod_res", "X_regular", "X_except" ],
	am        => "source,unary",
207
208
209
};

my $mulop = {
210
211
	# we should not rematerialize these nodes. They produce 2 results and have
	# very strict constraints
212
213
	irn_flags => [ "modify_flags" ],
	state     => "exc_pinned",
214
215
	in_reqs   => [ "gp", "gp", "mem", "eax", "gp" ],
	out_reqs  => [ "eax", "flags", "mem", "edx" ],
216
217
218
	ins       => [ "base", "index", "mem", "left", "right" ],
	outs      => [ "res_low", "flags", "M", "res_high" ],
	am        => "source,binary",
219
220
221
};

my $unop = {
222
	irn_flags => [ "modify_flags", "rematerializable" ],
223
224
	in_reqs   => [ "gp" ],
	out_reqs  => [ "in_r1", "flags" ],
225
226
	ins       => [ "val" ],
	outs      => [ "res", "flags" ],
227
	mode      => "first",
228
229
230
};

my $unop_no_flags = {
231
	# no flags modified
232
	irn_flags => [ "rematerializable" ],
233
234
	in_reqs   => [ "gp" ],
	out_reqs  => [ "in_r1" ],
235
236
237
238
239
	ins       => [ "val" ],
	outs      => [ "res" ],
};

my $unop_from_mem = {
240
241
	irn_flags => [ "modify_flags", "rematerializable" ],
	state     => "exc_pinned",
242
243
	in_reqs   => [ "gp", "gp", "mem", "gp" ],
	out_reqs  => [ "gp", "flags", "mem" ],
244
245
246
	ins       => [ "base", "index", "mem", "operand" ],
	outs      => [ "res", "flags", "M" ],
	am        => "source,unary",
247
	mode      => "first",
248
249
250
};

my $unop_mem = {
251
	irn_flags => [ "modify_flags", "rematerializable" ],
252
	state     => "exc_pinned",
253
254
	in_reqs   => [ "gp", "gp", "mem" ],
	out_reqs  => [ "none", "flags", "mem" ],
255
256
257
258
259
	ins       => [ "base", "index", "mem" ],
	outs      => [ "unused", "flags", "M" ],
};

my $memop = {
260
	state    => "pinned",
261
262
	in_reqs  => [ "mem" ],
	out_reqs => [ "mem" ],
263
	ins      => [ "mem" ],
264
265
266
267
268
};

my $prefetchop = {
	op_flags  => [ "uses_memory" ],
	state     => "exc_pinned",
269
270
	in_reqs   => [ "gp", "gp", "mem" ],
	out_reqs  => [ "mem" ],
271
272
273
274
275
276
277
	ins       => [ "base", "index", "mem" ],
	outs      => [ "M" ],
};

my $fbinop = {
#	irn_flags => [ "rematerializable" ],
	state     => "exc_pinned",
278
279
	in_reqs   => [ "gp", "gp", "mem", "fp", "fp", "fpcw" ],
	out_reqs  => [ "fp", "none", "mem" ],
280
281
282
	ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
	outs      => [ "res", "dummy", "M" ],
	am        => "source,binary",
283
	mode      => "first",
284
285
286
287
288
	attr_type => "ia32_x87_attr_t",
};

my $funop = {
	irn_flags => [ "rematerializable" ],
289
290
	in_reqs   => [ "fp" ],
	out_reqs  => [ "fp" ],
291
	ins       => [ "value" ],
292
	init      => "attr->ls_mode = ia32_mode_E;",
293
294
295
296
297
};

my $fconstop = {
	op_flags  => [ "constlike" ],
	irn_flags => [ "rematerializable" ],
298
	out_reqs  => [ "fp" ],
299
	outs      => [ "res" ],
300
	init      => "attr->ls_mode = ia32_mode_E;",
301
	fixed     => $x87sim,
302
303
304
305
306
};

my $valueop = {
	op_flags  => [ "constlike" ],
	irn_flags => [ "rematerializable" ],
307
	out_reqs  => [ "gp" ],
308
309
310
	outs      => [ "res" ],
};

311
312
313
314
315
316
317
my $fpopop = {
	op_flags    => [ "keep" ],
	out_reqs    => [ "none" ],
	attrs_equal => "attrs_equal_false",
	attr_type   => "ia32_x87_attr_t",
};

318
319
320
my $xbinop = {
	irn_flags => [ "rematerializable" ],
	state     => "exc_pinned",
321
322
	in_reqs   => [ "gp", "gp", "mem", "xmm", "xmm" ],
	out_reqs  => [ "in_r4 !in_r5", "flags", "mem" ],
323
324
325
	ins       => [ "base", "index", "mem", "left", "right" ],
	outs      => [ "res", "flags", "M" ],
	am        => "source,binary",
326
	mode      => "first",
327
328
329
330
331
};

my $xbinop_commutative = {
	irn_flags => [ "rematerializable" ],
	state     => "exc_pinned",
332
333
	in_reqs   => [ "gp", "gp", "mem", "xmm", "xmm" ],
	out_reqs  => [ "in_r4 in_r5", "flags", "mem" ],
334
335
336
	ins       => [ "base", "index", "mem", "left", "right" ],
	outs      => [ "res", "flags", "M" ],
	am        => "source,binary",
337
	mode      => "first",
338
339
340
};

my $xconv_i2f = {
341
	state    => "exc_pinned",
342
	in_reqs  => [ "gp", "gp", "mem", "gp" ],
343
344
345
	out_reqs => [ "xmm" ],
	ins      => [ "base", "index", "mem", "val" ],
	am       => "source,unary",
346
347
348
349
};

my $xshiftop = {
	irn_flags => [ "rematerializable" ],
350
351
	in_reqs   => [ "xmm", "xmm" ],
	out_reqs  => [ "in_r1 !in_r2" ],
352
353
354
355
356
};

my $xvalueop = {
	op_flags  => [ "constlike" ],
	irn_flags => [ "rematerializable" ],
357
	out_reqs  => [ "xmm" ],
358
359
360
	outs      => [ "res" ],
};

361
362
363
364
365
366
my $carry_user_op = {
	irn_flags => [ "modify_flags" ],
	attr_type => "ia32_condcode_attr_t",
	fixed     => "x86_condition_code_t condition_code = x86_cc_carry;",
};

367
368
369
370
371
372
my $noregop = {
	state     => "pinned",
	op_flags  => [ "constlike", "dump_noblock" ],
	irn_flags => [ "not_scheduled" ],
};

373
374
%nodes = (

375
376
Immediate => {
	state     => "pinned",
377
	op_flags  => [ "constlike" ],
378
	irn_flags => [ "not_scheduled" ],
379
	out_reqs  => [ "gp_NOREG:I" ],
380
	attr      => "const x86_imm32_t *imm",
381
	attr_type => "ia32_immediate_attr_t",
382
	hash_func => "ia32_hash_Immediate",
383
	latency   => 0,
384
},
385

386
Add => {
387
388
389
	template => $binop_commutative,
	emit     => "add%M %B",
	latency  => 1,
390
391
},

392
AddMem => {
393
394
395
	template => $binop_mem,
	emit     => "add%M %#S3, %AM",
	latency  => 1,
396
397
},

398
Adc => {
399
400
	template => $carry_user_op,
	state    => "exc_pinned",
401
402
	in_reqs  => [ "gp", "gp", "mem", "gp", "gp", "flags" ],
	out_reqs => [ "in_r4 in_r5", "flags", "mem" ],
403
404
405
406
407
	ins      => [ "base", "index", "mem", "left", "right", "eflags" ],
	outs     => [ "res", "flags", "M" ],
	emit     => "adc%M %B",
	am       => "source,binary",
	latency  => 1,
408
	mode     => "first",
409
410
},

411
412
l_Add => {
	ins       => [ "left", "right" ],
Matthias Braun's avatar
Matthias Braun committed
413
	outs      => [ "res", "flags" ],
414
415
	attr_type => "",
	dump_func => "NULL",
416
417
418
419
},

l_Adc => {
	ins       => [ "left", "right", "eflags" ],
420
421
	attr_type => "",
	dump_func => "NULL",
422
423
},

424
Mul => {
425
	template => $mulop,
426
427
	emit     => "mul%M %AS4",
	latency  => 10,
428
429
},

430
l_Mul => {
431
	ins       => [ "left", "right" ],
432
	outs      => [ "res_low", "flags", "M", "res_high" ],
433
434
	attr_type => "",
	dump_func => "NULL",
435
436
437
},

IMul => {
438
439
440
	template => $binop_commutative,
	emit     => "imul%M %B",
	latency  => 5,
441
442
443
},

IMulImm => {
444
	template => $binop_commutative,
445
446
447
	out_reqs => [ "gp", "flags", "mem" ],
	emit     => "imul%M %#S4, %#AS3, %#D0",
	latency  => 5,
448
449
450
},

IMul1OP => {
451
	template => $mulop,
452
453
	emit     => "imul%M %AS4",
	latency  => 5,
454
455
456
},

l_IMul => {
457
	ins       => [ "left", "right" ],
458
	outs      => [ "res_low", "flags", "M", "res_high" ],
459
460
	attr_type => "",
	dump_func => "NULL",
461
462
463
},

And => {
464
465
466
	template => $binop_commutative,
	emit     => "and%M %B",
	latency  => 1,
467
468
},

469
AndMem => {
470
471
472
	template => $binop_mem,
	emit     => "and%M %#S3, %AM",
	latency  => 1,
473
474
},

475
Or => {
476
477
478
	template => $binop_commutative,
	emit     => "or%M %B",
	latency  => 1,
479
480
},

481
OrMem => {
482
483
484
	template => $binop_mem,
	emit     => "or%M %#S3, %AM",
	latency  => 1,
485
486
},

487
Xor => {
488
489
490
	template => $binop_commutative,
	emit     => "xor%M %B",
	latency  => 1,
491
492
},

493
Xor0 => {
494
	op_flags  => [ "constlike" ],
495
	irn_flags => [ "modify_flags", "rematerializable" ],
496
	out_reqs  => [ "gp", "flags" ],
497
	outs      => [ "res", "flags" ],
498
	emit      => "xor%M %D0, %D0",
499
	latency   => 1,
500
	mode      => "first",
501
502
},

503
XorMem => {
504
505
506
	template => $binop_mem,
	emit     => "xor%M %#S3, %AM",
	latency  => 1,
507
508
},

509
Sub => {
510
	irn_flags => [ "modify_flags", "rematerializable" ],
511
	state     => "exc_pinned",
512
513
	in_reqs   => [ "gp", "gp", "mem", "gp", "gp" ],
	out_reqs  => [ "in_r4", "flags", "mem" ],
514
	ins       => [ "base", "index", "mem", "minuend", "subtrahend" ],
515
	outs      => [ "res", "flags", "M" ],
Christoph Mallon's avatar
Christoph Mallon committed
516
	am        => "source,binary",
517
	emit      => "sub%M %B",
518
	latency   => 1,
519
	mode      => "first",
520
521
},

522
SubMem => {
523
524
525
	template => $binop_mem,
	emit     => "sub%M %#S3, %AM",
	latency  => 1,
526
527
},

528
Sbb => {
529
530
	template => $carry_user_op,
	state    => "exc_pinned",
531
532
	in_reqs  => [ "gp", "gp", "mem", "gp", "gp", "flags" ],
	out_reqs => [ "in_r4", "flags", "mem" ],
533
534
535
536
537
	ins      => [ "base", "index", "mem", "minuend", "subtrahend", "eflags" ],
	outs     => [ "res", "flags", "M" ],
	am       => "source,binary",
	emit     => "sbb%M %B",
	latency  => 1,
538
	mode     => "first",
539
540
},

541
Sbb0 => {
542
	template => $carry_user_op,
543
	# Spiller currently fails when rematerializing flag consumers
544
	# irn_flags => [ "modify_flags", "rematerializable" ],
545
546
547
548
549
	in_reqs  => [ "flags" ],
	out_reqs => [ "gp", "flags" ],
	outs     => [ "res", "flags" ],
	emit     => "sbb%M %D0, %D0",
	latency  => 1,
550
	mode     => "first",
551
552
},

553
l_Sub => {
554
	ins       => [ "minuend", "subtrahend" ],
Matthias Braun's avatar
Matthias Braun committed
555
	outs      => [ "res", "flags" ],
556
557
	attr_type => "",
	dump_func => "NULL",
558
559
560
},

l_Sbb => {
561
	ins       => [ "minuend", "subtrahend", "eflags" ],
562
563
	attr_type => "",
	dump_func => "NULL",
564
565
},

566
IDiv => {
567
568
569
	template => $divop,
	emit     => "idiv%M %AS3",
	latency  => 25,
570
571
},

572
Div => {
573
574
575
	template => $divop,
	emit     => "div%M %AS3",
	latency  => 25,
576
577
},

578
Shl => {
579
580
581
	template => $shiftop,
	emit     => "shl%M %<,S1 %D0",
	latency  => 1,
582
583
},

584
ShlMem => {
585
586
587
	template => $shiftop_mem,
	emit     => "shl%M %<,S3 %AM",
	latency  => 1,
588
589
},

590
ShlD => {
591
592
593
	template => $shiftop_double,
	emit     => "shld%M %<S2, %S1, %D0",
	latency  => 6,
594
595
},

596
Shr => {
597
598
599
	template => $shiftop,
	emit     => "shr%M %<,S1 %D0",
	latency  => 1,
600
601
},

602
ShrMem => {
603
604
605
	template => $shiftop_mem,
	emit     => "shr%M %<,S3 %AM",
	latency  => 1,
606
607
},

608
ShrD => {
609
610
611
	template => $shiftop_double,
	emit     => "shrd%M %<S2, %S1, %D0",
	latency  => 6,
612
613
},

614
Sar => {
615
616
617
	template => $shiftop,
	emit     => "sar%M %<,S1 %D0",
	latency  => 1,
618
619
},

620
SarMem => {
621
622
623
	template => $shiftop_mem,
	emit     => "sar%M %<,S3 %AM",
	latency  => 1,
624
625
},

626
Ror => {
627
628
629
	template => $shiftop,
	emit     => "ror%M %<,S1 %D0",
	latency  => 1,
630
631
},

632
RorMem => {
633
634
635
	template => $shiftop_mem,
	emit     => "ror%M %<,S3 %AM",
	latency  => 1,
636
637
},

638
Rol => {
639
640
641
	template => $shiftop,
	emit     => "rol%M %<,S1 %#D0",
	latency  => 1,
642
643
},

644
RolMem => {
645
646
647
	template => $shiftop_mem,
	emit     => "rol%M %<,S3 %AM",
	latency  => 1,
648
649
},

650
Neg => {
651
652
653
	template => $unop,
	emit     => "neg%M %D0",
	latency  => 1,
654
655
},

656
NegMem => {
657
658
659
	template => $unop_mem,
	emit     => "neg%M %AM",
	latency  => 1,
660
661
},

Matthias Braun's avatar
Matthias Braun committed
662
Minus64 => {
663
	irn_flags => [ "modify_flags", "rematerializable" ],
664
665
	in_reqs   => [ "gp", "gp" ],
	out_reqs  => [ "in_r1", "in_r2" ],
666
	ins       => [ "low", "high" ],
Matthias Braun's avatar
Matthias Braun committed
667
	outs      => [ "res_low", "res_high" ],
668
	latency   => 3,
669
670
},

Matthias Braun's avatar
Matthias Braun committed
671
672
673
674
675
676
l_Minus64 => {
	ins       => [ "low", "high" ],
	outs      => [ "res_low", "res_high" ],
	attr_type => "",
	dump_func => "NULL",
},
677

678
Inc => {
679
680
681
	template => $unop,
	emit     => "inc%M %D0",
	latency  => 1,
Christian Würdig's avatar
Christian Würdig committed
682
683
},

684
IncMem => {
685
686
687
	template => $unop_mem,
	emit     => "inc%M %AM",
	latency  => 1,
688
689
},

690
Dec => {
691
692
693
	template => $unop,
	emit     => "dec%M %D0",
	latency  => 1,
694
695
},

696
DecMem => {
697
698
699
	template => $unop_mem,
	emit     => "dec%M %AM",
	latency  => 1,
700
701
},

702
Not => {
703
704
705
	template => $unop_no_flags,
	emit     => "not%M %D0",
	latency  => 1,
Christian Würdig's avatar
Christian Würdig committed
706
707
},

708
NotMem => {
709
	irn_flags => [ "rematerializable" ],
710
	state     => "exc_pinned",
711
712
	in_reqs   => [ "gp", "gp", "mem" ],
	out_reqs  => [ "none", "none", "mem" ],
713
	ins       => [ "base", "index", "mem" ],
714
	outs      => [ "unused0", "unused1", "M" ],
715
	emit      => "not%M %AM",
716
	latency   => 1,
717
	# no flags modified
718
719
},

720
Cmc => {
721
722
723
724
725
	template => $carry_user_op,
	in_reqs  => [ "flags" ],
	out_reqs => [ "flags" ],
	emit     => "cmc",
	latency  => 1,
726
727
728
},

Stc => {
729
	irn_flags => [ "modify_flags" ],
730
	out_reqs  => [ "flags" ],
731
	emit      => "stc",
732
733
734
	latency   => 1,
},

735
Cmp => {
736
737
738
	template => $binop_flags,
	emit     => "cmp%M %B",
	latency  => 1,
739
740
},

741
XorHighLow => {
742
	irn_flags => [ "modify_flags", "rematerializable" ],
743
	state     => "exc_pinned",
744
745
	in_reqs   => [ "eax ebx ecx edx" ],
	out_reqs  => [ "in_r1", "flags" ],
746
	emit      => "xorb %>D0, %<D0",
747
748
749
750
751
	ins       => [ "value" ],
	outs      => [ "res", "flags" ],
	latency   => 1,
},

752
Test => {
753
754
755
	template => $binop_flags,
	emit     => "test%M %B",
	latency  => 1,
756
757
},

758
Setcc => {
759
	#irn_flags => [ "rematerializable" ],
760
761
	in_reqs   => [ "eflags" ],
	out_reqs  => [ "eax ebx ecx edx" ],
762
	ins       => [ "eflags" ],
763
	outs      => [ "res" ],
Michael Beck's avatar
Michael Beck committed
764
	attr_type => "ia32_condcode_attr_t",
765
	attr      => "x86_condition_code_t condition_code",
Matthias Braun's avatar
Matthias Braun committed
766
767
	# The way we handle Setcc with float nodes (potentially) destroys the flags
	# (when we emit the setX; setp; orb and the setX;setnp;andb sequences)
768
769
770
771
772
	init      => "set_ia32_ls_mode(res, mode_Bu);\n".
	             "\tif (condition_code & x86_cc_additional_float_cases) {\n".
	             "\t\tarch_add_irn_flags(res, arch_irn_flag_modify_flags);\n".
	             "\t\t/* attr->latency = 3; */\n".
	             "\t}\n",
773
774
775
	latency   => 1,
},

776
SetccMem => {
777
	#irn_flags => [ "rematerializable" ],
Matthias Braun's avatar
Matthias Braun committed
778
	state     => "exc_pinned",
779
780
	in_reqs   => [ "gp", "gp", "mem", "eflags" ],
	out_reqs  => [ "mem" ],
Matthias Braun's avatar
Matthias Braun committed
781
782
	ins       => [ "base", "index", "mem","eflags" ],
	attr_type => "ia32_condcode_attr_t",
783
	attr      => "x86_condition_code_t condition_code",
784
	init      => "set_ia32_ls_mode(res, mode_Bu);\n",
785
	emit      => "set%P3 %AM",
Matthias Braun's avatar
Matthias Braun committed
786
787
788
	latency   => 1,
},

789
CMovcc => {
790
	#irn_flags => [ "rematerializable" ],
791
	state     => "exc_pinned",
792
793
	# (note: leave the false,true order intact to make it compatible with other
	#  ia32_binary ops)
794
795
	in_reqs   => [ "gp", "gp", "mem", "gp", "gp", "eflags" ],
	out_reqs  => [ "in_r4 in_r5", "none", "mem" ],
796
	ins       => [ "base", "index", "mem", "val_false", "val_true", "eflags" ],
797
	outs      => [ "res", "unused", "M" ],
798
	am        => "source,binary",
Michael Beck's avatar
Michael Beck committed
799
	attr_type => "ia32_condcode_attr_t",
800
	attr      => "x86_condition_code_t condition_code",
801
	emit      => "cmov%P5 %#AS4, %#D0",
802
	latency   => 1,
803
	mode      => "first",
804
805
},

806
Jcc => {
807
	state     => "pinned",
808
	op_flags  => [ "cfopcode", "forking" ],
809
	in_reqs   => [ "eflags" ],
810
	out_reqs  => [ "exec", "exec" ],
811
	ins       => [ "eflags" ],
812
	outs      => [ "false", "true" ],
Michael Beck's avatar
Michael Beck committed
813
	attr_type => "ia32_condcode_attr_t",
814
	attr      => "x86_condition_code_t condition_code",
815
	latency   => 2,
816
817
818
},

SwitchJmp => {
819
	state     => "pinned",
820
	op_flags  => [ "cfopcode", "forking" ],
821
	in_reqs   => [ "gp", "gp" ],
822
	ins       => [ "base", "index" ],
823
	out_reqs  => "...",
824
	attr_type => "ia32_switch_attr_t",
Matthias Braun's avatar
Matthias Braun committed
825
	attr      => "const ir_switch_table *switch_table",
826
	latency   => 2,
827
828
829
},

Jmp => {