ia32_spec.pl 50 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
$mode_xmm   = "ia32_mode_float64";
17
$mode_fp87  = "x86_mode_E";
18
19
20
$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
sub ia32_custom_init_attr {
70
71
72
73
74
75
	my ($constr, $node, $name) = @_;

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

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

118
119
my $x87sim = "ia32_request_x87_sim(irg);";

120
my $binop_commutative = {
121
122
	irn_flags => [ "modify_flags", "rematerializable" ],
	state     => "exc_pinned",
123
	constructors => {
124
125
126
127
128
129
130
131
		""     => {
			in_reqs  => [ "gp", "gp", "mem", "gp", "gp" ],
			out_reqs => [ "in_r3 in_r4", "flags", "mem" ],
		},
		"8bit" => {
			in_reqs  => [ "gp", "gp", "mem", "eax ebx ecx edx", "eax ebx ecx edx" ],
			out_reqs => [ "eax ebx ecx edx in_r3 in_r4", "flags", "mem" ],
		},
132
	},
133
134
	ins       => [ "base", "index", "mem", "left", "right" ],
	outs      => [ "res", "flags", "M" ],
135
	attr      => "x86_insn_size_t size",
136
	am        => "source,binary",
137
	mode      => "first",
138
139
};

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

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

169
my $shiftop = {
170
	irn_flags => [ "modify_flags", "rematerializable" ],
171
172
173
174
	constructors => {
		""     => { in_reqs => [ "gp",              "ecx" ] },
		"8bit" => { in_reqs => [ "eax ebx ecx edx", "ecx" ] },
	},
175
	out_reqs  => [ "in_r0 !in_r1", "flags" ],
176
177
	ins       => [ "val", "count" ],
	outs      => [ "res", "flags" ],
178
	mode      => "first",
179
	attr      => "x86_insn_size_t size",
180
181
182
};

my $shiftop_mem = {
183
184
	irn_flags => [ "modify_flags", "rematerializable" ],
	state     => "exc_pinned",
185
186
	in_reqs   => [ "gp", "gp", "mem", "ecx" ],
	out_reqs  => [ "none", "flags", "mem" ],
187
188
	ins       => [ "base", "index", "mem", "count" ],
	outs      => [ "unused", "flags", "M" ],
189
	attr      => "x86_insn_size_t size",
190
191
192
};

my $shiftop_double = {
193
194
	irn_flags => [ "modify_flags", "rematerializable" ],
	in_reqs   => [ "gp", "gp", "ecx" ],
195
	constructors => {
196
		""  => { out_reqs  => [ "in_r0 !in_r1 !in_r2", "flags" ] },
197
198
199
		# 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.
200
		imm => { out_reqs  => [ "in_r0 in_r1",         "flags" ] },
201
	},
202
203
	ins       => [ "val_high", "val_low", "count" ],
	outs      => [ "res", "flags" ],
204
	mode      => "first",
205
	fixed     => "x86_insn_size_t const size = X86_SIZE_32;",
206
207
208
};

my $divop = {
209
210
211
	op_flags  => [ "fragile", "uses_memory" ],
	irn_flags => [ "modify_flags" ],
	state     => "exc_pinned",
212
	in_reqs   => [ "gp", "gp", "mem", "gp", "eax", "edx" ],
213
	out_reqs  => [ "eax", "flags", "mem", "edx", "exec", "exec" ],
214
215
216
	ins       => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
	outs      => [ "div_res", "flags", "M", "mod_res", "X_regular", "X_except" ],
	am        => "source,unary",
217
	attr      => "x86_insn_size_t size",
218
219
220
};

my $mulop = {
221
222
	# we should not rematerialize these nodes. They produce 2 results and have
	# very strict constraints
223
224
	irn_flags => [ "modify_flags" ],
	state     => "exc_pinned",
225
226
	in_reqs   => [ "gp", "gp", "mem", "eax", "gp" ],
	out_reqs  => [ "eax", "flags", "mem", "edx" ],
227
228
229
	ins       => [ "base", "index", "mem", "left", "right" ],
	outs      => [ "res_low", "flags", "M", "res_high" ],
	am        => "source,binary",
230
	attr      => "x86_insn_size_t size",
231
232
233
};

my $unop = {
234
	irn_flags => [ "modify_flags", "rematerializable" ],
235
	in_reqs   => [ "gp" ],
236
	out_reqs  => [ "in_r0", "flags" ],
237
238
	ins       => [ "val" ],
	outs      => [ "res", "flags" ],
239
	attr      => "x86_insn_size_t size",
240
	mode      => "first",
241
242
243
};

my $unop_no_flags = {
244
	# no flags modified
245
	irn_flags => [ "rematerializable" ],
246
	in_reqs   => [ "gp" ],
247
	out_reqs  => [ "in_r0" ],
248
249
	ins       => [ "val" ],
	outs      => [ "res" ],
250
	attr      => "x86_insn_size_t size",
251
252
253
};

my $unop_from_mem = {
254
255
	irn_flags => [ "modify_flags", "rematerializable" ],
	state     => "exc_pinned",
256
257
	in_reqs   => [ "gp", "gp", "mem", "gp" ],
	out_reqs  => [ "gp", "flags", "mem" ],
258
259
260
	ins       => [ "base", "index", "mem", "operand" ],
	outs      => [ "res", "flags", "M" ],
	am        => "source,unary",
261
	mode      => "first",
262
	attr      => "x86_insn_size_t size",
263
264
265
};

my $unop_mem = {
266
	irn_flags => [ "modify_flags", "rematerializable" ],
267
	state     => "exc_pinned",
268
269
	in_reqs   => [ "gp", "gp", "mem" ],
	out_reqs  => [ "none", "flags", "mem" ],
270
271
	ins       => [ "base", "index", "mem" ],
	outs      => [ "unused", "flags", "M" ],
272
	attr      => "x86_insn_size_t size",
273
274
275
};

my $memop = {
276
	state    => "pinned",
277
278
	in_reqs  => [ "mem" ],
	out_reqs => [ "mem" ],
279
	ins      => [ "mem" ],
280
	fixed    => "x86_insn_size_t const size = X86_SIZE_32;",
281
282
283
284
285
};

my $prefetchop = {
	op_flags  => [ "uses_memory" ],
	state     => "exc_pinned",
286
287
	in_reqs   => [ "gp", "gp", "mem" ],
	out_reqs  => [ "mem" ],
288
289
	ins       => [ "base", "index", "mem" ],
	outs      => [ "M" ],
290
	fixed     => "x86_insn_size_t const size = X86_SIZE_8;",
291
292
293
294
295
};

my $fbinop = {
#	irn_flags => [ "rematerializable" ],
	state     => "exc_pinned",
296
297
	in_reqs   => [ "gp", "gp", "mem", "fp", "fp", "fpcw" ],
	out_reqs  => [ "fp", "none", "mem" ],
298
299
300
	ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
	outs      => [ "res", "dummy", "M" ],
	am        => "source,binary",
301
	mode      => "first",
302
	attr_type => "ia32_x87_attr_t",
303
	attr      => "x86_insn_size_t size",
304
305
306
307
};

my $funop = {
	irn_flags => [ "rematerializable" ],
308
309
	in_reqs   => [ "fp" ],
	out_reqs  => [ "fp" ],
310
	ins       => [ "value" ],
311
	fixed     => "x86_insn_size_t const size = X86_SIZE_80;",
312
313
314
315
316
};

my $fconstop = {
	op_flags  => [ "constlike" ],
	irn_flags => [ "rematerializable" ],
317
	out_reqs  => [ "fp" ],
318
	outs      => [ "res" ],
319
320
	fixed     => "x86_insn_size_t const size = X86_SIZE_80;\n"
	            ."\t".$x87sim,
321
322
323
324
325
};

my $valueop = {
	op_flags  => [ "constlike" ],
	irn_flags => [ "rematerializable" ],
326
	out_reqs  => [ "gp" ],
327
	outs      => [ "res" ],
328
	fixed     => "x86_insn_size_t const size = X86_SIZE_32;",
329
330
};

331
332
333
334
335
my $fpopop = {
	op_flags    => [ "keep" ],
	out_reqs    => [ "none" ],
	attrs_equal => "attrs_equal_false",
	attr_type   => "ia32_x87_attr_t",
336
	attr        => "const arch_register_t *reg",
337
	init        => "attr->x87.reg = reg;",
338
	fixed       => "x86_insn_size_t const size = X86_SIZE_80;",
339
340
};

341
342
343
my $xbinop = {
	irn_flags => [ "rematerializable" ],
	state     => "exc_pinned",
344
	in_reqs   => [ "gp", "gp", "mem", "xmm", "xmm" ],
345
	out_reqs  => [ "in_r3 !in_r4", "flags", "mem" ],
346
347
348
	ins       => [ "base", "index", "mem", "left", "right" ],
	outs      => [ "res", "flags", "M" ],
	am        => "source,binary",
349
	mode      => "first",
350
	attr      => "x86_insn_size_t size",
351
352
353
354
355
};

my $xbinop_commutative = {
	irn_flags => [ "rematerializable" ],
	state     => "exc_pinned",
356
	in_reqs   => [ "gp", "gp", "mem", "xmm", "xmm" ],
357
	out_reqs  => [ "in_r3 in_r4", "flags", "mem" ],
358
359
360
	ins       => [ "base", "index", "mem", "left", "right" ],
	outs      => [ "res", "flags", "M" ],
	am        => "source,binary",
361
	mode      => "first",
362
	attr      => "x86_insn_size_t size",
363
364
365
};

my $xconv_i2f = {
366
	state    => "exc_pinned",
367
	in_reqs  => [ "gp", "gp", "mem", "gp" ],
368
369
	out_reqs => [ "xmm" ],
	ins      => [ "base", "index", "mem", "val" ],
370
	attr     => "x86_insn_size_t size",
371
	am       => "source,unary",
372
373
374
375
};

my $xshiftop = {
	irn_flags => [ "rematerializable" ],
376
	in_reqs   => [ "xmm", "xmm" ],
377
	out_reqs  => [ "in_r0 !in_r1" ],
378
	attr      => "x86_insn_size_t size",
379
380
381
382
383
};

my $xvalueop = {
	op_flags  => [ "constlike" ],
	irn_flags => [ "rematerializable" ],
384
	out_reqs  => [ "xmm" ],
385
	outs      => [ "res" ],
386
	attr      => "x86_insn_size_t size",
387
388
};

389
390
391
392
my $carry_user_op = {
	irn_flags => [ "modify_flags" ],
	attr_type => "ia32_condcode_attr_t",
	fixed     => "x86_condition_code_t condition_code = x86_cc_carry;",
393
	attr      => "x86_insn_size_t size",
394
395
};

396
397
398
399
my $noregop = {
	state     => "pinned",
	op_flags  => [ "constlike", "dump_noblock" ],
	irn_flags => [ "not_scheduled" ],
400
	fixed     => "x86_insn_size_t const size = X86_SIZE_32;",
401
402
};

403
404
405
406
407
408
my $fpcwop = {
	op_flags => [ "uses_memory" ],
	state    => "pinned",
	fixed    => "x86_insn_size_t const size = X86_SIZE_16;",
};

409
410
411
412
413
414
415
416
my $emmsop = {
	op_flags    => [ "keep" ],
	out_reqs    => [ "none" ],
	attrs_equal => "attrs_equal_false",
	fixed       => "x86_insn_size_t const size = X86_SIZE_32;"
	              ."\t$x87sim",
};

417
418
%nodes = (

419
420
Immediate => {
	state     => "pinned",
421
	op_flags  => [ "constlike" ],
422
	irn_flags => [ "not_scheduled" ],
423
	out_reqs  => [ "gp_NOREG:I" ],
424
	attr      => "const x86_imm32_t *imm",
425
	attr_type => "ia32_immediate_attr_t",
426
	hash_func => "ia32_hash_Immediate",
427
	latency   => 0,
428
	fixed    => "x86_insn_size_t const size = X86_SIZE_32;",
429
},
430

431
Add => {
432
433
	template => $binop_commutative,
	emit     => "add%M %B",
434
	encode   => "ia32_enc_binop(node, 0)",
435
	latency  => 1,
436
437
},

438
AddMem => {
439
	template => $binop_mem,
440
	emit     => "add%M %S3, %AM",
441
	encode   => "ia32_enc_binop_mem(node, 0)",
442
	latency  => 1,
443
444
},

445
Adc => {
446
447
	template => $carry_user_op,
	state    => "exc_pinned",
448
	in_reqs  => [ "gp", "gp", "mem", "gp", "gp", "flags" ],
449
	out_reqs => [ "in_r3 in_r4", "flags", "mem" ],
450
451
452
	ins      => [ "base", "index", "mem", "left", "right", "eflags" ],
	outs     => [ "res", "flags", "M" ],
	emit     => "adc%M %B",
453
	encode   => "ia32_enc_binop(node, 2)",
454
455
	am       => "source,binary",
	latency  => 1,
456
	mode     => "first",
457
458
},

459
460
l_Add => {
	ins       => [ "left", "right" ],
Matthias Braun's avatar
Matthias Braun committed
461
	outs      => [ "res", "flags" ],
462
463
	attr_type => "",
	dump_func => "NULL",
464
465
466
467
},

l_Adc => {
	ins       => [ "left", "right", "eflags" ],
468
469
	attr_type => "",
	dump_func => "NULL",
470
471
},

472
Mul => {
473
	template => $mulop,
474
	emit     => "mul%M %AS4",
475
	encode   => "ia32_enc_unop(node, 0xF7, 4, n_ia32_Mul_right)",
476
	latency  => 10,
477
478
},

479
l_Mul => {
480
	ins       => [ "left", "right" ],
481
	outs      => [ "res_low", "flags", "M", "res_high" ],
482
483
	attr_type => "",
	dump_func => "NULL",
484
485
486
},

IMul => {
487
488
	template => $binop_commutative,
	emit     => "imul%M %B",
489
	encode   => "ia32_enc_0f_unop_reg(node, 0xAF, n_ia32_IMul_right)",
490
	latency  => 5,
491
492
493
},

IMulImm => {
494
	template => $binop_commutative,
495
496
497
498
499
500
	constructors => {
		"" => {
			in_reqs  => [ "gp", "gp", "mem", "gp", "gp" ],
			out_reqs => [ "gp", "flags", "mem" ],
		}
	},
501
	emit     => "imul%M %S4, %AS3, %D0",
502
	latency  => 5,
503
504
505
},

IMul1OP => {
506
	template => $mulop,
507
	emit     => "imul%M %AS4",
508
	encode   => "ia32_enc_unop(node, 0xF7, 5, n_ia32_IMul1OP_right)",
509
	latency  => 5,
510
511
512
},

l_IMul => {
513
	ins       => [ "left", "right" ],
514
	outs      => [ "res_low", "flags", "M", "res_high" ],
515
516
	attr_type => "",
	dump_func => "NULL",
517
518
519
},

And => {
520
521
	template => $binop_commutative,
	emit     => "and%M %B",
522
	encode   => "ia32_enc_binop(node, 4)",
523
	latency  => 1,
524
525
},

526
AndMem => {
527
	template => $binop_mem,
528
	emit     => "and%M %S3, %AM",
529
	encode   => "ia32_enc_binop_mem(node, 4)",
530
	latency  => 1,
531
532
},

533
Or => {
534
535
	template => $binop_commutative,
	emit     => "or%M %B",
536
	encode   => "ia32_enc_binop(node, 1)",
537
	latency  => 1,
538
539
},

540
OrMem => {
541
	template => $binop_mem,
542
	emit     => "or%M %S3, %AM",
543
	encode   => "ia32_enc_binop_mem(node, 1)",
544
	latency  => 1,
545
546
},

547
Xor => {
548
	template => $binop_commutative,
549
	emit     => "xor%M %B",
550
	encode   => "ia32_enc_binop(node, 6)",
551
	latency  => 1,
552
553
},

554
Xor0 => {
555
	op_flags  => [ "constlike" ],
556
	irn_flags => [ "modify_flags", "rematerializable" ],
557
	out_reqs  => [ "gp", "flags" ],
558
	outs      => [ "res", "flags" ],
559
	emit      => "xor%M %D0, %D0",
560
	attr      => "x86_insn_size_t size",
561
	latency   => 1,
562
	mode      => "first",
563
564
},

565
XorMem => {
566
	template => $binop_mem,
567
	emit     => "xor%M %S3, %AM",
568
	encode   => "ia32_enc_binop_mem(node, 6)",
569
	latency  => 1,
570
571
},

572
Sub => {
573
	irn_flags => [ "modify_flags", "rematerializable" ],
574
	state     => "exc_pinned",
yb9976's avatar
yb9976 committed
575
576
577
578
579
580
581
582
583
584
	constructors => {
		""     => {
			in_reqs  => [ "gp", "gp", "mem", "gp", "gp" ],
			out_reqs => [ "in_r3", "flags", "mem" ],
		},
		"8bit" => {
			in_reqs  => [ "gp", "gp", "mem", "eax ebx ecx edx", "eax ebx ecx edx" ],
			out_reqs => [ "eax ebx ecx edx in_r3", "flags", "mem" ],
		},
	},
585
	ins       => [ "base", "index", "mem", "minuend", "subtrahend" ],
586
	outs      => [ "res", "flags", "M" ],
Christoph Mallon's avatar
Christoph Mallon committed
587
	am        => "source,binary",
588
	attr      => "x86_insn_size_t size",
589
	emit      => "sub%M %B",
590
	encode    => "ia32_enc_binop(node, 5)",
591
	latency   => 1,
592
	mode      => "first",
593
594
},

595
SubMem => {
596
	template => $binop_mem,
597
	emit     => "sub%M %S3, %AM",
598
	encode   => "ia32_enc_binop_mem(node, 5)",
599
	latency  => 1,
600
601
},

602
Sbb => {
603
604
	template => $carry_user_op,
	state    => "exc_pinned",
605
	in_reqs  => [ "gp", "gp", "mem", "gp", "gp", "flags" ],
606
	out_reqs => [ "in_r3", "flags", "mem" ],
607
608
609
610
	ins      => [ "base", "index", "mem", "minuend", "subtrahend", "eflags" ],
	outs     => [ "res", "flags", "M" ],
	am       => "source,binary",
	emit     => "sbb%M %B",
611
	encode   => "ia32_enc_binop(node, 3)",
612
	latency  => 1,
613
	mode     => "first",
614
615
},

616
Sbb0 => {
617
	template => $carry_user_op,
618
	# Spiller currently fails when rematerializing flag consumers
619
	# irn_flags => [ "modify_flags", "rematerializable" ],
620
621
622
623
624
	in_reqs  => [ "flags" ],
	out_reqs => [ "gp", "flags" ],
	outs     => [ "res", "flags" ],
	emit     => "sbb%M %D0, %D0",
	latency  => 1,
625
	mode     => "first",
626
627
},

628
l_Sub => {
629
	ins       => [ "minuend", "subtrahend" ],
Matthias Braun's avatar
Matthias Braun committed
630
	outs      => [ "res", "flags" ],
631
632
	attr_type => "",
	dump_func => "NULL",
633
634
635
},

l_Sbb => {
636
	ins       => [ "minuend", "subtrahend", "eflags" ],
637
638
	attr_type => "",
	dump_func => "NULL",
639
640
},

641
IDiv => {
642
643
	template => $divop,
	emit     => "idiv%M %AS3",
644
	encode   => "ia32_enc_unop(node, 0xF7, 7, n_ia32_IDiv_divisor)",
645
	latency  => 25,
646
647
},

648
Div => {
649
650
	template => $divop,
	emit     => "div%M %AS3",
651
	encode   => "ia32_enc_unop(node, 0xF7, 6, n_ia32_Div_divisor)",
652
	latency  => 25,
653
654
},

655
Shl => {
656
657
	template => $shiftop,
	emit     => "shl%M %<,S1 %D0",
658
	encode   => "ia32_enc_shiftop(node, 4)",
659
	latency  => 1,
660
661
},

662
ShlMem => {
663
664
	template => $shiftop_mem,
	emit     => "shl%M %<,S3 %AM",
665
	encode   => "ia32_enc_shiftop_mem(node, 4)",
666
	latency  => 1,
667
668
},

669
ShlD => {
670
671
672
	template => $shiftop_double,
	emit     => "shld%M %<S2, %S1, %D0",
	latency  => 6,
673
674
},

675
Shr => {
676
677
	template => $shiftop,
	emit     => "shr%M %<,S1 %D0",
678
	encode   => "ia32_enc_shiftop(node, 5)",
679
	latency  => 1,
680
681
},

682
ShrMem => {
683
684
	template => $shiftop_mem,
	emit     => "shr%M %<,S3 %AM",
685
	encode   => "ia32_enc_shiftop_mem(node, 5)",
686
	latency  => 1,
687
688
},

689
ShrD => {
690
691
692
	template => $shiftop_double,
	emit     => "shrd%M %<S2, %S1, %D0",
	latency  => 6,
693
694
},

695
Sar => {
696
697
	template => $shiftop,
	emit     => "sar%M %<,S1 %D0",
698
	encode   => "ia32_enc_shiftop(node, 7)",
699
	latency  => 1,
700
701
},

702
SarMem => {
703
704
	template => $shiftop_mem,
	emit     => "sar%M %<,S3 %AM",
705
	encode   => "ia32_enc_shiftop_mem(node, 7)",
706
	latency  => 1,
707
708
},

709
Ror => {
710
711
	template => $shiftop,
	emit     => "ror%M %<,S1 %D0",
712
	encode   => "ia32_enc_shiftop(node, 1)",
713
	latency  => 1,
714
715
},

716
RorMem => {
717
718
	template => $shiftop_mem,
	emit     => "ror%M %<,S3 %AM",
719
	encode   => "ia32_enc_shiftop_mem(node, 1)",
720
	latency  => 1,
721
722
},

723
Rol => {
724
	template => $shiftop,
725
	emit     => "rol%M %<,S1 %D0",
726
	encode   => "ia32_enc_shiftop(node, 0)",
727
	latency  => 1,
728
729
},

730
RolMem => {
731
732
	template => $shiftop_mem,
	emit     => "rol%M %<,S3 %AM",
733
	encode   => "ia32_enc_shiftop_mem(node, 0)",
734
	latency  => 1,
735
736
},

737
Neg => {
738
739
	template => $unop,
	emit     => "neg%M %D0",
740
	encode   => "ia32_enc_unop(node, 0xF7, 3, n_ia32_Neg_val)",
741
	latency  => 1,
742
743
},

744
NegMem => {
745
746
	template => $unop_mem,
	emit     => "neg%M %AM",
747
	encode   => "ia32_enc_unop_mem(node, 0xF6, 3)",
748
	latency  => 1,
749
750
},

Matthias Braun's avatar
Matthias Braun committed
751
Minus64 => {
752
	irn_flags => [ "modify_flags", "rematerializable" ],
753
	in_reqs   => [ "gp", "gp" ],
754
	out_reqs  => [ "in_r0", "in_r1" ],
755
	ins       => [ "low", "high" ],