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

$arch = "ia32";

5
6
7
8
9
10
11
$mode_xmm           = "mode_D";
$mode_mmx           = "mode_D";
$mode_fp87          = "ia32_mode_E";
$mode_gp            = "mode_Iu";
$mode_flags         = "mode_Iu";
$mode_fpcw          = "ia32_mode_fpcw";

Christian Würdig's avatar
Christian Würdig committed
12
# register types:
13
$normal      =  0; # no special type
14
15
16
17
$ignore      =  1; # ignore (do not assign this register)
$arbitrary   =  2; # emitter can choose an arbitrary register of this class
$virtual     =  4; # the register is a virtual one
$state       =  8; # register represents a state
Christian Würdig's avatar
Christian Würdig committed
18
# NOTE: Last entry of each class is the largest Firm-Mode a register can hold
19
%reg_classes = (
20
	gp => [
21
22
23
24
25
26
27
28
		{ name => "edx", dwarf => 2 },
		{ name => "ecx", dwarf => 1 },
		{ name => "eax", dwarf => 0 },
		{ name => "ebx", dwarf => 3 },
		{ name => "esi", dwarf => 6 },
		{ name => "edi", dwarf => 7 },
		{ name => "ebp", dwarf => 5 },
		{ name => "esp", dwarf => 4, type => $ignore },
29
		{ name => "gp_NOREG", type => $ignore | $arbitrary | $virtual }, # we need a dummy register for NoReg nodes
30
		{ mode => $mode_gp }
31
	],
32
	mmx => [
33
34
35
36
37
38
39
40
		{ name => "mm0", dwarf => 29, type => $ignore },
		{ name => "mm1", dwarf => 30, type => $ignore },
		{ name => "mm2", dwarf => 31, type => $ignore },
		{ name => "mm3", dwarf => 32, type => $ignore },
		{ name => "mm4", dwarf => 33, type => $ignore },
		{ name => "mm5", dwarf => 34, type => $ignore },
		{ name => "mm6", dwarf => 35, type => $ignore },
		{ name => "mm7", dwarf => 36, type => $ignore },
41
		{ mode => $mode_mmx, flags => "manual_ra" }
42
	],
43
	xmm => [
44
45
46
47
48
49
50
51
		{ 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 },
52
		{ name => "xmm_NOREG", type => $ignore | $virtual },     # we need a dummy register for NoReg nodes
53
		{ mode => $mode_xmm }
54
	],
55
	vfp => [
56
57
58
59
60
61
62
63
		{ name => "vf0" },
		{ name => "vf1" },
		{ name => "vf2" },
		{ name => "vf3" },
		{ name => "vf4" },
		{ name => "vf5" },
		{ name => "vf6" },
		{ name => "vf7" },
64
		{ name => "vfp_NOREG", type => $ignore | $arbitrary | $virtual }, # we need a dummy register for NoReg nodes
65
		{ mode => $mode_fp87 }
66
	],
67
	st => [
68
69
70
71
72
73
74
75
		{ name => "st0", realname => "st",    dwarf => 11, type => $ignore },
		{ name => "st1", realname => "st(1)", dwarf => 12, type => $ignore },
		{ name => "st2", realname => "st(2)", dwarf => 13, type => $ignore },
		{ name => "st3", realname => "st(3)", dwarf => 14, type => $ignore },
		{ name => "st4", realname => "st(4)", dwarf => 15, type => $ignore },
		{ name => "st5", realname => "st(5)", dwarf => 16, type => $ignore },
		{ name => "st6", realname => "st(6)", dwarf => 17, type => $ignore },
		{ name => "st7", realname => "st(7)", dwarf => 18, type => $ignore },
76
		{ mode => $mode_fp87, flags => "manual_ra" }
77
	],
78
	fp_cw => [	# the floating point control word
79
		{ name => "fpcw", dwarf => 37, type => $ignore | $state },
80
		{ mode => $mode_fpcw, flags => "manual_ra|state" }
81
	],
82
	flags => [
83
		{ name => "eflags", dwarf => 9, type => 0 },
84
		{ mode => "mode_Iu", flags => "manual_ra" }
85
	],
86
87
); # %reg_classes

88
%cpu = (
89
90
91
92
	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" ],
93
94
); # %cpu

95
%vliw = (
96
97
	bundle_size       => 1,
	bundels_per_cycle => 1
98
99
); # vliw

100
101
102
$default_op_attr_type = "ia32_op_attr_t";
$default_attr_type    = "ia32_attr_t";
$default_copy_attr    = "ia32_copy_attr";
103

104
sub ia32_custom_init_attr {
105
106
107
108
	my $constr = shift;
	my $node   = shift;
	my $name   = shift;
	my $res    = "";
109

110
	if(defined($node->{modified_flags})) {
111
		$res .= "\tarch_add_irn_flags(res, arch_irn_flags_modify_flags);\n";
112
113
114
	}
	if(defined($node->{am})) {
		my $am = $node->{am};
Christoph Mallon's avatar
Christoph Mallon committed
115
		if($am eq "source,unary") {
116
			$res .= "\tset_ia32_am_support(res, ia32_am_unary);";
117
		} elsif($am eq "source,binary") {
118
			$res .= "\tset_ia32_am_support(res, ia32_am_binary);";
119
120
121
122
123
		} elsif($am eq "none") {
			# nothing to do
		} else {
			die("Invalid address mode '$am' specified on op $name");
		}
124
125
126
127
128
129
		if($am ne "none") {
			if($node->{state} ne "exc_pinned"
					and $node->{state} ne "pinned") {
				die("AM nodes must have pinned or AM pinned state ($name)");
			}
		}
130
131
132
133
134
	}
	return $res;
}
$custom_init_attr_func = \&ia32_custom_init_attr;

135
%init_attr = (
136
	ia32_asm_attr_t =>
137
		"\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);\n".
138
		"\tinit_ia32_x87_attributes(res);".
139
		"\tinit_ia32_asm_attributes(res);",
Christoph Mallon's avatar
Christoph Mallon committed
140
	ia32_attr_t     =>
141
		"\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);",
142
	ia32_call_attr_t =>
143
		"\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);\n".
144
		"\tinit_ia32_call_attributes(res, pop, call_tp);",
Christoph Mallon's avatar
Christoph Mallon committed
145
	ia32_condcode_attr_t =>
146
		"\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);\n".
147
148
		"\tinit_ia32_condcode_attributes(res, condition_code);",
	ia32_switch_attr_t =>
149
		"\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);\n".
Matthias Braun's avatar
Matthias Braun committed
150
		"\tinit_ia32_switch_attributes(res, switch_table);",
Michael Beck's avatar
Michael Beck committed
151
	ia32_copyb_attr_t =>
152
		"\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);\n".
Michael Beck's avatar
Michael Beck committed
153
		"\tinit_ia32_copyb_attributes(res, size);",
Christoph Mallon's avatar
Christoph Mallon committed
154
	ia32_immediate_attr_t =>
155
		"\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);\n".
156
		"\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, no_pic_adjust, offset);",
Christoph Mallon's avatar
Christoph Mallon committed
157
	ia32_x87_attr_t =>
158
		"\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);\n".
Christoph Mallon's avatar
Christoph Mallon committed
159
		"\tinit_ia32_x87_attributes(res);",
160
	ia32_climbframe_attr_t =>
161
		"\tinit_ia32_attributes(res, irn_flags_, in_reqs, n_res);\n".
162
		"\tinit_ia32_climbframe_attributes(res, count);",
163
164
165
);

%compare_attr = (
166
	ia32_asm_attr_t        => "ia32_compare_asm_attr",
167
168
169
170
	ia32_attr_t            => "ia32_compare_nodes_attr",
	ia32_call_attr_t       => "ia32_compare_call_attr",
	ia32_condcode_attr_t   => "ia32_compare_condcode_attr",
	ia32_copyb_attr_t      => "ia32_compare_copyb_attr",
Matthias Braun's avatar
Matthias Braun committed
171
	ia32_switch_attr_t     => "ia32_compare_nodes_attr",
172
173
174
	ia32_immediate_attr_t  => "ia32_compare_immediate_attr",
	ia32_x87_attr_t        => "ia32_compare_x87_attr",
	ia32_climbframe_attr_t => "ia32_compare_climbframe_attr",
175
176
);

Michael Beck's avatar
Michael Beck committed
177
178
179
%operands = (
);

180
181
182
183
$status_flags       = [ "CF", "PF", "AF", "ZF", "SF", "OF" ];
$status_flags_wo_cf = [       "PF", "AF", "ZF", "SF", "OF" ];
$fpcw_flags         = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM",
                        "FP_PC0", "FP_PC1", "FP_RC0", "FP_RC1", "FP_X" ];
184

185
186
%nodes = (

187
188
Immediate => {
	state     => "pinned",
189
	op_flags  => [ "constlike" ],
190
	irn_flags => [ "not_scheduled" ],
191
	reg_req   => { out => [ "gp_NOREG:I" ] },
192
	attr      => "ir_entity *symconst, int symconst_sign, int no_pic_adjust, long offset",
193
	attr_type => "ia32_immediate_attr_t",
194
	hash_func => "ia32_hash_Immediate",
195
	latency   => 0,
196
197
	mode      => $mode_gp,
},
198

199
200
201
202
Asm => {
	mode      => "mode_T",
	arity     => "variable",
	out_arity => "variable",
203
	attr_type => "ia32_asm_attr_t",
204
205
206
207
	attr      => "ident *asm_text, const ia32_asm_reg_t *register_map",
	init_attr => "attr->asm_text = asm_text;\n".
	             "\tattr->register_map = register_map;\n",
	latency   => 10,
208
	modified_flags => $status_flags,
209
210
},

211
212
# "allocates" a free register
ProduceVal => {
213
214
	op_flags  => [ "constlike", "cse_neutral" ],
	irn_flags => [ "rematerializable" ],
215
216
217
218
219
220
221
222
	reg_req   => { out => [ "gp" ] },
	emit      => "",
	units     => [ ],
	latency   => 0,
	mode      => $mode_gp,
	cmp_attr  => "return 1;",
},

223
Add => {
224
	irn_flags => [ "rematerializable" ],
225
	state     => "exc_pinned",
226
227
	reg_req   => { in  => [ "gp", "gp", "none", "gp", "gp" ],
	               out => [ "in_r4 in_r5", "flags", "none" ] },
228
	ins       => [ "base", "index", "mem", "left", "right" ],
229
	outs      => [ "res", "flags", "M" ],
230
	emit      => 'add%M %B',
Christoph Mallon's avatar
Christoph Mallon committed
231
	am        => "source,binary",
232
	units     => [ "GP" ],
233
	latency   => 1,
234
235
	mode      => $mode_gp,
	modified_flags => $status_flags
236
237
},

238
AddMem => {
239
	irn_flags => [ "rematerializable" ],
240
	state     => "exc_pinned",
241
242
	reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
	ins       => [ "base", "index", "mem", "val" ],
243
	emit      => "add%M %#S3, %AM",
244
	units     => [ "GP" ],
245
	latency   => 1,
246
247
248
249
	mode      => "mode_M",
	modified_flags => $status_flags
},

250
AddMem8Bit => {
251
	irn_flags => [ "rematerializable" ],
252
	state     => "exc_pinned",
253
254
	reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
	ins       => [ "base", "index", "mem", "val" ],
255
	emit      => "add%M %#S3, %AM",
256
	units     => [ "GP" ],
257
	latency   => 1,
258
259
260
261
	mode      => "mode_M",
	modified_flags => $status_flags
},

262
Adc => {
263
	state     => "exc_pinned",
264
265
	reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ],
	               out => [ "in_r4 in_r5", "flags", "none" ] },
266
	ins       => [ "base", "index", "mem", "left", "right", "eflags" ],
267
	outs      => [ "res", "flags", "M" ],
268
	emit      => 'adc%M %B',
Christoph Mallon's avatar
Christoph Mallon committed
269
	am        => "source,binary",
270
	units     => [ "GP" ],
271
	latency   => 1,
272
273
	mode      => $mode_gp,
	modified_flags => $status_flags
274
275
},

276
277
l_Add => {
	ins       => [ "left", "right" ],
278
279
	attr_type => "",
	dump_func => "NULL",
280
281
282
283
},

l_Adc => {
	ins       => [ "left", "right", "eflags" ],
284
285
	attr_type => "",
	dump_func => "NULL",
286
287
},

288
Mul => {
289
	# we should not rematrialize this node. It produces 2 results and has
Christoph Mallon's avatar
Christoph Mallon committed
290
	# very strict constraints
291
	state     => "exc_pinned",
292
	reg_req   => { in => [ "gp", "gp", "none", "eax", "gp" ],
293
	               out => [ "eax", "flags", "none", "edx" ] },
Christoph Mallon's avatar
Christoph Mallon committed
294
	ins       => [ "base", "index", "mem", "left", "right" ],
295
	emit      => 'mul%M %AS4',
296
	outs      => [ "res_low", "flags", "M", "res_high" ],
297
	am        => "source,binary",
298
299
	latency   => 10,
	units     => [ "GP" ],
300
	modified_flags => $status_flags
301
302
},

303
l_Mul => {
304
	ins       => [ "left", "right" ],
305
	outs      => [ "res_low", "flags", "M", "res_high" ],
306
307
	attr_type => "",
	dump_func => "NULL",
308
309
310
},

IMul => {
311
	irn_flags => [ "rematerializable" ],
312
	state     => "exc_pinned",
Matthias Braun's avatar
Matthias Braun committed
313
314
315
	# TODO: adjust out requirements for the 3 operand form
	# (no need for should_be_same then)
	reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ],
316
		           out => [ "in_r4 in_r5", "flags", "none" ] },
317
	ins       => [ "base", "index", "mem", "left", "right" ],
318
	outs      => [ "res", "flags", "M" ],
319
	am        => "source,binary",
320
321
	latency   => 5,
	units     => [ "GP" ],
322
323
	mode      => $mode_gp,
	modified_flags => $status_flags
324
325
326
},

IMul1OP => {
327
	irn_flags => [ "rematerializable" ],
328
	state     => "exc_pinned",
329
	reg_req   => { in => [ "gp", "gp", "none", "eax", "gp" ],
330
	               out => [ "eax", "flags", "none", "edx" ] },
Christoph Mallon's avatar
Christoph Mallon committed
331
	ins       => [ "base", "index", "mem", "left", "right" ],
332
	emit      => 'imul%M %AS4',
333
	outs      => [ "res_low", "flags", "M", "res_high" ],
334
	am        => "source,binary",
335
336
	latency   => 5,
	units     => [ "GP" ],
337
	modified_flags => $status_flags
338
339
340
},

l_IMul => {
341
	ins       => [ "left", "right" ],
342
	outs      => [ "res_low", "flags", "M", "res_high" ],
343
344
	attr_type => "",
	dump_func => "NULL",
345
346
347
},

And => {
348
	irn_flags => [ "rematerializable" ],
349
	state     => "exc_pinned",
350
351
	reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ],
		           out => [ "in_r4 in_r5", "flags", "none" ] },
352
	ins       => [ "base", "index", "mem", "left", "right" ],
353
	outs      => [ "res", "flags", "M" ],
Christoph Mallon's avatar
Christoph Mallon committed
354
	am        => "source,binary",
355
	emit      => 'and%M %B',
356
	units     => [ "GP" ],
357
	latency   => 1,
358
359
	mode      => $mode_gp,
	modified_flags => $status_flags
360
361
},

362
AndMem => {
363
	irn_flags => [ "rematerializable" ],
364
	state     => "exc_pinned",
365
366
	reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
	ins       => [ "base", "index", "mem", "val" ],
367
	emit      => 'and%M %#S3, %AM',
368
	units     => [ "GP" ],
369
	latency   => 1,
370
371
372
373
	mode      => "mode_M",
	modified_flags => $status_flags
},

374
AndMem8Bit => {
375
	irn_flags => [ "rematerializable" ],
376
	state     => "exc_pinned",
377
378
	reg_req   => { in => [ "gp", "gp", "none",  "eax ebx ecx edx" ], out => [ "none" ] },
	ins       => [ "base", "index", "mem", "val" ],
379
	emit      => 'and%M %#S3, %AM',
380
	units     => [ "GP" ],
381
	latency   => 1,
382
383
384
385
	mode      => "mode_M",
	modified_flags => $status_flags
},

386
Or => {
387
	irn_flags => [ "rematerializable" ],
388
	state     => "exc_pinned",
389
390
	reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ],
	               out => [ "in_r4 in_r5", "flags", "none" ] },
391
	ins       => [ "base", "index", "mem", "left", "right" ],
392
	outs      => [ "res", "flags", "M" ],
Christoph Mallon's avatar
Christoph Mallon committed
393
	am        => "source,binary",
394
	emit      => 'or%M %B',
395
	units     => [ "GP" ],
396
	latency   => 1,
397
398
	mode      => $mode_gp,
	modified_flags => $status_flags
399
400
},

401
OrMem => {
402
	irn_flags => [ "rematerializable" ],
403
	state     => "exc_pinned",
404
405
	reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
	ins       => [ "base", "index", "mem", "val" ],
406
	emit      => 'or%M %#S3, %AM',
407
	units     => [ "GP" ],
408
	latency   => 1,
409
410
411
412
	mode      => "mode_M",
	modified_flags => $status_flags
},

413
OrMem8Bit => {
414
	irn_flags => [ "rematerializable" ],
415
	state     => "exc_pinned",
416
417
	reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
	ins       => [ "base", "index", "mem", "val" ],
418
	emit      => 'or%M %#S3, %AM',
419
	units     => [ "GP" ],
420
	latency   => 1,
421
422
423
424
	mode      => "mode_M",
	modified_flags => $status_flags
},

425
Xor => {
426
	irn_flags => [ "rematerializable" ],
427
	state     => "exc_pinned",
428
429
	reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ],
	               out => [ "in_r4 in_r5", "flags", "none" ] },
430
	ins       => [ "base", "index", "mem", "left", "right" ],
431
	outs      => [ "res", "flags", "M" ],
Christoph Mallon's avatar
Christoph Mallon committed
432
	am        => "source,binary",
433
	emit      => 'xor%M %B',
434
	units     => [ "GP" ],
435
	latency   => 1,
436
437
	mode      => $mode_gp,
	modified_flags => $status_flags
438
439
},

440
Xor0 => {
441
442
	op_flags  => [ "constlike" ],
	irn_flags => [ "rematerializable" ],
443
444
	reg_req   => { out => [ "gp", "flags" ] },
	outs      => [ "res", "flags" ],
445
	emit      => "xor%M %D0, %D0",
446
447
448
449
450
451
	units     => [ "GP" ],
	latency   => 1,
	mode      => $mode_gp,
	modified_flags => $status_flags
},

452
XorMem => {
453
	irn_flags => [ "rematerializable" ],
454
	state     => "exc_pinned",
455
456
	reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
	ins       => [ "base", "index", "mem", "val" ],
457
	emit      => 'xor%M %#S3, %AM',
458
	units     => [ "GP" ],
459
	latency   => 1,
460
461
462
463
	mode      => "mode_M",
	modified_flags => $status_flags
},

464
XorMem8Bit => {
465
	irn_flags => [ "rematerializable" ],
466
	state     => "exc_pinned",
467
468
	reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
	ins       => [ "base", "index", "mem", "val" ],
469
	emit      => 'xor%M %#S3, %AM',
470
	units     => [ "GP" ],
471
	latency   => 1,
472
473
474
475
	mode      => "mode_M",
	modified_flags => $status_flags
},

476
Sub => {
477
	irn_flags => [ "rematerializable" ],
478
	state     => "exc_pinned",
479
480
	reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ],
	               out => [ "in_r4", "flags", "none" ] },
481
	ins       => [ "base", "index", "mem", "minuend", "subtrahend" ],
482
	outs      => [ "res", "flags", "M" ],
Christoph Mallon's avatar
Christoph Mallon committed
483
	am        => "source,binary",
484
	emit      => 'sub%M %B',
485
	units     => [ "GP" ],
486
	latency   => 1,
487
488
	mode      => $mode_gp,
	modified_flags => $status_flags
489
490
},

491
SubMem => {
492
	irn_flags => [ "rematerializable" ],
493
	state     => "exc_pinned",
494
	reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
495
	ins       => [ "base", "index", "mem", "subtrahend" ],
496
	emit      => 'sub%M %#S3, %AM',
497
	units     => [ "GP" ],
498
	latency   => 1,
499
500
501
502
	mode      => 'mode_M',
	modified_flags => $status_flags
},

503
SubMem8Bit => {
504
	irn_flags => [ "rematerializable" ],
505
	state     => "exc_pinned",
506
	reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
507
	ins       => [ "base", "index", "mem", "subtrahend" ],
508
	emit      => 'sub%M %#S3, %AM',
509
	units     => [ "GP" ],
510
	latency   => 1,
511
512
513
514
	mode      => 'mode_M',
	modified_flags => $status_flags
},

515
Sbb => {
516
	state     => "exc_pinned",
517
	reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ],
518
	               out => [ "in_r4", "flags", "none" ] },
519
	ins       => [ "base", "index", "mem", "minuend", "subtrahend", "eflags" ],
520
	outs      => [ "res", "flags", "M" ],
Christoph Mallon's avatar
Christoph Mallon committed
521
	am        => "source,binary",
522
	emit      => 'sbb%M %B',
523
	units     => [ "GP" ],
524
	latency   => 1,
525
526
	mode      => $mode_gp,
	modified_flags => $status_flags
527
528
},

529
Sbb0 => {
530
	# Spiller currently fails when rematerializing flag consumers
531
	# irn_flags => [ "rematerializable" ],
532
533
	reg_req   => { in => [ "flags" ], out => [ "gp", "flags" ] },
	outs      => [ "res", "flags" ],
534
	emit      => "sbb%M %D0, %D0",
535
536
537
538
539
540
	units     => [ "GP" ],
	latency   => 1,
	mode      => $mode_gp,
	modified_flags => $status_flags
},

541
l_Sub => {
542
	ins       => [ "minuend", "subtrahend" ],
543
544
	attr_type => "",
	dump_func => "NULL",
545
546
547
},

l_Sbb => {
548
	ins       => [ "minuend", "subtrahend", "eflags" ],
549
550
	attr_type => "",
	dump_func => "NULL",
551
552
},

553
IDiv => {
554
	op_flags  => [ "fragile", "uses_memory" ],
555
	state     => "exc_pinned",
556
	reg_req   => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
Matthias Braun's avatar
Matthias Braun committed
557
	               out => [ "eax", "flags", "none", "edx", "none", "none" ] },
558
	ins       => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
Matthias Braun's avatar
Matthias Braun committed
559
	outs      => [ "div_res", "flags", "M", "mod_res", "X_regular", "X_except" ],
560
	am        => "source,unary",
561
	emit      => "idiv%M %AS3",
562
563
	latency   => 25,
	units     => [ "GP" ],
564
	modified_flags => $status_flags
565
566
},

567
Div => {
568
	op_flags  => [ "fragile", "uses_memory" ],
569
	state     => "exc_pinned",
570
	reg_req   => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
Matthias Braun's avatar
Matthias Braun committed
571
	               out => [ "eax", "flags", "none", "edx", "none", "none" ] },
572
	ins       => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
Matthias Braun's avatar
Matthias Braun committed
573
	outs      => [ "div_res", "flags", "M", "mod_res", "X_regular", "X_except" ],
574
	am        => "source,unary",
575
	emit      => "div%M %AS3",
576
577
	latency   => 25,
	units     => [ "GP" ],
578
	modified_flags => $status_flags
579
580
},

581
Shl => {
582
	irn_flags => [ "rematerializable" ],
583
584
585
586
	reg_req   => { in => [ "gp", "ecx" ],
	               out => [ "in_r1 !in_r2", "flags" ] },
	ins       => [ "val", "count" ],
	outs      => [ "res", "flags" ],
587
	emit      => 'shl%M %<S1, %S0',
588
	units     => [ "GP" ],
589
	latency   => 1,
590
591
	mode      => $mode_gp,
	modified_flags => $status_flags
592
593
},

594
ShlMem => {
595
	irn_flags => [ "rematerializable" ],
596
	state     => "exc_pinned",
597
598
	reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
	ins       => [ "base", "index", "mem", "count" ],
599
	emit      => 'shl%M %<S3, %AM',
600
	units     => [ "GP" ],
601
	latency   => 1,
602
603
604
605
	mode      => "mode_M",
	modified_flags => $status_flags
},

606
ShlD => {
607
	irn_flags => [ "rematerializable" ],
608
609
610
611
	reg_req   => { in => [ "gp", "gp", "ecx" ],
	               out => [ "in_r1 !in_r2 !in_r3", "flags" ] },
	ins       => [ "val_high", "val_low", "count" ],
	outs      => [ "res", "flags" ],
612
	emit      => "shld%M %<S2, %S1, %D0",
613
614
	latency   => 6,
	units     => [ "GP" ],
615
616
	mode      => $mode_gp,
	modified_flags => $status_flags
617
618
},

619
Shr => {
620
	irn_flags => [ "rematerializable" ],
621
622
	reg_req   => { in => [ "gp", "ecx" ],
	               out => [ "in_r1 !in_r2", "flags" ] },
623
	ins       => [ "val", "count" ],
624
	outs      => [ "res", "flags" ],
625
	emit      => 'shr%M %<S1, %S0',
626
	units     => [ "GP" ],
627
	mode      => $mode_gp,
628
	latency   => 1,
629
	modified_flags => $status_flags
630
631
},

632
ShrMem => {
633
	irn_flags => [ "rematerializable" ],
634
	state     => "exc_pinned",
635
636
	reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
	ins       => [ "base", "index", "mem", "count" ],
637
	emit      => 'shr%M %<S3, %AM',
638
639
	units     => [ "GP" ],
	mode      => "mode_M",
640
	latency   => 1,
641
642
643
	modified_flags => $status_flags
},

644
ShrD => {
645
	irn_flags => [ "rematerializable" ],
646
647
648
649
	reg_req   => { in => [ "gp", "gp", "ecx" ],
	               out => [ "in_r1 !in_r2 !in_r3", "flags" ] },
	ins       => [ "val_high", "val_low", "count" ],
	outs      => [ "res", "flags" ],
650
	emit      => "shrd%M %<S2, %S1, %D0",
651
652
	latency   => 6,
	units     => [ "GP" ],
653
654
	mode      => $mode_gp,
	modified_flags => $status_flags
655
656
},

657
Sar => {
658
	irn_flags => [ "rematerializable" ],
659
660
	reg_req   => { in => [ "gp", "ecx" ],
	               out => [ "in_r1 !in_r2", "flags" ] },
661
	ins       => [ "val", "count" ],
662
	outs      => [ "res", "flags" ],
663
	emit      => 'sar%M %<S1, %S0',
664
	units     => [ "GP" ],
665
	latency   => 1,
666
667
	mode      => $mode_gp,
	modified_flags => $status_flags
668
669
},

670
SarMem => {
671
	irn_flags => [ "rematerializable" ],
672
	state     => "exc_pinned",
673
674
	reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
	ins       => [ "base", "index", "mem", "count" ],
675
	emit      => 'sar%M %<S3, %AM',
676
	units     => [ "GP" ],
677
	latency   => 1,
678
679
680
681
	mode      => "mode_M",
	modified_flags => $status_flags
},

682
Ror => {
683
	irn_flags => [ "rematerializable" ],
684
685
	reg_req   => { in => [ "gp", "ecx" ],
	               out => [ "in_r1 !in_r2", "flags" ] },
686
	ins       => [ "val", "count" ],
687
	outs      => [ "res", "flags" ],
688
	emit      => 'ror%M %<S1, %S0',
689
	units     => [ "GP" ],
690
	latency   => 1,
691
692
	mode      => $mode_gp,
	modified_flags => $status_flags
693
694
},

695
RorMem => {
696
	irn_flags => [ "rematerializable" ],
697
	state     => "exc_pinned",
698
699
	reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
	ins       => [ "base", "index", "mem", "count" ],
700
	emit      => 'ror%M %<S3, %AM',
701
	units     => [ "GP" ],
702
	latency   => 1,
703
704
705
706
	mode      => "mode_M",
	modified_flags => $status_flags
},

707
Rol => {
708
	irn_flags => [ "rematerializable" ],
709
710
	reg_req   => { in => [ "gp", "ecx" ],
	               out => [ "in_r1 !in_r2", "flags" ] },
711
	ins       => [ "val", "count" ],
712
	outs      => [ "res", "flags" ],
713
	emit      => 'rol%M %<S1, %D0',
714