+xLoad => {
+ op_flags => "L|F",
+ state => "exc_pinned",
+ reg_req => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
+ ins => [ "base", "index", "mem" ],
+ emit => '. mov%XXM %AM, %D0',
+ attr => "ir_mode *load_mode",
+ init_attr => "attr->ls_mode = load_mode;",
+ outs => [ "res", "M" ],
+ latency => 0,
+ units => [ "SSE" ],
+},
+
+xStore => {
+ op_flags => "L|F",
+ state => "exc_pinned",
+ reg_req => { in => [ "gp", "gp", "none", "xmm" ] },
+ ins => [ "base", "index", "mem", "val" ],
+ emit => '. mov%XXM %S3, %AM',
+ latency => 0,
+ units => [ "SSE" ],
+ mode => "mode_M",
+},
+
+xStoreSimple => {
+ op_flags => "L|F",
+ state => "exc_pinned",
+ reg_req => { in => [ "gp", "gp", "none", "xmm" ] },
+ ins => [ "base", "index", "mem", "val" ],
+ emit => '. mov%XXM %S3, %AM',
+ latency => 0,
+ units => [ "SSE" ],
+ mode => "mode_M",
+},
+
+CvtSI2SS => {
+ op_flags => "L|F",
+ reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
+ ins => [ "base", "index", "mem", "val" ],
+ emit => '. cvtsi2ss %D0, %AM',
+ latency => 2,
+ units => [ "SSE" ],
+ mode => $mode_xmm
+},
+
+CvtSI2SD => {
+ op_flags => "L|F",
+ reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
+ ins => [ "base", "index", "mem", "val" ],
+ emit => '. cvtsi2sd %unop3',
+ latency => 2,
+ units => [ "SSE" ],
+ mode => $mode_xmm
+},
+
+
+l_X87toSSE => {
+ op_flags => "L|F",
+ cmp_attr => "return 1;",
+ arity => 3,
+},
+
+l_SSEtoX87 => {
+ op_flags => "L|F",
+ cmp_attr => "return 1;",
+ arity => 3,
+},
+
+# CopyB
+
+CopyB => {
+ op_flags => "F|H",
+ state => "pinned",
+ reg_req => { in => [ "edi", "esi", "ecx", "none" ], out => [ "edi", "esi", "ecx", "none" ] },
+ outs => [ "DST", "SRC", "CNT", "M" ],
+ units => [ "GP" ],
+# we don't care about this flag, so no need to mark this node
+# modified_flags => [ "DF" ]
+},
+
+CopyB_i => {
+ op_flags => "F|H",
+ state => "pinned",
+ reg_req => { in => [ "edi", "esi", "none" ], out => [ "edi", "esi", "none" ] },
+ outs => [ "DST", "SRC", "M" ],
+ units => [ "GP" ],
+# we don't care about this flag, so no need to mark this node
+# modified_flags => [ "DF" ]
+},
+
+# Conversions
+
+Conv_I2I => {
+ state => "exc_pinned",
+ reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "gp", "none" ] },
+ ins => [ "base", "index", "mem", "val" ],
+ units => [ "GP" ],
+ attr => "ir_mode *smaller_mode",
+ init_attr => "attr->ls_mode = smaller_mode;",
+ mode => $mode_gp,
+},
+
+Conv_I2I8Bit => {
+ state => "exc_pinned",
+ reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "gp", "none" ] },
+ ins => [ "base", "index", "mem", "val" ],
+ units => [ "GP" ],
+ attr => "ir_mode *smaller_mode",
+ init_attr => "attr->ls_mode = smaller_mode;",
+ mode => $mode_gp,
+},
+
+Conv_I2FP => {
+ reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm", "none" ] },
+ ins => [ "base", "index", "mem", "val" ],
+ latency => 10,
+ units => [ "SSE" ],
+ mode => "mode_E",
+},
+
+Conv_FP2I => {
+ reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "gp", "none" ] },
+ ins => [ "base", "index", "mem", "val" ],
+ latency => 10,
+ units => [ "SSE" ],
+ mode => $mode_gp,
+},
+
+Conv_FP2FP => {
+ reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "xmm", "none" ] },
+ ins => [ "base", "index", "mem", "val" ],
+ latency => 8,
+ units => [ "SSE" ],
+ mode => "mode_E",
+},
+
+#----------------------------------------------------------#
+# _ _ _ __ _ _ #
+# (_) | | | | / _| | | | #
+# __ ___ _ __| |_ _ _ __ _| | | |_| | ___ __ _| |_ #
+# \ \ / / | '__| __| | | |/ _` | | | _| |/ _ \ / _` | __| #
+# \ V /| | | | |_| |_| | (_| | | | | | | (_) | (_| | |_ #
+# \_/ |_|_| \__|\__,_|\__,_|_| |_| |_|\___/ \__,_|\__| #
+# | | #
+# _ __ ___ __| | ___ ___ #
+# | '_ \ / _ \ / _` |/ _ \/ __| #
+# | | | | (_) | (_| | __/\__ \ #
+# |_| |_|\___/ \__,_|\___||___/ #
+#----------------------------------------------------------#
+
+vfadd => {
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
+ ins => [ "base", "index", "mem", "left", "right", "fpcw" ],
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+ attr_type => "ia32_x87_attr_t",
+},
+
+vfmul => {
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
+ ins => [ "base", "index", "mem", "left", "right", "fpcw" ],
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+ attr_type => "ia32_x87_attr_t",
+},
+
+l_vfmul => {
+ op_flags => "C",
+ cmp_attr => "return 1;",
+ arity => 2,
+},
+
+vfsub => {
+ irn_flags => "R",
+ reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
+ ins => [ "base", "index", "mem", "left", "right", "fpcw" ],
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+ attr_type => "ia32_x87_attr_t",
+},
+
+l_vfsub => {
+ cmp_attr => "return 1;",
+ arity => 2,
+},
+
+vfdiv => {
+ reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp", "none" ] },
+ ins => [ "base", "index", "mem", "left", "right", "fpcw" ],
+ outs => [ "res", "M" ],
+ latency => 20,
+ units => [ "VFP" ],
+ attr_type => "ia32_x87_attr_t",
+},
+
+l_vfdiv => {
+ cmp_attr => "return 1;",
+ outs => [ "res", "M" ],
+ arity => 2,
+},
+
+vfprem => {
+ reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
+ ins => [ "base", "index", "mem", "left", "right", "fpcw" ],
+ latency => 20,
+ units => [ "VFP" ],
+ mode => "mode_E",
+ attr_type => "ia32_x87_attr_t",
+},
+
+l_vfprem => {
+ cmp_attr => "return 1;",
+ arity => 2,
+},
+
+vfabs => {
+ irn_flags => "R",
+ reg_req => { in => [ "vfp"], out => [ "vfp" ] },
+ ins => [ "value" ],
+ latency => 2,
+ units => [ "VFP" ],
+ mode => "mode_E",
+ attr_type => "ia32_x87_attr_t",
+},
+
+vfchs => {
+ irn_flags => "R",
+ reg_req => { in => [ "vfp"], out => [ "vfp" ] },
+ ins => [ "value" ],
+ latency => 2,
+ units => [ "VFP" ],
+ mode => "mode_E",
+ attr_type => "ia32_x87_attr_t",
+},
+
+# virtual Load and Store
+
+vfld => {
+ op_flags => "L|F",
+ state => "exc_pinned",
+ reg_req => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
+ ins => [ "base", "index", "mem" ],
+ outs => [ "res", "M" ],
+ attr => "ir_mode *load_mode",
+ init_attr => "attr->attr.ls_mode = load_mode;",
+ latency => 2,
+ units => [ "VFP" ],
+ attr_type => "ia32_x87_attr_t",
+},
+
+vfst => {
+ op_flags => "L|F",
+ state => "exc_pinned",
+ reg_req => { in => [ "gp", "gp", "none", "vfp" ] },
+ ins => [ "base", "index", "mem", "val" ],
+ attr => "ir_mode *store_mode",
+ init_attr => "attr->attr.ls_mode = store_mode;",
+ latency => 2,
+ units => [ "VFP" ],
+ mode => "mode_M",
+ attr_type => "ia32_x87_attr_t",
+},
+
+# Conversions
+
+vfild => {
+ state => "exc_pinned",
+ reg_req => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
+ outs => [ "res", "M" ],
+ ins => [ "base", "index", "mem" ],
+ latency => 4,
+ units => [ "VFP" ],
+ attr_type => "ia32_x87_attr_t",
+},
+
+l_vfild => {
+ cmp_attr => "return 1;",
+ outs => [ "res", "M" ],
+ arity => 2,
+},
+
+vfist => {
+ state => "exc_pinned",
+ reg_req => { in => [ "gp", "gp", "none", "vfp", "fpcw" ] },
+ ins => [ "base", "index", "mem", "val", "fpcw" ],
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_M",
+ attr_type => "ia32_x87_attr_t",
+},
+
+l_vfist => {
+ cmp_attr => "return 1;",
+ state => "exc_pinned",
+ arity => 3,
+ mode => "mode_M",
+},
+
+
+# constants
+
+vfldz => {
+ irn_flags => "R",
+ reg_req => { out => [ "vfp" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+ attr_type => "ia32_x87_attr_t",
+},
+
+vfld1 => {
+ irn_flags => "R",
+ reg_req => { out => [ "vfp" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+ attr_type => "ia32_x87_attr_t",
+},
+
+vfldpi => {
+ irn_flags => "R",
+ reg_req => { out => [ "vfp" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+ attr_type => "ia32_x87_attr_t",
+},
+
+vfldln2 => {
+ irn_flags => "R",
+ reg_req => { out => [ "vfp" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+ attr_type => "ia32_x87_attr_t",
+},
+
+vfldlg2 => {
+ irn_flags => "R",
+ reg_req => { out => [ "vfp" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+ attr_type => "ia32_x87_attr_t",
+},
+
+vfldl2t => {
+ irn_flags => "R",
+ reg_req => { out => [ "vfp" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+ attr_type => "ia32_x87_attr_t",
+},
+
+vfldl2e => {
+ irn_flags => "R",
+ reg_req => { out => [ "vfp" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+ attr_type => "ia32_x87_attr_t",
+},
+
+# other
+
+vFucomFnstsw => {
+# we can't allow to rematerialize this node so we don't have
+# accidently produce Phi(Fucom, Fucom(flipped))
+# irn_flags => "R",
+ reg_req => { in => [ "vfp", "vfp" ], out => [ "eax" ] },
+ ins => [ "left", "right" ],
+ outs => [ "flags" ],
+ am => "source,binary",
+ attr => "int flipped",
+ init_attr => "attr->attr.data.cmp_flipped = flipped;",
+ latency => 3,
+ units => [ "VFP" ],
+ attr_type => "ia32_x87_attr_t",
+ mode => $mode_gp
+},
+
+Sahf => {
+ irn_flags => "R",
+ reg_req => { in => [ "eax" ], out => [ "eflags" ] },
+ ins => [ "val" ],
+ outs => [ "flags" ],
+ emit => '. sahf',
+ units => [ "GP" ],
+ mode => $mode_flags,
+},
+
+#------------------------------------------------------------------------#
+# ___ _____ __ _ _ _ #
+# __ _( _ )___ | / _| | ___ __ _| |_ _ __ ___ __| | ___ ___ #
+# \ \/ / _ \ / / | |_| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
+# > < (_) |/ / | _| | (_) | (_| | |_ | | | | (_) | (_| | __/\__ \ #
+# /_/\_\___//_/ |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
+#------------------------------------------------------------------------#
+
+# Note: gas is strangely buggy: fdivrp and fdivp as well as fsubrp and fsubp
+# are swapped, we work this around in the emitter...
+
+fadd => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ reg_req => { },
+ emit => '. fadd%XM %x87_binop',
+ attr_type => "ia32_x87_attr_t",
+},
+
+faddp => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ reg_req => { },
+ emit => '. faddp%XM %x87_binop',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fmul => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ reg_req => { },
+ emit => '. fmul%XM %x87_binop',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fmulp => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ reg_req => { },
+ emit => '. fmulp%XM %x87_binop',,
+ attr_type => "ia32_x87_attr_t",
+},
+
+fsub => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ reg_req => { },
+ emit => '. fsub%XM %x87_binop',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fsubp => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ reg_req => { },
+# see note about gas bugs
+ emit => '. fsubrp%XM %x87_binop',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fsubr => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ irn_flags => "R",
+ reg_req => { },
+ emit => '. fsubr%XM %x87_binop',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fsubrp => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ irn_flags => "R",
+ reg_req => { },
+# see note about gas bugs
+ emit => '. fsubp%XM %x87_binop',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fprem => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ reg_req => { },
+ emit => '. fprem1',
+ attr_type => "ia32_x87_attr_t",
+},
+
+# this node is just here, to keep the simulator running
+# we can omit this when a fprem simulation function exists
+fpremp => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ reg_req => { },
+ emit => '. fprem1',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fdiv => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ reg_req => { },
+ emit => '. fdiv%XM %x87_binop',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fdivp => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ reg_req => { },
+# see note about gas bugs
+ emit => '. fdivrp%XM %x87_binop',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fdivr => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ reg_req => { },
+ emit => '. fdivr%XM %x87_binop',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fdivrp => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ reg_req => { },
+# see note about gas bugs
+ emit => '. fdivp%XM %x87_binop',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fabs => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ reg_req => { },
+ emit => '. fabs',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fchs => {
+ op_flags => "R|K",
+ rd_constructor => "NONE",
+ reg_req => { },
+ emit => '. fchs',
+ attr_type => "ia32_x87_attr_t",
+},
+
+# x87 Load and Store
+
+fld => {
+ rd_constructor => "NONE",
+ op_flags => "R|L|F",
+ state => "exc_pinned",
+ reg_req => { },
+ emit => '. fld%XM %AM',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fst => {
+ rd_constructor => "NONE",
+ op_flags => "R|L|F",
+ state => "exc_pinned",
+ reg_req => { },
+ emit => '. fst%XM %AM',
+ mode => "mode_M",
+ attr_type => "ia32_x87_attr_t",
+},
+
+fstp => {
+ rd_constructor => "NONE",
+ op_flags => "R|L|F",
+ state => "exc_pinned",
+ reg_req => { },
+ emit => '. fstp%XM %AM',
+ mode => "mode_M",
+ attr_type => "ia32_x87_attr_t",
+},
+
+# Conversions
+
+fild => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ reg_req => { },
+ emit => '. fild%M %AM',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fist => {
+ op_flags => "R",
+ state => "exc_pinned",
+ rd_constructor => "NONE",
+ reg_req => { },
+ emit => '. fist%M %AM',
+ mode => "mode_M",
+ attr_type => "ia32_x87_attr_t",
+},
+
+fistp => {
+ op_flags => "R",
+ state => "exc_pinned",
+ rd_constructor => "NONE",
+ reg_req => { },
+ emit => '. fistp%M %AM',
+ mode => "mode_M",
+ attr_type => "ia32_x87_attr_t",
+},
+
+# constants
+
+fldz => {
+ op_flags => "R|c|K",
+ irn_flags => "R",
+ reg_req => { },
+ emit => '. fldz',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fld1 => {
+ op_flags => "R|c|K",
+ irn_flags => "R",
+ reg_req => { },
+ emit => '. fld1',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fldpi => {
+ op_flags => "R|c|K",
+ irn_flags => "R",
+ reg_req => { },
+ emit => '. fldpi',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fldln2 => {
+ op_flags => "R|c|K",
+ irn_flags => "R",
+ reg_req => { },
+ emit => '. fldln2',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fldlg2 => {
+ op_flags => "R|c|K",
+ irn_flags => "R",
+ reg_req => { },
+ emit => '. fldlg2',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fldl2t => {
+ op_flags => "R|c|K",
+ irn_flags => "R",
+ reg_req => { },
+ emit => '. fldll2t',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fldl2e => {
+ op_flags => "R|c|K",
+ irn_flags => "R",
+ reg_req => { },
+ emit => '. fldl2e',
+ attr_type => "ia32_x87_attr_t",
+},
+
+# fxch, fpush, fpop
+# Note that it is NEVER allowed to do CSE on these nodes
+# Moreover, note the virtual register requierements!
+
+fxch => {
+ op_flags => "R|K",
+ reg_req => { },
+ cmp_attr => "return 1;",
+ emit => '. fxch %X0',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fpush => {
+ op_flags => "R|K",
+ reg_req => {},
+ cmp_attr => "return 1;",
+ emit => '. fld %X0',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fpushCopy => {
+ op_flags => "R",
+ reg_req => { in => [ "vfp"], out => [ "vfp" ] },
+ cmp_attr => "return 1;",
+ emit => '. fld %X0',
+ attr_type => "ia32_x87_attr_t",
+},
+
+fpop => {
+ op_flags => "K",
+ reg_req => { },
+ cmp_attr => "return 1;",
+ emit => '. fstp %X0',
+ attr_type => "ia32_x87_attr_t",
+},
+
+ffreep => {
+ op_flags => "K",
+ reg_req => { },
+ cmp_attr => "return 1;",
+ emit => '. ffreep %X0',
+ attr_type => "ia32_x87_attr_t",
+},
+
+emms => {
+ op_flags => "K",
+ reg_req => { },
+ cmp_attr => "return 1;",
+ emit => '. emms',
+ attr_type => "ia32_x87_attr_t",
+},
+
+femms => {
+ op_flags => "K",
+ reg_req => { },
+ cmp_attr => "return 1;",
+ emit => '. femms',
+ attr_type => "ia32_x87_attr_t",
+},
+
+# compare
+
+FucomFnstsw => {
+ op_flags => "R",
+ reg_req => { },
+ emit => ". fucom %X1\n".
+ ". fnstsw",
+ attr_type => "ia32_x87_attr_t",
+},
+
+FucompFnstsw => {
+ op_flags => "R",
+ reg_req => { },
+ emit => ". fucomp %X1\n".
+ ". fnstsw",
+ attr_type => "ia32_x87_attr_t",
+},
+
+FucomppFnstsw => {
+ op_flags => "R",
+ reg_req => { },
+ emit => ". fucompp\n".
+ ". fnstsw",
+ attr_type => "ia32_x87_attr_t",
+},
+
+
+# -------------------------------------------------------------------------------- #
+# ____ ____ _____ _ _ #
+# / ___/ ___|| ____| __ _____ ___| |_ ___ _ __ _ __ ___ __| | ___ ___ #
+# \___ \___ \| _| \ \ / / _ \/ __| __/ _ \| '__| | '_ \ / _ \ / _` |/ _ \/ __| #
+# ___) |__) | |___ \ V / __/ (__| || (_) | | | | | | (_) | (_| | __/\__ \ #
+# |____/____/|_____| \_/ \___|\___|\__\___/|_| |_| |_|\___/ \__,_|\___||___/ #
+# #
+# -------------------------------------------------------------------------------- #
+
+
+# Spilling and reloading of SSE registers, hardcoded, not generated #
+
+xxLoad => {
+ op_flags => "L|F",
+ state => "exc_pinned",
+ reg_req => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
+ emit => '. movdqu %D0, %AM',
+ outs => [ "res", "M" ],
+ units => [ "SSE" ],
+},
+
+xxStore => {
+ op_flags => "L|F",
+ state => "exc_pinned",
+ reg_req => { in => [ "gp", "gp", "none", "xmm" ] },
+ ins => [ "base", "index", "mem", "val" ],
+ emit => '. movdqu %binop',
+ units => [ "SSE" ],
+ mode => "mode_M",