14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/compiler/assembler/x64/assembler_x64.h" 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_cinamespace panda::ecmascript::x64 { 194514f5e3Sopenharmony_civoid AssemblerX64::Pushq(Register x) 204514f5e3Sopenharmony_ci{ 214514f5e3Sopenharmony_ci EmitRexPrefix(x); 224514f5e3Sopenharmony_ci // 0x50: Push r16 234514f5e3Sopenharmony_ci EmitU8(0x50 | LowBits(x)); 244514f5e3Sopenharmony_ci} 254514f5e3Sopenharmony_ci 264514f5e3Sopenharmony_civoid AssemblerX64::Pushq(Immediate x) 274514f5e3Sopenharmony_ci{ 284514f5e3Sopenharmony_ci if (InRange8(x.Value())) { 294514f5e3Sopenharmony_ci // 6A: Push imm8 304514f5e3Sopenharmony_ci EmitU8(0x6A); 314514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(x.Value())); 324514f5e3Sopenharmony_ci } else { 334514f5e3Sopenharmony_ci // 68: Push imm32 344514f5e3Sopenharmony_ci EmitU8(0x68); 354514f5e3Sopenharmony_ci EmitI32(x.Value()); 364514f5e3Sopenharmony_ci } 374514f5e3Sopenharmony_ci} 384514f5e3Sopenharmony_ci 394514f5e3Sopenharmony_civoid AssemblerX64::Push(Register x) 404514f5e3Sopenharmony_ci{ 414514f5e3Sopenharmony_ci Pushq(x); 424514f5e3Sopenharmony_ci} 434514f5e3Sopenharmony_ci 444514f5e3Sopenharmony_civoid AssemblerX64::Popq(Register x) 454514f5e3Sopenharmony_ci{ 464514f5e3Sopenharmony_ci EmitRexPrefix(x); 474514f5e3Sopenharmony_ci // 0x58: Pop r16 484514f5e3Sopenharmony_ci EmitU8(0x58 | LowBits(x)); 494514f5e3Sopenharmony_ci} 504514f5e3Sopenharmony_ci 514514f5e3Sopenharmony_civoid AssemblerX64::Pop(Register x) 524514f5e3Sopenharmony_ci{ 534514f5e3Sopenharmony_ci Popq(x); 544514f5e3Sopenharmony_ci} 554514f5e3Sopenharmony_ci 564514f5e3Sopenharmony_ci 574514f5e3Sopenharmony_civoid AssemblerX64::Addq(Immediate src, Register dst) 584514f5e3Sopenharmony_ci{ 594514f5e3Sopenharmony_ci EmitRexPrefixW(dst); 604514f5e3Sopenharmony_ci if (InRange8(src.Value())) { 614514f5e3Sopenharmony_ci // 83: Add r/m16, imm8 624514f5e3Sopenharmony_ci EmitU8(0x83); 634514f5e3Sopenharmony_ci // 0: 83 /0 ib 644514f5e3Sopenharmony_ci EmitModrm(0, dst); 654514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(src.Value())); 664514f5e3Sopenharmony_ci } else if (dst == rax) { 674514f5e3Sopenharmony_ci // 0x5: Add rax, imm32 684514f5e3Sopenharmony_ci EmitU8(0x5); 694514f5e3Sopenharmony_ci EmitI32(src.Value()); 704514f5e3Sopenharmony_ci } else { 714514f5e3Sopenharmony_ci // 81: Add r/m32, imm32 724514f5e3Sopenharmony_ci EmitU8(0x81); 734514f5e3Sopenharmony_ci // 0: 81 /0 id 744514f5e3Sopenharmony_ci EmitModrm(0, dst); 754514f5e3Sopenharmony_ci EmitI32(src.Value()); 764514f5e3Sopenharmony_ci } 774514f5e3Sopenharmony_ci} 784514f5e3Sopenharmony_ci 794514f5e3Sopenharmony_civoid AssemblerX64::Addq(Register src, Register dst) 804514f5e3Sopenharmony_ci{ 814514f5e3Sopenharmony_ci EmitRexPrefix(dst, src); 824514f5e3Sopenharmony_ci // 03 : add r64, r/m64 834514f5e3Sopenharmony_ci EmitU8(0x03); 844514f5e3Sopenharmony_ci EmitModrm(dst, src); 854514f5e3Sopenharmony_ci} 864514f5e3Sopenharmony_ci 874514f5e3Sopenharmony_civoid AssemblerX64::Addl(Immediate src, Register dst) 884514f5e3Sopenharmony_ci{ 894514f5e3Sopenharmony_ci EmitRexPrefix(dst); 904514f5e3Sopenharmony_ci if (InRange8(src.Value())) { 914514f5e3Sopenharmony_ci // 83: Add r/m16, imm8 924514f5e3Sopenharmony_ci EmitU8(0x83); 934514f5e3Sopenharmony_ci // 0: 83 /0 ib 944514f5e3Sopenharmony_ci EmitModrm(0, dst); 954514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(src.Value())); 964514f5e3Sopenharmony_ci } else if (dst == rax) { 974514f5e3Sopenharmony_ci // 0x5: Add rax, imm32 984514f5e3Sopenharmony_ci EmitU8(0x5); 994514f5e3Sopenharmony_ci EmitI32(src.Value()); 1004514f5e3Sopenharmony_ci } else { 1014514f5e3Sopenharmony_ci // 81: Add r/m32, imm32 1024514f5e3Sopenharmony_ci EmitU8(0x81); 1034514f5e3Sopenharmony_ci // 0: 81 /0 id 1044514f5e3Sopenharmony_ci EmitModrm(0, dst); 1054514f5e3Sopenharmony_ci EmitI32(src.Value()); 1064514f5e3Sopenharmony_ci } 1074514f5e3Sopenharmony_ci} 1084514f5e3Sopenharmony_ci 1094514f5e3Sopenharmony_civoid AssemblerX64::Subq(Immediate src, Register dst) 1104514f5e3Sopenharmony_ci{ 1114514f5e3Sopenharmony_ci EmitRexPrefixW(dst); 1124514f5e3Sopenharmony_ci if (InRange8(src.Value())) { 1134514f5e3Sopenharmony_ci // 83: Sub r/m16, imm8 1144514f5e3Sopenharmony_ci EmitU8(0x83); 1154514f5e3Sopenharmony_ci // 5: 83 /5 ib 1164514f5e3Sopenharmony_ci EmitModrm(5, dst); 1174514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(src.Value())); 1184514f5e3Sopenharmony_ci } else if (dst == rax) { 1194514f5e3Sopenharmony_ci // 0x2D: Sub rax, imm32 1204514f5e3Sopenharmony_ci EmitU8(0x2D); 1214514f5e3Sopenharmony_ci EmitI32(src.Value()); 1224514f5e3Sopenharmony_ci } else { 1234514f5e3Sopenharmony_ci // 81: sub r/m32, imm32 1244514f5e3Sopenharmony_ci EmitU8(0x81); 1254514f5e3Sopenharmony_ci // 5: 81 /5 id 1264514f5e3Sopenharmony_ci EmitModrm(5, dst); 1274514f5e3Sopenharmony_ci EmitI32(src.Value()); 1284514f5e3Sopenharmony_ci } 1294514f5e3Sopenharmony_ci} 1304514f5e3Sopenharmony_ci 1314514f5e3Sopenharmony_civoid AssemblerX64::Subq(Register src, Register dst) 1324514f5e3Sopenharmony_ci{ 1334514f5e3Sopenharmony_ci EmitRexPrefix(src, dst); 1344514f5e3Sopenharmony_ci // 29: sub r/m64, r64 1354514f5e3Sopenharmony_ci EmitU8(0x29); 1364514f5e3Sopenharmony_ci EmitModrm(src, dst); 1374514f5e3Sopenharmony_ci} 1384514f5e3Sopenharmony_ci 1394514f5e3Sopenharmony_civoid AssemblerX64::Subl(Immediate src, Register dst) 1404514f5e3Sopenharmony_ci{ 1414514f5e3Sopenharmony_ci EmitRexPrefix(dst); 1424514f5e3Sopenharmony_ci if (InRange8(src.Value())) { 1434514f5e3Sopenharmony_ci // 83: Sub r/m16, imm8 1444514f5e3Sopenharmony_ci EmitU8(0x83); 1454514f5e3Sopenharmony_ci // 5: 83 /5 ib 1464514f5e3Sopenharmony_ci EmitModrm(5, dst); 1474514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(src.Value())); 1484514f5e3Sopenharmony_ci } else if (dst == rax) { 1494514f5e3Sopenharmony_ci // 0x2D: Sub eax, imm32 1504514f5e3Sopenharmony_ci EmitU8(0x2D); 1514514f5e3Sopenharmony_ci EmitI32(src.Value()); 1524514f5e3Sopenharmony_ci } else { 1534514f5e3Sopenharmony_ci // 81: sub r/m32, imm32 1544514f5e3Sopenharmony_ci EmitU8(0x81); 1554514f5e3Sopenharmony_ci // 5: 81 /5 id 1564514f5e3Sopenharmony_ci EmitModrm(5, dst); 1574514f5e3Sopenharmony_ci EmitI32(src.Value()); 1584514f5e3Sopenharmony_ci } 1594514f5e3Sopenharmony_ci} 1604514f5e3Sopenharmony_ci 1614514f5e3Sopenharmony_civoid AssemblerX64::Cmpq(Immediate src, Register dst) 1624514f5e3Sopenharmony_ci{ 1634514f5e3Sopenharmony_ci EmitRexPrefixW(dst); 1644514f5e3Sopenharmony_ci if (InRange8(src.Value())) { 1654514f5e3Sopenharmony_ci // 83: cmp r/m64, imm8 1664514f5e3Sopenharmony_ci EmitU8(0x83); 1674514f5e3Sopenharmony_ci // 7: 83 /7 ib 1684514f5e3Sopenharmony_ci EmitModrm(7, dst); 1694514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(src.Value())); 1704514f5e3Sopenharmony_ci } else if (dst == rax) { 1714514f5e3Sopenharmony_ci // 0x3D: cmp rax, imm32 1724514f5e3Sopenharmony_ci EmitU8(0x3D); 1734514f5e3Sopenharmony_ci EmitI32(src.Value()); 1744514f5e3Sopenharmony_ci } else { 1754514f5e3Sopenharmony_ci // 81: cmp r/m32, imm32 1764514f5e3Sopenharmony_ci EmitU8(0x81); 1774514f5e3Sopenharmony_ci // 7: 81 /7 id 1784514f5e3Sopenharmony_ci EmitModrm(7, dst); 1794514f5e3Sopenharmony_ci EmitI32(src.Value()); 1804514f5e3Sopenharmony_ci } 1814514f5e3Sopenharmony_ci} 1824514f5e3Sopenharmony_ci 1834514f5e3Sopenharmony_civoid AssemblerX64::Cmpb(Immediate src, Register dst) 1844514f5e3Sopenharmony_ci{ 1854514f5e3Sopenharmony_ci EmitRexPrefix(dst); 1864514f5e3Sopenharmony_ci if (InRange8(src.Value())) { 1874514f5e3Sopenharmony_ci // 80: cmp r/m8, imm8 1884514f5e3Sopenharmony_ci EmitU8(0x80); 1894514f5e3Sopenharmony_ci // 7: /7 ib 1904514f5e3Sopenharmony_ci EmitModrm(7, dst); 1914514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(src.Value())); 1924514f5e3Sopenharmony_ci } else if (dst == rax) { 1934514f5e3Sopenharmony_ci // 0x3C: cmp al, imm8 1944514f5e3Sopenharmony_ci EmitU8(0x3C); 1954514f5e3Sopenharmony_ci EmitI8(src.Value()); 1964514f5e3Sopenharmony_ci } else { 1974514f5e3Sopenharmony_ci LOG_ECMA(FATAL) << "this branch is unreachable"; 1984514f5e3Sopenharmony_ci UNREACHABLE(); 1994514f5e3Sopenharmony_ci } 2004514f5e3Sopenharmony_ci} 2014514f5e3Sopenharmony_ci 2024514f5e3Sopenharmony_civoid AssemblerX64::Cmpq(Register src, Register dst) 2034514f5e3Sopenharmony_ci{ 2044514f5e3Sopenharmony_ci EmitRexPrefix(src, dst); 2054514f5e3Sopenharmony_ci // 39: Cmp r/m64, r64 2064514f5e3Sopenharmony_ci EmitU8(0x39); 2074514f5e3Sopenharmony_ci EmitModrm(src, dst); 2084514f5e3Sopenharmony_ci} 2094514f5e3Sopenharmony_ci 2104514f5e3Sopenharmony_civoid AssemblerX64::Cmpl(Immediate src, Register dst) 2114514f5e3Sopenharmony_ci{ 2124514f5e3Sopenharmony_ci EmitRexPrefix(dst); 2134514f5e3Sopenharmony_ci if (InRange8(src.Value())) { 2144514f5e3Sopenharmony_ci // 83: cmp r/m32, imm8 2154514f5e3Sopenharmony_ci EmitU8(0x83); 2164514f5e3Sopenharmony_ci // 7: 83 /7 ib 2174514f5e3Sopenharmony_ci EmitModrm(7, dst); 2184514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(src.Value())); 2194514f5e3Sopenharmony_ci } else if (dst == rax) { 2204514f5e3Sopenharmony_ci // 0x3D: cmp rax, imm32 2214514f5e3Sopenharmony_ci EmitU8(0x3D); 2224514f5e3Sopenharmony_ci EmitI32(src.Value()); 2234514f5e3Sopenharmony_ci } else { 2244514f5e3Sopenharmony_ci // 81: cmp r/m32, imm32 2254514f5e3Sopenharmony_ci EmitU8(0x81); 2264514f5e3Sopenharmony_ci // 7: 81 /7 id 2274514f5e3Sopenharmony_ci EmitModrm(7, dst); 2284514f5e3Sopenharmony_ci EmitI32(src.Value()); 2294514f5e3Sopenharmony_ci } 2304514f5e3Sopenharmony_ci} 2314514f5e3Sopenharmony_ci 2324514f5e3Sopenharmony_civoid AssemblerX64::Cmp(Immediate src, Register dst) 2334514f5e3Sopenharmony_ci{ 2344514f5e3Sopenharmony_ci Cmpq(src, dst); 2354514f5e3Sopenharmony_ci} 2364514f5e3Sopenharmony_ci 2374514f5e3Sopenharmony_civoid AssemblerX64::Movq(Register src, Register dst) 2384514f5e3Sopenharmony_ci{ 2394514f5e3Sopenharmony_ci EmitRexPrefix(src, dst); 2404514f5e3Sopenharmony_ci // 0x89: Move r16 to r/m16 2414514f5e3Sopenharmony_ci EmitU8(0x89); 2424514f5e3Sopenharmony_ci EmitModrm(src, dst); 2434514f5e3Sopenharmony_ci} 2444514f5e3Sopenharmony_ci 2454514f5e3Sopenharmony_civoid AssemblerX64::Mov(Register src, Register dst) 2464514f5e3Sopenharmony_ci{ 2474514f5e3Sopenharmony_ci EmitRexPrefixl(dst, src); 2484514f5e3Sopenharmony_ci // 0x89: Move r16 to r/m16 2494514f5e3Sopenharmony_ci EmitU8(0x8B); 2504514f5e3Sopenharmony_ci EmitModrm(dst, src); 2514514f5e3Sopenharmony_ci} 2524514f5e3Sopenharmony_ci 2534514f5e3Sopenharmony_civoid AssemblerX64::Align16() 2544514f5e3Sopenharmony_ci{ 2554514f5e3Sopenharmony_ci auto pos = GetCurrentPosition(); 2564514f5e3Sopenharmony_ci // 16: align16 2574514f5e3Sopenharmony_ci size_t x = 16; 2584514f5e3Sopenharmony_ci size_t delta = static_cast<size_t>(x - (pos & (x - 1))); 2594514f5e3Sopenharmony_ci for (size_t i = 0; i < delta; i++) { 2604514f5e3Sopenharmony_ci // 0x90: NOP 2614514f5e3Sopenharmony_ci EmitU8(0x90); 2624514f5e3Sopenharmony_ci } 2634514f5e3Sopenharmony_ci} 2644514f5e3Sopenharmony_ci 2654514f5e3Sopenharmony_civoid AssemblerX64::Movq(const Operand &src, Register dst) 2664514f5e3Sopenharmony_ci{ 2674514f5e3Sopenharmony_ci EmitRexPrefix(dst, src); 2684514f5e3Sopenharmony_ci // 0x8B: Move r/m64 to r64 2694514f5e3Sopenharmony_ci EmitU8(0x8B); 2704514f5e3Sopenharmony_ci EmitOperand(dst, src); 2714514f5e3Sopenharmony_ci} 2724514f5e3Sopenharmony_ci 2734514f5e3Sopenharmony_civoid AssemblerX64::Movq(Register src, const Operand &dst) 2744514f5e3Sopenharmony_ci{ 2754514f5e3Sopenharmony_ci EmitRexPrefix(src, dst); 2764514f5e3Sopenharmony_ci // 0x89: Move r64 to r/m64 2774514f5e3Sopenharmony_ci EmitU8(0x89); 2784514f5e3Sopenharmony_ci EmitOperand(src, dst); 2794514f5e3Sopenharmony_ci} 2804514f5e3Sopenharmony_ci 2814514f5e3Sopenharmony_civoid AssemblerX64::Movq(Immediate src, Operand dst) 2824514f5e3Sopenharmony_ci{ 2834514f5e3Sopenharmony_ci EmitRexPrefix(dst); 2844514f5e3Sopenharmony_ci // 0xC7: Move imm32 to r/m32 2854514f5e3Sopenharmony_ci EmitU8(0xC7); 2864514f5e3Sopenharmony_ci // 0: C7 /0 id 2874514f5e3Sopenharmony_ci EmitOperand(0, dst); 2884514f5e3Sopenharmony_ci EmitI32(src.Value()); 2894514f5e3Sopenharmony_ci} 2904514f5e3Sopenharmony_ci 2914514f5e3Sopenharmony_civoid AssemblerX64::Movq(Immediate src, Register dst) 2924514f5e3Sopenharmony_ci{ 2934514f5e3Sopenharmony_ci EmitRexPrefix(dst); 2944514f5e3Sopenharmony_ci // B8 : mov r32, imm32 2954514f5e3Sopenharmony_ci EmitU8(0xB8 | LowBits(dst)); 2964514f5e3Sopenharmony_ci EmitI32(src.Value()); 2974514f5e3Sopenharmony_ci} 2984514f5e3Sopenharmony_ci 2994514f5e3Sopenharmony_civoid AssemblerX64::Mov(const Operand &src, Register dst) 3004514f5e3Sopenharmony_ci{ 3014514f5e3Sopenharmony_ci Movq(src, dst); 3024514f5e3Sopenharmony_ci} 3034514f5e3Sopenharmony_ci 3044514f5e3Sopenharmony_civoid AssemblerX64::EmitJmp(int32_t offset) 3054514f5e3Sopenharmony_ci{ 3064514f5e3Sopenharmony_ci offset--; 3074514f5e3Sopenharmony_ci if (InRange8(offset - SIZE_OF_INT8)) { 3084514f5e3Sopenharmony_ci // EB: Jmp rel8 3094514f5e3Sopenharmony_ci EmitU8(0xEB); 3104514f5e3Sopenharmony_ci EmitI8(offset - SIZE_OF_INT8); 3114514f5e3Sopenharmony_ci } else { 3124514f5e3Sopenharmony_ci // E9: Jmp rel32 3134514f5e3Sopenharmony_ci EmitU8(0xE9); 3144514f5e3Sopenharmony_ci EmitI32(offset - SIZE_OF_INT32); 3154514f5e3Sopenharmony_ci } 3164514f5e3Sopenharmony_ci} 3174514f5e3Sopenharmony_ci 3184514f5e3Sopenharmony_civoid AssemblerX64::EmitJa(int32_t offset) 3194514f5e3Sopenharmony_ci{ 3204514f5e3Sopenharmony_ci offset--; 3214514f5e3Sopenharmony_ci if (InRange8(offset - SIZE_OF_INT8)) { 3224514f5e3Sopenharmony_ci // 77 : Ja rel8 3234514f5e3Sopenharmony_ci EmitU8(0x77); 3244514f5e3Sopenharmony_ci EmitI8(offset - SIZE_OF_INT8); 3254514f5e3Sopenharmony_ci } else { 3264514f5e3Sopenharmony_ci offset--; 3274514f5e3Sopenharmony_ci // 0F 87 : ja rel32 3284514f5e3Sopenharmony_ci EmitU8(0x0F); 3294514f5e3Sopenharmony_ci EmitU8(0x87); 3304514f5e3Sopenharmony_ci EmitI32(offset - SIZE_OF_INT32); 3314514f5e3Sopenharmony_ci } 3324514f5e3Sopenharmony_ci} 3334514f5e3Sopenharmony_ci 3344514f5e3Sopenharmony_civoid AssemblerX64::EmitJb(int32_t offset) 3354514f5e3Sopenharmony_ci{ 3364514f5e3Sopenharmony_ci offset--; 3374514f5e3Sopenharmony_ci if (InRange8(offset - SIZE_OF_INT8)) { 3384514f5e3Sopenharmony_ci // 72 : Jb rel8 3394514f5e3Sopenharmony_ci EmitU8(0x72); 3404514f5e3Sopenharmony_ci EmitI8(offset - SIZE_OF_INT8); 3414514f5e3Sopenharmony_ci } else { 3424514f5e3Sopenharmony_ci offset--; 3434514f5e3Sopenharmony_ci // 0F 82 : Jb rel32 3444514f5e3Sopenharmony_ci EmitU8(0x0F); 3454514f5e3Sopenharmony_ci EmitU8(0x82); 3464514f5e3Sopenharmony_ci EmitI32(offset - SIZE_OF_INT32); 3474514f5e3Sopenharmony_ci } 3484514f5e3Sopenharmony_ci} 3494514f5e3Sopenharmony_ci 3504514f5e3Sopenharmony_civoid AssemblerX64::EmitJz(int32_t offset) 3514514f5e3Sopenharmony_ci{ 3524514f5e3Sopenharmony_ci offset--; 3534514f5e3Sopenharmony_ci if (InRange8(offset - SIZE_OF_INT8)) { 3544514f5e3Sopenharmony_ci // 74 : Jz rel8 3554514f5e3Sopenharmony_ci EmitU8(0x74); 3564514f5e3Sopenharmony_ci EmitI8(offset - SIZE_OF_INT8); 3574514f5e3Sopenharmony_ci } else { 3584514f5e3Sopenharmony_ci offset--; 3594514f5e3Sopenharmony_ci // 0F 84 : Jz rel32 3604514f5e3Sopenharmony_ci EmitU8(0x0F); 3614514f5e3Sopenharmony_ci EmitU8(0x84); 3624514f5e3Sopenharmony_ci EmitI32(offset - SIZE_OF_INT32); 3634514f5e3Sopenharmony_ci } 3644514f5e3Sopenharmony_ci} 3654514f5e3Sopenharmony_ci 3664514f5e3Sopenharmony_civoid AssemblerX64::EmitJne(int32_t offset) 3674514f5e3Sopenharmony_ci{ 3684514f5e3Sopenharmony_ci offset--; 3694514f5e3Sopenharmony_ci if (InRange8(offset - SIZE_OF_INT8)) { 3704514f5e3Sopenharmony_ci // 75 : Jne rel8; 3714514f5e3Sopenharmony_ci EmitU8(0x75); 3724514f5e3Sopenharmony_ci EmitI8(offset - SIZE_OF_INT8); 3734514f5e3Sopenharmony_ci } else { 3744514f5e3Sopenharmony_ci offset--; 3754514f5e3Sopenharmony_ci // 0F 85 : Jne rel32 3764514f5e3Sopenharmony_ci EmitU8(0x0F); 3774514f5e3Sopenharmony_ci EmitU8(0x85); 3784514f5e3Sopenharmony_ci EmitI32(offset - SIZE_OF_INT32); 3794514f5e3Sopenharmony_ci } 3804514f5e3Sopenharmony_ci} 3814514f5e3Sopenharmony_ci 3824514f5e3Sopenharmony_civoid AssemblerX64::EmitJbe(int32_t offset) 3834514f5e3Sopenharmony_ci{ 3844514f5e3Sopenharmony_ci offset--; 3854514f5e3Sopenharmony_ci if (InRange8(offset - SIZE_OF_INT8)) { 3864514f5e3Sopenharmony_ci // 76 : Jbe rel8; 3874514f5e3Sopenharmony_ci EmitU8(0x76); 3884514f5e3Sopenharmony_ci EmitI8(offset - SIZE_OF_INT8); 3894514f5e3Sopenharmony_ci } else { 3904514f5e3Sopenharmony_ci offset--; 3914514f5e3Sopenharmony_ci // 0F 86 : Jne rel32 3924514f5e3Sopenharmony_ci EmitU8(0x0F); 3934514f5e3Sopenharmony_ci EmitU8(0x86); 3944514f5e3Sopenharmony_ci EmitI32(offset - SIZE_OF_INT32); 3954514f5e3Sopenharmony_ci } 3964514f5e3Sopenharmony_ci} 3974514f5e3Sopenharmony_ci 3984514f5e3Sopenharmony_civoid AssemblerX64::EmitJnz(int32_t offset) 3994514f5e3Sopenharmony_ci{ 4004514f5e3Sopenharmony_ci offset--; 4014514f5e3Sopenharmony_ci if (InRange8(offset)) { 4024514f5e3Sopenharmony_ci // 75 : Jnz rel8 4034514f5e3Sopenharmony_ci EmitU8(0x75); 4044514f5e3Sopenharmony_ci EmitI8(offset - SIZE_OF_INT8); 4054514f5e3Sopenharmony_ci } else { 4064514f5e3Sopenharmony_ci offset--; 4074514f5e3Sopenharmony_ci // 0F 85: Jnz rel32 4084514f5e3Sopenharmony_ci EmitU8(0x0F); 4094514f5e3Sopenharmony_ci EmitU8(0x85); 4104514f5e3Sopenharmony_ci EmitI32(offset - SIZE_OF_INT32); 4114514f5e3Sopenharmony_ci } 4124514f5e3Sopenharmony_ci} 4134514f5e3Sopenharmony_ci 4144514f5e3Sopenharmony_civoid AssemblerX64::EmitJle(int32_t offset) 4154514f5e3Sopenharmony_ci{ 4164514f5e3Sopenharmony_ci offset--; 4174514f5e3Sopenharmony_ci if (InRange8(offset)) { 4184514f5e3Sopenharmony_ci // 7E : Jle rel8 4194514f5e3Sopenharmony_ci EmitU8(0x7E); 4204514f5e3Sopenharmony_ci EmitI8(offset - SIZE_OF_INT8); 4214514f5e3Sopenharmony_ci } else { 4224514f5e3Sopenharmony_ci offset--; 4234514f5e3Sopenharmony_ci // 0F 8E: Jle rel32 4244514f5e3Sopenharmony_ci EmitU8(0x0F); 4254514f5e3Sopenharmony_ci EmitU8(0x8E); 4264514f5e3Sopenharmony_ci EmitI32(offset - SIZE_OF_INT32); 4274514f5e3Sopenharmony_ci } 4284514f5e3Sopenharmony_ci} 4294514f5e3Sopenharmony_ci 4304514f5e3Sopenharmony_civoid AssemblerX64::EmitJae(int32_t offset) 4314514f5e3Sopenharmony_ci{ 4324514f5e3Sopenharmony_ci offset--; 4334514f5e3Sopenharmony_ci if (InRange8(offset)) { 4344514f5e3Sopenharmony_ci // 73 : Jae rel8 4354514f5e3Sopenharmony_ci EmitU8(0x73); 4364514f5e3Sopenharmony_ci EmitI8(offset - SIZE_OF_INT8); 4374514f5e3Sopenharmony_ci } else { 4384514f5e3Sopenharmony_ci offset--; 4394514f5e3Sopenharmony_ci // 0F 83: Jae rel32 4404514f5e3Sopenharmony_ci EmitU8(0x0F); 4414514f5e3Sopenharmony_ci EmitU8(0x83); 4424514f5e3Sopenharmony_ci EmitI32(offset - SIZE_OF_INT32); 4434514f5e3Sopenharmony_ci } 4444514f5e3Sopenharmony_ci} 4454514f5e3Sopenharmony_ci 4464514f5e3Sopenharmony_civoid AssemblerX64::EmitJg(int32_t offset) 4474514f5e3Sopenharmony_ci{ 4484514f5e3Sopenharmony_ci offset--; 4494514f5e3Sopenharmony_ci if (InRange8(offset)) { 4504514f5e3Sopenharmony_ci // 7F : Jg rel8 4514514f5e3Sopenharmony_ci EmitU8(0x7F); 4524514f5e3Sopenharmony_ci EmitI8(offset - SIZE_OF_INT8); 4534514f5e3Sopenharmony_ci } else { 4544514f5e3Sopenharmony_ci offset--; 4554514f5e3Sopenharmony_ci // 0F 8F: Jg rel32 4564514f5e3Sopenharmony_ci EmitU8(0x0F); 4574514f5e3Sopenharmony_ci EmitU8(0x8F); 4584514f5e3Sopenharmony_ci EmitI32(offset - SIZE_OF_INT32); 4594514f5e3Sopenharmony_ci } 4604514f5e3Sopenharmony_ci} 4614514f5e3Sopenharmony_ci 4624514f5e3Sopenharmony_civoid AssemblerX64::EmitJge(int32_t offset) 4634514f5e3Sopenharmony_ci{ 4644514f5e3Sopenharmony_ci offset--; 4654514f5e3Sopenharmony_ci if (InRange8(offset)) { 4664514f5e3Sopenharmony_ci // 7D : Jg rel8 4674514f5e3Sopenharmony_ci EmitU8(0x7D); 4684514f5e3Sopenharmony_ci EmitI8(offset - SIZE_OF_INT8); 4694514f5e3Sopenharmony_ci } else { 4704514f5e3Sopenharmony_ci offset--; 4714514f5e3Sopenharmony_ci // 0F 8F: Jg rel32 4724514f5e3Sopenharmony_ci EmitU8(0x0F); 4734514f5e3Sopenharmony_ci EmitU8(0x8D); 4744514f5e3Sopenharmony_ci EmitI32(offset - SIZE_OF_INT32); 4754514f5e3Sopenharmony_ci } 4764514f5e3Sopenharmony_ci} 4774514f5e3Sopenharmony_ci 4784514f5e3Sopenharmony_civoid AssemblerX64::EmitJe(int32_t offset) 4794514f5e3Sopenharmony_ci{ 4804514f5e3Sopenharmony_ci offset--; 4814514f5e3Sopenharmony_ci if (InRange8(offset)) { 4824514f5e3Sopenharmony_ci // 74 : Je rel8 4834514f5e3Sopenharmony_ci EmitU8(0x74); 4844514f5e3Sopenharmony_ci EmitI8(offset - SIZE_OF_INT8); 4854514f5e3Sopenharmony_ci } else { 4864514f5e3Sopenharmony_ci offset--; 4874514f5e3Sopenharmony_ci // 0F 84: Je rel32 4884514f5e3Sopenharmony_ci EmitU8(0x0F); 4894514f5e3Sopenharmony_ci EmitU8(0x84); 4904514f5e3Sopenharmony_ci EmitI32(offset - SIZE_OF_INT32); 4914514f5e3Sopenharmony_ci } 4924514f5e3Sopenharmony_ci} 4934514f5e3Sopenharmony_ci 4944514f5e3Sopenharmony_civoid AssemblerX64::EmitCall(int32_t offset) 4954514f5e3Sopenharmony_ci{ 4964514f5e3Sopenharmony_ci offset--; 4974514f5e3Sopenharmony_ci // E8: call rel32 4984514f5e3Sopenharmony_ci EmitU8(0xE8); 4994514f5e3Sopenharmony_ci EmitI32(offset - SIZE_OF_INT32); 5004514f5e3Sopenharmony_ci} 5014514f5e3Sopenharmony_ci 5024514f5e3Sopenharmony_civoid AssemblerX64::EmitJnb(int32_t offset) 5034514f5e3Sopenharmony_ci{ 5044514f5e3Sopenharmony_ci offset--; 5054514f5e3Sopenharmony_ci if (InRange8(offset)) { 5064514f5e3Sopenharmony_ci // 73 : Jnb rel8 5074514f5e3Sopenharmony_ci EmitU8(0x73); 5084514f5e3Sopenharmony_ci EmitI8(offset - SIZE_OF_INT8); 5094514f5e3Sopenharmony_ci } else { 5104514f5e3Sopenharmony_ci offset--; 5114514f5e3Sopenharmony_ci // 0F 83: Jnb rel32 5124514f5e3Sopenharmony_ci EmitU8(0x0F); 5134514f5e3Sopenharmony_ci EmitU8(0x83); 5144514f5e3Sopenharmony_ci EmitI32(offset - SIZE_OF_INT32); 5154514f5e3Sopenharmony_ci } 5164514f5e3Sopenharmony_ci} 5174514f5e3Sopenharmony_ci 5184514f5e3Sopenharmony_civoid AssemblerX64::Callq(Register addr) 5194514f5e3Sopenharmony_ci{ 5204514f5e3Sopenharmony_ci // C3: RET Near return to calling procedure 5214514f5e3Sopenharmony_ci EmitRexPrefix(addr); 5224514f5e3Sopenharmony_ci // FF: Call r/m16 5234514f5e3Sopenharmony_ci EmitU8(0xFF); 5244514f5e3Sopenharmony_ci // 0x2: FF /2 5254514f5e3Sopenharmony_ci EmitModrm(0x2, addr); 5264514f5e3Sopenharmony_ci} 5274514f5e3Sopenharmony_ci 5284514f5e3Sopenharmony_civoid AssemblerX64::Callq(Label *target) 5294514f5e3Sopenharmony_ci{ 5304514f5e3Sopenharmony_ci if (target->IsBound()) { 5314514f5e3Sopenharmony_ci int32_t offset = static_cast<int32_t>(target->GetPos() - GetCurrentPosition()); 5324514f5e3Sopenharmony_ci EmitCall(offset); 5334514f5e3Sopenharmony_ci return; 5344514f5e3Sopenharmony_ci } 5354514f5e3Sopenharmony_ci 5364514f5e3Sopenharmony_ci auto pos = GetCurrentPosition(); 5374514f5e3Sopenharmony_ci int32_t emitPos = 0; 5384514f5e3Sopenharmony_ci if (target->IsLinked()) { 5394514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedPos()); 5404514f5e3Sopenharmony_ci } 5414514f5e3Sopenharmony_ci // +1: skip opcode 5424514f5e3Sopenharmony_ci target->LinkTo(pos + 1); 5434514f5e3Sopenharmony_ci // E8: call rel32 5444514f5e3Sopenharmony_ci EmitU8(0xE8); 5454514f5e3Sopenharmony_ci EmitI32(emitPos); 5464514f5e3Sopenharmony_ci} 5474514f5e3Sopenharmony_ci 5484514f5e3Sopenharmony_civoid AssemblerX64::Ret() 5494514f5e3Sopenharmony_ci{ 5504514f5e3Sopenharmony_ci // C3: RET Near return to calling procedure 5514514f5e3Sopenharmony_ci EmitU8(0xC3); 5524514f5e3Sopenharmony_ci} 5534514f5e3Sopenharmony_ci 5544514f5e3Sopenharmony_civoid AssemblerX64::Jmp(Label *target, Distance distance) 5554514f5e3Sopenharmony_ci{ 5564514f5e3Sopenharmony_ci if (target->IsBound()) { 5574514f5e3Sopenharmony_ci int32_t offset = static_cast<int32_t>(target->GetPos() - GetCurrentPosition()); 5584514f5e3Sopenharmony_ci EmitJmp(offset); 5594514f5e3Sopenharmony_ci return; 5604514f5e3Sopenharmony_ci } 5614514f5e3Sopenharmony_ci 5624514f5e3Sopenharmony_ci auto pos = GetCurrentPosition(); 5634514f5e3Sopenharmony_ci int32_t emitPos = 0; 5644514f5e3Sopenharmony_ci if (distance == Distance::Near) { 5654514f5e3Sopenharmony_ci if (target->IsLinkedNear()) { 5664514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedNearPos() - pos); 5674514f5e3Sopenharmony_ci } 5684514f5e3Sopenharmony_ci // +1: skip opcode 5694514f5e3Sopenharmony_ci target->LinkNearPos(pos + 1); 5704514f5e3Sopenharmony_ci ASSERT(InRange8(emitPos)); 5714514f5e3Sopenharmony_ci // EB: Jmp rel8 5724514f5e3Sopenharmony_ci EmitU8(0xEB); 5734514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(emitPos)); 5744514f5e3Sopenharmony_ci } else { 5754514f5e3Sopenharmony_ci if (target->IsLinked()) { 5764514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedPos()); 5774514f5e3Sopenharmony_ci } 5784514f5e3Sopenharmony_ci // +1: skip opcode 5794514f5e3Sopenharmony_ci target->LinkTo(pos + 1); 5804514f5e3Sopenharmony_ci // E9: Jmp rel32 5814514f5e3Sopenharmony_ci EmitU8(0xE9); 5824514f5e3Sopenharmony_ci EmitI32(emitPos); 5834514f5e3Sopenharmony_ci } 5844514f5e3Sopenharmony_ci} 5854514f5e3Sopenharmony_ci 5864514f5e3Sopenharmony_civoid AssemblerX64::Jmp(Register dst) 5874514f5e3Sopenharmony_ci{ 5884514f5e3Sopenharmony_ci EmitRexPrefix(dst); 5894514f5e3Sopenharmony_ci // opcode FF/4 : jmp r/m64 5904514f5e3Sopenharmony_ci EmitU8(0xFF); 5914514f5e3Sopenharmony_ci // 4 means register 5924514f5e3Sopenharmony_ci EmitModrm(4, dst); 5934514f5e3Sopenharmony_ci} 5944514f5e3Sopenharmony_ci 5954514f5e3Sopenharmony_civoid AssemblerX64::Jmp(Immediate offset) 5964514f5e3Sopenharmony_ci{ 5974514f5e3Sopenharmony_ci if (InRange8(offset.Value())) { 5984514f5e3Sopenharmony_ci // opcode EB : jmp rel8 5994514f5e3Sopenharmony_ci EmitU8(0xEB); 6004514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(offset.Value())); 6014514f5e3Sopenharmony_ci } else { 6024514f5e3Sopenharmony_ci // opcode E9 : jmp rel32 6034514f5e3Sopenharmony_ci EmitU8(0xE9); 6044514f5e3Sopenharmony_ci EmitI32(offset.Value()); 6054514f5e3Sopenharmony_ci } 6064514f5e3Sopenharmony_ci} 6074514f5e3Sopenharmony_ci 6084514f5e3Sopenharmony_civoid AssemblerX64::Ja(Label *target, Distance distance) 6094514f5e3Sopenharmony_ci{ 6104514f5e3Sopenharmony_ci if (target->IsBound()) { 6114514f5e3Sopenharmony_ci int32_t offset = static_cast<int32_t>(target->GetPos() - GetCurrentPosition()); 6124514f5e3Sopenharmony_ci EmitJa(offset); 6134514f5e3Sopenharmony_ci return; 6144514f5e3Sopenharmony_ci } 6154514f5e3Sopenharmony_ci auto pos = GetCurrentPosition(); 6164514f5e3Sopenharmony_ci int32_t emitPos = 0; 6174514f5e3Sopenharmony_ci if (distance == Distance::Near) { 6184514f5e3Sopenharmony_ci if (target->IsLinkedNear()) { 6194514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedNearPos() - pos); 6204514f5e3Sopenharmony_ci } 6214514f5e3Sopenharmony_ci // +1: skip opcode 6224514f5e3Sopenharmony_ci target->LinkNearPos(pos + 1); 6234514f5e3Sopenharmony_ci ASSERT(InRange8(emitPos)); 6244514f5e3Sopenharmony_ci // 77: ja rel8 6254514f5e3Sopenharmony_ci EmitU8(0x77); 6264514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(emitPos)); 6274514f5e3Sopenharmony_ci } else { 6284514f5e3Sopenharmony_ci if (target->IsLinked()) { 6294514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedPos()); 6304514f5e3Sopenharmony_ci } 6314514f5e3Sopenharmony_ci // 2: skip opcode 6324514f5e3Sopenharmony_ci target->LinkTo(pos + 2); 6334514f5e3Sopenharmony_ci // 0F 87: ja rel32 6344514f5e3Sopenharmony_ci EmitU8(0X0F); 6354514f5e3Sopenharmony_ci EmitU8(0x87); 6364514f5e3Sopenharmony_ci EmitI32(emitPos); 6374514f5e3Sopenharmony_ci } 6384514f5e3Sopenharmony_ci} 6394514f5e3Sopenharmony_ci 6404514f5e3Sopenharmony_civoid AssemblerX64::Jb(Label *target, Distance distance) 6414514f5e3Sopenharmony_ci{ 6424514f5e3Sopenharmony_ci if (target->IsBound()) { 6434514f5e3Sopenharmony_ci int32_t offset = static_cast<int32_t>(target->GetPos() - GetCurrentPosition()); 6444514f5e3Sopenharmony_ci EmitJb(offset); 6454514f5e3Sopenharmony_ci return; 6464514f5e3Sopenharmony_ci } 6474514f5e3Sopenharmony_ci auto pos = GetCurrentPosition(); 6484514f5e3Sopenharmony_ci int32_t emitPos = 0; 6494514f5e3Sopenharmony_ci if (distance == Distance::Near) { 6504514f5e3Sopenharmony_ci if (target->IsLinkedNear()) { 6514514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedNearPos() - pos); 6524514f5e3Sopenharmony_ci } 6534514f5e3Sopenharmony_ci // +1: skip opcode 6544514f5e3Sopenharmony_ci target->LinkNearPos(pos + 1); 6554514f5e3Sopenharmony_ci ASSERT(InRange8(emitPos)); 6564514f5e3Sopenharmony_ci // 72 : Jb rel8 6574514f5e3Sopenharmony_ci EmitU8(0x72); 6584514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(emitPos)); 6594514f5e3Sopenharmony_ci } else { 6604514f5e3Sopenharmony_ci if (target->IsLinked()) { 6614514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedPos()); 6624514f5e3Sopenharmony_ci } 6634514f5e3Sopenharmony_ci // 2: skip opcode 6644514f5e3Sopenharmony_ci target->LinkTo(pos + 2); 6654514f5e3Sopenharmony_ci // 0F 82: jb rel32 6664514f5e3Sopenharmony_ci EmitU8(0X0F); 6674514f5e3Sopenharmony_ci EmitU8(0x82); 6684514f5e3Sopenharmony_ci EmitI32(emitPos); 6694514f5e3Sopenharmony_ci } 6704514f5e3Sopenharmony_ci} 6714514f5e3Sopenharmony_civoid AssemblerX64::Jz(Label *target, Distance distance) 6724514f5e3Sopenharmony_ci{ 6734514f5e3Sopenharmony_ci if (target->IsBound()) { 6744514f5e3Sopenharmony_ci int32_t offset = static_cast<int32_t>(target->GetPos() - GetCurrentPosition()); 6754514f5e3Sopenharmony_ci EmitJz(offset); 6764514f5e3Sopenharmony_ci return; 6774514f5e3Sopenharmony_ci } 6784514f5e3Sopenharmony_ci auto pos = GetCurrentPosition(); 6794514f5e3Sopenharmony_ci int32_t emitPos = 0; 6804514f5e3Sopenharmony_ci if (distance == Distance::Near) { 6814514f5e3Sopenharmony_ci if (target->IsLinkedNear()) { 6824514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedNearPos() - pos); 6834514f5e3Sopenharmony_ci } 6844514f5e3Sopenharmony_ci // +1: skip opcode 6854514f5e3Sopenharmony_ci target->LinkNearPos(pos + 1); 6864514f5e3Sopenharmony_ci ASSERT(InRange8(emitPos)); 6874514f5e3Sopenharmony_ci // 74 : Jz rel8 6884514f5e3Sopenharmony_ci EmitU8(0x74); 6894514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(emitPos)); 6904514f5e3Sopenharmony_ci } else { 6914514f5e3Sopenharmony_ci if (target->IsLinked()) { 6924514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedPos()); 6934514f5e3Sopenharmony_ci } 6944514f5e3Sopenharmony_ci // 2: skip opcode 6954514f5e3Sopenharmony_ci target->LinkTo(pos + 2); 6964514f5e3Sopenharmony_ci // 0F 84: Jz rel32 6974514f5e3Sopenharmony_ci EmitU8(0X0F); 6984514f5e3Sopenharmony_ci EmitU8(0x84); 6994514f5e3Sopenharmony_ci EmitI32(emitPos); 7004514f5e3Sopenharmony_ci } 7014514f5e3Sopenharmony_ci} 7024514f5e3Sopenharmony_ci 7034514f5e3Sopenharmony_civoid AssemblerX64::Je(Label *target, Distance distance) 7044514f5e3Sopenharmony_ci{ 7054514f5e3Sopenharmony_ci if (target->IsBound()) { 7064514f5e3Sopenharmony_ci int32_t offset = static_cast<int32_t>(target->GetPos() - GetCurrentPosition()); 7074514f5e3Sopenharmony_ci EmitJe(offset); 7084514f5e3Sopenharmony_ci return; 7094514f5e3Sopenharmony_ci } 7104514f5e3Sopenharmony_ci auto pos = GetCurrentPosition(); 7114514f5e3Sopenharmony_ci int32_t emitPos = 0; 7124514f5e3Sopenharmony_ci if (distance == Distance::Near) { 7134514f5e3Sopenharmony_ci if (target->IsLinkedNear()) { 7144514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedNearPos() - pos); 7154514f5e3Sopenharmony_ci } 7164514f5e3Sopenharmony_ci // +1: skip opcode 7174514f5e3Sopenharmony_ci target->LinkNearPos(pos + 1); 7184514f5e3Sopenharmony_ci ASSERT(InRange8(emitPos)); 7194514f5e3Sopenharmony_ci // 74 : Je rel8 7204514f5e3Sopenharmony_ci EmitU8(0x74); 7214514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(emitPos)); 7224514f5e3Sopenharmony_ci } else { 7234514f5e3Sopenharmony_ci if (target->IsLinked()) { 7244514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedPos()); 7254514f5e3Sopenharmony_ci } 7264514f5e3Sopenharmony_ci // 2: skip opcode 7274514f5e3Sopenharmony_ci target->LinkTo(pos + 2); 7284514f5e3Sopenharmony_ci // 0F 84: Je rel32 7294514f5e3Sopenharmony_ci EmitU8(0X0F); 7304514f5e3Sopenharmony_ci EmitU8(0x84); 7314514f5e3Sopenharmony_ci EmitI32(emitPos); 7324514f5e3Sopenharmony_ci } 7334514f5e3Sopenharmony_ci} 7344514f5e3Sopenharmony_ci 7354514f5e3Sopenharmony_civoid AssemblerX64::Bind(Label *target) 7364514f5e3Sopenharmony_ci{ 7374514f5e3Sopenharmony_ci size_t pos = GetCurrentPosition(); 7384514f5e3Sopenharmony_ci ASSERT(!target->IsBound()); 7394514f5e3Sopenharmony_ci 7404514f5e3Sopenharmony_ci if (target->IsLinked()) { 7414514f5e3Sopenharmony_ci uint32_t linkPos = target->GetLinkedPos(); 7424514f5e3Sopenharmony_ci while (linkPos != 0) { 7434514f5e3Sopenharmony_ci uint32_t preLinkPos = GetU32(linkPos); 7444514f5e3Sopenharmony_ci int32_t disp = static_cast<int32_t>(pos - linkPos - sizeof(int32_t)); 7454514f5e3Sopenharmony_ci PutI32(linkPos, disp); 7464514f5e3Sopenharmony_ci linkPos = preLinkPos; 7474514f5e3Sopenharmony_ci } 7484514f5e3Sopenharmony_ci } 7494514f5e3Sopenharmony_ci 7504514f5e3Sopenharmony_ci if (target->IsLinkedNear()) { 7514514f5e3Sopenharmony_ci uint32_t linkPos = target->GetLinkedNearPos(); 7524514f5e3Sopenharmony_ci while (linkPos != 0) { 7534514f5e3Sopenharmony_ci int8_t offsetToNext = GetI8(static_cast<size_t>(linkPos)); 7544514f5e3Sopenharmony_ci int32_t disp = static_cast<int32_t>(pos - linkPos - sizeof(int8_t)); 7554514f5e3Sopenharmony_ci ASSERT(InRange8(disp)); 7564514f5e3Sopenharmony_ci PutI8(linkPos, static_cast<int8_t>(disp)); 7574514f5e3Sopenharmony_ci if (offsetToNext == 0) { 7584514f5e3Sopenharmony_ci break; 7594514f5e3Sopenharmony_ci } 7604514f5e3Sopenharmony_ci linkPos += static_cast<uint32_t>(offsetToNext); 7614514f5e3Sopenharmony_ci } 7624514f5e3Sopenharmony_ci target->UnlinkNearPos(); 7634514f5e3Sopenharmony_ci } 7644514f5e3Sopenharmony_ci 7654514f5e3Sopenharmony_ci target->BindTo(pos); 7664514f5e3Sopenharmony_ci} 7674514f5e3Sopenharmony_ci 7684514f5e3Sopenharmony_ciOperand::Operand(Register base, int32_t disp) 7694514f5e3Sopenharmony_ci{ 7704514f5e3Sopenharmony_ci if (base == rsp || base == r12) { 7714514f5e3Sopenharmony_ci BuildSIB(Times1, rsp, base); 7724514f5e3Sopenharmony_ci } 7734514f5e3Sopenharmony_ci if (disp == 0 && base != rbp && base != r13) { 7744514f5e3Sopenharmony_ci // 0: mode 00 [r/m] 7754514f5e3Sopenharmony_ci BuildModerm(0, base); 7764514f5e3Sopenharmony_ci } else if (AssemblerX64::InRange8(disp)) { 7774514f5e3Sopenharmony_ci // 1: mode 01 [r/m + disp8] 7784514f5e3Sopenharmony_ci BuildModerm(1, base); 7794514f5e3Sopenharmony_ci BuildDisp8(disp); 7804514f5e3Sopenharmony_ci } else { 7814514f5e3Sopenharmony_ci // 2: mode 10 [r/m + disp32] 7824514f5e3Sopenharmony_ci BuildModerm(2, base); 7834514f5e3Sopenharmony_ci BuildDisp32(disp); 7844514f5e3Sopenharmony_ci } 7854514f5e3Sopenharmony_ci} 7864514f5e3Sopenharmony_ci 7874514f5e3Sopenharmony_ciOperand::Operand(Register base, Register index, Scale scale, int32_t disp) 7884514f5e3Sopenharmony_ci{ 7894514f5e3Sopenharmony_ci BuildSIB(scale, index, base); 7904514f5e3Sopenharmony_ci if (disp == 0 && base != rbp && base != r13) { 7914514f5e3Sopenharmony_ci // 0: mode 00 [r/m] 7924514f5e3Sopenharmony_ci BuildModerm(0, rsp); 7934514f5e3Sopenharmony_ci } else if (AssemblerX64::InRange8(disp)) { 7944514f5e3Sopenharmony_ci // 1: mode 01 [r/m + disp8] 7954514f5e3Sopenharmony_ci BuildModerm(1, rsp); 7964514f5e3Sopenharmony_ci BuildDisp8(disp); 7974514f5e3Sopenharmony_ci } else { 7984514f5e3Sopenharmony_ci // 2: mode 10 [r/m + disp32] 7994514f5e3Sopenharmony_ci BuildModerm(2, rsp); 8004514f5e3Sopenharmony_ci BuildDisp32(disp); 8014514f5e3Sopenharmony_ci } 8024514f5e3Sopenharmony_ci} 8034514f5e3Sopenharmony_ci 8044514f5e3Sopenharmony_ci// [index * scale + disp] 8054514f5e3Sopenharmony_ciOperand::Operand(Register index, Scale scale, int32_t disp) 8064514f5e3Sopenharmony_ci{ 8074514f5e3Sopenharmony_ci ASSERT(index != rsp); 8084514f5e3Sopenharmony_ci BuildModerm(0, rsp); 8094514f5e3Sopenharmony_ci BuildSIB(scale, index, rbp); 8104514f5e3Sopenharmony_ci BuildDisp32(disp); 8114514f5e3Sopenharmony_ci} 8124514f5e3Sopenharmony_ci 8134514f5e3Sopenharmony_civoid Operand::BuildSIB(Scale scale, Register index, Register base) 8144514f5e3Sopenharmony_ci{ 8154514f5e3Sopenharmony_ci sib_ = AssemblerX64::GetSIB(scale, index, base); 8164514f5e3Sopenharmony_ci rex_ |= AssemblerX64::GetSIBRex(index, base); 8174514f5e3Sopenharmony_ci hasSIB_ = true; 8184514f5e3Sopenharmony_ci} 8194514f5e3Sopenharmony_ci 8204514f5e3Sopenharmony_civoid Operand::BuildModerm(int32_t mode, Register rm) 8214514f5e3Sopenharmony_ci{ 8224514f5e3Sopenharmony_ci rex_ |= AssemblerX64::GetModrmRex(rm); 8234514f5e3Sopenharmony_ci moderm_ = AssemblerX64::GetModrm(mode, rm); 8244514f5e3Sopenharmony_ci} 8254514f5e3Sopenharmony_ci 8264514f5e3Sopenharmony_civoid Operand::BuildDisp8(int32_t disp) 8274514f5e3Sopenharmony_ci{ 8284514f5e3Sopenharmony_ci disp_ = disp; 8294514f5e3Sopenharmony_ci hasDisp8_ = true; 8304514f5e3Sopenharmony_ci} 8314514f5e3Sopenharmony_ci 8324514f5e3Sopenharmony_civoid Operand::BuildDisp32(int32_t disp) 8334514f5e3Sopenharmony_ci{ 8344514f5e3Sopenharmony_ci disp_ = disp; 8354514f5e3Sopenharmony_ci hasDisp32_ = true; 8364514f5e3Sopenharmony_ci} 8374514f5e3Sopenharmony_ci 8384514f5e3Sopenharmony_civoid AssemblerX64::EmitOperand(int32_t reg, Operand rm) 8394514f5e3Sopenharmony_ci{ 8404514f5e3Sopenharmony_ci // moderm 8414514f5e3Sopenharmony_ci EmitU8(rm.moderm_ | (static_cast<uint32_t>(reg) << LOW_BITS_SIZE)); 8424514f5e3Sopenharmony_ci if (rm.hasSIB_) { 8434514f5e3Sopenharmony_ci EmitU8(rm.sib_); 8444514f5e3Sopenharmony_ci } 8454514f5e3Sopenharmony_ci 8464514f5e3Sopenharmony_ci if (rm.hasDisp8_) { 8474514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(rm.disp_)); 8484514f5e3Sopenharmony_ci } else if (rm.hasDisp32_) { 8494514f5e3Sopenharmony_ci EmitI32(rm.disp_); 8504514f5e3Sopenharmony_ci } 8514514f5e3Sopenharmony_ci} 8524514f5e3Sopenharmony_ci 8534514f5e3Sopenharmony_civoid AssemblerX64::Movl(Register src, Register dst) 8544514f5e3Sopenharmony_ci{ 8554514f5e3Sopenharmony_ci EmitRexPrefixl(src, dst); 8564514f5e3Sopenharmony_ci // 0x89: Move r16 to r/m16 8574514f5e3Sopenharmony_ci EmitU8(0x89); 8584514f5e3Sopenharmony_ci EmitModrm(src, dst); 8594514f5e3Sopenharmony_ci} 8604514f5e3Sopenharmony_ci 8614514f5e3Sopenharmony_civoid AssemblerX64::Movl(const Operand &src, Register dst) 8624514f5e3Sopenharmony_ci{ 8634514f5e3Sopenharmony_ci EmitRexPrefixl(dst, src); 8644514f5e3Sopenharmony_ci // 0x8B: Move r/m64 to r64 8654514f5e3Sopenharmony_ci EmitU8(0x8B); 8664514f5e3Sopenharmony_ci EmitOperand(dst, src); 8674514f5e3Sopenharmony_ci} 8684514f5e3Sopenharmony_ci 8694514f5e3Sopenharmony_civoid AssemblerX64::Movl(Register src, const Operand& dst) 8704514f5e3Sopenharmony_ci{ 8714514f5e3Sopenharmony_ci EmitRexPrefixl(src, dst); 8724514f5e3Sopenharmony_ci // 0x89: Move r32 to r/m64 8734514f5e3Sopenharmony_ci EmitU8(0x89); 8744514f5e3Sopenharmony_ci EmitOperand(src, dst); 8754514f5e3Sopenharmony_ci} 8764514f5e3Sopenharmony_ci 8774514f5e3Sopenharmony_civoid AssemblerX64::Testq(Immediate src, Register dst) 8784514f5e3Sopenharmony_ci{ 8794514f5e3Sopenharmony_ci if (InRange8(src.Value())) { 8804514f5e3Sopenharmony_ci Testb(src, dst); 8814514f5e3Sopenharmony_ci } else if (dst == rax) { 8824514f5e3Sopenharmony_ci // A9: Test rax, imm32 8834514f5e3Sopenharmony_ci EmitU8(0xA9); 8844514f5e3Sopenharmony_ci EmitI32(src.Value()); 8854514f5e3Sopenharmony_ci } else { 8864514f5e3Sopenharmony_ci EmitRexPrefixW(dst); 8874514f5e3Sopenharmony_ci // F7: Test r/m64, imm32 8884514f5e3Sopenharmony_ci EmitU8(0xF7); 8894514f5e3Sopenharmony_ci // 0: F7 0 id 8904514f5e3Sopenharmony_ci EmitModrm(0, dst); 8914514f5e3Sopenharmony_ci EmitI32(src.Value()); 8924514f5e3Sopenharmony_ci } 8934514f5e3Sopenharmony_ci} 8944514f5e3Sopenharmony_ci 8954514f5e3Sopenharmony_civoid AssemblerX64::Testb(Immediate src, Register dst) 8964514f5e3Sopenharmony_ci{ 8974514f5e3Sopenharmony_ci ASSERT(InRange8(src.Value())); 8984514f5e3Sopenharmony_ci if (dst == rax) { 8994514f5e3Sopenharmony_ci // A8: Test al, imm8 9004514f5e3Sopenharmony_ci EmitU8(0xA8); 9014514f5e3Sopenharmony_ci } else { 9024514f5e3Sopenharmony_ci // AH BH CG DH can not be encoded to access if REX prefix used. 9034514f5e3Sopenharmony_ci if (dst >= rsp) { 9044514f5e3Sopenharmony_ci EmitRexPrefixL(dst); 9054514f5e3Sopenharmony_ci } 9064514f5e3Sopenharmony_ci // F6: Test r/m8, imm8 9074514f5e3Sopenharmony_ci // REX F6: Test r/m8*, imm8 9084514f5e3Sopenharmony_ci EmitU8(0xF6); 9094514f5e3Sopenharmony_ci // 0: F6 /0 ib 9104514f5e3Sopenharmony_ci EmitModrm(0, dst); 9114514f5e3Sopenharmony_ci } 9124514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(src.Value())); 9134514f5e3Sopenharmony_ci} 9144514f5e3Sopenharmony_ci 9154514f5e3Sopenharmony_civoid AssemblerX64::Jne(Label *target, Distance distance) 9164514f5e3Sopenharmony_ci{ 9174514f5e3Sopenharmony_ci if (target->IsBound()) { 9184514f5e3Sopenharmony_ci int32_t offset = static_cast<int32_t>(target->GetPos() - GetCurrentPosition()); 9194514f5e3Sopenharmony_ci EmitJne(offset); 9204514f5e3Sopenharmony_ci return; 9214514f5e3Sopenharmony_ci } 9224514f5e3Sopenharmony_ci auto pos = GetCurrentPosition(); 9234514f5e3Sopenharmony_ci int32_t emitPos = 0; 9244514f5e3Sopenharmony_ci if (distance == Distance::Near) { 9254514f5e3Sopenharmony_ci if (target->IsLinkedNear()) { 9264514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedNearPos() - pos); 9274514f5e3Sopenharmony_ci } 9284514f5e3Sopenharmony_ci // +1: skip opcode 9294514f5e3Sopenharmony_ci target->LinkNearPos(pos + 1); 9304514f5e3Sopenharmony_ci ASSERT(InRange8(emitPos)); 9314514f5e3Sopenharmony_ci // 75 : Jne rel8; 9324514f5e3Sopenharmony_ci EmitU8(0x75); 9334514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(emitPos)); 9344514f5e3Sopenharmony_ci } else { 9354514f5e3Sopenharmony_ci if (target->IsLinked()) { 9364514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedPos()); 9374514f5e3Sopenharmony_ci } 9384514f5e3Sopenharmony_ci // 2: skip opcode 9394514f5e3Sopenharmony_ci target->LinkTo(pos + 2); 9404514f5e3Sopenharmony_ci // 0F 85 : Jne rel32 9414514f5e3Sopenharmony_ci EmitU8(0x0F); 9424514f5e3Sopenharmony_ci EmitU8(0x85); 9434514f5e3Sopenharmony_ci EmitI32(emitPos); 9444514f5e3Sopenharmony_ci } 9454514f5e3Sopenharmony_ci} 9464514f5e3Sopenharmony_ci 9474514f5e3Sopenharmony_civoid AssemblerX64::Cmpl(Register src, Register dst) 9484514f5e3Sopenharmony_ci{ 9494514f5e3Sopenharmony_ci EmitRexPrefixl(src, dst); 9504514f5e3Sopenharmony_ci // 39: Cmp r16 to r/m16 9514514f5e3Sopenharmony_ci EmitU8(0x39); 9524514f5e3Sopenharmony_ci EmitModrm(src, dst); 9534514f5e3Sopenharmony_ci} 9544514f5e3Sopenharmony_ci 9554514f5e3Sopenharmony_civoid AssemblerX64::Jbe(Label *target, Distance distance) 9564514f5e3Sopenharmony_ci{ 9574514f5e3Sopenharmony_ci if (target->IsBound()) { 9584514f5e3Sopenharmony_ci int32_t offset = static_cast<int32_t>(target->GetPos() - GetCurrentPosition()); 9594514f5e3Sopenharmony_ci EmitJbe(offset); 9604514f5e3Sopenharmony_ci return; 9614514f5e3Sopenharmony_ci } 9624514f5e3Sopenharmony_ci auto pos = GetCurrentPosition(); 9634514f5e3Sopenharmony_ci int32_t emitPos = 0; 9644514f5e3Sopenharmony_ci if (distance == Distance::Near) { 9654514f5e3Sopenharmony_ci if (target->IsLinkedNear()) { 9664514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedNearPos() - pos); 9674514f5e3Sopenharmony_ci } 9684514f5e3Sopenharmony_ci // +1: skip opcode 9694514f5e3Sopenharmony_ci target->LinkNearPos(pos + 1); 9704514f5e3Sopenharmony_ci ASSERT(InRange8(emitPos)); 9714514f5e3Sopenharmony_ci // 76 : Jbe rel8; 9724514f5e3Sopenharmony_ci EmitU8(0x76); 9734514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(emitPos)); 9744514f5e3Sopenharmony_ci } else { 9754514f5e3Sopenharmony_ci if (target->IsLinked()) { 9764514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedPos()); 9774514f5e3Sopenharmony_ci } 9784514f5e3Sopenharmony_ci // 2: skip opcode 9794514f5e3Sopenharmony_ci target->LinkTo(pos + 2); 9804514f5e3Sopenharmony_ci // 0F 86 : Jbe rel32 9814514f5e3Sopenharmony_ci EmitU8(0x0F); 9824514f5e3Sopenharmony_ci EmitU8(0x86); 9834514f5e3Sopenharmony_ci EmitI32(emitPos); 9844514f5e3Sopenharmony_ci } 9854514f5e3Sopenharmony_ci} 9864514f5e3Sopenharmony_ci 9874514f5e3Sopenharmony_civoid AssemblerX64::CMovbe(Register src, Register dst) 9884514f5e3Sopenharmony_ci{ 9894514f5e3Sopenharmony_ci EmitRexPrefixl(dst, src); 9904514f5e3Sopenharmony_ci // 0f 46: CMovbe r32, r/m32 9914514f5e3Sopenharmony_ci EmitU8(0x0F); 9924514f5e3Sopenharmony_ci EmitU8(0x46); 9934514f5e3Sopenharmony_ci EmitModrm(dst, src); 9944514f5e3Sopenharmony_ci} 9954514f5e3Sopenharmony_ci 9964514f5e3Sopenharmony_civoid AssemblerX64::Leaq(const Operand &src, Register dst) 9974514f5e3Sopenharmony_ci{ 9984514f5e3Sopenharmony_ci EmitRexPrefix(dst, src); 9994514f5e3Sopenharmony_ci // 8D : lea r64, m 10004514f5e3Sopenharmony_ci EmitU8(0x8D); 10014514f5e3Sopenharmony_ci EmitOperand(dst, src); 10024514f5e3Sopenharmony_ci} 10034514f5e3Sopenharmony_ci 10044514f5e3Sopenharmony_civoid AssemblerX64::Leal(const Operand &src, Register dst) 10054514f5e3Sopenharmony_ci{ 10064514f5e3Sopenharmony_ci EmitRexPrefixl(dst, src); 10074514f5e3Sopenharmony_ci // 8D : lea r64, m 10084514f5e3Sopenharmony_ci EmitU8(0x8D); 10094514f5e3Sopenharmony_ci EmitOperand(dst, src); 10104514f5e3Sopenharmony_ci} 10114514f5e3Sopenharmony_ci 10124514f5e3Sopenharmony_civoid AssemblerX64::Shrq(Immediate src, Register dst) 10134514f5e3Sopenharmony_ci{ 10144514f5e3Sopenharmony_ci EmitRexPrefixW(dst); 10154514f5e3Sopenharmony_ci // C1 : Shr r/m64, imm8; 10164514f5e3Sopenharmony_ci EmitU8(0xc1); 10174514f5e3Sopenharmony_ci // 5: C1 /5 id 10184514f5e3Sopenharmony_ci EmitModrm(5, dst); 10194514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(src.Value())); 10204514f5e3Sopenharmony_ci} 10214514f5e3Sopenharmony_ci 10224514f5e3Sopenharmony_civoid AssemblerX64::Shrl(Immediate src, Register dst) 10234514f5e3Sopenharmony_ci{ 10244514f5e3Sopenharmony_ci EmitRexPrefix(dst); 10254514f5e3Sopenharmony_ci // C1 : Shr r/m32, imm8; 10264514f5e3Sopenharmony_ci EmitU8(0xc1); 10274514f5e3Sopenharmony_ci // 5: C1 /5 id 10284514f5e3Sopenharmony_ci EmitModrm(5, dst); 10294514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(src.Value())); 10304514f5e3Sopenharmony_ci} 10314514f5e3Sopenharmony_ci 10324514f5e3Sopenharmony_civoid AssemblerX64::Shr(Immediate src, Register dst) 10334514f5e3Sopenharmony_ci{ 10344514f5e3Sopenharmony_ci Shrq(src, dst); 10354514f5e3Sopenharmony_ci} 10364514f5e3Sopenharmony_ci 10374514f5e3Sopenharmony_civoid AssemblerX64::Andq(Immediate src, Register dst) 10384514f5e3Sopenharmony_ci{ 10394514f5e3Sopenharmony_ci EmitRexPrefixW(dst); 10404514f5e3Sopenharmony_ci if (InRange8(src.Value())) { 10414514f5e3Sopenharmony_ci // 83: and r/m64, imm8 10424514f5e3Sopenharmony_ci EmitU8(0x83); 10434514f5e3Sopenharmony_ci // 4: 83 /4 ib 10444514f5e3Sopenharmony_ci EmitModrm(4, dst); 10454514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(src.Value())); 10464514f5e3Sopenharmony_ci } else if (dst == rax) { 10474514f5e3Sopenharmony_ci // 0x25: and rax, imm32 10484514f5e3Sopenharmony_ci EmitU8(0x25); 10494514f5e3Sopenharmony_ci EmitI32(src.Value()); 10504514f5e3Sopenharmony_ci } else { 10514514f5e3Sopenharmony_ci // 81: and r/m64, imm32 10524514f5e3Sopenharmony_ci EmitU8(0x81); 10534514f5e3Sopenharmony_ci // 4: 81 /4 id 10544514f5e3Sopenharmony_ci EmitModrm(4, dst); 10554514f5e3Sopenharmony_ci EmitI32(src.Value()); 10564514f5e3Sopenharmony_ci } 10574514f5e3Sopenharmony_ci} 10584514f5e3Sopenharmony_ci 10594514f5e3Sopenharmony_civoid AssemblerX64::Andl(Immediate src, Register dst) 10604514f5e3Sopenharmony_ci{ 10614514f5e3Sopenharmony_ci EmitRexPrefix(dst); 10624514f5e3Sopenharmony_ci if (InRange8(src.Value())) { 10634514f5e3Sopenharmony_ci // 83: and r/m64, imm8 10644514f5e3Sopenharmony_ci EmitU8(0x83); 10654514f5e3Sopenharmony_ci // 4: 83 /4 ib 10664514f5e3Sopenharmony_ci EmitModrm(4, dst); 10674514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(src.Value())); 10684514f5e3Sopenharmony_ci } else if (dst == rax) { 10694514f5e3Sopenharmony_ci // 0x25: and rax, imm32 10704514f5e3Sopenharmony_ci EmitU8(0x25); 10714514f5e3Sopenharmony_ci EmitI32(src.Value()); 10724514f5e3Sopenharmony_ci } else { 10734514f5e3Sopenharmony_ci // 81: and r/m64, imm32 10744514f5e3Sopenharmony_ci EmitU8(0x81); 10754514f5e3Sopenharmony_ci // 4: 81 /4 id 10764514f5e3Sopenharmony_ci EmitModrm(4, dst); 10774514f5e3Sopenharmony_ci EmitI32(src.Value()); 10784514f5e3Sopenharmony_ci } 10794514f5e3Sopenharmony_ci} 10804514f5e3Sopenharmony_ci 10814514f5e3Sopenharmony_civoid AssemblerX64::And(Register src, Register dst) 10824514f5e3Sopenharmony_ci{ 10834514f5e3Sopenharmony_ci EmitRexPrefix(src, dst); 10844514f5e3Sopenharmony_ci // 21 : And r/m64, r64 10854514f5e3Sopenharmony_ci EmitU8(0x21); 10864514f5e3Sopenharmony_ci EmitModrm(src, dst); 10874514f5e3Sopenharmony_ci} 10884514f5e3Sopenharmony_ci 10894514f5e3Sopenharmony_civoid AssemblerX64::Or(Immediate src, Register dst) 10904514f5e3Sopenharmony_ci{ 10914514f5e3Sopenharmony_ci EmitRexPrefixW(dst); 10924514f5e3Sopenharmony_ci if (InRange8(src.Value())) { 10934514f5e3Sopenharmony_ci // 83: or r/m64, imm8 10944514f5e3Sopenharmony_ci EmitU8(0x83); 10954514f5e3Sopenharmony_ci // 1: 83 /1 ib 10964514f5e3Sopenharmony_ci EmitModrm(1, dst); 10974514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(src.Value())); 10984514f5e3Sopenharmony_ci } else if (dst == rax) { 10994514f5e3Sopenharmony_ci // 0x0D: or rax, imm32 11004514f5e3Sopenharmony_ci EmitU8(0x0D); 11014514f5e3Sopenharmony_ci EmitI32(src.Value()); 11024514f5e3Sopenharmony_ci } else { 11034514f5e3Sopenharmony_ci // 81: or r/m64, imm32 11044514f5e3Sopenharmony_ci EmitU8(0x81); 11054514f5e3Sopenharmony_ci // 1: 81 /1 id 11064514f5e3Sopenharmony_ci EmitModrm(1, dst); 11074514f5e3Sopenharmony_ci EmitI32(src.Value()); 11084514f5e3Sopenharmony_ci } 11094514f5e3Sopenharmony_ci} 11104514f5e3Sopenharmony_ci 11114514f5e3Sopenharmony_civoid AssemblerX64::Orq(Register src, Register dst) 11124514f5e3Sopenharmony_ci{ 11134514f5e3Sopenharmony_ci EmitRexPrefix(src, dst); 11144514f5e3Sopenharmony_ci // 09 : Or r/m64, r64 11154514f5e3Sopenharmony_ci EmitU8(0x09); 11164514f5e3Sopenharmony_ci EmitModrm(src, dst); 11174514f5e3Sopenharmony_ci} 11184514f5e3Sopenharmony_ci 11194514f5e3Sopenharmony_civoid AssemblerX64::Jnz(Label *target, Distance distance) 11204514f5e3Sopenharmony_ci{ 11214514f5e3Sopenharmony_ci if (target->IsBound()) { 11224514f5e3Sopenharmony_ci int32_t offset = static_cast<int32_t>(target->GetPos() - GetCurrentPosition()); 11234514f5e3Sopenharmony_ci EmitJnz(offset); 11244514f5e3Sopenharmony_ci return; 11254514f5e3Sopenharmony_ci } 11264514f5e3Sopenharmony_ci auto pos = GetCurrentPosition(); 11274514f5e3Sopenharmony_ci int32_t emitPos = 0; 11284514f5e3Sopenharmony_ci if (distance == Distance::Near) { 11294514f5e3Sopenharmony_ci if (target->IsLinkedNear()) { 11304514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedNearPos() - pos); 11314514f5e3Sopenharmony_ci } 11324514f5e3Sopenharmony_ci // +1: skip opcode 11334514f5e3Sopenharmony_ci target->LinkNearPos(pos + 1); 11344514f5e3Sopenharmony_ci ASSERT(InRange8(emitPos)); 11354514f5e3Sopenharmony_ci // 75 : Jnz rel8; 11364514f5e3Sopenharmony_ci EmitU8(0x75); 11374514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(emitPos)); 11384514f5e3Sopenharmony_ci } else { 11394514f5e3Sopenharmony_ci if (target->IsLinked()) { 11404514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedPos()); 11414514f5e3Sopenharmony_ci } 11424514f5e3Sopenharmony_ci // 2: skip opcode 11434514f5e3Sopenharmony_ci target->LinkTo(pos + 2); 11444514f5e3Sopenharmony_ci // 0F 85 : Jnz rel32 11454514f5e3Sopenharmony_ci EmitU8(0x0F); 11464514f5e3Sopenharmony_ci EmitU8(0x85); 11474514f5e3Sopenharmony_ci EmitI32(emitPos); 11484514f5e3Sopenharmony_ci } 11494514f5e3Sopenharmony_ci} 11504514f5e3Sopenharmony_ci 11514514f5e3Sopenharmony_civoid AssemblerX64::Jle(Label *target, Distance distance) 11524514f5e3Sopenharmony_ci{ 11534514f5e3Sopenharmony_ci if (target->IsBound()) { 11544514f5e3Sopenharmony_ci int32_t offset = static_cast<int32_t>(target->GetPos() - GetCurrentPosition()); 11554514f5e3Sopenharmony_ci EmitJle(offset); 11564514f5e3Sopenharmony_ci return; 11574514f5e3Sopenharmony_ci } 11584514f5e3Sopenharmony_ci auto pos = GetCurrentPosition(); 11594514f5e3Sopenharmony_ci int32_t emitPos = 0; 11604514f5e3Sopenharmony_ci if (distance == Distance::Near) { 11614514f5e3Sopenharmony_ci if (target->IsLinkedNear()) { 11624514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedNearPos() - pos); 11634514f5e3Sopenharmony_ci } 11644514f5e3Sopenharmony_ci // +1: skip opcode 11654514f5e3Sopenharmony_ci target->LinkNearPos(pos + 1); 11664514f5e3Sopenharmony_ci ASSERT(InRange8(emitPos)); 11674514f5e3Sopenharmony_ci // 7E : Jle rel8; 11684514f5e3Sopenharmony_ci EmitU8(0x7E); 11694514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(emitPos)); 11704514f5e3Sopenharmony_ci } else { 11714514f5e3Sopenharmony_ci if (target->IsLinked()) { 11724514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedPos()); 11734514f5e3Sopenharmony_ci } 11744514f5e3Sopenharmony_ci // 2: skip opcode 11754514f5e3Sopenharmony_ci target->LinkTo(pos + 2); 11764514f5e3Sopenharmony_ci // 0F 8E: Jle rel32 11774514f5e3Sopenharmony_ci EmitU8(0x0F); 11784514f5e3Sopenharmony_ci EmitU8(0x8E); 11794514f5e3Sopenharmony_ci EmitI32(emitPos); 11804514f5e3Sopenharmony_ci } 11814514f5e3Sopenharmony_ci} 11824514f5e3Sopenharmony_ci 11834514f5e3Sopenharmony_civoid AssemblerX64::Jae(Label *target, Distance distance) 11844514f5e3Sopenharmony_ci{ 11854514f5e3Sopenharmony_ci if (target->IsBound()) { 11864514f5e3Sopenharmony_ci int32_t offset = static_cast<int32_t>(target->GetPos() - GetCurrentPosition()); 11874514f5e3Sopenharmony_ci EmitJae(offset); 11884514f5e3Sopenharmony_ci return; 11894514f5e3Sopenharmony_ci } 11904514f5e3Sopenharmony_ci auto pos = GetCurrentPosition(); 11914514f5e3Sopenharmony_ci int32_t emitPos = 0; 11924514f5e3Sopenharmony_ci if (distance == Distance::Near) { 11934514f5e3Sopenharmony_ci if (target->IsLinkedNear()) { 11944514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedNearPos() - pos); 11954514f5e3Sopenharmony_ci } 11964514f5e3Sopenharmony_ci // +1: skip opcode 11974514f5e3Sopenharmony_ci target->LinkNearPos(pos + 1); 11984514f5e3Sopenharmony_ci ASSERT(InRange8(emitPos)); 11994514f5e3Sopenharmony_ci // 73 : Jae rel8 12004514f5e3Sopenharmony_ci EmitU8(0x73); 12014514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(emitPos)); 12024514f5e3Sopenharmony_ci } else { 12034514f5e3Sopenharmony_ci if (target->IsLinked()) { 12044514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedPos()); 12054514f5e3Sopenharmony_ci } 12064514f5e3Sopenharmony_ci // 2: skip opcode 12074514f5e3Sopenharmony_ci target->LinkTo(pos + 2); 12084514f5e3Sopenharmony_ci // 0F 83: Jae rel32 12094514f5e3Sopenharmony_ci EmitU8(0x0F); 12104514f5e3Sopenharmony_ci EmitU8(0x83); 12114514f5e3Sopenharmony_ci EmitI32(emitPos); 12124514f5e3Sopenharmony_ci } 12134514f5e3Sopenharmony_ci} 12144514f5e3Sopenharmony_ci 12154514f5e3Sopenharmony_civoid AssemblerX64::Jg(Label *target, Distance distance) 12164514f5e3Sopenharmony_ci{ 12174514f5e3Sopenharmony_ci if (target->IsBound()) { 12184514f5e3Sopenharmony_ci int32_t offset = static_cast<int32_t>(target->GetPos() - GetCurrentPosition()); 12194514f5e3Sopenharmony_ci EmitJg(offset); 12204514f5e3Sopenharmony_ci return; 12214514f5e3Sopenharmony_ci } 12224514f5e3Sopenharmony_ci auto pos = GetCurrentPosition(); 12234514f5e3Sopenharmony_ci int32_t emitPos = 0; 12244514f5e3Sopenharmony_ci if (distance == Distance::Near) { 12254514f5e3Sopenharmony_ci if (target->IsLinkedNear()) { 12264514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedNearPos() - pos); 12274514f5e3Sopenharmony_ci } 12284514f5e3Sopenharmony_ci // +1: skip opcode 12294514f5e3Sopenharmony_ci target->LinkNearPos(pos + 1); 12304514f5e3Sopenharmony_ci ASSERT(InRange8(emitPos)); 12314514f5e3Sopenharmony_ci // 7F : Jg rel8 12324514f5e3Sopenharmony_ci EmitU8(0x7F); 12334514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(emitPos)); 12344514f5e3Sopenharmony_ci } else { 12354514f5e3Sopenharmony_ci if (target->IsLinked()) { 12364514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedPos()); 12374514f5e3Sopenharmony_ci } 12384514f5e3Sopenharmony_ci // 2: skip opcode 12394514f5e3Sopenharmony_ci target->LinkTo(pos + 2); 12404514f5e3Sopenharmony_ci // 0F 8F: Jae rel32 12414514f5e3Sopenharmony_ci EmitU8(0x0F); 12424514f5e3Sopenharmony_ci EmitU8(0x8F); 12434514f5e3Sopenharmony_ci EmitI32(emitPos); 12444514f5e3Sopenharmony_ci } 12454514f5e3Sopenharmony_ci} 12464514f5e3Sopenharmony_ci 12474514f5e3Sopenharmony_civoid AssemblerX64::Jge(Label *target, Distance distance) 12484514f5e3Sopenharmony_ci{ 12494514f5e3Sopenharmony_ci if (target->IsBound()) { 12504514f5e3Sopenharmony_ci int32_t offset = static_cast<int32_t>(target->GetPos() - GetCurrentPosition()); 12514514f5e3Sopenharmony_ci EmitJge(offset); 12524514f5e3Sopenharmony_ci return; 12534514f5e3Sopenharmony_ci } 12544514f5e3Sopenharmony_ci auto pos = GetCurrentPosition(); 12554514f5e3Sopenharmony_ci int32_t emitPos = 0; 12564514f5e3Sopenharmony_ci if (distance == Distance::Near) { 12574514f5e3Sopenharmony_ci if (target->IsLinkedNear()) { 12584514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedNearPos() - pos); 12594514f5e3Sopenharmony_ci } 12604514f5e3Sopenharmony_ci // +1: skip opcode 12614514f5e3Sopenharmony_ci target->LinkNearPos(pos + 1); 12624514f5e3Sopenharmony_ci ASSERT(InRange8(emitPos)); 12634514f5e3Sopenharmony_ci // 7F : Jg rel8 12644514f5e3Sopenharmony_ci EmitU8(0x7D); 12654514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(emitPos)); 12664514f5e3Sopenharmony_ci } else { 12674514f5e3Sopenharmony_ci if (target->IsLinked()) { 12684514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedPos()); 12694514f5e3Sopenharmony_ci } 12704514f5e3Sopenharmony_ci // 2: skip opcode 12714514f5e3Sopenharmony_ci target->LinkTo(pos + 2); 12724514f5e3Sopenharmony_ci // 0F 8F: Jae rel32 12734514f5e3Sopenharmony_ci EmitU8(0x0F); 12744514f5e3Sopenharmony_ci EmitU8(0x8D); 12754514f5e3Sopenharmony_ci EmitI32(emitPos); 12764514f5e3Sopenharmony_ci } 12774514f5e3Sopenharmony_ci} 12784514f5e3Sopenharmony_ci 12794514f5e3Sopenharmony_civoid AssemblerX64::Movzbq(const Operand &src, Register dst) 12804514f5e3Sopenharmony_ci{ 12814514f5e3Sopenharmony_ci EmitRexPrefix(dst, src); 12824514f5e3Sopenharmony_ci // 0F B6 : Movzx r64, r/m16 12834514f5e3Sopenharmony_ci EmitU8(0x0F); 12844514f5e3Sopenharmony_ci EmitU8(0xB6); 12854514f5e3Sopenharmony_ci // 0F B6 /r: Movzx r64, r/m16 12864514f5e3Sopenharmony_ci EmitOperand(dst, src); 12874514f5e3Sopenharmony_ci} 12884514f5e3Sopenharmony_ci 12894514f5e3Sopenharmony_civoid AssemblerX64::Movzbl(const Operand &src, Register dst) 12904514f5e3Sopenharmony_ci{ 12914514f5e3Sopenharmony_ci EmitRexPrefixl(dst, src); 12924514f5e3Sopenharmony_ci // 0F B6 : Movzx r64, r/m16 12934514f5e3Sopenharmony_ci EmitU8(0x0F); 12944514f5e3Sopenharmony_ci EmitU8(0xB6); 12954514f5e3Sopenharmony_ci // 0F B6 /r: Movzx r64, r/m16 12964514f5e3Sopenharmony_ci EmitOperand(dst, src); 12974514f5e3Sopenharmony_ci} 12984514f5e3Sopenharmony_ci 12994514f5e3Sopenharmony_civoid AssemblerX64::Movzbl(Register src, Register dst) 13004514f5e3Sopenharmony_ci{ 13014514f5e3Sopenharmony_ci EmitRexPrefixl(dst, src); 13024514f5e3Sopenharmony_ci // 0F B6 : Movzx r64, r/m16 13034514f5e3Sopenharmony_ci EmitU8(0x0F); 13044514f5e3Sopenharmony_ci EmitU8(0xB6); 13054514f5e3Sopenharmony_ci // 0F B6 /r: Movzx r64, r/m16 13064514f5e3Sopenharmony_ci EmitModrm(dst, src); 13074514f5e3Sopenharmony_ci} 13084514f5e3Sopenharmony_ci 13094514f5e3Sopenharmony_civoid AssemblerX64::Btq(Immediate src, Register dst) 13104514f5e3Sopenharmony_ci{ 13114514f5e3Sopenharmony_ci EmitRexPrefixW(dst); 13124514f5e3Sopenharmony_ci // 0F BA: bt r/m32, imm8; 13134514f5e3Sopenharmony_ci EmitU8(0x0F); 13144514f5e3Sopenharmony_ci EmitU8(0xBA); 13154514f5e3Sopenharmony_ci // /4: 0F BA bt r/m32, imm8 13164514f5e3Sopenharmony_ci EmitModrm(4, dst); 13174514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(src.Value())); 13184514f5e3Sopenharmony_ci} 13194514f5e3Sopenharmony_civoid AssemblerX64::Btl(Immediate src, Register dst) 13204514f5e3Sopenharmony_ci{ 13214514f5e3Sopenharmony_ci EmitRexPrefix(dst); 13224514f5e3Sopenharmony_ci // 0F BA: bt r/m32, imm8; 13234514f5e3Sopenharmony_ci EmitU8(0x0F); 13244514f5e3Sopenharmony_ci EmitU8(0xBA); 13254514f5e3Sopenharmony_ci // /4: 0F BA bt r/m32, imm8 13264514f5e3Sopenharmony_ci EmitModrm(4, dst); 13274514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(src.Value())); 13284514f5e3Sopenharmony_ci} 13294514f5e3Sopenharmony_ci 13304514f5e3Sopenharmony_civoid AssemblerX64::Movabs(uint64_t src, Register dst) 13314514f5e3Sopenharmony_ci{ 13324514f5e3Sopenharmony_ci // REX.W + B8 + rd io : Mov r64, imm64 13334514f5e3Sopenharmony_ci EmitRexPrefixW(dst); 13344514f5e3Sopenharmony_ci EmitU8(0xB8 | LowBits(dst)); 13354514f5e3Sopenharmony_ci EmitU64(src); 13364514f5e3Sopenharmony_ci} 13374514f5e3Sopenharmony_ci 13384514f5e3Sopenharmony_civoid AssemblerX64::Shll(Immediate src, Register dst) 13394514f5e3Sopenharmony_ci{ 13404514f5e3Sopenharmony_ci EmitRexPrefix(dst); 13414514f5e3Sopenharmony_ci // C1 : shl r/m32, imm8 13424514f5e3Sopenharmony_ci EmitU8(0xC1); 13434514f5e3Sopenharmony_ci // C1 /4 13444514f5e3Sopenharmony_ci EmitModrm(4, dst); 13454514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(src.Value())); 13464514f5e3Sopenharmony_ci} 13474514f5e3Sopenharmony_ci 13484514f5e3Sopenharmony_civoid AssemblerX64::Shlq(Immediate src, Register dst) 13494514f5e3Sopenharmony_ci{ 13504514f5e3Sopenharmony_ci EmitRexPrefixW(dst); 13514514f5e3Sopenharmony_ci // C1 : shl r/m64, imm8 13524514f5e3Sopenharmony_ci EmitU8(0xC1); 13534514f5e3Sopenharmony_ci // C1 /4 13544514f5e3Sopenharmony_ci EmitModrm(4, dst); 13554514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(src.Value())); 13564514f5e3Sopenharmony_ci} 13574514f5e3Sopenharmony_ci 13584514f5e3Sopenharmony_civoid AssemblerX64::Btsl(Register src, Register dst) 13594514f5e3Sopenharmony_ci{ 13604514f5e3Sopenharmony_ci EmitRexPrefixl(src, dst); 13614514f5e3Sopenharmony_ci // 0F AB: bts r32, r32; 13624514f5e3Sopenharmony_ci EmitU8(0x0F); 13634514f5e3Sopenharmony_ci EmitU8(0xAB); 13644514f5e3Sopenharmony_ci 13654514f5e3Sopenharmony_ci EmitModrm(src, dst); 13664514f5e3Sopenharmony_ci} 13674514f5e3Sopenharmony_ci 13684514f5e3Sopenharmony_civoid AssemblerX64::Int3() 13694514f5e3Sopenharmony_ci{ 13704514f5e3Sopenharmony_ci // CC :: INT3 13714514f5e3Sopenharmony_ci EmitU8(0xCC); 13724514f5e3Sopenharmony_ci} 13734514f5e3Sopenharmony_ci 13744514f5e3Sopenharmony_civoid AssemblerX64::Movzwq(const Operand &src, Register dst) 13754514f5e3Sopenharmony_ci{ 13764514f5e3Sopenharmony_ci EmitRexPrefix(dst, src); 13774514f5e3Sopenharmony_ci EmitU8(0x0F); 13784514f5e3Sopenharmony_ci EmitU8(0xB7); 13794514f5e3Sopenharmony_ci EmitOperand(dst, src); 13804514f5e3Sopenharmony_ci} 13814514f5e3Sopenharmony_ci 13824514f5e3Sopenharmony_civoid AssemblerX64::Jnb(Label *target, Distance distance) 13834514f5e3Sopenharmony_ci{ 13844514f5e3Sopenharmony_ci if (target->IsBound()) { 13854514f5e3Sopenharmony_ci int32_t offset = static_cast<int32_t>(target->GetPos() - GetCurrentPosition()); 13864514f5e3Sopenharmony_ci EmitJnb(offset); 13874514f5e3Sopenharmony_ci return; 13884514f5e3Sopenharmony_ci } 13894514f5e3Sopenharmony_ci auto pos = GetCurrentPosition(); 13904514f5e3Sopenharmony_ci int32_t emitPos = 0; 13914514f5e3Sopenharmony_ci if (distance == Distance::Near) { 13924514f5e3Sopenharmony_ci if (target->IsLinkedNear()) { 13934514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedNearPos() - pos); 13944514f5e3Sopenharmony_ci } 13954514f5e3Sopenharmony_ci // +1: skip opcode 13964514f5e3Sopenharmony_ci target->LinkNearPos(pos + 1); 13974514f5e3Sopenharmony_ci ASSERT(InRange8(emitPos)); 13984514f5e3Sopenharmony_ci // 73 : Jnb rel8 13994514f5e3Sopenharmony_ci EmitU8(0x73); 14004514f5e3Sopenharmony_ci EmitI8(static_cast<int8_t>(emitPos)); 14014514f5e3Sopenharmony_ci } else { 14024514f5e3Sopenharmony_ci if (target->IsLinked()) { 14034514f5e3Sopenharmony_ci emitPos = static_cast<int32_t>(target->GetLinkedPos()); 14044514f5e3Sopenharmony_ci } 14054514f5e3Sopenharmony_ci // 2: skip opcode 14064514f5e3Sopenharmony_ci target->LinkTo(pos + 2); 14074514f5e3Sopenharmony_ci // 0F 83: Jnb rel32 14084514f5e3Sopenharmony_ci EmitU8(0x0F); 14094514f5e3Sopenharmony_ci EmitU8(0x83); 14104514f5e3Sopenharmony_ci EmitI32(emitPos); 14114514f5e3Sopenharmony_ci } 14124514f5e3Sopenharmony_ci} 14134514f5e3Sopenharmony_ci} // panda::ecmascript::x64 1414