From 34c7144143d174193188f8d81a3c7e0dde4fee5d Mon Sep 17 00:00:00 2001 From: mathewduong Date: Mon, 23 Mar 2026 13:55:19 +1030 Subject: [PATCH 1/2] fix signed loads lh and lb on both 32-bit and 64-bit RISC-V --- architecture/RISCV/RV32IMFD.yml | 80 ++++++++++++++++----------------- architecture/RISCV/RV64IMFD.yml | 79 ++++++++++++++++---------------- 2 files changed, 79 insertions(+), 80 deletions(-) diff --git a/architecture/RISCV/RV32IMFD.yml b/architecture/RISCV/RV32IMFD.yml index a9434c2f..99bd16d0 100644 --- a/architecture/RISCV/RV32IMFD.yml +++ b/architecture/RISCV/RV32IMFD.yml @@ -1614,7 +1614,9 @@ instructions: - field: funct3 value: "000" definition: | - registers[rd] = CAPI.MEM.read(imm + registers[rs1], 1, rd); + let addr = CAPI.FP.int2uint(registers[rs1], 32) + imm; + registers[rd] = CAPI.MEM.read(addr, 1, rd); + registers[rd] = CAPI.FP.int2uint(CAPI.FP.uint2int(registers[rd], 8)); help: Loads a 8-bit value from memory and sign-extends this to XLEN bits before storing it in register rd. - name: lbu @@ -1640,7 +1642,9 @@ instructions: - field: funct3 value: "001" definition: | - registers[rd] = CAPI.MEM.read(imm + registers[rs1], 2, rd); + let addr = CAPI.FP.int2uint(registers[rs1], 32) + imm; + registers[rd] = CAPI.MEM.read(addr, 2, rd); + registers[rd] = CAPI.FP.int2uint(CAPI.FP.uint2int(registers[rd], 16)); help: Loads a 16-bit value from memory and sign-extends this to XLEN bits before storing it in register rd. - name: lhu @@ -1781,7 +1785,7 @@ instructions: registers[rd] = registers.pc + 4n; registers.pc = registers.pc + imm; CAPI.STACK.beginFrame(); - } + } help: Jump to address and place return address in rd. # R-type instructions @@ -3645,7 +3649,6 @@ instructions: properties: - privileged - Zicsr: # _____ _ # |__ /(_) ___ ___ _ __ @@ -3671,42 +3674,40 @@ instructions: # TODO: Implement rest of CSR instructions - Zifencei: - # _____ _ __ _ - # |__ /(_) / _| ___ _ __ ___ ___ (_) - # / / | || |_ / _ \| '_ \ / __|/ _ \| | - # / /_ | || _|| __/| | | || (__| __/| | - # /____||_||_| \___||_| |_| \___|\___||_| - # RV32/RV64 Zifencei Standard Exension - - - name: fence.i - template: Custom - type: Syscall - fields: - - field: opcode - value: "0001111" - - field: funct3 - type: cop - startbit: 14 - stopbit: 12 - value: "001" - - field: zeros - type: cop - startbit: 31 - stopbit: 15 - value: "00000000000000000" - - field: zeros2 - type: cop - startbit: 11 - stopbit: 7 - value: "00000" - definition: | - console.log('Not implemented: fence.i'); - CAPI.VALIDATION.raise('fence.i not implemented'); - help: Provides explicit synchronization between writes to instruction - memory and instruction fetches on the same hart. - + # _____ _ __ _ + # |__ /(_) / _| ___ _ __ ___ ___ (_) + # / / | || |_ / _ \| '_ \ / __|/ _ \| | + # / /_ | || _|| __/| | | || (__| __/| | + # /____||_||_| \___||_| |_| \___|\___||_| + # RV32/RV64 Zifencei Standard Exension + + - name: fence.i + template: Custom + type: Syscall + fields: + - field: opcode + value: "0001111" + - field: funct3 + type: cop + startbit: 14 + stopbit: 12 + value: "001" + - field: zeros + type: cop + startbit: 31 + stopbit: 15 + value: "00000000000000000" + - field: zeros2 + type: cop + startbit: 11 + stopbit: 7 + value: "00000" + definition: | + console.log('Not implemented: fence.i'); + CAPI.VALIDATION.raise('fence.i not implemented'); + help: Provides explicit synchronization between writes to instruction + memory and instruction fetches on the same hart. pseudoinstructions: # Make sure the definitions correspond with those in the RISC-V ASM manual (TODO: Check these!) @@ -4205,4 +4206,3 @@ timer: registers.mie |= 2n ** 7n; // MTIE = 1 disable: | registers.mie &= ~(2n ** 7n); // MTIE = 0 - diff --git a/architecture/RISCV/RV64IMFD.yml b/architecture/RISCV/RV64IMFD.yml index 6492c5a1..d0a0213b 100644 --- a/architecture/RISCV/RV64IMFD.yml +++ b/architecture/RISCV/RV64IMFD.yml @@ -1632,7 +1632,9 @@ instructions: - field: funct3 value: "000" definition: | - registers[rd] = CAPI.MEM.read(imm + registers[rs1], 1, rd); + let addr = CAPI.FP.int2uint(registers[rs1], 32) + imm; + registers[rd] = CAPI.MEM.read(addr, 1, rd); + registers[rd] = CAPI.FP.int2uint(CAPI.FP.uint2int(registers[rd], 8)); help: Loads a 8-bit value from memory and sign-extends this to XLEN bits before storing it in register rd. - name: lbu @@ -1658,7 +1660,9 @@ instructions: - field: funct3 value: "001" definition: | - registers[rd] = CAPI.MEM.read(imm + registers[rs1], 2, rd); + let addr = CAPI.FP.int2uint(registers[rs1], 32) + imm; + registers[rd] = CAPI.MEM.read(addr, 2, rd); + registers[rd] = CAPI.FP.int2uint(CAPI.FP.uint2int(registers[rd], 16)); help: Loads a 16-bit value from memory and sign-extends this to XLEN bits before storing it in register rd. - name: lhu @@ -3793,7 +3797,6 @@ instructions: CAPI.MEM.addHint(registers[rs1] + imm, "float64", 64); help: Store a double-precision value from the floating-point registers to memory. - Priv: # ____ _ # | _ \ _ __ (_)__ __ @@ -3829,7 +3832,6 @@ instructions: properties: - privileged - Zicsr: # _____ _ # |__ /(_) ___ ___ _ __ @@ -3855,42 +3857,40 @@ instructions: # TODO: Implement rest of CSR instructions - Zifencei: - # _____ _ __ _ - # |__ /(_) / _| ___ _ __ ___ ___ (_) - # / / | || |_ / _ \| '_ \ / __|/ _ \| | - # / /_ | || _|| __/| | | || (__| __/| | - # /____||_||_| \___||_| |_| \___|\___||_| - # RV32/RV64 Zifencei Standard Exension - - - name: fence.i - template: Custom - type: Syscall - fields: - - field: opcode - value: "0001111" - - field: funct3 - type: cop - startbit: 14 - stopbit: 12 - value: "001" - - field: zeros - type: cop - startbit: 31 - stopbit: 15 - value: "00000000000000000" - - field: zeros2 - type: cop - startbit: 11 - stopbit: 7 - value: "00000" - definition: | - console.log('Not implemented: fence.i'); - CAPI.VALIDATION.raise('fence.i not implemented'); - help: Provides explicit synchronization between writes to instruction - memory and instruction fetches on the same hart. - + # _____ _ __ _ + # |__ /(_) / _| ___ _ __ ___ ___ (_) + # / / | || |_ / _ \| '_ \ / __|/ _ \| | + # / /_ | || _|| __/| | | || (__| __/| | + # /____||_||_| \___||_| |_| \___|\___||_| + # RV32/RV64 Zifencei Standard Exension + + - name: fence.i + template: Custom + type: Syscall + fields: + - field: opcode + value: "0001111" + - field: funct3 + type: cop + startbit: 14 + stopbit: 12 + value: "001" + - field: zeros + type: cop + startbit: 31 + stopbit: 15 + value: "00000000000000000" + - field: zeros2 + type: cop + startbit: 11 + stopbit: 7 + value: "00000" + definition: | + console.log('Not implemented: fence.i'); + CAPI.VALIDATION.raise('fence.i not implemented'); + help: Provides explicit synchronization between writes to instruction + memory and instruction fetches on the same hart. pseudoinstructions: # Make sure the definitions correspond with those in the RISC-V ASM manual (TODO: Check these!) @@ -4379,4 +4379,3 @@ timer: registers.mie |= 2n ** 7n; // MTIE = 1 disable: | registers.mie &= ~(2n ** 7n); // MTIE = 0 - From 85fa23cea53a1de49e569edc010889444b54e57a Mon Sep 17 00:00:00 2001 From: mathew <61689578+mathewduong@users.noreply.github.com> Date: Tue, 24 Mar 2026 09:44:16 +1030 Subject: [PATCH 2/2] remove unnecessary calls to int2uint and use local variables Co-authored-by: ALVAROPING1 <43814863+ALVAROPING1@users.noreply.github.com> --- architecture/RISCV/RV32IMFD.yml | 12 ++++++------ architecture/RISCV/RV64IMFD.yml | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/architecture/RISCV/RV32IMFD.yml b/architecture/RISCV/RV32IMFD.yml index 99bd16d0..e5b3efb4 100644 --- a/architecture/RISCV/RV32IMFD.yml +++ b/architecture/RISCV/RV32IMFD.yml @@ -1614,9 +1614,9 @@ instructions: - field: funct3 value: "000" definition: | - let addr = CAPI.FP.int2uint(registers[rs1], 32) + imm; - registers[rd] = CAPI.MEM.read(addr, 1, rd); - registers[rd] = CAPI.FP.int2uint(CAPI.FP.uint2int(registers[rd], 8)); + let addr = registers[rs1] + imm; + const result = CAPI.MEM.read(addr, 1, rd); + registers[rd] = CAPI.FP.int2uint(CAPI.FP.uint2int(result, 8)); help: Loads a 8-bit value from memory and sign-extends this to XLEN bits before storing it in register rd. - name: lbu @@ -1642,9 +1642,9 @@ instructions: - field: funct3 value: "001" definition: | - let addr = CAPI.FP.int2uint(registers[rs1], 32) + imm; - registers[rd] = CAPI.MEM.read(addr, 2, rd); - registers[rd] = CAPI.FP.int2uint(CAPI.FP.uint2int(registers[rd], 16)); + let addr = registers[rs1] + imm; + const result = CAPI.MEM.read(addr, 2, rd); + registers[rd] = CAPI.FP.int2uint(CAPI.FP.uint2int(result, 16)); help: Loads a 16-bit value from memory and sign-extends this to XLEN bits before storing it in register rd. - name: lhu diff --git a/architecture/RISCV/RV64IMFD.yml b/architecture/RISCV/RV64IMFD.yml index d0a0213b..8805994c 100644 --- a/architecture/RISCV/RV64IMFD.yml +++ b/architecture/RISCV/RV64IMFD.yml @@ -1632,9 +1632,9 @@ instructions: - field: funct3 value: "000" definition: | - let addr = CAPI.FP.int2uint(registers[rs1], 32) + imm; - registers[rd] = CAPI.MEM.read(addr, 1, rd); - registers[rd] = CAPI.FP.int2uint(CAPI.FP.uint2int(registers[rd], 8)); + let addr = registers[rs1] + imm; + const result = CAPI.MEM.read(addr, 1, rd); + registers[rd] = CAPI.FP.int2uint(CAPI.FP.uint2int(result, 8)); help: Loads a 8-bit value from memory and sign-extends this to XLEN bits before storing it in register rd. - name: lbu @@ -1660,9 +1660,9 @@ instructions: - field: funct3 value: "001" definition: | - let addr = CAPI.FP.int2uint(registers[rs1], 32) + imm; - registers[rd] = CAPI.MEM.read(addr, 2, rd); - registers[rd] = CAPI.FP.int2uint(CAPI.FP.uint2int(registers[rd], 16)); + let addr = registers[rs1] + imm; + const result = CAPI.MEM.read(addr, 2, rd); + registers[rd] = CAPI.FP.int2uint(CAPI.FP.uint2int(result, 16)); help: Loads a 16-bit value from memory and sign-extends this to XLEN bits before storing it in register rd. - name: lhu