From: Jan Beulich Date: Mon, 26 Apr 2021 08:37:30 +0000 (+0200) Subject: x86: optimize LEA X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=fe134c656991;p=binutils-gdb.git x86: optimize LEA Over the years I've seen a number of instances where people used lea (%reg1), %reg2 or lea symbol, %reg despite the same thing being expressable via MOV. Since additionally LEA often has restrictions towards the ports it can be issued to, while MOV typically gets dealt with simply by register renaming, transform to MOV when possible (without growing opcode size and without altering involved relocation types). Note that for Mach-O the new 64-bit testcases would fail (for BFD_RELOC_X86_64_32S not having a representation), and hence get skipped there. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 585c98b2521..1e056f7f8ff 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,16 @@ +2021-04-26 Jan Beulich + + * config/tc-i386.c (want_disp32): Also check for SIZE32. + (optimize_encoding): Handle LEA. + * testsuite/gas/i386/lea.s, testsuite/gas/i386/lea.d, + testsuite/gas/i386/lea.e, testsuite/gas/i386/lea-optimize.d: + Add many more forms. + * testsuite/gas/i386/lea16.s, testsuite/gas/i386/lea16-optimize.d, + testsuite/gas/i386/lea64.s, testsuite/gas/i386/lea64.d, + testsuite/gas/i386/lea64.e, testsuite/gas/i386/lea64-optimize.d: + New. + * testsuite/gas/i386/i386.exp: Run new tests. + 2021-04-26 Jan Beulich * config/tc-i386.c (md_apply_fix): Mark BFD_RELOC_X86_64_32S as diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 1f9844dcb52..116b9db518f 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -3562,7 +3562,8 @@ want_disp32 (const insn_template *t) || i.prefix[ADDR_PREFIX] || (t->base_opcode == 0x8d && t->opcode_modifier.opcodespace == SPACE_BASE - && !i.types[1].bitfield.qword); + && (!i.types[1].bitfield.qword + || t->opcode_modifier.size == SIZE32)); } static int @@ -4069,6 +4070,145 @@ optimize_encoding (void) { unsigned int j; + if (i.tm.opcode_modifier.opcodespace == SPACE_BASE + && i.tm.base_opcode == 0x8d) + { + /* Optimize: -O: + lea symbol, %rN -> mov $symbol, %rN + lea (%rM), %rN -> mov %rM, %rN + lea (,%rM,1), %rN -> mov %rM, %rN + + and in 32-bit mode for 16-bit addressing + + lea (%rM), %rN -> movzx %rM, %rN + + and in 64-bit mode zap 32-bit addressing in favor of using a + 32-bit (or less) destination. + */ + if (flag_code == CODE_64BIT && i.prefix[ADDR_PREFIX]) + { + if (!i.op[1].regs->reg_type.bitfield.word) + i.tm.opcode_modifier.size = SIZE32; + i.prefix[ADDR_PREFIX] = 0; + } + + if (!i.index_reg && !i.base_reg) + { + /* Handle: + lea symbol, %rN -> mov $symbol, %rN + */ + if (flag_code == CODE_64BIT) + { + /* Don't transform a relocation to a 16-bit one. */ + if (i.op[0].disps + && i.op[0].disps->X_op != O_constant + && i.op[1].regs->reg_type.bitfield.word) + return; + + if (!i.op[1].regs->reg_type.bitfield.qword + || i.tm.opcode_modifier.size == SIZE32) + { + i.tm.base_opcode = 0xb8; + i.tm.opcode_modifier.modrm = 0; + if (!i.op[1].regs->reg_type.bitfield.word) + i.types[0].bitfield.imm32 = 1; + else + { + i.tm.opcode_modifier.size = SIZE16; + i.types[0].bitfield.imm16 = 1; + } + } + else + { + /* Subject to further optimization below. */ + i.tm.base_opcode = 0xc7; + i.tm.extension_opcode = 0; + i.types[0].bitfield.imm32s = 1; + i.types[0].bitfield.baseindex = 0; + } + } + /* Outside of 64-bit mode address and operand sizes have to match if + a relocation is involved, as otherwise we wouldn't (currently) or + even couldn't express the relocation correctly. */ + else if (i.op[0].disps + && i.op[0].disps->X_op != O_constant + && ((!i.prefix[ADDR_PREFIX]) + != (flag_code == CODE_32BIT + ? i.op[1].regs->reg_type.bitfield.dword + : i.op[1].regs->reg_type.bitfield.word))) + return; + else + { + i.tm.base_opcode = 0xb8; + i.tm.opcode_modifier.modrm = 0; + if (i.op[1].regs->reg_type.bitfield.dword) + i.types[0].bitfield.imm32 = 1; + else + i.types[0].bitfield.imm16 = 1; + + if (i.op[0].disps + && i.op[0].disps->X_op == O_constant + && i.op[1].regs->reg_type.bitfield.dword + && !i.prefix[ADDR_PREFIX] != (flag_code == CODE_32BIT)) + i.op[0].disps->X_add_number &= 0xffff; + } + + i.tm.operand_types[0] = i.types[0]; + i.imm_operands = 1; + if (!i.op[0].imms) + { + i.op[0].imms = &im_expressions[0]; + i.op[0].imms->X_op = O_absent; + } + } + else if (i.op[0].disps + && (i.op[0].disps->X_op != O_constant + || i.op[0].disps->X_add_number)) + return; + else + { + /* Handle: + lea (%rM), %rN -> mov %rM, %rN + lea (,%rM,1), %rN -> mov %rM, %rN + lea (%rM), %rN -> movzx %rM, %rN + */ + const reg_entry *addr_reg; + + if (!i.index_reg && i.base_reg->reg_num != RegIP) + addr_reg = i.base_reg; + else if (!i.base_reg + && i.index_reg->reg_num != RegIZ + && !i.log2_scale_factor) + addr_reg = i.index_reg; + else + return; + + if (addr_reg->reg_type.bitfield.word + && i.op[1].regs->reg_type.bitfield.dword) + { + if (flag_code != CODE_32BIT) + return; + i.tm.opcode_modifier.opcodespace = SPACE_0F; + i.tm.base_opcode = 0xb7; + } + else + i.tm.base_opcode = 0x8b; + + if (addr_reg->reg_type.bitfield.dword + && i.op[1].regs->reg_type.bitfield.qword) + i.tm.opcode_modifier.size = SIZE32; + + i.op[0].regs = addr_reg; + i.reg_operands = 2; + } + + i.mem_operands = 0; + i.disp_operands = 0; + i.prefix[ADDR_PREFIX] = 0; + i.prefix[SEG_PREFIX] = 0; + i.seg[0] = NULL; + } + if (optimize_for_space && i.tm.opcode_modifier.opcodespace == SPACE_BASE && i.reg_operands == 1 diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp index a9a2a6403bb..00866458726 100644 --- a/gas/testsuite/gas/i386/i386.exp +++ b/gas/testsuite/gas/i386/i386.exp @@ -538,6 +538,7 @@ if [gas_32_check] then { run_dump_test "optimize-6b" run_list_test "optimize-7" "-I${srcdir}/$subdir -march=+noavx2 -al" run_dump_test "lea-optimize" + run_dump_test "lea16-optimize" run_dump_test "align-branch-1a" run_dump_test "align-branch-1b" run_dump_test "align-branch-1c" @@ -1194,6 +1195,8 @@ if [gas_64_check] then { run_dump_test "x86-64-align-branch-2a" run_dump_test "x86-64-align-branch-2b" run_dump_test "x86-64-align-branch-2c" + run_dump_test "lea64" + run_dump_test "lea64-optimize" } run_dump_test "x86-64-align-branch-4a" run_dump_test "x86-64-align-branch-4b" diff --git a/gas/testsuite/gas/i386/lea-optimize.d b/gas/testsuite/gas/i386/lea-optimize.d index 16e5b82daea..283b994bbfc 100644 --- a/gas/testsuite/gas/i386/lea-optimize.d +++ b/gas/testsuite/gas/i386/lea-optimize.d @@ -1,6 +1,6 @@ #as: -O -q #objdump: -dw -#name: i386 LEA-like segment overrride dropping +#name: i386 LEA optimizations #source: lea.s .*: +file format .* @@ -8,6 +8,41 @@ Disassembly of section .text: 0+ : -[ ]*[0-9a-f]+:[ ]+8d 00[ ]+lea[ ]+\(%eax\),%eax -[ ]*[0-9a-f]+:[ ]+8d 00[ ]+lea[ ]+\(%eax\),%eax +[ ]*[0-9a-f]+:[ ]+8d 04 08[ ]+lea[ ]+\(%eax,%ecx(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+8d 04 08[ ]+lea[ ]+\(%eax,%ecx(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+8d 48 01[ ]+lea[ ]+0x1\(%eax\),%ecx +[ ]*[0-9a-f]+:[ ]+8d 88 00 00 00 00[ ]+lea[ ]+0x0\(%eax\),%ecx +[ ]*[0-9a-f]+:[ ]+8d 0c 25 00 00 00 00[ ]+lea[ ]+0x0\(,(%eiz)?(,1)?\),%ecx +[ ]*[0-9a-f]+:[ ]+8d 04 00[ ]+lea[ ]+\(%eax,%eax(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+8d 04 45 00 00 00 00[ ]+lea[ ]+0x0\(,%eax,2\),%eax +[ ]*[0-9a-f]+:[ ]+8d 04 25 00 00 00 00[ ]+lea[ ]+0x0\(,(%eiz)?(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+67 8d 00[ ]+lea[ ]+\(%bx,%si\),%eax +[ ]*[0-9a-f]+:[ ]+8b c0[ ]+mov[ ]+%eax,%eax +[ ]*[0-9a-f]+:[ ]+8b c8[ ]+mov[ ]+%eax,%ecx +[ ]*[0-9a-f]+:[ ]+8b c8[ ]+mov[ ]+%eax,%ecx +[ ]*[0-9a-f]+:[ ]+8b c8[ ]+mov[ ]+%eax,%ecx +[ ]*[0-9a-f]+:[ ]+0f b7 c6[ ]+movzwl[ ]+%si,%eax +[ ]*[0-9a-f]+:[ ]+0f b7 f6[ ]+movzwl[ ]+%si,%esi +[ ]*[0-9a-f]+:[ ]+0f b7 c6[ ]+movzwl[ ]+%si,%eax +[ ]*[0-9a-f]+:[ ]+66 8b c0[ ]+mov[ ]+%ax,%ax +[ ]*[0-9a-f]+:[ ]+66 8b c8[ ]+mov[ ]+%ax,%cx +[ ]*[0-9a-f]+:[ ]+66 8b c8[ ]+mov[ ]+%ax,%cx +[ ]*[0-9a-f]+:[ ]+66 8b c6[ ]+mov[ ]+%si,%ax +[ ]*[0-9a-f]+:[ ]+66 8b f6[ ]+mov[ ]+%si,%si +[ ]*[0-9a-f]+:[ ]+8b c9[ ]+mov[ ]+%ecx,%ecx +[ ]*[0-9a-f]+:[ ]+8b c1[ ]+mov[ ]+%ecx,%eax +[ ]*[0-9a-f]+:[ ]+b8 01 00 00 00[ ]+mov[ ]+\$0x1,%eax +[ ]*[0-9a-f]+:[ ]+66 b8 02 00[ ]+mov[ ]+\$0x2,%ax +[ ]*[0-9a-f]+:[ ]+b8 ff ff ff ff[ ]+mov[ ]+\$0xffffffff,%eax +[ ]*[0-9a-f]+:[ ]+66 b8 fe ff[ ]+mov[ ]+\$0xfffe,%ax +[ ]*[0-9a-f]+:[ ]+b8 01 00 00 00[ ]+mov[ ]+\$0x1,%eax +[ ]*[0-9a-f]+:[ ]+66 b8 02 00[ ]+mov[ ]+\$0x2,%ax +[ ]*[0-9a-f]+:[ ]+b8 ff ff 00 00[ ]+mov[ ]+\$0xffff,%eax +[ ]*[0-9a-f]+:[ ]+66 b8 fe ff[ ]+mov[ ]+\$0xfffe,%ax +[ ]*[0-9a-f]+:[ ]+b8 00 00 00 00[ ]+mov[ ]+\$0x0,%eax +[ ]*[0-9a-f]+:[ ]+66 8d 05 00 00 00 00[ ]+lea[ ]+0x0,%ax +[ ]*[0-9a-f]+:[ ]+67 8d 06 00 00[ ]+lea[ ]+0x0,%eax +[ ]*[0-9a-f]+:[ ]+66 b8 00 00[ ]+mov[ ]+\$0x0,%ax +[ ]*[0-9a-f]+:[ ]+b8 00 00 00 00[ ]+mov[ ]+\$0x0,%eax +[ ]*[0-9a-f]+:[ ]+66 b8 00 00[ ]+mov[ ]+\$0x0,%ax #pass diff --git a/gas/testsuite/gas/i386/lea.d b/gas/testsuite/gas/i386/lea.d index aa0414b912a..bfc9c13559a 100644 --- a/gas/testsuite/gas/i386/lea.d +++ b/gas/testsuite/gas/i386/lea.d @@ -7,6 +7,41 @@ Disassembly of section .text: 0+ : -[ ]*[0-9a-f]+:[ ]+36 8d 00[ ]+lea[ ]+%ss:\(%eax\),%eax -[ ]*[0-9a-f]+:[ ]+36 8d 00[ ]+lea[ ]+%ss:\(%eax\),%eax +[ ]*[0-9a-f]+:[ ]+36 8d 04 08[ ]+lea[ ]+%ss:\(%eax,%ecx(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+36 8d 04 08[ ]+lea[ ]+%ss:\(%eax,%ecx(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+8d 48 01[ ]+lea[ ]+0x1\(%eax\),%ecx +[ ]*[0-9a-f]+:[ ]+8d 88 00 00 00 00[ ]+lea[ ]+0x0\(%eax\),%ecx +[ ]*[0-9a-f]+:[ ]+8d 0c 25 00 00 00 00[ ]+lea[ ]+0x0\(,(%eiz)?(,1)?\),%ecx +[ ]*[0-9a-f]+:[ ]+8d 04 00[ ]+lea[ ]+\(%eax,%eax(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+8d 04 45 00 00 00 00[ ]+lea[ ]+0x0\(,%eax,2\),%eax +[ ]*[0-9a-f]+:[ ]+8d 04 25 00 00 00 00[ ]+lea[ ]+0x0\(,(%eiz)?(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+67 8d 00[ ]+lea[ ]+\(%bx,%si\),%eax +[ ]*[0-9a-f]+:[ ]+8d 00[ ]+lea[ ]+\(%eax\),%eax +[ ]*[0-9a-f]+:[ ]+8d 08[ ]+lea[ ]+\(%eax\),%ecx +[ ]*[0-9a-f]+:[ ]+8d 08[ ]+lea[ ]+\(%eax\),%ecx +[ ]*[0-9a-f]+:[ ]+65 8d 08[ ]+lea[ ]+%gs:\(%eax\),%ecx +[ ]*[0-9a-f]+:[ ]+67 8d 04[ ]+lea[ ]+\(%si\),%eax +[ ]*[0-9a-f]+:[ ]+67 8d 34[ ]+lea[ ]+\(%si\),%esi +[ ]*[0-9a-f]+:[ ]+67 8d 04[ ]+lea[ ]+\(%si\),%eax +[ ]*[0-9a-f]+:[ ]+66 8d 00[ ]+lea[ ]+\(%eax\),%ax +[ ]*[0-9a-f]+:[ ]+66 8d 08[ ]+lea[ ]+\(%eax\),%cx +[ ]*[0-9a-f]+:[ ]+66 8d 08[ ]+lea[ ]+\(%eax\),%cx +[ ]*[0-9a-f]+:[ ]+67 66 8d 04[ ]+lea[ ]+\(%si\),%ax +[ ]*[0-9a-f]+:[ ]+67 66 8d 34[ ]+lea[ ]+\(%si\),%si +[ ]*[0-9a-f]+:[ ]+8d 0c 0d 00 00 00 00[ ]+lea[ ]+0x0\(,%ecx(,1)?\),%ecx +[ ]*[0-9a-f]+:[ ]+8d 04 0d 00 00 00 00[ ]+lea[ ]+0x0\(,%ecx(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+8d 05 01 00 00 00[ ]+lea[ ]+0x1,%eax +[ ]*[0-9a-f]+:[ ]+66 8d 05 02 00 00 00[ ]+lea[ ]+0x2,%ax +[ ]*[0-9a-f]+:[ ]+8d 05 ff ff ff ff[ ]+lea[ ]+0xffffffff,%eax +[ ]*[0-9a-f]+:[ ]+66 8d 05 fe ff ff ff[ ]+lea[ ]+0xfffffffe,%ax +[ ]*[0-9a-f]+:[ ]+67 8d 06 01 00[ ]+lea[ ]+0x1,%eax +[ ]*[0-9a-f]+:[ ]+67 66 8d 06 02 00[ ]+lea[ ]+0x2,%ax +[ ]*[0-9a-f]+:[ ]+67 8d 06 ff ff[ ]+lea[ ]+-0x1,%eax +[ ]*[0-9a-f]+:[ ]+67 66 8d 06 fe ff[ ]+lea[ ]+-0x2,%ax +[ ]*[0-9a-f]+:[ ]+8d 05 00 00 00 00[ ]+lea[ ]+0x0,%eax +[ ]*[0-9a-f]+:[ ]+66 8d 05 00 00 00 00[ ]+lea[ ]+0x0,%ax +[ ]*[0-9a-f]+:[ ]+67 8d 06 00 00[ ]+lea[ ]+0x0,%eax +[ ]*[0-9a-f]+:[ ]+67 66 8d 06 00 00[ ]+lea[ ]+0x0,%ax +[ ]*[0-9a-f]+:[ ]+8d 05 00 00 00 00[ ]+lea[ ]+0x0,%eax +[ ]*[0-9a-f]+:[ ]+66 8d 05 00 00 00 00[ ]+lea[ ]+0x0,%ax #pass diff --git a/gas/testsuite/gas/i386/lea.e b/gas/testsuite/gas/i386/lea.e index be965b39ee9..d0d47aeb3eb 100644 --- a/gas/testsuite/gas/i386/lea.e +++ b/gas/testsuite/gas/i386/lea.e @@ -1,3 +1,4 @@ .*: Assembler messages: .*:3: Warning: .* `lea' .* .*:4: Warning: .* `lea' .* +.*:19: Warning: .* `lea' .* diff --git a/gas/testsuite/gas/i386/lea.s b/gas/testsuite/gas/i386/lea.s index 4324ad0c6cc..1fb6aa85003 100644 --- a/gas/testsuite/gas/i386/lea.s +++ b/gas/testsuite/gas/i386/lea.s @@ -1,4 +1,54 @@ .text start: - lea %ss:(%eax), %eax - ss lea (%eax), %eax + lea %ss:(%eax,%ecx), %eax + ss lea (%eax,%ecx), %eax + + .allow_index_reg + lea 1(%eax), %ecx + lea sym(%eax), %ecx + lea sym(,%eiz), %ecx + + lea (%eax,%eax), %eax + lea (,%eax,2), %eax + lea (,%eiz), %eax + lea (%bx,%si), %eax + + lea (%eax), %eax + lea (%eax), %ecx + lea 1-1(%eax), %ecx + lea %gs:(%eax), %ecx + + lea (%si), %eax + lea (%si), %esi + leal (%si), %eax + + lea (%eax), %ax + lea (%eax), %cx + leaw (%eax), %cx + + lea (%si), %ax + lea (%si), %si + + lea (,%ecx,1), %ecx + lea (,%ecx,1), %eax + + lea 1, %eax + lea 2, %ax + + lea -1, %eax + lea -2, %ax + + addr16 lea 1, %eax + addr16 lea 2, %ax + + addr16 lea -1, %eax + addr16 lea -2, %ax + + lea sym, %eax + lea sym, %ax + + addr16 lea sym, %eax + addr16 lea sym, %ax + + lea (,1), %eax + lea (,1), %ax diff --git a/gas/testsuite/gas/i386/lea16-optimize.d b/gas/testsuite/gas/i386/lea16-optimize.d new file mode 100644 index 00000000000..e45b7377207 --- /dev/null +++ b/gas/testsuite/gas/i386/lea16-optimize.d @@ -0,0 +1,48 @@ +#as: -O -q -I${srcdir}/$subdir +#objdump: -dw -Mi8086 +#name: i386 16-bit LEA optimizations +#source: lea16.s + +.*: +file format .* + +Disassembly of section .text: + +0+ : +[ ]*[0-9a-f]+:[ ]+67 66 8d 04 08[ ]+lea[ ]+\(%eax,%ecx(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+67 66 8d 04 08[ ]+lea[ ]+\(%eax,%ecx(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+67 66 8d 48 01[ ]+lea[ ]+0x1\(%eax\),%ecx +[ ]*[0-9a-f]+:[ ]+67 66 8d 88 00 00 00 00[ ]+lea[ ]+0x0\(%eax\),%ecx +[ ]*[0-9a-f]+:[ ]+67 66 8d 0c 25 00 00 00 00[ ]+addr32 lea[ ]+0x0,%ecx +[ ]*[0-9a-f]+:[ ]+67 66 8d 04 00[ ]+lea[ ]+\(%eax,%eax(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+67 66 8d 04 45 00 00 00 00[ ]+lea[ ]+0x0\(,%eax,2\),%eax +[ ]*[0-9a-f]+:[ ]+67 66 8d 04 25 00 00 00 00[ ]+addr32 lea[ ]+0x0,%eax +[ ]*[0-9a-f]+:[ ]+66 8d 00[ ]+lea[ ]+\(%bx,%si\),%eax +[ ]*[0-9a-f]+:[ ]+66 8b c0[ ]+mov[ ]+%eax,%eax +[ ]*[0-9a-f]+:[ ]+66 8b c8[ ]+mov[ ]+%eax,%ecx +[ ]*[0-9a-f]+:[ ]+66 8b c8[ ]+mov[ ]+%eax,%ecx +[ ]*[0-9a-f]+:[ ]+66 8b c8[ ]+mov[ ]+%eax,%ecx +[ ]*[0-9a-f]+:[ ]+66 8d 04[ ]+lea[ ]+\(%si\),%eax +[ ]*[0-9a-f]+:[ ]+66 8d 34[ ]+lea[ ]+\(%si\),%esi +[ ]*[0-9a-f]+:[ ]+66 8d 04[ ]+lea[ ]+\(%si\),%eax +[ ]*[0-9a-f]+:[ ]+8b c0[ ]+mov[ ]+%ax,%ax +[ ]*[0-9a-f]+:[ ]+8b c8[ ]+mov[ ]+%ax,%cx +[ ]*[0-9a-f]+:[ ]+8b c8[ ]+mov[ ]+%ax,%cx +[ ]*[0-9a-f]+:[ ]+8b c6[ ]+mov[ ]+%si,%ax +[ ]*[0-9a-f]+:[ ]+8b f6[ ]+mov[ ]+%si,%si +[ ]*[0-9a-f]+:[ ]+66 8b c9[ ]+mov[ ]+%ecx,%ecx +[ ]*[0-9a-f]+:[ ]+66 8b c1[ ]+mov[ ]+%ecx,%eax +[ ]*[0-9a-f]+:[ ]+66 b8 01 00 00 00[ ]+mov[ ]+\$0x1,%eax +[ ]*[0-9a-f]+:[ ]+b8 02 00[ ]+mov[ ]+\$0x2,%ax +[ ]*[0-9a-f]+:[ ]+66 b8 ff ff 00 00[ ]+mov[ ]+\$0xffff,%eax +[ ]*[0-9a-f]+:[ ]+b8 fe ff[ ]+mov[ ]+\$0xfffe,%ax +[ ]*[0-9a-f]+:[ ]+66 b8 01 00 00 00[ ]+mov[ ]+\$0x1,%eax +[ ]*[0-9a-f]+:[ ]+b8 02 00[ ]+mov[ ]+\$0x2,%ax +[ ]*[0-9a-f]+:[ ]+66 b8 ff ff ff ff[ ]+mov[ ]+\$0xffffffff,%eax +[ ]*[0-9a-f]+:[ ]+b8 fe ff[ ]+mov[ ]+\$0xfffe,%ax +[ ]*[0-9a-f]+:[ ]+66 8d 06 00 00[ ]+lea[ ]+0x0,%eax +[ ]*[0-9a-f]+:[ ]+b8 00 00[ ]+mov[ ]+\$0x0,%ax +[ ]*[0-9a-f]+:[ ]+66 b8 00 00 00 00[ ]+mov[ ]+\$0x0,%eax +[ ]*[0-9a-f]+:[ ]+67 8d 05 00 00 00 00[ ]+addr32 lea[ ]+0x0,%ax +[ ]*[0-9a-f]+:[ ]+66 b8 00 00 00 00[ ]+mov[ ]+\$0x0,%eax +[ ]*[0-9a-f]+:[ ]+b8 00 00[ ]+mov[ ]+\$0x0,%ax +#pass diff --git a/gas/testsuite/gas/i386/lea16.s b/gas/testsuite/gas/i386/lea16.s new file mode 100644 index 00000000000..024a4e9c457 --- /dev/null +++ b/gas/testsuite/gas/i386/lea16.s @@ -0,0 +1,7 @@ + .code16 + + .macro addr16 mnem:req opnds:vararg + addr32 \mnem \opnds + .endm + + .include "lea.s" diff --git a/gas/testsuite/gas/i386/lea64-optimize.d b/gas/testsuite/gas/i386/lea64-optimize.d new file mode 100644 index 00000000000..301805a53e6 --- /dev/null +++ b/gas/testsuite/gas/i386/lea64-optimize.d @@ -0,0 +1,71 @@ +#as: -O -q +#objdump: -drw +#name: x86-64 LEA optimizations +#source: lea64.s + +.*: +file format .* + +Disassembly of section .text: + +0+ : +[ ]*[0-9a-f]+:[ ]+8d 04 08[ ]+lea[ ]+\(%rax,%rcx(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+8d 04 08[ ]+lea[ ]+\(%rax,%rcx(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+8d 48 01[ ]+lea[ ]+0x1\(%rax\),%ecx +[ ]*[0-9a-f]+:[ ]+8d 88 00 00 00 00[ ]+lea[ ]+0x0\(%rax\),%ecx[ ]+[0-9a-f]+: R_X86_64_32[ ]+sym +[ ]*[0-9a-f]+:[ ]+8d 0c 25 00 00 00 00[ ]+lea[ ]+0x0,%ecx[ ]+[0-9a-f]+: R_X86_64_32[ ]+sym +[ ]*[0-9a-f]+:[ ]+8d 04 00[ ]+lea[ ]+\(%rax,%rax(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+8d 04 45 00 00 00 00[ ]+lea[ ]+0x0\(,%rax,2\),%eax +[ ]*[0-9a-f]+:[ ]+8d 05 00 00 00 00[ ]+lea[ ]+0x0\(%rip\),%eax($| *#.*) +[ ]*[0-9a-f]+:[ ]+8d 04 25 00 00 00 00[ ]+lea[ ]+0x0,%eax +[ ]*[0-9a-f]+:[ ]+48 8b c0[ ]+mov[ ]+%rax,%rax +[ ]*[0-9a-f]+:[ ]+48 8b c8[ ]+mov[ ]+%rax,%rcx +[ ]*[0-9a-f]+:[ ]+48 8b c8[ ]+mov[ ]+%rax,%rcx +[ ]*[0-9a-f]+:[ ]+48 8b c8[ ]+mov[ ]+%rax,%rcx +[ ]*[0-9a-f]+:[ ]+8b c6[ ]+mov[ ]+%esi,%eax +[ ]*[0-9a-f]+:[ ]+8b f6[ ]+mov[ ]+%esi,%esi +[ ]*[0-9a-f]+:[ ]+8b c6[ ]+mov[ ]+%esi,%eax +[ ]*[0-9a-f]+:[ ]+66 8b c6[ ]+mov[ ]+%si,%ax +[ ]*[0-9a-f]+:[ ]+66 8b f6[ ]+mov[ ]+%si,%si +[ ]*[0-9a-f]+:[ ]+66 8b c6[ ]+mov[ ]+%si,%ax +[ ]*[0-9a-f]+:[ ]+8b c0[ ]+mov[ ]+%eax,%eax +[ ]*[0-9a-f]+:[ ]+8b c8[ ]+mov[ ]+%eax,%ecx +[ ]*[0-9a-f]+:[ ]+8b c8[ ]+mov[ ]+%eax,%ecx +[ ]*[0-9a-f]+:[ ]+8b c0[ ]+mov[ ]+%eax,%eax +[ ]*[0-9a-f]+:[ ]+8b c8[ ]+mov[ ]+%eax,%ecx +[ ]*[0-9a-f]+:[ ]+66 8b c6[ ]+mov[ ]+%si,%ax +[ ]*[0-9a-f]+:[ ]+66 8b f6[ ]+mov[ ]+%si,%si +[ ]*[0-9a-f]+:[ ]+66 8b c6[ ]+mov[ ]+%si,%ax +[ ]*[0-9a-f]+:[ ]+48 8b c9[ ]+mov[ ]+%rcx,%rcx +[ ]*[0-9a-f]+:[ ]+48 8b c1[ ]+mov[ ]+%rcx,%rax +[ ]*[0-9a-f]+:[ ]+8b c9[ ]+mov[ ]+%ecx,%ecx +[ ]*[0-9a-f]+:[ ]+8b c1[ ]+mov[ ]+%ecx,%eax +[ ]*[0-9a-f]+:[ ]+66 8b c9[ ]+mov[ ]+%cx,%cx +[ ]*[0-9a-f]+:[ ]+66 8b c1[ ]+mov[ ]+%cx,%ax +[ ]*[0-9a-f]+:[ ]+8b c9[ ]+mov[ ]+%ecx,%ecx +[ ]*[0-9a-f]+:[ ]+8b c1[ ]+mov[ ]+%ecx,%eax +[ ]*[0-9a-f]+:[ ]+8b c9[ ]+mov[ ]+%ecx,%ecx +[ ]*[0-9a-f]+:[ ]+8b c1[ ]+mov[ ]+%ecx,%eax +[ ]*[0-9a-f]+:[ ]+66 8b c9[ ]+mov[ ]+%cx,%cx +[ ]*[0-9a-f]+:[ ]+66 8b c1[ ]+mov[ ]+%cx,%ax +[ ]*[0-9a-f]+:[ ]+b8 01 00 00 00[ ]+mov[ ]+\$0x1,%eax +[ ]*[0-9a-f]+:[ ]+b8 02 00 00 00[ ]+mov[ ]+\$0x2,%eax +[ ]*[0-9a-f]+:[ ]+66 b8 03 00[ ]+mov[ ]+\$0x3,%ax +[ ]*[0-9a-f]+:[ ]+48 c7 c0 ff ff ff ff[ ]+mov[ ]+\$0xffffffffffffffff,%rax +[ ]*[0-9a-f]+:[ ]+b8 fe ff ff ff[ ]+mov[ ]+\$0xfffffffe,%eax +[ ]*[0-9a-f]+:[ ]+66 b8 fd ff[ ]+mov[ ]+\$0xfffd,%ax +[ ]*[0-9a-f]+:[ ]+b8 01 00 00 00[ ]+mov[ ]+\$0x1,%eax +[ ]*[0-9a-f]+:[ ]+b8 02 00 00 00[ ]+mov[ ]+\$0x2,%eax +[ ]*[0-9a-f]+:[ ]+66 b8 03 00[ ]+mov[ ]+\$0x3,%ax +[ ]*[0-9a-f]+:[ ]+b8 ff ff ff ff[ ]+mov[ ]+\$0xffffffff,%eax +[ ]*[0-9a-f]+:[ ]+b8 fe ff ff ff[ ]+mov[ ]+\$0xfffffffe,%eax +[ ]*[0-9a-f]+:[ ]+66 b8 fd ff[ ]+mov[ ]+\$0xfffd,%ax +[ ]*[0-9a-f]+:[ ]+48 c7 c0 00 00 00 00[ ]+mov[ ]+\$0x0,%rax[ ]+[0-9a-f]+: R_X86_64_32S[ ]+sym +[ ]*[0-9a-f]+:[ ]+b8 00 00 00 00[ ]+mov[ ]+\$0x0,%eax[ ]+[0-9a-f]+: R_X86_64_32[ ]+sym +[ ]*[0-9a-f]+:[ ]+66 8d 04 25 00 00 00 00[ ]+lea[ ]+0x0,%ax[ ]+[0-9a-f]+: R_X86_64_32[ ]+sym +[ ]*[0-9a-f]+:[ ]+b8 00 00 00 00[ ]+mov[ ]+\$0x0,%eax[ ]+[0-9a-f]+: R_X86_64_32[ ]+sym +[ ]*[0-9a-f]+:[ ]+b8 00 00 00 00[ ]+mov[ ]+\$0x0,%eax[ ]+[0-9a-f]+: R_X86_64_32[ ]+sym +[ ]*[0-9a-f]+:[ ]+66 8d 04 25 00 00 00 00[ ]+lea[ ]+0x0,%ax[ ]+[0-9a-f]+: R_X86_64_32[ ]+sym +[ ]*[0-9a-f]+:[ ]+48 c7 c0 00 00 00 00[ ]+mov[ ]+\$0x0,%rax +[ ]*[0-9a-f]+:[ ]+b8 00 00 00 00[ ]+mov[ ]+\$0x0,%eax +[ ]*[0-9a-f]+:[ ]+66 b8 00 00[ ]+mov[ ]+\$0x0,%ax +#pass diff --git a/gas/testsuite/gas/i386/lea64.d b/gas/testsuite/gas/i386/lea64.d new file mode 100644 index 00000000000..80136ffe6e3 --- /dev/null +++ b/gas/testsuite/gas/i386/lea64.d @@ -0,0 +1,70 @@ +#objdump: -drw +#name: x86-64 LEA +#warning_output: lea64.e + +.*: +file format .* + +Disassembly of section .text: + +0+ : +[ ]*[0-9a-f]+:[ ]+64 8d 04 08[ ]+lea[ ]+%fs:\(%rax,%rcx(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+65 8d 04 08[ ]+lea[ ]+%gs:\(%rax,%rcx(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+8d 48 01[ ]+lea[ ]+0x1\(%rax\),%ecx +[ ]*[0-9a-f]+:[ ]+8d 88 00 00 00 00[ ]+lea[ ]+0x0\(%rax\),%ecx[ ]+[0-9a-f]+: R_X86_64_32[ ]+sym +[ ]*[0-9a-f]+:[ ]+8d 0c 25 00 00 00 00[ ]+lea[ ]+0x0,%ecx[ ]+[0-9a-f]+: R_X86_64_32[ ]+sym +[ ]*[0-9a-f]+:[ ]+8d 04 00[ ]+lea[ ]+\(%rax,%rax(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+8d 04 45 00 00 00 00[ ]+lea[ ]+0x0\(,%rax,2\),%eax +[ ]*[0-9a-f]+:[ ]+8d 05 00 00 00 00[ ]+lea[ ]+0x0\(%rip\),%eax($| *#.*) +[ ]*[0-9a-f]+:[ ]+8d 04 25 00 00 00 00[ ]+lea[ ]+0x0,%eax +[ ]*[0-9a-f]+:[ ]+48 8d 00[ ]+lea[ ]+\(%rax\),%rax +[ ]*[0-9a-f]+:[ ]+48 8d 08[ ]+lea[ ]+\(%rax\),%rcx +[ ]*[0-9a-f]+:[ ]+48 8d 08[ ]+lea[ ]+\(%rax\),%rcx +[ ]*[0-9a-f]+:[ ]+65 48 8d 08[ ]+lea[ ]+%gs:\(%rax\),%rcx +[ ]*[0-9a-f]+:[ ]+8d 06[ ]+lea[ ]+\(%rsi\),%eax +[ ]*[0-9a-f]+:[ ]+8d 36[ ]+lea[ ]+\(%rsi\),%esi +[ ]*[0-9a-f]+:[ ]+8d 06[ ]+lea[ ]+\(%rsi\),%eax +[ ]*[0-9a-f]+:[ ]+66 8d 06[ ]+lea[ ]+\(%rsi\),%ax +[ ]*[0-9a-f]+:[ ]+66 8d 36[ ]+lea[ ]+\(%rsi\),%si +[ ]*[0-9a-f]+:[ ]+66 8d 06[ ]+lea[ ]+\(%rsi\),%ax +[ ]*[0-9a-f]+:[ ]+67 48 8d 00[ ]+lea[ ]+\(%eax\),%rax +[ ]*[0-9a-f]+:[ ]+67 48 8d 08[ ]+lea[ ]+\(%eax\),%rcx +[ ]*[0-9a-f]+:[ ]+67 48 8d 08[ ]+lea[ ]+\(%eax\),%rcx +[ ]*[0-9a-f]+:[ ]+67 8d 00[ ]+lea[ ]+\(%eax\),%eax +[ ]*[0-9a-f]+:[ ]+67 8d 08[ ]+lea[ ]+\(%eax\),%ecx +[ ]*[0-9a-f]+:[ ]+67 66 8d 06[ ]+lea[ ]+\(%esi\),%ax +[ ]*[0-9a-f]+:[ ]+67 66 8d 36[ ]+lea[ ]+\(%esi\),%si +[ ]*[0-9a-f]+:[ ]+67 66 8d 06[ ]+lea[ ]+\(%esi\),%ax +[ ]*[0-9a-f]+:[ ]+48 8d 0c 0d 00 00 00 00[ ]+lea[ ]+0x0\(,%rcx(,1)?\),%rcx +[ ]*[0-9a-f]+:[ ]+48 8d 04 0d 00 00 00 00[ ]+lea[ ]+0x0\(,%rcx(,1)?\),%rax +[ ]*[0-9a-f]+:[ ]+8d 0c 0d 00 00 00 00[ ]+lea[ ]+0x0\(,%rcx(,1)?\),%ecx +[ ]*[0-9a-f]+:[ ]+8d 04 0d 00 00 00 00[ ]+lea[ ]+0x0\(,%rcx(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+66 8d 0c 0d 00 00 00 00[ ]+lea[ ]+0x0\(,%rcx(,1)?\),%cx +[ ]*[0-9a-f]+:[ ]+66 8d 04 0d 00 00 00 00[ ]+lea[ ]+0x0\(,%rcx(,1)?\),%ax +[ ]*[0-9a-f]+:[ ]+67 48 8d 0c 0d 00 00 00 00[ ]+lea[ ]+0x0\(,%ecx(,1)?\),%rcx +[ ]*[0-9a-f]+:[ ]+67 48 8d 04 0d 00 00 00 00[ ]+lea[ ]+0x0\(,%ecx(,1)?\),%rax +[ ]*[0-9a-f]+:[ ]+67 8d 0c 0d 00 00 00 00[ ]+lea[ ]+0x0\(,%ecx(,1)?\),%ecx +[ ]*[0-9a-f]+:[ ]+67 8d 04 0d 00 00 00 00[ ]+lea[ ]+0x0\(,%ecx(,1)?\),%eax +[ ]*[0-9a-f]+:[ ]+67 66 8d 0c 0d 00 00 00 00[ ]+lea[ ]+0x0\(,%ecx(,1)?\),%cx +[ ]*[0-9a-f]+:[ ]+67 66 8d 04 0d 00 00 00 00[ ]+lea[ ]+0x0\(,%ecx(,1)?\),%ax +[ ]*[0-9a-f]+:[ ]+48 8d 04 25 01 00 00 00[ ]+lea[ ]+0x1,%rax +[ ]*[0-9a-f]+:[ ]+8d 04 25 02 00 00 00[ ]+lea[ ]+0x2,%eax +[ ]*[0-9a-f]+:[ ]+66 8d 04 25 03 00 00 00[ ]+lea[ ]+0x3,%ax +[ ]*[0-9a-f]+:[ ]+48 8d 04 25 ff ff ff ff[ ]+lea[ ]+0xffffffffffffffff,%rax +[ ]*[0-9a-f]+:[ ]+8d 04 25 fe ff ff ff[ ]+lea[ ]+0xfffffffffffffffe,%eax +[ ]*[0-9a-f]+:[ ]+66 8d 04 25 fd ff ff ff[ ]+lea[ ]+0xfffffffffffffffd,%ax +[ ]*[0-9a-f]+:[ ]+67 48 8d 04 25 01 00 00 00[ ]+lea[ ]+0x1\(,%eiz,1\),%rax +[ ]*[0-9a-f]+:[ ]+67 8d 04 25 02 00 00 00[ ]+lea[ ]+0x2\(,%eiz,1\),%eax +[ ]*[0-9a-f]+:[ ]+67 66 8d 04 25 03 00 00 00[ ]+lea[ ]+0x3\(,%eiz,1\),%ax +[ ]*[0-9a-f]+:[ ]+67 48 8d 04 25 ff ff ff ff[ ]+lea[ ]+0xffffffff\(,%eiz,1\),%rax +[ ]*[0-9a-f]+:[ ]+67 8d 04 25 fe ff ff ff[ ]+lea[ ]+0xfffffffe\(,%eiz,1\),%eax +[ ]*[0-9a-f]+:[ ]+67 66 8d 04 25 fd ff ff ff[ ]+lea[ ]+0xfffffffd\(,%eiz,1\),%ax +[ ]*[0-9a-f]+:[ ]+48 8d 04 25 00 00 00 00[ ]+lea[ ]+0x0,%rax[ ]+[0-9a-f]+: R_X86_64_32S[ ]+sym +[ ]*[0-9a-f]+:[ ]+8d 04 25 00 00 00 00[ ]+lea[ ]+0x0,%eax[ ]+[0-9a-f]+: R_X86_64_32[ ]+sym +[ ]*[0-9a-f]+:[ ]+66 8d 04 25 00 00 00 00[ ]+lea[ ]+0x0,%ax[ ]+[0-9a-f]+: R_X86_64_32[ ]+sym +[ ]*[0-9a-f]+:[ ]+67 48 8d 04 25 00 00 00 00[ ]+lea[ ]+0x0\(,%eiz,1\),%rax[ ]+[0-9a-f]+: R_X86_64_32[ ]+sym +[ ]*[0-9a-f]+:[ ]+67 8d 04 25 00 00 00 00[ ]+lea[ ]+0x0\(,%eiz,1\),%eax[ ]+[0-9a-f]+: R_X86_64_32[ ]+sym +[ ]*[0-9a-f]+:[ ]+67 66 8d 04 25 00 00 00 00[ ]+lea[ ]+0x0\(,%eiz,1\),%ax[ ]+[0-9a-f]+: R_X86_64_32[ ]+sym +[ ]*[0-9a-f]+:[ ]+48 8d 04 25 00 00 00 00[ ]+lea[ ]+0x0,%rax +[ ]*[0-9a-f]+:[ ]+8d 04 25 00 00 00 00[ ]+lea[ ]+0x0,%eax +[ ]*[0-9a-f]+:[ ]+66 8d 04 25 00 00 00 00[ ]+lea[ ]+0x0,%ax +#pass diff --git a/gas/testsuite/gas/i386/lea64.e b/gas/testsuite/gas/i386/lea64.e new file mode 100644 index 00000000000..d0d47aeb3eb --- /dev/null +++ b/gas/testsuite/gas/i386/lea64.e @@ -0,0 +1,4 @@ +.*: Assembler messages: +.*:3: Warning: .* `lea' .* +.*:4: Warning: .* `lea' .* +.*:19: Warning: .* `lea' .* diff --git a/gas/testsuite/gas/i386/lea64.s b/gas/testsuite/gas/i386/lea64.s new file mode 100644 index 00000000000..1778adc4851 --- /dev/null +++ b/gas/testsuite/gas/i386/lea64.s @@ -0,0 +1,84 @@ + .text +start: + lea %fs:(%rax,%rcx), %eax + gs lea (%rax,%rcx), %eax + + .allow_index_reg + lea 1(%rax), %ecx + lea sym(%rax), %ecx + lea sym(,%riz), %ecx + + lea (%rax,%rax), %eax + lea (,%rax,2), %eax + lea (%rip), %eax + lea (,%riz), %eax + + lea (%rax), %rax + lea (%rax), %rcx + lea 1-1(%rax), %rcx + lea %gs:(%rax), %rcx + + lea (%rsi), %eax + lea (%rsi), %esi + leal (%rsi), %eax + + lea (%rsi), %ax + lea (%rsi), %si + leaw (%rsi), %ax + + lea (%eax), %rax + lea (%eax), %rcx + leaq (%eax), %rcx + + lea (%eax), %eax + lea (%eax), %ecx + + lea (%esi), %ax + lea (%esi), %si + leaw (%esi), %ax + + lea (,%rcx,1), %rcx + lea (,%rcx,1), %rax + + lea (,%rcx,1), %ecx + lea (,%rcx,1), %eax + + lea (,%rcx,1), %cx + lea (,%rcx,1), %ax + + lea (,%ecx,1), %rcx + lea (,%ecx,1), %rax + + lea (,%ecx,1), %ecx + lea (,%ecx,1), %eax + + lea (,%ecx,1), %cx + lea (,%ecx,1), %ax + + lea 1, %rax + lea 2, %eax + lea 3, %ax + + lea -1, %rax + lea -2, %eax + lea -3, %ax + + addr32 lea 1, %rax + addr32 lea 2, %eax + addr32 lea 3, %ax + + addr32 lea -1, %rax + addr32 lea -2, %eax + addr32 lea -3, %ax + + lea sym, %rax + lea sym, %eax + lea sym, %ax + + addr32 lea sym, %rax + addr32 lea sym, %eax + addr32 lea sym, %ax + + lea (,1), %rax + lea (,1), %eax + lea (,1), %ax diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index bf495d02a07..f0840e34d9d 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,8 @@ +2021-04-26 Jan Beulich + + * i386-opc.tbl (lea): Add Optimize. + * opcodes/i386-tbl.h: Re-generate. + 2020-04-23 Max Filippov * xtensa-dis.c (print_xtensa_operand): For PC-relative operand diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl index 0c35848a22a..b0530e5fb82 100644 --- a/opcodes/i386-opc.tbl +++ b/opcodes/i386-opc.tbl @@ -228,7 +228,7 @@ out, 0xe6, None, 0, W|No_sSuf|No_qSuf|No_ldSuf, { Imm8 } out, 0xee, None, 0, W|No_sSuf|No_qSuf|No_ldSuf, { InOutPortReg } // Load effective address. -lea, 0x8d, None, 0, Modrm|Anysize|No_bSuf|No_sSuf|No_ldSuf, { BaseIndex, Reg16|Reg32|Reg64 } +lea, 0x8d, None, 0, Modrm|Anysize|No_bSuf|No_sSuf|No_ldSuf|Optimize, { BaseIndex, Reg16|Reg32|Reg64 } // Load segment registers from memory. lds, 0xc5, None, CpuNo64, Modrm|No_bSuf|No_sSuf|No_qSuf|No_ldSuf, { DWord|Fword|Unspecified|BaseIndex, Reg16|Reg32 } diff --git a/opcodes/i386-tbl.h b/opcodes/i386-tbl.h index d2ca247f028..df139ba6121 100644 --- a/opcodes/i386-tbl.h +++ b/opcodes/i386-tbl.h @@ -1121,7 +1121,7 @@ const insn_template i386_optab[] = { "lea", 0x8d, None, 2, { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,