diff --git a/CMakeLists.txt b/CMakeLists.txt index 454de86..f3abac3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,7 @@ set(LIB_SOURCES src/iss/arch/rv32gc.cpp src/iss/arch/rv32gcv.cpp src/iss/arch/rv64i.cpp + src/iss/arch/rv64imac.cpp src/iss/arch/rv64gc.cpp src/iss/arch/rv64gcv.cpp src/iss/arch/tgc5c.cpp @@ -70,6 +71,7 @@ set(LIB_SOURCES src/vm/interp/vm_rv32gc.cpp src/vm/interp/vm_rv32gcv.cpp src/vm/interp/vm_rv64i.cpp + src/vm/interp/vm_rv64imac.cpp src/vm/interp/vm_rv64gc.cpp src/vm/interp/vm_rv64gcv.cpp src/iss/debugger/csr_names.cpp @@ -102,6 +104,7 @@ if(WITH_ASMJIT) src/vm/asmjit/vm_rv32gc.cpp src/vm/asmjit/vm_rv32gcv.cpp src/vm/asmjit/vm_rv64i.cpp + src/vm/asmjit/vm_rv64imac.cpp src/vm/asmjit/vm_rv64gc.cpp src/vm/asmjit/vm_rv64gcv.cpp ) diff --git a/contrib/instr/RV64IMAC_instr.yaml b/contrib/instr/RV64IMAC_instr.yaml new file mode 100644 index 0000000..f801c62 --- /dev/null +++ b/contrib/instr/RV64IMAC_instr.yaml @@ -0,0 +1,977 @@ + +RVI: + LUI: + index: 0 + encoding: 0b00000000000000000000000000110111 + mask: 0b00000000000000000000000001111111 + size: 32 + branch: false + delay: 1 + AUIPC: + index: 1 + encoding: 0b00000000000000000000000000010111 + mask: 0b00000000000000000000000001111111 + size: 32 + branch: false + delay: 1 + JAL: + index: 2 + encoding: 0b00000000000000000000000001101111 + mask: 0b00000000000000000000000001111111 + size: 32 + branch: true + delay: 1 + JALR: + index: 3 + encoding: 0b00000000000000000000000001100111 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,1] + BEQ: + index: 4 + encoding: 0b00000000000000000000000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,1] + BNE: + index: 5 + encoding: 0b00000000000000000001000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,1] + BLT: + index: 6 + encoding: 0b00000000000000000100000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,1] + BGE: + index: 7 + encoding: 0b00000000000000000101000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,1] + BLTU: + index: 8 + encoding: 0b00000000000000000110000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,1] + BGEU: + index: 9 + encoding: 0b00000000000000000111000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,1] + LB: + index: 10 + encoding: 0b00000000000000000000000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + LH: + index: 11 + encoding: 0b00000000000000000001000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + LW: + index: 12 + encoding: 0b00000000000000000010000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + LBU: + index: 13 + encoding: 0b00000000000000000100000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + LHU: + index: 14 + encoding: 0b00000000000000000101000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + SB: + index: 15 + encoding: 0b00000000000000000000000000100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + SH: + index: 16 + encoding: 0b00000000000000000001000000100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + SW: + index: 17 + encoding: 0b00000000000000000010000000100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + ADDI: + index: 18 + encoding: 0b00000000000000000000000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + SLTI: + index: 19 + encoding: 0b00000000000000000010000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + SLTIU: + index: 20 + encoding: 0b00000000000000000011000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + XORI: + index: 21 + encoding: 0b00000000000000000100000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + ORI: + index: 22 + encoding: 0b00000000000000000110000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + ANDI: + index: 23 + encoding: 0b00000000000000000111000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + SLLI: + index: 24 + encoding: 0b00000000000000000001000000010011 + mask: 0b11111100000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + SRLI: + index: 25 + encoding: 0b00000000000000000101000000010011 + mask: 0b11111100000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + SRAI: + index: 26 + encoding: 0b01000000000000000101000000010011 + mask: 0b11111100000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + ADD: + index: 27 + encoding: 0b00000000000000000000000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SUB: + index: 28 + encoding: 0b01000000000000000000000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SLL: + index: 29 + encoding: 0b00000000000000000001000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SLT: + index: 30 + encoding: 0b00000000000000000010000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SLTU: + index: 31 + encoding: 0b00000000000000000011000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + XOR: + index: 32 + encoding: 0b00000000000000000100000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SRL: + index: 33 + encoding: 0b00000000000000000101000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SRA: + index: 34 + encoding: 0b01000000000000000101000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + OR: + index: 35 + encoding: 0b00000000000000000110000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + AND: + index: 36 + encoding: 0b00000000000000000111000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + FENCE: + index: 37 + encoding: 0b00000000000000000000000000001111 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + ECALL: + index: 38 + encoding: 0b00000000000000000000000001110011 + mask: 0b11111111111111111111111111111111 + attributes: [[name:no_cont]] + size: 32 + branch: false + delay: 1 + EBREAK: + index: 39 + encoding: 0b00000000000100000000000001110011 + mask: 0b11111111111111111111111111111111 + attributes: [[name:no_cont]] + size: 32 + branch: false + delay: 1 + MRET: + index: 40 + encoding: 0b00110000001000000000000001110011 + mask: 0b11111111111111111111111111111111 + attributes: [[name:no_cont]] + size: 32 + branch: false + delay: 1 + WFI: + index: 41 + encoding: 0b00010000010100000000000001110011 + mask: 0b11111111111111111111111111111111 + size: 32 + branch: false + delay: 1 + LWU: + index: 42 + encoding: 0b00000000000000000110000000000011 + mask: 0b00000000000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + LD: + index: 43 + encoding: 0b00000000000000000011000000000011 + mask: 0b00000000000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + SD: + index: 44 + encoding: 0b00000000000000000011000000100011 + mask: 0b00000000000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + ADDIW: + index: 45 + encoding: 0b00000000000000000000000000011011 + mask: 0b00000000000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + SLLIW: + index: 46 + encoding: 0b00000000000000000001000000011011 + mask: 0b11111110000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + SRLIW: + index: 47 + encoding: 0b00000000000000000101000000011011 + mask: 0b11111110000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + SRAIW: + index: 48 + encoding: 0b01000000000000000101000000011011 + mask: 0b11111110000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + ADDW: + index: 49 + encoding: 0b00000000000000000000000000111011 + mask: 0b11111110000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + SUBW: + index: 50 + encoding: 0b01000000000000000000000000111011 + mask: 0b11111110000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + SLLW: + index: 51 + encoding: 0b00000000000000000001000000111011 + mask: 0b11111110000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + SRLW: + index: 52 + encoding: 0b00000000000000000101000000111011 + mask: 0b11111110000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + SRAW: + index: 53 + encoding: 0b01000000000000000101000000111011 + mask: 0b11111110000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 +Zicsr: + CSRRW: + index: 54 + encoding: 0b00000000000000000001000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + CSRRS: + index: 55 + encoding: 0b00000000000000000010000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + CSRRC: + index: 56 + encoding: 0b00000000000000000011000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + CSRRWI: + index: 57 + encoding: 0b00000000000000000101000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + CSRRSI: + index: 58 + encoding: 0b00000000000000000110000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + CSRRCI: + index: 59 + encoding: 0b00000000000000000111000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 +Zifencei: + FENCE_I: + index: 60 + encoding: 0b00000000000000000001000000001111 + mask: 0b00000000000000000111000001111111 + attributes: [[name:flush]] + size: 32 + branch: false + delay: 1 +RVM: + MUL: + index: 61 + encoding: 0b00000010000000000000000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + MULH: + index: 62 + encoding: 0b00000010000000000001000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + MULHSU: + index: 63 + encoding: 0b00000010000000000010000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + MULHU: + index: 64 + encoding: 0b00000010000000000011000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + DIV: + index: 65 + encoding: 0b00000010000000000100000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + DIVU: + index: 66 + encoding: 0b00000010000000000101000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + REM: + index: 67 + encoding: 0b00000010000000000110000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + REMU: + index: 68 + encoding: 0b00000010000000000111000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + MULW: + index: 69 + encoding: 0b00000010000000000000000000111011 + mask: 0b11111110000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + DIVW: + index: 70 + encoding: 0b00000010000000000100000000111011 + mask: 0b11111110000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + DIVUW: + index: 71 + encoding: 0b00000010000000000101000000111011 + mask: 0b11111110000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + REMW: + index: 72 + encoding: 0b00000010000000000110000000111011 + mask: 0b11111110000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + REMUW: + index: 73 + encoding: 0b00000010000000000111000000111011 + mask: 0b11111110000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 +RVA: + LRW: + index: 74 + encoding: 0b00010000000000000010000000101111 + mask: 0b11111001111100000111000001111111 + size: 32 + branch: false + delay: 1 + SCW: + index: 75 + encoding: 0b00011000000000000010000000101111 + mask: 0b11111000000000000111000001111111 + size: 32 + branch: false + delay: 1 + AMOSWAPW: + index: 76 + encoding: 0b00001000000000000010000000101111 + mask: 0b11111000000000000111000001111111 + size: 32 + branch: false + delay: 1 + AMOADDW: + index: 77 + encoding: 0b00000000000000000010000000101111 + mask: 0b11111000000000000111000001111111 + size: 32 + branch: false + delay: 1 + AMOXORW: + index: 78 + encoding: 0b00100000000000000010000000101111 + mask: 0b11111000000000000111000001111111 + size: 32 + branch: false + delay: 1 + AMOANDW: + index: 79 + encoding: 0b01100000000000000010000000101111 + mask: 0b11111000000000000111000001111111 + size: 32 + branch: false + delay: 1 + AMOORW: + index: 80 + encoding: 0b01000000000000000010000000101111 + mask: 0b11111000000000000111000001111111 + size: 32 + branch: false + delay: 1 + AMOMINW: + index: 81 + encoding: 0b10000000000000000010000000101111 + mask: 0b11111000000000000111000001111111 + size: 32 + branch: false + delay: 1 + AMOMAXW: + index: 82 + encoding: 0b10100000000000000010000000101111 + mask: 0b11111000000000000111000001111111 + size: 32 + branch: false + delay: 1 + AMOMINUW: + index: 83 + encoding: 0b11000000000000000010000000101111 + mask: 0b11111000000000000111000001111111 + size: 32 + branch: false + delay: 1 + AMOMAXUW: + index: 84 + encoding: 0b11100000000000000010000000101111 + mask: 0b11111000000000000111000001111111 + size: 32 + branch: false + delay: 1 + LRD: + index: 85 + encoding: 0b00010000000000000011000000101111 + mask: 0b11111001111100000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + SCD: + index: 86 + encoding: 0b00011000000000000011000000101111 + mask: 0b11111000000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + AMOSWAPD: + index: 87 + encoding: 0b00001000000000000011000000101111 + mask: 0b11111000000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + AMOADDD: + index: 88 + encoding: 0b00000000000000000011000000101111 + mask: 0b11111000000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + AMOXORD: + index: 89 + encoding: 0b00100000000000000011000000101111 + mask: 0b11111000000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + AMOANDD: + index: 90 + encoding: 0b01100000000000000011000000101111 + mask: 0b11111000000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + AMOORD: + index: 91 + encoding: 0b01000000000000000011000000101111 + mask: 0b11111000000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + AMOMIND: + index: 92 + encoding: 0b10000000000000000011000000101111 + mask: 0b11111000000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + AMOMAXD: + index: 93 + encoding: 0b10100000000000000011000000101111 + mask: 0b11111000000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + AMOMINUD: + index: 94 + encoding: 0b11000000000000000011000000101111 + mask: 0b11111000000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 + AMOMAXUD: + index: 95 + encoding: 0b11100000000000000011000000101111 + mask: 0b11111000000000000111000001111111 + attributes: [[name:enable, value:1]] + size: 32 + branch: false + delay: 1 +Zca: + C__ADDI4SPN: + index: 96 + encoding: 0b0000000000000000 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__LW: + index: 97 + encoding: 0b0100000000000000 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__LD: + index: 98 + encoding: 0b0110000000000000 + mask: 0b1110000000000011 + attributes: [[name:enable, value:1]] + size: 16 + branch: false + delay: 1 + C__SW: + index: 99 + encoding: 0b1100000000000000 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__SD: + index: 100 + encoding: 0b1110000000000000 + mask: 0b1110000000000011 + attributes: [[name:enable, value:1]] + size: 16 + branch: false + delay: 1 + C__ADDI: + index: 101 + encoding: 0b0000000000000001 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__NOP: + index: 102 + encoding: 0b0000000000000001 + mask: 0b1110111110000011 + size: 16 + branch: false + delay: 1 + C__ADDIW: + index: 103 + encoding: 0b0010000000000001 + mask: 0b1110000000000011 + attributes: [[name:enable, value:1]] + size: 16 + branch: false + delay: 1 + C__LI: + index: 104 + encoding: 0b0100000000000001 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__LUI: + index: 105 + encoding: 0b0110000000000001 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__ADDI16SP: + index: 106 + encoding: 0b0110000100000001 + mask: 0b1110111110000011 + size: 16 + branch: false + delay: 1 + __reserved_clui: + index: 107 + encoding: 0b0110000000000001 + mask: 0b1111000001111111 + size: 16 + branch: false + delay: 1 + C__SRLI: + index: 108 + encoding: 0b1000000000000001 + mask: 0b1110110000000011 + attributes: [[name:enable, value:1]] + size: 16 + branch: false + delay: 1 + C__SRAI: + index: 109 + encoding: 0b1000010000000001 + mask: 0b1110110000000011 + attributes: [[name:enable, value:1]] + size: 16 + branch: false + delay: 1 + C__ANDI: + index: 110 + encoding: 0b1000100000000001 + mask: 0b1110110000000011 + size: 16 + branch: false + delay: 1 + C__SUB: + index: 111 + encoding: 0b1000110000000001 + mask: 0b1111110001100011 + size: 16 + branch: false + delay: 1 + C__XOR: + index: 112 + encoding: 0b1000110000100001 + mask: 0b1111110001100011 + size: 16 + branch: false + delay: 1 + C__OR: + index: 113 + encoding: 0b1000110001000001 + mask: 0b1111110001100011 + size: 16 + branch: false + delay: 1 + C__AND: + index: 114 + encoding: 0b1000110001100001 + mask: 0b1111110001100011 + size: 16 + branch: false + delay: 1 + C__SUBW: + index: 115 + encoding: 0b1001110000000001 + mask: 0b1111110001100011 + attributes: [[name:enable, value:1]] + size: 16 + branch: false + delay: 1 + C__ADDW: + index: 116 + encoding: 0b1001110000100001 + mask: 0b1111110001100011 + attributes: [[name:enable, value:1]] + size: 16 + branch: false + delay: 1 + C__J: + index: 117 + encoding: 0b1010000000000001 + mask: 0b1110000000000011 + size: 16 + branch: true + delay: 1 + C__BEQZ: + index: 118 + encoding: 0b1100000000000001 + mask: 0b1110000000000011 + size: 16 + branch: true + delay: [1,1] + C__BNEZ: + index: 119 + encoding: 0b1110000000000001 + mask: 0b1110000000000011 + size: 16 + branch: true + delay: [1,1] + C__SLLI: + index: 120 + encoding: 0b0000000000000010 + mask: 0b1110000000000011 + attributes: [[name:enable, value:1]] + size: 16 + branch: false + delay: 1 + C__LWSP: + index: 121 + encoding: 0b0100000000000010 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__LDSP: + index: 122 + encoding: 0b0110000000000010 + mask: 0b1110000000000011 + attributes: [[name:enable, value:1]] + size: 16 + branch: false + delay: 1 + C__MV: + index: 123 + encoding: 0b1000000000000010 + mask: 0b1111000000000011 + size: 16 + branch: false + delay: 1 + C__JR: + index: 124 + encoding: 0b1000000000000010 + mask: 0b1111000001111111 + size: 16 + branch: true + delay: 1 + __reserved_cmv: + index: 125 + encoding: 0b1000000000000010 + mask: 0b1111111111111111 + size: 16 + branch: false + delay: 1 + C__ADD: + index: 126 + encoding: 0b1001000000000010 + mask: 0b1111000000000011 + size: 16 + branch: false + delay: 1 + C__JALR: + index: 127 + encoding: 0b1001000000000010 + mask: 0b1111000001111111 + size: 16 + branch: true + delay: 1 + C__EBREAK: + index: 128 + encoding: 0b1001000000000010 + mask: 0b1111111111111111 + size: 16 + branch: false + delay: 1 + C__SWSP: + index: 129 + encoding: 0b1100000000000010 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__SDSP: + index: 130 + encoding: 0b1110000000000010 + mask: 0b1110000000000011 + attributes: [[name:enable, value:1]] + size: 16 + branch: false + delay: 1 + DII: + index: 131 + encoding: 0b0000000000000000 + mask: 0b1111111111111111 + size: 16 + branch: false + delay: 1 + diff --git a/gen_input/ISA b/gen_input/ISA index c59cf8b..4cb1545 160000 --- a/gen_input/ISA +++ b/gen_input/ISA @@ -1 +1 @@ -Subproject commit c59cf8b79ddba1d43720960b37db52f9cbd13c7b +Subproject commit 4cb1545f57007dca155f3453ff9961325aac7246 diff --git a/gen_input/cores.core_desc b/gen_input/cores.core_desc index d59e0cc..21b25cd 100644 --- a/gen_input/cores.core_desc +++ b/gen_input/cores.core_desc @@ -10,9 +10,7 @@ import "ISA/RVV/RVV.core_desc" Core RV32I provides RVI, Zicsr, Zifencei { architectural_state { XLEN=32; - // definitions for the architecture wrapper - // XL ZYXWVUTSRQPONMLKJIHGFEDCBA - unsigned MISA_VAL = 0b01000000000000000000000100000000; + unsigned MISA_VAL = 0x40000100; unsigned int MARCHID_VAL = 0x00000000; unsigned int CLIC_NUM_IRQ = 0; } @@ -21,9 +19,7 @@ Core RV32I provides RVI, Zicsr, Zifencei { Core RV32IMAC provides RVI, Zicsr, Zifencei, RVM, RVA, Zca { architectural_state { XLEN=32; - // definitions for the architecture wrapper - // XL ZYXWVUTSRQPONMLKJIHGFEDCBA - unsigned MISA_VAL = 0b01000000000000000001000100000101; + unsigned MISA_VAL = 0x40001105; unsigned int MARCHID_VAL = 0x00000000; unsigned int CLIC_NUM_IRQ = 0; } @@ -33,9 +29,7 @@ Core RV32GC provides RVI, Zicsr, Zifencei, RVM, RVA, Zca, Zcf, Zcd, RVSMode { architectural_state { XLEN=32; FLEN=64; - // definitions for the architecture wrapper - // XL ZYXWVUTSRQPONMLKJIHGFEDCBA - unsigned MISA_VAL = 0b01000000000000000001000100101101; + unsigned MISA_VAL = 0x4000112d; unsigned int MARCHID_VAL = 0x00000000; unsigned int CLIC_NUM_IRQ = 0; } @@ -47,9 +41,7 @@ Core RV32GCV provides RVI, Zicsr, Zifencei, RVM, RVA, Zca, Zcf, Zcd, RVSMode, RV FLEN=64; VLEN=256; ELEN=32; - // definitions for the architecture wrapper - // XL ZYXWVUTSRQPONMLKJIHGFEDCBA - unsigned MISA_VAL = 0b01000000000000000001000100101101; + unsigned MISA_VAL = 0x4020112d; unsigned int MARCHID_VAL = 0x00000000; unsigned int CLIC_NUM_IRQ = 0; } @@ -58,8 +50,16 @@ Core RV32GCV provides RVI, Zicsr, Zifencei, RVM, RVA, Zca, Zcf, Zcd, RVSMode, RV Core RV64I provides RVI, Zicsr, Zifencei { architectural_state { XLEN=64; - // definitions for the architecture wrapper - unsigned MISA_VAL = 0x80000100; + unsigned MISA_VAL = 0x8000000000000100; + unsigned int MARCHID_VAL = 0x00000000; + unsigned int CLIC_NUM_IRQ = 0; + } +} + +Core RV64IMAC provides RVI, Zicsr, Zifencei, RVM, RVA, Zca { + architectural_state { + XLEN=64; + unsigned MISA_VAL = 0x8000000000001105; unsigned int MARCHID_VAL = 0x00000000; unsigned int CLIC_NUM_IRQ = 0; } @@ -69,7 +69,6 @@ Core RV64GC provides RVI, Zicsr, Zifencei, RVM, RVA, Zca, Zcd, RVSMode { architectural_state { XLEN=64; FLEN=64; - // definitions for the architecture wrapper unsigned MISA_VAL = 0x800000000000112d; unsigned int MARCHID_VAL = 0x00000000; unsigned int CLIC_NUM_IRQ = 0; @@ -82,13 +81,12 @@ Core RV64GCV provides RVI, Zicsr, Zifencei, RVM, RVA, Zca, Zcd, RVSMode, RVVBase FLEN=64; VLEN=512; ELEN=64; - // definitions for the architecture wrapper - unsigned MISA_VAL = 0x800000000000112d; + unsigned MISA_VAL = 0x800000000020112d; unsigned int MARCHID_VAL = 0x00000000; unsigned int CLIC_NUM_IRQ = 0; } } /* -for b in interp asmjit; do for i in RV32I RV32IMAC RV32IMACF RV32GC RV64I RV64GC; do ./build/TGC-GEN/scripts/generate_iss.sh -b $b -o . -m src -r gen_input -t gen_input/templates -c $i gen_input/cores.core_desc; done ; done +for b in interp asmjit; do for i in RV32I RV32IMAC RV32GC RV32GCV RV64I RV64IMAC RV64GC RV64GCV; do ./build/TGC-GEN/scripts/generate_iss.sh -b $b -o . -m src -r gen_input -t gen_input/templates -c $i gen_input/cores.core_desc; done ; done */ diff --git a/src/iss/arch/rv32gc.h b/src/iss/arch/rv32gc.h index fa00f7e..c4a6646 100644 --- a/src/iss/arch/rv32gc.h +++ b/src/iss/arch/rv32gc.h @@ -162,8 +162,6 @@ struct rv32gc: public arch_if { }; -struct rv32gc; - template <> struct traits { constexpr static char const* const core_type = "RV32GC"; diff --git a/src/iss/arch/rv32gcv.h b/src/iss/arch/rv32gcv.h index c7d4cd9..78b791a 100644 --- a/src/iss/arch/rv32gcv.h +++ b/src/iss/arch/rv32gcv.h @@ -199,8 +199,6 @@ struct rv32gcv: public arch_if { }; -struct rv32gcv; - template <> struct traits { constexpr static char const* const core_type = "RV32GCV"; @@ -335,7 +333,7 @@ template <> struct traits { FFLAG_MASK=31ULL, VLEN=256ULL, ELEN=32ULL, EEW_MAX=32ULL, FP_SEW_MIN=32ULL, FP_SEW_MAX=64ULL, VSTART_ADDR=8ULL, VXSAT_ADDR=9ULL, VXRM_ADDR=10ULL, VCSR_ADDR=15ULL, VL_ADDR=3104ULL, VTYPE_ADDR=3105ULL, - VLENB_ADDR=3106ULL, MISA_VAL=1073746221ULL, MARCHID_VAL=0ULL, CLIC_NUM_IRQ=0ULL + VLENB_ADDR=3106ULL, MISA_VAL=1075843373ULL, MARCHID_VAL=0ULL, CLIC_NUM_IRQ=0ULL }; diff --git a/src/iss/arch/rv32i.h b/src/iss/arch/rv32i.h index 4a8d6b9..0c3d7bb 100644 --- a/src/iss/arch/rv32i.h +++ b/src/iss/arch/rv32i.h @@ -129,8 +129,6 @@ struct rv32i: public arch_if { }; -struct rv32i; - template <> struct traits { constexpr static char const* const core_type = "RV32I"; diff --git a/src/iss/arch/rv32imac.h b/src/iss/arch/rv32imac.h index a61f5dc..f0a500c 100644 --- a/src/iss/arch/rv32imac.h +++ b/src/iss/arch/rv32imac.h @@ -129,8 +129,6 @@ struct rv32imac: public arch_if { }; -struct rv32imac; - template <> struct traits { constexpr static char const* const core_type = "RV32IMAC"; diff --git a/src/iss/arch/rv64gc.h b/src/iss/arch/rv64gc.h index 9b1b427..aca78ae 100644 --- a/src/iss/arch/rv64gc.h +++ b/src/iss/arch/rv64gc.h @@ -162,8 +162,6 @@ struct rv64gc: public arch_if { }; -struct rv64gc; - template <> struct traits { constexpr static char const* const core_type = "RV64GC"; diff --git a/src/iss/arch/rv64gcv.h b/src/iss/arch/rv64gcv.h index 2294278..2be8f96 100644 --- a/src/iss/arch/rv64gcv.h +++ b/src/iss/arch/rv64gcv.h @@ -199,8 +199,6 @@ struct rv64gcv: public arch_if { }; -struct rv64gcv; - template <> struct traits { constexpr static char const* const core_type = "RV64GCV"; @@ -335,7 +333,7 @@ template <> struct traits { FFLAG_MASK=31ULL, VLEN=512ULL, ELEN=64ULL, EEW_MAX=64ULL, FP_SEW_MIN=32ULL, FP_SEW_MAX=64ULL, VSTART_ADDR=8ULL, VXSAT_ADDR=9ULL, VXRM_ADDR=10ULL, VCSR_ADDR=15ULL, VL_ADDR=3104ULL, VTYPE_ADDR=3105ULL, - VLENB_ADDR=3106ULL, MISA_VAL=9223372036854780205ULL, MARCHID_VAL=0ULL, CLIC_NUM_IRQ=0ULL + VLENB_ADDR=3106ULL, MISA_VAL=9223372036856877357ULL, MARCHID_VAL=0ULL, CLIC_NUM_IRQ=0ULL }; diff --git a/src/iss/arch/rv64i.h b/src/iss/arch/rv64i.h index 0a74d68..cf54cb3 100644 --- a/src/iss/arch/rv64i.h +++ b/src/iss/arch/rv64i.h @@ -129,8 +129,6 @@ struct rv64i: public arch_if { }; -struct rv64i; - template <> struct traits { constexpr static char const* const core_type = "RV64I"; @@ -261,7 +259,7 @@ template <> struct traits { RV_MIP_MTIP=128ULL, RV_MIP_UEIP=256ULL, RV_MIP_SEIP=512ULL, RV_MIP_VSEIP=1024ULL, RV_MIP_MEIP=2048ULL, RV_MIP_SGEIP=4096ULL, RV_MIP_LCOFIP=8192ULL, XLEN=64ULL, FLEN=0ULL, INSTR_ALIGNMENT=4ULL, RFS=32ULL, fence=0ULL, - fencei=1ULL, fencevma=2ULL, CSR_SIZE=4096ULL, MISA_VAL=2147483904ULL, + fencei=1ULL, fencevma=2ULL, CSR_SIZE=4096ULL, MISA_VAL=9223372036854776064ULL, MARCHID_VAL=0ULL, CLIC_NUM_IRQ=0ULL }; diff --git a/src/iss/arch/rv64imac.cpp b/src/iss/arch/rv64imac.cpp new file mode 100644 index 0000000..ce78811 --- /dev/null +++ b/src/iss/arch/rv64imac.cpp @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (C) 2024 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +// clang-format off +#include "rv64imac.h" +#include "util/ities.h" +#include +#include +#include +#include + +using namespace iss::arch; + +constexpr std::array iss::arch::traits::reg_names; +constexpr std::array iss::arch::traits::reg_aliases; +constexpr std::array iss::arch::traits::reg_bit_widths; +constexpr std::array iss::arch::traits::reg_byte_offsets; + +rv64imac::rv64imac() = default; + +rv64imac::~rv64imac() = default; + +void rv64imac::reset(uint64_t address) { + auto base_ptr = reinterpret_cast::reg_t*>(get_regs_base_ptr()); + for(size_t i=0; i::NUM_REGS; ++i) + *(base_ptr+i)=0; + reg.PC=address; + reg.NEXT_PC=reg.PC; + reg.PRIV=0x3; + reg.trap_state=0; + reg.icount=0; +} + +uint8_t *rv64imac::get_regs_base_ptr() { + return reinterpret_cast(®); +} + +rv64imac::phys_addr_t rv64imac::virt2phys(const iss::addr_t &addr) { + return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); +} +// clang-format on diff --git a/src/iss/arch/rv64imac.h b/src/iss/arch/rv64imac.h new file mode 100644 index 0000000..05bf15a --- /dev/null +++ b/src/iss/arch/rv64imac.h @@ -0,0 +1,531 @@ +/******************************************************************************* + * Copyright (C) 2024 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +#ifndef _RV64IMAC_H_ +#define _RV64IMAC_H_ +// clang-format off +#include +#include +#include +#include + +namespace iss { +namespace arch { + +struct rv64imac: public arch_if { + + using reg_t = uint64_t; + + using virt_addr_t = iss::virt_addr_t; + + using phys_addr_t = iss::phys_addr_t; + + rv64imac(); + ~rv64imac(); + + void reset(uint64_t address=0) override; + + uint8_t* get_regs_base_ptr() override; + + inline bool should_stop() { return interrupt_sim; } + + inline uint64_t stop_code() { return interrupt_sim; } + + virtual phys_addr_t virt2phys(const iss::addr_t& addr); + + virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } + + virtual void enable_disass(bool) = 0; + + struct RV64IMAC_regs { + uint64_t X0 = 0; + uint64_t X1 = 0; + uint64_t X2 = 0; + uint64_t X3 = 0; + uint64_t X4 = 0; + uint64_t X5 = 0; + uint64_t X6 = 0; + uint64_t X7 = 0; + uint64_t X8 = 0; + uint64_t X9 = 0; + uint64_t X10 = 0; + uint64_t X11 = 0; + uint64_t X12 = 0; + uint64_t X13 = 0; + uint64_t X14 = 0; + uint64_t X15 = 0; + uint64_t X16 = 0; + uint64_t X17 = 0; + uint64_t X18 = 0; + uint64_t X19 = 0; + uint64_t X20 = 0; + uint64_t X21 = 0; + uint64_t X22 = 0; + uint64_t X23 = 0; + uint64_t X24 = 0; + uint64_t X25 = 0; + uint64_t X26 = 0; + uint64_t X27 = 0; + uint64_t X28 = 0; + uint64_t X29 = 0; + uint64_t X30 = 0; + uint64_t X31 = 0; + uint64_t PC = 0; + uint64_t NEXT_PC = 0; + uint8_t PRIV = 0; + uint64_t DPC = 0; + uint32_t trap_state = 0, pending_trap = 0; + uint64_t icount = 0; + uint64_t cycle = 0; + uint64_t instret = 0; + uint32_t instruction = 0; + uint32_t last_branch = 0; + } reg; + + std::array addr_mode; + + uint64_t interrupt_sim=0; + + uint32_t get_fcsr(){return 0;} + void set_fcsr(uint32_t val){} + + uint32_t get_vstart(){return 0;} + void set_vstart(uint32_t val){} + uint32_t get_vl(){return 0;} + uint32_t get_vtype(){return 0;} + uint32_t get_vxsat(){return 0;} + void set_vxsat(uint32_t val){} + uint32_t get_vxrm(){return 0;} + void set_vxrm(uint32_t val){} + +}; + +template <> struct traits { + + constexpr static char const* const core_type = "RV64IMAC"; + + static constexpr std::array reg_names{ + {"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc", "next_pc", "priv", "dpc"}}; + + static constexpr std::array reg_aliases{ + {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "next_pc", "priv", "dpc"}}; + + enum constants { + RV_CSR_FFLAGS=1ULL, RV_CSR_FRM=2ULL, RV_CSR_FCSR=3ULL, RV_CSR_UTVT=7ULL, + RV_CSR_VSTART=8ULL, RV_CSR_VXSAT=9ULL, RV_CSR_VXRM=10ULL, RV_CSR_VCSR=15ULL, + RV_CSR_SEED=21ULL, RV_CSR_UNXTI=69ULL, RV_CSR_UINTSTATUS=70ULL, RV_CSR_USCRATCHCSW=72ULL, + RV_CSR_USCRATCHCSWL=73ULL, RV_CSR_SSTATUS=256ULL, RV_CSR_SEDELEG=258ULL, RV_CSR_SIDELEG=259ULL, + RV_CSR_SIE=260ULL, RV_CSR_STVEC=261ULL, RV_CSR_SCOUNTEREN=262ULL, RV_CSR_STVT=263ULL, + RV_CSR_SENVCFG=266ULL, RV_CSR_SSTATEEN0=268ULL, RV_CSR_SSTATEEN1=269ULL, RV_CSR_SSTATEEN2=270ULL, + RV_CSR_SSTATEEN3=271ULL, RV_CSR_SSCRATCH=320ULL, RV_CSR_SEPC=321ULL, RV_CSR_SCAUSE=322ULL, + RV_CSR_STVAL=323ULL, RV_CSR_SIP=324ULL, RV_CSR_SNXTI=325ULL, RV_CSR_SINTSTATUS=326ULL, + RV_CSR_SSCRATCHCSW=328ULL, RV_CSR_SSCRATCHCSWL=329ULL, RV_CSR_STIMECMP=333ULL, RV_CSR_STIMECMPH=349ULL, + RV_CSR_SATP=384ULL, RV_CSR_VSSTATUS=512ULL, RV_CSR_VSIE=516ULL, RV_CSR_VSTVEC=517ULL, + RV_CSR_VSSCRATCH=576ULL, RV_CSR_VSEPC=577ULL, RV_CSR_VSCAUSE=578ULL, RV_CSR_VSTVAL=579ULL, + RV_CSR_VSIP=580ULL, RV_CSR_VSTIMECMP=589ULL, RV_CSR_VSTIMECMPH=605ULL, RV_CSR_VSATP=640ULL, + RV_CSR_MSTATUS=768ULL, RV_CSR_MISA=769ULL, RV_CSR_MEDELEG=770ULL, RV_CSR_MIDELEG=771ULL, + RV_CSR_MIE=772ULL, RV_CSR_MTVEC=773ULL, RV_CSR_MCOUNTEREN=774ULL, RV_CSR_MTVT=775ULL, + RV_CSR_MENVCFG=778ULL, RV_CSR_MSTATEEN0=780ULL, RV_CSR_MSTATEEN1=781ULL, RV_CSR_MSTATEEN2=782ULL, + RV_CSR_MSTATEEN3=783ULL, RV_CSR_MSTATUSH=784ULL, RV_CSR_MENVCFGH=794ULL, RV_CSR_MSTATEEN0H=796ULL, + RV_CSR_MSTATEEN1H=797ULL, RV_CSR_MSTATEEN2H=798ULL, RV_CSR_MSTATEEN3H=799ULL, RV_CSR_MCOUNTINHIBIT=800ULL, + RV_CSR_MHPMEVENT3=803ULL, RV_CSR_MHPMEVENT4=804ULL, RV_CSR_MHPMEVENT5=805ULL, RV_CSR_MHPMEVENT6=806ULL, + RV_CSR_MHPMEVENT7=807ULL, RV_CSR_MHPMEVENT8=808ULL, RV_CSR_MHPMEVENT9=809ULL, RV_CSR_MHPMEVENT10=810ULL, + RV_CSR_MHPMEVENT11=811ULL, RV_CSR_MHPMEVENT12=812ULL, RV_CSR_MHPMEVENT13=813ULL, RV_CSR_MHPMEVENT14=814ULL, + RV_CSR_MHPMEVENT15=815ULL, RV_CSR_MHPMEVENT16=816ULL, RV_CSR_MHPMEVENT17=817ULL, RV_CSR_MHPMEVENT18=818ULL, + RV_CSR_MHPMEVENT19=819ULL, RV_CSR_MHPMEVENT20=820ULL, RV_CSR_MHPMEVENT21=821ULL, RV_CSR_MHPMEVENT22=822ULL, + RV_CSR_MHPMEVENT23=823ULL, RV_CSR_MHPMEVENT24=824ULL, RV_CSR_MHPMEVENT25=825ULL, RV_CSR_MHPMEVENT26=826ULL, + RV_CSR_MHPMEVENT27=827ULL, RV_CSR_MHPMEVENT28=828ULL, RV_CSR_MHPMEVENT29=829ULL, RV_CSR_MHPMEVENT30=830ULL, + RV_CSR_MHPMEVENT31=831ULL, RV_CSR_MSCRATCH=832ULL, RV_CSR_MEPC=833ULL, RV_CSR_MCAUSE=834ULL, + RV_CSR_MTVAL=835ULL, RV_CSR_MIP=836ULL, RV_CSR_MNXTI=837ULL, RV_CSR_MINTSTATUS=838ULL, + RV_CSR_MSCRATCHCSW=840ULL, RV_CSR_MSCRATCHCSWL=841ULL, RV_CSR_MTINST=842ULL, RV_CSR_MTVAL2=843ULL, + RV_CSR_PMPCFG0=928ULL, RV_CSR_PMPCFG1=929ULL, RV_CSR_PMPCFG2=930ULL, RV_CSR_PMPCFG3=931ULL, + RV_CSR_PMPCFG4=932ULL, RV_CSR_PMPCFG5=933ULL, RV_CSR_PMPCFG6=934ULL, RV_CSR_PMPCFG7=935ULL, + RV_CSR_PMPCFG8=936ULL, RV_CSR_PMPCFG9=937ULL, RV_CSR_PMPCFG10=938ULL, RV_CSR_PMPCFG11=939ULL, + RV_CSR_PMPCFG12=940ULL, RV_CSR_PMPCFG13=941ULL, RV_CSR_PMPCFG14=942ULL, RV_CSR_PMPCFG15=943ULL, + RV_CSR_PMPADDR0=944ULL, RV_CSR_PMPADDR1=945ULL, RV_CSR_PMPADDR2=946ULL, RV_CSR_PMPADDR3=947ULL, + RV_CSR_PMPADDR4=948ULL, RV_CSR_PMPADDR5=949ULL, RV_CSR_PMPADDR6=950ULL, RV_CSR_PMPADDR7=951ULL, + RV_CSR_PMPADDR8=952ULL, RV_CSR_PMPADDR9=953ULL, RV_CSR_PMPADDR10=954ULL, RV_CSR_PMPADDR11=955ULL, + RV_CSR_PMPADDR12=956ULL, RV_CSR_PMPADDR13=957ULL, RV_CSR_PMPADDR14=958ULL, RV_CSR_PMPADDR15=959ULL, + RV_CSR_PMPADDR16=960ULL, RV_CSR_PMPADDR17=961ULL, RV_CSR_PMPADDR18=962ULL, RV_CSR_PMPADDR19=963ULL, + RV_CSR_PMPADDR20=964ULL, RV_CSR_PMPADDR21=965ULL, RV_CSR_PMPADDR22=966ULL, RV_CSR_PMPADDR23=967ULL, + RV_CSR_PMPADDR24=968ULL, RV_CSR_PMPADDR25=969ULL, RV_CSR_PMPADDR26=970ULL, RV_CSR_PMPADDR27=971ULL, + RV_CSR_PMPADDR28=972ULL, RV_CSR_PMPADDR29=973ULL, RV_CSR_PMPADDR30=974ULL, RV_CSR_PMPADDR31=975ULL, + RV_CSR_PMPADDR32=976ULL, RV_CSR_PMPADDR33=977ULL, RV_CSR_PMPADDR34=978ULL, RV_CSR_PMPADDR35=979ULL, + RV_CSR_PMPADDR36=980ULL, RV_CSR_PMPADDR37=981ULL, RV_CSR_PMPADDR38=982ULL, RV_CSR_PMPADDR39=983ULL, + RV_CSR_PMPADDR40=984ULL, RV_CSR_PMPADDR41=985ULL, RV_CSR_PMPADDR42=986ULL, RV_CSR_PMPADDR43=987ULL, + RV_CSR_PMPADDR44=988ULL, RV_CSR_PMPADDR45=989ULL, RV_CSR_PMPADDR46=990ULL, RV_CSR_PMPADDR47=991ULL, + RV_CSR_PMPADDR48=992ULL, RV_CSR_PMPADDR49=993ULL, RV_CSR_PMPADDR50=994ULL, RV_CSR_PMPADDR51=995ULL, + RV_CSR_PMPADDR52=996ULL, RV_CSR_PMPADDR53=997ULL, RV_CSR_PMPADDR54=998ULL, RV_CSR_PMPADDR55=999ULL, + RV_CSR_PMPADDR56=1000ULL, RV_CSR_PMPADDR57=1001ULL, RV_CSR_PMPADDR58=1002ULL, RV_CSR_PMPADDR59=1003ULL, + RV_CSR_PMPADDR60=1004ULL, RV_CSR_PMPADDR61=1005ULL, RV_CSR_PMPADDR62=1006ULL, RV_CSR_PMPADDR63=1007ULL, + RV_CSR_SCONTEXT=1448ULL, RV_CSR_HSTATUS=1536ULL, RV_CSR_HEDELEG=1538ULL, RV_CSR_HIDELEG=1539ULL, + RV_CSR_HIE=1540ULL, RV_CSR_HTIMEDELTA=1541ULL, RV_CSR_HCOUNTEREN=1542ULL, RV_CSR_HGEIE=1543ULL, + RV_CSR_HENVCFG=1546ULL, RV_CSR_HSTATEEN0=1548ULL, RV_CSR_HSTATEEN1=1549ULL, RV_CSR_HSTATEEN2=1550ULL, + RV_CSR_HSTATEEN3=1551ULL, RV_CSR_HTIMEDELTAH=1557ULL, RV_CSR_HENVCFGH=1562ULL, RV_CSR_HSTATEEN0H=1564ULL, + RV_CSR_HSTATEEN1H=1565ULL, RV_CSR_HSTATEEN2H=1566ULL, RV_CSR_HSTATEEN3H=1567ULL, RV_CSR_HTVAL=1603ULL, + RV_CSR_HIP=1604ULL, RV_CSR_HVIP=1605ULL, RV_CSR_HTINST=1610ULL, RV_CSR_HGATP=1664ULL, + RV_CSR_HCONTEXT=1704ULL, RV_CSR_MHPMEVENT3H=1827ULL, RV_CSR_MHPMEVENT4H=1828ULL, RV_CSR_MHPMEVENT5H=1829ULL, + RV_CSR_MHPMEVENT6H=1830ULL, RV_CSR_MHPMEVENT7H=1831ULL, RV_CSR_MHPMEVENT8H=1832ULL, RV_CSR_MHPMEVENT9H=1833ULL, + RV_CSR_MHPMEVENT10H=1834ULL, RV_CSR_MHPMEVENT11H=1835ULL, RV_CSR_MHPMEVENT12H=1836ULL, RV_CSR_MHPMEVENT13H=1837ULL, + RV_CSR_MHPMEVENT14H=1838ULL, RV_CSR_MHPMEVENT15H=1839ULL, RV_CSR_MHPMEVENT16H=1840ULL, RV_CSR_MHPMEVENT17H=1841ULL, + RV_CSR_MHPMEVENT18H=1842ULL, RV_CSR_MHPMEVENT19H=1843ULL, RV_CSR_MHPMEVENT20H=1844ULL, RV_CSR_MHPMEVENT21H=1845ULL, + RV_CSR_MHPMEVENT22H=1846ULL, RV_CSR_MHPMEVENT23H=1847ULL, RV_CSR_MHPMEVENT24H=1848ULL, RV_CSR_MHPMEVENT25H=1849ULL, + RV_CSR_MHPMEVENT26H=1850ULL, RV_CSR_MHPMEVENT27H=1851ULL, RV_CSR_MHPMEVENT28H=1852ULL, RV_CSR_MHPMEVENT29H=1853ULL, + RV_CSR_MHPMEVENT30H=1854ULL, RV_CSR_MHPMEVENT31H=1855ULL, RV_CSR_MSECCFG=1863ULL, RV_CSR_MSECCFGH=1879ULL, + RV_CSR_TSELECT=1952ULL, RV_CSR_TDATA1=1953ULL, RV_CSR_TDATA2=1954ULL, RV_CSR_TDATA3=1955ULL, + RV_CSR_TINFO=1956ULL, RV_CSR_TCONTROL=1957ULL, RV_CSR_MCONTEXT=1960ULL, RV_CSR_MSCONTEXT=1962ULL, + RV_CSR_DCSR=1968ULL, RV_CSR_DPC=1969ULL, RV_CSR_DSCRATCH0=1970ULL, RV_CSR_DSCRATCH1=1971ULL, + RV_CSR_MCYCLE=2816ULL, RV_CSR_MINSTRET=2818ULL, RV_CSR_MHPMCOUNTER3=2819ULL, RV_CSR_MHPMCOUNTER4=2820ULL, + RV_CSR_MHPMCOUNTER5=2821ULL, RV_CSR_MHPMCOUNTER6=2822ULL, RV_CSR_MHPMCOUNTER7=2823ULL, RV_CSR_MHPMCOUNTER8=2824ULL, + RV_CSR_MHPMCOUNTER9=2825ULL, RV_CSR_MHPMCOUNTER10=2826ULL, RV_CSR_MHPMCOUNTER11=2827ULL, RV_CSR_MHPMCOUNTER12=2828ULL, + RV_CSR_MHPMCOUNTER13=2829ULL, RV_CSR_MHPMCOUNTER14=2830ULL, RV_CSR_MHPMCOUNTER15=2831ULL, RV_CSR_MHPMCOUNTER16=2832ULL, + RV_CSR_MHPMCOUNTER17=2833ULL, RV_CSR_MHPMCOUNTER18=2834ULL, RV_CSR_MHPMCOUNTER19=2835ULL, RV_CSR_MHPMCOUNTER20=2836ULL, + RV_CSR_MHPMCOUNTER21=2837ULL, RV_CSR_MHPMCOUNTER22=2838ULL, RV_CSR_MHPMCOUNTER23=2839ULL, RV_CSR_MHPMCOUNTER24=2840ULL, + RV_CSR_MHPMCOUNTER25=2841ULL, RV_CSR_MHPMCOUNTER26=2842ULL, RV_CSR_MHPMCOUNTER27=2843ULL, RV_CSR_MHPMCOUNTER28=2844ULL, + RV_CSR_MHPMCOUNTER29=2845ULL, RV_CSR_MHPMCOUNTER30=2846ULL, RV_CSR_MHPMCOUNTER31=2847ULL, RV_CSR_MCYCLEH=2944ULL, + RV_CSR_MINSTRETH=2946ULL, RV_CSR_MHPMCOUNTER3H=2947ULL, RV_CSR_MHPMCOUNTER4H=2948ULL, RV_CSR_MHPMCOUNTER5H=2949ULL, + RV_CSR_MHPMCOUNTER6H=2950ULL, RV_CSR_MHPMCOUNTER7H=2951ULL, RV_CSR_MHPMCOUNTER8H=2952ULL, RV_CSR_MHPMCOUNTER9H=2953ULL, + RV_CSR_MHPMCOUNTER10H=2954ULL, RV_CSR_MHPMCOUNTER11H=2955ULL, RV_CSR_MHPMCOUNTER12H=2956ULL, RV_CSR_MHPMCOUNTER13H=2957ULL, + RV_CSR_MHPMCOUNTER14H=2958ULL, RV_CSR_MHPMCOUNTER15H=2959ULL, RV_CSR_MHPMCOUNTER16H=2960ULL, RV_CSR_MHPMCOUNTER17H=2961ULL, + RV_CSR_MHPMCOUNTER18H=2962ULL, RV_CSR_MHPMCOUNTER19H=2963ULL, RV_CSR_MHPMCOUNTER20H=2964ULL, RV_CSR_MHPMCOUNTER21H=2965ULL, + RV_CSR_MHPMCOUNTER22H=2966ULL, RV_CSR_MHPMCOUNTER23H=2967ULL, RV_CSR_MHPMCOUNTER24H=2968ULL, RV_CSR_MHPMCOUNTER25H=2969ULL, + RV_CSR_MHPMCOUNTER26H=2970ULL, RV_CSR_MHPMCOUNTER27H=2971ULL, RV_CSR_MHPMCOUNTER28H=2972ULL, RV_CSR_MHPMCOUNTER29H=2973ULL, + RV_CSR_MHPMCOUNTER30H=2974ULL, RV_CSR_MHPMCOUNTER31H=2975ULL, RV_CSR_CYCLE=3072ULL, RV_CSR_TIME=3073ULL, + RV_CSR_INSTRET=3074ULL, RV_CSR_HPMCOUNTER3=3075ULL, RV_CSR_HPMCOUNTER4=3076ULL, RV_CSR_HPMCOUNTER5=3077ULL, + RV_CSR_HPMCOUNTER6=3078ULL, RV_CSR_HPMCOUNTER7=3079ULL, RV_CSR_HPMCOUNTER8=3080ULL, RV_CSR_HPMCOUNTER9=3081ULL, + RV_CSR_HPMCOUNTER10=3082ULL, RV_CSR_HPMCOUNTER11=3083ULL, RV_CSR_HPMCOUNTER12=3084ULL, RV_CSR_HPMCOUNTER13=3085ULL, + RV_CSR_HPMCOUNTER14=3086ULL, RV_CSR_HPMCOUNTER15=3087ULL, RV_CSR_HPMCOUNTER16=3088ULL, RV_CSR_HPMCOUNTER17=3089ULL, + RV_CSR_HPMCOUNTER18=3090ULL, RV_CSR_HPMCOUNTER19=3091ULL, RV_CSR_HPMCOUNTER20=3092ULL, RV_CSR_HPMCOUNTER21=3093ULL, + RV_CSR_HPMCOUNTER22=3094ULL, RV_CSR_HPMCOUNTER23=3095ULL, RV_CSR_HPMCOUNTER24=3096ULL, RV_CSR_HPMCOUNTER25=3097ULL, + RV_CSR_HPMCOUNTER26=3098ULL, RV_CSR_HPMCOUNTER27=3099ULL, RV_CSR_HPMCOUNTER28=3100ULL, RV_CSR_HPMCOUNTER29=3101ULL, + RV_CSR_HPMCOUNTER30=3102ULL, RV_CSR_HPMCOUNTER31=3103ULL, RV_CSR_VL=3104ULL, RV_CSR_VTYPE=3105ULL, + RV_CSR_VLENB=3106ULL, RV_CSR_CYCLEH=3200ULL, RV_CSR_TIMEH=3201ULL, RV_CSR_INSTRETH=3202ULL, + RV_CSR_HPMCOUNTER3H=3203ULL, RV_CSR_HPMCOUNTER4H=3204ULL, RV_CSR_HPMCOUNTER5H=3205ULL, RV_CSR_HPMCOUNTER6H=3206ULL, + RV_CSR_HPMCOUNTER7H=3207ULL, RV_CSR_HPMCOUNTER8H=3208ULL, RV_CSR_HPMCOUNTER9H=3209ULL, RV_CSR_HPMCOUNTER10H=3210ULL, + RV_CSR_HPMCOUNTER11H=3211ULL, RV_CSR_HPMCOUNTER12H=3212ULL, RV_CSR_HPMCOUNTER13H=3213ULL, RV_CSR_HPMCOUNTER14H=3214ULL, + RV_CSR_HPMCOUNTER15H=3215ULL, RV_CSR_HPMCOUNTER16H=3216ULL, RV_CSR_HPMCOUNTER17H=3217ULL, RV_CSR_HPMCOUNTER18H=3218ULL, + RV_CSR_HPMCOUNTER19H=3219ULL, RV_CSR_HPMCOUNTER20H=3220ULL, RV_CSR_HPMCOUNTER21H=3221ULL, RV_CSR_HPMCOUNTER22H=3222ULL, + RV_CSR_HPMCOUNTER23H=3223ULL, RV_CSR_HPMCOUNTER24H=3224ULL, RV_CSR_HPMCOUNTER25H=3225ULL, RV_CSR_HPMCOUNTER26H=3226ULL, + RV_CSR_HPMCOUNTER27H=3227ULL, RV_CSR_HPMCOUNTER28H=3228ULL, RV_CSR_HPMCOUNTER29H=3229ULL, RV_CSR_HPMCOUNTER30H=3230ULL, + RV_CSR_HPMCOUNTER31H=3231ULL, RV_CSR_SCOUNTOVF=3488ULL, RV_CSR_HGEIP=3602ULL, RV_CSR_MVENDORID=3857ULL, + RV_CSR_MARCHID=3858ULL, RV_CSR_MIMPID=3859ULL, RV_CSR_MHARTID=3860ULL, RV_CSR_MCONFIGPTR=3861ULL, + RV_CAUSE_MISALIGNED_FETCH=0ULL, RV_CAUSE_FETCH_ACCESS=1ULL, RV_CAUSE_ILLEGAL_INSTRUCTION=2ULL, RV_CAUSE_BREAKPOINT=3ULL, + RV_CAUSE_MISALIGNED_LOAD=4ULL, RV_CAUSE_LOAD_ACCESS=5ULL, RV_CAUSE_MISALIGNED_STORE=6ULL, RV_CAUSE_STORE_ACCESS=7ULL, + RV_CAUSE_USER_ECALL=8ULL, RV_CAUSE_SUPERVISOR_ECALL=9ULL, RV_CAUSE_VIRTUAL_SUPERVISOR_ECALL=10ULL, RV_CAUSE_MACHINE_ECALL=11ULL, + RV_CAUSE_FETCH_PAGE_FAULT=12ULL, RV_CAUSE_LOAD_PAGE_FAULT=13ULL, RV_CAUSE_STORE_PAGE_FAULT=15ULL, RV_CAUSE_FETCH_GUEST_PAGE_FAULT=20ULL, + RV_CAUSE_LOAD_GUEST_PAGE_FAULT=21ULL, RV_CAUSE_VIRTUAL_INSTRUCTION=22ULL, RV_CAUSE_STORE_GUEST_PAGE_FAULT=23ULL, RV_MSTATUS_UIE=1ULL, + RV_MSTATUS_SIE=2ULL, RV_MSTATUS_HIE=4ULL, RV_MSTATUS_MIE=8ULL, RV_MSTATUS_UPIE=16ULL, + RV_MSTATUS_SPIE=32ULL, RV_MSTATUS_UBE=64ULL, RV_MSTATUS_MPIE=128ULL, RV_MSTATUS_SPP=256ULL, + RV_MSTATUS_VS=1536ULL, RV_MSTATUS_MPP=6144ULL, RV_MSTATUS_FS=24576ULL, RV_MSTATUS_XS=98304ULL, + RV_MSTATUS_MPRV=131072ULL, RV_MSTATUS_SUM=262144ULL, RV_MSTATUS_MXR=524288ULL, RV_MSTATUS_TVM=1048576ULL, + RV_MSTATUS_TW=2097152ULL, RV_MSTATUS_TSR=4194304ULL, RV_MSTATUS32_SD=2147483648ULL, RV_MSTATUS_UXL=12884901888ULL, + RV_MSTATUS_SXL=51539607552ULL, RV_MSTATUS_SBE=68719476736ULL, RV_MSTATUS_MBE=137438953472ULL, RV_MSTATUS_GVA=274877906944ULL, + RV_MSTATUS_MPV=549755813888ULL, RV_MSTATUS64_SD=9223372036854775808ULL, RV_PRV_U=0ULL, RV_PRV_S=1ULL, + RV_PRV_H=2ULL, RV_PRV_M=3ULL, RV_IRQ_U_SOFT=0ULL, RV_IRQ_S_SOFT=1ULL, + RV_IRQ_VS_SOFT=2ULL, RV_IRQ_M_SOFT=3ULL, RV_IRQ_U_TIMER=4ULL, RV_IRQ_S_TIMER=5ULL, + RV_IRQ_VS_TIMER=6ULL, RV_IRQ_M_TIMER=7ULL, RV_IRQ_U_EXT=8ULL, RV_IRQ_S_EXT=9ULL, + RV_IRQ_VS_EXT=10ULL, RV_IRQ_M_EXT=11ULL, RV_IRQ_S_GEXT=12ULL, RV_IRQ_COP=12ULL, + RV_IRQ_LCOF=13ULL, RV_MIP_USIP=1ULL, RV_MIP_SSIP=2ULL, RV_MIP_VSSIP=4ULL, + RV_MIP_MSIP=8ULL, RV_MIP_UTIP=16ULL, RV_MIP_STIP=32ULL, RV_MIP_VSTIP=64ULL, + RV_MIP_MTIP=128ULL, RV_MIP_UEIP=256ULL, RV_MIP_SEIP=512ULL, RV_MIP_VSEIP=1024ULL, + RV_MIP_MEIP=2048ULL, RV_MIP_SGEIP=4096ULL, RV_MIP_LCOFIP=8192ULL, XLEN=64ULL, + FLEN=0ULL, INSTR_ALIGNMENT=2ULL, RFS=32ULL, fence=0ULL, + fencei=1ULL, fencevma=2ULL, CSR_SIZE=4096ULL, MUL_LEN=128ULL, + MISA_VAL=9223372036854780165ULL, MARCHID_VAL=0ULL, CLIC_NUM_IRQ=0ULL + }; + + + constexpr static unsigned FP_REGS_SIZE = 0; + constexpr static unsigned V_REGS_SIZE = 0; + + + enum reg_e { + X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, DPC, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH + }; + + using reg_t = uint64_t; + + using addr_t = uint64_t; + + using code_word_t = uint64_t; //TODO: check removal + + using virt_addr_t = iss::virt_addr_t; + + using phys_addr_t = iss::phys_addr_t; + + static constexpr std::array reg_bit_widths{{ + sizeof(rv64imac::RV64IMAC_regs::X0) * 8, + sizeof(rv64imac::RV64IMAC_regs::X1) * 8, + sizeof(rv64imac::RV64IMAC_regs::X2) * 8, + sizeof(rv64imac::RV64IMAC_regs::X3) * 8, + sizeof(rv64imac::RV64IMAC_regs::X4) * 8, + sizeof(rv64imac::RV64IMAC_regs::X5) * 8, + sizeof(rv64imac::RV64IMAC_regs::X6) * 8, + sizeof(rv64imac::RV64IMAC_regs::X7) * 8, + sizeof(rv64imac::RV64IMAC_regs::X8) * 8, + sizeof(rv64imac::RV64IMAC_regs::X9) * 8, + sizeof(rv64imac::RV64IMAC_regs::X10) * 8, + sizeof(rv64imac::RV64IMAC_regs::X11) * 8, + sizeof(rv64imac::RV64IMAC_regs::X12) * 8, + sizeof(rv64imac::RV64IMAC_regs::X13) * 8, + sizeof(rv64imac::RV64IMAC_regs::X14) * 8, + sizeof(rv64imac::RV64IMAC_regs::X15) * 8, + sizeof(rv64imac::RV64IMAC_regs::X16) * 8, + sizeof(rv64imac::RV64IMAC_regs::X17) * 8, + sizeof(rv64imac::RV64IMAC_regs::X18) * 8, + sizeof(rv64imac::RV64IMAC_regs::X19) * 8, + sizeof(rv64imac::RV64IMAC_regs::X20) * 8, + sizeof(rv64imac::RV64IMAC_regs::X21) * 8, + sizeof(rv64imac::RV64IMAC_regs::X22) * 8, + sizeof(rv64imac::RV64IMAC_regs::X23) * 8, + sizeof(rv64imac::RV64IMAC_regs::X24) * 8, + sizeof(rv64imac::RV64IMAC_regs::X25) * 8, + sizeof(rv64imac::RV64IMAC_regs::X26) * 8, + sizeof(rv64imac::RV64IMAC_regs::X27) * 8, + sizeof(rv64imac::RV64IMAC_regs::X28) * 8, + sizeof(rv64imac::RV64IMAC_regs::X29) * 8, + sizeof(rv64imac::RV64IMAC_regs::X30) * 8, + sizeof(rv64imac::RV64IMAC_regs::X31) * 8, + sizeof(rv64imac::RV64IMAC_regs::PC) * 8, + sizeof(rv64imac::RV64IMAC_regs::NEXT_PC) * 8, + sizeof(rv64imac::RV64IMAC_regs::PRIV) * 8, + sizeof(rv64imac::RV64IMAC_regs::DPC) * 8, + sizeof(rv64imac::RV64IMAC_regs::trap_state) * 8, + sizeof(rv64imac::RV64IMAC_regs::pending_trap) * 8, + sizeof(rv64imac::RV64IMAC_regs::icount) * 8, + sizeof(rv64imac::RV64IMAC_regs::cycle) * 8, + sizeof(rv64imac::RV64IMAC_regs::instret) * 8, + sizeof(rv64imac::RV64IMAC_regs::instruction) * 8, + sizeof(rv64imac::RV64IMAC_regs::last_branch) * 8, + }}; + + static constexpr std::array reg_byte_offsets{{ + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X0), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X1), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X2), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X3), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X4), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X5), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X6), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X7), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X8), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X9), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X10), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X11), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X12), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X13), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X14), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X15), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X16), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X17), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X18), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X19), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X20), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X21), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X22), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X23), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X24), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X25), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X26), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X27), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X28), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X29), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X30), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::X31), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::PC), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::NEXT_PC), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::PRIV), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::DPC), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::trap_state), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::pending_trap), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::icount), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::cycle), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::instret), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::instruction), + offsetof(rv64imac::RV64IMAC_regs, rv64imac::RV64IMAC_regs::last_branch), + }}; + + static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); + + enum sreg_flag_e { FLAGS }; + + enum mem_type_e { MEM, FENCE, RES, CSR, IMEM = std::numeric_limits::max()}; + + static constexpr std::array mem_sizes{{ + std::numeric_limits::max(), + 8, + 8, + 4096 + }}; + + static constexpr uint64_t max_mem_size = std::numeric_limits::max(); + + enum class opcode_e { + LUI = 0, + AUIPC = 1, + JAL = 2, + JALR = 3, + BEQ = 4, + BNE = 5, + BLT = 6, + BGE = 7, + BLTU = 8, + BGEU = 9, + LB = 10, + LH = 11, + LW = 12, + LBU = 13, + LHU = 14, + SB = 15, + SH = 16, + SW = 17, + ADDI = 18, + SLTI = 19, + SLTIU = 20, + XORI = 21, + ORI = 22, + ANDI = 23, + SLLI = 24, + SRLI = 25, + SRAI = 26, + ADD = 27, + SUB = 28, + SLL = 29, + SLT = 30, + SLTU = 31, + XOR = 32, + SRL = 33, + SRA = 34, + OR = 35, + AND = 36, + FENCE = 37, + ECALL = 38, + EBREAK = 39, + MRET = 40, + WFI = 41, + LWU = 42, + LD = 43, + SD = 44, + ADDIW = 45, + SLLIW = 46, + SRLIW = 47, + SRAIW = 48, + ADDW = 49, + SUBW = 50, + SLLW = 51, + SRLW = 52, + SRAW = 53, + CSRRW = 54, + CSRRS = 55, + CSRRC = 56, + CSRRWI = 57, + CSRRSI = 58, + CSRRCI = 59, + FENCE_I = 60, + MUL = 61, + MULH = 62, + MULHSU = 63, + MULHU = 64, + DIV = 65, + DIVU = 66, + REM = 67, + REMU = 68, + MULW = 69, + DIVW = 70, + DIVUW = 71, + REMW = 72, + REMUW = 73, + LRW = 74, + SCW = 75, + AMOSWAPW = 76, + AMOADDW = 77, + AMOXORW = 78, + AMOANDW = 79, + AMOORW = 80, + AMOMINW = 81, + AMOMAXW = 82, + AMOMINUW = 83, + AMOMAXUW = 84, + LRD = 85, + SCD = 86, + AMOSWAPD = 87, + AMOADDD = 88, + AMOXORD = 89, + AMOANDD = 90, + AMOORD = 91, + AMOMIND = 92, + AMOMAXD = 93, + AMOMINUD = 94, + AMOMAXUD = 95, + C__ADDI4SPN = 96, + C__LW = 97, + C__LD = 98, + C__SW = 99, + C__SD = 100, + C__ADDI = 101, + C__NOP = 102, + C__ADDIW = 103, + C__LI = 104, + C__LUI = 105, + C__ADDI16SP = 106, + __reserved_clui = 107, + C__SRLI = 108, + C__SRAI = 109, + C__ANDI = 110, + C__SUB = 111, + C__XOR = 112, + C__OR = 113, + C__AND = 114, + C__SUBW = 115, + C__ADDW = 116, + C__J = 117, + C__BEQZ = 118, + C__BNEZ = 119, + C__SLLI = 120, + C__LWSP = 121, + C__LDSP = 122, + C__MV = 123, + C__JR = 124, + __reserved_cmv = 125, + C__ADD = 126, + C__JALR = 127, + C__EBREAK = 128, + C__SWSP = 129, + C__SDSP = 130, + DII = 131, + MAX_OPCODE + }; +}; +} +} +#endif /* _RV64IMAC_H_ */ +// clang-format on diff --git a/src/sysc/core2sc_adapter.h b/src/sysc/core2sc_adapter.h index bb2dac3..7c0c2ef 100644 --- a/src/sysc/core2sc_adapter.h +++ b/src/sysc/core2sc_adapter.h @@ -99,8 +99,7 @@ template class core2sc_adapter : public PLAT, public sc2core_if this->disass_func = util::delegate::from(this); else - this->disass_func = - util::delegate::from(nullptr); + this->disass_func = util::delegate::from(this); } void set_clint_irq_count(size_t num) override { this->set_clint_irq_num(num); } @@ -177,7 +176,7 @@ template class core2sc_adapter : public PLAT, public sc2core_if SCCINFO(owner->hier_name()) << "[disass] " << str; } }; - + void no_disass(uint64_t pc, std::string const& str, bool printpc) { return; }; iss::mem::memory_if get_mem_if() { return iss::mem::memory_if{.rd_mem{util::delegate::from(this)}, .wr_mem{util::delegate::from(this)}}; diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index 3218896..410bdea 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -258,11 +258,10 @@ template void core_complex::t template void core_complex::before_end_of_elaboration() { auto& type = GET_PROP_VALUE(core_type); - SCCDEBUG(SCMOD) << "instantiating core " << type << " with " << GET_PROP_VALUE(backend) << " backend"; + SCCDEBUG(SCMOD) << "instantiating hart" << GET_PROP_VALUE(mhartid) << " " << type << " with " << GET_PROP_VALUE(backend) << " backend"; create_cpu(type, GET_PROP_VALUE(backend), GET_PROP_VALUE(gdb_server_port), GET_PROP_VALUE(mhartid)); - if(type != "?") { - if(!core || !vm) - SCCFATAL(SCOBJ) << "Could not create core " << type; + if(type != "?" && (!core || !vm)) { + SCCFATAL(SCOBJ) << "Could not create core " << type; return; } auto instr_trace = GET_PROP_VALUE(enable_instr_trace) ? trc.init(this->name()) : false; diff --git a/src/sysc/register_cores.cpp b/src/sysc/register_cores.cpp index 01e7a88..928da11 100644 --- a/src/sysc/register_cores.cpp +++ b/src/sysc/register_cores.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -49,7 +50,7 @@ namespace iss { namespace interp { using namespace sysc; -__attribute__((used)) volatile std::array riscv_init = { +__attribute__((used)) volatile std::array riscv_init = { iss_factory::instance().register_creator("rv32i_m:interp", [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t { auto* cpu = new core2sc_adapter>(cc); @@ -97,6 +98,23 @@ __attribute__((used)) volatile std::array riscv_init = { auto* cpu = new core2sc_adapter>(cc); return {sysc::core_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; }), + iss_factory::instance().register_creator("rv64imac_m:interp", + [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t { + auto* cpu = new core2sc_adapter>(cc); + return {sysc::core_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), + iss_factory::instance().register_creator("rv64imac_mp:interp", + [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t { + auto* cpu = new core2sc_adapter>(cc); + cpu->memories.insert_before_last( + std::make_unique>(cpu->get_priv_if())); + return {sysc::core_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), + iss_factory::instance().register_creator("rv64imac_mu:interp", + [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t { + auto* cpu = new core2sc_adapter>(cc); + return {sysc::core_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), iss_factory::instance().register_creator("rv64i_mu:interp", [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t { auto* cpu = new core2sc_adapter>(cc); @@ -157,7 +175,7 @@ volatile std::array riscv_init = { #if defined(WITH_ASMJIT) namespace asmjit { using namespace sysc; -volatile std::array riscv_init = { +volatile std::array riscv_init = { iss_factory::instance().register_creator("rv32i_m:asmjit", [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t { auto* cpu = new core2sc_adapter>(cc); @@ -203,6 +221,16 @@ volatile std::array riscv_init = { auto* cpu = new core2sc_adapter>(cc); return {sysc::core_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; }), + iss_factory::instance().register_creator("rv64imac_m:asmjit", + [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t { + auto* cpu = new core2sc_adapter>(cc); + return {sysc::core_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), + iss_factory::instance().register_creator("rv64imac_mu:asmjit", + [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t { + auto* cpu = new core2sc_adapter>(cc); + return {sysc::core_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), iss_factory::instance().register_creator("rv64gc_m:asmjit", [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t { auto* cpu = new core2sc_adapter>(cc); diff --git a/src/vm/asmjit/vm_rv32gc.cpp b/src/vm/asmjit/vm_rv32gc.cpp index 198ba4a..d476c41 100644 --- a/src/vm/asmjit/vm_rv32gc.cpp +++ b/src/vm/asmjit/vm_rv32gc.cpp @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. * *******************************************************************************/ - + // clang-format off #include #include @@ -5157,7 +5157,7 @@ template class vm_impl : public iss::asmjit::vm_base { /* generate disass */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), + "{mnemonic:10} {rd}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.lwsp"), fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); InvokeNode* call_print_disass; char* mnemonic_ptr = strdup(mnemonic.c_str()); @@ -10106,8 +10106,8 @@ std::unique_ptr create(arch::rv32gc *core, unsigned short p } // namespace iss #include -#include #include +#include #include namespace iss { namespace { diff --git a/src/vm/asmjit/vm_rv32gcv.cpp b/src/vm/asmjit/vm_rv32gcv.cpp index 9662cf0..e4ad6a6 100644 --- a/src/vm/asmjit/vm_rv32gcv.cpp +++ b/src/vm/asmjit/vm_rv32gcv.cpp @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. * *******************************************************************************/ - + // clang-format off #include #include @@ -6817,7 +6817,7 @@ template class vm_impl : public iss::asmjit::vm_base { /* generate disass */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), + "{mnemonic:10} {rd}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.lwsp"), fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); InvokeNode* call_print_disass; char* mnemonic_ptr = strdup(mnemonic.c_str()); @@ -85513,8 +85513,8 @@ std::unique_ptr create(arch::rv32gcv *core, unsigned short } // namespace iss #include -#include #include +#include #include namespace iss { namespace { diff --git a/src/vm/asmjit/vm_rv32i.cpp b/src/vm/asmjit/vm_rv32i.cpp index 4231527..70f0bec 100644 --- a/src/vm/asmjit/vm_rv32i.cpp +++ b/src/vm/asmjit/vm_rv32i.cpp @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. * *******************************************************************************/ - + // clang-format off #include #include @@ -2949,8 +2949,8 @@ std::unique_ptr create(arch::rv32i *core, unsigned short por } // namespace iss #include -#include #include +#include #include namespace iss { namespace { diff --git a/src/vm/asmjit/vm_rv32imac.cpp b/src/vm/asmjit/vm_rv32imac.cpp index fd4bf87..98e72b0 100644 --- a/src/vm/asmjit/vm_rv32imac.cpp +++ b/src/vm/asmjit/vm_rv32imac.cpp @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. * *******************************************************************************/ - + // clang-format off #include #include @@ -4994,7 +4994,7 @@ template class vm_impl : public iss::asmjit::vm_base { /* generate disass */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), + "{mnemonic:10} {rd}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.lwsp"), fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); InvokeNode* call_print_disass; char* mnemonic_ptr = strdup(mnemonic.c_str()); @@ -5549,8 +5549,8 @@ std::unique_ptr create(arch::rv32imac *core, unsigned sho } // namespace iss #include -#include #include +#include #include namespace iss { namespace { diff --git a/src/vm/asmjit/vm_rv64gc.cpp b/src/vm/asmjit/vm_rv64gc.cpp index 66800ec..dd412d1 100644 --- a/src/vm/asmjit/vm_rv64gc.cpp +++ b/src/vm/asmjit/vm_rv64gc.cpp @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. * *******************************************************************************/ - + // clang-format off #include #include @@ -6839,8 +6839,8 @@ template class vm_impl : public iss::asmjit::vm_base { /* generate disass */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rd}, {rs2}", fmt::arg("mnemonic", "c.subw"), - fmt::arg("rd", name(8+rd)), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.subw"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); InvokeNode* call_print_disass; char* mnemonic_ptr = strdup(mnemonic.c_str()); jh.disass_collection.push_back(mnemonic_ptr); @@ -6884,8 +6884,8 @@ template class vm_impl : public iss::asmjit::vm_base { /* generate disass */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rd}, {rs2}", fmt::arg("mnemonic", "c.addw"), - fmt::arg("rd", name(8+rd)), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.addw"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); InvokeNode* call_print_disass; char* mnemonic_ptr = strdup(mnemonic.c_str()); jh.disass_collection.push_back(mnemonic_ptr); @@ -7119,7 +7119,7 @@ template class vm_impl : public iss::asmjit::vm_base { /* generate disass */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), + "{mnemonic:10} {rd}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.lwsp"), fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); InvokeNode* call_print_disass; char* mnemonic_ptr = strdup(mnemonic.c_str()); @@ -12687,8 +12687,8 @@ std::unique_ptr create(arch::rv64gc *core, unsigned short p } // namespace iss #include -#include #include +#include #include namespace iss { namespace { diff --git a/src/vm/asmjit/vm_rv64gcv.cpp b/src/vm/asmjit/vm_rv64gcv.cpp index 7426209..54ff0ea 100644 --- a/src/vm/asmjit/vm_rv64gcv.cpp +++ b/src/vm/asmjit/vm_rv64gcv.cpp @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. * *******************************************************************************/ - + // clang-format off #include #include @@ -8499,8 +8499,8 @@ template class vm_impl : public iss::asmjit::vm_base { /* generate disass */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rd}, {rs2}", fmt::arg("mnemonic", "c.subw"), - fmt::arg("rd", name(8+rd)), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.subw"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); InvokeNode* call_print_disass; char* mnemonic_ptr = strdup(mnemonic.c_str()); jh.disass_collection.push_back(mnemonic_ptr); @@ -8544,8 +8544,8 @@ template class vm_impl : public iss::asmjit::vm_base { /* generate disass */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rd}, {rs2}", fmt::arg("mnemonic", "c.addw"), - fmt::arg("rd", name(8+rd)), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.addw"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); InvokeNode* call_print_disass; char* mnemonic_ptr = strdup(mnemonic.c_str()); jh.disass_collection.push_back(mnemonic_ptr); @@ -8779,7 +8779,7 @@ template class vm_impl : public iss::asmjit::vm_base { /* generate disass */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), + "{mnemonic:10} {rd}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.lwsp"), fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); InvokeNode* call_print_disass; char* mnemonic_ptr = strdup(mnemonic.c_str()); @@ -88094,8 +88094,8 @@ std::unique_ptr create(arch::rv64gcv *core, unsigned short } // namespace iss #include -#include #include +#include #include namespace iss { namespace { diff --git a/src/vm/asmjit/vm_rv64i.cpp b/src/vm/asmjit/vm_rv64i.cpp index f1cc199..e1de294 100644 --- a/src/vm/asmjit/vm_rv64i.cpp +++ b/src/vm/asmjit/vm_rv64i.cpp @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. * *******************************************************************************/ - + // clang-format off #include #include @@ -3604,8 +3604,8 @@ std::unique_ptr create(arch::rv64i *core, unsigned short por } // namespace iss #include -#include #include +#include #include namespace iss { namespace { diff --git a/src/vm/asmjit/vm_rv64imac.cpp b/src/vm/asmjit/vm_rv64imac.cpp new file mode 100644 index 0000000..5e2f240 --- /dev/null +++ b/src/vm/asmjit/vm_rv64imac.cpp @@ -0,0 +1,7630 @@ +/******************************************************************************* + * Copyright (C) 2024 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +// clang-format off +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifndef FMT_HEADER_ONLY +#define FMT_HEADER_ONLY +#endif +#include + +#include +#include + +#ifndef _MSC_VER +using int128_t = __int128; +using uint128_t = unsigned __int128; +namespace std { +template <> struct make_unsigned<__int128> { typedef unsigned __int128 type; }; +template <> class __make_unsigned_selector<__int128 unsigned, false, false> { +public: + typedef unsigned __int128 __type; +}; +template <> struct is_signed { static constexpr bool value = true; }; +template <> struct is_signed { static constexpr bool value = false; }; +template <> struct is_unsigned { static constexpr bool value = false; }; +template <> struct is_unsigned { static constexpr bool value = true; }; +} // namespace std +#endif + +namespace iss { +namespace asmjit { +namespace rv64imac{ + +using namespace ::asmjit; +using namespace iss::arch; +using namespace iss::debugger; + +template class vm_impl : public iss::asmjit::vm_base { +public: + using traits = arch::traits; + using super = typename iss::asmjit::vm_base; + using virt_addr_t = typename super::virt_addr_t; + using phys_addr_t = typename super::phys_addr_t; + using code_word_t = typename super::code_word_t; + using mem_type_e = typename super::mem_type_e; + using addr_t = typename super::addr_t; + + + vm_impl(); + + vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0); + + void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } + + target_adapter_if *accquire_target_adapter(server_if *srv) override { + debugger_if::dbg_enabled = true; + if (vm_base::tgt_adapter == nullptr) + vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); + return vm_base::tgt_adapter; + } + +protected: + using super::get_ptr_for; + using super::get_reg_for; + using super::get_reg_for_Gp; + using super::load_reg_from_mem; + using super::load_reg_from_mem_Gp; + using super::write_reg_to_mem; + using super::gen_read_mem; + using super::gen_write_mem; + using super::gen_leave; + using super::gen_sync; + + using this_class = vm_impl; + using compile_func = continuation_e (this_class::*)(virt_addr_t&, code_word_t, jit_holder&); + + continuation_e gen_single_inst_behavior(virt_addr_t&, jit_holder&) override; + enum globals_e {TVAL = 0, GLOBALS_SIZE}; + void gen_block_prologue(jit_holder& jh) override; + void gen_block_epilogue(jit_holder& jh) override; + inline const char *name(size_t index){return traits::reg_aliases.at(index);} + + void gen_instr_prologue(jit_holder& jh); + void gen_instr_epilogue(jit_holder& jh); + inline void gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause); + inline void gen_lower(jit_holder& jh); + template ::value>::type> void gen_set_tval(jit_holder& jh, T new_tval) ; + void gen_set_tval(jit_holder& jh, x86_reg_t _new_tval) ; + + template::type> + inline S sext(U from) { + auto mask = (1ULL<core.reg.trap_state = trap_val; + } + + +private: + /**************************************************************************** + * start opcode definitions + ****************************************************************************/ + struct instruction_descriptor { + uint32_t length; + uint32_t value; + uint32_t mask; + compile_func op; + }; + + const std::array instr_descr = {{ + /* entries are: size, valid value, valid mask, function ptr */ + /* instruction LUI, encoding '0b00000000000000000000000000110111' */ + {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, + /* instruction AUIPC, encoding '0b00000000000000000000000000010111' */ + {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, + /* instruction JAL, encoding '0b00000000000000000000000001101111' */ + {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, + /* instruction JALR, encoding '0b00000000000000000000000001100111' */ + {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, + /* instruction BEQ, encoding '0b00000000000000000000000001100011' */ + {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, + /* instruction BNE, encoding '0b00000000000000000001000001100011' */ + {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &this_class::__bne}, + /* instruction BLT, encoding '0b00000000000000000100000001100011' */ + {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, + /* instruction BGE, encoding '0b00000000000000000101000001100011' */ + {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, &this_class::__bge}, + /* instruction BLTU, encoding '0b00000000000000000110000001100011' */ + {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, &this_class::__bltu}, + /* instruction BGEU, encoding '0b00000000000000000111000001100011' */ + {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, + /* instruction LB, encoding '0b00000000000000000000000000000011' */ + {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, + /* instruction LH, encoding '0b00000000000000000001000000000011' */ + {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, + /* instruction LW, encoding '0b00000000000000000010000000000011' */ + {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, + /* instruction LBU, encoding '0b00000000000000000100000000000011' */ + {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, + /* instruction LHU, encoding '0b00000000000000000101000000000011' */ + {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, + /* instruction SB, encoding '0b00000000000000000000000000100011' */ + {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, + /* instruction SH, encoding '0b00000000000000000001000000100011' */ + {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, + /* instruction SW, encoding '0b00000000000000000010000000100011' */ + {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, + /* instruction ADDI, encoding '0b00000000000000000000000000010011' */ + {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, + /* instruction SLTI, encoding '0b00000000000000000010000000010011' */ + {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, + /* instruction SLTIU, encoding '0b00000000000000000011000000010011' */ + {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, + /* instruction XORI, encoding '0b00000000000000000100000000010011' */ + {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, + /* instruction ORI, encoding '0b00000000000000000110000000010011' */ + {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, + /* instruction ANDI, encoding '0b00000000000000000111000000010011' */ + {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, + /* instruction SLLI, encoding '0b00000000000000000001000000010011' */ + {32, 0b00000000000000000001000000010011, 0b11111100000000000111000001111111, &this_class::__slli}, + /* instruction SRLI, encoding '0b00000000000000000101000000010011' */ + {32, 0b00000000000000000101000000010011, 0b11111100000000000111000001111111, &this_class::__srli}, + /* instruction SRAI, encoding '0b01000000000000000101000000010011' */ + {32, 0b01000000000000000101000000010011, 0b11111100000000000111000001111111, &this_class::__srai}, + /* instruction ADD, encoding '0b00000000000000000000000000110011' */ + {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, + /* instruction SUB, encoding '0b01000000000000000000000000110011' */ + {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, + /* instruction SLL, encoding '0b00000000000000000001000000110011' */ + {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, + /* instruction SLT, encoding '0b00000000000000000010000000110011' */ + {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, + /* instruction SLTU, encoding '0b00000000000000000011000000110011' */ + {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, + /* instruction XOR, encoding '0b00000000000000000100000000110011' */ + {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, + /* instruction SRL, encoding '0b00000000000000000101000000110011' */ + {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, + /* instruction SRA, encoding '0b01000000000000000101000000110011' */ + {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, + /* instruction OR, encoding '0b00000000000000000110000000110011' */ + {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, + /* instruction AND, encoding '0b00000000000000000111000000110011' */ + {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, + /* instruction FENCE, encoding '0b00000000000000000000000000001111' */ + {32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, &this_class::__fence}, + /* instruction ECALL, encoding '0b00000000000000000000000001110011' */ + {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, + /* instruction EBREAK, encoding '0b00000000000100000000000001110011' */ + {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, + /* instruction MRET, encoding '0b00110000001000000000000001110011' */ + {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, + /* instruction WFI, encoding '0b00010000010100000000000001110011' */ + {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, + /* instruction LWU, encoding '0b00000000000000000110000000000011' */ + {32, 0b00000000000000000110000000000011, 0b00000000000000000111000001111111, &this_class::__lwu}, + /* instruction LD, encoding '0b00000000000000000011000000000011' */ + {32, 0b00000000000000000011000000000011, 0b00000000000000000111000001111111, &this_class::__ld}, + /* instruction SD, encoding '0b00000000000000000011000000100011' */ + {32, 0b00000000000000000011000000100011, 0b00000000000000000111000001111111, &this_class::__sd}, + /* instruction ADDIW, encoding '0b00000000000000000000000000011011' */ + {32, 0b00000000000000000000000000011011, 0b00000000000000000111000001111111, &this_class::__addiw}, + /* instruction SLLIW, encoding '0b00000000000000000001000000011011' */ + {32, 0b00000000000000000001000000011011, 0b11111110000000000111000001111111, &this_class::__slliw}, + /* instruction SRLIW, encoding '0b00000000000000000101000000011011' */ + {32, 0b00000000000000000101000000011011, 0b11111110000000000111000001111111, &this_class::__srliw}, + /* instruction SRAIW, encoding '0b01000000000000000101000000011011' */ + {32, 0b01000000000000000101000000011011, 0b11111110000000000111000001111111, &this_class::__sraiw}, + /* instruction ADDW, encoding '0b00000000000000000000000000111011' */ + {32, 0b00000000000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__addw}, + /* instruction SUBW, encoding '0b01000000000000000000000000111011' */ + {32, 0b01000000000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__subw}, + /* instruction SLLW, encoding '0b00000000000000000001000000111011' */ + {32, 0b00000000000000000001000000111011, 0b11111110000000000111000001111111, &this_class::__sllw}, + /* instruction SRLW, encoding '0b00000000000000000101000000111011' */ + {32, 0b00000000000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__srlw}, + /* instruction SRAW, encoding '0b01000000000000000101000000111011' */ + {32, 0b01000000000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__sraw}, + /* instruction CSRRW, encoding '0b00000000000000000001000001110011' */ + {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, + /* instruction CSRRS, encoding '0b00000000000000000010000001110011' */ + {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, + /* instruction CSRRC, encoding '0b00000000000000000011000001110011' */ + {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &this_class::__csrrc}, + /* instruction CSRRWI, encoding '0b00000000000000000101000001110011' */ + {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, &this_class::__csrrwi}, + /* instruction CSRRSI, encoding '0b00000000000000000110000001110011' */ + {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, + /* instruction CSRRCI, encoding '0b00000000000000000111000001110011' */ + {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, + /* instruction FENCE_I, encoding '0b00000000000000000001000000001111' */ + {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, + /* instruction MUL, encoding '0b00000010000000000000000000110011' */ + {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, + /* instruction MULH, encoding '0b00000010000000000001000000110011' */ + {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, + /* instruction MULHSU, encoding '0b00000010000000000010000000110011' */ + {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, + /* instruction MULHU, encoding '0b00000010000000000011000000110011' */ + {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, + /* instruction DIV, encoding '0b00000010000000000100000000110011' */ + {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, + /* instruction DIVU, encoding '0b00000010000000000101000000110011' */ + {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, + /* instruction REM, encoding '0b00000010000000000110000000110011' */ + {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, + /* instruction REMU, encoding '0b00000010000000000111000000110011' */ + {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, + /* instruction MULW, encoding '0b00000010000000000000000000111011' */ + {32, 0b00000010000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__mulw}, + /* instruction DIVW, encoding '0b00000010000000000100000000111011' */ + {32, 0b00000010000000000100000000111011, 0b11111110000000000111000001111111, &this_class::__divw}, + /* instruction DIVUW, encoding '0b00000010000000000101000000111011' */ + {32, 0b00000010000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__divuw}, + /* instruction REMW, encoding '0b00000010000000000110000000111011' */ + {32, 0b00000010000000000110000000111011, 0b11111110000000000111000001111111, &this_class::__remw}, + /* instruction REMUW, encoding '0b00000010000000000111000000111011' */ + {32, 0b00000010000000000111000000111011, 0b11111110000000000111000001111111, &this_class::__remuw}, + /* instruction LRW, encoding '0b00010000000000000010000000101111' */ + {32, 0b00010000000000000010000000101111, 0b11111001111100000111000001111111, &this_class::__lrw}, + /* instruction SCW, encoding '0b00011000000000000010000000101111' */ + {32, 0b00011000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__scw}, + /* instruction AMOSWAPW, encoding '0b00001000000000000010000000101111' */ + {32, 0b00001000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoswapw}, + /* instruction AMOADDW, encoding '0b00000000000000000010000000101111' */ + {32, 0b00000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoaddw}, + /* instruction AMOXORW, encoding '0b00100000000000000010000000101111' */ + {32, 0b00100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoxorw}, + /* instruction AMOANDW, encoding '0b01100000000000000010000000101111' */ + {32, 0b01100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoandw}, + /* instruction AMOORW, encoding '0b01000000000000000010000000101111' */ + {32, 0b01000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoorw}, + /* instruction AMOMINW, encoding '0b10000000000000000010000000101111' */ + {32, 0b10000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amominw}, + /* instruction AMOMAXW, encoding '0b10100000000000000010000000101111' */ + {32, 0b10100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxw}, + /* instruction AMOMINUW, encoding '0b11000000000000000010000000101111' */ + {32, 0b11000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amominuw}, + /* instruction AMOMAXUW, encoding '0b11100000000000000010000000101111' */ + {32, 0b11100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxuw}, + /* instruction LRD, encoding '0b00010000000000000011000000101111' */ + {32, 0b00010000000000000011000000101111, 0b11111001111100000111000001111111, &this_class::__lrd}, + /* instruction SCD, encoding '0b00011000000000000011000000101111' */ + {32, 0b00011000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__scd}, + /* instruction AMOSWAPD, encoding '0b00001000000000000011000000101111' */ + {32, 0b00001000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoswapd}, + /* instruction AMOADDD, encoding '0b00000000000000000011000000101111' */ + {32, 0b00000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoaddd}, + /* instruction AMOXORD, encoding '0b00100000000000000011000000101111' */ + {32, 0b00100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoxord}, + /* instruction AMOANDD, encoding '0b01100000000000000011000000101111' */ + {32, 0b01100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoandd}, + /* instruction AMOORD, encoding '0b01000000000000000011000000101111' */ + {32, 0b01000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoord}, + /* instruction AMOMIND, encoding '0b10000000000000000011000000101111' */ + {32, 0b10000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amomind}, + /* instruction AMOMAXD, encoding '0b10100000000000000011000000101111' */ + {32, 0b10100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxd}, + /* instruction AMOMINUD, encoding '0b11000000000000000011000000101111' */ + {32, 0b11000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amominud}, + /* instruction AMOMAXUD, encoding '0b11100000000000000011000000101111' */ + {32, 0b11100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxud}, + /* instruction C__ADDI4SPN, encoding '0b0000000000000000' */ + {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c__addi4spn}, + /* instruction C__LW, encoding '0b0100000000000000' */ + {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c__lw}, + /* instruction C__LD, encoding '0b0110000000000000' */ + {16, 0b0110000000000000, 0b1110000000000011, &this_class::__c__ld}, + /* instruction C__SW, encoding '0b1100000000000000' */ + {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c__sw}, + /* instruction C__SD, encoding '0b1110000000000000' */ + {16, 0b1110000000000000, 0b1110000000000011, &this_class::__c__sd}, + /* instruction C__ADDI, encoding '0b0000000000000001' */ + {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c__addi}, + /* instruction C__NOP, encoding '0b0000000000000001' */ + {16, 0b0000000000000001, 0b1110111110000011, &this_class::__c__nop}, + /* instruction C__ADDIW, encoding '0b0010000000000001' */ + {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c__addiw}, + /* instruction C__LI, encoding '0b0100000000000001' */ + {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c__li}, + /* instruction C__LUI, encoding '0b0110000000000001' */ + {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c__lui}, + /* instruction C__ADDI16SP, encoding '0b0110000100000001' */ + {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c__addi16sp}, + /* instruction __reserved_clui, encoding '0b0110000000000001' */ + {16, 0b0110000000000001, 0b1111000001111111, &this_class::____reserved_clui}, + /* instruction C__SRLI, encoding '0b1000000000000001' */ + {16, 0b1000000000000001, 0b1110110000000011, &this_class::__c__srli}, + /* instruction C__SRAI, encoding '0b1000010000000001' */ + {16, 0b1000010000000001, 0b1110110000000011, &this_class::__c__srai}, + /* instruction C__ANDI, encoding '0b1000100000000001' */ + {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c__andi}, + /* instruction C__SUB, encoding '0b1000110000000001' */ + {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c__sub}, + /* instruction C__XOR, encoding '0b1000110000100001' */ + {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c__xor}, + /* instruction C__OR, encoding '0b1000110001000001' */ + {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c__or}, + /* instruction C__AND, encoding '0b1000110001100001' */ + {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c__and}, + /* instruction C__SUBW, encoding '0b1001110000000001' */ + {16, 0b1001110000000001, 0b1111110001100011, &this_class::__c__subw}, + /* instruction C__ADDW, encoding '0b1001110000100001' */ + {16, 0b1001110000100001, 0b1111110001100011, &this_class::__c__addw}, + /* instruction C__J, encoding '0b1010000000000001' */ + {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c__j}, + /* instruction C__BEQZ, encoding '0b1100000000000001' */ + {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c__beqz}, + /* instruction C__BNEZ, encoding '0b1110000000000001' */ + {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c__bnez}, + /* instruction C__SLLI, encoding '0b0000000000000010' */ + {16, 0b0000000000000010, 0b1110000000000011, &this_class::__c__slli}, + /* instruction C__LWSP, encoding '0b0100000000000010' */ + {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c__lwsp}, + /* instruction C__LDSP, encoding '0b0110000000000010' */ + {16, 0b0110000000000010, 0b1110000000000011, &this_class::__c__ldsp}, + /* instruction C__MV, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c__mv}, + /* instruction C__JR, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c__jr}, + /* instruction __reserved_cmv, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111111111111111, &this_class::____reserved_cmv}, + /* instruction C__ADD, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c__add}, + /* instruction C__JALR, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c__jalr}, + /* instruction C__EBREAK, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c__ebreak}, + /* instruction C__SWSP, encoding '0b1100000000000010' */ + {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c__swsp}, + /* instruction C__SDSP, encoding '0b1110000000000010' */ + {16, 0b1110000000000010, 0b1110000000000011, &this_class::__c__sdsp}, + /* instruction DII, encoding '0b0000000000000000' */ + {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, + }}; + + //needs to be declared after instr_descr + decoder instr_decoder; + + /* instruction definitions */ + /* instruction 0: LUI */ + continuation_e __lui(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("LUI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 0); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto value_reg = get_reg_Gp(cc, 64, false); + cc.movabs(value_reg, (uint64_t)((int32_t)imm)); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + value_reg); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 0); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 1: AUIPC */ + continuation_e __auipc(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AUIPC_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 1); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto value_reg = get_reg_Gp(cc, 64, false); + cc.movabs(value_reg, (uint64_t)(PC+(int32_t)imm)); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + value_reg); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 1); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 2: JAL */ + continuation_e __jal(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("JAL_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 2); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(NO_JUMP)); + if(rd>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto new_pc = (uint64_t)(PC+(int32_t)sext<21>(imm)); + if(new_pc%static_cast(traits::INSTR_ALIGNMENT)){ + gen_set_tval(jh, new_pc); + gen_raise(jh, 0, 0); + } + else { + if(rd!=0){ + auto value_reg = get_reg_Gp(cc, 64, false); + cc.movabs(value_reg, (uint64_t)(PC+4)); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + value_reg); + } + auto PC_val_v = new_pc; + mov(cc, jh.next_pc, PC_val_v); + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(KNOWN_JUMP)); + } + } + auto returnValue = BRANCH; + + gen_sync(jh, POST_SYNC, 2); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 3: JALR */ + continuation_e __jalr(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("JALR_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 3); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(NO_JUMP)); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto addr_mask = (uint64_t)- 2; + auto new_pc = gen_ext(cc, + (gen_operation(cc, band, (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (int16_t)sext<12>(imm))), addr_mask)), 64, true); + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, urem, new_pc, static_cast(traits::INSTR_ALIGNMENT)); + cmp(cc, cond, 0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + gen_set_tval(jh, new_pc); + gen_raise(jh, 0, 0); + } + cc.jmp(label_merge); + cc.bind(label_else); + { + if(rd!=0){ + auto value_reg = get_reg_Gp(cc, 64, false); + cc.movabs(value_reg, (uint64_t)(PC+4)); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + value_reg); + } + auto PC_val_v = new_pc; + mov(cc, jh.next_pc, PC_val_v); + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(UNKNOWN_JUMP)); + } + cc.bind(label_merge); + } + } + auto returnValue = BRANCH; + + gen_sync(jh, POST_SYNC, 3); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 4: BEQ */ + continuation_e __beq(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("BEQ_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 4); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(NO_JUMP)); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, eq, load_reg_from_mem_Gp(jh, traits::X0 + rs1), load_reg_from_mem_Gp(jh, traits::X0 + rs2)); + cmp(cc, cond, 0); + cc.je(label_merge); + { + auto new_pc = (uint64_t)(PC+(int16_t)sext<13>(imm)); + if(new_pc%static_cast(traits::INSTR_ALIGNMENT)){ + gen_set_tval(jh, new_pc); + gen_raise(jh, 0, 0); + } + else { + auto PC_val_v = new_pc; + mov(cc, jh.next_pc, PC_val_v); + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(KNOWN_JUMP)); + } + } + cc.bind(label_merge); + } + } + auto returnValue = BRANCH; + + gen_sync(jh, POST_SYNC, 4); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 5: BNE */ + continuation_e __bne(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("BNE_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 5); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(NO_JUMP)); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, ne, load_reg_from_mem_Gp(jh, traits::X0 + rs1), load_reg_from_mem_Gp(jh, traits::X0 + rs2)); + cmp(cc, cond, 0); + cc.je(label_merge); + { + auto new_pc = (uint64_t)(PC+(int16_t)sext<13>(imm)); + if(new_pc%static_cast(traits::INSTR_ALIGNMENT)){ + gen_set_tval(jh, new_pc); + gen_raise(jh, 0, 0); + } + else { + auto PC_val_v = new_pc; + mov(cc, jh.next_pc, PC_val_v); + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(KNOWN_JUMP)); + } + } + cc.bind(label_merge); + } + } + auto returnValue = BRANCH; + + gen_sync(jh, POST_SYNC, 5); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 6: BLT */ + continuation_e __blt(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("BLT_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 6); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(NO_JUMP)); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, lt, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 64, false), gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 64, false)); + cmp(cc, cond, 0); + cc.je(label_merge); + { + auto new_pc = (uint64_t)(PC+(int16_t)sext<13>(imm)); + if(new_pc%static_cast(traits::INSTR_ALIGNMENT)){ + gen_set_tval(jh, new_pc); + gen_raise(jh, 0, 0); + } + else { + auto PC_val_v = new_pc; + mov(cc, jh.next_pc, PC_val_v); + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(KNOWN_JUMP)); + } + } + cc.bind(label_merge); + } + } + auto returnValue = BRANCH; + + gen_sync(jh, POST_SYNC, 6); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 7: BGE */ + continuation_e __bge(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("BGE_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 7); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(NO_JUMP)); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, gte, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 64, false), gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 64, false)); + cmp(cc, cond, 0); + cc.je(label_merge); + { + auto new_pc = (uint64_t)(PC+(int16_t)sext<13>(imm)); + if(new_pc%static_cast(traits::INSTR_ALIGNMENT)){ + gen_set_tval(jh, new_pc); + gen_raise(jh, 0, 0); + } + else { + auto PC_val_v = new_pc; + mov(cc, jh.next_pc, PC_val_v); + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(KNOWN_JUMP)); + } + } + cc.bind(label_merge); + } + } + auto returnValue = BRANCH; + + gen_sync(jh, POST_SYNC, 7); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 8: BLTU */ + continuation_e __bltu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("BLTU_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 8); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(NO_JUMP)); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, ltu, load_reg_from_mem_Gp(jh, traits::X0 + rs1), load_reg_from_mem_Gp(jh, traits::X0 + rs2)); + cmp(cc, cond, 0); + cc.je(label_merge); + { + auto new_pc = (uint64_t)(PC+(int16_t)sext<13>(imm)); + if(new_pc%static_cast(traits::INSTR_ALIGNMENT)){ + gen_set_tval(jh, new_pc); + gen_raise(jh, 0, 0); + } + else { + auto PC_val_v = new_pc; + mov(cc, jh.next_pc, PC_val_v); + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(KNOWN_JUMP)); + } + } + cc.bind(label_merge); + } + } + auto returnValue = BRANCH; + + gen_sync(jh, POST_SYNC, 8); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 9: BGEU */ + continuation_e __bgeu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("BGEU_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 9); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(NO_JUMP)); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, gteu, load_reg_from_mem_Gp(jh, traits::X0 + rs1), load_reg_from_mem_Gp(jh, traits::X0 + rs2)); + cmp(cc, cond, 0); + cc.je(label_merge); + { + auto new_pc = (uint64_t)(PC+(int16_t)sext<13>(imm)); + if(new_pc%static_cast(traits::INSTR_ALIGNMENT)){ + gen_set_tval(jh, new_pc); + gen_raise(jh, 0, 0); + } + else { + auto PC_val_v = new_pc; + mov(cc, jh.next_pc, PC_val_v); + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(KNOWN_JUMP)); + } + } + cc.bind(label_merge); + } + } + auto returnValue = BRANCH; + + gen_sync(jh, POST_SYNC, 9); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 10: LB */ + continuation_e __lb(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("LB_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 10); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto load_address = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (int16_t)sext<12>(imm))), 64, true); + auto res = gen_ext(cc, + gen_read_mem(jh, traits::MEM, load_address, 1), 8, false); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res, 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 10); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 11: LH */ + continuation_e __lh(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("LH_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 11); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto load_address = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (int16_t)sext<12>(imm))), 64, true); + auto res = gen_ext(cc, + gen_read_mem(jh, traits::MEM, load_address, 2), 16, false); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res, 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 11); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 12: LW */ + continuation_e __lw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("LW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 12); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto load_address = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (int16_t)sext<12>(imm))), 64, true); + auto res = gen_ext(cc, + gen_read_mem(jh, traits::MEM, load_address, 4), 32, false); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res, 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 12); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 13: LBU */ + continuation_e __lbu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("LBU_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 13); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto load_address = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (int16_t)sext<12>(imm))), 64, true); + auto res = gen_read_mem(jh, traits::MEM, load_address, 1); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res, 64, false)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 13); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 14: LHU */ + continuation_e __lhu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("LHU_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 14); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto load_address = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (int16_t)sext<12>(imm))), 64, true); + auto res = gen_read_mem(jh, traits::MEM, load_address, 2); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res, 64, false)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 14); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 15: SB */ + continuation_e __sb(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SB_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 15); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto store_address = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (int16_t)sext<12>(imm))), 64, true); + gen_write_mem(jh, traits::MEM, store_address, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 8, false), 1); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 15); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 16: SH */ + continuation_e __sh(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SH_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 16); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto store_address = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (int16_t)sext<12>(imm))), 64, true); + gen_write_mem(jh, traits::MEM, store_address, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 16, false), 2); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 16); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 17: SW */ + continuation_e __sw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 17); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto store_address = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (int16_t)sext<12>(imm))), 64, true); + gen_write_mem(jh, traits::MEM, store_address, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false), 4); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 17); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 18: ADDI */ + continuation_e __addi(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("ADDI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 18); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (int16_t)sext<12>(imm))), 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 18); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 19: SLTI */ + continuation_e __slti(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SLTI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 19); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto label_then1 = cc.newLabel(); + auto label_merge1 = cc.newLabel(); + auto tmp_reg1 = get_reg_Gp(cc, 8, false); + cmp(cc, gen_ext(cc, load_reg_from_mem_Gp(jh, traits::X0 + rs1), 64, true), (int16_t)sext<12>(imm)); + cc.jl(label_then1); + mov(cc, tmp_reg1,0); + cc.jmp(label_merge1); + cc.bind(label_then1); + mov(cc, tmp_reg1, 1); + cc.bind(label_merge1); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, tmp_reg1 + , 64, false) + ); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 19); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 20: SLTIU */ + continuation_e __sltiu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SLTIU_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 20); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto label_then2 = cc.newLabel(); + auto label_merge2 = cc.newLabel(); + auto tmp_reg2 = get_reg_Gp(cc, 8, false); + cmp(cc, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (uint64_t)((int16_t)sext<12>(imm))); + cc.jb(label_then2); + mov(cc, tmp_reg2,0); + cc.jmp(label_merge2); + cc.bind(label_then2); + mov(cc, tmp_reg2, 1); + cc.bind(label_merge2); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, tmp_reg2 + , 64, false) + ); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 20); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 21: XORI */ + continuation_e __xori(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("XORI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 21); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_operation(cc, bxor, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (uint64_t)((int16_t)sext<12>(imm)))); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 21); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 22: ORI */ + continuation_e __ori(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("ORI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 22); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_operation(cc, bor, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (uint64_t)((int16_t)sext<12>(imm)))); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 22); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 23: ANDI */ + continuation_e __andi(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("ANDI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 23); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_operation(cc, band, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (uint64_t)((int16_t)sext<12>(imm)))); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 23); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 24: SLLI */ + continuation_e __slli(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,6>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SLLI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 24); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_operation(cc, shl, load_reg_from_mem_Gp(jh, traits::X0 + rs1), shamt)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 24); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 25: SRLI */ + continuation_e __srli(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,6>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SRLI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 25); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_operation(cc, shr, load_reg_from_mem_Gp(jh, traits::X0 + rs1), shamt)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 25); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 26: SRAI */ + continuation_e __srai(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,6>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SRAI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 26); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + (gen_operation(cc, sar, (gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 64, false)), shamt)), 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 26); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 27: ADD */ + continuation_e __add(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("ADD_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 27); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1), load_reg_from_mem_Gp(jh, traits::X0 + rs2))), 64, false)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 27); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 28: SUB */ + continuation_e __sub(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SUB_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 28); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + (gen_operation(cc, sub, load_reg_from_mem_Gp(jh, traits::X0 + rs1), load_reg_from_mem_Gp(jh, traits::X0 + rs2))), 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 28); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 29: SLL */ + continuation_e __sll(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SLL_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 29); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_operation(cc, shl, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (gen_operation(cc, band, load_reg_from_mem_Gp(jh, traits::X0 + rs2), (static_cast(traits::XLEN)-1))))); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 29); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 30: SLT */ + continuation_e __slt(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SLT_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 30); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto label_then3 = cc.newLabel(); + auto label_merge3 = cc.newLabel(); + auto tmp_reg3 = get_reg_Gp(cc, 8, false); + cmp(cc, gen_ext(cc, load_reg_from_mem_Gp(jh, traits::X0 + rs1), 64, true), gen_ext(cc, load_reg_from_mem_Gp(jh, traits::X0 + rs2), 64, true)); + cc.jl(label_then3); + mov(cc, tmp_reg3,0); + cc.jmp(label_merge3); + cc.bind(label_then3); + mov(cc, tmp_reg3, 1); + cc.bind(label_merge3); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, tmp_reg3 + , 64, false) + ); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 30); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 31: SLTU */ + continuation_e __sltu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SLTU_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 31); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto label_then4 = cc.newLabel(); + auto label_merge4 = cc.newLabel(); + auto tmp_reg4 = get_reg_Gp(cc, 8, false); + cmp(cc, load_reg_from_mem_Gp(jh, traits::X0 + rs1), load_reg_from_mem_Gp(jh, traits::X0 + rs2)); + cc.jb(label_then4); + mov(cc, tmp_reg4,0); + cc.jmp(label_merge4); + cc.bind(label_then4); + mov(cc, tmp_reg4, 1); + cc.bind(label_merge4); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, tmp_reg4 + , 64, false) + ); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 31); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 32: XOR */ + continuation_e __xor(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("XOR_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 32); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_operation(cc, bxor, load_reg_from_mem_Gp(jh, traits::X0 + rs1), load_reg_from_mem_Gp(jh, traits::X0 + rs2))); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 32); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 33: SRL */ + continuation_e __srl(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SRL_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 33); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_operation(cc, shr, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (gen_operation(cc, band, load_reg_from_mem_Gp(jh, traits::X0 + rs2), (static_cast(traits::XLEN)-1))))); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 33); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 34: SRA */ + continuation_e __sra(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SRA_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 34); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + (gen_operation(cc, sar, gen_ext(cc, load_reg_from_mem_Gp(jh, traits::X0 + rs1), 64, true), (gen_operation(cc, band, load_reg_from_mem_Gp(jh, traits::X0 + rs2), (static_cast(traits::XLEN)-1))))), 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 34); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 35: OR */ + continuation_e __or(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("OR_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 35); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_operation(cc, bor, load_reg_from_mem_Gp(jh, traits::X0 + rs1), load_reg_from_mem_Gp(jh, traits::X0 + rs2))); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 35); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 36: AND */ + continuation_e __and(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AND_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 36); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_operation(cc, band, load_reg_from_mem_Gp(jh, traits::X0 + rs1), load_reg_from_mem_Gp(jh, traits::X0 + rs2))); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 36); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 37: FENCE */ + continuation_e __fence(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t succ = ((bit_sub<20,4>(instr))); + uint8_t pred = ((bit_sub<24,4>(instr))); + uint8_t fm = ((bit_sub<28,4>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {pred}, {succ} ({fm} , {rs1}, {rd})", fmt::arg("mnemonic", "fence"), + fmt::arg("pred", pred), fmt::arg("succ", succ), fmt::arg("fm", fm), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("FENCE_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 37); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + gen_write_mem(jh, traits::FENCE, static_cast(traits::fence), (uint8_t)pred<<4|succ, 8); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 37); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 38: ECALL */ + continuation_e __ecall(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate disass */ + + //No disass specified, using instruction name + std::string mnemonic = "ecall"; + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("ECALL_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 38); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(NO_JUMP)); + gen_raise(jh, 0, 11); + auto returnValue = TRAP; + + gen_sync(jh, POST_SYNC, 38); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 39: EBREAK */ + continuation_e __ebreak(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate disass */ + + //No disass specified, using instruction name + std::string mnemonic = "ebreak"; + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("EBREAK_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 39); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(NO_JUMP)); + gen_raise(jh, 0, 3); + auto returnValue = TRAP; + + gen_sync(jh, POST_SYNC, 39); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 40: MRET */ + continuation_e __mret(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate disass */ + + //No disass specified, using instruction name + std::string mnemonic = "mret"; + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("MRET_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 40); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(NO_JUMP)); + gen_leave(jh, 3); + auto returnValue = TRAP; + + gen_sync(jh, POST_SYNC, 40); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 41: WFI */ + continuation_e __wfi(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate disass */ + + //No disass specified, using instruction name + std::string mnemonic = "wfi"; + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("WFI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 41); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + InvokeNode* call_wait_5; + cc.invoke(&call_wait_5, &wait, FuncSignature::build()); + setArg(call_wait_5, 0, 1); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 41); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 42: LWU */ + continuation_e __lwu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lwu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("LWU_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 42); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (int16_t)sext<12>(imm))), 64, true); + auto res = gen_ext(cc, + gen_read_mem(jh, traits::MEM, offs, 4), 32, false); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res, 64, false)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 42); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 43: LD */ + continuation_e __ld(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "ld"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("LD_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 43); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (int16_t)sext<12>(imm))), 64, true); + auto res = gen_ext(cc, + gen_read_mem(jh, traits::MEM, offs, 8), 64, false); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res, 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 43); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 44: SD */ + continuation_e __sd(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sd"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SD_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 44); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (int16_t)sext<12>(imm))), 64, true); + gen_write_mem(jh, traits::MEM, offs, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 64, false), 8); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 44); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 45: ADDIW */ + continuation_e __addiw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addiw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("ADDIW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 45); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto res = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (int16_t)sext<12>(imm))), 32, true); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res, 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 45); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 46: SLLIW */ + continuation_e __slliw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slliw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SLLIW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 46); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto sh_val = gen_operation(cc, shl, (gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 32, false)), shamt); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + gen_ext(cc, sh_val, 32, true), 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 46); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 47: SRLIW */ + continuation_e __srliw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srliw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SRLIW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 47); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto sh_val = gen_operation(cc, shr, (gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 32, false)), shamt); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + gen_ext(cc, sh_val, 32, true), 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 47); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 48: SRAIW */ + continuation_e __sraiw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "sraiw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SRAIW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 48); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto sh_val = gen_operation(cc, sar, (gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 32, false)), shamt); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + sh_val, 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 48); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 49: ADDW */ + continuation_e __addw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + //No disass specified, using instruction name + std::string mnemonic = "addw"; + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("ADDW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 49); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto res = gen_ext(cc, + (gen_operation(cc, add, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 32, false), gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false))), 32, true); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res, 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 49); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 50: SUBW */ + continuation_e __subw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + //No disass specified, using instruction name + std::string mnemonic = "subw"; + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SUBW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 50); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto res = gen_ext(cc, + (gen_operation(cc, sub, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 32, false), gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false))), 32, true); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res, 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 50); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 51: SLLW */ + continuation_e __sllw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sllw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SLLW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 51); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto count = gen_operation(cc, band, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false), 31); + auto sh_val = gen_operation(cc, shl, (gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 32, false)), count); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + gen_ext(cc, sh_val, 32, true), 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 51); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 52: SRLW */ + continuation_e __srlw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srlw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SRLW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 52); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto count = gen_operation(cc, band, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false), 31); + auto sh_val = gen_operation(cc, shr, (gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 32, false)), count); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + gen_ext(cc, sh_val, 32, true), 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 52); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 53: SRAW */ + continuation_e __sraw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sraw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SRAW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 53); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto count = gen_operation(cc, band, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false), 31); + auto sh_val = gen_operation(cc, sar, (gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 32, false)), count); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + sh_val, 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 53); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 54: CSRRW */ + continuation_e __csrrw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("CSRRW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 54); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto xrs1 = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + if(rd!=0){ + auto xrd = gen_read_mem(jh, traits::CSR, csr, 8); + gen_write_mem(jh, traits::CSR, csr, xrs1, 8); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + xrd); + } + else { + gen_write_mem(jh, traits::CSR, csr, xrs1, 8); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 54); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 55: CSRRS */ + continuation_e __csrrs(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("CSRRS_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 55); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto xrd = gen_read_mem(jh, traits::CSR, csr, 8); + auto xrs1 = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + if(rs1!=0){ + gen_write_mem(jh, traits::CSR, csr, gen_operation(cc, bor, xrd, xrs1), 8); + } + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + xrd); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 55); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 56: CSRRC */ + continuation_e __csrrc(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("CSRRC_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 56); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto xrd = gen_read_mem(jh, traits::CSR, csr, 8); + auto xrs1 = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + if(rs1!=0){ + gen_write_mem(jh, traits::CSR, csr, gen_operation(cc, band, xrd, gen_operation(cc, bnot, xrs1)), 8); + } + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + xrd); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 56); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 57: CSRRWI */ + continuation_e __csrrwi(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("CSRRWI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 57); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto xrd = gen_read_mem(jh, traits::CSR, csr, 8); + gen_write_mem(jh, traits::CSR, csr, (uint64_t)zimm, 8); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + xrd); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 57); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 58: CSRRSI */ + continuation_e __csrrsi(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("CSRRSI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 58); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto xrd = gen_read_mem(jh, traits::CSR, csr, 8); + if(zimm!=0){ + gen_write_mem(jh, traits::CSR, csr, gen_operation(cc, bor, xrd, (uint64_t)zimm), 8); + } + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + xrd); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 58); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 59: CSRRCI */ + continuation_e __csrrci(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("CSRRCI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 59); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto xrd = gen_read_mem(jh, traits::CSR, csr, 8); + if(zimm!=0){ + gen_write_mem(jh, traits::CSR, csr, gen_operation(cc, band, xrd, ~ ((uint64_t)zimm)), 8); + } + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + xrd); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 59); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 60: FENCE_I */ + continuation_e __fence_i(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence_i"), + fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("FENCE_I_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 60); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + gen_write_mem(jh, traits::FENCE, static_cast(traits::fencei), imm, 8); + auto returnValue = FLUSH; + + gen_sync(jh, POST_SYNC, 60); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 61: MUL */ + continuation_e __mul(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("MUL_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 61); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto res = gen_operation(cc, smul, gen_ext(cc, load_reg_from_mem_Gp(jh, traits::X0 + rs1), 64, true), gen_ext(cc, load_reg_from_mem_Gp(jh, traits::X0 + rs2), 64, true)); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res, 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 61); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 62: MULH */ + continuation_e __mulh(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("MULH_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 62); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto res = gen_operation(cc, smul, gen_ext(cc, load_reg_from_mem_Gp(jh, traits::X0 + rs1), 64, true), gen_ext(cc, load_reg_from_mem_Gp(jh, traits::X0 + rs2), 64, true)); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + (gen_operation(cc, sar, res, static_cast(traits::XLEN))), 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 62); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 63: MULHSU */ + continuation_e __mulhsu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("MULHSU_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 63); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto res = gen_operation(cc, sumul, gen_ext(cc, load_reg_from_mem_Gp(jh, traits::X0 + rs1), 64, true), load_reg_from_mem_Gp(jh, traits::X0 + rs2)); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + (gen_operation(cc, sar, res, static_cast(traits::XLEN))), 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 63); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 64: MULHU */ + continuation_e __mulhu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("MULHU_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 64); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto res = gen_operation(cc, umul, load_reg_from_mem_Gp(jh, traits::X0 + rs1), load_reg_from_mem_Gp(jh, traits::X0 + rs2)); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + (gen_operation(cc, shr, res, static_cast(traits::XLEN))), 64, false)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 64); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 65: DIV */ + continuation_e __div(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("DIV_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 65); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto dividend = gen_ext(cc, load_reg_from_mem_Gp(jh, traits::X0 + rs1), 64, true); + auto divisor = gen_ext(cc, load_reg_from_mem_Gp(jh, traits::X0 + rs2), 64, true); + if(rd!=0){ + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, ne, divisor, 0); + cmp(cc, cond, 0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + auto MMIN = ((uint64_t)1)<<(static_cast(traits::XLEN)-1); + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, land, gen_operation(cc, eq, load_reg_from_mem_Gp(jh, traits::X0 + rs1), MMIN), gen_operation(cc, eq, divisor, - 1)); + cmp(cc, cond, 0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + auto value_reg = get_reg_Gp(cc, 64, false); + cc.movabs(value_reg, MMIN); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + value_reg); + } + cc.jmp(label_merge); + cc.bind(label_else); + { + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + (gen_operation(cc, sdiv, dividend, divisor)), 64, true)); + } + cc.bind(label_merge); + } + } + cc.jmp(label_merge); + cc.bind(label_else); + { + auto value_reg = get_reg_Gp(cc, 64, false); + cc.movabs(value_reg, (uint64_t)- 1); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + value_reg); + } + cc.bind(label_merge); + } + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 65); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 66: DIVU */ + continuation_e __divu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("DIVU_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 66); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, ne, load_reg_from_mem_Gp(jh, traits::X0 + rs2), 0); + cmp(cc, cond, 0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_operation(cc, udiv, load_reg_from_mem_Gp(jh, traits::X0 + rs1), load_reg_from_mem_Gp(jh, traits::X0 + rs2))); + } + } + cc.jmp(label_merge); + cc.bind(label_else); + { + if(rd!=0){ + auto value_reg = get_reg_Gp(cc, 64, false); + cc.movabs(value_reg, (uint64_t)- 1); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + value_reg); + } + } + cc.bind(label_merge); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 66); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 67: REM */ + continuation_e __rem(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("REM_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 67); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, ne, load_reg_from_mem_Gp(jh, traits::X0 + rs2), 0); + cmp(cc, cond, 0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + auto MMIN = (uint64_t)1<<(static_cast(traits::XLEN)-1); + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, land, gen_operation(cc, eq, load_reg_from_mem_Gp(jh, traits::X0 + rs1), MMIN), gen_operation(cc, eq, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 64, false), - 1)); + cmp(cc, cond, 0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + if(rd!=0){ + auto value_reg = get_reg_Gp(cc, 64, false); + cc.movabs(value_reg, 0); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + value_reg); + } + } + cc.jmp(label_merge); + cc.bind(label_else); + { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, (gen_operation(cc, srem, gen_ext(cc, load_reg_from_mem_Gp(jh, traits::X0 + rs1), 64, true), gen_ext(cc, load_reg_from_mem_Gp(jh, traits::X0 + rs2), 64, true))), 64, false)); + } + } + cc.bind(label_merge); + } + } + cc.jmp(label_merge); + cc.bind(label_else); + { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + load_reg_from_mem_Gp(jh, traits::X0 + rs1)); + } + } + cc.bind(label_merge); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 67); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 68: REMU */ + continuation_e __remu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("REMU_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 68); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, ne, load_reg_from_mem_Gp(jh, traits::X0 + rs2), 0); + cmp(cc, cond, 0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_operation(cc, urem, load_reg_from_mem_Gp(jh, traits::X0 + rs1), load_reg_from_mem_Gp(jh, traits::X0 + rs2))); + } + } + cc.jmp(label_merge); + cc.bind(label_else); + { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + load_reg_from_mem_Gp(jh, traits::X0 + rs1)); + } + } + cc.bind(label_merge); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 68); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 69: MULW */ + continuation_e __mulw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("MULW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 69); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto resw = gen_ext(cc, + (gen_operation(cc, smul, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 32, false), gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false))), 32, true); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, gen_ext(cc, + resw, 64, true), 64, false)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 69); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 70: DIVW */ + continuation_e __divw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("DIVW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 70); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto dividend = gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 32, false); + auto divisor = gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false); + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, ne, divisor, 0); + cmp(cc, cond, 0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + auto MMIN = (int32_t)1<<31; + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, land, gen_operation(cc, eq, dividend, MMIN), gen_operation(cc, eq, divisor, - 1)); + cmp(cc, cond, 0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + if(rd!=0){ + auto value_reg = get_reg_Gp(cc, 64, false); + cc.movabs(value_reg, (uint64_t)- 1<<31); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + value_reg); + } + } + cc.jmp(label_merge); + cc.bind(label_else); + { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + (gen_operation(cc, sdiv, dividend, divisor)), 64, true)); + } + } + cc.bind(label_merge); + } + } + cc.jmp(label_merge); + cc.bind(label_else); + { + if(rd!=0){ + auto value_reg = get_reg_Gp(cc, 64, false); + cc.movabs(value_reg, (uint64_t)- 1); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + value_reg); + } + } + cc.bind(label_merge); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 70); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 71: DIVUW */ + continuation_e __divuw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divuw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("DIVUW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 71); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto divisor = gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false); + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, ne, divisor, 0); + cmp(cc, cond, 0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + auto res = gen_ext(cc, + (gen_operation(cc, udiv, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 32, false), divisor)), 32, false); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, gen_ext(cc, + res, 64, true), 64, false)); + } + } + cc.jmp(label_merge); + cc.bind(label_else); + { + if(rd!=0){ + auto value_reg = get_reg_Gp(cc, 64, false); + cc.movabs(value_reg, (uint64_t)- 1); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + value_reg); + } + } + cc.bind(label_merge); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 71); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 72: REMW */ + continuation_e __remw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("REMW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 72); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, ne, (gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false)), 0); + cmp(cc, cond, 0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + auto SMIN = (int32_t)1<<31; + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, land, gen_operation(cc, eq, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 32, false), SMIN), gen_operation(cc, eq, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false), - 1)); + cmp(cc, cond, 0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + if(rd!=0){ + auto value_reg = get_reg_Gp(cc, 64, false); + cc.movabs(value_reg, 0); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + value_reg); + } + } + cc.jmp(label_merge); + cc.bind(label_else); + { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + (gen_operation(cc, srem, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 32, false), gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false))), 64, true)); + } + } + cc.bind(label_merge); + } + } + cc.jmp(label_merge); + cc.bind(label_else); + { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + (gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 32, false)), 64, true)); + } + } + cc.bind(label_merge); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 72); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 73: REMUW */ + continuation_e __remuw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remuw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("REMUW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 73); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto divisor = gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false); + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, ne, divisor, 0); + cmp(cc, cond, 0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + auto res = gen_ext(cc, + (gen_operation(cc, urem, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 32, false), divisor)), 32, false); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, gen_ext(cc, + res, 64, true), 64, false)); + } + } + cc.jmp(label_merge); + cc.bind(label_else); + { + auto res = gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 32, false); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, gen_ext(cc, + res, 64, true), 64, false)); + } + } + cc.bind(label_merge); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 73); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 74: LRW */ + continuation_e __lrw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {aq}, {rl}", fmt::arg("mnemonic", "lrw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("aq", name(aq)), fmt::arg("rl", name(rl))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("LRW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 74); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + (gen_ext(cc, + gen_read_mem(jh, traits::MEM, offs, 4), 32, false)), 64, true)); + gen_write_mem(jh, traits::RES, offs, (uint8_t)- 1, 1); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 74); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 75: SCW */ + continuation_e __scw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}, {aq}, {rl}", fmt::arg("mnemonic", "scw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", name(aq)), fmt::arg("rl", name(rl))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SCW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 75); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res1 = gen_read_mem(jh, traits::RES, offs, 1); + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, ne, res1, 0); + cmp(cc, cond, 0); + cc.je(label_merge); + { + gen_write_mem(jh, traits::MEM, offs, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false), 4); + } + cc.bind(label_merge); + } + if(rd!=0){ + auto label_then6 = cc.newLabel(); + auto label_merge6 = cc.newLabel(); + auto tmp_reg6 = get_reg_Gp(cc, 8, false); + cmp(cc, res1, 0); + cc.jne(label_then6); + mov(cc, tmp_reg6,1); + cc.jmp(label_merge6); + cc.bind(label_then6); + mov(cc, tmp_reg6, 0); + cc.bind(label_merge6); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, tmp_reg6 + , 64, false) + ); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 75); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 76: AMOSWAPW */ + continuation_e __amoswapw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoswapw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOSWAPW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 76); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res = load_reg_from_mem_Gp(jh, traits::X0 + rs2); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + (gen_ext(cc, + gen_read_mem(jh, traits::MEM, offs, 4), 32, false)), 64, true)); + } + gen_write_mem(jh, traits::MEM, offs, gen_ext(cc, + res, 32, false), 4); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 76); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 77: AMOADDW */ + continuation_e __amoaddw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoaddw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOADDW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 77); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res1 = gen_ext(cc, + gen_read_mem(jh, traits::MEM, offs, 4), 32, false); + auto res2 = gen_operation(cc, add, res1, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false)); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res1, 64, true)); + } + gen_write_mem(jh, traits::MEM, offs, gen_ext(cc, + res2, 32, true), 4); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 77); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 78: AMOXORW */ + continuation_e __amoxorw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoxorw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOXORW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 78); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res1 = gen_read_mem(jh, traits::MEM, offs, 4); + auto res2 = gen_operation(cc, bxor, res1, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false)); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, gen_ext(cc, + gen_ext(cc, res1, 32, true), 64, true), 64, false)); + } + gen_write_mem(jh, traits::MEM, offs, res2, 4); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 78); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 79: AMOANDW */ + continuation_e __amoandw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoandw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOANDW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 79); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res1 = gen_read_mem(jh, traits::MEM, offs, 4); + auto res2 = gen_operation(cc, band, res1, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false)); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, gen_ext(cc, + gen_ext(cc, res1, 32, true), 64, true), 64, false)); + } + gen_write_mem(jh, traits::MEM, offs, res2, 4); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 79); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 80: AMOORW */ + continuation_e __amoorw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoorw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOORW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 80); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res1 = gen_read_mem(jh, traits::MEM, offs, 4); + auto res2 = gen_operation(cc, bor, res1, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false)); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, gen_ext(cc, + gen_ext(cc, res1, 32, true), 64, true), 64, false)); + } + gen_write_mem(jh, traits::MEM, offs, res2, 4); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 80); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 81: AMOMINW */ + continuation_e __amominw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amominw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOMINW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 81); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res1 = gen_ext(cc, + gen_read_mem(jh, traits::MEM, offs, 4), 32, false); + auto label_then7 = cc.newLabel(); + auto label_merge7 = cc.newLabel(); + auto tmp_reg7 = get_reg_Gp(cc, 32, false); + cmp(cc, res1, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false)); + cc.jg(label_then7); + mov(cc, tmp_reg7,gen_ext(cc, res1, 32, false)); + cc.jmp(label_merge7); + cc.bind(label_then7); + mov(cc, tmp_reg7, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false)); + cc.bind(label_merge7); + auto res2 = tmp_reg7 + ; + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res1, 64, true)); + } + gen_write_mem(jh, traits::MEM, offs, res2, 4); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 81); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 82: AMOMAXW */ + continuation_e __amomaxw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amomaxw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOMAXW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 82); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res1 = gen_ext(cc, + gen_read_mem(jh, traits::MEM, offs, 4), 32, false); + auto label_then8 = cc.newLabel(); + auto label_merge8 = cc.newLabel(); + auto tmp_reg8 = get_reg_Gp(cc, 32, false); + cmp(cc, res1, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false)); + cc.jl(label_then8); + mov(cc, tmp_reg8,gen_ext(cc, res1, 32, false)); + cc.jmp(label_merge8); + cc.bind(label_then8); + mov(cc, tmp_reg8, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false)); + cc.bind(label_merge8); + auto res2 = tmp_reg8 + ; + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res1, 64, true)); + } + gen_write_mem(jh, traits::MEM, offs, res2, 4); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 82); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 83: AMOMINUW */ + continuation_e __amominuw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amominuw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOMINUW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 83); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res1 = gen_read_mem(jh, traits::MEM, offs, 4); + auto label_then9 = cc.newLabel(); + auto label_merge9 = cc.newLabel(); + auto tmp_reg9 = get_reg_Gp(cc, 32, false); + cmp(cc, res1, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false)); + cc.ja(label_then9); + mov(cc, tmp_reg9,res1); + cc.jmp(label_merge9); + cc.bind(label_then9); + mov(cc, tmp_reg9, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false)); + cc.bind(label_merge9); + auto res2 = tmp_reg9 + ; + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, gen_ext(cc, + gen_ext(cc, res1, 32, true), 64, true), 64, false)); + } + gen_write_mem(jh, traits::MEM, offs, res2, 4); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 83); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 84: AMOMAXUW */ + continuation_e __amomaxuw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amomaxuw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOMAXUW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 84); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res1 = gen_read_mem(jh, traits::MEM, offs, 4); + auto label_then10 = cc.newLabel(); + auto label_merge10 = cc.newLabel(); + auto tmp_reg10 = get_reg_Gp(cc, 32, false); + cmp(cc, res1, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false)); + cc.jb(label_then10); + mov(cc, tmp_reg10,res1); + cc.jmp(label_merge10); + cc.bind(label_then10); + mov(cc, tmp_reg10, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false)); + cc.bind(label_merge10); + auto res2 = tmp_reg10 + ; + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, gen_ext(cc, + gen_ext(cc, res1, 32, true), 64, true), 64, false)); + } + gen_write_mem(jh, traits::MEM, offs, res2, 4); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 84); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 85: LRD */ + continuation_e __lrd(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}", fmt::arg("mnemonic", "lrd"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("LRD_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 85); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + (gen_ext(cc, + gen_read_mem(jh, traits::MEM, offs, 8), 64, false)), 64, true)); + gen_write_mem(jh, traits::RES, offs, (uint8_t)- 1, 1); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 85); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 86: SCD */ + continuation_e __scd(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "scd"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("SCD_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 86); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res = gen_read_mem(jh, traits::RES, offs, 1); + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, ne, res, 0); + cmp(cc, cond, 0); + cc.je(label_merge); + { + gen_write_mem(jh, traits::MEM, offs, load_reg_from_mem_Gp(jh, traits::X0 + rs2), 8); + } + cc.bind(label_merge); + } + if(rd!=0){ + auto label_then11 = cc.newLabel(); + auto label_merge11 = cc.newLabel(); + auto tmp_reg11 = get_reg_Gp(cc, 8, false); + cmp(cc, res, 0); + cc.jne(label_then11); + mov(cc, tmp_reg11,1); + cc.jmp(label_merge11); + cc.bind(label_then11); + mov(cc, tmp_reg11, 0); + cc.bind(label_merge11); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, tmp_reg11 + , 64, false) + ); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 86); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 87: AMOSWAPD */ + continuation_e __amoswapd(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoswapd"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOSWAPD_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 87); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res = load_reg_from_mem_Gp(jh, traits::X0 + rs2); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + (gen_ext(cc, + gen_read_mem(jh, traits::MEM, offs, 8), 64, false)), 64, true)); + } + gen_write_mem(jh, traits::MEM, offs, gen_ext(cc, + res, 64, false), 8); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 87); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 88: AMOADDD */ + continuation_e __amoaddd(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoaddd"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOADDD_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 88); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res1 = gen_read_mem(jh, traits::MEM, offs, 8); + auto res2 = gen_ext(cc, + (gen_operation(cc, add, res1, load_reg_from_mem_Gp(jh, traits::X0 + rs2))), 64, false); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res1, 64, false)); + } + gen_write_mem(jh, traits::MEM, offs, res2, 8); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 88); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 89: AMOXORD */ + continuation_e __amoxord(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoxord"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOXORD_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 89); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res1 = gen_read_mem(jh, traits::MEM, offs, 8); + auto res2 = gen_operation(cc, bxor, res1, load_reg_from_mem_Gp(jh, traits::X0 + rs2)); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, gen_ext(cc, + res1, 64, false), 64, false)); + } + gen_write_mem(jh, traits::MEM, offs, res2, 8); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 89); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 90: AMOANDD */ + continuation_e __amoandd(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoandd"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOANDD_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 90); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res1 = gen_read_mem(jh, traits::MEM, offs, 8); + auto res2 = gen_operation(cc, band, res1, load_reg_from_mem_Gp(jh, traits::X0 + rs2)); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res1, 64, false)); + } + gen_write_mem(jh, traits::MEM, offs, res2, 8); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 90); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 91: AMOORD */ + continuation_e __amoord(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoord"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOORD_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 91); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res1 = gen_read_mem(jh, traits::MEM, offs, 8); + auto res2 = gen_operation(cc, bor, res1, load_reg_from_mem_Gp(jh, traits::X0 + rs2)); + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res1, 64, false)); + } + gen_write_mem(jh, traits::MEM, offs, res2, 8); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 91); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 92: AMOMIND */ + continuation_e __amomind(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amomind"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOMIND_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 92); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res1 = gen_ext(cc, + gen_read_mem(jh, traits::MEM, offs, 8), 64, false); + auto label_then12 = cc.newLabel(); + auto label_merge12 = cc.newLabel(); + auto tmp_reg12 = get_reg_Gp(cc, 64, false); + cmp(cc, res1, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 64, false)); + cc.jg(label_then12); + mov(cc, tmp_reg12,gen_ext(cc, res1, 64, false)); + cc.jmp(label_merge12); + cc.bind(label_then12); + mov(cc, tmp_reg12, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 64, false)); + cc.bind(label_merge12); + auto res2 = tmp_reg12 + ; + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res1, 64, true)); + } + gen_write_mem(jh, traits::MEM, offs, res2, 8); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 92); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 93: AMOMAXD */ + continuation_e __amomaxd(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amomaxd"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOMAXD_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 93); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res1 = gen_ext(cc, + gen_read_mem(jh, traits::MEM, offs, 8), 64, false); + auto label_then13 = cc.newLabel(); + auto label_merge13 = cc.newLabel(); + auto tmp_reg13 = get_reg_Gp(cc, 64, false); + cmp(cc, res1, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 64, false)); + cc.jl(label_then13); + mov(cc, tmp_reg13,gen_ext(cc, res1, 64, false)); + cc.jmp(label_merge13); + cc.bind(label_then13); + mov(cc, tmp_reg13, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 64, false)); + cc.bind(label_merge13); + auto res2 = tmp_reg13 + ; + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res1, 64, true)); + } + gen_write_mem(jh, traits::MEM, offs, res2, 8); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 93); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 94: AMOMINUD */ + continuation_e __amominud(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amominud"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOMINUD_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 94); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res1 = gen_read_mem(jh, traits::MEM, offs, 8); + auto label_then14 = cc.newLabel(); + auto label_merge14 = cc.newLabel(); + auto tmp_reg14 = get_reg_Gp(cc, 64, false); + cmp(cc, res1, load_reg_from_mem_Gp(jh, traits::X0 + rs2)); + cc.ja(label_then14); + mov(cc, tmp_reg14,res1); + cc.jmp(label_merge14); + cc.bind(label_then14); + mov(cc, tmp_reg14, load_reg_from_mem_Gp(jh, traits::X0 + rs2)); + cc.bind(label_merge14); + auto res2 = tmp_reg14 + ; + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res1, 64, false)); + } + gen_write_mem(jh, traits::MEM, offs, res2, 8); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 94); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 95: AMOMAXUD */ + continuation_e __amomaxud(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amomaxud"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("AMOMAXUD_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 95); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+4; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto res1 = gen_read_mem(jh, traits::MEM, offs, 8); + auto label_then15 = cc.newLabel(); + auto label_merge15 = cc.newLabel(); + auto tmp_reg15 = get_reg_Gp(cc, 64, false); + cmp(cc, res1, load_reg_from_mem_Gp(jh, traits::X0 + rs2)); + cc.jb(label_then15); + mov(cc, tmp_reg15,res1); + cc.jmp(label_merge15); + cc.bind(label_then15); + mov(cc, tmp_reg15, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 64, false)); + cc.bind(label_merge15); + auto res2 = tmp_reg15 + ; + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + res1, 64, false)); + } + gen_write_mem(jh, traits::MEM, offs, res2, 8); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 95); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 96: C__ADDI4SPN */ + continuation_e __c__addi4spn(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<2,3>(instr))); + uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), + fmt::arg("rd", name(8+rd)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__ADDI4SPN_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 96); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(imm){ + mov(cc, get_ptr_for(jh, traits::X0+ rd+8), + gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + 2), imm)), 64, false)); + } + else { + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 96); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 97: C__LW */ + continuation_e __c__lw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), + fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__LW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 97); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + auto offs = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1+8), uimm)), 64, false); + mov(cc, get_ptr_for(jh, traits::X0+ rd+8), + gen_ext(cc, + gen_ext(cc, + gen_read_mem(jh, traits::MEM, offs, 4), 32, false), 64, true)); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 97); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 98: C__LD */ + continuation_e __c__ld(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {uimm},({rs1})", fmt::arg("mnemonic", "c.ld"), + fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__LD_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 98); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + auto offs = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1+8), uimm)), 64, false); + mov(cc, get_ptr_for(jh, traits::X0+ rd+8), + gen_ext(cc, + gen_read_mem(jh, traits::MEM, offs, 8), 64, false)); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 98); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 99: C__SW */ + continuation_e __c__sw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), + fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__SW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 99); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + auto offs = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1+8), uimm)), 64, false); + gen_write_mem(jh, traits::MEM, offs, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2+8), 32, false), 4); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 99); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 100: C__SD */ + continuation_e __c__sd(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm},({rs1})", fmt::arg("mnemonic", "c.sd"), + fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__SD_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 100); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + auto offs = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1+8), uimm)), 64, false); + gen_write_mem(jh, traits::MEM, offs, load_reg_from_mem_Gp(jh, traits::X0 + rs2+8), 8); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 100); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 101: C__ADDI */ + continuation_e __c__addi(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), + fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__ADDI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 101); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rs1!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rs1), + gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rs1), (int8_t)sext<6>(imm))), 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 101); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 102: C__NOP */ + continuation_e __c__nop(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + if(this->disass_enabled){ + /* generate disass */ + + //No disass specified, using instruction name + std::string mnemonic = "c.nop"; + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__NOP_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 102); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 102); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 103: C__ADDIW */ + continuation_e __c__addiw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addiw"), + fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__ADDIW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 103); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rs1>=static_cast(traits::RFS)||rs1==0){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rs1!=0){ + auto res = gen_ext(cc, + (gen_operation(cc, add, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1), 32, false), (int8_t)sext<6>(imm))), 32, true); + mov(cc, get_ptr_for(jh, traits::X0+ rs1), + gen_ext(cc, + res, 64, true)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 103); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 104: C__LI */ + continuation_e __c__li(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__LI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 104); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + auto value_reg = get_reg_Gp(cc, 64, false); + cc.movabs(value_reg, (uint64_t)((int8_t)sext<6>(imm))); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + value_reg); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 104); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 105: C__LUI */ + continuation_e __c__lui(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__LUI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 105); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(imm==0||rd>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + if(rd!=0){ + auto value_reg = get_reg_Gp(cc, 64, false); + cc.movabs(value_reg, (uint64_t)((int32_t)sext<18>(imm))); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + value_reg); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 105); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 106: C__ADDI16SP */ + continuation_e __c__addi16sp(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), + fmt::arg("nzimm", nzimm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__ADDI16SP_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 106); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(nzimm){ + mov(cc, get_ptr_for(jh, traits::X0+ 2), + gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + 2), (int16_t)sext<10>(nzimm))), 64, true)); + } + else { + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 106); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 107: __reserved_clui */ + continuation_e ____reserved_clui(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + //No disass specified, using instruction name + std::string mnemonic = ".reserved_clui"; + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("__reserved_clui_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 107); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 107); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 108: C__SRLI */ + continuation_e __c__srli(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t nzuimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "c.srli"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("nzuimm", nzuimm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__SRLI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 108); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::X0+ rs1+8), + gen_operation(cc, shr, load_reg_from_mem_Gp(jh, traits::X0 + rs1+8), nzuimm)); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 108); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 109: C__SRAI */ + continuation_e __c__srai(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t shamt = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__SRAI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 109); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::X0+ rs1+8), + gen_ext(cc, + (gen_operation(cc, sar, (gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs1+8), 64, false)), shamt)), 64, true)); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 109); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 110: C__ANDI */ + continuation_e __c__andi(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__ANDI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 110); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::X0+ rs1+8), + gen_ext(cc, + (gen_operation(cc, band, load_reg_from_mem_Gp(jh, traits::X0 + rs1+8), (int8_t)sext<6>(imm))), 64, true)); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 110); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 111: C__SUB */ + continuation_e __c__sub(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__SUB_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 111); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::X0+ rd+8), + gen_ext(cc, + (gen_operation(cc, sub, load_reg_from_mem_Gp(jh, traits::X0 + rd+8), load_reg_from_mem_Gp(jh, traits::X0 + rs2+8))), 64, true)); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 111); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 112: C__XOR */ + continuation_e __c__xor(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__XOR_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 112); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::X0+ rd+8), + gen_operation(cc, bxor, load_reg_from_mem_Gp(jh, traits::X0 + rd+8), load_reg_from_mem_Gp(jh, traits::X0 + rs2+8))); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 112); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 113: C__OR */ + continuation_e __c__or(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__OR_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 113); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::X0+ rd+8), + gen_operation(cc, bor, load_reg_from_mem_Gp(jh, traits::X0 + rd+8), load_reg_from_mem_Gp(jh, traits::X0 + rs2+8))); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 113); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 114: C__AND */ + continuation_e __c__and(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__AND_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 114); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::X0+ rd+8), + gen_operation(cc, band, load_reg_from_mem_Gp(jh, traits::X0 + rd+8), load_reg_from_mem_Gp(jh, traits::X0 + rs2+8))); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 114); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 115: C__SUBW */ + continuation_e __c__subw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.subw"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__SUBW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 115); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + auto res = gen_ext(cc, + (gen_operation(cc, sub, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rd+8), 32, false), gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2+8), 32, false))), 32, true); + mov(cc, get_ptr_for(jh, traits::X0+ rd+8), + gen_ext(cc, + res, 64, true)); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 115); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 116: C__ADDW */ + continuation_e __c__addw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.addw"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__ADDW_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 116); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + auto res = gen_ext(cc, + (gen_operation(cc, add, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rd+8), 32, false), gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2+8), 32, false))), 32, true); + mov(cc, get_ptr_for(jh, traits::X0+ rd+8), + gen_ext(cc, + res, 64, true)); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 116); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 117: C__J */ + continuation_e __c__j(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), + fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__J_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 117); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(NO_JUMP)); + auto PC_val_v = (uint64_t)(PC+(int16_t)sext<12>(imm)); + mov(cc, jh.next_pc, PC_val_v); + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(KNOWN_JUMP)); + auto returnValue = BRANCH; + + gen_sync(jh, POST_SYNC, 117); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 118: C__BEQZ */ + continuation_e __c__beqz(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__BEQZ_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 118); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(NO_JUMP)); + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, eq, load_reg_from_mem_Gp(jh, traits::X0 + rs1+8), 0); + cmp(cc, cond, 0); + cc.je(label_merge); + { + auto PC_val_v = (uint64_t)(PC+(int16_t)sext<9>(imm)); + mov(cc, jh.next_pc, PC_val_v); + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(KNOWN_JUMP)); + } + cc.bind(label_merge); + } + auto returnValue = BRANCH; + + gen_sync(jh, POST_SYNC, 118); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 119: C__BNEZ */ + continuation_e __c__bnez(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__BNEZ_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 119); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(NO_JUMP)); + { + auto label_merge = cc.newLabel(); + auto cond = gen_operation(cc, ne, load_reg_from_mem_Gp(jh, traits::X0 + rs1+8), 0); + cmp(cc, cond, 0); + cc.je(label_merge); + { + auto PC_val_v = (uint64_t)(PC+(int16_t)sext<9>(imm)); + mov(cc, jh.next_pc, PC_val_v); + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(KNOWN_JUMP)); + } + cc.bind(label_merge); + } + auto returnValue = BRANCH; + + gen_sync(jh, POST_SYNC, 119); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 120: C__SLLI */ + continuation_e __c__slli(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t shamt = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.slli"), + fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__SLLI_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 120); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rs1!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rs1), + gen_operation(cc, shl, load_reg_from_mem_Gp(jh, traits::X0 + rs1), shamt)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 120); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 121: C__LWSP */ + continuation_e __c__lwsp(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.lwsp"), + fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__LWSP_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 121); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rd==0){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + 2), uimm)), 64, false); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + gen_ext(cc, + gen_read_mem(jh, traits::MEM, offs, 4), 32, false), 64, true)); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 121); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 122: C__LDSP */ + continuation_e __c__ldsp(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t uimm = ((bit_sub<2,3>(instr) << 6) | (bit_sub<5,2>(instr) << 3) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {uimm}(sp)", fmt::arg("mnemonic", "c.ldsp"), + fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__LDSP_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 122); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rd==0){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + 2), uimm)), 64, false); + auto res = gen_ext(cc, + gen_read_mem(jh, traits::MEM, offs, 8), 64, false); + mov(cc, get_ptr_for(jh, traits::X0+ rd), + res); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 122); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 123: C__MV */ + continuation_e __c__mv(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__MV_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 123); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + load_reg_from_mem_Gp(jh, traits::X0 + rs2)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 123); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 124: C__JR */ + continuation_e __c__jr(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), + fmt::arg("rs1", name(rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__JR_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 124); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(NO_JUMP)); + if(rs1&&rs1(traits::RFS)){ + auto addr_mask = (uint64_t)- 2; + auto PC_val_v = gen_operation(cc, band, load_reg_from_mem_Gp(jh, traits::X0 + rs1%static_cast(traits::RFS)), addr_mask); + mov(cc, jh.next_pc, PC_val_v); + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(UNKNOWN_JUMP)); + } + else { + gen_raise(jh, 0, 2); + } + auto returnValue = BRANCH; + + gen_sync(jh, POST_SYNC, 124); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 125: __reserved_cmv */ + continuation_e ____reserved_cmv(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate disass */ + + //No disass specified, using instruction name + std::string mnemonic = ".reserved_cmv"; + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("__reserved_cmv_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 125); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + gen_raise(jh, 0, 2); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 125); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 126: C__ADD */ + continuation_e __c__add(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__ADD_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 126); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + if(rd!=0){ + mov(cc, get_ptr_for(jh, traits::X0+ rd), + gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + rd), load_reg_from_mem_Gp(jh, traits::X0 + rs2))), 64, false)); + } + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 126); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 127: C__JALR */ + continuation_e __c__jalr(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), + fmt::arg("rs1", name(rs1))); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__JALR_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 127); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(NO_JUMP)); + if(rs1>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto addr_mask = (uint64_t)- 2; + auto new_pc = load_reg_from_mem_Gp(jh, traits::X0 + rs1); + auto value_reg = get_reg_Gp(cc, 64, false); + cc.movabs(value_reg, (uint64_t)(PC+2)); + mov(cc, get_ptr_for(jh, traits::X0+ 1), + value_reg); + auto PC_val_v = gen_operation(cc, band, new_pc, addr_mask); + mov(cc, jh.next_pc, PC_val_v); + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(UNKNOWN_JUMP)); + } + auto returnValue = BRANCH; + + gen_sync(jh, POST_SYNC, 127); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 128: C__EBREAK */ + continuation_e __c__ebreak(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate disass */ + + //No disass specified, using instruction name + std::string mnemonic = "c.ebreak"; + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__EBREAK_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 128); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + gen_raise(jh, 0, 3); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 128); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 129: C__SWSP */ + continuation_e __c__swsp(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), + fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__SWSP_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 129); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + 2), uimm)), 64, false); + gen_write_mem(jh, traits::MEM, offs, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 32, false), 4); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 129); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 130: C__SDSP */ + continuation_e __c__sdsp(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint16_t uimm = ((bit_sub<7,3>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); + if(this->disass_enabled){ + /* generate disass */ + + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm}(sp)", fmt::arg("mnemonic", "c.sdsp"), + fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("C__SDSP_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 130); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + if(rs2>=static_cast(traits::RFS)){ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + } + else { + auto offs = gen_ext(cc, + (gen_operation(cc, add, load_reg_from_mem_Gp(jh, traits::X0 + 2), uimm)), 64, false); + gen_write_mem(jh, traits::MEM, offs, gen_ext(cc, + load_reg_from_mem_Gp(jh, traits::X0 + rs2), 64, false), 8); + } + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 130); + gen_instr_epilogue(jh); + return returnValue; + } + + /* instruction 131: DII */ + continuation_e __dii(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate disass */ + + //No disass specified, using instruction name + std::string mnemonic = "dii"; + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + + } + x86::Compiler& cc = jh.cc; + cc.comment(fmt::format("DII_{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, 131); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc+2; + mov(cc, jh.next_pc, pc.val); + cc.mov(get_ptr_for(jh, traits::INSTRUCTION), instr); + + gen_instr_prologue(jh); + /*generate behavior*/ + gen_raise(jh, 0, static_cast(traits::RV_CAUSE_ILLEGAL_INSTRUCTION)); + auto returnValue = CONT; + + gen_sync(jh, POST_SYNC, 131); + gen_instr_epilogue(jh); + return returnValue; + } + + /**************************************************************************** + * end opcode definitions + ****************************************************************************/ + continuation_e illegal_instruction(virt_addr_t &pc, code_word_t instr, jit_holder& jh ) { + x86::Compiler& cc = jh.cc; + if(this->disass_enabled){ + auto mnemonic = std::string("illegal_instruction"); + InvokeNode* call_print_disass; + char* mnemonic_ptr = strdup(mnemonic.c_str()); + jh.disass_collection.push_back(mnemonic_ptr); + jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build()); + call_print_disass->setArg(0, jh.arch_if_ptr); + call_print_disass->setArg(1, pc.val); + call_print_disass->setArg(2, mnemonic_ptr); + } + cc.comment(fmt::format("illegal_instruction{:#x}:",pc.val).c_str()); + gen_sync(jh, PRE_SYNC, instr_descr.size()); + mov(cc, jh.pc, pc.val); + gen_set_tval(jh, instr); + pc = pc + ((instr & 3) == 3 ? 4 : 2); + mov(cc, jh.next_pc, pc.val); + gen_instr_prologue(jh); + gen_raise(jh, 0, 2); + gen_sync(jh, POST_SYNC, instr_descr.size()); + gen_instr_epilogue(jh); + return ILLEGAL_INSTR; + } +}; + +template vm_impl::vm_impl() +: vm_base(std::make_unique()) {} + +template +vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) +: vm_base(core, core_id, cluster_id) +, instr_decoder([this]() { + std::vector g_instr_descr; + g_instr_descr.reserve(instr_descr.size()); + for (uint32_t i = 0; i < instr_descr.size(); ++i) { + generic_instruction_descriptor new_instr_descr {instr_descr[i].value, instr_descr[i].mask, i}; + g_instr_descr.push_back(new_instr_descr); + } + return std::move(g_instr_descr); + }()) {} + +template +continuation_e vm_impl::gen_single_inst_behavior(virt_addr_t &pc, jit_holder& jh) { + enum {TRAP_ID=1<<16}; + code_word_t instr = 0; + auto *const data = (uint8_t *)&instr; + auto res = this->core.read({address_type::LOGICAL, access_type::DEBUG_READ, arch::traits::IMEM, pc.val}, 4, data); + if (res != iss::Ok) + return ILLEGAL_FETCH; + if (instr == 0x0000006f || (instr&0xffff)==0xa001) + return JUMP_TO_SELF; + uint32_t inst_index = instr_decoder.decode_instr(instr); + compile_func f = nullptr; + if(inst_index < instr_descr.size()) + f = instr_descr[inst_index].op; + if (f == nullptr) + f = &this_class::illegal_instruction; + return (this->*f)(pc, instr, jh); +} +template +void vm_impl::gen_instr_prologue(jit_holder& jh) { + auto& cc = jh.cc; + + x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE); + mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE)); + mov(cc, get_ptr_for(jh, traits::PENDING_TRAP), current_trap_state); + cc.inc(get_ptr_for(jh, traits::CYCLE)); + cc.comment("//Instruction prologue end"); + +} +template +void vm_impl::gen_instr_epilogue(jit_holder& jh) { + auto& cc = jh.cc; + + cc.comment("//Instruction epilogue begin"); + x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE); + mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE)); + cmp(cc, current_trap_state, 0); + cc.jne(jh.trap_entry); + cc.inc(get_ptr_for(jh, traits::ICOUNT)); + cc.inc(get_ptr_for(jh, traits::INSTRET)); + cc.comment("//Instruction epilogue end"); + +} +template +void vm_impl::gen_block_prologue(jit_holder& jh){ + jh.pc = load_reg_from_mem_Gp(jh, traits::PC); + jh.next_pc = load_reg_from_mem_Gp(jh, traits::NEXT_PC); + jh.globals.resize(GLOBALS_SIZE); + jh.globals[TVAL] = get_reg_Gp(jh.cc, 64, false); +} +template +void vm_impl::gen_block_epilogue(jit_holder& jh){ + x86::Compiler& cc = jh.cc; + cc.comment("//gen_block_epilogue"); + cc.ret(jh.next_pc); + + cc.bind(jh.trap_entry); + this->write_back(jh); + + x86::Gp current_trap_state = get_reg_for_Gp(cc, traits::TRAP_STATE); + mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE)); + + x86::Gp current_pc = get_reg_for_Gp(cc, traits::PC); + mov(cc, current_pc, get_ptr_for(jh, traits::PC)); + + InvokeNode* call_enter_trap; + cc.invoke(&call_enter_trap, &enter_trap, FuncSignature::build()); + call_enter_trap->setArg(0, jh.arch_if_ptr); + call_enter_trap->setArg(1, current_trap_state); + call_enter_trap->setArg(2, current_pc); + call_enter_trap->setArg(3, jh.globals[TVAL]); + + x86_reg_t current_next_pc = get_reg_for(cc, traits::NEXT_PC); + mov(cc, current_next_pc, get_ptr_for(jh, traits::NEXT_PC)); + mov(cc, jh.next_pc, current_next_pc); + + mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast(UNKNOWN_JUMP)); + cc.ret(jh.next_pc); +} +template +inline void vm_impl::gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) { + auto& cc = jh.cc; + auto tmp1 = get_reg_for(cc, traits::TRAP_STATE); + mov(cc, tmp1, 0x80ULL << 24 | (cause << 16) | trap_id); + mov(cc, get_ptr_for(jh, traits::TRAP_STATE), tmp1); + cc.jmp(jh.trap_entry); +} +template +inline void vm_impl::gen_lower(jit_holder& jh) { + auto& cc = jh.cc; + auto tmp1 = get_reg_for(cc, traits::TRAP_STATE); + mov(cc, tmp1, 0); + mov(cc, get_ptr_for(jh, traits::TRAP_STATE), tmp1); +} +template +template +void vm_impl::gen_set_tval(jit_holder& jh, T new_tval) { + mov(jh.cc, jh.globals[TVAL], new_tval); + } +template +void vm_impl::gen_set_tval(jit_holder& jh, x86_reg_t _new_tval) { + if(nonstd::holds_alternative(_new_tval)) { + x86::Gp new_tval = nonstd::get(_new_tval); + if(new_tval.size() < 8) + new_tval = gen_ext_Gp(jh.cc, new_tval, 64, false); + mov(jh.cc, jh.globals[TVAL], new_tval); + } else { + throw std::runtime_error("Variant not supported in gen_set_tval"); + } +} + +} // namespace tgc5c + +template <> +std::unique_ptr create(arch::rv64imac *core, unsigned short port, bool dump) { + auto ret = new rv64imac::vm_impl(*core, dump); + if (port != 0) debugger::server::run_server(ret, port); + return std::unique_ptr(ret); +} +} // namespace asmjit +} // namespace iss + +#include +#include +#include +#include +namespace iss { +namespace { + +volatile std::array dummy = { + core_factory::instance().register_creator("rv64imac_m:asmjit", [](unsigned port, void* init_data) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto vm = new asmjit::rv64imac::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + if(init_data){ + auto* cb = reinterpret_cast::reg_t>*>(init_data); + cpu->set_semihosting_callback(*cb); + } + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("rv64imac_mu:asmjit", [](unsigned port, void* init_data) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto vm = new asmjit::rv64imac::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + if(init_data){ + auto* cb = reinterpret_cast::reg_t>*>(init_data); + cpu->set_semihosting_callback(*cb); + } + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} +// clang-format on diff --git a/src/vm/interp/vm_rv32gc.cpp b/src/vm/interp/vm_rv32gc.cpp index 237b75e..8fca91c 100644 --- a/src/vm/interp/vm_rv32gc.cpp +++ b/src/vm/interp/vm_rv32gc.cpp @@ -419,6 +419,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto& instr = this->core.reg.instruction; // we fetch at max 4 byte, alignment is 2 auto *const data = reinterpret_cast(&instr); + this->core.enable_disass(this->disass_enabled); while(!this->core.should_stop() && !(is_icount_limit_enabled(cond) && icount >= count_limit) && @@ -440,7 +441,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co inst_id = instr_descr[inst_index].op; // pre execution stuff - this->core.reg.last_branch = 0; + this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); try{ switch(inst_id){ diff --git a/src/vm/interp/vm_rv32gcv.cpp b/src/vm/interp/vm_rv32gcv.cpp index 5a092e9..91a8ea4 100644 --- a/src/vm/interp/vm_rv32gcv.cpp +++ b/src/vm/interp/vm_rv32gcv.cpp @@ -1390,6 +1390,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto& instr = this->core.reg.instruction; // we fetch at max 4 byte, alignment is 2 auto *const data = reinterpret_cast(&instr); + this->core.enable_disass(this->disass_enabled); while(!this->core.should_stop() && !(is_icount_limit_enabled(cond) && icount >= count_limit) && @@ -1411,7 +1412,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co inst_id = instr_descr[inst_index].op; // pre execution stuff - this->core.reg.last_branch = 0; + this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); try{ switch(inst_id){ diff --git a/src/vm/interp/vm_rv32i.cpp b/src/vm/interp/vm_rv32i.cpp index 59677d4..00d5b39 100644 --- a/src/vm/interp/vm_rv32i.cpp +++ b/src/vm/interp/vm_rv32i.cpp @@ -275,6 +275,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto& instr = this->core.reg.instruction; // we fetch at max 4 byte, alignment is 2 auto *const data = reinterpret_cast(&instr); + this->core.enable_disass(this->disass_enabled); while(!this->core.should_stop() && !(is_icount_limit_enabled(cond) && icount >= count_limit) && @@ -296,7 +297,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co inst_id = instr_descr[inst_index].op; // pre execution stuff - this->core.reg.last_branch = 0; + this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); try{ switch(inst_id){ @@ -1793,7 +1794,6 @@ std::unique_ptr create(arch::rv32i *core, unsigned short por } // namespace iss #include -#include #include #include diff --git a/src/vm/interp/vm_rv32imac.cpp b/src/vm/interp/vm_rv32imac.cpp index 9da59a0..1b384e5 100644 --- a/src/vm/interp/vm_rv32imac.cpp +++ b/src/vm/interp/vm_rv32imac.cpp @@ -324,6 +324,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto& instr = this->core.reg.instruction; // we fetch at max 4 byte, alignment is 2 auto *const data = reinterpret_cast(&instr); + this->core.enable_disass(this->disass_enabled); while(!this->core.should_stop() && !(is_icount_limit_enabled(cond) && icount >= count_limit) && @@ -345,7 +346,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co inst_id = instr_descr[inst_index].op; // pre execution stuff - this->core.reg.last_branch = 0; + this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); try{ switch(inst_id){ @@ -3195,7 +3196,6 @@ std::unique_ptr create(arch::rv32imac *core, unsigned sho } // namespace iss #include -#include #include #include diff --git a/src/vm/interp/vm_rv64gc.cpp b/src/vm/interp/vm_rv64gc.cpp index 004e002..e8f650e 100644 --- a/src/vm/interp/vm_rv64gc.cpp +++ b/src/vm/interp/vm_rv64gc.cpp @@ -459,6 +459,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto& instr = this->core.reg.instruction; // we fetch at max 4 byte, alignment is 2 auto *const data = reinterpret_cast(&instr); + this->core.enable_disass(this->disass_enabled); while(!this->core.should_stop() && !(is_icount_limit_enabled(cond) && icount >= count_limit) && @@ -480,7 +481,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co inst_id = instr_descr[inst_index].op; // pre execution stuff - this->core.reg.last_branch = 0; + this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); try{ switch(inst_id){ @@ -3978,8 +3979,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rd}, {rs2}", fmt::arg("mnemonic", "c.subw"), - fmt::arg("rd", name(8+rd)), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.subw"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); this->core.disass_output(pc.val, mnemonic); } // used registers @@ -3999,8 +4000,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rd}, {rs2}", fmt::arg("mnemonic", "c.addw"), - fmt::arg("rd", name(8+rd)), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.addw"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); this->core.disass_output(pc.val, mnemonic); } // used registers diff --git a/src/vm/interp/vm_rv64gcv.cpp b/src/vm/interp/vm_rv64gcv.cpp index b51990d..950336e 100644 --- a/src/vm/interp/vm_rv64gcv.cpp +++ b/src/vm/interp/vm_rv64gcv.cpp @@ -1430,6 +1430,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto& instr = this->core.reg.instruction; // we fetch at max 4 byte, alignment is 2 auto *const data = reinterpret_cast(&instr); + this->core.enable_disass(this->disass_enabled); while(!this->core.should_stop() && !(is_icount_limit_enabled(cond) && icount >= count_limit) && @@ -1451,7 +1452,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co inst_id = instr_descr[inst_index].op; // pre execution stuff - this->core.reg.last_branch = 0; + this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); try{ switch(inst_id){ @@ -4949,8 +4950,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rd}, {rs2}", fmt::arg("mnemonic", "c.subw"), - fmt::arg("rd", name(8+rd)), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.subw"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); this->core.disass_output(pc.val, mnemonic); } // used registers @@ -4970,8 +4971,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rd}, {rs2}", fmt::arg("mnemonic", "c.addw"), - fmt::arg("rd", name(8+rd)), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.addw"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); this->core.disass_output(pc.val, mnemonic); } // used registers diff --git a/src/vm/interp/vm_rv64i.cpp b/src/vm/interp/vm_rv64i.cpp index 9623bb7..c276ff4 100644 --- a/src/vm/interp/vm_rv64i.cpp +++ b/src/vm/interp/vm_rv64i.cpp @@ -287,6 +287,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto& instr = this->core.reg.instruction; // we fetch at max 4 byte, alignment is 2 auto *const data = reinterpret_cast(&instr); + this->core.enable_disass(this->disass_enabled); while(!this->core.should_stop() && !(is_icount_limit_enabled(cond) && icount >= count_limit) && @@ -308,7 +309,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co inst_id = instr_descr[inst_index].op; // pre execution stuff - this->core.reg.last_branch = 0; + this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); try{ switch(inst_id){ @@ -2159,7 +2160,6 @@ std::unique_ptr create(arch::rv64i *core, unsigned short por } // namespace iss #include -#include #include #include diff --git a/src/vm/interp/vm_rv64imac.cpp b/src/vm/interp/vm_rv64imac.cpp new file mode 100644 index 0000000..2d68518 --- /dev/null +++ b/src/vm/interp/vm_rv64imac.cpp @@ -0,0 +1,4359 @@ +/******************************************************************************* + * Copyright (C) 2024 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +// clang-format off +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include + + +#ifndef FMT_HEADER_ONLY +#define FMT_HEADER_ONLY +#endif +#include + +#include +#include + +namespace iss { +namespace interp { +namespace rv64imac { + +using namespace iss::arch; +using namespace iss::debugger; +using namespace std::placeholders; + +struct memory_access_exception : public std::exception{ + memory_access_exception(){} +}; + +template class vm_impl : public iss::interp::vm_base { +public: + using traits = arch::traits; + using super = typename iss::interp::vm_base; + using virt_addr_t = typename super::virt_addr_t; + using phys_addr_t = typename super::phys_addr_t; + using code_word_t = typename super::code_word_t; + using addr_t = typename super::addr_t; + using reg_t = typename traits::reg_t; + using mem_type_e = typename traits::mem_type_e; + using opcode_e = typename traits::opcode_e; + + + vm_impl(); + + vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0); + + void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } + + target_adapter_if *accquire_target_adapter(server_if *srv) override { + debugger_if::dbg_enabled = true; + if (super::tgt_adapter == nullptr) + super::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); + return super::tgt_adapter; + } + +protected: + using this_class = vm_impl; + using compile_ret_t = virt_addr_t; + using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr); + + inline const char *name(size_t index){return traits::reg_aliases.at(index);} + + + virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override; + + // some compile time constants + + inline void raise(uint16_t trap_id, uint16_t cause){ + auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; + this->core.reg.trap_state = trap_val; + } + + inline void leave(unsigned lvl){ + this->core.leave_trap(lvl); + } + + inline void wait(unsigned type){ + this->core.wait_until(type); + } + + inline void set_tval(uint64_t new_tval){ + tval = new_tval; + } + uint64_t fetch_count{0}; + uint64_t tval{0}; + + using yield_t = boost::coroutines2::coroutine::push_type; + using coro_t = boost::coroutines2::coroutine::pull_type; + std::vector spawn_blocks; + + template::type> + inline S sext(U from) { + auto mask = (1ULL<::opcode_e op; + }; + + const std::array instr_descr = {{ + /* entries are: size, valid value, valid mask, function ptr */ + {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, arch::traits::opcode_e::LUI}, + {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, arch::traits::opcode_e::AUIPC}, + {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, arch::traits::opcode_e::JAL}, + {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, arch::traits::opcode_e::JALR}, + {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BEQ}, + {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BNE}, + {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BLT}, + {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BGE}, + {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BLTU}, + {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BGEU}, + {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LB}, + {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LH}, + {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LW}, + {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LBU}, + {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LHU}, + {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SB}, + {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SH}, + {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SW}, + {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ADDI}, + {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SLTI}, + {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SLTIU}, + {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::XORI}, + {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ORI}, + {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ANDI}, + {32, 0b00000000000000000001000000010011, 0b11111100000000000111000001111111, arch::traits::opcode_e::SLLI}, + {32, 0b00000000000000000101000000010011, 0b11111100000000000111000001111111, arch::traits::opcode_e::SRLI}, + {32, 0b01000000000000000101000000010011, 0b11111100000000000111000001111111, arch::traits::opcode_e::SRAI}, + {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::ADD}, + {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SUB}, + {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLL}, + {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLT}, + {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLTU}, + {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::XOR}, + {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRL}, + {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRA}, + {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::OR}, + {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::AND}, + {32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, arch::traits::opcode_e::FENCE}, + {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::ECALL}, + {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::EBREAK}, + {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::MRET}, + {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::WFI}, + {32, 0b00000000000000000110000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LWU}, + {32, 0b00000000000000000011000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LD}, + {32, 0b00000000000000000011000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SD}, + {32, 0b00000000000000000000000000011011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ADDIW}, + {32, 0b00000000000000000001000000011011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLLIW}, + {32, 0b00000000000000000101000000011011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRLIW}, + {32, 0b01000000000000000101000000011011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRAIW}, + {32, 0b00000000000000000000000000111011, 0b11111110000000000111000001111111, arch::traits::opcode_e::ADDW}, + {32, 0b01000000000000000000000000111011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SUBW}, + {32, 0b00000000000000000001000000111011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLLW}, + {32, 0b00000000000000000101000000111011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRLW}, + {32, 0b01000000000000000101000000111011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRAW}, + {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRW}, + {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRS}, + {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRC}, + {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRWI}, + {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRSI}, + {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRCI}, + {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, arch::traits::opcode_e::FENCE_I}, + {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::MUL}, + {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::MULH}, + {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::MULHSU}, + {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::MULHU}, + {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::DIV}, + {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::DIVU}, + {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::REM}, + {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::REMU}, + {32, 0b00000010000000000000000000111011, 0b11111110000000000111000001111111, arch::traits::opcode_e::MULW}, + {32, 0b00000010000000000100000000111011, 0b11111110000000000111000001111111, arch::traits::opcode_e::DIVW}, + {32, 0b00000010000000000101000000111011, 0b11111110000000000111000001111111, arch::traits::opcode_e::DIVUW}, + {32, 0b00000010000000000110000000111011, 0b11111110000000000111000001111111, arch::traits::opcode_e::REMW}, + {32, 0b00000010000000000111000000111011, 0b11111110000000000111000001111111, arch::traits::opcode_e::REMUW}, + {32, 0b00010000000000000010000000101111, 0b11111001111100000111000001111111, arch::traits::opcode_e::LRW}, + {32, 0b00011000000000000010000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::SCW}, + {32, 0b00001000000000000010000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOSWAPW}, + {32, 0b00000000000000000010000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOADDW}, + {32, 0b00100000000000000010000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOXORW}, + {32, 0b01100000000000000010000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOANDW}, + {32, 0b01000000000000000010000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOORW}, + {32, 0b10000000000000000010000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOMINW}, + {32, 0b10100000000000000010000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOMAXW}, + {32, 0b11000000000000000010000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOMINUW}, + {32, 0b11100000000000000010000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOMAXUW}, + {32, 0b00010000000000000011000000101111, 0b11111001111100000111000001111111, arch::traits::opcode_e::LRD}, + {32, 0b00011000000000000011000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::SCD}, + {32, 0b00001000000000000011000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOSWAPD}, + {32, 0b00000000000000000011000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOADDD}, + {32, 0b00100000000000000011000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOXORD}, + {32, 0b01100000000000000011000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOANDD}, + {32, 0b01000000000000000011000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOORD}, + {32, 0b10000000000000000011000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOMIND}, + {32, 0b10100000000000000011000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOMAXD}, + {32, 0b11000000000000000011000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOMINUD}, + {32, 0b11100000000000000011000000101111, 0b11111000000000000111000001111111, arch::traits::opcode_e::AMOMAXUD}, + {16, 0b0000000000000000, 0b1110000000000011, arch::traits::opcode_e::C__ADDI4SPN}, + {16, 0b0100000000000000, 0b1110000000000011, arch::traits::opcode_e::C__LW}, + {16, 0b0110000000000000, 0b1110000000000011, arch::traits::opcode_e::C__LD}, + {16, 0b1100000000000000, 0b1110000000000011, arch::traits::opcode_e::C__SW}, + {16, 0b1110000000000000, 0b1110000000000011, arch::traits::opcode_e::C__SD}, + {16, 0b0000000000000001, 0b1110000000000011, arch::traits::opcode_e::C__ADDI}, + {16, 0b0000000000000001, 0b1110111110000011, arch::traits::opcode_e::C__NOP}, + {16, 0b0010000000000001, 0b1110000000000011, arch::traits::opcode_e::C__ADDIW}, + {16, 0b0100000000000001, 0b1110000000000011, arch::traits::opcode_e::C__LI}, + {16, 0b0110000000000001, 0b1110000000000011, arch::traits::opcode_e::C__LUI}, + {16, 0b0110000100000001, 0b1110111110000011, arch::traits::opcode_e::C__ADDI16SP}, + {16, 0b0110000000000001, 0b1111000001111111, arch::traits::opcode_e::__reserved_clui}, + {16, 0b1000000000000001, 0b1110110000000011, arch::traits::opcode_e::C__SRLI}, + {16, 0b1000010000000001, 0b1110110000000011, arch::traits::opcode_e::C__SRAI}, + {16, 0b1000100000000001, 0b1110110000000011, arch::traits::opcode_e::C__ANDI}, + {16, 0b1000110000000001, 0b1111110001100011, arch::traits::opcode_e::C__SUB}, + {16, 0b1000110000100001, 0b1111110001100011, arch::traits::opcode_e::C__XOR}, + {16, 0b1000110001000001, 0b1111110001100011, arch::traits::opcode_e::C__OR}, + {16, 0b1000110001100001, 0b1111110001100011, arch::traits::opcode_e::C__AND}, + {16, 0b1001110000000001, 0b1111110001100011, arch::traits::opcode_e::C__SUBW}, + {16, 0b1001110000100001, 0b1111110001100011, arch::traits::opcode_e::C__ADDW}, + {16, 0b1010000000000001, 0b1110000000000011, arch::traits::opcode_e::C__J}, + {16, 0b1100000000000001, 0b1110000000000011, arch::traits::opcode_e::C__BEQZ}, + {16, 0b1110000000000001, 0b1110000000000011, arch::traits::opcode_e::C__BNEZ}, + {16, 0b0000000000000010, 0b1110000000000011, arch::traits::opcode_e::C__SLLI}, + {16, 0b0100000000000010, 0b1110000000000011, arch::traits::opcode_e::C__LWSP}, + {16, 0b0110000000000010, 0b1110000000000011, arch::traits::opcode_e::C__LDSP}, + {16, 0b1000000000000010, 0b1111000000000011, arch::traits::opcode_e::C__MV}, + {16, 0b1000000000000010, 0b1111000001111111, arch::traits::opcode_e::C__JR}, + {16, 0b1000000000000010, 0b1111111111111111, arch::traits::opcode_e::__reserved_cmv}, + {16, 0b1001000000000010, 0b1111000000000011, arch::traits::opcode_e::C__ADD}, + {16, 0b1001000000000010, 0b1111000001111111, arch::traits::opcode_e::C__JALR}, + {16, 0b1001000000000010, 0b1111111111111111, arch::traits::opcode_e::C__EBREAK}, + {16, 0b1100000000000010, 0b1110000000000011, arch::traits::opcode_e::C__SWSP}, + {16, 0b1110000000000010, 0b1110000000000011, arch::traits::opcode_e::C__SDSP}, + {16, 0b0000000000000000, 0b1111111111111111, arch::traits::opcode_e::DII}, + }}; + + //needs to be declared after instr_descr + decoder instr_decoder; + + iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ + if (this->core.read({iss::address_type::LOGICAL, pc.access, arch::traits::IMEM, pc.val}, 4, data) != iss::Ok) + return iss::Err; + return iss::Ok; + } +}; + +template void debug_fn(CODE_WORD insn) { + volatile CODE_WORD x = insn; + insn = 2 * x; +} +// according to +// https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation +#ifdef __GCC__ +constexpr size_t bit_count(uint32_t u) { return __builtin_popcount(u); } +#elif __cplusplus < 201402L +constexpr size_t uCount(uint32_t u) { return u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); } +constexpr size_t bit_count(uint32_t u) { return ((uCount(u) + (uCount(u) >> 3)) & 030707070707) % 63; } +#else +constexpr size_t bit_count(uint32_t u) { + size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); + return ((uCount + (uCount >> 3)) & 030707070707) % 63; +} +#endif + +template +vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) +: vm_base(core, core_id, cluster_id) +, instr_decoder([this]() { + std::vector g_instr_descr; + g_instr_descr.reserve(instr_descr.size()); + for (uint32_t i = 0; i < instr_descr.size(); ++i) { + generic_instruction_descriptor new_instr_descr {instr_descr[i].value, instr_descr[i].mask, i}; + g_instr_descr.push_back(new_instr_descr); + } + return std::move(g_instr_descr); + }()) {} + +inline bool is_icount_limit_enabled(finish_cond_e cond){ + return (cond & finish_cond_e::ICOUNT_LIMIT) == finish_cond_e::ICOUNT_LIMIT; +} + +inline bool is_fcount_limit_enabled(finish_cond_e cond){ + return (cond & finish_cond_e::FCOUNT_LIMIT) == finish_cond_e::FCOUNT_LIMIT; +} + +inline bool is_jump_to_self_enabled(finish_cond_e cond){ + return (cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF; +} + +template +typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t count_limit){ + auto pc=start; + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + auto& trap_state = this->core.reg.trap_state; + auto& icount = this->core.reg.icount; + auto& cycle = this->core.reg.cycle; + auto& instret = this->core.reg.instret; + auto& instr = this->core.reg.instruction; + // we fetch at max 4 byte, alignment is 2 + auto *const data = reinterpret_cast(&instr); + this->core.enable_disass(this->disass_enabled); + + while(!this->core.should_stop() && + !(is_icount_limit_enabled(cond) && icount >= count_limit) && + !(is_fcount_limit_enabled(cond) && fetch_count >= count_limit)){ + if(this->debugging_enabled()) + this->tgt_adapter->check_continue(*PC); + pc.val=*PC; + if(fetch_ins(pc, data)!=iss::Ok){ + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, std::numeric_limits::max()); + process_spawn_blocks(); + if(this->sync_exec && POST_SYNC) this->do_sync(PRE_SYNC, std::numeric_limits::max()); + *PC = super::core.enter_trap(trap_state, pc.val, instr); + } else { + if (is_jump_to_self_enabled(cond) && + (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' + uint32_t inst_index = instr_decoder.decode_instr(instr); + opcode_e inst_id = arch::traits::opcode_e::MAX_OPCODE;; + if(inst_index core.reg.last_branch = 0; + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); + try{ + switch(inst_id){ + case arch::traits::opcode_e::LUI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = (uint64_t)((int32_t)imm); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AUIPC: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = (uint64_t)((uint128_t)(*PC) + (int128_t)((int32_t)imm)); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::JAL: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t new_pc = (uint64_t)((uint128_t)(*PC) + (int128_t)((int32_t)sext<21>(imm))); + if(new_pc % (uint64_t)(traits::INSTR_ALIGNMENT)) { + set_tval(new_pc); + raise(0, 0); + } + else { + if(rd != 0) { + *(X+rd) = (uint64_t)((uint128_t)(*PC) + (uint128_t)(4)); + } + *NEXT_PC = new_pc; + this->core.reg.last_branch = 1; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::JALR: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t addr_mask = (uint64_t)- 2; + uint64_t new_pc = (uint64_t)(((uint128_t)(*(X+rs1)) + (int128_t)((int16_t)sext<12>(imm))) & (uint128_t)(addr_mask)); + if(new_pc % (uint64_t)(traits::INSTR_ALIGNMENT)) { + set_tval(new_pc); + raise(0, 0); + } + else { + if(rd != 0) { + *(X+rd) = (uint64_t)((uint128_t)(*PC) + (uint128_t)(4)); + } + *NEXT_PC = new_pc; + this->core.reg.last_branch = 1; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::BEQ: { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(*(X+rs1) == *(X+rs2)) { + uint64_t new_pc = (uint64_t)((uint128_t)(*PC) + (int128_t)((int16_t)sext<13>(imm))); + if(new_pc % (uint64_t)(traits::INSTR_ALIGNMENT)) { + set_tval(new_pc); + raise(0, 0); + } + else { + *NEXT_PC = new_pc; + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::BNE: { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(*(X+rs1) != *(X+rs2)) { + uint64_t new_pc = (uint64_t)((uint128_t)(*PC) + (int128_t)((int16_t)sext<13>(imm))); + if(new_pc % (uint64_t)(traits::INSTR_ALIGNMENT)) { + set_tval(new_pc); + raise(0, 0); + } + else { + *NEXT_PC = new_pc; + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::BLT: { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if((int64_t)*(X+rs1) < (int64_t)*(X+rs2)) { + uint64_t new_pc = (uint64_t)((uint128_t)(*PC) + (int128_t)((int16_t)sext<13>(imm))); + if(new_pc % (uint64_t)(traits::INSTR_ALIGNMENT)) { + set_tval(new_pc); + raise(0, 0); + } + else { + *NEXT_PC = new_pc; + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::BGE: { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if((int64_t)*(X+rs1) >= (int64_t)*(X+rs2)) { + uint64_t new_pc = (uint64_t)((uint128_t)(*PC) + (int128_t)((int16_t)sext<13>(imm))); + if(new_pc % (uint64_t)(traits::INSTR_ALIGNMENT)) { + set_tval(new_pc); + raise(0, 0); + } + else { + *NEXT_PC = new_pc; + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::BLTU: { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(*(X+rs1) < *(X+rs2)) { + uint64_t new_pc = (uint64_t)((uint128_t)(*PC) + (int128_t)((int16_t)sext<13>(imm))); + if(new_pc % (uint64_t)(traits::INSTR_ALIGNMENT)) { + set_tval(new_pc); + raise(0, 0); + } + else { + *NEXT_PC = new_pc; + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::BGEU: { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(*(X+rs1) >= *(X+rs2)) { + uint64_t new_pc = (uint64_t)((uint128_t)(*PC) + (int128_t)((int16_t)sext<13>(imm))); + if(new_pc % (uint64_t)(traits::INSTR_ALIGNMENT)) { + set_tval(new_pc); + raise(0, 0); + } + else { + *NEXT_PC = new_pc; + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::LB: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t load_address = (uint64_t)((uint128_t)(*(X+rs1)) + (int128_t)((int16_t)sext<12>(imm))); + int8_t res_1 = super::template read_mem(traits::MEM, load_address); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + int8_t res = (int8_t)res_1; + if(rd != 0) { + *(X+rd) = (uint64_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::LH: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t load_address = (uint64_t)((uint128_t)(*(X+rs1)) + (int128_t)((int16_t)sext<12>(imm))); + int16_t res_2 = super::template read_mem(traits::MEM, load_address); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + int16_t res = (int16_t)res_2; + if(rd != 0) { + *(X+rd) = (uint64_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::LW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t load_address = (uint64_t)((uint128_t)(*(X+rs1)) + (int128_t)((int16_t)sext<12>(imm))); + int32_t res_3 = super::template read_mem(traits::MEM, load_address); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + int32_t res = (int32_t)res_3; + if(rd != 0) { + *(X+rd) = (uint64_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::LBU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t load_address = (uint64_t)((uint128_t)(*(X+rs1)) + (int128_t)((int16_t)sext<12>(imm))); + uint8_t res_4 = super::template read_mem(traits::MEM, load_address); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint8_t res = res_4; + if(rd != 0) { + *(X+rd) = (uint64_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::LHU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t load_address = (uint64_t)((uint128_t)(*(X+rs1)) + (int128_t)((int16_t)sext<12>(imm))); + uint16_t res_5 = super::template read_mem(traits::MEM, load_address); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint16_t res = res_5; + if(rd != 0) { + *(X+rd) = (uint64_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SB: { + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t store_address = (uint64_t)((uint128_t)(*(X+rs1)) + (int128_t)((int16_t)sext<12>(imm))); + super::template write_mem(traits::MEM, store_address, (uint8_t)*(X+rs2)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SH: { + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t store_address = (uint64_t)((uint128_t)(*(X+rs1)) + (int128_t)((int16_t)sext<12>(imm))); + super::template write_mem(traits::MEM, store_address, (uint16_t)*(X+rs2)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SW: { + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t store_address = (uint64_t)((uint128_t)(*(X+rs1)) + (int128_t)((int16_t)sext<12>(imm))); + super::template write_mem(traits::MEM, store_address, (uint32_t)*(X+rs2)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::ADDI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = (uint64_t)((uint128_t)(*(X+rs1)) + (int128_t)((int16_t)sext<12>(imm))); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SLTI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = ((int64_t)*(X+rs1) < (int16_t)sext<12>(imm))? 1 : 0; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SLTIU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = (*(X+rs1) < (uint64_t)((int16_t)sext<12>(imm)))? 1 : 0; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::XORI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) ^ (uint64_t)((int16_t)sext<12>(imm)); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::ORI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) | (uint64_t)((int16_t)sext<12>(imm)); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::ANDI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) & (uint64_t)((int16_t)sext<12>(imm)); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SLLI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,6>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) << shamt; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SRLI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,6>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) >> shamt; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SRAI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,6>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = (uint64_t)(((int64_t)*(X+rs1)) >> shamt); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::ADD: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = (uint64_t)((uint128_t)(*(X+rs1)) + (uint128_t)(*(X+rs2))); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SUB: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = (uint64_t)((uint128_t)(*(X+rs1)) - (uint128_t)(*(X+rs2))); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SLL: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) << (*(X+rs2) & ((uint64_t)(traits::XLEN) - (uint64_t)(1))); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SLT: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = (int64_t)*(X+rs1) < (int64_t)*(X+rs2)? 1 : 0; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SLTU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) < *(X+rs2)? 1 : 0; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::XOR: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) ^ *(X+rs2); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SRL: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) >> (*(X+rs2) & ((uint64_t)(traits::XLEN) - (uint64_t)(1))); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SRA: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = (uint64_t)((int64_t)*(X+rs1) >> (*(X+rs2) & ((uint64_t)(traits::XLEN) - (uint64_t)(1)))); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::OR: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) | *(X+rs2); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AND: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) & *(X+rs2); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::FENCE: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t succ = ((bit_sub<20,4>(instr))); + uint8_t pred = ((bit_sub<24,4>(instr))); + uint8_t fm = ((bit_sub<28,4>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {pred}, {succ} ({fm} , {rs1}, {rd})", fmt::arg("mnemonic", "fence"), + fmt::arg("pred", pred), fmt::arg("succ", succ), fmt::arg("fm", fm), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + super::template write_mem(traits::FENCE, traits::fence, (uint8_t)pred << 4 | succ); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::ECALL: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + //No disass specified, using instruction name + std::string mnemonic = "ecall"; + this->core.disass_output(pc.val, mnemonic); + } + // used registers + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + raise(0, 11); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::EBREAK: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + //No disass specified, using instruction name + std::string mnemonic = "ebreak"; + this->core.disass_output(pc.val, mnemonic); + } + // used registers + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + raise(0, 3); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::MRET: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + //No disass specified, using instruction name + std::string mnemonic = "mret"; + this->core.disass_output(pc.val, mnemonic); + } + // used registers + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + leave(3); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::WFI: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + //No disass specified, using instruction name + std::string mnemonic = "wfi"; + this->core.disass_output(pc.val, mnemonic); + } + // used registers + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + wait(1); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::LWU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lwu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = (uint64_t)((uint128_t)(*(X+rs1)) + (int128_t)((int16_t)sext<12>(imm))); + uint32_t res_6 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t res = (uint32_t)res_6; + if(rd != 0) { + *(X+rd) = (uint64_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::LD: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "ld"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = (uint64_t)((uint128_t)(*(X+rs1)) + (int128_t)((int16_t)sext<12>(imm))); + int64_t res_7 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + int64_t res = (int64_t)res_7; + if(rd != 0) { + *(X+rd) = (uint64_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SD: { + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sd"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = (uint64_t)((uint128_t)(*(X+rs1)) + (int128_t)((int16_t)sext<12>(imm))); + super::template write_mem(traits::MEM, offs, (uint64_t)*(X+rs2)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::ADDIW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addiw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + int32_t res = (int32_t)((uint128_t)(*(X+rs1)) + (int128_t)((int16_t)sext<12>(imm))); + *(X+rd) = (uint64_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SLLIW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slliw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + uint32_t sh_val = ((uint32_t)*(X+rs1)) << shamt; + *(X+rd) = (uint64_t)(int32_t)sh_val; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SRLIW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srliw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + uint32_t sh_val = ((uint32_t)*(X+rs1)) >> shamt; + *(X+rd) = (uint64_t)(int32_t)sh_val; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SRAIW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "sraiw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + int32_t sh_val = ((int32_t)*(X+rs1)) >> shamt; + *(X+rd) = (uint64_t)sh_val; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::ADDW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + //No disass specified, using instruction name + std::string mnemonic = "addw"; + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + int32_t res = (int32_t)((int64_t)((int32_t)*(X+rs1)) + (int64_t)((int32_t)*(X+rs2))); + *(X+rd) = (uint64_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SUBW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + //No disass specified, using instruction name + std::string mnemonic = "subw"; + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + int32_t res = (int32_t)((int64_t)((int32_t)*(X+rs1)) - (int64_t)((int32_t)*(X+rs2))); + *(X+rd) = (uint64_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SLLW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sllw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + uint32_t count = (uint32_t)*(X+rs2) & (uint32_t)(31); + uint32_t sh_val = ((uint32_t)*(X+rs1)) << count; + *(X+rd) = (uint64_t)(int32_t)sh_val; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SRLW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srlw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + uint32_t count = (uint32_t)*(X+rs2) & (uint32_t)(31); + uint32_t sh_val = ((uint32_t)*(X+rs1)) >> count; + *(X+rd) = (uint64_t)(int32_t)sh_val; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SRAW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sraw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + uint32_t count = (uint32_t)*(X+rs2) & (uint32_t)(31); + int32_t sh_val = ((int32_t)*(X+rs1)) >> count; + *(X+rd) = (uint64_t)sh_val; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSRRW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t xrs1 = *(X+rs1); + if(rd != 0) { + uint64_t res_8 = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint64_t xrd = res_8; + super::template write_mem(traits::CSR, csr, xrs1); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + *(X+rd) = xrd; + } + else { + super::template write_mem(traits::CSR, csr, xrs1); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSRRS: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t res_9 = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint64_t xrd = res_9; + uint64_t xrs1 = *(X+rs1); + if(rs1 != 0) { + super::template write_mem(traits::CSR, csr, xrd | xrs1); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + if(rd != 0) { + *(X+rd) = xrd; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSRRC: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t res_10 = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint64_t xrd = res_10; + uint64_t xrs1 = *(X+rs1); + if(rs1 != 0) { + super::template write_mem(traits::CSR, csr, xrd & ~xrs1); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + if(rd != 0) { + *(X+rd) = xrd; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSRRWI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t res_11 = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint64_t xrd = res_11; + super::template write_mem(traits::CSR, csr, (uint64_t)zimm); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + if(rd != 0) { + *(X+rd) = xrd; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSRRSI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t res_12 = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint64_t xrd = res_12; + if(zimm != 0) { + super::template write_mem(traits::CSR, csr, xrd | (uint64_t)zimm); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + if(rd != 0) { + *(X+rd) = xrd; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSRRCI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t res_13 = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint64_t xrd = res_13; + if(zimm != 0) { + super::template write_mem(traits::CSR, csr, xrd & ~((uint64_t)zimm)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + if(rd != 0) { + *(X+rd) = xrd; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::FENCE_I: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence_i"), + fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + super::template write_mem(traits::FENCE, traits::fencei, imm); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::MUL: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + int128_t res = (int128_t)((int64_t)*(X+rs1)) * (int128_t)((int64_t)*(X+rs2)); + if(rd != 0) { + *(X+rd) = (uint64_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::MULH: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + int128_t res = (int128_t)((int64_t)*(X+rs1)) * (int128_t)((int64_t)*(X+rs2)); + if(rd != 0) { + *(X+rd) = (uint64_t)(res >> traits::XLEN); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::MULHSU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + int128_t res = (int128_t)((int64_t)*(X+rs1)) * (uint128_t)(*(X+rs2)); + if(rd != 0) { + *(X+rd) = (uint64_t)(res >> traits::XLEN); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::MULHU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint128_t res = (uint128_t)(*(X+rs1)) * (uint128_t)(*(X+rs2)); + if(rd != 0) { + *(X+rd) = (uint64_t)(res >> traits::XLEN); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::DIV: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + int64_t dividend = (int64_t)*(X+rs1); + int64_t divisor = (int64_t)*(X+rs2); + if(rd != 0) { + if(divisor != 0) { + uint64_t MMIN = ((uint64_t)1) << ((uint64_t)(traits::XLEN) - (uint64_t)(1)); + if(*(X+rs1) == MMIN && divisor == - 1) { + *(X+rd) = MMIN; + } + else { + *(X+rd) = (uint64_t)(dividend / divisor); + } + } + else { + *(X+rd) = (uint64_t)- 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::DIVU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(*(X+rs2) != 0) { + if(rd != 0) { + *(X+rd) = *(X+rs1) / *(X+rs2); + } + } + else { + if(rd != 0) { + *(X+rd) = (uint64_t)- 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::REM: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(*(X+rs2) != 0) { + uint64_t MMIN = (uint64_t)1 << ((uint64_t)(traits::XLEN) - (uint64_t)(1)); + if(*(X+rs1) == MMIN && (int64_t)*(X+rs2) == - 1) { + if(rd != 0) { + *(X+rd) = 0; + } + } + else { + if(rd != 0) { + *(X+rd) = ((uint64_t)((int64_t)*(X+rs1) % (int64_t)*(X+rs2))); + } + } + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1); + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::REMU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(*(X+rs2) != 0) { + if(rd != 0) { + *(X+rd) = *(X+rs1) % *(X+rs2); + } + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1); + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::MULW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + int32_t resw = (int32_t)((int64_t)((int32_t)*(X+rs1)) * (int64_t)((int32_t)*(X+rs2))); + *(X+rd) = ((uint64_t)(int64_t)resw); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::DIVW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + int32_t dividend = (int32_t)*(X+rs1); + int32_t divisor = (int32_t)*(X+rs2); + if(divisor != 0) { + int32_t MMIN = (int32_t)1 << 31; + if(dividend == MMIN && divisor == - 1) { + if(rd != 0) { + *(X+rd) = (uint64_t)- 1 << 31; + } + } + else { + if(rd != 0) { + *(X+rd) = (uint64_t)(dividend / divisor); + } + } + } + else { + if(rd != 0) { + *(X+rd) = (uint64_t)- 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::DIVUW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divuw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint32_t divisor = (uint32_t)*(X+rs2); + if(divisor != 0) { + int32_t res = (int32_t)((uint32_t)*(X+rs1) / divisor); + if(rd != 0) { + *(X+rd) = ((uint64_t)(int64_t)res); + } + } + else { + if(rd != 0) { + *(X+rd) = (uint64_t)- 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::REMW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(((int32_t)*(X+rs2)) != 0) { + int32_t SMIN = (int32_t)1 << 31; + if((int32_t)*(X+rs1) == SMIN && (int32_t)*(X+rs2) == - 1) { + if(rd != 0) { + *(X+rd) = 0; + } + } + else { + if(rd != 0) { + *(X+rd) = (uint64_t)((int32_t)*(X+rs1) % (int32_t)*(X+rs2)); + } + } + } + else { + if(rd != 0) { + *(X+rd) = (uint64_t)((int32_t)*(X+rs1)); + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::REMUW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remuw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint32_t divisor = (uint32_t)*(X+rs2); + if(divisor != 0) { + int32_t res = (int32_t)((uint32_t)*(X+rs1) % divisor); + if(rd != 0) { + *(X+rd) = ((uint64_t)(int64_t)res); + } + } + else { + int32_t res = (int32_t)*(X+rs1); + if(rd != 0) { + *(X+rd) = ((uint64_t)(int64_t)res); + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::LRW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {aq}, {rl}", fmt::arg("mnemonic", "lrw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("aq", name(aq)), fmt::arg("rl", name(rl))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + uint64_t offs = *(X+rs1); + int32_t res_14 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + *(X+rd) = (uint64_t)((int32_t)res_14); + super::template write_mem(traits::RES, offs, (uint8_t)- 1); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SCW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}, {aq}, {rl}", fmt::arg("mnemonic", "scw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", name(aq)), fmt::arg("rl", name(rl))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + uint8_t res_15 = super::template read_mem(traits::RES, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t res1 = res_15; + if(res1 != 0) { + super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + if(rd != 0) { + *(X+rd) = res1? 0 : 1; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOSWAPW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoswapw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + uint64_t res = *(X+rs2); + if(rd != 0) { + int32_t res_16 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + *(X+rd) = (uint64_t)((int32_t)res_16); + } + super::template write_mem(traits::MEM, offs, (uint32_t)res); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOADDW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoaddw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + int32_t res_17 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + int32_t res1 = (int32_t)res_17; + int64_t res2 = (int64_t)(res1) + (int64_t)((int32_t)*(X+rs2)); + if(rd != 0) { + *(X+rd) = (uint64_t)res1; + } + super::template write_mem(traits::MEM, offs, (uint32_t)res2); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOXORW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoxorw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + uint32_t res_18 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t res1 = res_18; + uint32_t res2 = res1 ^ (uint32_t)*(X+rs2); + if(rd != 0) { + *(X+rd) = ((uint64_t)(int64_t)(int32_t)res1); + } + super::template write_mem(traits::MEM, offs, res2); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOANDW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoandw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + uint32_t res_19 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t res1 = res_19; + uint32_t res2 = res1 & (uint32_t)*(X+rs2); + if(rd != 0) { + *(X+rd) = ((uint64_t)(int64_t)(int32_t)res1); + } + super::template write_mem(traits::MEM, offs, res2); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOORW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoorw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + uint32_t res_20 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t res1 = res_20; + uint32_t res2 = res1 | (uint32_t)*(X+rs2); + if(rd != 0) { + *(X+rd) = ((uint64_t)(int64_t)(int32_t)res1); + } + super::template write_mem(traits::MEM, offs, res2); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOMINW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amominw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + int32_t res_21 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + int32_t res1 = (int32_t)res_21; + uint32_t res2 = res1 > (int32_t)*(X+rs2)? (uint32_t)*(X+rs2) : ((uint32_t)res1); + if(rd != 0) { + *(X+rd) = (uint64_t)res1; + } + super::template write_mem(traits::MEM, offs, res2); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOMAXW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amomaxw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + int32_t res_22 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + int32_t res1 = (int32_t)res_22; + uint32_t res2 = res1 < (int32_t)*(X+rs2)? (uint32_t)*(X+rs2) : ((uint32_t)res1); + if(rd != 0) { + *(X+rd) = (uint64_t)res1; + } + super::template write_mem(traits::MEM, offs, res2); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOMINUW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amominuw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + uint32_t res_23 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t res1 = res_23; + uint32_t res2 = res1 > (uint32_t)*(X+rs2)? (uint32_t)*(X+rs2) : res1; + if(rd != 0) { + *(X+rd) = ((uint64_t)(int64_t)(int32_t)res1); + } + super::template write_mem(traits::MEM, offs, res2); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOMAXUW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amomaxuw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + uint32_t res_24 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t res1 = res_24; + uint32_t res2 = res1 < (int32_t)*(X+rs2)? (uint32_t)*(X+rs2) : res1; + if(rd != 0) { + *(X+rd) = ((uint64_t)(int64_t)(int32_t)res1); + } + super::template write_mem(traits::MEM, offs, res2); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::LRD: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}", fmt::arg("mnemonic", "lrd"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + uint64_t offs = *(X+rs1); + int64_t res_25 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + *(X+rd) = (uint64_t)((int64_t)res_25); + super::template write_mem(traits::RES, offs, (uint8_t)- 1); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SCD: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "scd"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + uint8_t res_26 = super::template read_mem(traits::RES, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint64_t res = res_26; + if(res != 0) { + super::template write_mem(traits::MEM, offs, *(X+rs2)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + if(rd != 0) { + *(X+rd) = res? 0 : 1; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOSWAPD: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoswapd"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + uint64_t res = *(X+rs2); + if(rd != 0) { + int64_t res_27 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + *(X+rd) = (uint64_t)((int64_t)res_27); + } + super::template write_mem(traits::MEM, offs, (uint64_t)res); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOADDD: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoaddd"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + uint64_t res_28 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint64_t res1 = res_28; + uint64_t res2 = (uint64_t)((uint128_t)(res1) + (uint128_t)(*(X+rs2))); + if(rd != 0) { + *(X+rd) = (uint64_t)res1; + } + super::template write_mem(traits::MEM, offs, res2); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOXORD: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoxord"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + uint64_t res_29 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint64_t res1 = res_29; + uint64_t res2 = res1 ^ *(X+rs2); + if(rd != 0) { + *(X+rd) = ((uint64_t)(int64_t)res1); + } + super::template write_mem(traits::MEM, offs, res2); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOANDD: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoandd"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + uint64_t res_30 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint64_t res1 = res_30; + uint64_t res2 = res1 & *(X+rs2); + if(rd != 0) { + *(X+rd) = (uint64_t)res1; + } + super::template write_mem(traits::MEM, offs, res2); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOORD: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amoord"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + uint64_t res_31 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint64_t res1 = res_31; + uint64_t res2 = res1 | *(X+rs2); + if(rd != 0) { + *(X+rd) = (uint64_t)res1; + } + super::template write_mem(traits::MEM, offs, res2); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOMIND: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amomind"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + int64_t res_32 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + int64_t res1 = (int64_t)res_32; + uint64_t res2 = res1 > (int64_t)*(X+rs2)? (uint64_t)*(X+rs2) : ((uint64_t)res1); + if(rd != 0) { + *(X+rd) = (uint64_t)res1; + } + super::template write_mem(traits::MEM, offs, res2); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOMAXD: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amomaxd"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + int64_t res_33 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + int64_t res1 = (int64_t)res_33; + uint64_t res2 = res1 < (int64_t)*(X+rs2)? (uint64_t)*(X+rs2) : ((uint64_t)res1); + if(rd != 0) { + *(X+rd) = (uint64_t)res1; + } + super::template write_mem(traits::MEM, offs, res2); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOMINUD: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amominud"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + uint64_t res_34 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint64_t res1 = res_34; + uint64_t res2 = res1 > *(X+rs2)? *(X+rs2) : res1; + if(rd != 0) { + *(X+rd) = (uint64_t)res1; + } + super::template write_mem(traits::MEM, offs, res2); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AMOMAXUD: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu = {aq},rel = {rl})", fmt::arg("mnemonic", "amomaxud"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = *(X+rs1); + uint64_t res_35 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint64_t res1 = res_35; + uint64_t res2 = res1 < *(X+rs2)? (uint64_t)*(X+rs2) : res1; + if(rd != 0) { + *(X+rd) = (uint64_t)res1; + } + super::template write_mem(traits::MEM, offs, res2); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__ADDI4SPN: { + uint8_t rd = ((bit_sub<2,3>(instr))); + uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), + fmt::arg("rd", name(8+rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(imm) { + *(X+rd + 8) = (uint64_t)((uint128_t)(*(X+2)) + (uint128_t)(imm)); + } + else { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__LW: { + uint8_t rd = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), + fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + uint64_t offs = (uint64_t)((uint128_t)(*(X+rs1 + 8)) + (uint128_t)(uimm)); + int32_t res_36 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + *(X+rd + 8) = (uint64_t)(int32_t)res_36; + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__LD: { + uint8_t rd = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {uimm},({rs1})", fmt::arg("mnemonic", "c.ld"), + fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + uint64_t offs = (uint64_t)((uint128_t)(*(X+rs1 + 8)) + (uint128_t)(uimm)); + uint64_t res_37 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + *(X+rd + 8) = (uint64_t)res_37; + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__SW: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), + fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + uint64_t offs = (uint64_t)((uint128_t)(*(X+rs1 + 8)) + (uint128_t)(uimm)); + super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2 + 8)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__SD: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm},({rs1})", fmt::arg("mnemonic", "c.sd"), + fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + uint64_t offs = (uint64_t)((uint128_t)(*(X+rs1 + 8)) + (uint128_t)(uimm)); + super::template write_mem(traits::MEM, offs, *(X+rs2 + 8)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__ADDI: { + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), + fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rs1 != 0) { + *(X+rs1) = (uint64_t)((uint128_t)(*(X+rs1)) + (int128_t)((int8_t)sext<6>(imm))); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__NOP: { + uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + //No disass specified, using instruction name + std::string mnemonic = "c.nop"; + this->core.disass_output(pc.val, mnemonic); + } + // used registers + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__ADDIW: { + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addiw"), + fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rs1 >= traits::RFS || rs1 == 0) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rs1 != 0) { + int32_t res = (int32_t)((int64_t)((int32_t)*(X+rs1)) + (int64_t)((int8_t)sext<6>(imm))); + *(X+rs1) = (uint64_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__LI: { + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = (uint64_t)((int8_t)sext<6>(imm)); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__LUI: { + uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(imm == 0 || rd >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + if(rd != 0) { + *(X+rd) = (uint64_t)((int32_t)sext<18>(imm)); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__ADDI16SP: { + uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), + fmt::arg("nzimm", nzimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(nzimm) { + *(X+2) = (uint64_t)((uint128_t)(*(X+2)) + (int128_t)((int16_t)sext<10>(nzimm))); + } + else { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::__reserved_clui: { + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + //No disass specified, using instruction name + std::string mnemonic = ".reserved_clui"; + this->core.disass_output(pc.val, mnemonic); + } + // used registers + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__SRLI: { + uint8_t nzuimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "c.srli"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("nzuimm", nzuimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *(X+rs1 + 8) = *(X+rs1 + 8) >> nzuimm; + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__SRAI: { + uint8_t shamt = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *(X+rs1 + 8) = (uint64_t)(((int64_t)*(X+rs1 + 8)) >> shamt); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__ANDI: { + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *(X+rs1 + 8) = (uint64_t)(*(X+rs1 + 8) & (int64_t)((int8_t)sext<6>(imm))); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__SUB: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *(X+rd + 8) = (uint64_t)((uint128_t)(*(X+rd + 8)) - (uint128_t)(*(X+rs2 + 8))); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__XOR: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *(X+rd + 8) = *(X+rd + 8) ^ *(X+rs2 + 8); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__OR: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *(X+rd + 8) = *(X+rd + 8) | *(X+rs2 + 8); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__AND: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *(X+rd + 8) = *(X+rd + 8) & *(X+rs2 + 8); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__SUBW: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.subw"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + int32_t res = (int32_t)((int64_t)((int32_t)*(X+rd + 8)) - (int64_t)((int32_t)*(X+rs2 + 8))); + *(X+rd + 8) = (uint64_t)res; + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__ADDW: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.addw"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + int32_t res = (int32_t)((int64_t)((int32_t)*(X+rd + 8)) + (int64_t)((int32_t)*(X+rs2 + 8))); + *(X+rd + 8) = (uint64_t)res; + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__J: { + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), + fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *NEXT_PC = (uint64_t)((uint128_t)(*PC) + (int128_t)((int16_t)sext<12>(imm))); + this->core.reg.last_branch = 1; + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__BEQZ: { + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(*(X+rs1 + 8) == 0) { + *NEXT_PC = (uint64_t)((uint128_t)(*PC) + (int128_t)((int16_t)sext<9>(imm))); + this->core.reg.last_branch = 1; + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__BNEZ: { + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(*(X+rs1 + 8) != 0) { + *NEXT_PC = (uint64_t)((uint128_t)(*PC) + (int128_t)((int16_t)sext<9>(imm))); + this->core.reg.last_branch = 1; + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__SLLI: { + uint8_t shamt = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.slli"), + fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rs1 != 0) { + *(X+rs1) = *(X+rs1) << shamt; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__LWSP: { + uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.lwsp"), + fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rd >= traits::RFS || rd == 0) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = (uint64_t)((uint128_t)(*(X+2)) + (uint128_t)(uimm)); + int32_t res_38 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + *(X+rd) = (uint64_t)(int32_t)res_38; + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__LDSP: { + uint16_t uimm = ((bit_sub<2,3>(instr) << 6) | (bit_sub<5,2>(instr) << 3) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {uimm}(sp)", fmt::arg("mnemonic", "c.ldsp"), + fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rd >= traits::RFS || rd == 0) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = (uint64_t)((uint128_t)(*(X+2)) + (uint128_t)(uimm)); + uint64_t res_39 = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint64_t res = (uint64_t)res_39; + *(X+rd) = res; + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__MV: { + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs2); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__JR: { + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), + fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rs1 && rs1 < traits::RFS) { + uint64_t addr_mask = (uint64_t)- 2; + *NEXT_PC = *(X+(uint32_t)(rs1) % traits::RFS) & addr_mask; + this->core.reg.last_branch = 1; + } + else { + raise(0, 2); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::__reserved_cmv: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + //No disass specified, using instruction name + std::string mnemonic = ".reserved_cmv"; + this->core.disass_output(pc.val, mnemonic); + } + // used registers + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + raise(0, 2); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__ADD: { + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + if(rd != 0) { + *(X+rd) = (uint64_t)((uint128_t)(*(X+rd)) + (uint128_t)(*(X+rs2))); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__JALR: { + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), + fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rs1 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t addr_mask = (uint64_t)- 2; + uint64_t new_pc = *(X+rs1); + *(X+1) = (uint64_t)((uint128_t)(*PC) + (uint128_t)(2)); + *NEXT_PC = new_pc & addr_mask; + this->core.reg.last_branch = 1; + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__EBREAK: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + //No disass specified, using instruction name + std::string mnemonic = "c.ebreak"; + this->core.disass_output(pc.val, mnemonic); + } + // used registers + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + raise(0, 3); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__SWSP: { + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), + fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = (uint64_t)((uint128_t)(*(X+2)) + (uint128_t)(uimm)); + super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::C__SDSP: { + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint16_t uimm = ((bit_sub<7,3>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm}(sp)", fmt::arg("mnemonic", "c.sdsp"), + fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rs2 >= traits::RFS) { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + else { + uint64_t offs = (uint64_t)((uint128_t)(*(X+2)) + (uint128_t)(uimm)); + super::template write_mem(traits::MEM, offs, (uint64_t)*(X+rs2)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::DII: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + //No disass specified, using instruction name + std::string mnemonic = "dii"; + this->core.disass_output(pc.val, mnemonic); + } + // used registers + // calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + break; + }// @suppress("No break at end of case") + default: { + if(this->core.can_handle_unknown_instruction()) { + auto res = this->core.handle_unknown_instruction(pc.val, sizeof(instr), reinterpret_cast(&instr)); + if(std::get<0>(res)) { + *NEXT_PC = std::get<1>(res); + break; + } + } + if(this->disass_enabled){ + std::string mnemonic = "Illegal Instruction"; + this->core.disass_output(pc.val, mnemonic); + } + *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); + raise(0, traits::RV_CAUSE_ILLEGAL_INSTRUCTION); + } + } + }catch(memory_access_exception& e){} + // post execution stuff + process_spawn_blocks(); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); + // if(!this->core.reg.trap_state) // update trap state if there is a pending interrupt + // this->core.reg.trap_state = this->core.reg.pending_trap; + // trap check + if(trap_state!=0){ + //In case of Instruction address misaligned (cause = 0 and trapid = 0) need the targeted addr (in tval) + auto mcause = (trap_state>>16) & 0xff; + super::core.enter_trap(trap_state, pc.val, mcause ? instr:tval); + } else { + icount++; + instret++; + } + *PC = *NEXT_PC; + this->core.reg.trap_state = this->core.reg.pending_trap; + } + fetch_count++; + cycle++; + } + return pc; +} + +} // namespace rv64imac + +template <> +std::unique_ptr create(arch::rv64imac *core, unsigned short port, bool dump) { + auto ret = new rv64imac::vm_impl(*core, dump); + if (port != 0) debugger::server::run_server(ret, port); + return std::unique_ptr(ret); +} +} // namespace interp +} // namespace iss + +#include +#include +#include + + +namespace iss { +namespace { + +volatile std::array dummy = { + core_factory::instance().register_creator("rv64imac_m:interp", [](unsigned port, void* init_data) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto vm = new interp::rv64imac::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + if(init_data){ + auto* cb = reinterpret_cast::reg_t>*>(init_data); + cpu->set_semihosting_callback(*cb); + } + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("rv64imac_mu:interp", [](unsigned port, void* init_data) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto vm = new interp::rv64imac::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + if(init_data){ + auto* cb = reinterpret_cast::reg_t>*>(init_data); + cpu->set_semihosting_callback(*cb); + } + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} +// clang-format on