# <op-name> => {
# "op_flags" => "N|L|C|X|I|F|Y|H|c|K",
# "irn_flags" => "R|N|I"
-# "arity" => "0|1|2|3 ... |variable|dynamic|all",
-# "state" => "floats|pinned",
+# "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" },
# ...
# ],
# "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",
# "rd_constructor" => "c source code which constructs an ir_node"
# },
# N not spillable
# I ignore for register allocation
#
-# state: state of the operation, OPTIONAL (default is "pinned")
+# state: state of the operation, OPTIONAL (default is "floats")
#
# arity: arity of the operation, MUST NOT BE OMITTED
#
# 1 - caller save (register must be saved by the caller of a function)
# 2 - callee save (register must be saved by the called function)
# 4 - ignore (do not assign this register)
-# 8 - this is the stack pointer
-# 16 - this is the base pointer
-# NOTE: Make sure to list the registers returning the call-result before all other
-# caller save registers and in the correct order, otherwise it will break
-# the magic!
-# Last entry of each class is the largest Firm-Mode a register can hold
+# NOTE: Last entry of each class is the largest Firm-Mode a register can hold
%reg_classes = (
"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" => 16 },
- { "name" => "esp", "type" => 8 },
- { "name" => "xxx", "type" => 4 }, # we need a dummy register for NoReg and Unknown nodes
+ { "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" => 6 },
+ { "name" => "xxx", "type" => 6 }, # we need a dummy register for NoReg and Unknown nodes
{ "mode" => "mode_P" }
],
"fp" => [
{ "name" => "xmm5", "type" => 1 },
{ "name" => "xmm6", "type" => 1 },
{ "name" => "xmm7", "type" => 1 },
+ { "name" => "xxxx", "type" => 6 }, # we need a dummy register for NoReg and Unknown nodes
{ "mode" => "mode_D" }
]
); # %reg_classes
'
},
+"CMov" => {
+ "irn_flags" => "R",
+ "comment" => "construct Mux: Mux(sel, a, b) == sel ? a : b",
+ "reg_req" => { "in" => [ "gp", "gp", "gp" ], "out" => [ "in_r2" ] },
+ "emit" =>
+'. cmp %S1, 0\t\t\t/* compare Sel for CMov (%A2, %A3) */
+. cmovne %D1, %S3\t\t\t/* sel == true -> return %S3 */
+'
+},
+
# not commutative operations
"Sub" => {
# other operations
"Conv" => {
- "arity" => 1,
"reg_req" => { "in" => [ "gp" ], "out" => [ "in_r1" ] },
"comment" => "construct Conv: Conv(a) = (conv)a"
},
"emit" => '. mov %D1, %C\t\t\t/* Mov Const into register */',
"cmp_attr" =>
'
- if (attr_a->tp == attr_b->tp) {
- if (attr_a->tp == ia32_SymConst) {
+ if (attr_a->data.tp == attr_b->data.tp) {
+ if (attr_a->data.tp == ia32_SymConst) {
if (attr_a->sc == NULL || attr_b->sc == NULL)
return 1;
else
"emit" => '. lea %D1, %ia32_emit_am\t\t/* %D1 = %S1 + %S2 << %C + %O, (%A1, %A2) */'
},
-"StackParam" => {
- "arity" => 1,
- "remat" => 1,
- "comment" => "constructs a Stack Parameter to retrieve a parameter from Stack",
- "reg_req" => { "in" => [ "none" ], "out" => [ "gp" ] },
- "cmp_attr" =>
-'
- return (attr_a->pn_code != attr_b->pn_code);
-'
-},
-
-"StackArg" => {
- "arity" => 2,
- "comment" => "constructs a Stack Argument to pass an argument on Stack",
- "reg_req" => { "in" => [ "none", "gp" ], "out" => [ "none" ] },
- "cmp_attr" =>
-'
- return (attr_a->pn_code != attr_b->pn_code);
-'
-},
-
#--------------------------------------------------------#
# __ _ _ _ #
# / _| | | | | | #
# other operations
"fConv" => {
- "arity" => 1,
"reg_req" => { "in" => [ "fp" ], "out" => [ "gp" ] },
"comment" => "construct Conv: Conv(a) = (conv)a"
},
"emit" => '. mov%M %D1, %C\t\t\t/* Load fConst into register */',
"cmp_attr" =>
'
- if (attr_a->tp == attr_b->tp) {
- if (attr_a->tp == ia32_SymConst) {
+ if (attr_a->data.tp == attr_b->data.tp) {
+ if (attr_a->data.tp == ia32_SymConst) {
if (attr_a->sc == NULL || attr_b->sc == NULL)
return 1;
else
"emit" => '. movs%M %ia32_emit_am, %S3\t\t\t/* Store(%S3) -> (%A1) */'
},
-"fStackParam" => {
- "arity" => 1,
- "remat" => 1,
- "comment" => "constructs a Stack Parameter to retrieve a SSE parameter from Stack",
- "reg_req" => { "in" => [ "none" ], "out" => [ "fp" ] },
- "cmp_attr" =>
-'
- return (attr_a->pn_code != attr_b->pn_code);
-'
+# CopyB
+
+"CopyB" => {
+ "op_flags" => "F|H",
+ "state" => "pinned",
+ "comment" => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)",
+ "reg_req" => { "in" => [ "edi", "esi", "ecx", "none" ], "out" => [ "none" ] },
},
-"fStackArg" => {
- "arity" => 2,
- "comment" => "constructs a Stack Argument to pass an argument on Stack",
- "reg_req" => { "in" => [ "none", "fp" ], "out" => [ "none" ] },
- "cmp_attr" =>
-'
- return (attr_a->pn_code != attr_b->pn_code);
-'
+"CopyB_i" => {
+ "op_flags" => "F|H",
+ "state" => "pinned",
+ "comment" => "implements a memcopy: CopyB(dst, src, mem) == memcpy(dst, src, attr(size))",
+ "reg_req" => { "in" => [ "edi", "esi", "none" ], "out" => [ "none" ] },
},
# Call
"
},
-# Return
-
-"Return" => {
- "op_flags" => "L|X",
- "state" => "pinned",
- "arity" => "variable",
- "comment" => "construct Return: Return(...)",
- "args" => [
- { "type" => "int", "name" => "n" },
- { "type" => "ir_node **", "name" => "in" }
- ],
- "rd_constructor" =>
-" if (!op_ia32_Return) assert(0);
- return new_ir_node(db, irg, block, op_ia32_Return, mode_X, n, in);
-"
-},
-
-# M/Alloc
-
-"Alloca" => {
- "op_flags" => "L|F",
- "state" => "pinned",
- "arity" => "2",
- "comment" => "construct Alloca: allocate memory on Stack",
- "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] }
-},
-
); # end of %nodes