| // Copyright 2024 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "cheriot/riscv_cheriot_vector_fp_compare_instructions.h" |
| |
| #include "absl/log/log.h" |
| #include "cheriot/cheriot_state.h" |
| #include "cheriot/cheriot_vector_state.h" |
| #include "cheriot/riscv_cheriot_vector_instruction_helpers.h" |
| |
| namespace mpact { |
| namespace sim { |
| namespace cheriot { |
| |
| // Vector floating point compare equal. |
| void Vmfeq(const Instruction *inst) { |
| auto *rv_vector = static_cast<CheriotState *>(inst->state())->rv_vector(); |
| int sew = rv_vector->selected_element_width(); |
| switch (sew) { |
| case 4: |
| return RiscVBinaryVectorMaskOp<float, float>( |
| rv_vector, inst, |
| [](float vs2, float vs1) -> bool { return vs2 == vs1; }); |
| case 8: |
| return RiscVBinaryVectorMaskOp<double, double>( |
| rv_vector, inst, |
| [](double vs2, double vs1) -> bool { return vs2 == vs1; }); |
| default: |
| LOG(ERROR) << "Vmfeq: Illegal sew (" << sew << ")"; |
| rv_vector->set_vector_exception(); |
| return; |
| } |
| } |
| |
| // Vector floating point compare less than or equal. |
| void Vmfle(const Instruction *inst) { |
| auto *rv_vector = static_cast<CheriotState *>(inst->state())->rv_vector(); |
| int sew = rv_vector->selected_element_width(); |
| switch (sew) { |
| case 4: |
| return RiscVBinaryVectorMaskOp<float, float>( |
| rv_vector, inst, |
| [](float vs2, float vs1) -> bool { return vs2 <= vs1; }); |
| case 8: |
| return RiscVBinaryVectorMaskOp<double, double>( |
| rv_vector, inst, |
| [](double vs2, double vs1) -> bool { return vs2 <= vs1; }); |
| default: |
| LOG(ERROR) << "Vmfle: Illegal sew (" << sew << ")"; |
| rv_vector->set_vector_exception(); |
| return; |
| } |
| } |
| |
| // Vector floating compare less than. |
| void Vmflt(const Instruction *inst) { |
| auto *rv_vector = static_cast<CheriotState *>(inst->state())->rv_vector(); |
| int sew = rv_vector->selected_element_width(); |
| switch (sew) { |
| case 4: |
| return RiscVBinaryVectorMaskOp<float, float>( |
| rv_vector, inst, |
| [](float vs2, float vs1) -> bool { return vs2 < vs1; }); |
| case 8: |
| return RiscVBinaryVectorMaskOp<double, double>( |
| rv_vector, inst, |
| [](double vs2, double vs1) -> bool { return vs2 < vs1; }); |
| default: |
| LOG(ERROR) << "Vmflt: Illegal sew (" << sew << ")"; |
| rv_vector->set_vector_exception(); |
| return; |
| } |
| } |
| |
| // Vector floating point compare not equal. |
| void Vmfne(const Instruction *inst) { |
| auto *rv_vector = static_cast<CheriotState *>(inst->state())->rv_vector(); |
| int sew = rv_vector->selected_element_width(); |
| switch (sew) { |
| case 4: |
| return RiscVBinaryVectorMaskOp<float, float>( |
| rv_vector, inst, |
| [](float vs2, float vs1) -> bool { return vs2 != vs1; }); |
| case 8: |
| return RiscVBinaryVectorMaskOp<double, double>( |
| rv_vector, inst, |
| [](double vs2, double vs1) -> bool { return vs2 != vs1; }); |
| default: |
| LOG(ERROR) << "Vmfne: Illegal sew (" << sew << ")"; |
| rv_vector->set_vector_exception(); |
| return; |
| } |
| } |
| |
| // Vector floating point compare greater than. |
| void Vmfgt(const Instruction *inst) { |
| auto *rv_vector = static_cast<CheriotState *>(inst->state())->rv_vector(); |
| int sew = rv_vector->selected_element_width(); |
| switch (sew) { |
| case 4: |
| return RiscVBinaryVectorMaskOp<float, float>( |
| rv_vector, inst, |
| [](float vs2, float vs1) -> bool { return vs2 > vs1; }); |
| case 8: |
| return RiscVBinaryVectorMaskOp<double, double>( |
| rv_vector, inst, |
| [](double vs2, double vs1) -> bool { return vs2 > vs1; }); |
| default: |
| LOG(ERROR) << "Vmfgt: Illegal sew (" << sew << ")"; |
| rv_vector->set_vector_exception(); |
| return; |
| } |
| } |
| |
| // Vector floating point compare greater than or equal. |
| void Vmfge(const Instruction *inst) { |
| auto *rv_vector = static_cast<CheriotState *>(inst->state())->rv_vector(); |
| int sew = rv_vector->selected_element_width(); |
| switch (sew) { |
| case 4: |
| return RiscVBinaryVectorMaskOp<float, float>( |
| rv_vector, inst, |
| [](float vs2, float vs1) -> bool { return vs2 >= vs1; }); |
| case 8: |
| return RiscVBinaryVectorMaskOp<double, double>( |
| rv_vector, inst, |
| [](double vs2, double vs1) -> bool { return vs2 >= vs1; }); |
| default: |
| LOG(ERROR) << "Vmfge: Illegal sew (" << sew << ")"; |
| rv_vector->set_vector_exception(); |
| return; |
| } |
| } |
| |
| } // namespace cheriot |
| } // namespace sim |
| } // namespace mpact |