- * :technologist: [Diego Camarmas Alonso](https://github.com/)
- * :technologist: [Félix García Carballeira](https://www.researchgate.net/profile/Felix_Garcia-Carballeira)
+ * :technologist: [Diego Camarmas Alonso](https://github.com/dcamarmas)
+ * :technologist: [Félix García Carballeira](https://github.com/fgcarbal)
* :technologist: [Alejandro Calderón Mateos](https://github.com/acaldero)
### Contributors
@@ -305,10 +305,10 @@
* :technologist: [Lucas Elvira Martín](https://github.com/luelvira) (RISC-V and several improvements)
* :technologist: [José Antonio Verde Jiménez](https://github.com/joseaverde) (Real hardware integration)
* :technologist: [Álvaro Guerrero Espinosa](https://github.com/ALVAROPING1) (New compiler)
- * :technologist: [Elisa Utrilla Arroyo](https://github.com/EUtrilla2002) (Real hardware integration)
+ * :technologist: [Elisa Utrilla Arroyo](https://github.com/EUtrilla2002) (Real hardware integration, Arduino integration)
* :technologist: [Luis Daniel Casais Mezquida](https://github.com/rajayonin) (Website migration, interrupts, timers, and memory-mapped devices)
* :technologist: [Jorge Ramos Santana](https://github.com/mjorgers) (core/tests rewrite, new web UI, new CLI, RV64 & Z80 architectures)
- * :technologist: [Juan Carlos Cano Resa](https://github.com/Jotaceee) (SAIL integration)
+ * :technologist: [Juan Carlos Cano Resa](https://github.com/Jotaceee) (Sail integration)
@@ -317,6 +317,24 @@
+:atom: 6.1.x
+
+ - [x] Sail integration:
+ * RISC-V 32 and RISC-V 64 full specification supported
+ * Cache module integrated
+ - [x] Arduino support:
+ * ESP32 Microcontroller
+ * Arduino GPIO simulation UI
+ - [x] New activity bar
+
+
+
+ - Source Code: https://github.com/creatorsim/creator-v6.1
+ - Try Version: https://creatorsim.github.io/creator-v6.1
+
+
+
+:atom: 6.0.x
- [x] **BREAKING CHANGES**:
diff --git a/architecture.json b/architecture.json
deleted file mode 100644
index 91826afab..000000000
--- a/architecture.json
+++ /dev/null
@@ -1,307 +0,0 @@
-{
- "version": "2.0.0",
- "config": {
- "name": "Simple8Bit",
- "word_size": 8,
- "byte_size": 8,
- "description": "A simple custom 8-bit architecture",
- "endianness": "little_endian",
- "memory_alignment": true,
- "passing_convention": true,
- "sensitive_register_name": false,
- "main_function": "main",
- "comment_prefix": ";",
- "start_address": 0,
- "pc_offset": 0
- },
- "templates": [
- {
- "name": "standard",
- "nwords": 1,
- "clk_cycles": 1,
- "fields": [
- {
- "name": "opcode",
- "type": "co",
- "startbit": 7,
- "stopbit": 0,
- "order": 0
- }
- ]
- }
- ],
- "components": [
- {
- "name": "Control registers",
- "type": "ctrl_registers",
- "double_precision": false,
- "elements": [
- {
- "name": [
- "PC"
- ],
- "nbits": 8,
- "encoding": 0,
- "value": 0,
- "default_value": 0,
- "properties": [
- "read",
- "write",
- "program_counter"
- ]
- }
- ]
- },
- {
- "name": "Integer registers",
- "type": "int_registers",
- "double_precision": false,
- "elements": [
- {
- "name": [
- "A"
- ],
- "encoding": 0,
- "nbits": 8,
- "value": 0,
- "default_value": 0,
- "properties": [
- "read",
- "write"
- ]
- },
- {
- "name": [
- "B"
- ],
- "encoding": 1,
- "nbits": 8,
- "value": 0,
- "default_value": 0,
- "properties": [
- "read",
- "write"
- ]
- },
- {
- "name": [
- "SP"
- ],
- "encoding": 2,
- "nbits": 8,
- "value": 0,
- "default_value": 0,
- "properties": [
- "read",
- "write",
- "stack_pointer"
- ]
- }
- ]
- }
- ],
- "memory_layout": {
- "text": {
- "start": 0,
- "end": 1023
- },
- "data": {
- "start": 1024,
- "end": 32767
- },
- "stack": {
- "start": 32768,
- "end": 65535
- }
- },
- "instructions": [
- {
- "name": "nop",
- "nwords": 1,
- "clk_cycles": 1,
- "fields": [
- {
- "name": "opcode",
- "type": "co",
- "startbit": 7,
- "stopbit": 0,
- "order": 0,
- "value": "00000000"
- }
- ],
- "template": "standard",
- "definition": "",
- "type": "Other",
- "help": "",
- "signature_definition": "F0",
- "signature_pretty": "nop",
- "co": "00000000"
- },
- {
- "name": "add",
- "nwords": 3,
- "clk_cycles": 5,
- "fields": [
- {
- "name": "opcode",
- "type": "co",
- "startbit": 7,
- "stopbit": 0,
- "order": 0,
- "value": "00100000"
- },
- {
- "type": "INT-Reg",
- "word": 1,
- "startbit": 7,
- "stopbit": 0,
- "order": 1,
- "suffix": ",",
- "name": "reg1"
- },
- {
- "type": "INT-Reg",
- "word": 2,
- "order": 2,
- "startbit": 7,
- "stopbit": 0,
- "name": "reg2"
- }
- ],
- "template": "standard",
- "definition": "registers[reg1] = (registers[reg1] + registers[reg2]) & 0xFFn;\n",
- "type": "Other",
- "help": "",
- "signature_definition": "F0 F1, F2",
- "signature_pretty": "add reg1, reg2",
- "co": "00100000"
- },
- {
- "name": "load",
- "nwords": 3,
- "clk_cycles": 4,
- "fields": [
- {
- "name": "opcode",
- "type": "co",
- "startbit": 7,
- "stopbit": 0,
- "order": 0,
- "value": "10000001"
- },
- {
- "type": "INT-Reg",
- "word": 1,
- "startbit": 7,
- "stopbit": 0,
- "order": 1,
- "suffix": ",",
- "name": "reg"
- },
- {
- "type": "imm-signed",
- "word": 2,
- "startbit": 7,
- "stopbit": 0,
- "order": 2,
- "name": "number"
- }
- ],
- "template": "standard",
- "definition": "registers[reg] = number\n",
- "type": "Other",
- "help": "",
- "signature_definition": "F0 F1, F2",
- "signature_pretty": "load reg, number",
- "co": "10000001"
- }
- ],
- "directives": [
- {
- "name": ".data",
- "action": "data_segment",
- "size": null
- },
- {
- "name": ".text",
- "action": "code_segment",
- "size": null
- },
- {
- "name": ".bss",
- "action": "global_symbol",
- "size": null
- },
- {
- "name": ".zero",
- "action": "space",
- "size": 1
- },
- {
- "name": ".space",
- "action": "space",
- "size": 1
- },
- {
- "name": ".align",
- "action": "align",
- "size": null
- },
- {
- "name": ".balign",
- "action": "balign",
- "size": null
- },
- {
- "name": ".globl",
- "action": "global_symbol",
- "size": null
- },
- {
- "name": ".string",
- "action": "ascii_null_end",
- "size": null
- },
- {
- "name": ".asciz",
- "action": "ascii_null_end",
- "size": null
- },
- {
- "name": ".ascii",
- "action": "ascii_not_null_end",
- "size": null
- },
- {
- "name": ".byte",
- "action": "byte",
- "size": 1
- },
- {
- "name": ".half",
- "action": "half_word",
- "size": 2
- },
- {
- "name": ".word",
- "action": "word",
- "size": 4
- },
- {
- "name": ".dword",
- "action": "double_word",
- "size": 8
- },
- {
- "name": ".float",
- "action": "float",
- "size": 4
- },
- {
- "name": ".double",
- "action": "double",
- "size": 8
- }
- ],
- "pseudoinstructions": []
-}
\ No newline at end of file
diff --git a/architecture/MIPS32.yml b/architecture/MIPS32.yml
index d61d0743b..7c01aae82 100644
--- a/architecture/MIPS32.yml
+++ b/architecture/MIPS32.yml
@@ -132,7 +132,7 @@ components:
double_precision: false
elements:
- name:
- - r0
+ - "0"
- zero
nbits: 32
value: 0
@@ -141,7 +141,7 @@ components:
properties:
- read
- name:
- - r1
+ - "1"
- at
nbits: 32
value: 0
@@ -151,7 +151,7 @@ components:
- read
- write
- name:
- - r2
+ - "2"
- v0
nbits: 32
value: 0
@@ -161,7 +161,7 @@ components:
- read
- write
- name:
- - r3
+ - "3"
- v1
nbits: 32
value: 0
@@ -171,7 +171,7 @@ components:
- read
- write
- name:
- - r4
+ - "4"
- a0
nbits: 32
value: 0
@@ -181,7 +181,7 @@ components:
- read
- write
- name:
- - r5
+ - "5"
- a1
nbits: 32
value: 0
@@ -191,7 +191,7 @@ components:
- read
- write
- name:
- - r6
+ - "6"
- a2
nbits: 32
value: 0
@@ -201,7 +201,7 @@ components:
- read
- write
- name:
- - r7
+ - "7"
- a3
nbits: 32
value: 0
@@ -211,7 +211,7 @@ components:
- read
- write
- name:
- - r8
+ - "8"
- t0
nbits: 32
value: 0
@@ -221,7 +221,7 @@ components:
- read
- write
- name:
- - r9
+ - "9"
- t1
nbits: 32
value: 0
@@ -231,7 +231,7 @@ components:
- read
- write
- name:
- - r10
+ - "10"
- t2
nbits: 32
value: 0
@@ -241,7 +241,7 @@ components:
- read
- write
- name:
- - r11
+ - "11"
- t3
nbits: 32
value: 0
@@ -251,7 +251,7 @@ components:
- read
- write
- name:
- - r12
+ - "12"
- t4
nbits: 32
value: 0
@@ -261,7 +261,7 @@ components:
- read
- write
- name:
- - r13
+ - "13"
- t5
nbits: 32
value: 0
@@ -271,7 +271,7 @@ components:
- read
- write
- name:
- - r14
+ - "14"
- t6
nbits: 32
value: 0
@@ -281,7 +281,7 @@ components:
- read
- write
- name:
- - r15
+ - "15"
- t7
nbits: 32
value: 0
@@ -291,7 +291,7 @@ components:
- read
- write
- name:
- - r16
+ - "16"
- s0
nbits: 32
value: 0
@@ -302,7 +302,7 @@ components:
- write
- saved
- name:
- - r17
+ - "17"
- s1
nbits: 32
value: 0
@@ -313,7 +313,7 @@ components:
- write
- saved
- name:
- - r18
+ - "18"
- s2
nbits: 32
value: 0
@@ -324,7 +324,7 @@ components:
- write
- saved
- name:
- - r19
+ - "19"
- s3
nbits: 32
value: 0
@@ -335,7 +335,7 @@ components:
- write
- saved
- name:
- - r20
+ - "20"
- s4
nbits: 32
value: 0
@@ -346,7 +346,7 @@ components:
- write
- saved
- name:
- - r21
+ - "21"
- s5
nbits: 32
value: 0
@@ -357,7 +357,7 @@ components:
- write
- saved
- name:
- - r22
+ - "22"
- s6
nbits: 32
value: 0
@@ -368,7 +368,7 @@ components:
- write
- saved
- name:
- - r23
+ - "23"
- s7
nbits: 32
value: 0
@@ -379,7 +379,7 @@ components:
- write
- saved
- name:
- - r24
+ - "24"
- t8
nbits: 32
value: 0
@@ -389,7 +389,7 @@ components:
- read
- write
- name:
- - r25
+ - "25"
- t9
nbits: 32
value: 0
@@ -399,7 +399,7 @@ components:
- read
- write
- name:
- - r26
+ - "26"
- k0
nbits: 32
value: 0
@@ -409,7 +409,7 @@ components:
- read
- write
- name:
- - r27
+ - "27"
- k1
nbits: 32
value: 0
@@ -419,7 +419,7 @@ components:
- read
- write
- name:
- - r28
+ - "28"
- gp
nbits: 32
value: 0
@@ -430,18 +430,18 @@ components:
- write
- global_pointer
- name:
- - r29
+ - "29"
- sp
nbits: 32
- value: 268435452
- default_value: 268435452
+ value: 0x0FFFFFFC
+ default_value: 0x0FFFFFFC
encoding: 29
properties:
- read
- write
- stack_pointer
- name:
- - r30
+ - "30"
- fp
nbits: 32
value: 0
@@ -452,11 +452,11 @@ components:
- write
- frame_pointer
- name:
- - r31
+ - "31"
- ra
nbits: 32
- value: 4294967295
- default_value: 4294967295
+ value: -1
+ default_value: -1
encoding: 31
properties:
- read
@@ -467,6 +467,7 @@ components:
elements:
- name:
- f0
+ - FP0
nbits: 32
value: 0
default_value: 0
@@ -485,6 +486,7 @@ components:
- write
- name:
- f2
+ - FP2
nbits: 32
value: 0
default_value: 0
@@ -503,6 +505,7 @@ components:
- write
- name:
- f4
+ - FP4
nbits: 32
value: 0
default_value: 0
@@ -521,6 +524,7 @@ components:
- write
- name:
- f6
+ - FP6
nbits: 32
value: 0
default_value: 0
@@ -539,6 +543,7 @@ components:
- write
- name:
- f8
+ - FP8
nbits: 32
value: 0
default_value: 0
@@ -557,6 +562,7 @@ components:
- write
- name:
- f10
+ - FP10
nbits: 32
value: 0
default_value: 0
@@ -575,6 +581,7 @@ components:
- write
- name:
- f12
+ - FP12
nbits: 32
value: 0
default_value: 0
@@ -593,6 +600,7 @@ components:
- write
- name:
- f14
+ - FP14
nbits: 32
value: 0
default_value: 0
@@ -611,6 +619,7 @@ components:
- write
- name:
- f16
+ - FP16
nbits: 32
value: 0
default_value: 0
@@ -629,6 +638,7 @@ components:
- write
- name:
- f18
+ - FP18
nbits: 32
value: 0
default_value: 0
@@ -647,6 +657,7 @@ components:
- write
- name:
- f20
+ - FP20
nbits: 32
value: 0
default_value: 0
@@ -665,6 +676,7 @@ components:
- write
- name:
- f22
+ - FP22
nbits: 32
value: 0
default_value: 0
@@ -683,6 +695,7 @@ components:
- write
- name:
- f24
+ - FP24
nbits: 32
value: 0
default_value: 0
@@ -701,6 +714,7 @@ components:
- write
- name:
- f26
+ - FP26
nbits: 32
value: 0
default_value: 0
@@ -719,6 +733,7 @@ components:
- write
- name:
- f28
+ - FP28
nbits: 32
value: 0
default_value: 0
@@ -737,6 +752,7 @@ components:
- write
- name:
- f30
+ - FP30
nbits: 32
value: 0
default_value: 0
@@ -1019,13 +1035,36 @@ instructions:
fields:
- field: function
value: "000101"
+ - field: fmt
+ type: cop
+ value: "00000"
- field: ft
order: null
value: "00000"
preoperation: |
- let fsValue = CAPI.FS.uint2float32(registers[fs]);
+ let fsValue = CAPI.FP.uint2float32(registers[fs]);
postoperation: |
- fd = CAPI.FS.float322uint(result);
+ registers[fd] = CAPI.FP.float322uint(result);
+ definition: |
+ let result = Math.abs(fsValue);
+ - name: abs.d
+ type: Arithmetic floating point
+ template: FPU_R
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - field: function
+ value: "000101"
+ - field: fmt
+ type: cop
+ value: "00001"
+ - field: ft
+ order: null
+ value: "00000"
+ preoperation: |
+ let fsValue = CAPI.ARCH.readDouble(fs);
+ postoperation: |
+ CAPI.ARCH.writeDouble(result, fd)
definition: |
let result = Math.abs(fsValue);
@@ -1058,10 +1097,10 @@ instructions:
value: "00000"
type: cop
preoperation: |
- fsValue = CAPI.FS.uint2float32(registers[fs]);
- ftValue = CAPI.FS.uint2float32(registers[ft]);
+ fsValue = CAPI.FP.uint2float32(registers[fs]);
+ ftValue = CAPI.FP.uint2float32(registers[ft]);
postoperation: |
- registers[fd] = CAPI.FS.float322uint(result);
+ registers[fd] = CAPI.FP.float322uint(result);
definition: |
let result = fsValue + ftValue;
@@ -1151,7 +1190,7 @@ instructions:
- field: opcode
value: "001100"
definition: |
- registers[rt] = registers[rs] & (imm & 0xFFFF);
+ registers[rt] = registers[rs] & (imm & 0xFFFFn);
- name: bc
template: Custom
@@ -1169,6 +1208,7 @@ instructions:
order: 1
definition: |
// Not implemented
+ CAPI.VALIDATION.raise('bc not implemented');
- name: bc1eqz
template: FPU_I
@@ -1322,7 +1362,9 @@ instructions:
type: offset_bytes
definition: |
if (CAPI.FP.uint2int(registers[rs]) >= 0) {
- registers.PC = registers.PC - 4n + imm;
+ const pc = registers.PC
+ registers.ra = pc
+ registers.PC = pc - 4n + imm;
CAPI.STACK.beginFrame(registers[rs]);
}
@@ -1675,7 +1717,9 @@ instructions:
startbit: 5
stopbit: 0
value: "100001"
- definition: registers[fd] = registers[fs];
+ definition: |
+ let val = CAPI.FP.uint2float32(registers[fs]);
+ CAPI.ARCH.writeDouble(val, fd);
- name: cvt.d.w
template: Custom
type: Arithmetic floating point
@@ -1696,7 +1740,7 @@ instructions:
stopbit: 21
value: "00001"
- field: fs
- type: SFP-Reg
+ type: INT-Reg
startbit: 15
stopbit: 11
order: 2
@@ -1714,7 +1758,7 @@ instructions:
startbit: 5
stopbit: 0
value: "100001"
- definition: registers[fd] = registers[fs];
+ definition: CAPI.ARCH.writeDouble(Number(CAPI.FP.uint2int(registers[fs])), fd);
- name: cvt.s.d
template: Custom
type: Arithmetic floating point
@@ -1754,8 +1798,8 @@ instructions:
stopbit: 0
value: "100000"
definition: |
- let val = CAPI.FS.uint2float32(registers[fs]);
- CAPI.ARCH.writeDouble(val, fd);
+ let val = CAPI.ARCH.readDouble(fs);
+ registers[fd] = CAPI.FP.float322uint(val, fd);
- name: cvt.s.w
template: Custom
type: Arithmetic floating point
@@ -1776,7 +1820,7 @@ instructions:
stopbit: 21
value: "00010"
- field: fs
- type: SFP-Reg
+ type: INT-Reg
startbit: 15
stopbit: 11
order: 2
@@ -1794,7 +1838,7 @@ instructions:
startbit: 5
stopbit: 0
value: "100000"
- definition: registers[fd] = parseFloat(float2int_v2(registers[fs]));
+ definition: registers[fd] = CAPI.FP.float322uint(Number(CAPI.FP.uint2int(registers[fs])));
- name: cvt.w.d
template: Custom
type: Arithmetic floating point
@@ -1822,7 +1866,7 @@ instructions:
prefix: $
suffix: ","
- field: fd
- type: SFP-Reg
+ type: INT-Reg
startbit: 10
stopbit: 6
order: 1
@@ -1835,7 +1879,7 @@ instructions:
value: "100100"
definition: |
let val = CAPI.ARCH.readDouble(fs);
- CAPI.REG.write(BigInt(Math.trunc(val)), fd);
+ CAPI.REG.write(CAPI.FP.int2uint(BigInt(Math.trunc(val))), fd);
- name: cvt.w.s
template: Custom
type: Arithmetic floating point
@@ -1863,7 +1907,7 @@ instructions:
prefix: $
suffix: ","
- field: fd
- type: SFP-Reg
+ type: INT-Reg
startbit: 10
stopbit: 6
order: 1
@@ -1874,7 +1918,9 @@ instructions:
startbit: 5
stopbit: 0
value: "100100"
- definition: registers[fd] = parseInt(registers[fs]);
+ definition: |
+ let val = CAPI.FP.uint2float32(registers[fs]);
+ CAPI.REG.write(CAPI.FP.int2uint(BigInt(Math.trunc(val))), fd);
- name: div
template: Custom
type: Arithmetic integer
@@ -2077,10 +2123,10 @@ instructions:
stopbit: 0
value: "000011"
preoperation: |
- fsValue = CAPI.FS.uint2float32(fs);
- ftValue = CAPI.FS.uint2float32(ft);
+ fsValue = CAPI.FP.uint2float32(registers[fs]);
+ ftValue = CAPI.FP.uint2float32(registers[ft]);
postoperation: |
- fd = CAPI.FS.float322uint(result);
+ registers[fd] = CAPI.FP.float322uint(result);
definition: |-
let result;
if (ftValue != 0)
@@ -2132,7 +2178,7 @@ instructions:
value: "011011"
definition: |-
if (registers[rt] != 0)
- { registers[rd] = Math.floor(CAPI.FP.int2uint(registers[rs]) / CAPI.FP.int2uint(registers[rt])); }
+ { registers[rd] = CAPI.FP.int2uint(registers[rs]) / CAPI.FP.int2uint(registers[rt]); }
else { CAPI.VALIDATION.raise('Division by zero not allowed'); }
- name: divu
template: Custom
@@ -2168,9 +2214,9 @@ instructions:
value: "011011"
definition: |-
if (registers[rt] != 0)
- { registers.LO = Math.floor(CAPI.FP.int2uint(registers[rs]) / CAPI.FP.int2uint(registers[rt]));
- registers.HI = CAPI.FP.int2uint(registers[rs]) % CAPI.FP.int2uint(registers[rt]); }
- else { CAPI.VALIDATION.raise('Division by zero not allowed'); }
+ { registers.LO = CAPI.FP.int2uint(registers[rs]) / CAPI.FP.int2uint(registers[rt]);
+ registers.HI = CAPI.FP.int2uint(registers[rs]) % CAPI.FP.int2uint(registers[rt]); }
+ else { CAPI.VALIDATION.raise('Division by zero not allowed'); }
- name: j
template: Custom
type: Unconditional bifurcation
@@ -2279,8 +2325,10 @@ instructions:
stopbit: 0
value: "001000"
definition: |-
- registers.PC = registers[rs];
- CAPI.STACK.endFrame();
+ const pc = registers[rs]
+ registers.PC = pc;
+ if (BigInt.asIntN(32, pc) === -1n) CAPI.SYSCALL.exit();
+ else CAPI.STACK.endFrame();
- name: lb
template: Custom
type: Memory access
@@ -2316,7 +2364,8 @@ instructions:
suffix: )
order: 3
definition: |
- registers[reg1] = CAPI.MEM.read(registers[reg2]+val, 1, reg1);
+ const result = CAPI.MEM.read(registers[reg2]+val, 1, reg1, false);
+ registers[reg1] = CAPI.FP.int2uint(CAPI.FP.uint2int(result, 8));
- name: lbu
template: Custom
type: Memory access
@@ -2352,7 +2401,7 @@ instructions:
order: 2
space: false
definition: |
- registers[rt] = CAPI.MEM.read(registers[base]+off, 1, rt);
+ registers[rt] = CAPI.MEM.read(registers[base]+off, 1, rt, false);
- name: ldc1
template: Custom
type: Memory access
@@ -2392,11 +2441,11 @@ instructions:
postoperation: |
CAPI.ARCH.writeDouble(doubleValue, ft);
definition: |
- if (CAPI.VALIDATION.isMisaligned(registers[base] + off, 'd')) {
- CAPI.VALIDATION.raise('The memory must be aligned');
- }
- let high = CAPI.MEM.read(registers[base] + off, 4);
- let low = CAPI.MEM.read(registers[base] + off + 4n, 4, ft);
+ let addr = registers[base] + off;
+ if (CAPI.VALIDATION.isMisaligned(addr, 8))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ let high = CAPI.MEM.read(addr, 4, false);
+ let low = CAPI.MEM.read(addr + 4n, 4, ft, false);
let doubleValue = CAPI.FP.uint2float64(Number(low), Number(high));
- name: lh
template: Custom
@@ -2433,7 +2482,11 @@ instructions:
prefix: ($
suffix: )
definition: |
- registers[reg1] = CAPI.MEM.read(registers[reg2]+val, 2, reg1);
+ let addr = registers[reg2] + val;
+ if (CAPI.VALIDATION.isMisaligned(addr, 2))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ const result = CAPI.MEM.read(addr, 2, reg1, false);
+ registers[reg1] = CAPI.FP.int2uint(CAPI.FP.uint2int(result, 16));
- name: lhu
template: Custom
type: Memory access
@@ -2469,7 +2522,10 @@ instructions:
order: 2
space: false
definition: |
- registers[rt] = CAPI.MEM.read(registers[base]+off, 2, rt);
+ let addr = registers[base] + off;
+ if (CAPI.VALIDATION.isMisaligned(addr, 2))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[rt] = CAPI.MEM.read(addr, 2, rt, false);
- name: lui
template: Custom
type: Other
@@ -2533,7 +2589,10 @@ instructions:
suffix: )
order: 3
definition: |
- registers[reg1] = CAPI.MEM.read(registers[reg2]+val, 4, reg1);
+ let addr = registers[reg2] + val;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[reg1] = CAPI.MEM.read(addr, 4, reg1, false);
- name: lwc1
template: Custom
type: Memory access
@@ -2569,7 +2628,10 @@ instructions:
order: 2
space: false
definition: |-
- registers[ft] = CAPI.MEM.read(registers[base]+off, 4, ft);
+ let addr = registers[base] + off;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[ft] = CAPI.MEM.read(addr, 4, ft, false);
- name: mfc1
template: Custom
type: Transfer between registers
@@ -2821,9 +2883,9 @@ instructions:
stopbit: 0
value: "000110"
preoperation: |
- fsValue = CAPI.FS.uint2float32(fs);
+ fsValue = CAPI.FP.uint2float32(fs);
postoperation: |
- registers[fd] = CAPI.FS.float322uint(result);
+ registers[fd] = CAPI.FP.float322uint(result);
definition: let result = fsValue;
- name: mtc1
template: Custom
@@ -2857,7 +2919,7 @@ instructions:
stopbit: 11
order: 2
prefix: $
- definition: registers[fs] = CAPI.FP.uint2float32(registers[rt]);
+ definition: registers[fs] = registers[rt];
- name: mthi
template: Custom
type: Transfer between registers
@@ -3046,10 +3108,10 @@ instructions:
stopbit: 0
value: "000010"
preoperation: |
- fsValue = CAPI.FS.uint2float32(fs);
- ftValue = CAPI.FS.uint2float32(ft);
+ fsValue = CAPI.FP.uint2float32(registers[fs]);
+ ftValue = CAPI.FP.uint2float32(registers[ft]);
postoperation: |
- registers[fd] = CAPI.FS.float322uint(result);
+ registers[fd] = CAPI.FP.float322uint(result);
definition: |
let result = fsValue * ftValue;
- name: mult
@@ -3086,8 +3148,8 @@ instructions:
value: "011000"
definition: |-
let result = CAPI.FP.uint2int(registers[rs]) * CAPI.FP.uint2int(registers[rt]);
- registers.HI = Math.floor(result / Math.pow (2, 32));
- registers.LO = result % Math.pow(2, 32);
+ registers.HI = CAPI.FP.int2uint(result >> 32n);
+ registers.LO = CAPI.FP.int2uint(result & 0xFFFFFFFFn);
- name: multu
template: Custom
type: Arithmetic integer
@@ -3122,10 +3184,8 @@ instructions:
value: "011001"
definition: |-
let result = CAPI.FP.int2uint(registers[rs]) * CAPI.FP.int2uint(registers[rt]);
- registers.HI = Math.floor(result / Math.pow(2, 32));
- registers.HI = registers.HI >>> 0; // TODO: This is broken with bigints.
- registers.LO = result % Math.pow(2, 32);
- registers.LO = registers.LO >>> 0;
+ registers.HI = CAPI.FP.int2uint(result >> 32n);
+ registers.LO = CAPI.FP.int2uint(result & 0xFFFFFFFFn);
- name: nop
template: Custom
type: Logic
@@ -3304,7 +3364,7 @@ instructions:
stopbit: 0
value: "000010"
definition: |
- registers[rd] = CAPI.FP.int2uint((registers[rt] >>> sa) | (registers[rt] << (32 - sa))); // TODO: This is broken with bigints.
+ registers[rd] = CAPI.FP.int2uint((CAPI.FP.int2uint(registers[rt]) >> sa) | (registers[rt] << (32n - sa)));
- name: rsqrt.d
template: Custom
type: Arithmetic floating point
@@ -3391,9 +3451,9 @@ instructions:
stopbit: 0
value: "010110"
preoperation: |
- fsValue = CAPI.FS.uint2float32(fs);
+ fsValue = CAPI.FP.uint2float32(registers[fs]);
postoperation: |
- fd = CAPI.FS.float322uint(fd);
+ registers[fd] = CAPI.FP.float322uint(result);
definition: |-
let result;
if (fsValue >= 0) {
@@ -3435,7 +3495,7 @@ instructions:
stopbit: 0
order: 2
space: false
- definition: "CAPI.MEM.write(registers[base]+off, 1, registers[rt], rt);"
+ definition: "CAPI.MEM.write(registers[base]+off, 1, BigInt.asUintN(8, registers[rt]), rt, 'byte', false);"
- name: sdc1
template: Custom
type: Memory access
@@ -3473,12 +3533,12 @@ instructions:
preoperation: |
let doubleValue = CAPI.ARCH.readDouble(ft);
let parts = CAPI.FP.float642uint(doubleValue);
+ let value = (BigInt(parts[1]) << 32n) | BigInt(parts[0])
definition: |
- if (CAPI.VALIDATION.isMisaligned(registers[base] + off, 'd')) {
- CAPI.VALIDATION.raise('The memory must be aligned');
- }
- CAPI.MEM.write(registers[base] + off, 4, BigInt(parts[0]), ft);
- CAPI.MEM.write(registers[base] + off + 4n, 4, BigInt(parts[1]));
+ let addr = registers[base] + off;
+ if (CAPI.VALIDATION.isMisaligned(addr, 8))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 8, value, ft, 'float64', false);
- name: sh
template: Custom
type: Memory access
@@ -3513,7 +3573,11 @@ instructions:
stopbit: 0
order: 2
space: false
- definition: "CAPI.MEM.write(registers[base]+off, 2, registers[rt], rt);"
+ definition: |
+ let addr = registers[base] + off;
+ if (CAPI.VALIDATION.isMisaligned(addr, 2))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 2, BigInt.asUintN(16, registers[rt]), rt, 'half', false);
- name: sll
template: Custom
type: Arithmetic integer
@@ -3552,7 +3616,7 @@ instructions:
startbit: 5
stopbit: 0
value: "111111"
- definition: rd = CAPI.FP.int2uint(registers[rt] << sa);
+ definition: registers[rd] = CAPI.FP.int2uint(registers[rt] << sa);
- name: slt
template: Custom
type: Logic
@@ -3700,7 +3764,7 @@ instructions:
startbit: 5
stopbit: 0
value: "101011"
- definition: "registers[rd] = CAPI.FP.uint2int(registers[rs]) < CAPI.FP.uint2int(registers[rt]) ? 1n : 0n;"
+ definition: "registers[rd] = registers[rs] < registers[rt] ? 1n : 0n;"
- name: sqrt.d
template: Custom
type: Arithmetic floating point
@@ -3787,9 +3851,9 @@ instructions:
stopbit: 0
value: "000100"
preoperation: |
- fsValue = CAPI.FS.uint2float32(fs);
+ fsValue = CAPI.FP.uint2float32(registers[fs]);
postoperation: |
- registers[fd] = CAPI.FS.float322uint(result);
+ registers[fd] = CAPI.FP.float322uint(result);
definition: |-
let result;
if (fsValue >= 0) {
@@ -3836,7 +3900,7 @@ instructions:
stopbit: 0
value: "000011"
definition: |
- registers[rd] = CAPI.FP.int2uint(registers[rt] >> sa);
+ registers[rd] = CAPI.FP.int2uint(CAPI.FP.uint2int(registers[rt]) >> sa);
- name: srl
template: Custom
type: Arithmetic integer
@@ -3881,7 +3945,7 @@ instructions:
stopbit: 0
value: "000010"
definition: |
- registers[rd] = registers[rt] >>> sa; // TODO:broken with bigints.
+ registers[rd] = CAPI.FP.int2uint(registers[rt]) >> sa;
- name: sub
template: Custom
type: Arithmetic integer
@@ -4019,10 +4083,10 @@ instructions:
stopbit: 0
value: "000001"
preoperation: |
- fsValue = CAPI.FS.uint2float32(fs);
- ftValue = CAPI.FS.uint2float32(ft);
+ fsValue = CAPI.FP.uint2float32(registers[fs]);
+ ftValue = CAPI.FP.uint2float32(registers[ft]);
postoperation: |
- registers[fd] = CAPI.FS.float322uint(result);
+ registers[fd] = CAPI.FP.float322uint(result);
definition: let result = fsValue - ftValue;
- name: subu
template: Custom
@@ -4099,7 +4163,11 @@ instructions:
prefix: ($
suffix: )
order: 3
- definition: "CAPI.MEM.write(val+registers[reg2], 4, registers[reg1], reg1);"
+ definition: |
+ let addr = registers[reg2] + val;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 4, registers[reg1], reg1, 'word', false);
- name: swc1
template: Custom
type: Memory access
@@ -4134,7 +4202,11 @@ instructions:
stopbit: 0
order: 2
space: false
- definition: "CAPI.MEM.write(registers[base]+off, 4, registers[ft], ft);"
+ definition: |
+ let addr = registers[base] + off;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 4, registers[ft], ft, 'float32', false);
- name: syscall
template: Custom
type: Syscall
@@ -4156,6 +4228,7 @@ instructions:
value: "001100"
definition: |-
let FP0 = CAPI.ARCH.readDouble('f0');
+ let f12 = CAPI.FP.uint2float32(registers.f12);
let FP12 = CAPI.ARCH.readDouble('f12');
switch(registers["v0"]) {
case 1n:
@@ -4174,10 +4247,10 @@ instructions:
CAPI.SYSCALL.read('v0', 'int32');
break;
case 6n:
- CAPI.SYSCALL.read(f0, 'float');
+ CAPI.SYSCALL.read('f0', 'float');
break;
case 7n:
- CAPI.SYSCALL.read(FP0, 'double');
+ CAPI.SYSCALL.read('FP0', 'double');
break;
case 8n:
CAPI.SYSCALL.read('a0', 'string', 'a1');
@@ -4981,18 +5054,24 @@ pseudoinstructions:
- field: val
type: imm-signed
definition: |-
- no_ret_op{tmp0=Field.2.(63,32).double;
- tmp_low0=tmp0&0x0000FFFF;
- tmp_hi0=tmp0>>>16;
- tmp1=Field.2.(31,0).double;
- tmp_low1=tmp1&0x0000FFFF;
- tmp_hi1=tmp1>>>16};
+ no_ret_op{
+ tmp0=Field.2.(63,32).double;
+ tmp_low0=tmp0&0x0000FFFF;
+ tmp_hi0=tmp0>>>16;
+ tmp1=Field.2.(31,0).double;
+ tmp_low1=tmp1&0x0000FFFF;
+ tmp_hi1=tmp1>>>16;
+ tmp_reg=reg_name{1};
+ regNumber=parseInt(tmp_reg.substring(2), 10);
+ reg0="f" + regNumber;
+ reg1="f" + (regNumber + 1);
+ };
lui $at, op{tmp_hi1};
ori $at, $at, op{tmp_low1};
- mtc1 $at, $aliasDouble(rd;1);
+ mtc1 $at, $op{reg1};
lui $at, op{tmp_hi0};
ori $at, $at, op{tmp_low0};
- mtc1 $at, $aliasDouble(rd;0);
+ mtc1 $at, $op{reg0};
- name: li.s
help: ""
properties: []
diff --git a/architecture/RISCV/RV32IMFD.yml b/architecture/RISCV/RV32IMFD.yml
index 8cc988d99..825c89625 100644
--- a/architecture/RISCV/RV32IMFD.yml
+++ b/architecture/RISCV/RV32IMFD.yml
@@ -8,7 +8,7 @@ config:
name: RV32
word_size: 32
byte_size: 8
- description: RISC-V is an instruction set architecture (ISA) based on the RISC type and its hardware is free. This architecture was created in 2010 at the University of California, Berkeley.
+ description: RISC-V is a free and open standard ISA (Instruction Set Architecture) based on RISC (Reduced Instruction Set Computer) principles. It was created in 2010 at the University of California, Berkeley.
endianness: big_endian
memory_alignment: true
main_function: main
@@ -20,32 +20,33 @@ config:
plugin: riscv
assemblers:
- name: CreatorAssembler
- description: Default CREATOR assembler
+ description: "Default CREATOR assembler"
+
extensions:
I:
- description: RV32I Base Instruction Set
+ description: "RV32I Base Instruction Set"
template: Base
M:
- description: RV32M Integer Multiply/Divide Extension
+ description: "RV32M Integer Multiply/Divide Extension"
type: extension
F:
- description: RV32F Single-Precision Floating-Point Extension
+ description: "RV32F Single-Precision Floating-Point Extension"
type: extension
implies:
- Zicsr
D:
- description: RV32D Double-Precision Floating-Point Extension
+ description: "RV32D Double-Precision Floating-Point Extension"
type: extension
implies:
- F
Zifencei:
- description: RV32/RV64 Zifencei Standard Extension
+ description: "RV32/RV64 Zifencei Standard Extension"
type: extension
Zicsr:
- description: RV32/RV64 Zicsr Standard Extension
+ description: "RV32/RV64 Zicsr Standard Extension"
type: extension
Priv:
- description: RV32/RV64 Privileged instructions
+ description: "RV32/RV64 Privileged instructions"
type: extension
components:
@@ -91,6 +92,7 @@ components:
encoding: 2
properties:
- read
+ - write
- name:
- mstatus
nbits: 32
@@ -164,8 +166,8 @@ components:
- x1
- ra
nbits: 32
- value: 0xFFFFFF00
- default_value: 0xFFFFFF00
+ value: -1
+ default_value: -1
encoding: 1
properties:
- read
@@ -888,6 +890,16 @@ memory_layout:
start: 0x0FFFFFFC
end: 0x0FFFFFFF
+modifiers:
+ hi:
+ lower_signed: true
+ output_signed: false
+ range: [12, 32]
+ lo:
+ lower_signed: false
+ output_signed: true
+ range: [0, 12]
+
templates:
- name: B
type: Conditional bifurcation
@@ -1489,8 +1501,8 @@ instructions:
- field: funct3
value: "000"
definition: |
- if (registers[rs1] === registers[rs2])
- registers.pc = registers.pc + imm;
+ if (registers[rs1] === registers[rs2])
+ registers.pc = registers.pc + imm;
help: Take the branch if registers rs1 and rs2 are equal.
- name: bge
@@ -1502,7 +1514,7 @@ instructions:
value: "101"
definition: |
if (CAPI.FP.uint2int(registers[rs1]) >= CAPI.FP.uint2int(registers[rs2]))
- registers.pc = registers.pc + imm;
+ registers.pc = registers.pc + imm;
help: Take the branch if registers rs1 is greater than or equal to rs2,
using signed comparison.
@@ -1514,8 +1526,8 @@ instructions:
- field: funct3
value: "111"
definition: |
- if (CAPI.FP.int2uint(registers[rs1]) > CAPI.FP.int2uint(registers[rs2]))
- registers.pc = registers.pc + imm;
+ if (CAPI.FP.int2uint(registers[rs1]) >= CAPI.FP.int2uint(registers[rs2]))
+ registers.pc = registers.pc + imm;
help: Take the branch if registers rs1 is greater than or equal to rs2,
using unsigned comparison.
@@ -1528,9 +1540,8 @@ instructions:
value: "100"
definition: |
if (CAPI.FP.uint2int(registers[rs1]) < CAPI.FP.uint2int(registers[rs2]))
- registers.pc = registers.pc + imm;
- help: Take the branch if registers rs1 is less than rs2, using signed
- comparison.
+ registers.pc = registers.pc + imm;
+ help: Take the branch if registers rs1 is less than rs2, using signed comparison.
- name: bltu
template: B
@@ -1541,9 +1552,8 @@ instructions:
value: "110"
definition: |
if (CAPI.FP.int2uint(registers[rs1]) < CAPI.FP.int2uint(registers[rs2]))
- registers.pc = registers.pc + imm;
- help: Take the branch if registers rs1 is less than rs2, using unsigned
- comparison.
+ registers.pc = registers.pc + imm;
+ help: Take the branch if registers rs1 is less than rs2, using unsigned comparison.
- name: bne
template: B
@@ -1553,8 +1563,8 @@ instructions:
- field: funct3
value: "001"
definition: |
- if (registers[rs1] !== registers[rs2])
- registers.pc = registers.pc + imm;
+ if (registers[rs1] !== registers[rs2])
+ registers.pc = registers.pc + imm;
help: Take the branch if registers rs1 and rs2 are not equal.
# I-type instructions
@@ -1589,8 +1599,7 @@ instructions:
value: "111"
definition: |
registers[rd] = registers[rs1] & CAPI.FP.int2uint(imm);
- help: Performs bitwise AND on register rs1 and the sign-extended 12-bit
- immediate and place the result in rd.
+ help: Performs bitwise AND on register rs1 and the sign-extended 12-bit immediate and place the result in rd.
- name: jalr
template: I-Offset
@@ -1602,8 +1611,10 @@ instructions:
value: "000"
definition: |
registers[rd] = registers.pc + 4n;
- registers.pc = (registers[rs1] + imm) & ~1n;
- CAPI.STACK.endFrame();
+ const pc = registers[rs1] + imm;
+ registers.pc = pc & ~1n;
+ if (BigInt.asIntN(32, pc) === -1n) CAPI.SYSCALL.exit();
+ else CAPI.STACK.endFrame();
help: Jump to address and place return address in rd.
- name: lb
@@ -1615,9 +1626,10 @@ instructions:
- field: funct3
value: "000"
definition: |
- registers[rd] = CAPI.MEM.read(imm + registers[rs1], 1, rd);
- help: Loads a 8-bit value from memory and sign-extends this to XLEN bits
- before storing it in register rd.
+ let addr = registers[rs1] + imm;
+ const result = CAPI.MEM.read(addr, 1, rd, false);
+ 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
template: I-Offset
@@ -1629,10 +1641,9 @@ instructions:
value: "100"
definition: |
let addr = CAPI.FP.int2uint(registers[rs1]) + imm;
- registers[rd] = CAPI.MEM.read(addr, 1, rd);
- registers[rd] = CAPI.FP.int2uint(registers[rd]);
- help: Loads a 8-bit value from memory and zero-extends this to XLEN bits
- before storing it in register rd.
+ let result = CAPI.MEM.read(addr, 1, rd, false);
+ registers[rd] = CAPI.FP.int2uint(result);
+ help: Loads a 8-bit value from memory and zero-extends this to XLEN bits before storing it in register rd.
- name: lh
template: I-Offset
@@ -1643,9 +1654,12 @@ instructions:
- field: funct3
value: "001"
definition: |
- registers[rd] = CAPI.MEM.read(imm + registers[rs1], 2, rd);
- help: Loads a 16-bit value from memory and sign-extends this to XLEN bits
- before storing it in register rd.
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 2))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ const result = CAPI.MEM.read(addr, 2, rd, false);
+ 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
template: I-Offset
@@ -1656,11 +1670,12 @@ instructions:
- field: funct3
value: "101"
definition: |
- let addr = CAPI.FP.int2uint(registers[rs1], 32) + imm;
- registers[rd] = CAPI.MEM.read(addr, 2, rd);
- registers[rd] = CAPI.FP.int2uint(registers[rd]);
- help: Loads a 16-bit value from memory and zero-extends this to XLEN bits
- before storing it in register rd.
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 2))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ let result = CAPI.MEM.read(addr, 2, rd, false);
+ registers[rd] = CAPI.FP.int2uint(result);
+ help: Loads a 16-bit value from memory and zero-extends this to XLEN bits before storing it in register rd.
- name: lw
template: I-Offset
@@ -1671,10 +1686,11 @@ instructions:
- field: funct3
value: "010"
definition: |
- let addr = CAPI.FP.int2uint(registers[rs1], 32) + imm;
- registers[rd] = CAPI.MEM.read(addr, 4, rd);
- help: Loads a 32-bit value from memory and sign-extends this to XLEN bits
- before storing it in register rd.
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[rd] = CAPI.MEM.read(addr, 4, rd, false);
+ help: Loads a 32-bit value from memory and sign-extends this to XLEN bits before storing it in register rd.
- name: ori
template: I
@@ -1686,8 +1702,7 @@ instructions:
value: "110"
definition: |
registers[rd] = registers[rs1] | imm;
- help: Performs bitwise OR on register rs1 and the sign-extended 12-bit
- immediate and place the result in rd.
+ help: Performs bitwise OR on register rs1 and the sign-extended 12-bit immediate and place the result in rd.
- name: slli
template: I-Shift
@@ -1701,8 +1716,7 @@ instructions:
value: "0000000"
definition: |
if (shamt > 0) registers[rd] = CAPI.FP.int2uint(registers[rs1] << shamt);
- help: Performs logical left shift on the value in register rs1 by the
- shift amount held in the lower 5 bits of the immediate.
+ help: Performs logical left shift on the value in register rs1 by the shift amount held in the lower 5 bits of the immediate.
- name: slti
template: I
@@ -1713,9 +1727,8 @@ instructions:
- field: funct3
value: "010"
definition: |
- registers[rd] = (CAPI.FP.uint2int(registers[rs1]) < CAPI.FP.uint2int(imm)) ? 1 : 0;
- help: Place the value 1 in register rd if register rs1 is less than the
- signextended immediate when both are treated as signed numbers, else 0 is written to rd.
+ registers[rd] = (CAPI.FP.uint2int(registers[rs1]) < CAPI.FP.uint2int(imm)) ? 1n : 0n;
+ help: Place the value 1 in register rd if register rs1 is less than the signextended immediate when both are treated as signed numbers, else 0 is written to rd.
- name: sltiu
template: I
@@ -1726,9 +1739,8 @@ instructions:
- field: funct3
value: "011"
definition: |
- registers[rd] = (CAPI.FP.int2uint(registers[rs1]) < CAPI.FP.int2uint(imm)) ? 1: 0;
- help: Place the value 1 in register rd if register rs1 is less than the
- immediate when both are treated as unsigned numbers, else 0 is written to rd.
+ registers[rd] = (CAPI.FP.int2uint(registers[rs1]) < CAPI.FP.int2uint(imm)) ? 1n : 0n;
+ help: Place the value 1 in register rd if register rs1 is less than the immediate when both are treated as unsigned numbers, else 0 is written to rd.
- name: srai
template: I-Shift
@@ -1741,9 +1753,8 @@ instructions:
- field: funct7
value: "0100000"
definition: |
- if (shamt > 0) registers[rd] = CAPI.FP.int2uint(registers[rs1] >> shamt);
- help: Performs arithmetic right shift on the value in register rs1 by the
- shift amount held in the lower 5 bits of the immediate.
+ if (shamt > 0) registers[rd] = CAPI.FP.int2uint(CAPI.FP.uint2int(registers[rs1]) >> shamt);
+ help: Performs arithmetic right shift on the value in register rs1 by the shift amount held in the lower 5 bits of the immediate.
- name: srli
template: I-Shift
@@ -1757,8 +1768,7 @@ instructions:
value: "0000000"
definition: |
if (shamt > 0) registers[rd] = CAPI.FP.int2uint(registers[rs1] >> shamt);
- help: Performs logical right shift on the value in register rs1 by the
- shift amount held in the lower 5 bits of the immediate.
+ help: Performs logical right shift on the value in register rs1 by the shift amount held in the lower 5 bits of the immediate.
- name: xori
template: I
@@ -1789,9 +1799,11 @@ instructions:
- field: opcode
value: "1101111"
definition: |
- registers[rd] = registers.pc + 4n;
- registers.pc += imm;
- CAPI.STACK.beginFrame();
+ if (CAPI.ARDUINO.check_arduino(imm,registers.pc) === false) {
+ 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
@@ -1827,8 +1839,7 @@ instructions:
value: "111"
definition: |
registers[rd] = registers[rs1] & registers[rs2];
- help: Performs bitwise AND on registers rs1 and rs2 and place the result
- in rd.
+ help: Performs bitwise AND on registers rs1 and rs2 and place the result in rd.
- name: or
template: R
@@ -1841,8 +1852,8 @@ instructions:
value: "110"
definition: |
registers[rd] = registers[rs1] | registers[rs2];
- help: Performs bitwise OR on registers rs1 and rs2 and place the result in
- rd.
+ help: Performs bitwise OR on registers rs1 and rs2 and place the result in rd.
+
- name: sll
template: R
fields:
@@ -1855,8 +1866,7 @@ instructions:
definition: |
const shiftAmount = registers[rs2] & 0x1Fn;
registers[rd] = (registers[rs1] << shiftAmount) & 0xFFFFFFFFn;
- help: Performs logical left shift on the value in register rs1 by the
- shift amount held in the lower 5 bits of register rs2.
+ help: Performs logical left shift on the value in register rs1 by the shift amount held in the lower 5 bits of register rs2.
- name: slt
template: R
@@ -1868,9 +1878,8 @@ instructions:
- field: funct3
value: "010"
definition: |
- registers[rd] = (CAPI.FP.uint2int(registers[rs1]) < CAPI.FP.uint2int(registers[rs2])) ? 1 : 0;
- help: Place the value 1 in register rd if register rs1 is less than
- register rs2 when both are treated as signed numbers, else 0 is written to rd.
+ registers[rd] = (CAPI.FP.uint2int(registers[rs1]) < CAPI.FP.uint2int(registers[rs2])) ? 1n : 0n;
+ help: Place the value 1 in register rd if register rs1 is less than register rs2 when both are treated as signed numbers, else 0 is written to rd.
- name: sltu
template: R
@@ -1914,8 +1923,7 @@ instructions:
definition: |
const shiftAmount = registers[rs2] & 0x1Fn;
registers[rd] = (registers[rs1] >> shiftAmount) & 0xFFFFFFFFn;
- help: Logical right shift on the value in register rs1 by the shift amount
- held in the lower 5 bits of register rs2.
+ help: Logical right shift on the value in register rs1 by the shift amount held in the lower 5 bits of register rs2.
- name: sub
template: R
@@ -1943,8 +1951,7 @@ instructions:
value: "100"
definition: |
registers[rd] = (registers[rs1] ^ registers[rs2]);
- help: Performs bitwise XOR on registers rs1 and rs2 and place the result
- in rd.
+ help: Performs bitwise XOR on registers rs1 and rs2 and place the result in rd.
# S-type instructions
# 31-25 24-20 19-15 14-12 11-7 6-0
@@ -1962,7 +1969,7 @@ instructions:
- field: funct3
value: "000"
definition: |
- CAPI.MEM.write(registers[rs1] + imm, 1, BigInt.asUintN(8, registers[rs2]), rs2, 'byte');
+ CAPI.MEM.write(registers[rs1] + imm, 1, BigInt.asUintN(8, registers[rs2]), rs2, 'byte', false);
help: Store 8-bit, values from the low bits of register rs2 to memory.
- name: sh
@@ -1973,10 +1980,12 @@ instructions:
- field: funct3
value: "001"
definition: |
- CAPI.MEM.write(imm + registers[rs1], 2, BigInt.asUintN(16, registers[rs2]), rs2, 'half');
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 2))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 2, BigInt.asUintN(16, registers[rs2]), rs2, 'half', false);
help: Store 16-bit, values from the low bits of register rs2 to memory.
- # The check for the
- name: sw
template: S
fields:
@@ -1985,7 +1994,10 @@ instructions:
- field: funct3
value: "010"
definition: |
- CAPI.MEM.write(imm + registers[rs1], 4, BigInt.asUintN(32, registers[rs2]), rs2, 'word');
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 4, BigInt.asUintN(32, registers[rs2]), rs2, 'word', false);
help: Store 32-bit, values from the low bits of register rs2 to memory.
# U-type instructions
@@ -2107,7 +2119,7 @@ instructions:
(BigInt.asIntN(32, BigInt(registers[rs1])) / BigInt.asIntN(32, BigInt(registers[rs2])))
);
}
- else CAPI.VALIDATION.raise('Division by registers[zero] not allowed');
+ else CAPI.VALIDATION.raise('Division by zero not allowed');
help: Perform an XLEN bits by XLEN bits signed integer division of rs1 by
rs2, rounding towards zero.
@@ -2121,13 +2133,11 @@ instructions:
- field: funct3
value: "101"
definition: |
- if (registers[rs2] != 0) {
- registers[rd] = BigInt.asIntN(
- 32,
- (BigInt.asUintN(32, BigInt(registers[rs1])) / BigInt.asUintN(32, BigInt(registers[rs2])))
- );
+ const div = registers[rs2]
+ if (div != 0) {
+ registers[rd] = CAPI.FP.int2uint(registers[rs1] / div);
}
- else CAPI.VALIDATION.raise('Division by registers[zero] not allowed');
+ else CAPI.VALIDATION.raise('Division by zero not allowed');
help: Perform an XLEN-bit by XLEN-bit unsigned integer division of rs1 by
rs2, rounding towards zero.
@@ -2155,12 +2165,8 @@ instructions:
- field: funct3
value: "001"
definition: |
- registers[rd] = BigInt.asIntN(
- 32,
- BigInt.asIntN(
- 64,
- BigInt.asIntN(32, BigInt(registers[rs1])) * BigInt.asIntN(32, BigInt(registers[rs2])),
- ) >> 32n,
+ registers[rd] = CAPI.FP.int2uint(
+ (CAPI.FP.uint2int(registers[rs1]) * CAPI.FP.uint2int(registers[rs2])) >> 32n,
);
help: Performs an XLEN-bit by XLEN-bit multiplication of signed rs1 by
signed rs2 and places the lower XLEN bits in the destination register.
@@ -2175,12 +2181,8 @@ instructions:
- field: funct3
value: "010"
definition: |
- registers[rd] = BigInt.asIntN(
- 32,
- BigInt.asIntN(
- 64,
- BigInt.asIntN(32, BigInt(registers[rs1])) * BigInt.asUintN(32, BigInt(registers[rs2])),
- ) >> 32n,
+ registers[rd] = CAPI.FP.int2uint(
+ (CAPI.FP.uint2int(registers[rs1]) * registers[rs2]) >> 32n,
);
help: Performs an XLEN-bit by XLEN-bit multiplication of signed rs1 by
unsigned rs2 and places the upper XLEN bits in the destination register.
@@ -2195,12 +2197,8 @@ instructions:
- field: funct3
value: "011"
definition: |
- registers[rd] = BigInt.asIntN(
- 32,
- BigInt.asUintN(
- 64,
- BigInt.asUintN(32, BigInt(registers[rs1])) * BigInt.asUintN(32, BigInt(registers[rs2])),
- ) >> 32n,
+ registers[rd] = CAPI.FP.int2uint(
+ (registers[rs1] * registers[rs2]) >> 32n,
);
help: Performs an XLEN-bit by XLEN-bit multiplication of unsigned rs1 by
unsigned rs2 and places the upper XLEN bits in the destination register.
@@ -2251,12 +2249,14 @@ instructions:
- field: rd
type: DFP-Reg
definition: |
- registers[rd] = CAPI.MEM.read(registers[rs1] + imm, 4, rd);
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[rd] = CAPI.MEM.read(addr, 4, rd, false);
postoperation: |
registers[rd] = CAPI.ARCH.NaNBox(registers[rd]);
- help: Load a single-precision floating-point value from memory into
- floating-point register rd.
+ help: Load a single-precision floating-point value from memory into floating-point register rd.
- name: fadd.s
template: R-Floating
@@ -2335,11 +2335,10 @@ instructions:
optional: true
order: 3
postoperation: |
- registers[rd] = CAPI.ARCH.toBigInt(registers[rd],'NaNBfloat32_64');
+ registers[rd] = CAPI.ARCH.toBigInt(result,'NaNBfloat32_64');
definition: |
- registers[rd] = CAPI.FP.uint2int(registers[rs1])
- help: Converts a 32-bit signed integer, in integer register rs1 into a
- floating-point number in floating-point register rd.
+ const result = CAPI.FP.uint2int(registers[rs1])
+ help: Converts a 32-bit signed integer, in integer register rs1 into a floating-point number in floating-point register rd.
- name: fcvt.s.wu
template: R-IntToFloat
@@ -2357,8 +2356,7 @@ instructions:
order: 3
definition: |
registers[rd] = CAPI.FP.int2uint(registers[rs1])
- help: Converts a 32-bit unsigned integer, in integer register rs1 into a
- floating-point number in floating-point register rd.
+ help: Converts a 32-bit unsigned integer, in integer register rs1 into a floating-point number in floating-point register rd.
- name: fcvt.w.s
template: R-FloatToInt
@@ -2386,8 +2384,7 @@ instructions:
}
definition: |
result = parseInt(registers[rs1]);
- help: Convert a floating-point number in floating-point register rs1 to a
- signed 32-bit in integer register rd.
+ help: Convert a floating-point number in floating-point register rs1 to a signed 32-bit in integer register rd.
- name: fcvt.wu.s
template: R-FloatToInt
@@ -2415,8 +2412,7 @@ instructions:
}
definition: |
registers[rd] = CAPI.FP.int2uint(parseInt(rs1Number));
- help: Convert a floating-point number in floating-point register rs1 to a
- signed 32-bit in unsigned integer register rd.
+ help: Convert a floating-point number in floating-point register rs1 to a signed 32-bit in unsigned integer register rd.
- name: fdiv.s
template: R-Floating
@@ -2457,17 +2453,11 @@ instructions:
- field: rd
type: INT-Reg
preoperation: |
- let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ let rs1Number, rs2Number, type_rs1, type_rs2;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- postoperation: |
- if (CAPI.FP.isNaN(result)) {
- registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
- } else {
- registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
- }
definition: |
- result = (rs1Number === rs2Number) ? 1 : 0;
+ registers[rd] = (rs1Number === rs2Number)? 1n : 0n;
help: Performs a quiet equal comparison between floating-point registers
rs1 and rs2 and record the Boolean result in integer register rd. Only
signaling NaN inputs cause an Invalid Operation exception. The result is
@@ -2485,17 +2475,11 @@ instructions:
- field: rd
type: INT-Reg
preoperation: |
- let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ let rs1Number, rs2Number, type_rs1, type_rs2;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- postoperation: |
- if (CAPI.FP.isNaN(result)) {
- registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
- } else {
- registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
- }
definition: |
- result = (rs1Number <= rs2Number) ? 1 : 0;
+ registers[rd] = (rs1Number <= rs2Number)? 1n : 0n;
help: Performs a quiet less or equal comparison between floating-point
registers rs1 and rs2 and record the Boolean result in integer register
rd. Only signaling NaN inputs cause an Invalid Operation exception. The
@@ -2513,17 +2497,11 @@ instructions:
- field: rd
type: INT-Reg
preoperation: |
- let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ let rs1Number, rs2Number, type_rs1, type_rs2;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- postoperation: |
- if (CAPI.FP.isNaN(result)) {
- registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
- } else {
- registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
- }
definition: |
- result = (rs1Number < rs2Number) ? 1 : 0;
+ registers[rd] = (rs1Number < rs2Number)? 1n : 0n;
help: Performs a quiet less comparison between floating-point registers
rs1 and rs2 and record the Boolean result in integer register rd. Only
signaling NaN inputs cause an Invalid Operation exception. The result is
@@ -2675,8 +2653,7 @@ instructions:
}
definition: |
result = (rs2Number >= 0) ? Math.abs(rs1Number) : -Math.abs(rs1Number);
- help: Produce a result that takes all bits except the sign bit from rs1.
- The result's sign bit is rs2's sign bit.
+ help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is rs2's sign bit.
- name: fsgnjn.s
template: R-Floating
@@ -2699,8 +2676,7 @@ instructions:
}
definition: |
result = (rs2Number <= 0) ? Math.abs(rs1Number) : -Math.abs(rs1Number);
- help: Produce a result that takes all bits except the sign bit from rs1.
- The result's sign bit is rs2's sign bit.
+ help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is rs2's sign bit.
- name: fsgnjx.s
template: R-Floating
@@ -2725,8 +2701,7 @@ instructions:
let a = rs1Number < 0;
let b = rs2Number < 0;
result = a ^ b ? -Math.abs(rs1Number) : Math.abs(rs1Number);
- help: Produce a result that takes all bits except the sign bit from rs1.
- The result's sign bit is XOR of sign bit of rs1 and rs2.
+ help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is XOR of sign bit of rs1 and rs2.
- name: fsqrt.s
template: R-Floating
@@ -2745,9 +2720,8 @@ instructions:
optional: true
order: 3
preoperation: |
- let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ let result, rs1Number, type_rs1;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
- [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
postoperation: |
if (CAPI.FP.isNaN(result)) {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
@@ -2759,7 +2733,7 @@ instructions:
result = Math.sqrt(rs1Number);
} else {
CAPI.VALIDATION.raise(
- 'Square root of a negative number is not allowed.'
+ "Square root of a negative number is not allowed."
);
}
help: Perform single-precision square root.
@@ -2788,7 +2762,7 @@ instructions:
}
definition: |
result = rs1Number - rs2Number;
- help: Perform single-precision floating-point substraction.
+ help: Perform single-precision floating-point subtraction.
- name: fmadd.s
template: R4
@@ -2806,7 +2780,7 @@ instructions:
let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(rs3);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
postoperation: |
if (CAPI.FP.isNaN(result)) {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
@@ -2833,7 +2807,7 @@ instructions:
let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(rs3);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
postoperation: |
if (CAPI.FP.isNaN(result)) {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
@@ -2860,7 +2834,7 @@ instructions:
let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(rs3);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
postoperation: |
if (CAPI.FP.isNaN(result)) {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
@@ -2887,7 +2861,7 @@ instructions:
let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(rs3);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
postoperation: |
if (CAPI.FP.isNaN(result)) {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
@@ -2909,9 +2883,11 @@ instructions:
type: DFP-Reg
definition: |
let value = registers[rs2] & 0xFFFFFFFFn;
- CAPI.MEM.write(registers[rs1] + imm, 4, value, rs2, 'float32');
- help: Store a single-precision value from floating-point register rs2 to
- memory.
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 4, value, rs2, 'float32', false);
+ help: Store a single-precision value from floating-point register rs2 to memory.
D:
# ____ __ __ _____ ____ ____
@@ -2932,12 +2908,11 @@ instructions:
- field: rd
type: DFP-Reg
definition: |
- if (CAPI.VALIDATION.isMisaligned(registers[rs1] + imm, 'd')) {
- CAPI.VALIDATION.raise('The memory must be aligned');
- }
- registers[rd] = CAPI.MEM.read(registers[rs1] + imm, 8, rd);
- help: Load a double-precision floating-point value from memory into
- floating-point register rd.
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 8))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[rd] = CAPI.MEM.read(addr, 8, rd, false);
+ help: Load a double-precision floating-point value from memory into floating-point register rd.
- name: fadd.d
template: R-Double
@@ -3035,8 +3010,7 @@ instructions:
}
definition: |
result = rs1Number; // TODO: This doesn't seem right, check the RISC-V manual
- help: Converts double floating-point register in rs1 into a double
- floating-point number in floating-point register rd.
+ help: Converts double floating-point register in rs1 into a double floating-point number in floating-point register rd.
- name: fcvt.d.w
template: R-Conversion
@@ -3057,14 +3031,13 @@ instructions:
- field: rs1
type: INT-Reg
preoperation: |
- let result, rs1Number, type_rs1;
- [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ let result, rs1Number;
+ rs1Number = registers[rs1];
postoperation: |
registers[rd] = CAPI.ARCH.toBigInt(result, 'float64');
definition: |
result = CAPI.FP.uint2int(rs1Number);
- help: Converts a 32-bit signed integer, in integer register rs1 into a
- double-precision floating-point number in floating-point register rd.
+ help: Converts a 32-bit signed integer, in integer register rs1 into a double-precision floating-point number in floating-point register rd.
- name: fcvt.d.wu
template: R-Conversion
@@ -3096,8 +3069,7 @@ instructions:
}
definition: |
result = CAPI.FP.int2uint(parseFloat(rs1Number));
- help: Converts a 32-bit unsigned integer, in integer register rs1 into a
- double-precision floating-point number in floating-point register rd.
+ help: Converts a 32-bit unsigned integer, in integer register rs1 into a double-precision floating-point number in floating-point register rd.
- name: fcvt.s.d
template: R-Conversion
@@ -3129,8 +3101,7 @@ instructions:
}
definition: |
result = rs1Number; // TODO: This doesn't seem right, check the RISC-V manual
- help: Converts double floating-point register in rs1 into a floating-point
- number in floating-point register rd.
+ help: Converts double floating-point register in rs1 into a floating-point number in floating-point register rd.
- name: fcvt.w.d
template: R-Conversion
@@ -3162,8 +3133,7 @@ instructions:
}
definition: |
result = CAPI.FP.int2uint(parseInt(rs1Number));
- help: Converts a double-precision floating-point number in floating-point
- register rs1 to a signed 32-bit integer, in integer register rd.
+ help: Converts a double-precision floating-point number in floating-point register rs1 to a signed 32-bit integer, in integer register rd.
- name: fcvt.wu.d
template: R-Conversion
@@ -3195,8 +3165,7 @@ instructions:
}
definition: |
result = CAPI.FP.int2uint(parseInt(rs1Number));
- help: Converts a double-precision floating-point number in floating-point
- register rs1 to a unsigned 32-bit integer, in integer register rd.
+ help: Converts a double-precision floating-point number in floating-point register rs1 to a unsigned 32-bit integer, in integer register rd.
- name: fdiv.d
template: R-Double
@@ -3236,17 +3205,11 @@ instructions:
- field: rd
type: INT-Reg
preoperation: |
- let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ let rs1Number, rs2Number, type_rs1, type_rs2;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- postoperation: |
- if (CAPI.FP.isNaN(result)) {
- registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
- } else {
- registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
- }
definition: |
- registers[rd] = (rs1Number == rs2Number) ? 1 : 0;
+ registers[rd] = (rs1Number === rs2Number)? 1n : 0n;
help: Performs a quiet equal comparison between double-precision
floating-point registers rs1 and rs2 and record the Boolean result in
integer register rd. Only signaling NaN inputs cause an Invalid
@@ -3267,14 +3230,8 @@ instructions:
let rs1Number, rs2Number, type_rs1, type_rs2;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- postoperation: |
- if (CAPI.FP.isNaN(result)) {
- registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
- } else {
- registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
- }
definition: |
- registers[rd] = (rs1Number <= rs2Number) ? 1 : 0;
+ registers[rd] = (rs1Number <= rs2Number)? 1n : 0n;
help: Performs a quiet less or equal comparison between double-precision
floating-point registers rs1 and rs2 and record the Boolean result in
integer register rd. Only signaling NaN inputs cause an Invalid
@@ -3295,14 +3252,8 @@ instructions:
let rs1Number, rs2Number, type_rs1, type_rs2;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- postoperation: |
- if (CAPI.FP.isNaN(result)) {
- registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
- } else {
- registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
- }
definition: |
- registers[rd] = (rs1Number < rs2Number) ? 1 : 0;
+ registers[rd] = (rs1Number < rs2Number) ? 1n : 0n;
help: Performs a quiet less comparison between double-precision
floating-point registers rs1 and rs2 and record the Boolean result in
integer register rd. Only signaling NaN inputs cause an Invalid
@@ -3423,7 +3374,7 @@ instructions:
registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
}
definition: |
- registers[rd] = (rs2Number > 0) ? -Math.abs(rs1Number) : +Math.abs(rs1Number);
+ result = (rs2Number > 0) ? -Math.abs(rs1Number) : +Math.abs(rs1Number);
help: Produce a result that takes all bits except the sign bit from rs1.
The result's sign bit is opposite of rs2's sign bit.
@@ -3449,7 +3400,7 @@ instructions:
definition: |
let a = rs1Number < 0;
let b = rs2Number < 0;
- registers[rd] = a ^ b ? -Math.abs(rs1Number) : Math.abs(rs1Number);
+ result = a ^ b ? -Math.abs(rs1Number) : Math.abs(rs1Number);
help: Produce a result that takes all bits except the sign bit from rs1.
The result's sign bit is XOR of sign bit of rs1 and rs2.
@@ -3470,9 +3421,8 @@ instructions:
optional: true
order: 3
preoperation: |
- let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ let result, rs1Number, type_rs1;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
- [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
postoperation: |
if (CAPI.FP.isNaN(result)) {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
@@ -3481,7 +3431,7 @@ instructions:
}
definition: |
if (rs1Number >= 0) {
- registers[rd] = Math.sqrt(rs1Number);
+ result = Math.sqrt(rs1Number);
} else {
CAPI.VALIDATION.raise(
"Square root of a negative number is not allowed."
@@ -3637,7 +3587,10 @@ instructions:
- field: rs2
type: DFP-Reg
definition: |
- CAPI.MEM.write(registers[rs1] + imm, 8, registers[rs2], rs2, 'float64');
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 8))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 8, registers[rs2], rs2, 'float64', false);
help: Store a double-precision value from the floating-point registers to
memory.
@@ -3701,40 +3654,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.
+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.
pseudoinstructions:
# Make sure the definitions correspond with those in the RISC-V ASM manual (TODO: Check these!)
@@ -3760,9 +3713,8 @@ pseudoinstructions:
- field: off
type: offset_bytes
definition: |
- bge reg1, x0, off;
- help: Take the branch if the value in register rs1 is greater or equal to
- 0.
+ bge rs1, x0, off;
+ help: Take the branch if the value in register rs1 is greater or equal to 0.
- name: bgt
fields:
@@ -3887,13 +3839,13 @@ pseudoinstructions:
type: imm-unsigned
definition: |
no_ret_op{
- tmp = Field.2.(31,0).int;
- tmp_pc_offset = (reg.pc - 4) & 0xFFF;
+ tmp = Field.2.(31,0).int - (reg.pc - 4);
tmp_low = tmp & 0x00000FFF;
- tmp_hi = tmp >> 12;
+ tmp_low = tmp_low>0x7FF? tmp_low - 0x1000 : tmp_low;
+ tmp_hi = (tmp - tmp_low) >> 12;
};
auipc rd, op{tmp_hi};
- addi rd, rd, op{tmp_low - (tmp_pc_offset)};
+ addi rd, rd, op{tmp_low};
- name: li
fields:
@@ -4111,13 +4063,13 @@ interrupts:
CAPI.SYSCALL.read('a0', 'char');
break;
}
-
CAPI.INTERRUPTS.clearHighlight();
+ CAPI.STACK.endFrame();
custom: |
CAPI.INTERRUPTS.globalDisable();
CAPI.INTERRUPTS.setKernelMode();
- registers.epc = registers.pc;
+ registers.mepc = CAPI.REG.read("pc"); // get "real" PC (next instruction)
// jump to handler
if (registers.mtvec & 1n) { // vectored mode
@@ -4134,7 +4086,6 @@ interrupts:
return null;
is_enabled: |
- if (!(registers.mstatus & 2n ** 3n)) return false; // MIE
switch (type) {
case InterruptType.Software:
case InterruptType.EnvironmentCall:
@@ -4147,7 +4098,7 @@ interrupts:
return false;
is_global_enabled: |
- return !(registers.mstatus & 2n ** 3n); // MIE
+ return !!(registers.mstatus & 2n ** 3n); // MIE
enable: |
switch (type) {
diff --git a/architecture/RISCV/RV64IMFD.yml b/architecture/RISCV/RV64IMFD.yml
index e358d6212..5efea7a0a 100644
--- a/architecture/RISCV/RV64IMFD.yml
+++ b/architecture/RISCV/RV64IMFD.yml
@@ -6,9 +6,9 @@ version: 2.0.0
config:
name: RV64
- word_size: 32 # In RV64, the word size is also 32 bits
+ word_size: 32 # In RV64, word size is also 32 bits
byte_size: 8
- description: RISC-V is an instruction set architecture (ISA) based on the RISC type and its hardware is free. This architecture was created in 2010 at the University of California, Berkeley.
+ description: RISC-V is a free and open standard ISA (Instruction Set Architecture) based on RISC (Reduced Instruction Set Computer) principles. It was created in 2010 at the University of California, Berkeley.
endianness: big_endian
memory_alignment: true
main_function: main
@@ -46,6 +46,9 @@ extensions:
Zicsr:
description: "RV32/RV64 Zicsr Standard Extension"
type: extension
+ Priv:
+ description: "RV32/RV64 Privileged instructions"
+ type: extension
components:
- name: Control registers
@@ -53,7 +56,7 @@ components:
double_precision: false
elements:
- name:
- - PC
+ - pc
nbits: 64
value: 0
default_value: 0
@@ -62,6 +65,90 @@ components:
- read
- write
- program_counter
+ - name:
+ - mepc
+ nbits: 64
+ value: 0
+ encoding: 1
+ default_value: 0
+ properties:
+ - read
+ - write
+ - exception_program_counter
+ - name:
+ - mcause
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0x342
+ properties:
+ - read
+ - write
+
+ - name:
+ - mtvec
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 2
+ properties:
+ - read
+ - write
+ - name:
+ - mstatus
+ nbits: 64
+ value: 8
+ default_value: 8
+ encoding: 3
+ properties:
+ - read
+ - write
+ - name:
+ - mip
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 4
+ properties:
+ - read
+ - write
+ - name:
+ - mie
+ nbits: 64
+ value: 0x00000888
+ default_value: 0x00000888 # MEIE + MTIE + MSIE
+ encoding: 5
+ properties:
+ - read
+ - write
+ - name:
+ - mscratch
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 6
+ properties:
+ - read
+ - write
+ - name:
+ - mtime
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 7
+ properties:
+ - read
+ - write
+ - name:
+ - mtimecmp
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 8
+ properties:
+ - read
+ - write
+
- name: Integer registers
type: int_registers
double_precision: false
@@ -80,8 +167,8 @@ components:
- x1
- ra
nbits: 64
- value: 18446744073709551615
- default_value: 18446744073709551615
+ value: -1
+ default_value: -1
encoding: 1
properties:
- read
@@ -90,8 +177,8 @@ components:
- x2
- sp
nbits: 64
- value: 268435452
- default_value: 268435452
+ value: 0x0FFFFFFC
+ default_value: 0x0FFFFFFC
encoding: 2
properties:
- read
@@ -402,6 +489,7 @@ components:
properties:
- read
- write
+
- name: Floating point registers
type: fp_registers
double_precision: true
@@ -1403,8 +1491,8 @@ instructions:
- field: funct3
value: "000"
definition: |
- if (registers[rs1] === registers[rs2])
- registers["PC"] = registers["PC"] + imm;
+ if (registers[rs1] === registers[rs2])
+ registers.pc = registers.pc + imm;
help: Take the branch if registers rs1 and rs2 are equal.
- name: bge
@@ -1416,7 +1504,7 @@ instructions:
value: "101"
definition: |
if (CAPI.FP.uint2int(registers[rs1]) >= CAPI.FP.uint2int(registers[rs2]))
- registers["PC"] = registers["PC"] + imm;
+ registers.pc = registers.pc + imm;
help: Take the branch if registers rs1 is greater than or equal to rs2,
using signed comparison.
@@ -1428,8 +1516,8 @@ instructions:
- field: funct3
value: "111"
definition: |
- if (CAPI.FP.int2uint(registers[rs1]) > CAPI.FP.int2uint(registers[rs2]))
- registers["PC"] = registers["PC"] + imm;
+ if (CAPI.FP.int2uint(registers[rs1]) >= CAPI.FP.int2uint(registers[rs2]))
+ registers.pc = registers.pc + imm;
help: Take the branch if registers rs1 is greater than or equal to rs2,
using unsigned comparison.
@@ -1442,9 +1530,8 @@ instructions:
value: "100"
definition: |
if (CAPI.FP.uint2int(registers[rs1]) < CAPI.FP.uint2int(registers[rs2]))
- registers["PC"] = registers["PC"] + imm;
- help: Take the branch if registers rs1 is less than rs2, using signed
- comparison.
+ registers.pc = registers.pc + imm;
+ help: Take the branch if registers rs1 is less than rs2, using signed comparison.
- name: bltu
template: B
@@ -1455,9 +1542,8 @@ instructions:
value: "110"
definition: |
if (CAPI.FP.int2uint(registers[rs1]) < CAPI.FP.int2uint(registers[rs2]))
- registers["PC"] = registers["PC"] + imm;
- help: Take the branch if registers rs1 is less than rs2, using unsigned
- comparison.
+ registers.pc = registers.pc + imm;
+ help: Take the branch if registers rs1 is less than rs2, using unsigned comparison.
- name: bne
template: B
@@ -1467,8 +1553,8 @@ instructions:
- field: funct3
value: "001"
definition: |
- if (registers[rs1] !== registers[rs2])
- registers["PC"] = registers["PC"] + imm;
+ if (registers[rs1] !== registers[rs2])
+ registers.pc = registers.pc + imm;
help: Take the branch if registers rs1 and rs2 are not equal.
# I-type instructions
@@ -1521,8 +1607,7 @@ instructions:
value: "111"
definition: |
registers[rd] = registers[rs1] & CAPI.FP.int2uint(imm);
- help: Performs bitwise AND on register rs1 and the sign-extended 12-bit
- immediate and place the result in rd.
+ help: Performs bitwise AND on register rs1 and the sign-extended 12-bit immediate and place the result in rd.
- name: jalr
template: I-Offset
@@ -1533,9 +1618,11 @@ instructions:
- field: funct3
value: "000"
definition: |
- registers[rd] = registers["PC"] + 4n;
- registers["PC"] = (registers[rs1] + imm) & ~1n;
- CAPI.STACK.endFrame();
+ registers[rd] = registers.pc + 4n;
+ const pc = registers[rs1] + imm;
+ registers.pc = pc & ~1n;
+ if (BigInt.asIntN(64, pc) === -1n) CAPI.SYSCALL.exit();
+ else CAPI.STACK.endFrame();
help: Jump to address and place return address in rd.
- name: lb
@@ -1547,9 +1634,11 @@ instructions:
- field: funct3
value: "000"
definition: |
- registers[rd] = CAPI.MEM.read(imm + registers[rs1], 1, rd);
-
+ let addr = registers[rs1] + imm;
+ const result = CAPI.MEM.read(addr, 1, rd, false);
+ 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
template: I-Offset
type: Memory access
@@ -1560,9 +1649,10 @@ instructions:
value: "100"
definition: |
let addr = CAPI.FP.int2uint(registers[rs1]) + imm;
- registers[rd] = CAPI.MEM.read(addr, 1, rd);
- registers[rd] = CAPI.FP.int2uint(registers[rd]);
+ let result = CAPI.MEM.read(addr, 1, rd, false);
+ registers[rd] = CAPI.FP.int2uint(result);
help: Loads a 8-bit value from memory and zero-extends this to XLEN bits before storing it in register rd.
+
- name: lh
template: I-Offset
type: Memory access
@@ -1572,9 +1662,13 @@ instructions:
- field: funct3
value: "001"
definition: |
- registers[rd] = CAPI.MEM.read(imm + registers[rs1], 2, rd);
-
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 2))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ const result = CAPI.MEM.read(addr, 2, rd, false);
+ 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
template: I-Offset
type: Memory access
@@ -1584,10 +1678,13 @@ instructions:
- field: funct3
value: "101"
definition: |
- let addr = CAPI.FP.int2uint(registers[rs1], 32) + imm;
- registers[rd] = CAPI.MEM.read(addr, 2, rd);
- registers[rd] = CAPI.FP.int2uint(registers[rd]);
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 2))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ let result = CAPI.MEM.read(addr, 2, rd, false);
+ registers[rd] = CAPI.FP.int2uint(result);
help: Loads a 16-bit value from memory and zero-extends this to XLEN bits before storing it in register rd.
+
- name: lw
template: I-Offset
type: Memory access
@@ -1597,10 +1694,11 @@ instructions:
- field: funct3
value: "010"
definition: |
- let addr = CAPI.FP.int2uint(registers[rs1], 32) + imm;
- registers[rd] = CAPI.MEM.read(addr, 4, rd);
- help: Loads a 32-bit value from memory and sign-extends this to XLEN bits
- before storing it in register rd.
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[rd] = CAPI.MEM.read(addr, 4, rd, false);
+ help: Loads a 32-bit value from memory and sign-extends this to XLEN bits before storing it in register rd.
- name: lwu
template: I-Offset
@@ -1611,11 +1709,12 @@ instructions:
- field: funct3
value: "110"
definition: |
- var addr = CAPI.FP.int2uint(registers[rs1]) + imm;
- registers[rd] = CAPI.MEM.read(addr, 4, rd);
- registers[rd] = CAPI.FP.int2uint(registers[rd]);
- help: Loads a 32-bit value from memory and zero-extends this to 64 bits
- before storing it in register rd.
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ result = CAPI.MEM.read(addr, 4, rd, false);
+ registers[rd] = CAPI.FP.int2uint(result);
+ help: Loads a 32-bit value from memory and zero-extends this to 64 bits before storing it in register rd.
- name: ld
template: I-Offset
@@ -1626,8 +1725,10 @@ instructions:
- field: funct3
value: "011"
definition: |
- let addr = CAPI.FP.int2uint(registers[rs1]) + imm;
- registers[rd] = CAPI.MEM.read(addr, 8, rd);
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 8))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[rd] = CAPI.MEM.read(addr, 8, rd, false);
help: Loads a 64-bit value from memory into register rd for RV64I.
- name: ori
@@ -1640,8 +1741,8 @@ instructions:
value: "110"
definition: |
registers[rd] = registers[rs1] | imm;
-
help: Performs bitwise OR on register rs1 and the sign-extended 12-bit immediate and place the result in rd.
+
- name: slli
# In RV64, slli is a 6-bit shift, so we need to slightly modify the template
template: I-Shift
@@ -1658,8 +1759,7 @@ instructions:
startbit: 25
definition: |
if (shamt > 0) registers[rd] = CAPI.FP.int2uint(registers[rs1] << shamt);
- help: Performs logical left shift on the value in register rs1 by the
- shift amount held in the lower 5 bits of the immediate.
+ help: Performs logical left shift on the value in register rs1 by the shift amount held in the lower 5 bits of the immediate.
- name: slliw
template: I-Shift
@@ -1677,8 +1777,7 @@ instructions:
registers[rd] = temp & 0x80000000n ? temp | 0xFFFFFFFF00000000n : temp;
registers[rd] = CAPI.FP.int2uint(registers[rd]);
}
- help: Performs logical left shift on the 32-bit of value in register rs1
- by the shift amount held in the lower 5 bits of the immediate.
+ help: Performs logical left shift on the 32-bit of value in register rs1 by the shift amount held in the lower 5 bits of the immediate.
- name: slti
template: I
@@ -1689,9 +1788,9 @@ instructions:
- field: funct3
value: "010"
definition: |
- registers[rd] = (CAPI.FP.uint2int(registers[rs1]) < CAPI.FP.uint2int(imm)) ? 1 : 0;
-
+ registers[rd] = (CAPI.FP.uint2int(registers[rs1]) < CAPI.FP.uint2int(imm)) ? 1n : 0n;
help: Place the value 1 in register rd if register rs1 is less than the signextended immediate when both are treated as signed numbers, else 0 is written to rd.
+
- name: sltiu
template: I
type: Logic
@@ -1701,8 +1800,9 @@ instructions:
- field: funct3
value: "011"
definition: |
- registers[rd] = (CAPI.FP.int2uint(registers[rs1]) < CAPI.FP.int2uint(imm)) ? 1: 0;
+ registers[rd] = (CAPI.FP.int2uint(registers[rs1]) < CAPI.FP.int2uint(imm)) ? 1n : 0n;
help: Place the value 1 in register rd if register rs1 is less than the immediate when both are treated as unsigned numbers, else 0 is written to rd.
+
- name: srai
template: I-Shift
type: Arithmetic integer
@@ -1715,8 +1815,7 @@ instructions:
value: "0100000"
definition: |
if (shamt > 0) registers[rd] = (BigInt.asIntN(64, registers[rs1]) >> shamt);
- help: Performs arithmetic right shift on the value in register rs1 by the
- shift amount held in the lower 5 bits of the immediate.
+ help: Performs arithmetic right shift on the value in register rs1 by the shift amount held in the lower 5 bits of the immediate.
- name: sraiw
template: I-Shift
@@ -1733,8 +1832,7 @@ instructions:
const temp = BigInt.asIntN(32, BigInt(registers[rs1])) >> BigInt(shamt);
registers[rd] = CAPI.FP.int2uint(temp);
}
- help: Performs arithmetic right shift on the 32-bit of value in register
- rs1 by the shift amount held in the lower 5 bits of the immediate.
+ help: Performs arithmetic right shift on the 32-bit of value in register rs1 by the shift amount held in the lower 5 bits of the immediate.
- name: srli
template: I-Shift
@@ -1746,9 +1844,8 @@ instructions:
- field: funct7
value: "0000000"
definition: |
- if (shamt > 0) rd = (rs1 >> shamt);
- help: Performs logical right shift on the value in register rs1 by the
- shift amount held in the lower 5 bits of the immediate.
+ if (shamt > 0) registers[rd] = CAPI.FP.int2uint(registers[rs1] >> shamt);
+ help: Performs logical right shift on the value in register rs1 by the shift amount held in the lower 5 bits of the immediate.
- name: srliw
template: I-Shift
@@ -1763,12 +1860,11 @@ instructions:
definition: |
if (shamt > 0) {
const temp =
- ((BigInt(registers[rs1]) & 0xffffffffn) >> BigInt(shamt)) & 0xffffffffn;
+ ((registers[rs1] & 0xffffffffn) >> shamt) & 0xffffffffn;
registers[rd] = temp & 0x80000000n ? temp | 0xffffffff00000000n : temp;
registers[rd] = CAPI.FP.int2uint(registers[rd]);
}
- help: Performs logical right shift on the 32-bit of value in register rs1
- by the shift amount held in the lower 5 bits of the immediate.
+ help: Performs logical right shift on the 32-bit of value in register rs1 by the shift amount held in the lower 5 bits of the immediate.
- name: xori
template: I
@@ -1799,8 +1895,8 @@ instructions:
- field: opcode
value: "1101111"
definition: |
- registers[rd] = registers["PC"] + 4n;
- registers["PC"] = registers["PC"] + imm;
+ registers[rd] = registers.pc + 4n;
+ registers.pc = registers.pc + imm;
CAPI.STACK.beginFrame();
help: Jump to address and place return address in rd.
@@ -1824,8 +1920,7 @@ instructions:
definition: |
registers[rd] = registers[rs2] + registers[rs1];
help: Adds the registers rs1 and rs2 and stores the result in rd.
- Arithmetic overflow is ignored and the result is simply the low XLEN
- bits of the result.
+ Arithmetic overflow is ignored and the result is simply the low XLEN bits of the result.
- name: addw
template: R
@@ -1855,8 +1950,8 @@ instructions:
value: "111"
definition: |
registers[rd] = registers[rs1] & registers[rs2];
-
help: Performs bitwise AND on registers rs1 and rs2 and place the result in rd.
+
- name: or
template: R
fields:
@@ -1868,8 +1963,8 @@ instructions:
value: "110"
definition: |
registers[rd] = registers[rs1] | registers[rs2];
-
help: Performs bitwise OR on registers rs1 and rs2 and place the result in rd.
+
- name: sll
template: R
fields:
@@ -1882,8 +1977,7 @@ instructions:
definition: |
const shiftAmount = registers[rs2] & 0x1Fn;
registers[rd] = (registers[rs1] << shiftAmount) & 0xFFFFFFFFn;
- help: Performs logical left shift on the value in register rs1 by the
- shift amount held in the lower 5 bits of register rs2.
+ help: Performs logical left shift on the value in register rs1 by the shift amount held in the lower 5 bits of register rs2.
- name: sllw
template: R
@@ -1912,9 +2006,9 @@ instructions:
- field: funct3
value: "010"
definition: |
- registers[rd] = (CAPI.FP.uint2int(registers[rs1]) < CAPI.FP.uint2int(registers[rs2])) ? 1 : 0;
-
+ registers[rd] = (CAPI.FP.uint2int(registers[rs1]) < CAPI.FP.uint2int(registers[rs2])) ? 1n : 0n;
help: Place the value 1 in register rd if register rs1 is less than register rs2 when both are treated as signed numbers, else 0 is written to rd.
+
- name: sltu
template: R
fields:
@@ -1926,8 +2020,10 @@ instructions:
value: "011"
definition: |
registers[rd] = ((registers[rs1] & 0xFFFFFFFFn) < (registers[rs2] & 0xFFFFFFFFn)) ? 1n : 0n;
+ help: Place the value 1 in register rd if register rs1 is less than
+ register rs2 when both are treated as unsigned numbers, else 0 is
+ written to rd.
- help: Place the value 1 in register rd if register rs1 is less than register rs2 when both are treated as unsigned numbers, else 0 is written to rd.
- name: sra
template: R
fields:
@@ -2016,8 +2112,8 @@ instructions:
- field: funct3
value: "000"
definition: |
- const temp = (BigInt(rs1) + BigInt(rs2)) & 0xFFFFFFFFn;
- rd = temp & 0x80000000n ? temp | 0xFFFFFFFF00000000n : temp;
+ const temp = (registers[rs1] + registers[rs2]) & 0xFFFFFFFFn;
+ registers[rd] = temp & 0x80000000n ? temp | 0xFFFFFFFF00000000n : temp;
help: Subtract the 32-bit of registers rs1 and 32-bit of register rs2 and
stores the result in rd. Arithmetic overflow is ignored and the low
32-bits of the result is sign-extended to 64-bits and written to the
@@ -2034,8 +2130,7 @@ instructions:
value: "100"
definition: |
registers[rd] = (registers[rs1] ^ registers[rs2]);
- help: Performs bitwise XOR on registers rs1 and rs2 and place the result
- in rd.
+ help: Performs bitwise XOR on registers rs1 and rs2 and place the result in rd.
# S-type instructions
# 31-25 24-20 19-15 14-12 11-7 6-0
@@ -2053,7 +2148,7 @@ instructions:
- field: funct3
value: "000"
definition: |
- CAPI.MEM.write(registers[rs1] + imm, 1, BigInt.asUintN(8, registers[rs2]), rs2, 'byte');
+ CAPI.MEM.write(registers[rs1] + imm, 1, BigInt.asUintN(8, registers[rs2]), rs2, 'byte', false);
help: Store 8-bit, values from the low bits of register rs2 to memory.
- name: sh
@@ -2064,8 +2159,10 @@ instructions:
- field: funct3
value: "001"
definition: |
- CAPI.MEM.write(imm + registers[rs1], 2, BigInt.asUintN(16, registers[rs2]), rs2, 'half');
-
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 2))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 2, BigInt.asUintN(16, registers[rs2]), rs2, 'half', false);
help: Store 16-bit, values from the low bits of register rs2 to memory.
# The check for the
@@ -2077,8 +2174,10 @@ instructions:
- field: funct3
value: "010"
definition: |
- CAPI.MEM.write(imm + registers[rs1], 4, BigInt.asUintN(32, registers[rs2]), rs2, 'word');
-
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 4, BigInt.asUintN(32, registers[rs2]), rs2, 'word', false);
help: Store 32-bit, values from the low bits of register rs2 to memory.
- name: sd
@@ -2089,12 +2188,16 @@ instructions:
- field: funct3
value: "011"
definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 8))
+ CAPI.VALIDATION.raise('The memory must be aligned');
CAPI.MEM.write(
- imm + registers[rs1],
+ addr,
8,
BigInt.asUintN(64, registers[rs2]),
rs2,
- "double",
+ "float64",
+ false,
);
help: Loads a 64-bit value from memory into register rd for RV64I.
@@ -2114,9 +2217,9 @@ instructions:
- field: imm
type: offset_bytes
definition: |
- registers[rd] = registers["PC"] + (imm << 12n);
-
+ registers[rd] = registers.pc + (imm << 12n);
help: Build pc-relative addresses and uses the U-type format. AUIPC forms a 32-bit offset from the 20-bit U-immediate, filling in the lowest 12 bits with zeros, adds this offset to the pc, then places the result in register rd.
+
- name: lui
template: U
fields:
@@ -2144,42 +2247,8 @@ instructions:
value: "0000000000000000000000000"
preoperation: 'let [fa0Value, fa0Type] = CAPI.ARCH.toJSNumberD(registers["fa0"]);'
definition: |
- switch (registers["a7"]) {
- case 1n:
- CAPI.SYSCALL.print(registers["a0"], 'int32');
- break;
- case 2n:
- case 3n:
- CAPI.SYSCALL.print(fa0Value, 'float');
- break;
- case 4n:
- CAPI.SYSCALL.print(registers["a0"], 'string');
- break;
- case 5n:
- CAPI.SYSCALL.read('registers["a0"]', 'int32');
- break;
- case 6n:
- CAPI.SYSCALL.read(fa0Value, 'float');
- break;
- case 7n:
- CAPI.SYSCALL.read(fa0Value, 'double');
- break;
- case 8n:
- CAPI.SYSCALL.read('registers["a0"]', 'string', 'registers["a1"]');
- break;
- case 9n:
- CAPI.SYSCALL.sbrk('registers["a0"]', 'registers["a0"]');
- break;
- case 10n:
- CAPI.SYSCALL.exit();
- break;
- case 11n:
- CAPI.SYSCALL.print(registers["a0"], 'char');
- break;
- case 12n:
- CAPI.SYSCALL.read('registers["a0"]', 'char');
- break;
- }
+ CAPI.INTERRUPTS.create(InterruptType.EnvironmentCall);
+ CAPI.STACK.beginFrame();
help: Make a request to the supporting execution environment. When
executed in U-mode, S-mode, or M-mode, it generates an
environment-call-from-U-mode exception, environment-call-from-S-mode
@@ -2231,7 +2300,7 @@ instructions:
if (registers[rs2] != 0) {
registers[rd] = BigInt.asIntN(
32,
- (BigInt.asIntN(32, registers[rs1]) / BigInt.asIntN(32, registers[rs2]))
+ (BigInt.asIntN(32, BigInt(registers[rs1])) / BigInt.asIntN(32, BigInt(registers[rs2])))
);
}
else CAPI.VALIDATION.raise('Division by zero not allowed');
@@ -2248,10 +2317,11 @@ instructions:
- field: funct3
value: "101"
definition: |
- if (registers[rs2] != 0) {
+ const div = registers[rs2]
+ if (div != 0) {
registers[rd] = BigInt.asIntN(
32,
- (BigInt.asUintN(32, registers[rs1]) / BigInt.asUintN(32, registers[rs2]))
+ (BigInt.asUintN(32, registers[rs1]) / BigInt.asUintN(32, div))
);
}
else CAPI.VALIDATION.raise('Division by zero not allowed');
@@ -2282,7 +2352,7 @@ instructions:
- field: funct3
value: "001"
definition: |
- registers[rd] = BigInt.asIntN(
+ registers[rd] = BigInt.asUintN(
32,
BigInt.asIntN(
64,
@@ -2379,12 +2449,14 @@ instructions:
- field: rd
type: SFP-Reg
definition: |
- registers[rd] = CAPI.MEM.read(registers[rs1] + imm, 4, rd);
-
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[rd] = CAPI.MEM.read(addr, 4, rd, false);
postoperation: |
registers[rd] = CAPI.ARCH.NaNBox(registers[rd]);
-
help: Load a single-precision floating-point value from memory into floating-point register rd.
+
- name: fadd.s
template: R-Floating
fields:
@@ -2407,11 +2479,10 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
}
-
definition: |
result = rs1Number + rs2Number;
-
help: Perform single-precision floating-point addition.
+
- name: fclass.s
template: R-Floating
fields:
@@ -2439,7 +2510,12 @@ instructions:
a.slice(1, 9),
a.slice(10),
));
- help: Examines the value in floating-point register rs1 and writes to integer register rd a 10-bit mask that indicates the class of the floating-point number. The corresponding bit in rd will be set if the property is true and clear otherwise. All other bits in rd are cleared. Note that exactly one bit in rd will be set.
+ help: Examines the value in floating-point register rs1 and writes to
+ integer register rd a 10-bit mask that indicates the class of the
+ floating-point number. The corresponding bit in rd will be set if the
+ property is true and clear otherwise. All other bits in rd are cleared.
+ Note that exactly one bit in rd will be set.
+
- name: fcvt.s.w
template: R-IntToFloat
fields:
@@ -2455,11 +2531,11 @@ instructions:
optional: true
order: 3
postoperation: |
- registers[rd] = CAPI.ARCH.toBigInt(registers[rd],'NaNBfloat32_64');
+ registers[rd] = CAPI.ARCH.toBigInt(result,'NaNBfloat32_64');
definition: |
- registers[rd] = CAPI.FP.uint2int(registers[rs1])
-
+ result = CAPI.FP.uint2int(registers[rs1])
help: Converts a 32-bit signed integer, in integer register rs1 into a floating-point number in floating-point register rd.
+
- name: fcvt.s.wu
template: R-IntToFloat
fields:
@@ -2476,8 +2552,8 @@ instructions:
order: 3
definition: |
registers[rd] = CAPI.FP.int2uint(registers[rs1])
-
help: Converts a 32-bit unsigned integer, in integer register rs1 into a floating-point number in floating-point register rd.
+
- name: fcvt.w.s
template: R-FloatToInt
fields:
@@ -2502,11 +2578,10 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
}
-
definition: |
result = parseInt(registers[rs1]);
-
help: Convert a floating-point number in floating-point register rs1 to a signed 32-bit in integer register rd.
+
- name: fcvt.wu.s
template: R-FloatToInt
fields:
@@ -2533,8 +2608,8 @@ instructions:
}
definition: |
registers[rd] = CAPI.FP.int2uint(parseInt(rs1Number));
-
help: Convert a floating-point number in floating-point register rs1 to a signed 32-bit in unsigned integer register rd.
+
- name: fdiv.s
template: R-Floating
fields:
@@ -2560,8 +2635,8 @@ instructions:
definition: |
if (rs2Number != 0) { result = rs1Number / rs2Number; }
else CAPI.VALIDATION.raise('Division by registers[zero] not allowed');
-
help: Perform single-precision floating-point division.
+
- name: feq.s
template: R-Floating
fields:
@@ -2574,20 +2649,16 @@ instructions:
- field: rd
type: INT-Reg
preoperation: |
- let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ let rs1Number, rs2Number, type_rs1, type_rs2;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- postoperation: |
- if (CAPI.FP.isNaN(result)) {
- registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
- } else {
- registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
- }
-
definition: |
- result = (rs1Number === rs2Number) ? 1 : 0;
+ registers[rd] = (rs1Number === rs2Number)? 1n : 0n;
+ help: Performs a quiet equal comparison between floating-point registers
+ rs1 and rs2 and record the Boolean result in integer register rd. Only
+ signaling NaN inputs cause an Invalid Operation exception. The result is
+ 0 if either operand is NaN.
- help: Performs a quiet equal comparison between floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
- name: fle.s
template: R-Floating
fields:
@@ -2600,20 +2671,16 @@ instructions:
- field: rd
type: INT-Reg
preoperation: |
- let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ let rs1Number, rs2Number, type_rs1, type_rs2;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- postoperation: |
- if (CAPI.FP.isNaN(result)) {
- registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
- } else {
- registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
- }
-
definition: |
- result = (rs1Number <= rs2Number) ? 1 : 0;
+ registers[rd] = (rs1Number <= rs2Number)? 1n : 0n;
+ help: Performs a quiet equal comparison between floating-point registers
+ rs1 and rs2 and record the Boolean result in integer register rd. Only
+ signaling NaN inputs cause an Invalid Operation exception. The result is
+ 0 if either operand is NaN.
- help: Performs a quiet less or equal comparison between floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
- name: flt.s
template: R-Floating
fields:
@@ -2626,20 +2693,16 @@ instructions:
- field: rd
type: INT-Reg
preoperation: |
- let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ let rs1Number, rs2Number, type_rs1, type_rs2;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- postoperation: |
- if (CAPI.FP.isNaN(result)) {
- registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
- } else {
- registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
- }
-
definition: |
- result = (rs1Number < rs2Number) ? 1 : 0;
+ registers[rd] = (rs1Number < rs2Number)? 1n : 0n;
+ help: Performs a quiet less or equal comparison between floating-point
+ registers rs1 and rs2 and record the Boolean result in integer register
+ rd. Only signaling NaN inputs cause an Invalid Operation exception. The
+ result is 0 if either operand is NaN.
- help: Performs a quiet less comparison between floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
- name: fmax.s
template: R-Floating
fields:
@@ -2659,11 +2722,10 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
}
-
definition: |
result = Math.max(rs1Number, rs2Number);
-
help: Write the larger of single precision data in rs1 and rs2 to rd.
+
- name: fmin.s
template: R-Floating
fields:
@@ -2685,8 +2747,8 @@ instructions:
}
definition: |
result = Math.min(rs1Number, rs2Number);
-
help: Write the smaller of single precision data in rs1 and rs2 to rd.
+
- name: fmul.s
template: R-Floating
fields:
@@ -2711,8 +2773,8 @@ instructions:
}
definition: |
result = rs2Number * rs1Number;
-
help: Perform single-precision floating-point multiplication.
+
- name: fmv.w.x
template: R-IntToFloat
fields:
@@ -2733,11 +2795,12 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
}
-
definition: |
result = CAPI.FP.uint2float32(rs1Number);
+ help: Move the single-precision value encoded in IEEE 754-2008 standard
+ encoding from the lower 32 bits of integer register rs1 to the
+ floating-point register rd.
- help: Move the single-precision value encoded in IEEE 754-2008 standard encoding from the lower 32 bits of integer register rs1 to the floating-point register rd.
- name: fmv.x.w
template: R-FloatToInt
fields:
@@ -2761,8 +2824,10 @@ instructions:
registers[rs1] = CAPI.ARCH.toBigInt(rs1Number, type_rs1);
definition: |
result = CAPI.FP.float322uint(rs1Number);
+ help: Move the single-precision value in floating-point register rs1
+ represented in IEEE 754-2008 encoding to the lower 32 bits of integer
+ register rd.
- help: Move the single-precision value in floating-point register rs1 represented in IEEE 754-2008 encoding to the lower 32 bits of integer register rd.
- name: fsgnj.s
template: R-Floating
fields:
@@ -2784,8 +2849,8 @@ instructions:
}
definition: |
result = (rs2Number >= 0) ? Math.abs(rs1Number) : -Math.abs(rs1Number);
-
help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is rs2's sign bit.
+
- name: fsgnjn.s
template: R-Floating
fields:
@@ -2808,6 +2873,7 @@ instructions:
definition: |
result = (rs2Number <= 0) ? Math.abs(rs1Number) : -Math.abs(rs1Number);
help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is rs2's sign bit.
+
- name: fsgnjx.s
template: R-Floating
fields:
@@ -2832,6 +2898,7 @@ instructions:
let b = rs2Number < 0;
result = a ^ b ? -Math.abs(rs1Number) : Math.abs(rs1Number);
help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is XOR of sign bit of rs1 and rs2.
+
- name: fsqrt.s
template: R-Floating
fields:
@@ -2849,25 +2916,24 @@ instructions:
optional: true
order: 3
preoperation: |
- let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ let result, rs1Number, type_rs1;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
- [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
postoperation: |
if (CAPI.FP.isNaN(result)) {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
}
-
definition: |
if (rs1Number >= 0) {
result = Math.sqrt(rs1Number);
} else {
CAPI.VALIDATION.raise(
- 'Square root of a negative number is not allowed.'
+ "Square root of a negative number is not allowed."
);
}
help: Perform single-precision square root.
+
- name: fsub.s
template: R-Floating
fields:
@@ -2890,11 +2956,10 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
}
-
definition: |
result = rs1Number - rs2Number;
+ help: Perform single-precision floating-point subtraction.
- help: Perform single-precision floating-point substraction.
- name: fmadd.s
template: R4
fields:
@@ -2911,18 +2976,17 @@ instructions:
let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(rs3);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
postoperation: |
if (CAPI.FP.isNaN(result)) {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
}
-
definition: |
result = rs1Number * rs2Number + rs3Number;
-
help: Perform single-precision fused multiply addition.
+
- name: fmsub.s
template: R4
fields:
@@ -2939,18 +3003,17 @@ instructions:
let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(rs3);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
postoperation: |
if (CAPI.FP.isNaN(result)) {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
}
-
definition: |
result = rs1Number * rs2Number - rs3Number;
-
help: Perform single-precision fused multiply addition.
+
- name: fnmadd.s
template: R4
fields:
@@ -2967,18 +3030,17 @@ instructions:
let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(rs3);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
postoperation: |
if (CAPI.FP.isNaN(result)) {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
}
-
definition: |
result = -rs1Number * rs2Number - rs3Number;
-
help: Perform negated single-precision fused multiply addition.
+
- name: fnmsub.s
template: R4
fields:
@@ -2995,18 +3057,17 @@ instructions:
let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(rs3);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
postoperation: |
if (CAPI.FP.isNaN(result)) {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
}
-
definition: |
result = -rs1Number * rs2Number + rs3Number;
-
help: Perform negated single-precision fused multiply addition.
+
- name: fsw
template: S
fields:
@@ -3018,7 +3079,10 @@ instructions:
type: SFP-Reg
definition: |
let value = registers[rs2] & 0xFFFFFFFFn;
- CAPI.MEM.write(registers[rs1] + imm, 4, value, rs2, 'float32');
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 4, value, rs2, 'float32', false);
help: Store a single-precision value from floating-point register rs2 to memory.
D:
@@ -3040,11 +3104,12 @@ instructions:
- field: rd
type: DFP-Reg
definition: |
- if (CAPI.VALIDATION.isMisaligned(registers[rs1] + imm, 'd')) {
- CAPI.VALIDATION.raise('The memory must be aligned');
- }
- registers[rd] = CAPI.MEM.read(registers[rs1] + imm, 8, rd);
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 8))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[rd] = CAPI.MEM.read(8, 8, rd, false);
help: Load a double-precision floating-point value from memory into floating-point register rd.
+
- name: fadd.d
template: R-Double
fields:
@@ -3069,8 +3134,8 @@ instructions:
}
definition: |
result = rs1Number + rs2Number;
-
help: Perform double-precision floating-point addition.
+
- name: fclass.d
template: R-Double
fields:
@@ -3103,7 +3168,12 @@ instructions:
a.slice(1, 12),
a.slice(13),
);
- help: Examines the value in double-precision floating-point register rs1 and writes to integer register rd a 10-bit mask that indicates the class of the floating-point number. The corresponding bit in rd will be set if the property is true and clear otherwise. All other bits in rd are cleared. Note that exactly one bit in rd will be set.
+ help: Examines the value in double-precision floating-point register rs1
+ and writes to integer register rd a 10-bit mask that indicates the class
+ of the floating-point number. The corresponding bit in rd will be set if
+ the property is true and clear otherwise. All other bits in rd are
+ cleared. Note that exactly one bit in rd will be set.
+
- name: fcvt.d.s
template: R-Conversion
fields:
@@ -3134,8 +3204,8 @@ instructions:
}
definition: |
result = rs1Number; // TODO: This doesn't seem right, check the RISC-V manual
-
help: Converts double floating-point register in rs1 into a double floating-point number in floating-point register rd.
+
- name: fcvt.d.w
template: R-Conversion
fields:
@@ -3155,14 +3225,14 @@ instructions:
- field: rs1
type: INT-Reg
preoperation: |
- let result, rs1Number, type_rs1;
- [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ let result, rs1Number;
+ rs1Number = registers[rs1];
postoperation: |
registers[rd] = CAPI.ARCH.toBigInt(result, 'float64');
definition: |
result = CAPI.FP.uint2int(rs1Number);
-
help: Converts a 32-bit signed integer, in integer register rs1 into a double-precision floating-point number in floating-point register rd.
+
- name: fcvt.d.wu
template: R-Conversion
fields:
@@ -3193,8 +3263,8 @@ instructions:
}
definition: |
result = CAPI.FP.int2uint(parseFloat(rs1Number));
-
help: Converts a 32-bit unsigned integer, in integer register rs1 into a double-precision floating-point number in floating-point register rd.
+
- name: fcvt.s.d
template: R-Conversion
fields:
@@ -3225,8 +3295,8 @@ instructions:
}
definition: |
result = rs1Number; // TODO: This doesn't seem right, check the RISC-V manual
-
help: Converts double floating-point register in rs1 into a floating-point number in floating-point register rd.
+
- name: fcvt.w.d
template: R-Conversion
fields:
@@ -3255,11 +3325,10 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
}
-
definition: |
result = CAPI.FP.int2uint(parseInt(rs1Number));
-
help: Converts a double-precision floating-point number in floating-point register rs1 to a signed 32-bit integer, in integer register rd.
+
- name: fcvt.wu.d
template: R-Conversion
fields:
@@ -3288,11 +3357,10 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
}
-
definition: |
result = CAPI.FP.int2uint(parseInt(rs1Number));
-
help: Converts a double-precision floating-point number in floating-point register rs1 to a unsigned 32-bit integer, in integer register rd.
+
- name: fdiv.d
template: R-Double
fields:
@@ -3315,10 +3383,10 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
}
-
definition: |
result = rs1Number / rs2Number;
help: Perform double-precision floating-point division.
+
- name: feq.d
template: R-Double
fields:
@@ -3331,15 +3399,16 @@ instructions:
- field: rd
type: INT-Reg
preoperation: |
- let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ let rs1Number, rs2Number, type_rs1, type_rs2;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- postoperation: |
-
definition: |
- registers[rd] = (rs1Number == rs2Number) ? 1 : 0;
+ registers[rd] = (rs1Number === rs2Number)? 1n : 0n;
+ help: Performs a quiet equal comparison between double-precision
+ floating-point registers rs1 and rs2 and record the Boolean result in
+ integer register rd. Only signaling NaN inputs cause an Invalid
+ Operation exception. The result is 0 if either operand is NaN.
- help: Performs a quiet equal comparison between double-precision floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
- name: fle.d
template: R-Double
fields:
@@ -3355,12 +3424,13 @@ instructions:
let rs1Number, rs2Number, type_rs1, type_rs2;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- postoperation: |
-
definition: |
- registers[rd] = (rs1Number <= rs2Number) ? 1 : 0;
+ registers[rd] = (rs1Number <= rs2Number)? 1n : 0n;
+ help: Performs a quiet less or equal comparison between double-precision
+ floating-point registers rs1 and rs2 and record the Boolean result in
+ integer register rd. Only signaling NaN inputs cause an Invalid
+ Operation exception. The result is 0 if either operand is NaN.
- help: Performs a quiet less or equal comparison between double-precision floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
- name: flt.d
template: R-Double
fields:
@@ -3376,12 +3446,13 @@ instructions:
let rs1Number, rs2Number, type_rs1, type_rs2;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
[rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
- postoperation: |
-
definition: |
- registers[rd] = (rs1Number < rs2Number) ? 1 : 0;
+ registers[rd] = (rs1Number < rs2Number)? 1n : 0n;
+ help: Performs a quiet less comparison between double-precision
+ floating-point registers rs1 and rs2 and record the Boolean result in
+ integer register rd. Only signaling NaN inputs cause an Invalid
+ Operation exception. The result is 0 if either operand is NaN.
- help: Performs a quiet less comparison between double-precision floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
- name: fmax.d
template: R-Double
fields:
@@ -3401,11 +3472,10 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
}
-
definition: |
result = Math.max(rs1Number, rs2Number);
-
help: Write the larger of double precision data in rs1 and rs2 to rd.
+
- name: fmin.d
template: R-Double
fields:
@@ -3425,11 +3495,10 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
}
-
definition: |
result = Math.min(rs1Number, rs2Number);
-
help: Write the smaller of double precision data in rs1 and rs2 to rd.
+
- name: fmul.d
template: R-Double
fields:
@@ -3452,11 +3521,10 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
}
-
definition: |
result = rs1Number * rs2Number;
-
help: Perform double-precision floating-point addition.
+
- name: fsgnj.d
template: R-Double
fields:
@@ -3476,10 +3544,10 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
}
-
definition: |
registers[rd] = (rs2Number > 0) ? Math.abs(rs1Number) : -Math.abs(rs1Number);
help: Perform double-precision floating-point multiplication.
+
- name: fsgnjn.d
template: R-Double
fields:
@@ -3499,11 +3567,11 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
}
-
definition: |
- registers[rd] = (rs2Number > 0) ? -Math.abs(rs1Number) : +Math.abs(rs1Number);
+ result = (rs2Number > 0) ? -Math.abs(rs1Number) : +Math.abs(rs1Number);
+ help: Produce a result that takes all bits except the sign bit from rs1.
+ The result's sign bit is opposite of rs2's sign bit.
- help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is opposite of rs2's sign bit.
- name: fsgnjx.d
template: R-Double
fields:
@@ -3523,12 +3591,13 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
}
-
definition: |
let a = rs1Number < 0;
let b = rs2Number < 0;
- registers[rd] = a ^ b ? -Math.abs(rs1Number) : Math.abs(rs1Number);
- help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is XOR of sign bit of rs1 and rs2.
+ result = a ^ b ? -Math.abs(rs1Number) : Math.abs(rs1Number);
+ help: Produce a result that takes all bits except the sign bit from rs1.
+ The result's sign bit is XOR of sign bit of rs1 and rs2.
+
- name: fsqrt.d
template: R-Double
fields:
@@ -3546,25 +3615,24 @@ instructions:
optional: true
order: 3
preoperation: |
- let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ let result, rs1Number, type_rs1;
[rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
- [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
postoperation: |
if (CAPI.FP.isNaN(result)) {
registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
}
-
definition: |
if (rs1Number >= 0) {
- registers[rd] = Math.sqrt(rs1Number);
+ result = Math.sqrt(rs1Number);
} else {
CAPI.VALIDATION.raise(
"Square root of a negative number is not allowed."
);
}
help: Perform double-precision square root.
+
- name: fsub.d
template: R-Double
fields:
@@ -3587,11 +3655,10 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
}
-
definition: |
result = rs1Number - rs2Number;
-
help: Perform double-precision floating-point addition.
+
- name: fmadd.d
template: R4-Double
fields:
@@ -3615,12 +3682,11 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
}
-
registers[rs3] = CAPI.ARCH.toBigInt(rs3Number, type_rs3);
definition: |
result = rs1Number * rs2Number + rs3Number;
-
help: Perform double-precision fused multiply addition.
+
- name: fmsub.d
template: R4-Double
fields:
@@ -3644,12 +3710,11 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
}
-
registers[rs3] = CAPI.ARCH.toBigInt(rs3Number, type_rs3);
definition: |
result = rs1Number * rs2Number - rs3Number;
-
help: Perform double-precision fused multiply subtraction.
+
- name: fnmadd.d
template: R4-Double
fields:
@@ -3673,12 +3738,11 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
}
-
registers[rs3] = CAPI.ARCH.toBigInt(rs3Number, type_rs3);
definition: |
result = -rs1Number * rs2Number - rs3Number;
-
help: Perform negated double-precision fused multiply addition.
+
- name: fnmsub.d
template: R4-Double
fields:
@@ -3702,12 +3766,11 @@ instructions:
} else {
registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
}
-
registers[rs3] = CAPI.ARCH.toBigInt(rs3Number, type_rs3);
definition: |
result = -rs1Number * rs2Number + rs3Number;
-
help: Perform negated double-precision fused multiply subtraction.
+
- name: fsd
template: S
fields:
@@ -3718,57 +3781,106 @@ instructions:
- field: rs2
type: DFP-Reg
definition: |
- let val = BigInt("0x" + CAPI.FP.split_double(registers[rs2], 0));
- CAPI.MEM.write(registers[rs1] + imm, 4, val, rs2);
- val = BigInt("0x" + CAPI.FP.split_double(registers[rs2], 1));
- CAPI.MEM.write(registers[rs1] + imm + 4n, 4, val, rs2);
- CAPI.MEM.addHint(registers[rs1] + imm, "float64", 64);
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 8))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 8, registers[rs2], rs2, 'float64', false);
help: Store a double-precision value from the floating-point registers to memory.
- # Zicsr:
- # _____ _
- # |__ /(_) ___ ___ _ __
- # / / | | / __|/ __|| '__|
- # / /_ | || (__ \__ \| |
- # /____||_| \___||___/|_|
- # RV32/64 Zicsr Standard Extension
-
- # TODO: Implement CSR instructions
+ Priv:
+ # ____ _
+ # | _ \ _ __ (_)__ __
+ # | |_) || '__|| |\ \ / /
+ # | __/ | | | | \ V /
+ # |_| |_| |_| \_/
+ # RV32/64 Privileged instructions
- Zifencei:
- # _____ _ __ _
- # |__ /(_) / _| ___ _ __ ___ ___ (_)
- # / / | || |_ / _ \| '_ \ / __|/ _ \| |
- # / /_ | || _|| __/| | | || (__| __/| |
- # /____||_||_| \___||_| |_| \___|\___||_|
- # RV32/RV64 Zifencei Standard Exension
-
- - name: fence.i
+ - name: mret
+ type: Control
template: Custom
- type: Syscall
fields:
- field: opcode
- value: "0001111"
- - field: funct3
- type: cop
- startbit: 14
- stopbit: 12
- value: "001"
- - field: zeros
+ value: "1110011"
+ - field: funct12
type: cop
startbit: 31
- stopbit: 15
- value: "00000000000000000"
- - field: zeros2
+ stopbit: 20
+ value: "001100000010"
+ - field: zeros
type: cop
- startbit: 11
+ startbit: 19
stopbit: 7
- value: "00000"
+ value: "0000000000000"
+ definition: |
+ registers.pc = registers.mepc;
+ CAPI.INTERRUPTS.globalClear(); // TODO: clear only pending interrupt
+ CAPI.STACK.endFrame();
+ CAPI.INTERRUPTS.setUserMode();
+ CAPI.INTERRUPTS.clearHighlight();
+ help: Return from traps in M-mode, and mret copies mpie into mie, then
+ sets mpie.
+ properties:
+ - privileged
+
+ Zicsr:
+ # _____ _
+ # |__ /(_) ___ ___ _ __
+ # / / | | / __|/ __|| '__|
+ # / /_ | || (__ \__ \| |
+ # /____||_| \___||___/|_|
+ # RV32/64 Zicsr Standard Extension
+
+ - name: csrrw
+ type: Transfer between registers
+ template: CSR
+ fields:
+ - field: opcode
+ value: "1110011"
+ - field: funct3
+ value: "001"
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.
+ registers[rd] = registers[csr];
+ registers[csr] = registers[rs1];
+ help: Atomically swaps values in the CSRs and integer registers. CSRRW
+ reads the old value of the CSR, then writes it to integer register rd.
+ The initial value in rs1 is written to the CSR.
+
+ # 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.
pseudoinstructions:
# Make sure the definitions correspond with those in the RISC-V ASM manual (TODO: Check these!)
@@ -3793,7 +3905,7 @@ pseudoinstructions:
- field: off
type: offset_bytes
definition: |
- bge reg1, x0, off;
+ bge rs1, x0, off;
help: Take the branch if the value in register rs1 is zero.
- name: bgt
@@ -3918,13 +4030,13 @@ pseudoinstructions:
type: imm-unsigned
definition: |
no_ret_op{
- tmp = Field.2.(31,0).int;
- tmp_pc_offset = (reg.pc - 4) & 0xFFF;
+ tmp = Field.2.(31,0).int - (reg.pc - 4);
tmp_low = tmp & 0x00000FFF;
- tmp_hi = tmp >> 12
+ tmp_low = tmp_low>0x7FF? tmp_low - 0x1000 : tmp_low;
+ tmp_hi = (tmp - tmp_low) >> 12;
};
auipc rd, op{tmp_hi};
- addi rd, rd, op{tmp_low - (tmp_pc_offset)};
+ addi rd, rd, op{tmp_low};
- name: li
fields:
@@ -4093,3 +4205,168 @@ enums:
rmm: 4
dyn: 7
DEFAULT: dyn
+
+interrupts:
+ handlers:
+ creator_syscall: |
+ let [fa0Value, fa0Type] = CAPI.ARCH.toJSNumberD(registers.fa0);
+ switch (registers.a7) {
+ case 1n:
+ CAPI.SYSCALL.print(registers.a0, 'int32');
+ break;
+ case 2n:
+ case 3n:
+ CAPI.SYSCALL.print(fa0Value, 'float');
+ break;
+ case 4n:
+ CAPI.SYSCALL.print(registers.a0, 'string');
+ break;
+ case 5n:
+ CAPI.SYSCALL.read('a0', 'int32');
+ break;
+ case 6n:
+ CAPI.SYSCALL.read('fa0', 'float');
+ break;
+ case 7n:
+ CAPI.SYSCALL.read('fa0', 'double');
+ break;
+ case 8n:
+ CAPI.SYSCALL.read('a0', 'string', 'a1');
+ break;
+ case 9n:
+ CAPI.SYSCALL.sbrk('a0', 'a0');
+ break;
+ case 10n:
+ CAPI.SYSCALL.exit();
+ break;
+ case 11n:
+ CAPI.SYSCALL.print(registers.a0, 'char');
+ break;
+ case 12n:
+ CAPI.SYSCALL.read('a0', 'char');
+ break;
+ }
+ CAPI.INTERRUPTS.clearHighlight();
+ CAPI.STACK.endFrame();
+
+ custom: |
+ CAPI.INTERRUPTS.globalDisable();
+ CAPI.INTERRUPTS.setKernelMode();
+ registers.mepc = CAPI.REG.read("pc"); // get "real" PC (next instruction)
+
+ // jump to handler
+ if (registers.mtvec & 1n) { // vectored mode
+ registers.pc =
+ (registers.mtvec >> 2n) + 4 * (registers.mcause & (2 ** 32 - 1));
+ } else { // direct mode
+ registers.pc = registers.mtvec >> 2n
+ }
+
+ check: |
+ if (registers.mip & (2n ** 11n)) return InterruptType.External;
+ if (registers.mip & (2n ** 3n)) return InterruptType.Software;
+ if (registers.mip & (2n ** 7n)) return InterruptType.Timer;
+ return null;
+
+ is_enabled: |
+ switch (type) {
+ case InterruptType.Software:
+ case InterruptType.EnvironmentCall:
+ return !! (registers.mie & 2n ** 3n); // MSIE
+ case InterruptType.External:
+ return !! (registers.mie & 2n ** 11n); // MEIE
+ case InterruptType.Timer:
+ return !! (registers.mie & 2n ** 7n); // MTIE
+ }
+ return false;
+
+ is_global_enabled: |
+ return !!(registers.mstatus & 2n ** 3n); // MIE
+
+ enable: |
+ switch (type) {
+ case InterruptType.Software:
+ case InterruptType.EnvironmentCall:
+ registers.mie |= 2n ** 3n; // MSIE
+ break;
+ case InterruptType.External:
+ registers.mie |= 2n ** 11n; // MEIE
+ break;
+ case InterruptType.Timer:
+ registers.mie |= 2n ** 7n; // MTIE
+ break;
+ }
+
+ disable: |
+ switch (type) {
+ case InterruptType.Software:
+ case InterruptType.EnvironmentCall:
+ registers.mie &= ~(2n ** 3n); // MSIE
+ break;
+ case InterruptType.External:
+ registers.mie &= ~(2n ** 11n); // MEIE
+ break;
+ case InterruptType.Timer:
+ registers.mie &= ~(2n ** 7n); // MTIE
+ break;
+ }
+
+ global_enable: |
+ registers.mstatus | 2n ** 3n
+
+ global_disable: |
+ return !(registers.mstatus | (2n ** 3n));
+
+ global_clear: |
+ registers.mip = 0n;
+ registers.mcause = 0n;
+
+ clear: |
+ switch (type) {
+ case InterruptType.Software:
+ case InterruptType.EnvironmentCall:
+ registers.mip &= ~(2n ** 3n); // MSIP
+ break;
+ case InterruptType.External:
+ registers.mip &= ~(2n ** 11n); // MEIP
+ break;
+ case InterruptType.Timer:
+ registers.mip &= ~(2n ** 7n); // MTIP
+ break;
+ }
+ registers.mcause = 0n;
+
+ create: |
+ switch (type) {
+ case InterruptType.Software:
+ registers.mcause = 2n ** 3n;
+ registers.mip |= 2n ** 3n; // MSIP
+ break;
+ case InterruptType.External:
+ registers.mcause = 2n ** 31n + 11n;
+ registers.mip |= 2n ** 11n; // MEIP
+ break;
+ case InterruptType.EnvironmentCall:
+ registers.mcause = 2n ** 8n;
+ registers.mip |= 2n ** 3n; // MSIP
+ break;
+ case InterruptType.Timer:
+ registers.mcause = 2n ** 31n + 7n;
+ registers.mip |= 2n ** 7n; // MTIP
+ break;
+ }
+
+timer:
+ tick_cycles: 1
+ advance: |
+ registers.mtime = (registers.mtime + 1n) % (2n**32n - 1n);
+ handler: |
+ if (registers.mtime === registers.mtimecmp) {
+ CAPI.INTERRUPTS.create(InterruptType.Timer);
+ }
+ is_enabled: |
+ return !! (registers.mie & 2n ** 7n); // MTIE
+ enable: |
+ registers.mie |= 2n ** 7n; // MTIE = 1
+ disable: |
+ registers.mie &= ~(2n ** 7n); // MTIE = 0
diff --git a/architecture/RISCV/SRV32.yml b/architecture/RISCV/SRV32.yml
new file mode 100644
index 000000000..1bc57cd10
--- /dev/null
+++ b/architecture/RISCV/SRV32.yml
@@ -0,0 +1,4567 @@
+# yaml-language-server: $schema=../schema.json
+version: 2.0.0
+
+# ASCII text generated w/ https://patorjk.com/software/taag/#p=display&h=1&f=Standard
+# instruction help text extracted from https://msyksphinz-self.github.io/riscv-isadoc/html/index.html
+
+config:
+ name: SRV32
+ word_size: 32
+ description: RISC-V is an instruction set architecture (ISA) based on the RISC type and its hardware is free. This architecture was created in 2010 at the University of California, Berkeley.
+ endianness: big_endian
+ memory_alignment: true
+ main_function: main
+ passing_convention: true
+ sensitive_register_name: true
+ comment_prefix: "#"
+ start_address: 0
+ pc_offset: -4
+ byte_size: 8
+ plugin: riscv
+ assemblers:
+ - name: "Sail"
+ description: Default Creator Compiler
+extensions:
+ I:
+ description: RV32I Base Instruction Set
+ template: Base
+ M:
+ description: RV32M Integer Multiply/Divide Extension
+ type: extension
+ F:
+ description: RV32F Single-Precision Floating-Point Extension
+ type: extension
+ implies:
+ - Zicsr
+ D:
+ description: RV32D Double-Precision Floating-Point Extension
+ type: extension
+ implies:
+ - F
+ Zifencei:
+ description: RV32/RV64 Zifencei Standard Extension
+ type: extension
+ Zicsr:
+ description: RV32/RV64 Zicsr Standard Extension
+ type: extension
+components:
+ - name: Control registers
+ type: ctrl_registers
+ double_precision: false
+ elements:
+ - name:
+ - PC
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - program_counter
+ - name: Integer registers
+ type: int_registers
+ double_precision: false
+ elements:
+ - name:
+ - x0
+ - zero
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - ignore_write
+ - name:
+ - x1
+ - ra
+ nbits: 32
+ value: -1
+ default_value: -1
+ encoding: 1
+ properties:
+ - read
+ - write
+ - name:
+ - x2
+ - sp
+ nbits: 32
+ value: 0x0FFFFFFC
+ default_value: 0x0FFFFFFC
+ encoding: 2
+ properties:
+ - read
+ - write
+ - stack_pointer
+ - name:
+ - x3
+ - gp
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 3
+ properties:
+ - read
+ - write
+ - global_pointer
+ - name:
+ - x4
+ - tp
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 4
+ properties:
+ - read
+ - write
+ - name:
+ - x5
+ - t0
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 5
+ properties:
+ - read
+ - write
+ - name:
+ - x6
+ - t1
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 6
+ properties:
+ - read
+ - write
+ - name:
+ - x7
+ - t2
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 7
+ properties:
+ - read
+ - write
+ - name:
+ - x8
+ - fp
+ - s0
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 8
+ properties:
+ - read
+ - write
+ - frame_pointer
+ - saved
+ - name:
+ - x9
+ - s1
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 9
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x10
+ - a0
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 10
+ properties:
+ - read
+ - write
+ - name:
+ - x11
+ - a1
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 11
+ properties:
+ - read
+ - write
+ - name:
+ - x12
+ - a2
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 12
+ properties:
+ - read
+ - write
+ - name:
+ - x13
+ - a3
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 13
+ properties:
+ - read
+ - write
+ - name:
+ - x14
+ - a4
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 14
+ properties:
+ - read
+ - write
+ - name:
+ - x15
+ - a5
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 15
+ properties:
+ - read
+ - write
+ - name:
+ - x16
+ - a6
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 16
+ properties:
+ - read
+ - write
+ - name:
+ - x17
+ - a7
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 17
+ properties:
+ - read
+ - write
+ - name:
+ - x18
+ - s2
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 18
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x19
+ - s3
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 19
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x20
+ - s4
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 20
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x21
+ - s5
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 21
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x22
+ - s6
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 22
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x23
+ - s7
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 23
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x24
+ - s8
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 24
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x25
+ - s9
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 25
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x26
+ - s10
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 26
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x27
+ - s11
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 27
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x28
+ - t3
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 28
+ properties:
+ - read
+ - write
+ - name:
+ - x29
+ - t4
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 29
+ properties:
+ - read
+ - write
+ - name:
+ - x30
+ - t5
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 30
+ properties:
+ - read
+ - write
+ - name:
+ - x31
+ - t6
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 31
+ properties:
+ - read
+ - write
+ - name: Floating point registers
+ type: fp_registers
+ double_precision: true
+ elements:
+ - name:
+ - f0
+ - ft0
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - f1
+ - ft1
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 1
+ properties:
+ - read
+ - write
+ - name:
+ - f2
+ - ft2
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 2
+ properties:
+ - read
+ - write
+ - name:
+ - f3
+ - ft3
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 3
+ properties:
+ - read
+ - write
+ - name:
+ - f4
+ - ft4
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 4
+ properties:
+ - read
+ - write
+ - name:
+ - f5
+ - ft5
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 5
+ properties:
+ - read
+ - write
+ - name:
+ - f6
+ - ft6
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 6
+ properties:
+ - read
+ - write
+ - name:
+ - f7
+ - ft7
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 7
+ properties:
+ - read
+ - write
+ - name:
+ - f8
+ - fs0
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 8
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f9
+ - fs1
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 9
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f10
+ - fa0
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 10
+ properties:
+ - read
+ - write
+ - name:
+ - f11
+ - fa1
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 11
+ properties:
+ - read
+ - write
+ - name:
+ - f12
+ - fa2
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 12
+ properties:
+ - read
+ - write
+ - name:
+ - f13
+ - fa3
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 13
+ properties:
+ - read
+ - write
+ - name:
+ - f14
+ - fa4
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 14
+ properties:
+ - read
+ - write
+ - name:
+ - f15
+ - fa5
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 15
+ properties:
+ - read
+ - write
+ - name:
+ - f16
+ - fa6
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 16
+ properties:
+ - read
+ - write
+ - name:
+ - f17
+ - fa7
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 17
+ properties:
+ - read
+ - write
+ - name:
+ - f18
+ - fs2
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 18
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f19
+ - fs3
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 19
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f20
+ - fs4
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 20
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f21
+ - fs5
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 21
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f22
+ - fs6
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 22
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f23
+ - fs7
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 23
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f24
+ - fs8
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 24
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f25
+ - fs9
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 25
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f26
+ - fs10
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 26
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f27
+ - fs11
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 27
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f28
+ - ft8
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 28
+ properties:
+ - read
+ - write
+ - name:
+ - f29
+ - ft9
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 29
+ properties:
+ - read
+ - write
+ - name:
+ - f30
+ - ft10
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 30
+ properties:
+ - read
+ - write
+ - name:
+ - f31
+ - ft11
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 31
+ properties:
+ - read
+ - write
+ - name: Vectorial registers
+ type: v_registers
+ double_precision: true
+ elements:
+ - name:
+ - v0
+ - vt0
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v1
+ - vt1
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v2
+ - vt2
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v3
+ - vt3
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v4
+ - vt4
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v5
+ - vt5
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v6
+ - vt6
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v7
+ - vt7
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v8
+ - vt8
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v9
+ - vt9
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v10
+ - vt10
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v11
+ - vt11
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v12
+ - vt12
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v13
+ - vt13
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v14
+ - vt14
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v15
+ - vt15
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v16
+ - vt16
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v17
+ - vt17
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v18
+ - vt18
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v19
+ - vt19
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v20
+ - vt20
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v21
+ - vt21
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v22
+ - vt22
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v23
+ - vt23
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v24
+ - vt24
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v25
+ - vt25
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v26
+ - vt26
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v27
+ - vt27
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v28
+ - vt28
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v29
+ - vt29
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v30
+ - vt30
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v31
+ - vt31
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name: Control state registers
+ type: csr_registers
+ double_precision: false
+ elements:
+# USER registers
+ - name:
+ - ustatus
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - uie
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - utvec
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - uscratch
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - uepc
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - ucause
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - utval
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - uip
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+# SUPERVISOR registers
+ - name:
+ - sstatus
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - sedeleg
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - sideleg
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - sie
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - stvec
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - sscratch
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - sepc
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - scause
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - stval
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - sip
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - satp
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+# MACHINE REGISTERS
+ - name:
+ - mstatus
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - misa
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - medeleg
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mideleg
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mie
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mstvec
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mscratch
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mepc
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mcause
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mtval
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mip
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mcycle
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - minstret
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+# COMMON REGISTERS
+ - name:
+ - cycle
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - time
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - instret
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - hpmcounterX
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - hpmcounterXh
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mhartid
+ nbits: 32
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+
+directives:
+ - name: .data
+ action: data_segment
+ size: null
+ - name: .text
+ action: code_segment
+ size: null
+ - name: .bss
+ action: global_symbol
+ size: null
+ - name: .zero
+ action: space
+ size: 1
+ - name: .space
+ action: space
+ size: 1
+ - name: .align
+ action: align
+ size: null
+ - name: .balign
+ action: balign
+ size: null
+ - name: .globl
+ action: global_symbol
+ size: null
+ - name: .string
+ action: ascii_null_end
+ size: null
+ - name: .asciz
+ action: ascii_null_end
+ size: null
+ - name: .ascii
+ action: ascii_not_null_end
+ size: null
+ - name: .byte
+ action: byte
+ size: 1
+ - name: .half
+ action: half_word
+ size: 2
+ - name: .word
+ action: word
+ size: 4
+ - name: .dword
+ action: double_word
+ size: 8
+ - name: .float
+ action: float
+ size: 4
+ - name: .double
+ action: double
+ size: 8
+
+memory_layout:
+ text:
+ start: 0x80000000
+ end: 0x80003FFF
+ data:
+ start: 0x80004000
+ end: 0x80005FFF
+ stack:
+ start: 0x8000AFFC
+ end: 0x8000AFFF
+
+templates:
+ - name: B
+ type: Conditional bifurcation
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rs1
+ type: INT-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 1
+ - name: rs2
+ type: INT-Reg
+ startbit: 24
+ stopbit: 20
+ suffix: ","
+ order: 2
+ - name: imm
+ type: offset_bytes
+ startbit:
+ - 31
+ - 7
+ - 30
+ - 11
+ stopbit:
+ - 31
+ - 7
+ - 25
+ - 8
+ padding: 1
+ order: 3
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: I
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: INT-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: imm
+ type: imm-signed
+ startbit: 31
+ stopbit: 20
+ order: 3
+ - name: rs1
+ type: INT-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: I-Offset
+ # Not an "official" instruction, but used for the offset in the I-type instructions
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: INT-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: imm
+ type: imm-signed
+ startbit: 31
+ stopbit: 20
+ order: 2
+ space: false
+ - name: rs1
+ type: INT-Reg
+ startbit: 19
+ stopbit: 15
+ order: 3
+ prefix: (
+ suffix: )
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: I-Shift
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: INT-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: INT-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: shamt
+ type: imm-unsigned
+ startbit: 24
+ stopbit: 20
+ order: 3
+ - name: funct7
+ type: cop
+ startbit: 31
+ stopbit: 25
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: J
+ type: Unconditional bifurcation
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: INT-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: imm
+ type: offset_bytes
+ startbit:
+ - 31
+ - 19
+ - 20
+ - 30
+ stopbit:
+ - 31
+ - 12
+ - 20
+ - 21
+ padding: 1
+ order: 2
+
+ - name: R
+ type: Arithmetic integer
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: INT-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: INT-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: rs2
+ type: INT-Reg
+ startbit: 24
+ stopbit: 20
+ order: 3
+ - name: funct7
+ type: cop
+ startbit: 31
+ stopbit: 25
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: R-Floating # Used in rv32f / rv64f
+ type: Arithmetic floating point
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: DFP-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: DFP-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: rs2
+ type: DFP-Reg
+ startbit: 24
+ stopbit: 20
+ suffix: ","
+ order: 3
+ - name: funct7
+ type: cop
+ startbit: 31
+ stopbit: 25
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: R-Double # Used in rv64d
+ nwords: 1
+ type: Arithmetic floating point
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: DFP-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: DFP-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: rs2
+ type: DFP-Reg
+ startbit: 24
+ stopbit: 20
+ suffix: ","
+ order: 3
+ - name: funct7
+ type: cop
+ startbit: 31
+ stopbit: 25
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: R-IntToFloat # fcvt.s.w,...
+ nwords: 1
+ type: Transfer between registers
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: DFP-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: INT-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: funct5
+ type: cop
+ startbit: 24
+ stopbit: 20
+ - name: funct7
+ type: cop
+ startbit: 31
+ stopbit: 25
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: R-FloatToInt # fcvt.w.s,...
+ type: Transfer between registers
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: INT-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: DFP-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: funct5
+ type: cop
+ startbit: 24
+ stopbit: 20
+ - name: funct7
+ type: cop
+ startbit: 31
+ stopbit: 25
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: R-Conversion # Generic template
+ type: Transfer between registers
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: Not-Set
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: Not-Set
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: funct5
+ type: cop
+ startbit: 24
+ stopbit: 20
+ - name: funct7
+ type: cop
+ startbit: 31
+ stopbit: 25
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: R4
+ type: Arithmetic floating point
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: DFP-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: DFP-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: rs2
+ type: DFP-Reg
+ startbit: 24
+ stopbit: 20
+ suffix: ","
+ order: 3
+ - name: rs3
+ type: DFP-Reg
+ startbit: 31
+ stopbit: 27
+ suffix: ","
+ order: 4
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+ - name: funct2
+ type: cop
+ startbit: 26
+ stopbit: 25
+
+ - name: R4-Double
+ type: Arithmetic floating point
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: DFP-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: DFP-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: rs2
+ type: DFP-Reg
+ startbit: 24
+ stopbit: 20
+ suffix: ","
+ order: 3
+ - name: rs3
+ type: DFP-Reg
+ startbit: 31
+ stopbit: 27
+ suffix: ","
+ order: 4
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+ - name: funct2
+ type: cop
+ startbit: 26
+ stopbit: 25
+
+ - name: S
+ type: Memory access
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rs2
+ type: INT-Reg
+ startbit: 24
+ stopbit: 20
+ suffix: ","
+ order: 1
+ - name: imm
+ type: imm-signed
+ startbit:
+ - 31
+ - 11
+ stopbit:
+ - 25
+ - 7
+ order: 2
+ space: false
+ - name: rs1
+ type: INT-Reg
+ startbit: 19
+ stopbit: 15
+ prefix: (
+ suffix: )
+ order: 3
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: U
+ type: Arithmetic integer
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: INT-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: imm
+ type: imm-unsigned
+ startbit: 31
+ stopbit: 12
+ order: 2
+
+ - name: CSR
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: INT-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+ - name: rs1
+ type: INT-Reg
+ startbit: 19
+ stopbit: 15
+ order: 3
+ - name: csr
+ type: Ctrl-Reg
+ startbit: 31
+ stopbit: 20
+ suffix: ","
+ order: 2
+
+ - name: Custom
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+
+instructions:
+ I:
+ - name: beq
+ extension: I
+ template: B
+ fields:
+ - field: opcode
+ value: "1100011"
+ - field: funct3
+ value: "000"
+ definition: |
+ if (registers[rs1] === registers[rs2])
+ registers["PC"] = registers["PC"] + imm;
+
+ help: Take the branch if registers rs1 and rs2 are equal.
+ - name: bge
+ extension: I
+ template: B
+ fields:
+ - field: opcode
+ value: "1100011"
+ - field: funct3
+ value: "101"
+ definition: |
+ if (CAPI.FP.uint2int(registers[rs1]) >= CAPI.FP.uint2int(registers[rs2]))
+ registers["PC"] = registers["PC"] + imm;
+ help: Take the branch if registers rs1 is greater than or equal to rs2, using signed comparison.
+ - name: bgeu
+ template: B
+ fields:
+ - field: opcode
+ value: "1100011"
+ - field: funct3
+ value: "111"
+ definition: |
+ if (CAPI.FP.int2uint(registers[rs1]) >= CAPI.FP.int2uint(registers[rs2]))
+ registers["PC"] = registers["PC"] + imm;
+ help: Take the branch if registers rs1 is greater than or equal to rs2, using unsigned comparison.
+ - name: blt
+ extension: I
+ template: B
+ fields:
+ - field: opcode
+ value: "1100011"
+ - field: funct3
+ value: "100"
+ definition: |
+ if (CAPI.FP.uint2int(registers[rs1]) < CAPI.FP.uint2int(registers[rs2]))
+ registers["PC"] = registers["PC"] + imm;
+ help: Take the branch if registers rs1 is less than rs2, using signed comparison.
+ - name: bltu
+ extension: I
+ template: B
+ fields:
+ - field: opcode
+ value: "1100011"
+ - field: funct3
+ value: "110"
+ definition: |
+ if (CAPI.FP.int2uint(registers[rs1]) < CAPI.FP.int2uint(registers[rs2]))
+ registers["PC"] = registers["PC"] + imm;
+ help: Take the branch if registers rs1 is less than rs2, using unsigned comparison.
+ - name: bne
+ extension: I
+ template: B
+ fields:
+ - field: opcode
+ value: "1100011"
+ - field: funct3
+ value: "001"
+ definition: |
+ if (registers[rs1] !== registers[rs2])
+ registers["PC"] = registers["PC"] + imm;
+
+ help: Take the branch if registers rs1 and rs2 are not equal.
+ - name: addi
+ extension: I
+ template: I
+ type: Arithmetic integer
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "000"
+ definition: |
+ registers[rd] = registers[rs1] + imm;
+
+ help: Adds the sign-extended 12-bit immediate to register rs1. Arithmetic overflow is ignored and the result is simply the low XLEN bits of the result.
+ - name: andi
+ extension: I
+ template: I
+ type: Logic
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "111"
+ definition: |
+ registers[rd] = registers[rs1] & CAPI.FP.int2uint(imm);
+
+ help: Performs bitwise AND on register rs1 and the sign-extended 12-bit immediate and place the result in rd.
+ - name: jalr
+ extension: I
+ template: I-Offset
+ type: Unconditional bifurcation
+ fields:
+ - field: opcode
+ value: "1100111"
+ - field: funct3
+ value: "000"
+ definition: |
+ registers[rd] = registers.pc + 4n;
+ const pc = registers[rs1] + imm;
+ registers.pc = pc & ~1n;
+ if (BigInt.asIntN(32, pc) === -1n) CAPI.SYSCALL.exit();
+ else CAPI.STACK.endFrame();
+ help: Jump to address and place return address in rd.
+ - name: lb
+ extension: I
+ template: I-Offset
+ type: Memory access
+ fields:
+ - field: opcode
+ value: "0000011"
+ - field: funct3
+ value: "000"
+ definition: |
+ registers[rd] = CAPI.MEM.read(imm + registers[rs1], 1, rd, false);
+
+ help: Loads a 8-bit value from memory and sign-extends this to XLEN bits before storing it in register rd.
+ - name: lbu
+ extension: I
+ template: I-Offset
+ type: Memory access
+ fields:
+ - field: opcode
+ value: "0000011"
+ - field: funct3
+ value: "100"
+ definition: |
+ let addr = CAPI.FP.int2uint(registers[rs1]) + imm;
+ let result = CAPI.MEM.read(addr, 1, rd, false);
+ registers[rd] = CAPI.FP.int2uint(result);
+ help: Loads a 8-bit value from memory and zero-extends this to XLEN bits before storing it in register rd.
+ - name: lh
+ extension: I
+ template: I-Offset
+ type: Memory access
+ fields:
+ - field: opcode
+ value: "0000011"
+ - field: funct3
+ value: "001"
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 2))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[rd] = CAPI.MEM.read(addr, 2, rd, false);
+
+ help: Loads a 16-bit value from memory and sign-extends this to XLEN bits before storing it in register rd.
+ - name: lhu
+ extension: I
+ template: I-Offset
+ type: Memory access
+ fields:
+ - field: opcode
+ value: "0000011"
+ - field: funct3
+ value: "101"
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 2))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ let result = CAPI.MEM.read(addr, 2, rd, false);
+ registers[rd] = CAPI.FP.int2uint(result);
+ help: Loads a 16-bit value from memory and zero-extends this to XLEN bits before storing it in register rd.
+ - name: lw
+ extension: I
+ template: I-Offset
+ type: Memory access
+ fields:
+ - field: opcode
+ value: "0000011"
+ - field: funct3
+ value: "010"
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[rd] = CAPI.MEM.read(addr, 4, rd, false);
+ help: Loads a 32-bit value from memory and sign-extends this to XLEN bits before storing it in register rd.
+ - name: ld
+ extension: D
+ template: I-Offset
+ type: Memory access
+ fields:
+ - field: opcode
+ value: "0000011"
+ - field: funct3
+ value: "011"
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 8))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[rd] = CAPI.MEM.read(addr, 8, rd, false);
+ help: Loads a 64-bit value from memory into register rd for RV64I.
+ - name: ori
+ extension: I
+ template: I
+ type: Logic
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "110"
+ definition: |
+ registers[rd] = registers[rs1] | imm;
+
+ help: Performs bitwise OR on register rs1 and the sign-extended 12-bit immediate and place the result in rd.
+ - name: slli
+ extension: I
+ template: I-Shift
+ type: Arithmetic integer
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "001"
+ - field: funct7
+ value: "0000000"
+ definition: |
+ if (shamt > 0) registers[rd] = CAPI.FP.int2uint(registers[rs1] << shamt);
+
+ help: Performs logical left shift on the value in register rs1 by the shift amount held in the lower 5 bits of the immediate.
+ - name: slti
+ extension: I
+ template: I
+ type: Logic
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "010"
+ definition: |
+ registers[rd] = (CAPI.FP.uint2int(registers[rs1]) < CAPI.FP.uint2int(imm)) ? 1n : 0n;
+
+ help: Place the value 1 in register rd if register rs1 is less than the signextended immediate when both are treated as signed numbers, else 0 is written to rd.
+ - name: sltiu
+ extension: I
+ template: I
+ type: Logic
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "011"
+ definition: |
+ registers[rd] = (CAPI.FP.int2uint(registers[rs1]) < CAPI.FP.int2uint(imm)) ? 1n: 0n;
+ help: Place the value 1 in register rd if register rs1 is less than the immediate when both are treated as unsigned numbers, else 0 is written to rd.
+ - name: srai
+ extension: I
+ template: I-Shift
+ type: Arithmetic integer
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "101"
+ - field: funct7
+ value: "0100000"
+ definition: |
+ if (shamt > 0) registers[rd] = CAPI.FP.int2uint(registers[rs1] >> shamt);
+
+ help: Performs arithmetic right shift on the value in register rs1 by the shift amount held in the lower 5 bits of the immediate.
+ - name: srli
+ extension: I
+ template: I-Shift
+ type: Arithmetic integer
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "101"
+ - field: funct7
+ value: "0000000"
+ definition: |
+ if (shamt > 0) registers[rd] = CAPI.FP.int2uint(registers[rs1] >> shamt);
+
+ help: Performs logical right shift on the value in register rs1 by the shift amount held in the lower 5 bits of the immediate.
+ - name: xori
+ extension: I
+ template: I
+ type: Logic
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "100"
+ definition: |
+ registers[rd] = registers[rs1] ^ imm;
+
+ help: Performs bitwise XOR on register rs1 and the sign-extended 12-bit immediate and place the result in rd. Note, 'XORI rd, rs1, -1' performs a bitwise logical inversion of register rs1(assembler pseudo-instruction NOT rd, rs).
+ - name: jal
+ extension: I
+ template: J
+ fields:
+ - field: opcode
+ value: "1101111"
+ definition: |
+ registers[rd] = registers["PC"] + 4n;
+ registers["PC"] = registers["PC"] + imm;
+ CAPI.CHECK_STACK.begin(registers["PC"] + imm);
+ CAPI.DRAW_STACK.begin(registers["PC"] + imm); // This is not an accident. We only see the virtual PC here, and the virtual/physical PC sync happens after the instruction execution.
+ help: Jump to address and place return address in rd.
+ - name: add
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ value: "000"
+ definition: |
+ registers[rd] = registers[rs2] + registers[rs1];
+
+ help: Adds the registers rs1 and rs2 and stores the result in rd. Arithmetic overflow is ignored and the result is simply the low XLEN bits of the result.
+ - name: and
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ value: "111"
+ definition: |
+ registers[rd] = registers[rs1] & registers[rs2];
+
+ help: Performs bitwise AND on registers rs1 and rs2 and place the result in rd.
+ - name: or
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ value: "110"
+ definition: |
+ registers[rd] = registers[rs1] | registers[rs2];
+
+ help: Performs bitwise OR on registers rs1 and rs2 and place the result in rd.
+ - name: sll
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ value: "001"
+ definition: |
+ const shiftAmount = registers[rs2] & 0x1Fn;
+ registers[rd] = (registers[rs1] << shiftAmount) & 0xFFFFFFFFn;
+ help: Performs logical left shift on the value in register rs1 by the shift amount held in the lower 5 bits of register rs2.
+ - name: slt
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ value: "010"
+ definition: |
+ registers[rd] = (CAPI.FP.uint2int(registers[rs1]) < CAPI.FP.uint2int(registers[rs2])) ? 1n : 0n;
+
+ help: Place the value 1 in register rd if register rs1 is less than register rs2 when both are treated as signed numbers, else 0 is written to rd.
+ - name: sltu
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ value: "011"
+ definition: |
+ registers[rd] = ((registers[rs1] & 0xFFFFFFFFn) < (registers[rs2] & 0xFFFFFFFFn)) ? 1n : 0n;
+
+ help: Place the value 1 in register rd if register rs1 is less than register rs2 when both are treated as unsigned numbers, else 0 is written to rd.
+ - name: sra
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0100000"
+ - field: funct3
+ value: "101"
+ definition: |
+ const temp = BigInt.asIntN(32, BigInt(registers[rs1])) >> BigInt(registers[rs2]);
+ registers[rd] = CAPI.FP.int2uint(temp);
+ help: Performs arithmetic right shift on the value in register rs1 by the shift amount held in the lower 5 bits of register rs2.
+ - name: srl
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ value: "101"
+ definition: |
+ const shiftAmount = registers[rs2] & 0x1Fn;
+ registers[rd] = (registers[rs1] >> shiftAmount) & 0xFFFFFFFFn;
+ help: Logical right shift on the value in register rs1 by the shift amount held in the lower 5 bits of register rs2.
+ - name: sub
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0100000"
+ - field: funct3
+ value: "000"
+ definition: |
+ registers[rd] = registers[rs1] - registers[rs2];
+
+ help: Subs the register rs2 from rs1 and stores the result in rd. Arithmetic overflow is ignored and the result is simply the low XLEN bits of the result.
+ - name: xor
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ value: "100"
+ definition: |
+ registers[rd] = (registers[rs1] ^ registers[rs2]);
+
+ help: Performs bitwise XOR on registers rs1 and rs2 and place the result in rd.
+ - name: sb
+ extension: I
+ template: S
+ fields:
+ - field: opcode
+ value: "0100011"
+ - field: funct3
+ value: "000"
+ definition: |
+ CAPI.MEM.write(registers[rs1] + imm, 1, BigInt.asUintN(8, registers[rs2]), rs2, 'byte', false);
+
+ help: Store 8-bit, values from the low bits of register rs2 to memory.
+ - name: sh
+ extension: I
+ template: S
+ fields:
+ - field: opcode
+ value: "0100011"
+ - field: funct3
+ value: "001"
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 2))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 2, BigInt.asUintN(16, registers[rs2]), rs2, 'half', false);
+
+ help: Store 16-bit, values from the low bits of register rs2 to memory.
+ - name: sw
+ extension: I
+ template: S
+ fields:
+ - field: opcode
+ value: "0100011"
+ - field: funct3
+ value: "010"
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 4, BigInt.asUintN(32, registers[rs2]), rs2, 'word', false);
+
+ help: Store 32-bit, values from the low bits of register rs2 to memory.
+
+ - name: sd
+ extension: D
+ template: S
+ fields:
+ - field: opcode
+ value: "0100011"
+ - field: funct3
+ value: "011"
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 8))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(
+ addr,
+ 8,
+ BigInt.asUintN(64, registers[rs2]),
+ rs2,
+ "float64",
+ false,
+ );
+ help: Loads a 64-bit value from memory into register rd for RV64I.
+
+ - name: auipc
+ extension: I
+ template: U
+ fields:
+ - field: opcode
+ value: "0010111"
+ - field: imm
+ type: offset_bytes
+ definition: |
+ registers[rd] = registers["PC"] + (imm << 12n);
+
+ help: Build pc-relative addresses and uses the U-type format. AUIPC forms a 32-bit offset from the 20-bit U-immediate, filling in the lowest 12 bits with zeros, adds this offset to the pc, then places the result in register rd.
+ - name: lui
+ extension: I
+ template: U
+ fields:
+ - field: opcode
+ value: "0110111"
+ - field: imm
+ type: imm-unsigned
+ definition: |
+ registers[rd] = imm << 12n;
+
+ help: Build 32-bit constants and uses the U-type format. LUI places the U-immediate value in the top 20 bits of the destination register rd, filling in the lowest 12 bits with zeros.
+ - name: ecall
+ extension: I
+ template: Custom
+ type: Syscall
+ fields:
+ - field: opcode
+ value: "1110011"
+ - field: zeros
+ type: cop
+ startbit: 31
+ stopbit: 7
+ value: "0000000000000000000000000"
+ preoperation: 'let [fa0Value, fa0Type] = CAPI.ARCH.toJSNumberD(registers["fa0"]);'
+ definition: |
+ switch (registers["a7"]) {
+ case 1n:
+ CAPI.SYSCALL.print(registers["a0"], 'int32');
+ break;
+ case 2n:
+ case 3n:
+ CAPI.SYSCALL.print(fa0Value, 'float');
+ break;
+ case 4n:
+ CAPI.SYSCALL.print(registers["a0"], 'string');
+ break;
+ case 5n:
+ CAPI.SYSCALL.read('a0', 'int');
+ break;
+ case 6n:
+ CAPI.SYSCALL.read('fa0', 'float');
+ break;
+ case 7n:
+ CAPI.SYSCALL.read('fa0', 'double');
+ break;
+ case 8n:
+ CAPI.SYSCALL.read('a0', 'string', 'a1');
+ break;
+ case 9n:
+ CAPI.SYSCALL.sbrk('a0', 'a0');
+ break;
+ case 10n:
+ CAPI.SYSCALL.exit();
+ break;
+ case 11n:
+ CAPI.SYSCALL.print(registers["a0"], 'char');
+ break;
+ case 12n:
+ CAPI.SYSCALL.read('a0', 'char');
+ break;
+ }
+ help: Make a request to the supporting execution environment. When executed in U-mode, S-mode, or M-mode, it generates an environment-call-from-U-mode exception, environment-call-from-S-mode exception, or environment-call-from-M-mode exception, respectively, and performs no other operation.
+ - name: ebreak
+ extension: I
+ template: Custom
+ type: Syscall
+ fields:
+ - field: opcode
+ value: "1110011"
+ - field: funct12
+ type: cop
+ startbit: 31
+ stopbit: 20
+ value: "000000000001"
+ - field: zeros
+ type: cop
+ startbit: 19
+ stopbit: 7
+ value: "0000000000000"
+ definition: |
+ console.log('Not implemented: ebreak');
+ CAPI.VALIDATION.raise('ebreak not implemented');
+ help: Used by debuggers to cause control to be transferred back to a debugging environment. It generates a breakpoint exception and performs no other operation.
+ M:
+ - name: div
+ extension: M
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ value: "100"
+ definition: |
+ if (registers[rs2] != 0) {
+ registers[rd] = BigInt.asIntN(
+ 32,
+ (BigInt.asIntN(32, BigInt(registers[rs1])) / BigInt.asIntN(32, BigInt(registers[rs2])))
+ );
+ }
+ else CAPI.VALIDATION.raise('Division by registers[zero] not allowed');
+ help: Perform an XLEN bits by XLEN bits signed integer division of rs1 by rs2, rounding towards zero.
+ - name: divu
+ extension: M
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ value: "101"
+ definition: |
+ const div = registers[rs2]
+ if (div != 0) {
+ registers[rd] = CAPI.FP.int2uint(registers[rs1] / div);
+ }
+ else CAPI.VALIDATION.raise('Division by zero not allowed');
+ help: Perform an XLEN-bit by XLEN-bit unsigned integer division of rs1 by rs2, rounding towards zero.
+ - name: mul
+ extension: M
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ value: "000"
+ definition: |
+ registers[rd] = CAPI.FP.uint2int(registers[rs1]) * CAPI.FP.uint2int(registers[rs2]);
+
+ help: Performs an XLEN-bit by XLEN-bit multiplication of signed rs1 by signed rs2 and places the lower XLEN bits in the destination register.
+ - name: mulh
+ extension: M
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ value: "001"
+ definition: |
+ registers[rd] = CAPI.FP.int2uint(
+ (CAPI.FP.uint2int(registers[rs1]) * CAPI.FP.uint2int(registers[rs2])) >> 32n,
+ );
+ help: Performs an XLEN-bit by XLEN-bit multiplication of signed rs1 by signed rs2 and places the lower XLEN bits in the destination register.
+ - name: mulhsu
+ extension: M
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ value: "010"
+ definition: |
+ registers[rd] = CAPI.FP.int2uint(
+ (CAPI.FP.uint2int(registers[rs1]) * registers[rs2]) >> 32n,
+ );
+ help: Performs an XLEN-bit by XLEN-bit multiplication of signed rs1 by unsigned rs2 and places the upper XLEN bits in the destination register.
+ - name: mulhu
+ extension: M
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ value: "011"
+ definition: |
+ registers[rd] = CAPI.FP.int2uint(
+ (registers[rs1] * registers[rs2]) >> 32n,
+ );
+ help: Performs an XLEN-bit by XLEN-bit multiplication of unsigned rs1 by unsigned rs2 and places the upper XLEN bits in the destination register.
+ - name: rem
+ extension: M
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ value: "110"
+ definition: |
+ registers[rd] = registers[rs1] % registers[rs2];
+
+ help: Perform an XLEN-bit by XLEN-bit signed integer reminder of rs1 by rs2.
+ - name: remu
+ extension: M
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ value: "111"
+ definition: |
+ registers[rd] = registers[rs1] % registers[rs2];
+
+ help: Perform an XLEN-bit by XLEN-bit unsigned integer reminder of rs1 by rs2.
+ F:
+ - name: flw
+ extension: F
+ template: I-Offset
+ type: Memory access
+ fields:
+ - field: opcode
+ value: "0000111"
+ - field: funct3
+ value: "010"
+ - field: rd
+ type: DFP-Reg
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[rd] = CAPI.MEM.read(addr, 4, rd, false);
+
+ postoperation: |
+ registers[rd] = CAPI.ARCH.NaNBox(registers[rd]);
+
+ help: Load a single-precision floating-point value from memory into floating-point register rd.
+ - name: fadd.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 4
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = rs1Number + rs2Number;
+
+ help: Perform single-precision floating-point addition.
+ - name: fclass.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1110000"
+ - field: funct3
+ value: "001"
+ - field: rs1
+ suffix: null
+ - field: rs2
+ type: cop
+ value: "00000"
+ order: null
+ - field: rd
+ type: INT-Reg
+ preoperation: |
+ let rs1Value, rs2Value, type_rs1, type_rs2;
+ [rs1Value, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Value, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(registers[rd])) {
+ registers[rd] = CAPI.ARCH.toBigInt(registers[rd], "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(registers[rd], "NaNBfloat32_64");
+ }
+ registers[rs1] = CAPI.ARCH.toBigInt(rs1Value, type_rs1);
+ registers[rs2] = CAPI.ARCH.toBigInt(rs2Value, type_rs2);
+ definition: |
+ let a = CAPI.FP.float2bin(registers[rs1]);
+ registers[rd] = CAPI.FP.check_ieee(
+ parseInt(a[0]),
+ parseInt(a.slice(1, 9), 2),
+ parseInt(a.slice(10), 2),
+ );
+ help: Examines the value in floating-point register rs1 and writes to integer register rd a 10-bit mask that indicates the class of the floating-point number. The corresponding bit in rd will be set if the property is true and clear otherwise. All other bits in rd are cleared. Note that exactly one bit in rd will be set.
+ - name: fcvt.s.w
+ extension: F
+ template: R-IntToFloat
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1101000"
+ - field: funct5
+ value: "00000"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ postoperation: |
+ registers[rd] = CAPI.ARCH.toBigInt(result,'NaNBfloat32_64');
+ definition: |
+ result = CAPI.FP.uint2int(registers[rs1])
+
+ help: Converts a 32-bit signed integer, in integer register rs1 into a floating-point number in floating-point register rd.
+ - name: fcvt.s.wu
+ extension: F
+ template: R-IntToFloat
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1101000"
+ - field: funct5
+ value: "00001"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ definition: |
+ registers[rd] = CAPI.FP.int2uint(registers[rs1])
+
+ help: Converts a 32-bit unsigned integer, in integer register rs1 into a floating-point number in floating-point register rd.
+ - name: fcvt.w.s
+ extension: F
+ template: R-FloatToInt
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1100000"
+ - field: funct5
+ value: "00000"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = parseInt(registers[rs1]);
+
+ help: Convert a floating-point number in floating-point register rs1 to a signed 32-bit in integer register rd.
+ - name: fcvt.wu.s
+ extension: F
+ template: R-FloatToInt
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1100000"
+ - field: funct5
+ value: "00001"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+ definition: |
+ registers[rd] = CAPI.FP.int2uint(parseInt(rs1Number));
+
+ help: Convert a floating-point number in floating-point register rs1 to a signed 32-bit in unsigned integer register rd.
+ - name: fdiv.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0001100"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 4
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+ definition: |
+ if (rs2Number != 0) { result = rs1Number / rs2Number; }
+ else CAPI.VALIDATION.raise('Division by registers[zero] not allowed');
+
+ help: Perform single-precision floating-point division.
+ - name: feq.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1010000"
+ - field: funct3
+ value: "010"
+ - field: rd
+ type: INT-Reg
+ preoperation: |
+ let rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ definition: |
+ registers[rd] = (rs1Number === rs2Number)? 1n : 0n;
+
+ help: Performs a quiet equal comparison between floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
+ - name: fle.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1010000"
+ - field: funct3
+ value: "000"
+ - field: rd
+ type: INT-Reg
+ preoperation: |
+ let rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ definition: |
+ registers[rd] = (rs1Number <= rs2Number)? 1n : 0n;
+
+ help: Performs a quiet less or equal comparison between floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
+ - name: flt.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1010000"
+ - field: funct3
+ value: "001"
+ - field: rd
+ type: INT-Reg
+ preoperation: |
+ let rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ definition: |
+ registers[rd] = (rs1Number < rs2Number)? 1n : 0n;
+
+ help: Performs a quiet less comparison between floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
+ - name: fmax.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010100"
+ - field: funct3
+ value: "001"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = Math.max(rs1Number, rs2Number);
+
+ help: Write the larger of single precision data in rs1 and rs2 to rd.
+ - name: fmin.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010100"
+ - field: funct3
+ value: "000"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+ definition: |
+ result = Math.min(rs1Number, rs2Number);
+
+ help: Write the smaller of single precision data in rs1 and rs2 to rd.
+ - name: fmul.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0001000"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 4
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+ definition: |
+ result = rs2Number * rs1Number;
+
+ help: Perform single-precision floating-point multiplication.
+ - name: fmv.w.x
+ extension: F
+ template: R-IntToFloat
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1111000"
+ - field: funct5
+ value: "00000"
+ - field: funct3
+ value: "000"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = CAPI.FP.uint2float32(rs1Number);
+
+ help: Move the single-precision value encoded in IEEE 754-2008 standard encoding from the lower 32 bits of integer register rs1 to the floating-point register rd.
+ - name: fmv.x.w
+ extension: F
+ template: R-FloatToInt
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1110000"
+ - field: funct5
+ value: "00000"
+ - field: funct3
+ value: "000"
+ preoperation: |
+ let result, rs1Number, type_rs1;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+ registers[rs1] = CAPI.ARCH.toBigInt(rs1Number, type_rs1);
+ definition: |
+ result = CAPI.FP.float322uint(rs1Number);
+
+ help: Move the single-precision value in floating-point register rs1 represented in IEEE 754-2008 encoding to the lower 32 bits of integer register rd.
+ - name: fsgnj.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010000"
+ - field: funct3
+ value: "000"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+ definition: |
+ result = (rs2Number >= 0) ? Math.abs(rs1Number) : -Math.abs(rs1Number);
+
+ help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is rs2's sign bit.
+ - name: fsgnjn.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010000"
+ - field: funct3
+ value: "001"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+ definition: |
+ result = (rs2Number <= 0) ? Math.abs(rs1Number) : -Math.abs(rs1Number);
+ help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is rs2's sign bit.
+ - name: fsgnjx.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010000"
+ - field: funct3
+ value: "010"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+ definition: |
+ let a = rs1Number < 0;
+ let b = rs2Number < 0;
+ result = a ^ b ? -Math.abs(rs1Number) : Math.abs(rs1Number);
+ help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is XOR of sign bit of rs1 and rs2.
+ - name: fsqrt.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0101100"
+ - field: rs2
+ type: cop
+ value: "00000"
+ order: null
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ preoperation: |
+ let result, rs1Number, type_rs1;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ if (rs1Number >= 0) {
+ result = Math.sqrt(rs1Number);
+ } else {
+ CAPI.VALIDATION.raise(
+ "Square root of a negative number is not allowed."
+ );
+ }
+ help: Perform single-precision square root.
+ - name: fsub.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0000100"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 4
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = rs1Number - rs2Number;
+
+ help: Perform single-precision floating-point subtraction.
+ - name: fmadd.s
+ extension: F
+ template: R4
+ fields:
+ - field: opcode
+ value: "1000011"
+ - field: funct2
+ value: "00"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 5
+ preoperation: |
+ let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = rs1Number * rs2Number + rs3Number;
+
+ help: Perform single-precision fused multiply addition.
+ - name: fmsub.s
+ extension: F
+ template: R4
+ fields:
+ - field: opcode
+ value: "1000111"
+ - field: funct2
+ value: "00"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 5
+ preoperation: |
+ let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = rs1Number * rs2Number - rs3Number;
+
+ help: Perform single-precision fused multiply addition.
+ - name: fnmadd.s
+ extension: F
+ template: R4
+ fields:
+ - field: opcode
+ value: "1001111"
+ - field: funct2
+ value: "00"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 5
+ preoperation: |
+ let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = -rs1Number * rs2Number - rs3Number;
+
+ help: Perform negated single-precision fused multiply addition.
+ - name: fnmsub.s
+ extension: F
+ template: R4
+ fields:
+ - field: opcode
+ value: "1001011"
+ - field: funct2
+ value: "00"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 5
+ preoperation: |
+ let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = -rs1Number * rs2Number + rs3Number;
+
+ help: Perform negated single-precision fused multiply addition.
+ - name: fsw
+ extension: F
+ template: S
+ fields:
+ - field: opcode
+ value: "0100111"
+ - field: funct3
+ value: "010"
+ - field: rs2
+ type: DFP-Reg
+ definition: |
+ let value = registers[rs2] & 0xFFFFFFFFn;
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 4, value, rs2, 'float32', false);
+ help: Store a single-precision value from floating-point register rs2 to memory.
+ D:
+ - name: fld
+ extension: D
+ template: I-Offset
+ type: Memory access
+ fields:
+ - field: opcode
+ value: "0000111"
+ - field: funct3
+ value: "011"
+ - field: rd
+ type: DFP-Reg
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 8))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[rd] = CAPI.MEM.read(addr, 8, rd, false);
+ help: Load a double-precision floating-point value from memory into floating-point register rd.
+ - name: fadd.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 4
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+ definition: |
+ result = rs1Number + rs2Number;
+
+ help: Perform double-precision floating-point addition.
+ - name: fclass.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1110001"
+ - field: funct3
+ value: "001"
+ - field: rs1
+ suffix: null
+ - field: rs2
+ type: cop
+ value: "00000"
+ order: null
+ - field: rd
+ type: INT-Reg
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+ definition: |
+ let a = CAPI.FP.float2bin(rs1Number);
+ registers[rd] = CAPI.FP.check_ieee(
+ parseInt(a[0]),
+ parseInt(a.slice(1, 12), 2),
+ parseInt(a.slice(13), 2),
+ );
+ help: Examines the value in double-precision floating-point register rs1 and writes to integer register rd a 10-bit mask that indicates the class of the floating-point number. The corresponding bit in rd will be set if the property is true and clear otherwise. All other bits in rd are cleared. Note that exactly one bit in rd will be set.
+ - name: fcvt.d.s
+ extension: D
+ template: R-Conversion
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: rd
+ type: DFP-Reg
+ - field: rs1
+ type: DFP-Reg
+ - field: funct7
+ value: "0100001"
+ - field: funct5
+ value: "00000"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: null
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+ definition: |
+ result = rs1Number; // TODO: This doesn't seem right, check the RISC-V manual
+
+ help: Converts double floating-point register in rs1 into a double floating-point number in floating-point register rd.
+ - name: fcvt.d.w
+ extension: D
+ template: R-Conversion
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1101001"
+ - field: funct5
+ value: "00000"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: null
+ - field: rd
+ type: DFP-Reg
+ - field: rs1
+ type: INT-Reg
+ preoperation: |
+ let result, rs1Number;
+ rs1Number = registers[rs1];
+ postoperation: |
+ registers[rd] = CAPI.ARCH.toBigInt(result, 'float64');
+ definition: |
+ result = CAPI.FP.uint2int(rs1Number);
+
+ help: Converts a 32-bit signed integer, in integer register rs1 into a double-precision floating-point number in floating-point register rd.
+ - name: fcvt.d.wu
+ extension: D
+ template: R-Conversion
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1101001"
+ - field: funct5
+ value: "00001"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: null
+ - field: rd
+ type: DFP-Reg
+ - field: rs1
+ type: INT-Reg
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+ definition: |
+ result = CAPI.FP.int2uint(parseFloat(rs1Number));
+
+ help: Converts a 32-bit unsigned integer, in integer register rs1 into a double-precision floating-point number in floating-point register rd.
+ - name: fcvt.s.d
+ extension: D
+ template: R-Conversion
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0100000"
+ - field: funct5
+ value: "00001"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ - field: rd
+ type: DFP-Reg
+ - field: rs1
+ type: DFP-Reg
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+ definition: |
+ result = rs1Number; // TODO: This doesn't seem right, check the RISC-V manual
+
+ help: Converts double floating-point register in rs1 into a floating-point number in floating-point register rd.
+ - name: fcvt.w.d
+ extension: D
+ template: R-Conversion
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1100001"
+ - field: funct5
+ value: "00000"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ - field: rd
+ type: INT-Reg
+ - field: rs1
+ type: DFP-Reg
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ result = CAPI.FP.int2uint(parseInt(rs1Number));
+
+ help: Converts a double-precision floating-point number in floating-point register rs1 to a signed 32-bit integer, in integer register rd.
+ - name: fcvt.wu.d
+ extension: D
+ template: R-Conversion
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1100001"
+ - field: funct5
+ value: "00001"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ - field: rd
+ type: INT-Reg
+ - field: rs1
+ type: DFP-Reg
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ result = CAPI.FP.int2uint(parseInt(rs1Number));
+
+ help: Converts a double-precision floating-point number in floating-point register rs1 to a unsigned 32-bit integer, in integer register rd.
+ - name: fdiv.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0001101"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 4
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ result = rs1Number / rs2Number;
+ help: Perform double-precision floating-point division.
+ - name: feq.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1010001"
+ - field: funct3
+ value: "010"
+ - field: rd
+ type: INT-Reg
+ preoperation: |
+ let rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ definition: |
+ registers[rd] = (rs1Number === rs2Number)? 1n : 0n;
+
+ help: Performs a quiet equal comparison between double-precision floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
+ - name: fle.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1010001"
+ - field: funct3
+ value: "000"
+ - field: rd
+ type: INT-Reg
+ preoperation: |
+ let rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ definition: |
+ registers[rd] = (rs1Number <= rs2Number)? 1n : 0n;
+
+ help: Performs a quiet less or equal comparison between double-precision floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
+ - name: flt.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1010001"
+ - field: funct3
+ value: "001"
+ - field: rd
+ type: INT-Reg
+ preoperation: |
+ let rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ definition: |
+ registers[rd] = (rs1Number < rs2Number)? 1n : 0n;
+
+ help: Performs a quiet less comparison between double-precision floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
+ - name: fmax.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010101"
+ - field: funct3
+ value: "001"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ result = Math.max(rs1Number, rs2Number);
+
+ help: Write the larger of double precision data in rs1 and rs2 to rd.
+ - name: fmin.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010101"
+ - field: funct3
+ value: "000"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ result = Math.min(rs1Number, rs2Number);
+
+ help: Write the smaller of double precision data in rs1 and rs2 to rd.
+ - name: fmul.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0001001"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 4
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ result = rs1Number * rs2Number;
+
+ help: Perform double-precision floating-point addition.
+ - name: fsgnj.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010001"
+ - field: funct3
+ value: "000"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ registers[rd] = (rs2Number > 0) ? Math.abs(rs1Number) : -Math.abs(rs1Number);
+ help: Perform double-precision floating-point multiplication.
+ - name: fsgnjn.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010001"
+ - field: funct3
+ value: "001"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ result = (rs2Number > 0) ? -Math.abs(rs1Number) : +Math.abs(rs1Number);
+
+ help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is opposite of rs2's sign bit.
+ - name: fsgnjx.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010001"
+ - field: funct3
+ value: "010"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ let a = rs1Number < 0;
+ let b = rs2Number < 0;
+ result = a ^ b ? -Math.abs(rs1Number) : Math.abs(rs1Number);
+ help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is XOR of sign bit of rs1 and rs2.
+ - name: fsqrt.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0101101"
+ - field: rs2
+ type: cop
+ value: "00000"
+ order: null
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ preoperation: |
+ let result, rs1Number, type_rs1;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ if (rs1Number >= 0) {
+ result = Math.sqrt(rs1Number);
+ } else {
+ CAPI.VALIDATION.raise(
+ "Square root of a negative number is not allowed."
+ );
+ }
+ help: Perform double-precision square root.
+ - name: fsub.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0000101"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 4
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ result = rs1Number - rs2Number;
+
+ help: Perform double-precision floating-point addition.
+ - name: fmadd.d
+ extension: D
+ template: R4-Double
+ fields:
+ - field: opcode
+ value: "1000011"
+ - field: funct2
+ value: "01"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 5
+ preoperation: |
+ let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ registers[rs3] = CAPI.ARCH.toBigInt(rs3Number, type_rs3);
+ definition: |
+ result = rs1Number * rs2Number + rs3Number;
+
+ help: Perform double-precision fused multiply addition.
+ - name: fmsub.d
+ extension: D
+ template: R4-Double
+ fields:
+ - field: opcode
+ value: "1000111"
+ - field: funct2
+ value: "01"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 5
+ preoperation: |
+ let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ registers[rs3] = CAPI.ARCH.toBigInt(rs3Number, type_rs3);
+ definition: |
+ result = rs1Number * rs2Number - rs3Number;
+
+ help: Perform double-precision fused multiply subtraction.
+ - name: fnmadd.d
+ extension: D
+ template: R4-Double
+ fields:
+ - field: opcode
+ value: "1001111"
+ - field: funct2
+ value: "01"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 5
+ preoperation: |
+ let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ registers[rs3] = CAPI.ARCH.toBigInt(rs3Number, type_rs3);
+ definition: |
+ result = -rs1Number * rs2Number - rs3Number;
+
+ help: Perform negated double-precision fused multiply addition.
+ - name: fnmsub.d
+ extension: D
+ template: R4-Double
+ fields:
+ - field: opcode
+ value: "1001011"
+ - field: funct2
+ value: "01"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 5
+ preoperation: |
+ let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ registers[rs3] = CAPI.ARCH.toBigInt(rs3Number, type_rs3);
+ definition: |
+ result = -rs1Number * rs2Number + rs3Number;
+
+ help: Perform negated double-precision fused multiply subtraction.
+ - name: fsd
+ extension: D
+ template: S
+ fields:
+ - field: opcode
+ value: "0100111"
+ - field: funct3
+ value: "011"
+ - field: rs2
+ type: DFP-Reg
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 8))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 8, registers[rs2], rs2, 'float64', false);
+ help: Store a double-precision value from the floating-point registers to memory.
+ Zifencei:
+ - name: fence.i
+ extension: D
+ 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!)
+
+ # RV32I Pseudoinstructions
+ I:
+ - name: beqz
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ beq rs1, x0, off;
+
+ - name: bgez
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ bge rs1, x0, off;
+ help: Take the branch if the value in register rs1 is zero.
+
+ - name: bgt
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: rs2
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ blt rs2, rs1, off;
+
+ - name: bgtu
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: rs2
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ bltu rs2, rs1, off;
+
+ - name: bgtz
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ bgt rs1, x0, off;
+
+ - name: ble
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: rs2
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ bge rs2, rs1, off;
+
+ - name: bleu
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: rs2
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ bgeu rs2, rs1, off;
+
+ - name: blez
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ ble x0, rs1, off;
+
+ - name: bltz
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ blt rs1, x0, off;
+
+ - name: bnez
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ bne rs1, x0, off;
+
+ - name: j
+ extension: I
+ fields:
+ - field: off
+ type: offset_bytes
+ definition: |
+ beq zero, zero, off;
+
+ - name: jalr
+ extension: I
+ fields:
+ - field: rs
+ type: INT-Reg
+ definition: |
+ jalr x1, 0(rs);
+
+ - name: jr
+ extension: I
+ fields:
+ - field: rs
+ type: INT-Reg
+ definition: |
+ jalr x0, 0(rs);
+
+ - name: la
+ extension: I
+ fields:
+ - field: rd
+ type: INT-Reg
+ suffix: ","
+ - field: addr
+ type: imm-unsigned
+ definition: |
+ no_ret_op{
+ tmp = Field.2.(31,0).int - (reg.pc - 4);
+ tmp_low = tmp & 0x00000FFF;
+ tmp_low = tmp_low>0x7FF? tmp_low - 0x1000 : tmp_low;
+ tmp_hi = (tmp - tmp_low) >> 12;
+ };
+ auipc rd, op{tmp_hi};
+ addi rd, rd, op{tmp_low};
+
+ - name: li
+ extension: I
+ fields:
+ - field: rd
+ type: INT-Reg
+ suffix: ","
+ - field: val
+ type: imm-signed
+ definition: |
+ no_ret_op{
+ tmp = Field.2.(31,0).int;
+ tmp_low = tmp & 0x00000FFF;
+ tmp_low -= tmp_low > 0x7FF ? 0x1000 : 0;
+ tmp_hi = (tmp - tmp_low) >>> 12;
+ };
+ if (tmp_hi === 0) {
+ addi rd, x0, op{tmp_low};
+ }
+ else {
+ lui rd, op{tmp_hi};
+ addi rd, rd, op{tmp_low};
+ };
+ help: Load the sign-extended 6-bit immediate, imm, into register rd.
+
+ - name: mv
+ extension: I
+ fields:
+ - field: reg1
+ type: INT-Reg
+ suffix: ","
+ - field: reg2
+ type: INT-Reg
+ definition: |
+ addi reg1, reg2, 0;
+ help: Copy the value in register rs2 into register rd.
+
+ - name: neg
+ extension: I
+ fields:
+ - field: reg1
+ type: INT-Reg
+ suffix: ","
+ - field: reg2
+ type: INT-Reg
+ definition: |
+ sub reg1, x0, reg2;
+
+ - name: nop
+ extension: I
+ definition: |
+ addi x0, x0, 0;
+ help: Does not change any user-visible state, except for advancing the pc.
+
+ - name: not
+ extension: I
+ fields:
+ - field: reg1
+ type: INT-Reg
+ suffix: ","
+ - field: reg2
+ type: INT-Reg
+ definition: |
+ xori reg1, reg2, -1;
+
+ - name: ret
+ extension: I
+ definition: |
+ jalr x0, 0(x1); # TODO: check this!
+
+ - name: seqz
+ extension: I
+ fields:
+ - field: reg1
+ type: INT-Reg
+ suffix: ","
+ - field: reg2
+ type: INT-Reg
+ definition: |
+ sltiu reg1, reg2, 1;
+
+ - name: sgtz
+ extension: I
+ fields:
+ - field: reg1
+ type: INT-Reg
+ suffix: ","
+ - field: reg2
+ type: INT-Reg
+ definition: |
+ slt reg1, x0, reg2;
+
+ - name: sltz
+ extension: I
+ fields:
+ - field: reg1
+ type: INT-Reg
+ suffix: ","
+ - field: reg2
+ type: INT-Reg
+ definition: |
+ slt reg1, reg2, x0;
+
+ - name: snez
+ extension: I
+ fields:
+ - field: reg1
+ type: INT-Reg
+ suffix: ","
+ - field: reg2
+ type: INT-Reg
+ definition: |
+ sltu reg1, x0, reg2;
+ F:
+ # RV32F Pseudoinstructions
+ - name: fabs.s
+ extension: F
+ fields:
+ - field: rs1
+ type: DFP-Reg
+ suffix: ","
+ - field: rs2
+ type: DFP-Reg
+ definition: |
+ fsgnjx.s rs1, rs2, rs2;
+
+ - name: fmv.s
+ extension: F
+ fields:
+ - field: rs1
+ type: DFP-Reg
+ suffix: ","
+ - field: rs2
+ type: DFP-Reg
+ definition: |
+ fsgnj.s rs1, rs2, rs2;
+
+ - name: fneg.s
+ extension: F
+ fields:
+ - field: rs1
+ type: DFP-Reg
+ suffix: ","
+ - field: rs2
+ type: DFP-Reg
+ definition: |
+ fsgnjn.s rs1, rs2, rs2;
+ D:
+ # RV32D Pseudoinstructions
+ - name: fabs.d
+ extension: D
+ fields:
+ - field: rs1
+ type: DFP-Reg
+ suffix: ","
+ - field: rs2
+ type: DFP-Reg
+ definition: |
+ fsgnjx.d rs1, rs2, rs2;
+
+ - name: fmv.d
+ extension: D
+ fields:
+ - field: rs1
+ type: DFP-Reg
+ suffix: ","
+ - field: rs2
+ type: DFP-Reg
+ definition: |
+ fsgnj.d rs1, rs2, rs2;
+
+ - name: fneg.d
+ extension: D
+ fields:
+ - field: rs1
+ type: DFP-Reg
+ suffix: ","
+ - field: rs2
+ type: DFP-Reg
+ definition: |
+ fsgnjn.d rs1, rs2, rs2;
+
+enums:
+ rounding_mode:
+ rne: 0
+ rtz: 1
+ rdn: 2
+ rup: 3
+ rmm: 4
+ dyn: 7
+ DEFAULT: dyn
diff --git a/architecture/RISCV/SRV64.yml b/architecture/RISCV/SRV64.yml
new file mode 100644
index 000000000..ff392e157
--- /dev/null
+++ b/architecture/RISCV/SRV64.yml
@@ -0,0 +1,4555 @@
+# yaml-language-server: $schema=../schema.json
+version: 2.0.0
+
+# ASCII text generated w/ https://patorjk.com/software/taag/#p=display&h=1&f=Standard
+# instruction help text extracted from https://msyksphinz-self.github.io/riscv-isadoc/html/index.html
+
+config:
+ name: SRV64
+ word_size: 32
+ description: RISC-V is an instruction set architecture (ISA) based on the RISC type and its hardware is free. This architecture was created in 2010 at the University of California, Berkeley.
+ endianness: big_endian
+ memory_alignment: true
+ main_function: main
+ passing_convention: true
+ sensitive_register_name: true
+ comment_prefix: "#"
+ start_address: 0
+ pc_offset: -4
+ byte_size: 8
+ plugin: riscv
+ assemblers:
+ - name: "Sail"
+ description: Default Creator Compiler
+extensions:
+ I:
+ description: RV32I Base Instruction Set
+ template: Base
+ M:
+ description: RV32M Integer Multiply/Divide Extension
+ type: extension
+ F:
+ description: RV32F Single-Precision Floating-Point Extension
+ type: extension
+ implies:
+ - Zicsr
+ D:
+ description: RV32D Double-Precision Floating-Point Extension
+ type: extension
+ implies:
+ - F
+ Zifencei:
+ description: RV32/RV64 Zifencei Standard Extension
+ type: extension
+ Zicsr:
+ description: RV32/RV64 Zicsr Standard Extension
+ type: extension
+components:
+ - name: Control registers
+ type: ctrl_registers
+ double_precision: false
+ elements:
+ - name:
+ - PC
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - program_counter
+ - name: Integer registers
+ type: int_registers
+ double_precision: false
+ elements:
+ - name:
+ - x0
+ - zero
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - ignore_write
+ - name:
+ - x1
+ - ra
+ nbits: 64
+ value: -1
+ default_value: -1
+ encoding: 1
+ properties:
+ - read
+ - write
+ - name:
+ - x2
+ - sp
+ nbits: 64
+ value: 0x0FFFFFFC
+ default_value: 0x0FFFFFFC
+ encoding: 2
+ properties:
+ - read
+ - write
+ - stack_pointer
+ - name:
+ - x3
+ - gp
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 3
+ properties:
+ - read
+ - write
+ - global_pointer
+ - name:
+ - x4
+ - tp
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 4
+ properties:
+ - read
+ - write
+ - name:
+ - x5
+ - t0
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 5
+ properties:
+ - read
+ - write
+ - name:
+ - x6
+ - t1
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 6
+ properties:
+ - read
+ - write
+ - name:
+ - x7
+ - t2
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 7
+ properties:
+ - read
+ - write
+ - name:
+ - x8
+ - fp
+ - s0
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 8
+ properties:
+ - read
+ - write
+ - frame_pointer
+ - saved
+ - name:
+ - x9
+ - s1
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 9
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x10
+ - a0
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 10
+ properties:
+ - read
+ - write
+ - name:
+ - x11
+ - a1
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 11
+ properties:
+ - read
+ - write
+ - name:
+ - x12
+ - a2
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 12
+ properties:
+ - read
+ - write
+ - name:
+ - x13
+ - a3
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 13
+ properties:
+ - read
+ - write
+ - name:
+ - x14
+ - a4
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 14
+ properties:
+ - read
+ - write
+ - name:
+ - x15
+ - a5
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 15
+ properties:
+ - read
+ - write
+ - name:
+ - x16
+ - a6
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 16
+ properties:
+ - read
+ - write
+ - name:
+ - x17
+ - a7
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 17
+ properties:
+ - read
+ - write
+ - name:
+ - x18
+ - s2
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 18
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x19
+ - s3
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 19
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x20
+ - s4
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 20
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x21
+ - s5
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 21
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x22
+ - s6
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 22
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x23
+ - s7
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 23
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x24
+ - s8
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 24
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x25
+ - s9
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 25
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x26
+ - s10
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 26
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x27
+ - s11
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 27
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - x28
+ - t3
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 28
+ properties:
+ - read
+ - write
+ - name:
+ - x29
+ - t4
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 29
+ properties:
+ - read
+ - write
+ - name:
+ - x30
+ - t5
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 30
+ properties:
+ - read
+ - write
+ - name:
+ - x31
+ - t6
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 31
+ properties:
+ - read
+ - write
+ - name: Floating point registers
+ type: fp_registers
+ double_precision: true
+ elements:
+ - name:
+ - f0
+ - ft0
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - f1
+ - ft1
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 1
+ properties:
+ - read
+ - write
+ - name:
+ - f2
+ - ft2
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 2
+ properties:
+ - read
+ - write
+ - name:
+ - f3
+ - ft3
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 3
+ properties:
+ - read
+ - write
+ - name:
+ - f4
+ - ft4
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 4
+ properties:
+ - read
+ - write
+ - name:
+ - f5
+ - ft5
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 5
+ properties:
+ - read
+ - write
+ - name:
+ - f6
+ - ft6
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 6
+ properties:
+ - read
+ - write
+ - name:
+ - f7
+ - ft7
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 7
+ properties:
+ - read
+ - write
+ - name:
+ - f8
+ - fs0
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 8
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f9
+ - fs1
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 9
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f10
+ - fa0
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 10
+ properties:
+ - read
+ - write
+ - name:
+ - f11
+ - fa1
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 11
+ properties:
+ - read
+ - write
+ - name:
+ - f12
+ - fa2
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 12
+ properties:
+ - read
+ - write
+ - name:
+ - f13
+ - fa3
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 13
+ properties:
+ - read
+ - write
+ - name:
+ - f14
+ - fa4
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 14
+ properties:
+ - read
+ - write
+ - name:
+ - f15
+ - fa5
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 15
+ properties:
+ - read
+ - write
+ - name:
+ - f16
+ - fa6
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 16
+ properties:
+ - read
+ - write
+ - name:
+ - f17
+ - fa7
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 17
+ properties:
+ - read
+ - write
+ - name:
+ - f18
+ - fs2
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 18
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f19
+ - fs3
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 19
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f20
+ - fs4
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 20
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f21
+ - fs5
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 21
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f22
+ - fs6
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 22
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f23
+ - fs7
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 23
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f24
+ - fs8
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 24
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f25
+ - fs9
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 25
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f26
+ - fs10
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 26
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f27
+ - fs11
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 27
+ properties:
+ - read
+ - write
+ - saved
+ - name:
+ - f28
+ - ft8
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 28
+ properties:
+ - read
+ - write
+ - name:
+ - f29
+ - ft9
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 29
+ properties:
+ - read
+ - write
+ - name:
+ - f30
+ - ft10
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 30
+ properties:
+ - read
+ - write
+ - name:
+ - f31
+ - ft11
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 31
+ properties:
+ - read
+ - write
+ - name: Vectorial registers
+ type: v_registers
+ double_precision: true
+ elements:
+ - name:
+ - v0
+ - vt0
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v1
+ - vt1
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v2
+ - vt2
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v3
+ - vt3
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v4
+ - vt4
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v5
+ - vt5
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v6
+ - vt6
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v7
+ - vt7
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v8
+ - vt8
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v9
+ - vt9
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v10
+ - vt10
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v11
+ - vt11
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v12
+ - vt12
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v13
+ - vt13
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v14
+ - vt14
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v15
+ - vt15
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v16
+ - vt16
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v17
+ - vt17
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v18
+ - vt18
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v19
+ - vt19
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v20
+ - vt20
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v21
+ - vt21
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v22
+ - vt22
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v23
+ - vt23
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v24
+ - vt24
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v25
+ - vt25
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v26
+ - vt26
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v27
+ - vt27
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v28
+ - vt28
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v29
+ - vt29
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v30
+ - vt30
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - v31
+ - vt31
+ nbits: 512
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name: Control state registers
+ type: csr_registers
+ double_precision: false
+ elements:
+# USER registers
+ - name:
+ - ustatus
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - uie
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - utvec
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - uscratch
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - uepc
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - ucause
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - utval
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - uip
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+# SUPERVISOR registers
+ - name:
+ - sstatus
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - sedeleg
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - sideleg
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - sie
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - stvec
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - sscratch
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - sepc
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - scause
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - stval
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - sip
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - satp
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+# MACHINE REGISTERS
+ - name:
+ - mstatus
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - misa
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - medeleg
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mideleg
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mie
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mstvec
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mscratch
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mepc
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mcause
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mtval
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mip
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mcycle
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - minstret
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+# COMMON REGISTERS
+ - name:
+ - cycle
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - time
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - instret
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - hpmcounterX
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - hpmcounterXh
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+ - name:
+ - mhartid
+ nbits: 64
+ value: 0
+ default_value: 0
+ encoding: 0
+ properties:
+ - read
+ - write
+
+directives:
+ - name: .data
+ action: data_segment
+ size: null
+ - name: .text
+ action: code_segment
+ size: null
+ - name: .bss
+ action: global_symbol
+ size: null
+ - name: .zero
+ action: space
+ size: 1
+ - name: .space
+ action: space
+ size: 1
+ - name: .align
+ action: align
+ size: null
+ - name: .balign
+ action: balign
+ size: null
+ - name: .globl
+ action: global_symbol
+ size: null
+ - name: .string
+ action: ascii_null_end
+ size: null
+ - name: .asciz
+ action: ascii_null_end
+ size: null
+ - name: .ascii
+ action: ascii_not_null_end
+ size: null
+ - name: .byte
+ action: byte
+ size: 1
+ - name: .half
+ action: half_word
+ size: 2
+ - name: .word
+ action: word
+ size: 4
+ - name: .dword
+ action: double_word
+ size: 8
+ - name: .float
+ action: float
+ size: 4
+ - name: .double
+ action: double
+ size: 8
+
+memory_layout:
+ text:
+ start: 0x0
+ end: 0x1FFFF
+ data:
+ start: 0x20000
+ end: 0x0FFFFFFF
+ stack:
+ start: 0x3FFFFFFC
+ end: 0x3FFFFFFF
+
+# memory_layout:
+# text:
+# start: 0
+# end: 131071
+# data:
+# start: 131072
+# end: 70368744177663
+# stack:
+# start: 140737488355324
+# end: 140737488355327
+
+templates:
+ - name: B
+ type: Conditional bifurcation
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rs1
+ type: INT-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 1
+ - name: rs2
+ type: INT-Reg
+ startbit: 24
+ stopbit: 20
+ suffix: ","
+ order: 2
+ - name: imm
+ type: offset_bytes
+ startbit:
+ - 31
+ - 7
+ - 30
+ - 11
+ stopbit:
+ - 31
+ - 7
+ - 25
+ - 8
+ padding: 1
+ order: 3
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: I
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: INT-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: imm
+ type: imm-signed
+ startbit: 31
+ stopbit: 20
+ order: 3
+ - name: rs1
+ type: INT-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: I-Offset
+ # Not an "official" instruction, but used for the offset in the I-type instructions
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: INT-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: imm
+ type: imm-signed
+ startbit: 31
+ stopbit: 20
+ order: 2
+ space: false
+ - name: rs1
+ type: INT-Reg
+ startbit: 19
+ stopbit: 15
+ order: 3
+ prefix: (
+ suffix: )
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: I-Shift
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: INT-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: INT-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: shamt
+ type: imm-unsigned
+ startbit: 24
+ stopbit: 20
+ order: 3
+ - name: funct7
+ type: cop
+ startbit: 31
+ stopbit: 25
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: J
+ type: Unconditional bifurcation
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: INT-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: imm
+ type: offset_bytes
+ startbit:
+ - 31
+ - 19
+ - 20
+ - 30
+ stopbit:
+ - 31
+ - 12
+ - 20
+ - 21
+ padding: 1
+ order: 2
+
+ - name: R
+ type: Arithmetic integer
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: INT-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: INT-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: rs2
+ type: INT-Reg
+ startbit: 24
+ stopbit: 20
+ order: 3
+ - name: funct7
+ type: cop
+ startbit: 31
+ stopbit: 25
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: R-Floating # Used in rv32f / rv64f
+ type: Arithmetic floating point
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: DFP-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: DFP-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: rs2
+ type: DFP-Reg
+ startbit: 24
+ stopbit: 20
+ suffix: ","
+ order: 3
+ - name: funct7
+ type: cop
+ startbit: 31
+ stopbit: 25
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: R-Double # Used in rv64d
+ nwords: 1
+ type: Arithmetic floating point
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: DFP-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: DFP-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: rs2
+ type: DFP-Reg
+ startbit: 24
+ stopbit: 20
+ suffix: ","
+ order: 3
+ - name: funct7
+ type: cop
+ startbit: 31
+ stopbit: 25
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: R-IntToFloat # fcvt.s.w,...
+ nwords: 1
+ type: Transfer between registers
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: DFP-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: INT-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: funct5
+ type: cop
+ startbit: 24
+ stopbit: 20
+ - name: funct7
+ type: cop
+ startbit: 31
+ stopbit: 25
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: R-FloatToInt # fcvt.w.s,...
+ type: Transfer between registers
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: INT-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: DFP-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: funct5
+ type: cop
+ startbit: 24
+ stopbit: 20
+ - name: funct7
+ type: cop
+ startbit: 31
+ stopbit: 25
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: R-Conversion # Generic template
+ type: Transfer between registers
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: Not-Set
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: Not-Set
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: funct5
+ type: cop
+ startbit: 24
+ stopbit: 20
+ - name: funct7
+ type: cop
+ startbit: 31
+ stopbit: 25
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: R4
+ type: Arithmetic floating point
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: DFP-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: DFP-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: rs2
+ type: DFP-Reg
+ startbit: 24
+ stopbit: 20
+ suffix: ","
+ order: 3
+ - name: rs3
+ type: DFP-Reg
+ startbit: 31
+ stopbit: 27
+ suffix: ","
+ order: 4
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+ - name: funct2
+ type: cop
+ startbit: 26
+ stopbit: 25
+
+ - name: R4-Double
+ type: Arithmetic floating point
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: DFP-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: rs1
+ type: DFP-Reg
+ startbit: 19
+ stopbit: 15
+ suffix: ","
+ order: 2
+ - name: rs2
+ type: DFP-Reg
+ startbit: 24
+ stopbit: 20
+ suffix: ","
+ order: 3
+ - name: rs3
+ type: DFP-Reg
+ startbit: 31
+ stopbit: 27
+ suffix: ","
+ order: 4
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+ - name: funct2
+ type: cop
+ startbit: 26
+ stopbit: 25
+
+ - name: S
+ type: Memory access
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rs2
+ type: INT-Reg
+ startbit: 24
+ stopbit: 20
+ suffix: ","
+ order: 1
+ - name: imm
+ type: imm-signed
+ startbit:
+ - 31
+ - 11
+ stopbit:
+ - 25
+ - 7
+ order: 2
+ space: false
+ - name: rs1
+ type: INT-Reg
+ startbit: 19
+ stopbit: 15
+ prefix: (
+ suffix: )
+ order: 3
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+
+ - name: U
+ type: Arithmetic integer
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: INT-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: imm
+ type: imm-unsigned
+ startbit: 31
+ stopbit: 12
+ order: 2
+
+ - name: CSR
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+ - name: rd
+ type: INT-Reg
+ startbit: 11
+ stopbit: 7
+ suffix: ","
+ order: 1
+ - name: funct3
+ type: cop
+ startbit: 14
+ stopbit: 12
+ - name: rs1
+ type: INT-Reg
+ startbit: 19
+ stopbit: 15
+ order: 3
+ - name: csr
+ type: Ctrl-Reg
+ startbit: 31
+ stopbit: 20
+ suffix: ","
+ order: 2
+
+ - name: Custom
+ nwords: 1
+ clk_cycles: 1
+ fields:
+ - name: opcode
+ type: co
+ startbit: 6
+ stopbit: 0
+ order: 0
+
+instructions:
+ I:
+ - name: beq
+ extension: I
+ template: B
+ fields:
+ - field: opcode
+ value: "1100011"
+ - field: funct3
+ value: "000"
+ definition: |
+ if (registers[rs1] === registers[rs2])
+ registers["PC"] = registers["PC"] + imm;
+
+ help: Take the branch if registers rs1 and rs2 are equal.
+ - name: bge
+ extension: I
+ template: B
+ fields:
+ - field: opcode
+ value: "1100011"
+ - field: funct3
+ value: "101"
+ definition: |
+ if (CAPI.FP.uint2int(registers[rs1]) >= CAPI.FP.uint2int(registers[rs2]))
+ registers["PC"] = registers["PC"] + imm;
+ help: Take the branch if registers rs1 is greater than or equal to rs2, using signed comparison.
+ - name: bgeu
+ template: B
+ fields:
+ - field: opcode
+ value: "1100011"
+ - field: funct3
+ value: "111"
+ definition: |
+ if (CAPI.FP.int2uint(registers[rs1]) >= CAPI.FP.int2uint(registers[rs2]))
+ registers["PC"] = registers["PC"] + imm;
+ help: Take the branch if registers rs1 is greater than or equal to rs2, using unsigned comparison.
+ - name: blt
+ extension: I
+ template: B
+ fields:
+ - field: opcode
+ value: "1100011"
+ - field: funct3
+ value: "100"
+ definition: |
+ if (CAPI.FP.uint2int(registers[rs1]) < CAPI.FP.uint2int(registers[rs2]))
+ registers["PC"] = registers["PC"] + imm;
+ help: Take the branch if registers rs1 is less than rs2, using signed comparison.
+ - name: bltu
+ extension: I
+ template: B
+ fields:
+ - field: opcode
+ value: "1100011"
+ - field: funct3
+ value: "110"
+ definition: |
+ if (CAPI.FP.int2uint(registers[rs1]) < CAPI.FP.int2uint(registers[rs2]))
+ registers["PC"] = registers["PC"] + imm;
+ help: Take the branch if registers rs1 is less than rs2, using unsigned comparison.
+ - name: bne
+ extension: I
+ template: B
+ fields:
+ - field: opcode
+ value: "1100011"
+ - field: funct3
+ value: "001"
+ definition: |
+ if (registers[rs1] !== registers[rs2])
+ registers["PC"] = registers["PC"] + imm;
+
+ help: Take the branch if registers rs1 and rs2 are not equal.
+ - name: addi
+ extension: I
+ template: I
+ type: Arithmetic integer
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "000"
+ definition: |
+ registers[rd] = registers[rs1] + imm;
+
+ help: Adds the sign-extended 12-bit immediate to register rs1. Arithmetic overflow is ignored and the result is simply the low XLEN bits of the result.
+ - name: andi
+ extension: I
+ template: I
+ type: Logic
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "111"
+ definition: |
+ registers[rd] = registers[rs1] & CAPI.FP.int2uint(imm);
+
+ help: Performs bitwise AND on register rs1 and the sign-extended 12-bit immediate and place the result in rd.
+ - name: jalr
+ extension: I
+ template: I-Offset
+ type: Unconditional bifurcation
+ fields:
+ - field: opcode
+ value: "1100111"
+ - field: funct3
+ value: "000"
+ definition: |
+ registers[rd] = registers.pc + 4n;
+ const pc = registers[rs1] + imm;
+ registers.pc = pc & ~1n;
+ if (BigInt.asIntN(64, pc) === -1n) CAPI.SYSCALL.exit();
+ else CAPI.STACK.endFrame();
+ help: Jump to address and place return address in rd.
+ - name: lb
+ extension: I
+ template: I-Offset
+ type: Memory access
+ fields:
+ - field: opcode
+ value: "0000011"
+ - field: funct3
+ value: "000"
+ definition: |
+ registers[rd] = CAPI.MEM.read(imm + registers[rs1], 1, rd, false);
+
+ help: Loads a 8-bit value from memory and sign-extends this to XLEN bits before storing it in register rd.
+ - name: lbu
+ extension: I
+ template: I-Offset
+ type: Memory access
+ fields:
+ - field: opcode
+ value: "0000011"
+ - field: funct3
+ value: "100"
+ definition: |
+ let addr = CAPI.FP.int2uint(registers[rs1]) + imm;
+ let result = CAPI.MEM.read(addr, 1, rd, false);
+ registers[rd] = CAPI.FP.int2uint(result);
+ help: Loads a 8-bit value from memory and zero-extends this to XLEN bits before storing it in register rd.
+ - name: lh
+ extension: I
+ template: I-Offset
+ type: Memory access
+ fields:
+ - field: opcode
+ value: "0000011"
+ - field: funct3
+ value: "001"
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 2))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[rd] = CAPI.MEM.read(addr, 2, rd, false);
+
+ help: Loads a 16-bit value from memory and sign-extends this to XLEN bits before storing it in register rd.
+ - name: lhu
+ extension: I
+ template: I-Offset
+ type: Memory access
+ fields:
+ - field: opcode
+ value: "0000011"
+ - field: funct3
+ value: "101"
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 2))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ let result = CAPI.MEM.read(addr, 2, rd, false);
+ registers[rd] = CAPI.FP.int2uint(result);
+ help: Loads a 16-bit value from memory and zero-extends this to XLEN bits before storing it in register rd.
+ - name: lw
+ extension: I
+ template: I-Offset
+ type: Memory access
+ fields:
+ - field: opcode
+ value: "0000011"
+ - field: funct3
+ value: "010"
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[rd] = CAPI.MEM.read(addr, 4, rd, false);
+ help: Loads a 32-bit value from memory and sign-extends this to XLEN bits before storing it in register rd.
+ - name: ori
+ extension: I
+ template: I
+ type: Logic
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "110"
+ definition: |
+ registers[rd] = registers[rs1] | imm;
+
+ help: Performs bitwise OR on register rs1 and the sign-extended 12-bit immediate and place the result in rd.
+ - name: slli
+ extension: I
+ template: I-Shift
+ type: Arithmetic integer
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "001"
+ - field: funct7
+ value: "0000000"
+ definition: |
+ if (shamt > 0) registers[rd] = CAPI.FP.int2uint(registers[rs1] << shamt);
+
+ help: Performs logical left shift on the value in register rs1 by the shift amount held in the lower 5 bits of the immediate.
+ - name: slti
+ extension: I
+ template: I
+ type: Logic
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "010"
+ definition: |
+ registers[rd] = (CAPI.FP.uint2int(registers[rs1]) < CAPI.FP.uint2int(imm)) ? 1n : 0n;
+
+ help: Place the value 1 in register rd if register rs1 is less than the signextended immediate when both are treated as signed numbers, else 0 is written to rd.
+ - name: sltiu
+ extension: I
+ template: I
+ type: Logic
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "011"
+ definition: |
+ registers[rd] = (CAPI.FP.int2uint(registers[rs1]) < CAPI.FP.int2uint(imm)) ? 1n: 0n;
+ help: Place the value 1 in register rd if register rs1 is less than the immediate when both are treated as unsigned numbers, else 0 is written to rd.
+ - name: srai
+ extension: I
+ template: I-Shift
+ type: Arithmetic integer
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "101"
+ - field: funct7
+ value: "0100000"
+ definition: |
+ if (shamt > 0) registers[rd] = (BigInt.asIntN(64, registers[rs1]) >> shamt);
+
+ help: Performs arithmetic right shift on the value in register rs1 by the shift amount held in the lower 5 bits of the immediate.
+ - name: srli
+ extension: I
+ template: I-Shift
+ type: Arithmetic integer
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "101"
+ - field: funct7
+ value: "0000000"
+ definition: |
+ if (shamt > 0) registers[rd] = CAPI.FP.int2uint(registers[rs1] >> shamt);
+
+ help: Performs logical right shift on the value in register rs1 by the shift amount held in the lower 5 bits of the immediate.
+ - name: xori
+ extension: I
+ template: I
+ type: Logic
+ fields:
+ - field: opcode
+ value: "0010011"
+ - field: funct3
+ value: "100"
+ definition: |
+ registers[rd] = registers[rs1] ^ imm;
+
+ help: Performs bitwise XOR on register rs1 and the sign-extended 12-bit immediate and place the result in rd. Note, 'XORI rd, rs1, -1' performs a bitwise logical inversion of register rs1(assembler pseudo-instruction NOT rd, rs).
+ - name: jal
+ extension: I
+ template: J
+ fields:
+ - field: opcode
+ value: "1101111"
+ definition: |
+ registers[rd] = registers["PC"] + 4n;
+ registers["PC"] = registers["PC"] + imm;
+ CAPI.CHECK_STACK.begin(registers["PC"] + imm);
+ CAPI.DRAW_STACK.begin(registers["PC"] + imm); // This is not an accident. We only see the virtual PC here, and the virtual/physical PC sync happens after the instruction execution.
+ help: Jump to address and place return address in rd.
+ - name: add
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ value: "000"
+ definition: |
+ registers[rd] = registers[rs2] + registers[rs1];
+
+ help: Adds the registers rs1 and rs2 and stores the result in rd. Arithmetic overflow is ignored and the result is simply the low XLEN bits of the result.
+ - name: and
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ value: "111"
+ definition: |
+ registers[rd] = registers[rs1] & registers[rs2];
+
+ help: Performs bitwise AND on registers rs1 and rs2 and place the result in rd.
+ - name: or
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ value: "110"
+ definition: |
+ registers[rd] = registers[rs1] | registers[rs2];
+
+ help: Performs bitwise OR on registers rs1 and rs2 and place the result in rd.
+ - name: sll
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ value: "001"
+ definition: |
+ const shiftAmount = registers[rs2] & 0x1Fn;
+ registers[rd] = (registers[rs1] << shiftAmount) & 0xFFFFFFFFn;
+ help: Performs logical left shift on the value in register rs1 by the shift amount held in the lower 5 bits of register rs2.
+ - name: slt
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ value: "010"
+ definition: |
+ registers[rd] = (CAPI.FP.uint2int(registers[rs1]) < CAPI.FP.uint2int(registers[rs2])) ? 1n : 0n;
+
+ help: Place the value 1 in register rd if register rs1 is less than register rs2 when both are treated as signed numbers, else 0 is written to rd.
+ - name: sltu
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ value: "011"
+ definition: |
+ registers[rd] = ((registers[rs1] & 0xFFFFFFFFn) < (registers[rs2] & 0xFFFFFFFFn)) ? 1n : 0n;
+
+ help: Place the value 1 in register rd if register rs1 is less than register rs2 when both are treated as unsigned numbers, else 0 is written to rd.
+ - name: sra
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0100000"
+ - field: funct3
+ value: "101"
+ definition: |
+ const temp = BigInt.asIntN(32, BigInt(registers[rs1])) >> BigInt(registers[rs2]);
+ registers[rd] = CAPI.FP.int2uint(temp);
+ help: Performs arithmetic right shift on the value in register rs1 by the shift amount held in the lower 5 bits of register rs2.
+ - name: srl
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ value: "101"
+ definition: |
+ const shiftAmount = registers[rs2] & 0x1Fn;
+ registers[rd] = (registers[rs1] >> shiftAmount) & 0xFFFFFFFFn;
+ help: Logical right shift on the value in register rs1 by the shift amount held in the lower 5 bits of register rs2.
+ - name: sub
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0100000"
+ - field: funct3
+ value: "000"
+ definition: |
+ registers[rd] = registers[rs1] - registers[rs2];
+
+ help: Subs the register rs2 from rs1 and stores the result in rd. Arithmetic overflow is ignored and the result is simply the low XLEN bits of the result.
+ - name: xor
+ extension: I
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ value: "100"
+ definition: |
+ registers[rd] = (registers[rs1] ^ registers[rs2]);
+
+ help: Performs bitwise XOR on registers rs1 and rs2 and place the result in rd.
+ - name: sb
+ extension: I
+ template: S
+ fields:
+ - field: opcode
+ value: "0100011"
+ - field: funct3
+ value: "000"
+ definition: |
+ CAPI.MEM.write(registers[rs1] + imm, 1, BigInt.asUintN(8, registers[rs2]), rs2, 'byte', false);
+
+ help: Store 8-bit, values from the low bits of register rs2 to memory.
+ - name: sh
+ extension: I
+ template: S
+ fields:
+ - field: opcode
+ value: "0100011"
+ - field: funct3
+ value: "001"
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 2))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 2, BigInt.asUintN(16, registers[rs2]), rs2, 'half', false);
+
+ help: Store 16-bit, values from the low bits of register rs2 to memory.
+ - name: sw
+ extension: I
+ template: S
+ fields:
+ - field: opcode
+ value: "0100011"
+ - field: funct3
+ value: "010"
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 4, BigInt.asUintN(32, registers[rs2]), rs2, 'word', false);
+
+ help: Store 32-bit, values from the low bits of register rs2 to memory.
+ - name: auipc
+ extension: I
+ template: U
+ fields:
+ - field: opcode
+ value: "0010111"
+ - field: imm
+ type: offset_bytes
+ definition: |
+ registers[rd] = registers["PC"] + (imm << 12n);
+
+ help: Build pc-relative addresses and uses the U-type format. AUIPC forms a 32-bit offset from the 20-bit U-immediate, filling in the lowest 12 bits with zeros, adds this offset to the pc, then places the result in register rd.
+ - name: lui
+ extension: I
+ template: U
+ fields:
+ - field: opcode
+ value: "0110111"
+ - field: imm
+ type: imm-unsigned
+ definition: |
+ registers[rd] = imm << 12n;
+
+ help: Build 32-bit constants and uses the U-type format. LUI places the U-immediate value in the top 20 bits of the destination register rd, filling in the lowest 12 bits with zeros.
+ - name: ecall
+ extension: I
+ template: Custom
+ type: Syscall
+ fields:
+ - field: opcode
+ value: "1110011"
+ - field: zeros
+ type: cop
+ startbit: 31
+ stopbit: 7
+ value: "0000000000000000000000000"
+ preoperation: 'let [fa0Value, fa0Type] = CAPI.ARCH.toJSNumberD(registers["fa0"]);'
+ definition: |
+ switch (registers["a7"]) {
+ case 1n:
+ CAPI.SYSCALL.print(registers["a0"], 'int32');
+ break;
+ case 2n:
+ case 3n:
+ CAPI.SYSCALL.print(fa0Value, 'float');
+ break;
+ case 4n:
+ CAPI.SYSCALL.print(registers["a0"], 'string');
+ break;
+ case 5n:
+ CAPI.SYSCALL.read('a0', 'int');
+ break;
+ case 6n:
+ CAPI.SYSCALL.read('fa0', 'float');
+ break;
+ case 7n:
+ CAPI.SYSCALL.read('fa0', 'double');
+ break;
+ case 8n:
+ CAPI.SYSCALL.read('a0', 'string', 'a1');
+ break;
+ case 9n:
+ CAPI.SYSCALL.sbrk('a0', 'a0');
+ break;
+ case 10n:
+ CAPI.SYSCALL.exit();
+ break;
+ case 11n:
+ CAPI.SYSCALL.print(registers["a0"], 'char');
+ break;
+ case 12n:
+ CAPI.SYSCALL.read('a0', 'char');
+ break;
+ }
+ help: Make a request to the supporting execution environment. When executed in U-mode, S-mode, or M-mode, it generates an environment-call-from-U-mode exception, environment-call-from-S-mode exception, or environment-call-from-M-mode exception, respectively, and performs no other operation.
+ - name: ebreak
+ extension: I
+ template: Custom
+ type: Syscall
+ fields:
+ - field: opcode
+ value: "1110011"
+ - field: funct12
+ type: cop
+ startbit: 31
+ stopbit: 20
+ value: "000000000001"
+ - field: zeros
+ type: cop
+ startbit: 19
+ stopbit: 7
+ value: "0000000000000"
+ definition: |
+ console.log('Not implemented: ebreak');
+ CAPI.VALIDATION.raise('ebreak not implemented');
+ help: Used by debuggers to cause control to be transferred back to a debugging environment. It generates a breakpoint exception and performs no other operation.
+ M:
+ - name: div
+ extension: M
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ value: "100"
+ definition: |
+ if (registers[rs2] != 0) {
+ registers[rd] = BigInt.asIntN(
+ 32,
+ (BigInt.asIntN(32, BigInt(registers[rs1])) / BigInt.asIntN(32, BigInt(registers[rs2])))
+ );
+ }
+ else CAPI.VALIDATION.raise('Division by registers[zero] not allowed');
+ help: Perform an XLEN bits by XLEN bits signed integer division of rs1 by rs2, rounding towards zero.
+ - name: divu
+ extension: M
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ value: "101"
+ definition: |
+ const div = registers[rs2]
+ if (div != 0) {
+ registers[rd] = BigInt.asIntN(
+ 32,
+ (BigInt.asUintN(32, registers[rs1]) / BigInt.asUintN(32, div))
+ );
+ }
+ else CAPI.VALIDATION.raise('Division by zero not allowed');
+ help: Perform an XLEN-bit by XLEN-bit unsigned integer division of rs1 by rs2, rounding towards zero.
+ - name: mul
+ extension: M
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ value: "000"
+ definition: |
+ registers[rd] = CAPI.FP.uint2int(registers[rs1]) * CAPI.FP.uint2int(registers[rs2]);
+
+ help: Performs an XLEN-bit by XLEN-bit multiplication of signed rs1 by signed rs2 and places the lower XLEN bits in the destination register.
+ - name: mulh
+ extension: M
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ value: "001"
+ definition: |
+ registers[rd] = BigInt.asUintN(
+ 32,
+ BigInt.asIntN(
+ 64,
+ BigInt.asIntN(32, registers[rs1]) * BigInt.asIntN(32, registers[rs2]),
+ ) >> 32n,
+ );
+ help: Performs an XLEN-bit by XLEN-bit multiplication of signed rs1 by signed rs2 and places the lower XLEN bits in the destination register.
+ - name: mulhsu
+ extension: M
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ value: "010"
+ definition: |
+ registers[rd] = BigInt.asIntN(
+ 32,
+ BigInt.asIntN(
+ 64,
+ BigInt.asIntN(32, registers[rs1]) * BigInt.asUintN(32, registers[rs2]),
+ ) >> 32n,
+ );
+ help: Performs an XLEN-bit by XLEN-bit multiplication of signed rs1 by unsigned rs2 and places the upper XLEN bits in the destination register.
+ - name: mulhu
+ extension: M
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ value: "011"
+ definition: |
+ registers[rd] = BigInt.asIntN(
+ 32,
+ BigInt.asUintN(
+ 64,
+ BigInt.asUintN(32, registers[rs1]) * BigInt.asUintN(32, registers[rs2]),
+ ) >> 32n,
+ );
+ help: Performs an XLEN-bit by XLEN-bit multiplication of unsigned rs1 by unsigned rs2 and places the upper XLEN bits in the destination register.
+ - name: rem
+ extension: M
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ value: "110"
+ definition: |
+ registers[rd] = registers[rs1] % registers[rs2];
+
+ help: Perform an XLEN-bit by XLEN-bit signed integer reminder of rs1 by rs2.
+ - name: remu
+ extension: M
+ template: R
+ fields:
+ - field: opcode
+ value: "0110011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ value: "111"
+ definition: |
+ registers[rd] = registers[rs1] % registers[rs2];
+
+ help: Perform an XLEN-bit by XLEN-bit unsigned integer reminder of rs1 by rs2.
+ F:
+ - name: flw
+ extension: F
+ template: I-Offset
+ type: Memory access
+ fields:
+ - field: opcode
+ value: "0000111"
+ - field: funct3
+ value: "010"
+ - field: rd
+ type: DFP-Reg
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[rd] = CAPI.MEM.read(addr, 4, rd, false);
+
+ postoperation: |
+ registers[rd] = CAPI.ARCH.NaNBox(registers[rd]);
+
+ help: Load a single-precision floating-point value from memory into floating-point register rd.
+ - name: fadd.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0000000"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 4
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = rs1Number + rs2Number;
+
+ help: Perform single-precision floating-point addition.
+ - name: fclass.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1110000"
+ - field: funct3
+ value: "001"
+ - field: rs1
+ suffix: null
+ - field: rs2
+ type: cop
+ value: "00000"
+ order: null
+ - field: rd
+ type: INT-Reg
+ preoperation: |
+ let rs1Value, rs2Value, type_rs1, type_rs2;
+ [rs1Value, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Value, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(registers[rd])) {
+ registers[rd] = CAPI.ARCH.toBigInt(registers[rd], "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(registers[rd], "NaNBfloat32_64");
+ }
+ registers[rs1] = CAPI.ARCH.toBigInt(rs1Value, type_rs1);
+ registers[rs2] = CAPI.ARCH.toBigInt(rs2Value, type_rs2);
+ definition: |
+ let a = CAPI.FP.float2bin(registers[rs1]);
+ registers[rd] = CAPI.FP.check_ieee(
+ parseInt(a[0]),
+ parseInt(a.slice(1, 9), 2),
+ parseInt(a.slice(10), 2),
+ );
+ help: Examines the value in floating-point register rs1 and writes to integer register rd a 10-bit mask that indicates the class of the floating-point number. The corresponding bit in rd will be set if the property is true and clear otherwise. All other bits in rd are cleared. Note that exactly one bit in rd will be set.
+ - name: fcvt.s.w
+ extension: F
+ template: R-IntToFloat
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1101000"
+ - field: funct5
+ value: "00000"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ postoperation: |
+ registers[rd] = CAPI.ARCH.toBigInt(result,'NaNBfloat32_64');
+ definition: |
+ result = CAPI.FP.uint2int(registers[rs1])
+
+ help: Converts a 32-bit signed integer, in integer register rs1 into a floating-point number in floating-point register rd.
+ - name: fcvt.s.wu
+ extension: F
+ template: R-IntToFloat
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1101000"
+ - field: funct5
+ value: "00001"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ definition: |
+ registers[rd] = CAPI.FP.int2uint(registers[rs1])
+
+ help: Converts a 32-bit unsigned integer, in integer register rs1 into a floating-point number in floating-point register rd.
+ - name: fcvt.w.s
+ extension: F
+ template: R-FloatToInt
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1100000"
+ - field: funct5
+ value: "00000"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = parseInt(registers[rs1]);
+
+ help: Convert a floating-point number in floating-point register rs1 to a signed 32-bit in integer register rd.
+ - name: fcvt.wu.s
+ extension: F
+ template: R-FloatToInt
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1100000"
+ - field: funct5
+ value: "00001"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+ definition: |
+ registers[rd] = CAPI.FP.int2uint(parseInt(rs1Number));
+
+ help: Convert a floating-point number in floating-point register rs1 to a signed 32-bit in unsigned integer register rd.
+ - name: fdiv.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0001100"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 4
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+ definition: |
+ if (rs2Number != 0) { result = rs1Number / rs2Number; }
+ else CAPI.VALIDATION.raise('Division by registers[zero] not allowed');
+
+ help: Perform single-precision floating-point division.
+ - name: feq.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1010000"
+ - field: funct3
+ value: "010"
+ - field: rd
+ type: INT-Reg
+ preoperation: |
+ let rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ definition: |
+ registers[rd] = (rs1Number === rs2Number)? 1n : 0n;
+
+ help: Performs a quiet equal comparison between floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
+ - name: fle.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1010000"
+ - field: funct3
+ value: "000"
+ - field: rd
+ type: INT-Reg
+ preoperation: |
+ let rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ definition: |
+ registers[rd] = (rs1Number <= rs2Number)? 1n : 0n;
+
+ help: Performs a quiet less or equal comparison between floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
+ - name: flt.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1010000"
+ - field: funct3
+ value: "001"
+ - field: rd
+ type: INT-Reg
+ preoperation: |
+ let rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ definition: |
+ registers[rd] = (rs1Number < rs2Number)? 1n : 0n;
+
+ help: Performs a quiet less comparison between floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
+ - name: fmax.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010100"
+ - field: funct3
+ value: "001"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = Math.max(rs1Number, rs2Number);
+
+ help: Write the larger of single precision data in rs1 and rs2 to rd.
+ - name: fmin.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010100"
+ - field: funct3
+ value: "000"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+ definition: |
+ result = Math.min(rs1Number, rs2Number);
+
+ help: Write the smaller of single precision data in rs1 and rs2 to rd.
+ - name: fmul.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0001000"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 4
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+ definition: |
+ result = rs2Number * rs1Number;
+
+ help: Perform single-precision floating-point multiplication.
+ - name: fmv.w.x
+ extension: F
+ template: R-IntToFloat
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1111000"
+ - field: funct5
+ value: "00000"
+ - field: funct3
+ value: "000"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = CAPI.FP.uint2float32(rs1Number);
+
+ help: Move the single-precision value encoded in IEEE 754-2008 standard encoding from the lower 32 bits of integer register rs1 to the floating-point register rd.
+ - name: fmv.x.w
+ extension: F
+ template: R-FloatToInt
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1110000"
+ - field: funct5
+ value: "00000"
+ - field: funct3
+ value: "000"
+ preoperation: |
+ let result, rs1Number, type_rs1;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+ registers[rs1] = CAPI.ARCH.toBigInt(rs1Number, type_rs1);
+ definition: |
+ result = CAPI.FP.float322uint(rs1Number);
+
+ help: Move the single-precision value in floating-point register rs1 represented in IEEE 754-2008 encoding to the lower 32 bits of integer register rd.
+ - name: fsgnj.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010000"
+ - field: funct3
+ value: "000"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+ definition: |
+ result = (rs2Number >= 0) ? Math.abs(rs1Number) : -Math.abs(rs1Number);
+
+ help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is rs2's sign bit.
+ - name: fsgnjn.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010000"
+ - field: funct3
+ value: "001"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+ definition: |
+ result = (rs2Number <= 0) ? Math.abs(rs1Number) : -Math.abs(rs1Number);
+ help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is rs2's sign bit.
+ - name: fsgnjx.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010000"
+ - field: funct3
+ value: "010"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+ definition: |
+ let a = rs1Number < 0;
+ let b = rs2Number < 0;
+ result = a ^ b ? -Math.abs(rs1Number) : Math.abs(rs1Number);
+ help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is XOR of sign bit of rs1 and rs2.
+ - name: fsqrt.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0101100"
+ - field: rs2
+ type: cop
+ value: "00000"
+ order: null
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ preoperation: |
+ let result, rs1Number, type_rs1;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ if (rs1Number >= 0) {
+ result = Math.sqrt(rs1Number);
+ } else {
+ CAPI.VALIDATION.raise(
+ "Square root of a negative number is not allowed."
+ );
+ }
+ help: Perform single-precision square root.
+ - name: fsub.s
+ extension: F
+ template: R-Floating
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0000100"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 4
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = rs1Number - rs2Number;
+
+ help: Perform single-precision floating-point subtraction.
+ - name: fmadd.s
+ extension: F
+ template: R4
+ fields:
+ - field: opcode
+ value: "1000011"
+ - field: funct2
+ value: "00"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 5
+ preoperation: |
+ let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = rs1Number * rs2Number + rs3Number;
+
+ help: Perform single-precision fused multiply addition.
+ - name: fmsub.s
+ extension: F
+ template: R4
+ fields:
+ - field: opcode
+ value: "1000111"
+ - field: funct2
+ value: "00"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 5
+ preoperation: |
+ let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = rs1Number * rs2Number - rs3Number;
+
+ help: Perform single-precision fused multiply addition.
+ - name: fnmadd.s
+ extension: F
+ template: R4
+ fields:
+ - field: opcode
+ value: "1001111"
+ - field: funct2
+ value: "00"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 5
+ preoperation: |
+ let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = -rs1Number * rs2Number - rs3Number;
+
+ help: Perform negated single-precision fused multiply addition.
+ - name: fnmsub.s
+ extension: F
+ template: R4
+ fields:
+ - field: opcode
+ value: "1001011"
+ - field: funct2
+ value: "00"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 5
+ preoperation: |
+ let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaNBfloat32_64");
+ }
+
+ definition: |
+ result = -rs1Number * rs2Number + rs3Number;
+
+ help: Perform negated single-precision fused multiply addition.
+ - name: fsw
+ extension: F
+ template: S
+ fields:
+ - field: opcode
+ value: "0100111"
+ - field: funct3
+ value: "010"
+ - field: rs2
+ type: DFP-Reg
+ definition: |
+ let value = registers[rs2] & 0xFFFFFFFFn;
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 4))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 4, value, rs2, 'float32', false);
+ help: Store a single-precision value from floating-point register rs2 to memory.
+ D:
+ - name: fld
+ extension: D
+ template: I-Offset
+ type: Memory access
+ fields:
+ - field: opcode
+ value: "0000111"
+ - field: funct3
+ value: "011"
+ - field: rd
+ type: DFP-Reg
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 8))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ registers[rd] = CAPI.MEM.read(addr, 8, rd, false);
+ help: Load a double-precision floating-point value from memory into floating-point register rd.
+ - name: fadd.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0000001"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 4
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+ definition: |
+ result = rs1Number + rs2Number;
+
+ help: Perform double-precision floating-point addition.
+ - name: fclass.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1110001"
+ - field: funct3
+ value: "001"
+ - field: rs1
+ suffix: null
+ - field: rs2
+ type: cop
+ value: "00000"
+ order: null
+ - field: rd
+ type: INT-Reg
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+ definition: |
+ let a = CAPI.FP.float2bin(rs1Number);
+ registers[rd] = CAPI.FP.check_ieee(
+ parseInt(a[0]),
+ parseInt(a.slice(1, 12), 2),
+ parseInt(a.slice(13), 2),
+ );
+ help: Examines the value in double-precision floating-point register rs1 and writes to integer register rd a 10-bit mask that indicates the class of the floating-point number. The corresponding bit in rd will be set if the property is true and clear otherwise. All other bits in rd are cleared. Note that exactly one bit in rd will be set.
+ - name: fcvt.d.s
+ extension: D
+ template: R-Conversion
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: rd
+ type: DFP-Reg
+ - field: rs1
+ type: DFP-Reg
+ - field: funct7
+ value: "0100001"
+ - field: funct5
+ value: "00000"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: null
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+ definition: |
+ result = rs1Number; // TODO: This doesn't seem right, check the RISC-V manual
+
+ help: Converts double floating-point register in rs1 into a double floating-point number in floating-point register rd.
+ - name: fcvt.d.w
+ extension: D
+ template: R-Conversion
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1101001"
+ - field: funct5
+ value: "00000"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: null
+ - field: rd
+ type: DFP-Reg
+ - field: rs1
+ type: INT-Reg
+ preoperation: |
+ let result, rs1Number;
+ rs1Number = registers[rs1];
+ postoperation: |
+ registers[rd] = CAPI.ARCH.toBigInt(result, 'float64');
+ definition: |
+ result = CAPI.FP.uint2int(rs1Number);
+
+ help: Converts a 32-bit signed integer, in integer register rs1 into a double-precision floating-point number in floating-point register rd.
+ - name: fcvt.d.wu
+ extension: D
+ template: R-Conversion
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1101001"
+ - field: funct5
+ value: "00001"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: null
+ - field: rd
+ type: DFP-Reg
+ - field: rs1
+ type: INT-Reg
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+ definition: |
+ result = CAPI.FP.int2uint(parseFloat(rs1Number));
+
+ help: Converts a 32-bit unsigned integer, in integer register rs1 into a double-precision floating-point number in floating-point register rd.
+ - name: fcvt.s.d
+ extension: D
+ template: R-Conversion
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0100000"
+ - field: funct5
+ value: "00001"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ - field: rd
+ type: DFP-Reg
+ - field: rs1
+ type: DFP-Reg
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+ definition: |
+ result = rs1Number; // TODO: This doesn't seem right, check the RISC-V manual
+
+ help: Converts double floating-point register in rs1 into a floating-point number in floating-point register rd.
+ - name: fcvt.w.d
+ extension: D
+ template: R-Conversion
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1100001"
+ - field: funct5
+ value: "00000"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ - field: rd
+ type: INT-Reg
+ - field: rs1
+ type: DFP-Reg
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ result = CAPI.FP.int2uint(parseInt(rs1Number));
+
+ help: Converts a double-precision floating-point number in floating-point register rs1 to a signed 32-bit integer, in integer register rd.
+ - name: fcvt.wu.d
+ extension: D
+ template: R-Conversion
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1100001"
+ - field: funct5
+ value: "00001"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ - field: rd
+ type: INT-Reg
+ - field: rs1
+ type: DFP-Reg
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ result = CAPI.FP.int2uint(parseInt(rs1Number));
+
+ help: Converts a double-precision floating-point number in floating-point register rs1 to a unsigned 32-bit integer, in integer register rd.
+ - name: fdiv.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0001101"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 4
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ result = rs1Number / rs2Number;
+ help: Perform double-precision floating-point division.
+ - name: feq.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1010001"
+ - field: funct3
+ value: "010"
+ - field: rd
+ type: INT-Reg
+ preoperation: |
+ let rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ definition: |
+ registers[rd] = (rs1Number == rs2Number)? 1n : 0n;
+
+ help: Performs a quiet equal comparison between double-precision floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
+ - name: fle.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1010001"
+ - field: funct3
+ value: "000"
+ - field: rd
+ type: INT-Reg
+ preoperation: |
+ let rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ definition: |
+ registers[rd] = (rs1Number <= rs2Number) ? 1n : 0n;
+
+ help: Performs a quiet less or equal comparison between double-precision floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
+ - name: flt.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "1010001"
+ - field: funct3
+ value: "001"
+ - field: rd
+ type: INT-Reg
+ preoperation: |
+ let rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ definition: |
+ registers[rd] = (rs1Number < rs2Number)? 1n : 0n;
+
+ help: Performs a quiet less comparison between double-precision floating-point registers rs1 and rs2 and record the Boolean result in integer register rd. Only signaling NaN inputs cause an Invalid Operation exception. The result is 0 if either operand is NaN.
+ - name: fmax.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010101"
+ - field: funct3
+ value: "001"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ result = Math.max(rs1Number, rs2Number);
+
+ help: Write the larger of double precision data in rs1 and rs2 to rd.
+ - name: fmin.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010101"
+ - field: funct3
+ value: "000"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ result = Math.min(rs1Number, rs2Number);
+
+ help: Write the smaller of double precision data in rs1 and rs2 to rd.
+ - name: fmul.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0001001"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 4
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ result = rs1Number * rs2Number;
+
+ help: Perform double-precision floating-point addition.
+ - name: fsgnj.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010001"
+ - field: funct3
+ value: "000"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ registers[rd] = (rs2Number > 0) ? Math.abs(rs1Number) : -Math.abs(rs1Number);
+ help: Perform double-precision floating-point multiplication.
+ - name: fsgnjn.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010001"
+ - field: funct3
+ value: "001"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ result = (rs2Number > 0) ? -Math.abs(rs1Number) : +Math.abs(rs1Number);
+
+ help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is opposite of rs2's sign bit.
+ - name: fsgnjx.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0010001"
+ - field: funct3
+ value: "010"
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ let a = rs1Number < 0;
+ let b = rs2Number < 0;
+ result = a ^ b ? -Math.abs(rs1Number) : Math.abs(rs1Number);
+ help: Produce a result that takes all bits except the sign bit from rs1. The result's sign bit is XOR of sign bit of rs1 and rs2.
+ - name: fsqrt.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0101101"
+ - field: rs2
+ type: cop
+ value: "00000"
+ order: null
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 3
+ preoperation: |
+ let result, rs1Number, type_rs1;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ if (rs1Number >= 0) {
+ result = Math.sqrt(rs1Number);
+ } else {
+ CAPI.VALIDATION.raise(
+ "Square root of a negative number is not allowed."
+ );
+ }
+ help: Perform double-precision square root.
+ - name: fsub.d
+ extension: D
+ template: R-Double
+ fields:
+ - field: opcode
+ value: "1010011"
+ - field: funct7
+ value: "0000101"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 4
+ preoperation: |
+ let result, rs1Number, rs2Number, type_rs1, type_rs2;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ definition: |
+ result = rs1Number - rs2Number;
+
+ help: Perform double-precision floating-point addition.
+ - name: fmadd.d
+ extension: D
+ template: R4-Double
+ fields:
+ - field: opcode
+ value: "1000011"
+ - field: funct2
+ value: "01"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 5
+ preoperation: |
+ let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ registers[rs3] = CAPI.ARCH.toBigInt(rs3Number, type_rs3);
+ definition: |
+ result = rs1Number * rs2Number + rs3Number;
+
+ help: Perform double-precision fused multiply addition.
+ - name: fmsub.d
+ extension: D
+ template: R4-Double
+ fields:
+ - field: opcode
+ value: "1000111"
+ - field: funct2
+ value: "01"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 5
+ preoperation: |
+ let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ registers[rs3] = CAPI.ARCH.toBigInt(rs3Number, type_rs3);
+ definition: |
+ result = rs1Number * rs2Number - rs3Number;
+
+ help: Perform double-precision fused multiply subtraction.
+ - name: fnmadd.d
+ extension: D
+ template: R4-Double
+ fields:
+ - field: opcode
+ value: "1001111"
+ - field: funct2
+ value: "01"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 5
+ preoperation: |
+ let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ registers[rs3] = CAPI.ARCH.toBigInt(rs3Number, type_rs3);
+ definition: |
+ result = -rs1Number * rs2Number - rs3Number;
+
+ help: Perform negated double-precision fused multiply addition.
+ - name: fnmsub.d
+ extension: D
+ template: R4-Double
+ fields:
+ - field: opcode
+ value: "1001011"
+ - field: funct2
+ value: "01"
+ - field: funct3
+ type: enum
+ enum_name: rounding_mode
+ optional: true
+ order: 5
+ preoperation: |
+ let result, rs1Number, rs2Number, rs3Number, type_rs1, type_rs2, type_rs3;
+ [rs1Number, type_rs1] = CAPI.ARCH.toJSNumberD(registers[rs1]);
+ [rs2Number, type_rs2] = CAPI.ARCH.toJSNumberD(registers[rs2]);
+ [rs3Number, type_rs3] = CAPI.ARCH.toJSNumberD(registers[rs3]);
+ postoperation: |
+ if (isNaN(result)) {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64");
+ } else {
+ registers[rd] = CAPI.ARCH.toBigInt(result, "float64");
+ }
+
+ registers[rs3] = CAPI.ARCH.toBigInt(rs3Number, type_rs3);
+ definition: |
+ result = -rs1Number * rs2Number + rs3Number;
+
+ help: Perform negated double-precision fused multiply subtraction.
+ - name: fsd
+ extension: D
+ template: S
+ fields:
+ - field: opcode
+ value: "0100111"
+ - field: funct3
+ value: "011"
+ - field: rs2
+ type: DFP-Reg
+ definition: |
+ let addr = registers[rs1] + imm;
+ if (CAPI.VALIDATION.isMisaligned(addr, 8))
+ CAPI.VALIDATION.raise('The memory must be aligned');
+ CAPI.MEM.write(addr, 8, registers[rs2], rs2, 'float64', false);
+ help: Store a double-precision value from the floating-point registers to memory.
+ Zifencei:
+ - name: fence.i
+ extension: D
+ 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!)
+
+ # RV32I Pseudoinstructions
+ I:
+ - name: beqz
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ beq rs1, x0, off;
+
+ - name: bgez
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ bge rs1, x0, off;
+ help: Take the branch if the value in register rs1 is zero.
+
+ - name: bgt
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: rs2
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ blt rs2, rs1, off;
+
+ - name: bgtu
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: rs2
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ bltu rs2, rs1, off;
+
+ - name: bgtz
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ bgt rs1, x0, off;
+
+ - name: ble
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: rs2
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ bge rs2, rs1, off;
+
+ - name: bleu
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: rs2
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ bgeu rs2, rs1, off;
+
+ - name: blez
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ ble x0, rs1, off;
+
+ - name: bltz
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ blt rs1, x0, off;
+
+ - name: bnez
+ extension: I
+ fields:
+ - field: rs1
+ type: INT-Reg
+ suffix: ","
+ - field: off
+ type: offset_bytes
+ definition: |
+ bne rs1, x0, off;
+
+ - name: j
+ extension: I
+ fields:
+ - field: off
+ type: offset_bytes
+ definition: |
+ beq zero, zero, off;
+
+ - name: jalr
+ extension: I
+ fields:
+ - field: rs
+ type: INT-Reg
+ definition: |
+ jalr x1, 0(rs);
+
+ - name: jr
+ extension: I
+ fields:
+ - field: rs
+ type: INT-Reg
+ definition: |
+ jalr x0, 0(rs);
+
+ - name: la
+ extension: I
+ fields:
+ - field: rd
+ type: INT-Reg
+ suffix: ","
+ - field: addr
+ type: imm-unsigned
+ definition: |
+ no_ret_op{
+ tmp = Field.2.(31,0).int - (reg.pc - 4);
+ tmp_low = tmp & 0x00000FFF;
+ tmp_low = tmp_low>0x7FF? tmp_low - 0x1000 : tmp_low;
+ tmp_hi = (tmp - tmp_low) >> 12;
+ };
+ auipc rd, op{tmp_hi};
+ addi rd, rd, op{tmp_low};
+
+ - name: li
+ extension: I
+ fields:
+ - field: rd
+ type: INT-Reg
+ suffix: ","
+ - field: val
+ type: imm-signed
+ definition: |
+ no_ret_op{
+ tmp = Field.2.(31,0).int;
+ tmp_low = tmp & 0x00000FFF;
+ tmp_low -= tmp_low > 0x7FF ? 0x1000 : 0;
+ tmp_hi = (tmp - tmp_low) >>> 12;
+ };
+ if (tmp_hi === 0) {
+ addi rd, x0, op{tmp_low};
+ }
+ else {
+ lui rd, op{tmp_hi};
+ addi rd, rd, op{tmp_low};
+ };
+ help: Load the sign-extended 6-bit immediate, imm, into register rd.
+
+ - name: mv
+ extension: I
+ fields:
+ - field: reg1
+ type: INT-Reg
+ suffix: ","
+ - field: reg2
+ type: INT-Reg
+ definition: |
+ addi reg1, reg2, 0;
+ help: Copy the value in register rs2 into register rd.
+
+ - name: neg
+ extension: I
+ fields:
+ - field: reg1
+ type: INT-Reg
+ suffix: ","
+ - field: reg2
+ type: INT-Reg
+ definition: |
+ sub reg1, x0, reg2;
+
+ - name: nop
+ extension: I
+ definition: |
+ addi x0, x0, 0;
+ help: Does not change any user-visible state, except for advancing the pc.
+
+ - name: not
+ extension: I
+ fields:
+ - field: reg1
+ type: INT-Reg
+ suffix: ","
+ - field: reg2
+ type: INT-Reg
+ definition: |
+ xori reg1, reg2, -1;
+
+ - name: ret
+ extension: I
+ definition: |
+ jalr x0, 0(x1); # TODO: check this!
+
+ - name: seqz
+ extension: I
+ fields:
+ - field: reg1
+ type: INT-Reg
+ suffix: ","
+ - field: reg2
+ type: INT-Reg
+ definition: |
+ sltiu reg1, reg2, 1;
+
+ - name: sgtz
+ extension: I
+ fields:
+ - field: reg1
+ type: INT-Reg
+ suffix: ","
+ - field: reg2
+ type: INT-Reg
+ definition: |
+ slt reg1, x0, reg2;
+
+ - name: sltz
+ extension: I
+ fields:
+ - field: reg1
+ type: INT-Reg
+ suffix: ","
+ - field: reg2
+ type: INT-Reg
+ definition: |
+ slt reg1, reg2, x0;
+
+ - name: snez
+ extension: I
+ fields:
+ - field: reg1
+ type: INT-Reg
+ suffix: ","
+ - field: reg2
+ type: INT-Reg
+ definition: |
+ sltu reg1, x0, reg2;
+ F:
+ # RV32F Pseudoinstructions
+ - name: fabs.s
+ extension: F
+ fields:
+ - field: rs1
+ type: DFP-Reg
+ suffix: ","
+ - field: rs2
+ type: DFP-Reg
+ definition: |
+ fsgnjx.s rs1, rs2, rs2;
+
+ - name: fmv.s
+ extension: F
+ fields:
+ - field: rs1
+ type: DFP-Reg
+ suffix: ","
+ - field: rs2
+ type: DFP-Reg
+ definition: |
+ fsgnj.s rs1, rs2, rs2;
+
+ - name: fneg.s
+ extension: F
+ fields:
+ - field: rs1
+ type: DFP-Reg
+ suffix: ","
+ - field: rs2
+ type: DFP-Reg
+ definition: |
+ fsgnjn.s rs1, rs2, rs2;
+ D:
+ # RV32D Pseudoinstructions
+ - name: fabs.d
+ extension: D
+ fields:
+ - field: rs1
+ type: DFP-Reg
+ suffix: ","
+ - field: rs2
+ type: DFP-Reg
+ definition: |
+ fsgnjx.d rs1, rs2, rs2;
+
+ - name: fmv.d
+ extension: D
+ fields:
+ - field: rs1
+ type: DFP-Reg
+ suffix: ","
+ - field: rs2
+ type: DFP-Reg
+ definition: |
+ fsgnj.d rs1, rs2, rs2;
+
+ - name: fneg.d
+ extension: D
+ fields:
+ - field: rs1
+ type: DFP-Reg
+ suffix: ","
+ - field: rs2
+ type: DFP-Reg
+ definition: |
+ fsgnjn.d rs1, rs2, rs2;
+
+enums:
+ rounding_mode:
+ rne: 0
+ rtz: 1
+ rdn: 2
+ rup: 3
+ rmm: 4
+ dyn: 7
+ DEFAULT: dyn
diff --git a/architecture/available_arch.json b/architecture/available_arch.json
index bbc9a7400..babddbe29 100644
--- a/architecture/available_arch.json
+++ b/architecture/available_arch.json
@@ -15,11 +15,11 @@
"alt": "RISC-V",
"id": "select_confRISV",
"examples": ["default"],
- "description": "RISC-V is an instruction set architecture (ISA) based on the RISC type and its hardware is free. This architecture was created in 2010 at the University of California, Berkeley.",
+ "description": "RISC-V is a free and open-standard instruction set architecture (ISA) based on RISC principles. This architecture was developed in 2010 at the University of California, Berkeley.
This ISA includes the 32-bit I (integer), M (multiplication and division), F (single-precision floating-point), and D (double-precision floating-point) RISC-V extensions.",
"guide": "guides/riscv.pdf",
"available": true
},
- {
+ {
"name": "RISC-V (RV64IMFD)",
"alias": [
"RISC-V (RV64IMFD)",
@@ -35,7 +35,39 @@
"alt": "RISC-V",
"id": "select_confRISV",
"examples": ["default"],
- "description": "RISC-V is an instruction set architecture (ISA) based on the RISC type and its hardware is free. This architecture was created in 2010 at the University of California, Berkeley.",
+ "description": "RISC-V is a free and open-standard instruction set architecture (ISA) based on RISC principles. This architecture was developed in 2010 at the University of California, Berkeley.
This ISA includes the 64-bit I (integer), M (multiplication and division), F (single-precision floating-point), and D (double-precision floating-point) RISC-V extensions.",
+ "guide": "/guides/riscv.pdf",
+ "available": true
+ },
+ {
+ "name": "RISC-V Sail 32 - Full Specification",
+ "alias": [
+ "RISC-V (SRV32)",
+ "SRV32",
+ "srv32"
+ ],
+ "file": "RISCV/SRV32",
+ "img": "riscv.png",
+ "alt": "RISC-V",
+ "id": "select_confRISV",
+ "examples": ["default"],
+ "description": "RISC-V is a free and open-standard instruction set architecture (ISA) based on RISC principles. This architecture was developed in 2010 at the University of California, Berkeley.
This ISA includes the full 32-bit specification of RISC-V based on Sail.",
+ "guide": "/guides/riscv.pdf",
+ "available": true
+ },
+ {
+ "name": "RISC-V Sail 64 - Full Specification",
+ "alias": [
+ "RISC-V (SRV64)",
+ "SRV64",
+ "srv64"
+ ],
+ "file": "RISCV/SRV64",
+ "img": "riscv.png",
+ "alt": "RISC-V",
+ "id": "select_confRISV",
+ "examples": ["default"],
+ "description": "RISC-V is a free and open-standard instruction set architecture (ISA) based on RISC principles. This architecture was developed in 2010 at the University of California, Berkeley.