| // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #include "vm/globals.h" |
| #if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64) |
| |
| #include "vm/compiler/assembler/assembler.h" |
| #include "vm/cpu.h" |
| #include "vm/os.h" |
| #include "vm/unit_test.h" |
| #include "vm/virtual_memory.h" |
| |
| namespace dart { |
| namespace compiler { |
| #define __ assembler-> |
| |
| #if defined(PRODUCT) |
| #define EXPECT_DISASSEMBLY(expected) |
| #else |
| #define EXPECT_DISASSEMBLY(expected) \ |
| EXPECT_STREQ(expected, test->RelativeDisassembly()) |
| #endif |
| |
| // Called from assembler_test.cc. |
| // RA: return address. |
| // A0: value. |
| // A1: growable array. |
| // A2: current thread. |
| ASSEMBLER_TEST_GENERATE(StoreIntoObject, assembler) { |
| __ PushRegister(RA); |
| __ PushNativeCalleeSavedRegisters(); |
| |
| __ mv(THR, A2); |
| __ lx(WRITE_BARRIER_MASK, Address(THR, Thread::write_barrier_mask_offset())); |
| |
| __ StoreIntoObject(A1, FieldAddress(A1, GrowableObjectArray::data_offset()), |
| A0); |
| |
| __ PopNativeCalleeSavedRegisters(); |
| __ PopRegister(RA); |
| __ ret(); |
| } |
| |
| static intx_t Call(intx_t entry, |
| intx_t arg0 = 0, |
| intx_t arg1 = 0, |
| intx_t arg2 = 0, |
| intx_t arg3 = 0) { |
| #if defined(USING_SIMULATOR) |
| return Simulator::Current()->Call(entry, arg0, arg1, arg2, arg3); |
| #else |
| typedef intx_t (*F)(intx_t, intx_t, intx_t, intx_t); |
| return reinterpret_cast<F>(entry)(arg0, arg1, arg2, arg3); |
| #endif |
| } |
| static float CallF(intx_t entry, intx_t arg0) { |
| #if defined(USING_SIMULATOR) |
| return Simulator::Current()->CallF(entry, arg0); |
| #else |
| typedef float (*F)(intx_t); |
| return reinterpret_cast<F>(entry)(arg0); |
| #endif |
| } |
| static float CallF(intx_t entry, intx_t arg0, float arg1) { |
| #if defined(USING_SIMULATOR) |
| return Simulator::Current()->CallF(entry, arg0, arg1); |
| #else |
| typedef float (*F)(intx_t, float); |
| return reinterpret_cast<F>(entry)(arg0, arg1); |
| #endif |
| } |
| static float CallF(intx_t entry, double arg0) { |
| #if defined(USING_SIMULATOR) |
| return Simulator::Current()->CallF(entry, arg0); |
| #else |
| typedef float (*F)(double); |
| return reinterpret_cast<F>(entry)(arg0); |
| #endif |
| } |
| static float CallF(intx_t entry, float arg0) { |
| #if defined(USING_SIMULATOR) |
| return Simulator::Current()->CallF(entry, arg0); |
| #else |
| typedef float (*F)(float); |
| return reinterpret_cast<F>(entry)(arg0); |
| #endif |
| } |
| static float CallF(intx_t entry, float arg0, float arg1) { |
| #if defined(USING_SIMULATOR) |
| return Simulator::Current()->CallF(entry, arg0, arg1); |
| #else |
| typedef float (*F)(float, float); |
| return reinterpret_cast<F>(entry)(arg0, arg1); |
| #endif |
| } |
| static float CallF(intx_t entry, float arg0, float arg1, float arg2) { |
| #if defined(USING_SIMULATOR) |
| return Simulator::Current()->CallF(entry, arg0, arg1, arg2); |
| #else |
| typedef float (*F)(float, float, float); |
| return reinterpret_cast<F>(entry)(arg0, arg1, arg2); |
| #endif |
| } |
| static intx_t CallI(intx_t entry, float arg0) { |
| #if defined(USING_SIMULATOR) |
| return Simulator::Current()->CallI(entry, arg0); |
| #else |
| typedef intx_t (*F)(float); |
| return reinterpret_cast<F>(entry)(arg0); |
| #endif |
| } |
| static intx_t CallI(intx_t entry, float arg0, float arg1) { |
| #if defined(USING_SIMULATOR) |
| return Simulator::Current()->CallI(entry, arg0, arg1); |
| #else |
| typedef intx_t (*F)(float, float); |
| return reinterpret_cast<F>(entry)(arg0, arg1); |
| #endif |
| } |
| static double CallD(intx_t entry, intx_t arg0) { |
| #if defined(USING_SIMULATOR) |
| return Simulator::Current()->CallD(entry, arg0); |
| #else |
| typedef double (*F)(intx_t); |
| return reinterpret_cast<F>(entry)(arg0); |
| #endif |
| } |
| static double CallD(intx_t entry, intx_t arg0, double arg1) { |
| #if defined(USING_SIMULATOR) |
| return Simulator::Current()->CallD(entry, arg0, arg1); |
| #else |
| typedef double (*F)(intx_t, double); |
| return reinterpret_cast<F>(entry)(arg0, arg1); |
| #endif |
| } |
| static double CallD(intx_t entry, float arg0) { |
| #if defined(USING_SIMULATOR) |
| return Simulator::Current()->CallD(entry, arg0); |
| #else |
| typedef double (*F)(float); |
| return reinterpret_cast<F>(entry)(arg0); |
| #endif |
| } |
| static double CallD(intx_t entry, double arg0) { |
| #if defined(USING_SIMULATOR) |
| return Simulator::Current()->CallD(entry, arg0); |
| #else |
| typedef double (*F)(double); |
| return reinterpret_cast<F>(entry)(arg0); |
| #endif |
| } |
| static double CallD(intx_t entry, double arg0, double arg1) { |
| #if defined(USING_SIMULATOR) |
| return Simulator::Current()->CallD(entry, arg0, arg1); |
| #else |
| typedef double (*F)(double, double); |
| return reinterpret_cast<F>(entry)(arg0, arg1); |
| #endif |
| } |
| static double CallD(intx_t entry, double arg0, double arg1, double arg2) { |
| #if defined(USING_SIMULATOR) |
| return Simulator::Current()->CallD(entry, arg0, arg1, arg2); |
| #else |
| typedef double (*F)(double, double, double); |
| return reinterpret_cast<F>(entry)(arg0, arg1, arg2); |
| #endif |
| } |
| static intx_t CallI(intx_t entry, double arg0) { |
| #if defined(USING_SIMULATOR) |
| return Simulator::Current()->CallI(entry, arg0); |
| #else |
| typedef intx_t (*F)(double); |
| return reinterpret_cast<F>(entry)(arg0); |
| #endif |
| } |
| static intx_t CallI(intx_t entry, double arg0, double arg1) { |
| #if defined(USING_SIMULATOR) |
| return Simulator::Current()->CallI(entry, arg0, arg1); |
| #else |
| typedef intx_t (*F)(double, double); |
| return reinterpret_cast<F>(entry)(arg0, arg1); |
| #endif |
| } |
| |
| ASSEMBLER_TEST_GENERATE(LoadUpperImmediate, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| __ lui(A0, 42 << 16); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadUpperImmediate, test) { |
| EXPECT_DISASSEMBLY( |
| "002a0537 lui a0, 2752512\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(42 << 16, Call(test->entry())); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(AddUpperImmediatePC, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| __ auipc(A0, 0); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(AddUpperImmediatePC, test) { |
| EXPECT_DISASSEMBLY( |
| "00000517 auipc a0, 0\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(test->entry(), static_cast<uintx_t>(Call(test->entry()))); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(JumpAndLink, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| Label label1, label2; |
| __ jal(T4, &label1); // Forward. |
| __ sub(A0, T0, T1); |
| __ ret(); |
| __ trap(); |
| |
| __ Bind(&label2); |
| __ li(T1, 7); |
| __ jalr(ZR, T5); |
| __ trap(); |
| |
| __ Bind(&label1); |
| __ li(T0, 4); |
| __ jal(T5, &label2); // Backward. |
| __ jalr(ZR, T4); |
| __ trap(); |
| } |
| ASSEMBLER_TEST_RUN(JumpAndLink, test) { |
| EXPECT_DISASSEMBLY( |
| "01c00eef jal t4, +28\n" |
| "40628533 sub a0, t0, t1\n" |
| "00008067 ret\n" |
| "00000000 trap\n" |
| "00700313 li t1, 7\n" |
| "000f0067 jr t5\n" |
| "00000000 trap\n" |
| "00400293 li t0, 4\n" |
| "ff1fff6f jal t5, -16\n" |
| "000e8067 jr t4\n" |
| "00000000 trap\n"); |
| EXPECT_EQ(-3, Call(test->entry())); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(Jump, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| Label label1, label2; |
| __ j(&label1); // Forward. |
| __ trap(); |
| __ Bind(&label2); |
| __ li(T1, 7); |
| __ sub(A0, T0, T1); |
| __ ret(); |
| __ Bind(&label1); |
| __ li(T0, 4); |
| __ j(&label2); // Backward. |
| __ trap(); |
| } |
| ASSEMBLER_TEST_RUN(Jump, test) { |
| EXPECT_DISASSEMBLY( |
| "0140006f j +20\n" |
| "00000000 trap\n" |
| "00700313 li t1, 7\n" |
| "40628533 sub a0, t0, t1\n" |
| "00008067 ret\n" |
| "00400293 li t0, 4\n" |
| "ff1ff06f j -16\n" |
| "00000000 trap\n"); |
| EXPECT_EQ(-3, Call(test->entry())); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(JumpAndLinkRegister, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| /* 00 */ __ jalr(T4, A1, 28); // Forward. |
| /* 04 */ __ sub(A0, T0, T1); |
| /* 08 */ __ ret(); |
| /* 12 */ __ trap(); |
| |
| /* 16 */ __ li(T1, 7); |
| /* 20 */ __ jalr(ZR, T5); |
| /* 24 */ __ trap(); |
| |
| /* 28 */ __ li(T0, 4); |
| /* 32 */ __ jalr(T5, A1, 16); // Backward. |
| /* 36 */ __ jalr(ZR, T4); |
| /* 40 */ __ trap(); |
| } |
| ASSEMBLER_TEST_RUN(JumpAndLinkRegister, test) { |
| EXPECT_DISASSEMBLY( |
| "01c58ee7 jalr t4, 28(a1)\n" |
| "40628533 sub a0, t0, t1\n" |
| "00008067 ret\n" |
| "00000000 trap\n" |
| "00700313 li t1, 7\n" |
| "000f0067 jr t5\n" |
| "00000000 trap\n" |
| "00400293 li t0, 4\n" |
| "01058f67 jalr t5, 16(a1)\n" |
| "000e8067 jr t4\n" |
| "00000000 trap\n"); |
| EXPECT_EQ(-3, Call(test->entry(), 0, test->entry())); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(JumpRegister, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| /* 00 */ __ jr(A1, 20); // Forward. |
| /* 04 */ __ trap(); |
| /* 08 */ __ li(T1, 7); |
| /* 12 */ __ sub(A0, T0, T1); |
| /* 16 */ __ ret(); |
| /* 20 */ __ li(T0, 4); |
| /* 24 */ __ jr(A1, 8); // Backward. |
| /* 28 */ __ trap(); |
| } |
| ASSEMBLER_TEST_RUN(JumpRegister, test) { |
| EXPECT_DISASSEMBLY( |
| "01458067 jr 20(a1)\n" |
| "00000000 trap\n" |
| "00700313 li t1, 7\n" |
| "40628533 sub a0, t0, t1\n" |
| "00008067 ret\n" |
| "00400293 li t0, 4\n" |
| "00858067 jr 8(a1)\n" |
| "00000000 trap\n"); |
| EXPECT_EQ(-3, Call(test->entry(), 0, test->entry())); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchEqualForward, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| Label label; |
| __ beq(A0, A1, &label); |
| __ li(A0, 3); |
| __ ret(); |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchEqualForward, test) { |
| EXPECT_DISASSEMBLY( |
| "00b50663 beq a0, a1, +12\n" |
| "00300513 li a0, 3\n" |
| "00008067 ret\n" |
| "00400513 li a0, 4\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(4, Call(test->entry(), 1, 1)); |
| EXPECT_EQ(3, Call(test->entry(), 1, 0)); |
| EXPECT_EQ(3, Call(test->entry(), 1, -1)); |
| EXPECT_EQ(3, Call(test->entry(), 0, 1)); |
| EXPECT_EQ(4, Call(test->entry(), 0, 0)); |
| EXPECT_EQ(3, Call(test->entry(), 0, -1)); |
| EXPECT_EQ(3, Call(test->entry(), -1, 1)); |
| EXPECT_EQ(3, Call(test->entry(), -1, 0)); |
| EXPECT_EQ(4, Call(test->entry(), -1, -1)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchEqualForwardFar, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| Label label; |
| __ beq(A0, A1, &label); |
| __ li(A0, 3); |
| __ ret(); |
| for (intptr_t i = 0; i < (1 << 13); i++) { |
| __ ebreak(); |
| } |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchEqualForwardFar, test) { |
| // EXPECT_DISASSEMBLY(constant too big); |
| EXPECT_EQ(4, Call(test->entry(), 1, 1)); |
| EXPECT_EQ(3, Call(test->entry(), 1, 0)); |
| EXPECT_EQ(3, Call(test->entry(), 1, -1)); |
| EXPECT_EQ(3, Call(test->entry(), 0, 1)); |
| EXPECT_EQ(4, Call(test->entry(), 0, 0)); |
| EXPECT_EQ(3, Call(test->entry(), 0, -1)); |
| EXPECT_EQ(3, Call(test->entry(), -1, 1)); |
| EXPECT_EQ(3, Call(test->entry(), -1, 0)); |
| EXPECT_EQ(4, Call(test->entry(), -1, -1)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchNotEqualForward, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| Label label; |
| __ bne(A0, A1, &label); |
| __ li(A0, 3); |
| __ ret(); |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchNotEqualForward, test) { |
| EXPECT_DISASSEMBLY( |
| "00b51663 bne a0, a1, +12\n" |
| "00300513 li a0, 3\n" |
| "00008067 ret\n" |
| "00400513 li a0, 4\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(3, Call(test->entry(), 1, 1)); |
| EXPECT_EQ(4, Call(test->entry(), 1, 0)); |
| EXPECT_EQ(4, Call(test->entry(), 1, -1)); |
| EXPECT_EQ(4, Call(test->entry(), 0, 1)); |
| EXPECT_EQ(3, Call(test->entry(), 0, 0)); |
| EXPECT_EQ(4, Call(test->entry(), 0, -1)); |
| EXPECT_EQ(4, Call(test->entry(), -1, 1)); |
| EXPECT_EQ(4, Call(test->entry(), -1, 0)); |
| EXPECT_EQ(3, Call(test->entry(), -1, -1)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchNotEqualForwardFar, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| Label label; |
| __ bne(A0, A1, &label); |
| __ li(A0, 3); |
| __ ret(); |
| for (intptr_t i = 0; i < (1 << 13); i++) { |
| __ ebreak(); |
| } |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchNotEqualForwardFar, test) { |
| // EXPECT_DISASSEMBLY(constant too big); |
| EXPECT_EQ(3, Call(test->entry(), 1, 1)); |
| EXPECT_EQ(4, Call(test->entry(), 1, 0)); |
| EXPECT_EQ(4, Call(test->entry(), 1, -1)); |
| EXPECT_EQ(4, Call(test->entry(), 0, 1)); |
| EXPECT_EQ(3, Call(test->entry(), 0, 0)); |
| EXPECT_EQ(4, Call(test->entry(), 0, -1)); |
| EXPECT_EQ(4, Call(test->entry(), -1, 1)); |
| EXPECT_EQ(4, Call(test->entry(), -1, 0)); |
| EXPECT_EQ(3, Call(test->entry(), -1, -1)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchLessThanForward, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| Label label; |
| __ blt(A0, A1, &label); |
| __ li(A0, 3); |
| __ ret(); |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchLessThanForward, test) { |
| EXPECT_DISASSEMBLY( |
| "00b54663 blt a0, a1, +12\n" |
| "00300513 li a0, 3\n" |
| "00008067 ret\n" |
| "00400513 li a0, 4\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(3, Call(test->entry(), 1, 1)); |
| EXPECT_EQ(3, Call(test->entry(), 1, 0)); |
| EXPECT_EQ(3, Call(test->entry(), 1, -1)); |
| EXPECT_EQ(4, Call(test->entry(), 0, 1)); |
| EXPECT_EQ(3, Call(test->entry(), 0, 0)); |
| EXPECT_EQ(3, Call(test->entry(), 0, -1)); |
| EXPECT_EQ(4, Call(test->entry(), -1, 1)); |
| EXPECT_EQ(4, Call(test->entry(), -1, 0)); |
| EXPECT_EQ(3, Call(test->entry(), -1, -1)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchLessThanForwardFar, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| Label label; |
| __ blt(A0, A1, &label); |
| __ li(A0, 3); |
| __ ret(); |
| for (intptr_t i = 0; i < (1 << 13); i++) { |
| __ ebreak(); |
| } |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchLessThanForwardFar, test) { |
| // EXPECT_DISASSEMBLY(constant too big); |
| EXPECT_EQ(3, Call(test->entry(), 1, 1)); |
| EXPECT_EQ(3, Call(test->entry(), 1, 0)); |
| EXPECT_EQ(3, Call(test->entry(), 1, -1)); |
| EXPECT_EQ(4, Call(test->entry(), 0, 1)); |
| EXPECT_EQ(3, Call(test->entry(), 0, 0)); |
| EXPECT_EQ(3, Call(test->entry(), 0, -1)); |
| EXPECT_EQ(4, Call(test->entry(), -1, 1)); |
| EXPECT_EQ(4, Call(test->entry(), -1, 0)); |
| EXPECT_EQ(3, Call(test->entry(), -1, -1)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchLessOrEqualForward, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| Label label; |
| __ ble(A0, A1, &label); |
| __ li(A0, 3); |
| __ ret(); |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchLessOrEqualForward, test) { |
| EXPECT_DISASSEMBLY( |
| "00a5d663 ble a0, a1, +12\n" |
| "00300513 li a0, 3\n" |
| "00008067 ret\n" |
| "00400513 li a0, 4\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(4, Call(test->entry(), 1, 1)); |
| EXPECT_EQ(3, Call(test->entry(), 1, 0)); |
| EXPECT_EQ(3, Call(test->entry(), 1, -1)); |
| EXPECT_EQ(4, Call(test->entry(), 0, 1)); |
| EXPECT_EQ(4, Call(test->entry(), 0, 0)); |
| EXPECT_EQ(3, Call(test->entry(), 0, -1)); |
| EXPECT_EQ(4, Call(test->entry(), -1, 1)); |
| EXPECT_EQ(4, Call(test->entry(), -1, 0)); |
| EXPECT_EQ(4, Call(test->entry(), -1, -1)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchLessOrEqualForwardFar, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| Label label; |
| __ ble(A0, A1, &label); |
| __ li(A0, 3); |
| __ ret(); |
| for (intptr_t i = 0; i < (1 << 13); i++) { |
| __ ebreak(); |
| } |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchLessOrEqualForwardFar, test) { |
| // EXPECT_DISASSEMBLY(constant too big); |
| EXPECT_EQ(4, Call(test->entry(), 1, 1)); |
| EXPECT_EQ(3, Call(test->entry(), 1, 0)); |
| EXPECT_EQ(3, Call(test->entry(), 1, -1)); |
| EXPECT_EQ(4, Call(test->entry(), 0, 1)); |
| EXPECT_EQ(4, Call(test->entry(), 0, 0)); |
| EXPECT_EQ(3, Call(test->entry(), 0, -1)); |
| EXPECT_EQ(4, Call(test->entry(), -1, 1)); |
| EXPECT_EQ(4, Call(test->entry(), -1, 0)); |
| EXPECT_EQ(4, Call(test->entry(), -1, -1)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchGreaterThanForward, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| Label label; |
| __ bgt(A0, A1, &label); |
| __ li(A0, 3); |
| __ ret(); |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchGreaterThanForward, test) { |
| EXPECT_DISASSEMBLY( |
| "00a5c663 blt a1, a0, +12\n" |
| "00300513 li a0, 3\n" |
| "00008067 ret\n" |
| "00400513 li a0, 4\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(3, Call(test->entry(), 1, 1)); |
| EXPECT_EQ(4, Call(test->entry(), 1, 0)); |
| EXPECT_EQ(4, Call(test->entry(), 1, -1)); |
| EXPECT_EQ(3, Call(test->entry(), 0, 1)); |
| EXPECT_EQ(3, Call(test->entry(), 0, 0)); |
| EXPECT_EQ(4, Call(test->entry(), 0, -1)); |
| EXPECT_EQ(3, Call(test->entry(), -1, 1)); |
| EXPECT_EQ(3, Call(test->entry(), -1, 0)); |
| EXPECT_EQ(3, Call(test->entry(), -1, -1)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchGreaterOrEqualForward, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| Label label; |
| __ bge(A0, A1, &label); |
| __ li(A0, 3); |
| __ ret(); |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchGreaterOrEqualForward, test) { |
| EXPECT_DISASSEMBLY( |
| "00b55663 ble a1, a0, +12\n" |
| "00300513 li a0, 3\n" |
| "00008067 ret\n" |
| "00400513 li a0, 4\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(4, Call(test->entry(), 1, 1)); |
| EXPECT_EQ(4, Call(test->entry(), 1, 0)); |
| EXPECT_EQ(4, Call(test->entry(), 1, -1)); |
| EXPECT_EQ(3, Call(test->entry(), 0, 1)); |
| EXPECT_EQ(4, Call(test->entry(), 0, 0)); |
| EXPECT_EQ(4, Call(test->entry(), 0, -1)); |
| EXPECT_EQ(3, Call(test->entry(), -1, 1)); |
| EXPECT_EQ(3, Call(test->entry(), -1, 0)); |
| EXPECT_EQ(4, Call(test->entry(), -1, -1)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchLessThanUnsignedForward, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| Label label; |
| __ bltu(A0, A1, &label); |
| __ li(A0, 3); |
| __ ret(); |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchLessThanUnsignedForward, test) { |
| EXPECT_DISASSEMBLY( |
| "00b56663 bltu a0, a1, +12\n" |
| "00300513 li a0, 3\n" |
| "00008067 ret\n" |
| "00400513 li a0, 4\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(3, Call(test->entry(), 1, 1)); |
| EXPECT_EQ(3, Call(test->entry(), 1, 0)); |
| EXPECT_EQ(4, Call(test->entry(), 1, -1)); |
| EXPECT_EQ(4, Call(test->entry(), 0, 1)); |
| EXPECT_EQ(3, Call(test->entry(), 0, 0)); |
| EXPECT_EQ(4, Call(test->entry(), 0, -1)); |
| EXPECT_EQ(3, Call(test->entry(), -1, 1)); |
| EXPECT_EQ(3, Call(test->entry(), -1, 0)); |
| EXPECT_EQ(3, Call(test->entry(), -1, -1)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchLessOrEqualUnsignedForward, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| Label label; |
| __ bleu(A0, A1, &label); |
| __ li(A0, 3); |
| __ ret(); |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchLessOrEqualUnsignedForward, test) { |
| EXPECT_DISASSEMBLY( |
| "00a5f663 bleu a0, a1, +12\n" |
| "00300513 li a0, 3\n" |
| "00008067 ret\n" |
| "00400513 li a0, 4\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(4, Call(test->entry(), 1, 1)); |
| EXPECT_EQ(3, Call(test->entry(), 1, 0)); |
| EXPECT_EQ(4, Call(test->entry(), 1, -1)); |
| EXPECT_EQ(4, Call(test->entry(), 0, 1)); |
| EXPECT_EQ(4, Call(test->entry(), 0, 0)); |
| EXPECT_EQ(4, Call(test->entry(), 0, -1)); |
| EXPECT_EQ(3, Call(test->entry(), -1, 1)); |
| EXPECT_EQ(3, Call(test->entry(), -1, 0)); |
| EXPECT_EQ(4, Call(test->entry(), -1, -1)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchGreaterThanUnsignedForward, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| Label label; |
| __ bgtu(A0, A1, &label); |
| __ li(A0, 3); |
| __ ret(); |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchGreaterThanUnsignedForward, test) { |
| EXPECT_DISASSEMBLY( |
| "00a5e663 bltu a1, a0, +12\n" |
| "00300513 li a0, 3\n" |
| "00008067 ret\n" |
| "00400513 li a0, 4\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(3, Call(test->entry(), 1, 1)); |
| EXPECT_EQ(4, Call(test->entry(), 1, 0)); |
| EXPECT_EQ(3, Call(test->entry(), 1, -1)); |
| EXPECT_EQ(3, Call(test->entry(), 0, 1)); |
| EXPECT_EQ(3, Call(test->entry(), 0, 0)); |
| EXPECT_EQ(3, Call(test->entry(), 0, -1)); |
| EXPECT_EQ(4, Call(test->entry(), -1, 1)); |
| EXPECT_EQ(4, Call(test->entry(), -1, 0)); |
| EXPECT_EQ(3, Call(test->entry(), -1, -1)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchGreaterOrEqualUnsignedForward, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| |
| Label label; |
| __ bgeu(A0, A1, &label); |
| __ li(A0, 3); |
| __ ret(); |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchGreaterOrEqualUnsignedForward, test) { |
| EXPECT_DISASSEMBLY( |
| "00b57663 bleu a1, a0, +12\n" |
| "00300513 li a0, 3\n" |
| "00008067 ret\n" |
| "00400513 li a0, 4\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(4, Call(test->entry(), 1, 1)); |
| EXPECT_EQ(4, Call(test->entry(), 1, 0)); |
| EXPECT_EQ(3, Call(test->entry(), 1, -1)); |
| EXPECT_EQ(3, Call(test->entry(), 0, 1)); |
| EXPECT_EQ(4, Call(test->entry(), 0, 0)); |
| EXPECT_EQ(3, Call(test->entry(), 0, -1)); |
| EXPECT_EQ(4, Call(test->entry(), -1, 1)); |
| EXPECT_EQ(4, Call(test->entry(), -1, 0)); |
| EXPECT_EQ(4, Call(test->entry(), -1, -1)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(LoadByte_0, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ lb(A0, Address(A0, 0)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadByte_0, test) { |
| EXPECT_DISASSEMBLY( |
| "00050503 lb a0, 0(a0)\n" |
| "00008067 ret\n"); |
| |
| uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t))); |
| values[0] = 0xAB; |
| values[1] = 0xCD; |
| values[2] = 0xEF; |
| EXPECT_EQ(-51, Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| free(values); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(LoadByte_Pos, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ lb(A0, Address(A0, 1)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadByte_Pos, test) { |
| EXPECT_DISASSEMBLY( |
| "00150503 lb a0, 1(a0)\n" |
| "00008067 ret\n"); |
| |
| uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t))); |
| values[0] = 0xAB; |
| values[1] = 0xCD; |
| values[2] = 0xEF; |
| |
| EXPECT_EQ(-17, Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| free(values); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(LoadByte_Neg, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ lb(A0, Address(A0, -1)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadByte_Neg, test) { |
| EXPECT_DISASSEMBLY( |
| "fff50503 lb a0, -1(a0)\n" |
| "00008067 ret\n"); |
| |
| uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t))); |
| values[0] = 0xAB; |
| values[1] = 0xCD; |
| values[2] = 0xEF; |
| |
| EXPECT_EQ(-85, Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| free(values); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(LoadByteUnsigned_0, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ lbu(A0, Address(A0, 0)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadByteUnsigned_0, test) { |
| EXPECT_DISASSEMBLY( |
| "00054503 lbu a0, 0(a0)\n" |
| "00008067 ret\n"); |
| |
| uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t))); |
| values[0] = 0xAB; |
| values[1] = 0xCD; |
| values[2] = 0xEF; |
| |
| EXPECT_EQ(0xCD, Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| free(values); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(LoadByteUnsigned_Pos, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ lbu(A0, Address(A0, 1)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadByteUnsigned_Pos, test) { |
| EXPECT_DISASSEMBLY( |
| "00154503 lbu a0, 1(a0)\n" |
| "00008067 ret\n"); |
| |
| uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t))); |
| values[0] = 0xAB; |
| values[1] = 0xCD; |
| values[2] = 0xEF; |
| |
| EXPECT_EQ(0xEF, Call(test->entry(), reinterpret_cast<intx_t>((&values[1])))); |
| free(values); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(LoadByteUnsigned_Neg, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ lbu(A0, Address(A0, -1)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadByteUnsigned_Neg, test) { |
| EXPECT_DISASSEMBLY( |
| "fff54503 lbu a0, -1(a0)\n" |
| "00008067 ret\n"); |
| |
| uint8_t* values = reinterpret_cast<uint8_t*>(malloc(3 * sizeof(uint8_t))); |
| values[0] = 0xAB; |
| values[1] = 0xCD; |
| values[2] = 0xEF; |
| |
| EXPECT_EQ(0xAB, Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(LoadHalfword_0, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ lh(A0, Address(A0, 0)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadHalfword_0, test) { |
| EXPECT_DISASSEMBLY( |
| "00051503 lh a0, 0(a0)\n" |
| "00008067 ret\n"); |
| |
| uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t))); |
| values[0] = 0xAB01; |
| values[1] = 0xCD02; |
| values[2] = 0xEF03; |
| |
| EXPECT_EQ(-13054, Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| } |
| ASSEMBLER_TEST_GENERATE(LoadHalfword_Pos, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ lh(A0, Address(A0, 2)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadHalfword_Pos, test) { |
| EXPECT_DISASSEMBLY( |
| "00251503 lh a0, 2(a0)\n" |
| "00008067 ret\n"); |
| |
| uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t))); |
| values[0] = 0xAB01; |
| values[1] = 0xCD02; |
| values[2] = 0xEF03; |
| |
| EXPECT_EQ(-4349, Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| } |
| ASSEMBLER_TEST_GENERATE(LoadHalfword_Neg, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ lh(A0, Address(A0, -2)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadHalfword_Neg, test) { |
| EXPECT_DISASSEMBLY( |
| "ffe51503 lh a0, -2(a0)\n" |
| "00008067 ret\n"); |
| |
| uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t))); |
| values[0] = 0xAB01; |
| values[1] = 0xCD02; |
| values[2] = 0xEF03; |
| |
| EXPECT_EQ(-21759, Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(LoadHalfwordUnsigned_0, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ lhu(A0, Address(A0, 0)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadHalfwordUnsigned_0, test) { |
| EXPECT_DISASSEMBLY( |
| "00055503 lhu a0, 0(a0)\n" |
| "00008067 ret\n"); |
| |
| uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t))); |
| values[0] = 0xAB01; |
| values[1] = 0xCD02; |
| values[2] = 0xEF03; |
| |
| EXPECT_EQ(0xCD02, Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(LoadHalfwordUnsigned_Pos, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ lhu(A0, Address(A0, 2)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadHalfwordUnsigned_Pos, test) { |
| EXPECT_DISASSEMBLY( |
| "00255503 lhu a0, 2(a0)\n" |
| "00008067 ret\n"); |
| |
| uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t))); |
| values[0] = 0xAB01; |
| values[1] = 0xCD02; |
| values[2] = 0xEF03; |
| |
| EXPECT_EQ(0xEF03, Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| } |
| ASSEMBLER_TEST_GENERATE(LoadHalfwordUnsigned_Neg, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ lhu(A0, Address(A0, -2)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadHalfwordUnsigned_Neg, test) { |
| EXPECT_DISASSEMBLY( |
| "ffe55503 lhu a0, -2(a0)\n" |
| "00008067 ret\n"); |
| |
| uint16_t* values = reinterpret_cast<uint16_t*>(malloc(3 * sizeof(uint16_t))); |
| values[0] = 0xAB01; |
| values[1] = 0xCD02; |
| values[2] = 0xEF03; |
| |
| EXPECT_EQ(0xAB01, Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(LoadWord_0, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ lw(A0, Address(A0, 0)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadWord_0, test) { |
| EXPECT_DISASSEMBLY( |
| "00052503 lw a0, 0(a0)\n" |
| "00008067 ret\n"); |
| |
| uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t))); |
| values[0] = 0xAB010203; |
| values[1] = 0xCD020405; |
| values[2] = 0xEF030607; |
| |
| EXPECT_EQ(-855505915, |
| Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| } |
| ASSEMBLER_TEST_GENERATE(LoadWord_Pos, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ lw(A0, Address(A0, 4)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadWord_Pos, test) { |
| EXPECT_DISASSEMBLY( |
| "00452503 lw a0, 4(a0)\n" |
| "00008067 ret\n"); |
| |
| uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t))); |
| values[0] = 0xAB010203; |
| values[1] = 0xCD020405; |
| values[2] = 0xEF030607; |
| |
| EXPECT_EQ(-285014521, |
| Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| } |
| ASSEMBLER_TEST_GENERATE(LoadWord_Neg, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ lw(A0, Address(A0, -4)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadWord_Neg, test) { |
| EXPECT_DISASSEMBLY( |
| "ffc52503 lw a0, -4(a0)\n" |
| "00008067 ret\n"); |
| |
| uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t))); |
| values[0] = 0xAB010203; |
| values[1] = 0xCD020405; |
| values[2] = 0xEF030607; |
| |
| EXPECT_EQ(-1425997309, |
| Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(StoreWord_0, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sw(A1, Address(A0, 0)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(StoreWord_0, test) { |
| EXPECT_DISASSEMBLY( |
| "00b52023 sw a1, 0(a0)\n" |
| "00008067 ret\n"); |
| |
| uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t))); |
| values[0] = 0; |
| values[1] = 0; |
| values[2] = 0; |
| |
| Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xCD020405); |
| EXPECT_EQ(0u, values[0]); |
| EXPECT_EQ(0xCD020405, values[1]); |
| EXPECT_EQ(0u, values[2]); |
| } |
| ASSEMBLER_TEST_GENERATE(StoreWord_Pos, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sw(A1, Address(A0, 4)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(StoreWord_Pos, test) { |
| EXPECT_DISASSEMBLY( |
| "00b52223 sw a1, 4(a0)\n" |
| "00008067 ret\n"); |
| |
| uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t))); |
| values[0] = 0; |
| values[1] = 0; |
| values[2] = 0; |
| |
| Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xEF030607); |
| EXPECT_EQ(0u, values[0]); |
| EXPECT_EQ(0u, values[1]); |
| EXPECT_EQ(0xEF030607, values[2]); |
| } |
| ASSEMBLER_TEST_GENERATE(StoreWord_Neg, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sw(A1, Address(A0, -4)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(StoreWord_Neg, test) { |
| EXPECT_DISASSEMBLY( |
| "feb52e23 sw a1, -4(a0)\n" |
| "00008067 ret\n"); |
| |
| uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t))); |
| values[0] = 0; |
| values[1] = 0; |
| values[2] = 0; |
| |
| Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xAB010203); |
| EXPECT_EQ(0xAB010203, values[0]); |
| EXPECT_EQ(0u, values[1]); |
| EXPECT_EQ(0u, values[2]); |
| } |
| |
| #if XLEN >= 64 |
| ASSEMBLER_TEST_GENERATE(LoadWordUnsigned_0, assembler) { |
| __ lwu(A0, Address(A0, 0)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadWordUnsigned_0, test) { |
| EXPECT_DISASSEMBLY( |
| "00056503 lwu a0, 0(a0)\n" |
| "00008067 ret\n"); |
| |
| uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t))); |
| values[0] = 0xAB010203; |
| values[1] = 0xCD020405; |
| values[2] = 0xEF030607; |
| |
| EXPECT_EQ(0xCD020405, |
| Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| } |
| ASSEMBLER_TEST_GENERATE(LoadWordUnsigned_Pos, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ lwu(A0, Address(A0, 4)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadWordUnsigned_Pos, test) { |
| EXPECT_DISASSEMBLY( |
| "00456503 lwu a0, 4(a0)\n" |
| "00008067 ret\n"); |
| |
| uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t))); |
| values[0] = 0xAB010203; |
| values[1] = 0xCD020405; |
| values[2] = 0xEF030607; |
| |
| EXPECT_EQ(0xEF030607, |
| Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| } |
| ASSEMBLER_TEST_GENERATE(LoadWordUnsigned_Neg, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ lwu(A0, Address(A0, -4)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadWordUnsigned_Neg, test) { |
| EXPECT_DISASSEMBLY( |
| "ffc56503 lwu a0, -4(a0)\n" |
| "00008067 ret\n"); |
| |
| uint32_t* values = reinterpret_cast<uint32_t*>(malloc(3 * sizeof(uint32_t))); |
| values[0] = 0xAB010203; |
| values[1] = 0xCD020405; |
| values[2] = 0xEF030607; |
| |
| EXPECT_EQ(0xAB010203, |
| Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(LoadDoubleWord_0, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ ld(A0, Address(A0, 0)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadDoubleWord_0, test) { |
| EXPECT_DISASSEMBLY( |
| "00053503 ld a0, 0(a0)\n" |
| "00008067 ret\n"); |
| |
| uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t))); |
| values[0] = 0xAB01020304050607; |
| values[1] = 0xCD02040505060708; |
| values[2] = 0xEF03060708090A0B; |
| |
| EXPECT_EQ(-3674369926375274744, |
| Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| } |
| ASSEMBLER_TEST_GENERATE(LoadDoubleWord_Pos, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ ld(A0, Address(A0, 8)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadDoubleWord_Pos, test) { |
| EXPECT_DISASSEMBLY( |
| "00853503 ld a0, 8(a0)\n" |
| "00008067 ret\n"); |
| |
| uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t))); |
| values[0] = 0xAB01020304050607; |
| values[1] = 0xCD02040505060708; |
| values[2] = 0xEF03060708090A0B; |
| |
| EXPECT_EQ(-1224128046445295093, |
| Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| } |
| ASSEMBLER_TEST_GENERATE(LoadDoubleWord_Neg, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ ld(A0, Address(A0, -8)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(LoadDoubleWord_Neg, test) { |
| EXPECT_DISASSEMBLY( |
| "ff853503 ld a0, -8(a0)\n" |
| "00008067 ret\n"); |
| |
| uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t))); |
| values[0] = 0xAB01020304050607; |
| values[1] = 0xCD02040505060708; |
| values[2] = 0xEF03060708090A0B; |
| |
| EXPECT_EQ(-6124611806271568377, |
| Call(test->entry(), reinterpret_cast<intx_t>(&values[1]))); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(StoreDoubleWord_0, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sd(A1, Address(A0, 0)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(StoreDoubleWord_0, test) { |
| EXPECT_DISASSEMBLY( |
| "00b53023 sd a1, 0(a0)\n" |
| "00008067 ret\n"); |
| |
| uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t))); |
| values[0] = 0; |
| values[1] = 0; |
| values[2] = 0; |
| |
| Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xCD02040505060708); |
| EXPECT_EQ(0u, values[0]); |
| EXPECT_EQ(0xCD02040505060708, values[1]); |
| EXPECT_EQ(0u, values[2]); |
| } |
| ASSEMBLER_TEST_GENERATE(StoreDoubleWord_Pos, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sd(A1, Address(A0, 8)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(StoreDoubleWord_Pos, test) { |
| EXPECT_DISASSEMBLY( |
| "00b53423 sd a1, 8(a0)\n" |
| "00008067 ret\n"); |
| |
| uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t))); |
| values[0] = 0; |
| values[1] = 0; |
| values[2] = 0; |
| |
| Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xEF03060708090A0B); |
| EXPECT_EQ(0u, values[0]); |
| EXPECT_EQ(0u, values[1]); |
| EXPECT_EQ(0xEF03060708090A0B, values[2]); |
| } |
| ASSEMBLER_TEST_GENERATE(StoreDoubleWord_Neg, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sd(A1, Address(A0, -8)); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(StoreDoubleWord_Neg, test) { |
| EXPECT_DISASSEMBLY( |
| "feb53c23 sd a1, -8(a0)\n" |
| "00008067 ret\n"); |
| |
| uint64_t* values = reinterpret_cast<uint64_t*>(malloc(3 * sizeof(uint64_t))); |
| values[0] = 0; |
| values[1] = 0; |
| values[2] = 0; |
| |
| Call(test->entry(), reinterpret_cast<intx_t>(&values[1]), 0xAB01020304050607); |
| EXPECT_EQ(0xAB01020304050607, values[0]); |
| EXPECT_EQ(0u, values[1]); |
| EXPECT_EQ(0u, values[2]); |
| } |
| #endif |
| |
| ASSEMBLER_TEST_GENERATE(AddImmediate1, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ addi(A0, A0, 42); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(AddImmediate1, test) { |
| EXPECT_DISASSEMBLY( |
| "02a50513 addi a0, a0, 42\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(42, Call(test->entry(), 0)); |
| EXPECT_EQ(40, Call(test->entry(), -2)); |
| EXPECT_EQ(0, Call(test->entry(), -42)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(AddImmediate2, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ addi(A0, A0, -42); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(AddImmediate2, test) { |
| EXPECT_DISASSEMBLY( |
| "fd650513 addi a0, a0, -42\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(-42, Call(test->entry(), 0)); |
| EXPECT_EQ(-44, Call(test->entry(), -2)); |
| EXPECT_EQ(38, Call(test->entry(), 80)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(SetLessThanImmediate1, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ slti(A0, A0, 7); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(SetLessThanImmediate1, test) { |
| EXPECT_DISASSEMBLY( |
| "00752513 slti a0, a0, 7\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(1, Call(test->entry(), 6)); |
| EXPECT_EQ(0, Call(test->entry(), 7)); |
| EXPECT_EQ(0, Call(test->entry(), 8)); |
| EXPECT_EQ(1, Call(test->entry(), -6)); |
| EXPECT_EQ(1, Call(test->entry(), -7)); |
| EXPECT_EQ(1, Call(test->entry(), -8)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(SetLessThanImmediate2, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ slti(A0, A0, -7); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(SetLessThanImmediate2, test) { |
| EXPECT_DISASSEMBLY( |
| "ff952513 slti a0, a0, -7\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(0, Call(test->entry(), 6)); |
| EXPECT_EQ(0, Call(test->entry(), 7)); |
| EXPECT_EQ(0, Call(test->entry(), 8)); |
| EXPECT_EQ(0, Call(test->entry(), -6)); |
| EXPECT_EQ(0, Call(test->entry(), -7)); |
| EXPECT_EQ(1, Call(test->entry(), -8)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(SetLessThanImmediateUnsigned1, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sltiu(A0, A0, 7); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(SetLessThanImmediateUnsigned1, test) { |
| EXPECT_DISASSEMBLY( |
| "00753513 sltiu a0, a0, 7\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(1, Call(test->entry(), 6)); |
| EXPECT_EQ(0, Call(test->entry(), 7)); |
| EXPECT_EQ(0, Call(test->entry(), 8)); |
| EXPECT_EQ(0, Call(test->entry(), -6)); |
| EXPECT_EQ(0, Call(test->entry(), -7)); |
| EXPECT_EQ(0, Call(test->entry(), -8)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(SetLessThanImmediateUnsigned2, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sltiu(A0, A0, -7); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(SetLessThanImmediateUnsigned2, test) { |
| EXPECT_DISASSEMBLY( |
| "ff953513 sltiu a0, a0, -7\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(1, Call(test->entry(), 6)); |
| EXPECT_EQ(1, Call(test->entry(), 7)); |
| EXPECT_EQ(1, Call(test->entry(), 8)); |
| EXPECT_EQ(0, Call(test->entry(), -6)); |
| EXPECT_EQ(0, Call(test->entry(), -7)); |
| EXPECT_EQ(1, Call(test->entry(), -8)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(XorImmediate1, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ xori(A0, A0, 42); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(XorImmediate1, test) { |
| EXPECT_DISASSEMBLY( |
| "02a54513 xori a0, a0, 42\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(42, Call(test->entry(), 0)); |
| EXPECT_EQ(43, Call(test->entry(), 1)); |
| EXPECT_EQ(32, Call(test->entry(), 10)); |
| EXPECT_EQ(-43, Call(test->entry(), -1)); |
| EXPECT_EQ(-36, Call(test->entry(), -10)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(XorImmediate2, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ xori(A0, A0, -42); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(XorImmediate2, test) { |
| EXPECT_DISASSEMBLY( |
| "fd654513 xori a0, a0, -42\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(-42, Call(test->entry(), 0)); |
| EXPECT_EQ(-41, Call(test->entry(), 1)); |
| EXPECT_EQ(-36, Call(test->entry(), 10)); |
| EXPECT_EQ(41, Call(test->entry(), -1)); |
| EXPECT_EQ(32, Call(test->entry(), -10)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(OrImmediate1, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ ori(A0, A0, -6); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(OrImmediate1, test) { |
| EXPECT_DISASSEMBLY( |
| "ffa56513 ori a0, a0, -6\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(-6, Call(test->entry(), 0)); |
| EXPECT_EQ(-5, Call(test->entry(), 1)); |
| EXPECT_EQ(-5, Call(test->entry(), 11)); |
| EXPECT_EQ(-1, Call(test->entry(), -1)); |
| EXPECT_EQ(-1, Call(test->entry(), -11)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(OrImmediate2, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ ori(A0, A0, 6); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(OrImmediate2, test) { |
| EXPECT_DISASSEMBLY( |
| "00656513 ori a0, a0, 6\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(6, Call(test->entry(), 0)); |
| EXPECT_EQ(7, Call(test->entry(), 1)); |
| EXPECT_EQ(15, Call(test->entry(), 11)); |
| EXPECT_EQ(-1, Call(test->entry(), -1)); |
| EXPECT_EQ(-9, Call(test->entry(), -11)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(AndImmediate1, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ andi(A0, A0, -6); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(AndImmediate1, test) { |
| EXPECT_DISASSEMBLY( |
| "ffa57513 andi a0, a0, -6\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(0, Call(test->entry(), 0)); |
| EXPECT_EQ(0, Call(test->entry(), 1)); |
| EXPECT_EQ(10, Call(test->entry(), 11)); |
| EXPECT_EQ(-6, Call(test->entry(), -1)); |
| EXPECT_EQ(-16, Call(test->entry(), -11)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(AndImmediate2, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ andi(A0, A0, 6); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(AndImmediate2, test) { |
| EXPECT_DISASSEMBLY( |
| "00657513 andi a0, a0, 6\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(0, Call(test->entry(), 0)); |
| EXPECT_EQ(0, Call(test->entry(), 1)); |
| EXPECT_EQ(2, Call(test->entry(), 11)); |
| EXPECT_EQ(6, Call(test->entry(), -1)); |
| EXPECT_EQ(4, Call(test->entry(), -11)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(ShiftLeftLogicalImmediate, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ slli(A0, A0, 2); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(ShiftLeftLogicalImmediate, test) { |
| EXPECT_DISASSEMBLY( |
| "00251513 slli a0, a0, 0x2\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(84, Call(test->entry(), 21)); |
| EXPECT_EQ(4, Call(test->entry(), 1)); |
| EXPECT_EQ(0, Call(test->entry(), 0)); |
| EXPECT_EQ(-4, Call(test->entry(), -1)); |
| EXPECT_EQ(-84, Call(test->entry(), -21)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(ShiftLeftLogicalImmediate2, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ slli(A0, A0, XLEN - 1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(ShiftLeftLogicalImmediate2, test) { |
| #if XLEN == 32 |
| EXPECT_DISASSEMBLY( |
| "01f51513 slli a0, a0, 0x1f\n" |
| "00008067 ret\n"); |
| #elif XLEN == 64 |
| EXPECT_DISASSEMBLY( |
| "03f51513 slli a0, a0, 0x3f\n" |
| "00008067 ret\n"); |
| #endif |
| EXPECT_EQ(0, Call(test->entry(), 2)); |
| EXPECT_EQ(kMinIntX, Call(test->entry(), 1)); |
| EXPECT_EQ(0, Call(test->entry(), 0)); |
| EXPECT_EQ(kMinIntX, Call(test->entry(), -1)); |
| EXPECT_EQ(0, Call(test->entry(), -2)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(ShiftRightLogicalImmediate, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ srli(A0, A0, 2); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(ShiftRightLogicalImmediate, test) { |
| EXPECT_DISASSEMBLY( |
| "00255513 srli a0, a0, 0x2\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(5, Call(test->entry(), 21)); |
| EXPECT_EQ(0, Call(test->entry(), 1)); |
| EXPECT_EQ(0, Call(test->entry(), 0)); |
| EXPECT_EQ(static_cast<intx_t>(static_cast<uintx_t>(-1) >> 2), |
| Call(test->entry(), -1)); |
| EXPECT_EQ(static_cast<intx_t>(static_cast<uintx_t>(-21) >> 2), |
| Call(test->entry(), -21)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(ShiftRightLogicalImmediate2, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ srli(A0, A0, XLEN - 1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(ShiftRightLogicalImmediate2, test) { |
| #if XLEN == 32 |
| EXPECT_DISASSEMBLY( |
| "01f55513 srli a0, a0, 0x1f\n" |
| "00008067 ret\n"); |
| #elif XLEN == 64 |
| EXPECT_DISASSEMBLY( |
| "03f55513 srli a0, a0, 0x3f\n" |
| "00008067 ret\n"); |
| #endif |
| EXPECT_EQ(0, Call(test->entry(), 21)); |
| EXPECT_EQ(0, Call(test->entry(), 1)); |
| EXPECT_EQ(0, Call(test->entry(), 0)); |
| EXPECT_EQ(1, Call(test->entry(), -1)); |
| EXPECT_EQ(1, Call(test->entry(), -21)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(ShiftRightArithmeticImmediate, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ srai(A0, A0, 2); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(ShiftRightArithmeticImmediate, test) { |
| EXPECT_DISASSEMBLY( |
| "40255513 srai a0, a0, 0x2\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(5, Call(test->entry(), 21)); |
| EXPECT_EQ(0, Call(test->entry(), 1)); |
| EXPECT_EQ(0, Call(test->entry(), 0)); |
| EXPECT_EQ(-1, Call(test->entry(), -1)); |
| EXPECT_EQ(-6, Call(test->entry(), -21)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(ShiftRightArithmeticImmediate2, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ srai(A0, A0, XLEN - 1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(ShiftRightArithmeticImmediate2, test) { |
| #if XLEN == 32 |
| EXPECT_DISASSEMBLY( |
| "41f55513 srai a0, a0, 0x1f\n" // CHECK |
| "00008067 ret\n"); |
| #elif XLEN == 64 |
| EXPECT_DISASSEMBLY( |
| "43f55513 srai a0, a0, 0x3f\n" // CHECK |
| "00008067 ret\n"); |
| #endif |
| EXPECT_EQ(0, Call(test->entry(), 21)); |
| EXPECT_EQ(0, Call(test->entry(), 1)); |
| EXPECT_EQ(0, Call(test->entry(), 0)); |
| EXPECT_EQ(-1, Call(test->entry(), -1)); |
| EXPECT_EQ(-1, Call(test->entry(), -21)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(Add, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ add(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(Add, test) { |
| EXPECT_DISASSEMBLY( |
| "00b50533 add a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(24, Call(test->entry(), 7, 17)); |
| EXPECT_EQ(-10, Call(test->entry(), 7, -17)); |
| EXPECT_EQ(10, Call(test->entry(), -7, 17)); |
| EXPECT_EQ(-24, Call(test->entry(), -7, -17)); |
| EXPECT_EQ(24, Call(test->entry(), 17, 7)); |
| EXPECT_EQ(10, Call(test->entry(), 17, -7)); |
| EXPECT_EQ(-10, Call(test->entry(), -17, 7)); |
| EXPECT_EQ(-24, Call(test->entry(), -17, -7)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(Subtract, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sub(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(Subtract, test) { |
| EXPECT_DISASSEMBLY( |
| "40b50533 sub a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(-10, Call(test->entry(), 7, 17)); |
| EXPECT_EQ(24, Call(test->entry(), 7, -17)); |
| EXPECT_EQ(-24, Call(test->entry(), -7, 17)); |
| EXPECT_EQ(10, Call(test->entry(), -7, -17)); |
| EXPECT_EQ(10, Call(test->entry(), 17, 7)); |
| EXPECT_EQ(24, Call(test->entry(), 17, -7)); |
| EXPECT_EQ(-24, Call(test->entry(), -17, 7)); |
| EXPECT_EQ(-10, Call(test->entry(), -17, -7)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(ShiftLeftLogical, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sll(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(ShiftLeftLogical, test) { |
| EXPECT_DISASSEMBLY( |
| "00b51533 sll a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(2176, Call(test->entry(), 17, 7)); |
| EXPECT_EQ(-2176, Call(test->entry(), -17, 7)); |
| EXPECT_EQ(34, Call(test->entry(), 17, 1)); |
| EXPECT_EQ(-34, Call(test->entry(), -17, 1)); |
| EXPECT_EQ(17, Call(test->entry(), 17, 0)); |
| EXPECT_EQ(-17, Call(test->entry(), -17, 0)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(SetLessThan, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ slt(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(SetLessThan, test) { |
| EXPECT_DISASSEMBLY( |
| "00b52533 slt a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(0, Call(test->entry(), 7, 7)); |
| EXPECT_EQ(0, Call(test->entry(), -7, -7)); |
| EXPECT_EQ(1, Call(test->entry(), 7, 17)); |
| EXPECT_EQ(0, Call(test->entry(), 7, -17)); |
| EXPECT_EQ(1, Call(test->entry(), -7, 17)); |
| EXPECT_EQ(0, Call(test->entry(), -7, -17)); |
| EXPECT_EQ(0, Call(test->entry(), 17, 7)); |
| EXPECT_EQ(0, Call(test->entry(), 17, -7)); |
| EXPECT_EQ(1, Call(test->entry(), -17, 7)); |
| EXPECT_EQ(1, Call(test->entry(), -17, -7)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(SetLessThanUnsigned, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sltu(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(SetLessThanUnsigned, test) { |
| EXPECT_DISASSEMBLY( |
| "00b53533 sltu a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(0, Call(test->entry(), 7, 7)); |
| EXPECT_EQ(0, Call(test->entry(), -7, -7)); |
| EXPECT_EQ(1, Call(test->entry(), 7, 17)); |
| EXPECT_EQ(1, Call(test->entry(), 7, -17)); |
| EXPECT_EQ(0, Call(test->entry(), -7, 17)); |
| EXPECT_EQ(0, Call(test->entry(), -7, -17)); |
| EXPECT_EQ(0, Call(test->entry(), 17, 7)); |
| EXPECT_EQ(1, Call(test->entry(), 17, -7)); |
| EXPECT_EQ(0, Call(test->entry(), -17, 7)); |
| EXPECT_EQ(1, Call(test->entry(), -17, -7)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(Xor, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ xor_(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(Xor, test) { |
| EXPECT_DISASSEMBLY( |
| "00b54533 xor a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(22, Call(test->entry(), 7, 17)); |
| EXPECT_EQ(-24, Call(test->entry(), 7, -17)); |
| EXPECT_EQ(-24, Call(test->entry(), -7, 17)); |
| EXPECT_EQ(22, Call(test->entry(), -7, -17)); |
| EXPECT_EQ(22, Call(test->entry(), 17, 7)); |
| EXPECT_EQ(-24, Call(test->entry(), 17, -7)); |
| EXPECT_EQ(-24, Call(test->entry(), -17, 7)); |
| EXPECT_EQ(22, Call(test->entry(), -17, -7)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(ShiftRightLogical, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ srl(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(ShiftRightLogical, test) { |
| EXPECT_DISASSEMBLY( |
| "00b55533 srl a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(0, Call(test->entry(), 17, 7)); |
| EXPECT_EQ(static_cast<intx_t>(static_cast<uintx_t>(-17) >> 7), |
| Call(test->entry(), -17, 7)); |
| EXPECT_EQ(8, Call(test->entry(), 17, 1)); |
| EXPECT_EQ(static_cast<intx_t>(static_cast<uintx_t>(-17) >> 1), |
| Call(test->entry(), -17, 1)); |
| EXPECT_EQ(17, Call(test->entry(), 17, 0)); |
| EXPECT_EQ(-17, Call(test->entry(), -17, 0)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(ShiftRightArithmetic, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sra(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(ShiftRightArithmetic, test) { |
| EXPECT_DISASSEMBLY( |
| "40b55533 sra a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(0, Call(test->entry(), 17, 7)); |
| EXPECT_EQ(-1, Call(test->entry(), -17, 7)); |
| EXPECT_EQ(8, Call(test->entry(), 17, 1)); |
| EXPECT_EQ(-9, Call(test->entry(), -17, 1)); |
| EXPECT_EQ(17, Call(test->entry(), 17, 0)); |
| EXPECT_EQ(-17, Call(test->entry(), -17, 0)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(Or, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ or_(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(Or, test) { |
| EXPECT_DISASSEMBLY( |
| "00b56533 or a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(23, Call(test->entry(), 7, 17)); |
| EXPECT_EQ(-17, Call(test->entry(), 7, -17)); |
| EXPECT_EQ(-7, Call(test->entry(), -7, 17)); |
| EXPECT_EQ(-1, Call(test->entry(), -7, -17)); |
| EXPECT_EQ(23, Call(test->entry(), 17, 7)); |
| EXPECT_EQ(-7, Call(test->entry(), 17, -7)); |
| EXPECT_EQ(-17, Call(test->entry(), -17, 7)); |
| EXPECT_EQ(-1, Call(test->entry(), -17, -7)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(And, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ and_(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(And, test) { |
| EXPECT_DISASSEMBLY( |
| "00b57533 and a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(1, Call(test->entry(), 7, 17)); |
| EXPECT_EQ(7, Call(test->entry(), 7, -17)); |
| EXPECT_EQ(17, Call(test->entry(), -7, 17)); |
| EXPECT_EQ(-23, Call(test->entry(), -7, -17)); |
| EXPECT_EQ(1, Call(test->entry(), 17, 7)); |
| EXPECT_EQ(17, Call(test->entry(), 17, -7)); |
| EXPECT_EQ(7, Call(test->entry(), -17, 7)); |
| EXPECT_EQ(-23, Call(test->entry(), -17, -7)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(Fence, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ fence(); |
| __ fence(kRead, kWrite); |
| __ fence(kInput, kOutput); |
| __ fence(kMemory, kMemory); |
| __ fence(kAll, kAll); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(Fence, test) { |
| EXPECT_DISASSEMBLY( |
| "0ff0000f fence\n" |
| "0210000f fence r,w\n" |
| "0840000f fence i,o\n" |
| "0330000f fence rw,rw\n" |
| "0ff0000f fence\n" |
| "00008067 ret\n"); |
| Call(test->entry()); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(InstructionFence, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ fencei(); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(InstructionFence, test) { |
| EXPECT_DISASSEMBLY( |
| "0000100f fence.i\n" |
| "00008067 ret\n"); |
| Call(test->entry()); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(EnvironmentCall, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ ecall(); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(EnvironmentCall, test) { |
| EXPECT_DISASSEMBLY( |
| "00000073 ecall\n" |
| "00008067 ret\n"); |
| |
| // Not running: would trap. |
| } |
| |
| ASSEMBLER_TEST_GENERATE(EnvironmentBreak, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ ebreak(); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(EnvironmentBreak, test) { |
| EXPECT_DISASSEMBLY( |
| "00100073 ebreak\n" |
| "00008067 ret\n"); |
| |
| // Not running: would trap. |
| } |
| |
| ASSEMBLER_TEST_GENERATE(ControlStatusRegisters, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ csrrw(T0, 0x123, S1); |
| __ csrrs(T1, 0x123, S2); |
| __ csrrc(T2, 0x123, S3); |
| __ csrr(T3, 0x123); |
| __ csrw(0x123, S4); |
| __ csrs(0x123, S5); |
| __ csrc(0x123, S6); |
| __ csrrwi(T1, 0x123, 1); |
| __ csrrsi(T2, 0x123, 2); |
| __ csrrci(T3, 0x123, 3); |
| __ csrwi(0x123, 4); |
| __ csrsi(0x123, 5); |
| __ csrci(0x123, 6); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(ControlStatusRegisters, test) { |
| EXPECT_DISASSEMBLY( |
| "123492f3 csrrw t0, 0x123, thr\n" |
| "12392373 csrrs t1, 0x123, s2\n" |
| "1239b3f3 csrrc t2, 0x123, s3\n" |
| "12302e73 csrr t3, 0x123\n" |
| "123a1073 csrw 0x123, s4\n" |
| "123aa073 csrs 0x123, s5\n" |
| "123b3073 csrc 0x123, s6\n" |
| "1230d373 csrrwi t1, 0x123, 1\n" |
| "123163f3 csrrsi t2, 0x123, 2\n" |
| "1231fe73 csrrci t3, 0x123, 3\n" |
| "12325073 csrwi 0x123, 4\n" |
| "1232e073 csrsi 0x123, 5\n" |
| "12337073 csrci 0x123, 6\n" |
| "00008067 ret\n"); |
| |
| // Not running: would trap. |
| } |
| |
| ASSEMBLER_TEST_GENERATE(Nop, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ nop(); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(Nop, test) { |
| EXPECT_DISASSEMBLY( |
| "00000013 nop\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(123, Call(test->entry(), 123)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(Move, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ mv(A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(Move, test) { |
| EXPECT_DISASSEMBLY( |
| "00058513 mv a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(36, Call(test->entry(), 42, 36)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(Not, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ not_(A0, A0); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(Not, test) { |
| EXPECT_DISASSEMBLY( |
| "fff54513 not a0, a0\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(~42, Call(test->entry(), 42)); |
| EXPECT_EQ(~-42, Call(test->entry(), -42)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(Negate, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ neg(A0, A0); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(Negate, test) { |
| EXPECT_DISASSEMBLY( |
| "40a00533 neg a0, a0\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(-42, Call(test->entry(), 42)); |
| EXPECT_EQ(42, Call(test->entry(), -42)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(SetNotEqualToZero, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ snez(A0, A0); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(SetNotEqualToZero, test) { |
| EXPECT_DISASSEMBLY( |
| "00a03533 snez a0, a0\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(1, Call(test->entry(), -42)); |
| EXPECT_EQ(0, Call(test->entry(), 0)); |
| EXPECT_EQ(1, Call(test->entry(), 42)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(SetEqualToZero, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ seqz(A0, A0); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(SetEqualToZero, test) { |
| EXPECT_DISASSEMBLY( |
| "00153513 seqz a0, a0\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(0, Call(test->entry(), -42)); |
| EXPECT_EQ(1, Call(test->entry(), 0)); |
| EXPECT_EQ(0, Call(test->entry(), 42)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(SetLessThanZero, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sltz(A0, A0); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(SetLessThanZero, test) { |
| EXPECT_DISASSEMBLY( |
| "00052533 sltz a0, a0\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(1, Call(test->entry(), -42)); |
| EXPECT_EQ(0, Call(test->entry(), 0)); |
| EXPECT_EQ(0, Call(test->entry(), 42)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(SetGreaterThanZero, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sgtz(A0, A0); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(SetGreaterThanZero, test) { |
| EXPECT_DISASSEMBLY( |
| "00a02533 sgtz a0, a0\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(0, Call(test->entry(), -42)); |
| EXPECT_EQ(0, Call(test->entry(), 0)); |
| EXPECT_EQ(1, Call(test->entry(), 42)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchEqualZero, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| Label label; |
| __ beqz(A0, &label); |
| __ li(A0, 3); |
| __ ret(); |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchEqualZero, test) { |
| EXPECT_DISASSEMBLY( |
| "00050663 beqz a0, +12\n" |
| "00300513 li a0, 3\n" |
| "00008067 ret\n" |
| "00400513 li a0, 4\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(3, Call(test->entry(), -42)); |
| EXPECT_EQ(4, Call(test->entry(), 0)); |
| EXPECT_EQ(3, Call(test->entry(), 42)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchNotEqualZero, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| Label label; |
| __ bnez(A0, &label); |
| __ li(A0, 3); |
| __ ret(); |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchNotEqualZero, test) { |
| EXPECT_DISASSEMBLY( |
| "00051663 bnez a0, +12\n" |
| "00300513 li a0, 3\n" |
| "00008067 ret\n" |
| "00400513 li a0, 4\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(4, Call(test->entry(), -42)); |
| EXPECT_EQ(3, Call(test->entry(), 0)); |
| EXPECT_EQ(4, Call(test->entry(), 42)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchLessOrEqualZero, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| Label label; |
| __ blez(A0, &label); |
| __ li(A0, 3); |
| __ ret(); |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchLessOrEqualZero, test) { |
| EXPECT_DISASSEMBLY( |
| "00a05663 blez a0, +12\n" |
| "00300513 li a0, 3\n" |
| "00008067 ret\n" |
| "00400513 li a0, 4\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(4, Call(test->entry(), -42)); |
| EXPECT_EQ(4, Call(test->entry(), 0)); |
| EXPECT_EQ(3, Call(test->entry(), 42)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchGreaterOrEqualZero, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| Label label; |
| __ bgez(A0, &label); |
| __ li(A0, 3); |
| __ ret(); |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchGreaterOrEqualZero, test) { |
| EXPECT_DISASSEMBLY( |
| "00055663 bgez a0, +12\n" |
| "00300513 li a0, 3\n" |
| "00008067 ret\n" |
| "00400513 li a0, 4\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(3, Call(test->entry(), -42)); |
| EXPECT_EQ(4, Call(test->entry(), 0)); |
| EXPECT_EQ(4, Call(test->entry(), 42)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchLessThanZero, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| Label label; |
| __ bltz(A0, &label); |
| __ li(A0, 3); |
| __ ret(); |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchLessThanZero, test) { |
| EXPECT_DISASSEMBLY( |
| "00054663 bltz a0, +12\n" |
| "00300513 li a0, 3\n" |
| "00008067 ret\n" |
| "00400513 li a0, 4\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(4, Call(test->entry(), -42)); |
| EXPECT_EQ(3, Call(test->entry(), 0)); |
| EXPECT_EQ(3, Call(test->entry(), 42)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(BranchGreaterThanZero, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| Label label; |
| __ bgtz(A0, &label); |
| __ li(A0, 3); |
| __ ret(); |
| __ Bind(&label); |
| __ li(A0, 4); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(BranchGreaterThanZero, test) { |
| EXPECT_DISASSEMBLY( |
| "00a04663 bgtz a0, +12\n" |
| "00300513 li a0, 3\n" |
| "00008067 ret\n" |
| "00400513 li a0, 4\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(3, Call(test->entry(), -42)); |
| EXPECT_EQ(3, Call(test->entry(), 0)); |
| EXPECT_EQ(4, Call(test->entry(), 42)); |
| } |
| |
| #if XLEN >= 64 |
| ASSEMBLER_TEST_GENERATE(AddImmediateWord1, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ addiw(A0, A0, 42); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(AddImmediateWord1, test) { |
| EXPECT_DISASSEMBLY( |
| "02a5051b addiw a0, a0, 42\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(42, Call(test->entry(), 0)); |
| EXPECT_EQ(40, Call(test->entry(), -2)); |
| EXPECT_EQ(0, Call(test->entry(), -42)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(AddImmediateWord2, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ addiw(A0, A0, -42); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(AddImmediateWord2, test) { |
| EXPECT_DISASSEMBLY( |
| "fd65051b addiw a0, a0, -42\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(-42, Call(test->entry(), 0)); |
| EXPECT_EQ(-44, Call(test->entry(), -2)); |
| EXPECT_EQ(38, Call(test->entry(), 80)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(ShiftLeftLogicalImmediateWord, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ slliw(A0, A0, 2); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(ShiftLeftLogicalImmediateWord, test) { |
| EXPECT_DISASSEMBLY( |
| "0025151b slliw a0, a0, 0x2\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(84, Call(test->entry(), 21)); |
| EXPECT_EQ(4, Call(test->entry(), 1)); |
| EXPECT_EQ(0, Call(test->entry(), 0)); |
| EXPECT_EQ(-4, Call(test->entry(), -1)); |
| EXPECT_EQ(-84, Call(test->entry(), -21)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(ShiftRightLogicalImmediateWord, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ srliw(A0, A0, 2); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(ShiftRightLogicalImmediateWord, test) { |
| EXPECT_DISASSEMBLY( |
| "0025551b srliw a0, a0, 0x2\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(5, Call(test->entry(), 21)); |
| EXPECT_EQ(0, Call(test->entry(), 1)); |
| EXPECT_EQ(0, Call(test->entry(), 0)); |
| EXPECT_EQ(sign_extend(static_cast<uint32_t>(-1) >> 2), |
| Call(test->entry(), -1)); |
| EXPECT_EQ(sign_extend(static_cast<uint32_t>(-21) >> 2), |
| Call(test->entry(), -21)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(ShiftRightArithmeticImmediateWord, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sraiw(A0, A0, 2); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(ShiftRightArithmeticImmediateWord, test) { |
| EXPECT_DISASSEMBLY( |
| "4025551b sraiw a0, a0, 0x2\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(5, Call(test->entry(), 21)); |
| EXPECT_EQ(0, Call(test->entry(), 1)); |
| EXPECT_EQ(0, Call(test->entry(), 0)); |
| EXPECT_EQ(-1, Call(test->entry(), -1)); |
| EXPECT_EQ(-6, Call(test->entry(), -21)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(AddWord, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ addw(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(AddWord, test) { |
| EXPECT_DISASSEMBLY( |
| "00b5053b addw a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(24, Call(test->entry(), 7, 17)); |
| EXPECT_EQ(-10, Call(test->entry(), 7, -17)); |
| EXPECT_EQ(10, Call(test->entry(), -7, 17)); |
| EXPECT_EQ(-24, Call(test->entry(), -7, -17)); |
| EXPECT_EQ(24, Call(test->entry(), 17, 7)); |
| EXPECT_EQ(10, Call(test->entry(), 17, -7)); |
| EXPECT_EQ(-10, Call(test->entry(), -17, 7)); |
| EXPECT_EQ(-24, Call(test->entry(), -17, -7)); |
| EXPECT_EQ(3, Call(test->entry(), 0x200000002, 0x100000001)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(SubtractWord, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ subw(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(SubtractWord, test) { |
| EXPECT_DISASSEMBLY( |
| "40b5053b subw a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(-10, Call(test->entry(), 7, 17)); |
| EXPECT_EQ(24, Call(test->entry(), 7, -17)); |
| EXPECT_EQ(-24, Call(test->entry(), -7, 17)); |
| EXPECT_EQ(10, Call(test->entry(), -7, -17)); |
| EXPECT_EQ(10, Call(test->entry(), 17, 7)); |
| EXPECT_EQ(24, Call(test->entry(), 17, -7)); |
| EXPECT_EQ(-24, Call(test->entry(), -17, 7)); |
| EXPECT_EQ(-10, Call(test->entry(), -17, -7)); |
| EXPECT_EQ(1, Call(test->entry(), 0x200000002, 0x100000001)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(ShiftLeftLogicalWord, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sllw(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(ShiftLeftLogicalWord, test) { |
| EXPECT_DISASSEMBLY( |
| "00b5153b sllw a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(2176, Call(test->entry(), 17, 7)); |
| EXPECT_EQ(-2176, Call(test->entry(), -17, 7)); |
| EXPECT_EQ(34, Call(test->entry(), 17, 1)); |
| EXPECT_EQ(-34, Call(test->entry(), -17, 1)); |
| EXPECT_EQ(17, Call(test->entry(), 17, 0)); |
| EXPECT_EQ(-17, Call(test->entry(), -17, 0)); |
| EXPECT_EQ(0x10, Call(test->entry(), 0x10000001, 4)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(ShiftRightLogicalWord, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ srlw(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(ShiftRightLogicalWord, test) { |
| EXPECT_DISASSEMBLY( |
| "00b5553b srlw a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(0, Call(test->entry(), 17, 7)); |
| EXPECT_EQ(sign_extend(static_cast<uint32_t>(-17) >> 7), |
| Call(test->entry(), -17, 7)); |
| EXPECT_EQ(8, Call(test->entry(), 17, 1)); |
| EXPECT_EQ(sign_extend(static_cast<uint32_t>(-17) >> 1), |
| Call(test->entry(), -17, 1)); |
| EXPECT_EQ(17, Call(test->entry(), 17, 0)); |
| EXPECT_EQ(-17, Call(test->entry(), -17, 0)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(ShiftRightArithmeticWord, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sraw(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(ShiftRightArithmeticWord, test) { |
| EXPECT_DISASSEMBLY( |
| "40b5553b sraw a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(0, Call(test->entry(), 17, 7)); |
| EXPECT_EQ(-1, Call(test->entry(), -17, 7)); |
| EXPECT_EQ(8, Call(test->entry(), 17, 1)); |
| EXPECT_EQ(-9, Call(test->entry(), -17, 1)); |
| EXPECT_EQ(17, Call(test->entry(), 17, 0)); |
| EXPECT_EQ(-17, Call(test->entry(), -17, 0)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(NegateWord, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ negw(A0, A0); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(NegateWord, test) { |
| EXPECT_DISASSEMBLY( |
| "40a0053b negw a0, a0\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(0, Call(test->entry(), 0)); |
| EXPECT_EQ(-42, Call(test->entry(), 42)); |
| EXPECT_EQ(42, Call(test->entry(), -42)); |
| EXPECT_EQ(1, Call(test->entry(), 0x10FFFFFFFF)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(SignExtendWord, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ sextw(A0, A0); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(SignExtendWord, test) { |
| EXPECT_DISASSEMBLY( |
| "0005051b sext.w a0, a0\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(0, Call(test->entry(), 0)); |
| EXPECT_EQ(42, Call(test->entry(), 42)); |
| EXPECT_EQ(-42, Call(test->entry(), -42)); |
| EXPECT_EQ(-1, Call(test->entry(), 0x10FFFFFFFF)); |
| } |
| #endif // XLEN >= 64 |
| |
| ASSEMBLER_TEST_GENERATE(Multiply, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ mul(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(Multiply, test) { |
| EXPECT_DISASSEMBLY( |
| "02b50533 mul a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(68, Call(test->entry(), 4, 17)); |
| EXPECT_EQ(-68, Call(test->entry(), -4, 17)); |
| EXPECT_EQ(-68, Call(test->entry(), 4, -17)); |
| EXPECT_EQ(68, Call(test->entry(), -4, -17)); |
| EXPECT_EQ(68, Call(test->entry(), 17, 4)); |
| EXPECT_EQ(-68, Call(test->entry(), -17, 4)); |
| EXPECT_EQ(-68, Call(test->entry(), 17, -4)); |
| EXPECT_EQ(68, Call(test->entry(), -17, -4)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(MultiplyHigh, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ mulh(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(MultiplyHigh, test) { |
| EXPECT_DISASSEMBLY( |
| "02b51533 mulh a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(0, Call(test->entry(), 4, 17)); |
| EXPECT_EQ(-1, Call(test->entry(), -4, 17)); |
| EXPECT_EQ(-1, Call(test->entry(), 4, -17)); |
| EXPECT_EQ(0, Call(test->entry(), -4, -17)); |
| EXPECT_EQ(0, Call(test->entry(), 17, 4)); |
| EXPECT_EQ(-1, Call(test->entry(), -17, 4)); |
| EXPECT_EQ(-1, Call(test->entry(), 17, -4)); |
| EXPECT_EQ(0, Call(test->entry(), -17, -4)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(MultiplyHighSignedUnsigned, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ mulhsu(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(MultiplyHighSignedUnsigned, test) { |
| EXPECT_DISASSEMBLY( |
| "02b52533 mulhsu a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(0, Call(test->entry(), 4, 17)); |
| EXPECT_EQ(-1, Call(test->entry(), -4, 17)); |
| EXPECT_EQ(3, Call(test->entry(), 4, -17)); |
| EXPECT_EQ(-4, Call(test->entry(), -4, -17)); |
| EXPECT_EQ(0, Call(test->entry(), 17, 4)); |
| EXPECT_EQ(-1, Call(test->entry(), -17, 4)); |
| EXPECT_EQ(16, Call(test->entry(), 17, -4)); |
| EXPECT_EQ(-17, Call(test->entry(), -17, -4)); |
| } |
| |
| ASSEMBLER_TEST_GENERATE(MultiplyHighUnsigned, assembler) { |
| FLAG_use_compressed_instructions = false; |
| __ SetExtensions(RV_G); |
| __ mulhu(A0, A0, A1); |
| __ ret(); |
| } |
| ASSEMBLER_TEST_RUN(MultiplyHighUnsigned, test) { |
| EXPECT_DISASSEMBLY( |
| "02b53533 mulhu a0, a0, a1\n" |
| "00008067 ret\n"); |
| EXPECT_EQ(0, Call(test->entry(), 4, 17)); |
| EXPECT_EQ(16, Call(test->entry(), -4, 17)); |
| EXPECT_EQ(3, Call(test->entry(), 4, -17)); |
| EXPECT_EQ(-21, Call(test->entry(), -4, -17)); |
| EXPECT_EQ(0, Call(test->entry(), 17, 4)); |
| EXPECT_EQ(3, Call(test->entry(), -17, 4)); |
| EXPECT_EQ(16, Call(test->entry(), 17, -4)); |
| EXPECT_EQ(-21, Call(test->entry(), -17 |