diff --git a/.editorconfig b/.editorconfig index 7f5b23fc3..ee80e45e9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,9 +1,10 @@ -[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue}] charset = utf-8 -indent_size = 2 +indent_size = 4 indent_style = space insert_final_newline = true trim_trailing_whitespace = true - end_of_line = lf -max_line_length = 100 +max_line_length = 80 + +[*.{vue,json,jsonc,html,css,config.ts,lock,yaml,yml}] +indent_size = 2 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 e5b3efb40..825c89625 100644 --- a/architecture/RISCV/RV32IMFD.yml +++ b/architecture/RISCV/RV32IMFD.yml @@ -166,8 +166,8 @@ components: - x1 - ra nbits: 32 - value: 0xFFFFFF00 - default_value: 0xFFFFFF00 + value: -1 + default_value: -1 encoding: 1 properties: - read @@ -890,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 @@ -1516,7 +1526,7 @@ instructions: - field: funct3 value: "111" definition: | - if (CAPI.FP.int2uint(registers[rs1]) > CAPI.FP.int2uint(registers[rs2])) + 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. @@ -1601,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,7 +1627,7 @@ instructions: value: "000" definition: | let addr = registers[rs1] + imm; - const result = CAPI.MEM.read(addr, 1, rd); + 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. @@ -1629,8 +1641,8 @@ 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 @@ -1643,7 +1655,9 @@ instructions: value: "001" definition: | let addr = registers[rs1] + imm; - const result = CAPI.MEM.read(addr, 2, rd); + 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. @@ -1656,9 +1670,11 @@ 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 @@ -1670,8 +1686,10 @@ instructions: - field: funct3 value: "010" definition: | - let addr = CAPI.FP.int2uint(registers[rs1], 32) + imm; - registers[rd] = CAPI.MEM.read(addr, 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); help: Loads a 32-bit value from memory and sign-extends this to XLEN bits before storing it in register rd. - name: ori @@ -1735,7 +1753,7 @@ instructions: - field: funct7 value: "0100000" definition: | - if (shamt > 0) registers[rd] = CAPI.FP.int2uint(registers[rs1] >> shamt); + 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 @@ -1951,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 @@ -1962,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: @@ -1974,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 @@ -2110,11 +2133,9 @@ 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 zero not allowed'); help: Perform an XLEN-bit by XLEN-bit unsigned integer division of rs1 by @@ -2144,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. @@ -2164,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. @@ -2184,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. @@ -2240,7 +2249,10 @@ 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]); @@ -2323,9 +2335,9 @@ 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]) + 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 @@ -2441,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 @@ -2469,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 @@ -2497,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 @@ -2726,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"); @@ -2740,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. @@ -2787,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"); @@ -2814,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"); @@ -2841,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"); @@ -2868,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"); @@ -2890,7 +2883,10 @@ instructions: type: DFP-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: @@ -2912,10 +2908,10 @@ 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(addr, 8, rd, false); help: Load a double-precision floating-point value from memory into floating-point register rd. - name: fadd.d @@ -3035,8 +3031,8 @@ 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: | @@ -3209,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 @@ -3240,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 @@ -3268,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 @@ -3396,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. @@ -3422,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. @@ -3443,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"); @@ -3454,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." @@ -3610,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. @@ -3733,7 +3713,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 greater or equal to 0. - name: bgt @@ -4084,6 +4064,7 @@ interrupts: break; } CAPI.INTERRUPTS.clearHighlight(); + CAPI.STACK.endFrame(); custom: | CAPI.INTERRUPTS.globalDisable(); diff --git a/architecture/RISCV/RV64IMFD.yml b/architecture/RISCV/RV64IMFD.yml index 8805994ce..5efea7a0a 100644 --- a/architecture/RISCV/RV64IMFD.yml +++ b/architecture/RISCV/RV64IMFD.yml @@ -167,8 +167,8 @@ components: - x1 - ra nbits: 64 - value: 18446744073709551615 - default_value: 18446744073709551615 + value: -1 + default_value: -1 encoding: 1 properties: - read @@ -177,8 +177,8 @@ components: - x2 - sp nbits: 64 - value: 268435452 - default_value: 268435452 + value: 0x0FFFFFFC + default_value: 0x0FFFFFFC encoding: 2 properties: - read @@ -1516,7 +1516,7 @@ instructions: - field: funct3 value: "111" definition: | - if (CAPI.FP.int2uint(registers[rs1]) > CAPI.FP.int2uint(registers[rs2])) + 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. @@ -1619,8 +1619,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(64, pc) === -1n) CAPI.SYSCALL.exit(); + else CAPI.STACK.endFrame(); help: Jump to address and place return address in rd. - name: lb @@ -1633,7 +1635,7 @@ instructions: value: "000" definition: | let addr = registers[rs1] + imm; - const result = CAPI.MEM.read(addr, 1, rd); + 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. @@ -1647,8 +1649,8 @@ 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 @@ -1661,7 +1663,9 @@ instructions: value: "001" definition: | let addr = registers[rs1] + imm; - const result = CAPI.MEM.read(addr, 2, rd); + 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. @@ -1674,9 +1678,11 @@ 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 @@ -1688,8 +1694,10 @@ instructions: - field: funct3 value: "010" definition: | - let addr = CAPI.FP.int2uint(registers[rs1], 32) + imm; - registers[rd] = CAPI.MEM.read(addr, 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); help: Loads a 32-bit value from memory and sign-extends this to XLEN bits before storing it in register rd. - name: lwu @@ -1701,9 +1709,11 @@ 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]); + 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 @@ -1715,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 @@ -1832,7 +1844,7 @@ instructions: - field: funct7 value: "0000000" definition: | - if (shamt > 0) rd = (rs1 >> shamt); + 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 @@ -1848,7 +1860,7 @@ 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]); } @@ -2100,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 @@ -2136,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 @@ -2147,7 +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 @@ -2159,7 +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 @@ -2170,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. @@ -2295,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, BigInt(registers[rs1])) / BigInt.asUintN(32, BigInt(registers[rs2]))) + (BigInt.asUintN(32, registers[rs1]) / BigInt.asUintN(32, div)) ); } else CAPI.VALIDATION.raise('Division by zero not allowed'); @@ -2329,7 +2352,7 @@ instructions: - field: funct3 value: "001" definition: | - registers[rd] = BigInt.asIntN( + registers[rd] = BigInt.asUintN( 32, BigInt.asIntN( 64, @@ -2426,7 +2449,10 @@ 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. @@ -2505,9 +2531,9 @@ 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 @@ -2623,17 +2649,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 @@ -2651,17 +2671,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 @@ -2679,17 +2693,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 @@ -2908,9 +2916,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"); @@ -2922,7 +2929,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. @@ -2969,7 +2976,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"); @@ -2996,7 +3003,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"); @@ -3023,7 +3030,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"); @@ -3050,7 +3057,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"); @@ -3072,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: @@ -3094,10 +3104,10 @@ 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 @@ -3215,8 +3225,8 @@ 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: | @@ -3389,17 +3399,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 @@ -3420,14 +3424,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 @@ -3448,14 +3446,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 @@ -3576,7 +3568,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. @@ -3602,7 +3594,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. @@ -3623,9 +3615,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"); @@ -3634,7 +3625,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." @@ -3790,11 +3781,10 @@ 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. Priv: @@ -3915,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 @@ -4257,6 +4247,7 @@ interrupts: break; } CAPI.INTERRUPTS.clearHighlight(); + CAPI.STACK.endFrame(); custom: | CAPI.INTERRUPTS.globalDisable(); diff --git a/architecture/RISCV/SRV32.yml b/architecture/RISCV/SRV32.yml index acb3049ed..1bc57cd10 100644 --- a/architecture/RISCV/SRV32.yml +++ b/architecture/RISCV/SRV32.yml @@ -77,8 +77,8 @@ components: - x1 - ra nbits: 32 - value: 4294967295 - default_value: 4294967295 + value: -1 + default_value: -1 encoding: 1 properties: - read @@ -87,8 +87,8 @@ components: - x2 - sp nbits: 32 - value: 268435452 - default_value: 26843545 + value: 0x0FFFFFFC + default_value: 0x0FFFFFFC encoding: 2 properties: - read @@ -2084,7 +2084,7 @@ instructions: - field: funct3 value: "111" definition: | - if (CAPI.FP.int2uint(registers[rs1]) > CAPI.FP.int2uint(registers[rs2])) + 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 @@ -2160,9 +2160,11 @@ instructions: - field: funct3 value: "000" definition: | - registers[rd] = registers["PC"] + 4n; - registers["PC"] = (registers[rs1] + imm) & ~1n; - CAPI.CHECK_STACK.end(); CAPI.DRAW_STACK.end(registers["PC"]); + 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 @@ -2174,7 +2176,7 @@ instructions: - field: funct3 value: "000" definition: | - registers[rd] = CAPI.MEM.read(imm + registers[rs1], 1, rd); + 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 @@ -2188,8 +2190,8 @@ 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 extension: I @@ -2201,7 +2203,10 @@ 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'); + 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 @@ -2214,9 +2219,11 @@ 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 extension: I @@ -2228,8 +2235,10 @@ instructions: - field: funct3 value: "010" definition: | - let addr = CAPI.FP.int2uint(registers[rs1], 32) + imm; - registers[rd] = CAPI.MEM.read(addr, 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); 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 @@ -2241,8 +2250,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 extension: I @@ -2282,7 +2293,7 @@ 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 @@ -2295,7 +2306,7 @@ 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 extension: I @@ -2419,7 +2430,7 @@ 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 @@ -2501,7 +2512,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 @@ -2513,7 +2524,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. - name: sw @@ -2525,7 +2539,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. @@ -2538,12 +2555,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. @@ -2674,13 +2695,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. - name: mul extension: M @@ -2707,12 +2726,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. - name: mulhsu @@ -2726,12 +2741,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. - name: mulhu @@ -2745,12 +2756,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. - name: rem @@ -2794,7 +2801,10 @@ 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]); @@ -2882,9 +2892,9 @@ 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 @@ -3006,18 +3016,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 (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. - name: fle.s @@ -3033,18 +3036,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 (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. - name: flt.s @@ -3060,18 +3056,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 (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 0 if either operand is NaN. - name: fmax.s @@ -3293,9 +3282,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 (isNaN(result)) { registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32"); @@ -3308,7 +3296,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. @@ -3357,7 +3345,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 (isNaN(result)) { registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32"); @@ -3386,7 +3374,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 (isNaN(result)) { registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32"); @@ -3415,7 +3403,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 (isNaN(result)) { registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32"); @@ -3444,7 +3432,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 (isNaN(result)) { registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32"); @@ -3468,7 +3456,10 @@ instructions: type: DFP-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: - name: fld @@ -3483,10 +3474,10 @@ 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(addr, 8, rd, false); help: Load a double-precision floating-point value from memory into floating-point register rd. - name: fadd.d extension: D @@ -3604,8 +3595,8 @@ 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: | @@ -3678,7 +3669,7 @@ instructions: 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 + - name: fcvt.w.d extension: D template: R-Conversion fields: @@ -3712,7 +3703,7 @@ instructions: 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 + - name: fcvt.wu.d extension: D template: R-Conversion fields: @@ -3746,7 +3737,7 @@ instructions: 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 + - name: fdiv.d extension: D template: R-Double fields: @@ -3773,7 +3764,7 @@ instructions: definition: | result = rs1Number / rs2Number; help: Perform double-precision floating-point division. - - name: feq.d + - name: feq.d extension: D template: R-Double fields: @@ -3786,16 +3777,14 @@ 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. - - name: fle.d + - name: fle.d extension: D template: R-Double fields: @@ -3811,13 +3800,11 @@ 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. - - name: flt.d + - name: flt.d extension: D template: R-Double fields: @@ -3833,13 +3820,11 @@ 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. - - name: fmax.d + - name: fmax.d extension: D template: R-Double fields: @@ -3864,7 +3849,7 @@ instructions: result = Math.max(rs1Number, rs2Number); help: Write the larger of double precision data in rs1 and rs2 to rd. - - name: fmin.d + - name: fmin.d extension: D template: R-Double fields: @@ -3889,7 +3874,7 @@ instructions: result = Math.min(rs1Number, rs2Number); help: Write the smaller of double precision data in rs1 and rs2 to rd. - - name: fmul.d + - name: fmul.d extension: D template: R-Double fields: @@ -3917,7 +3902,7 @@ instructions: result = rs1Number * rs2Number; help: Perform double-precision floating-point addition. - - name: fsgnj.d + - name: fsgnj.d extension: D template: R-Double fields: @@ -3941,7 +3926,7 @@ instructions: definition: | registers[rd] = (rs2Number > 0) ? Math.abs(rs1Number) : -Math.abs(rs1Number); help: Perform double-precision floating-point multiplication. - - name: fsgnjn.d + - name: fsgnjn.d extension: D template: R-Double fields: @@ -3963,10 +3948,10 @@ instructions: } 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. - - name: fsgnjx.d + - name: fsgnjx.d extension: D template: R-Double fields: @@ -3990,9 +3975,9 @@ 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. - - name: fsqrt.d + - name: fsqrt.d extension: D template: R-Double fields: @@ -4010,9 +3995,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 (isNaN(result)) { registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64"); @@ -4022,14 +4006,14 @@ 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." ); } help: Perform double-precision square root. - - name: fsub.d + - name: fsub.d extension: D template: R-Double fields: @@ -4057,7 +4041,7 @@ instructions: result = rs1Number - rs2Number; help: Perform double-precision floating-point addition. - - name: fmadd.d + - name: fmadd.d extension: D template: R4-Double fields: @@ -4087,7 +4071,7 @@ instructions: result = rs1Number * rs2Number + rs3Number; help: Perform double-precision fused multiply addition. - - name: fmsub.d + - name: fmsub.d extension: D template: R4-Double fields: @@ -4117,7 +4101,7 @@ instructions: result = rs1Number * rs2Number - rs3Number; help: Perform double-precision fused multiply subtraction. - - name: fnmadd.d + - name: fnmadd.d extension: D template: R4-Double fields: @@ -4147,7 +4131,7 @@ instructions: result = -rs1Number * rs2Number - rs3Number; help: Perform negated double-precision fused multiply addition. - - name: fnmsub.d + - name: fnmsub.d extension: D template: R4-Double fields: @@ -4177,7 +4161,7 @@ instructions: result = -rs1Number * rs2Number + rs3Number; help: Perform negated double-precision fused multiply subtraction. - - name: fsd + - name: fsd extension: D template: S fields: @@ -4188,14 +4172,13 @@ 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. Zifencei: - - name: fence.i + - name: fence.i extension: D template: Custom type: Syscall @@ -4247,7 +4230,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 diff --git a/architecture/RISCV/SRV64.yml b/architecture/RISCV/SRV64.yml index ee506592c..ff392e157 100644 --- a/architecture/RISCV/SRV64.yml +++ b/architecture/RISCV/SRV64.yml @@ -77,8 +77,8 @@ components: - x1 - ra nbits: 64 - value: 4294967295 - default_value: 4294967295 + value: -1 + default_value: -1 encoding: 1 properties: - read @@ -87,8 +87,8 @@ components: - x2 - sp nbits: 64 - value: 268435452 - default_value: 26843545 + value: 0x0FFFFFFC + default_value: 0x0FFFFFFC encoding: 2 properties: - read @@ -2095,7 +2095,7 @@ instructions: - field: funct3 value: "111" definition: | - if (CAPI.FP.int2uint(registers[rs1]) > CAPI.FP.int2uint(registers[rs2])) + 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 @@ -2171,9 +2171,11 @@ instructions: - field: funct3 value: "000" definition: | - registers[rd] = registers["PC"] + 4n; - registers["PC"] = (registers[rs1] + imm) & ~1n; - CAPI.CHECK_STACK.end(); CAPI.DRAW_STACK.end(registers["PC"]); + 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 @@ -2185,7 +2187,7 @@ instructions: - field: funct3 value: "000" definition: | - registers[rd] = CAPI.MEM.read(imm + registers[rs1], 1, rd); + 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 @@ -2199,8 +2201,8 @@ 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 extension: I @@ -2212,7 +2214,10 @@ 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'); + 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 @@ -2225,9 +2230,11 @@ 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 extension: I @@ -2239,8 +2246,10 @@ instructions: - field: funct3 value: "010" definition: | - let addr = CAPI.FP.int2uint(registers[rs1], 32) + imm; - registers[rd] = CAPI.MEM.read(addr, 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); 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 @@ -2280,7 +2289,7 @@ 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 @@ -2293,7 +2302,7 @@ 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 extension: I @@ -2307,7 +2316,7 @@ instructions: - field: funct7 value: "0100000" definition: | - if (shamt > 0) registers[rd] = CAPI.FP.int2uint(registers[rs1] >> shamt); + 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 @@ -2417,7 +2426,7 @@ 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 @@ -2499,7 +2508,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 @@ -2511,7 +2520,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. - name: sw @@ -2523,7 +2535,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: auipc @@ -2653,13 +2668,14 @@ 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, BigInt(registers[rs1])) / BigInt.asUintN(32, BigInt(registers[rs2]))) + (BigInt.asUintN(32, registers[rs1]) / BigInt.asUintN(32, 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. - name: mul extension: M @@ -2686,11 +2702,11 @@ instructions: - field: funct3 value: "001" definition: | - registers[rd] = BigInt.asIntN( + registers[rd] = BigInt.asUintN( 32, BigInt.asIntN( 64, - BigInt.asIntN(32, BigInt(registers[rs1])) * BigInt.asIntN(32, BigInt(registers[rs2])), + 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. @@ -2709,7 +2725,7 @@ instructions: 32, BigInt.asIntN( 64, - BigInt.asIntN(32, BigInt(registers[rs1])) * BigInt.asUintN(32, BigInt(registers[rs2])), + 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. @@ -2728,7 +2744,7 @@ instructions: 32, BigInt.asUintN( 64, - BigInt.asUintN(32, BigInt(registers[rs1])) * BigInt.asUintN(32, BigInt(registers[rs2])), + 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. @@ -2773,7 +2789,10 @@ 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]); @@ -2861,9 +2880,9 @@ 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 @@ -2985,18 +3004,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 (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. - name: fle.s @@ -3012,18 +3024,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 (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. - name: flt.s @@ -3039,18 +3044,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 (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 0 if either operand is NaN. - name: fmax.s @@ -3272,9 +3270,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 (isNaN(result)) { registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32"); @@ -3287,7 +3284,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. @@ -3336,7 +3333,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 (isNaN(result)) { registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32"); @@ -3365,7 +3362,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 (isNaN(result)) { registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32"); @@ -3394,7 +3391,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 (isNaN(result)) { registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32"); @@ -3423,7 +3420,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 (isNaN(result)) { registers[rd] = CAPI.ARCH.toBigInt(result, "NaN32"); @@ -3447,7 +3444,10 @@ instructions: type: DFP-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: - name: fld @@ -3462,10 +3462,10 @@ 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(addr, 8, rd, false); help: Load a double-precision floating-point value from memory into floating-point register rd. - name: fadd.d extension: D @@ -3583,8 +3583,8 @@ 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: | @@ -3657,7 +3657,7 @@ instructions: 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 + - name: fcvt.w.d extension: D template: R-Conversion fields: @@ -3691,7 +3691,7 @@ instructions: 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 + - name: fcvt.wu.d extension: D template: R-Conversion fields: @@ -3725,7 +3725,7 @@ instructions: 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 + - name: fdiv.d extension: D template: R-Double fields: @@ -3752,7 +3752,7 @@ instructions: definition: | result = rs1Number / rs2Number; help: Perform double-precision floating-point division. - - name: feq.d + - name: feq.d extension: D template: R-Double fields: @@ -3765,16 +3765,14 @@ 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. - - name: fle.d + - name: fle.d extension: D template: R-Double fields: @@ -3790,13 +3788,11 @@ 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. - - name: flt.d + - name: flt.d extension: D template: R-Double fields: @@ -3812,13 +3808,11 @@ 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. - - name: fmax.d + - name: fmax.d extension: D template: R-Double fields: @@ -3843,7 +3837,7 @@ instructions: result = Math.max(rs1Number, rs2Number); help: Write the larger of double precision data in rs1 and rs2 to rd. - - name: fmin.d + - name: fmin.d extension: D template: R-Double fields: @@ -3868,7 +3862,7 @@ instructions: result = Math.min(rs1Number, rs2Number); help: Write the smaller of double precision data in rs1 and rs2 to rd. - - name: fmul.d + - name: fmul.d extension: D template: R-Double fields: @@ -3896,7 +3890,7 @@ instructions: result = rs1Number * rs2Number; help: Perform double-precision floating-point addition. - - name: fsgnj.d + - name: fsgnj.d extension: D template: R-Double fields: @@ -3920,7 +3914,7 @@ instructions: definition: | registers[rd] = (rs2Number > 0) ? Math.abs(rs1Number) : -Math.abs(rs1Number); help: Perform double-precision floating-point multiplication. - - name: fsgnjn.d + - name: fsgnjn.d extension: D template: R-Double fields: @@ -3942,10 +3936,10 @@ instructions: } 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. - - name: fsgnjx.d + - name: fsgnjx.d extension: D template: R-Double fields: @@ -3969,9 +3963,9 @@ 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. - - name: fsqrt.d + - name: fsqrt.d extension: D template: R-Double fields: @@ -3989,9 +3983,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 (isNaN(result)) { registers[rd] = CAPI.ARCH.toBigInt(result, "NaN64"); @@ -4001,14 +3994,14 @@ 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." ); } help: Perform double-precision square root. - - name: fsub.d + - name: fsub.d extension: D template: R-Double fields: @@ -4036,7 +4029,7 @@ instructions: result = rs1Number - rs2Number; help: Perform double-precision floating-point addition. - - name: fmadd.d + - name: fmadd.d extension: D template: R4-Double fields: @@ -4066,7 +4059,7 @@ instructions: result = rs1Number * rs2Number + rs3Number; help: Perform double-precision fused multiply addition. - - name: fmsub.d + - name: fmsub.d extension: D template: R4-Double fields: @@ -4096,7 +4089,7 @@ instructions: result = rs1Number * rs2Number - rs3Number; help: Perform double-precision fused multiply subtraction. - - name: fnmadd.d + - name: fnmadd.d extension: D template: R4-Double fields: @@ -4126,7 +4119,7 @@ instructions: result = -rs1Number * rs2Number - rs3Number; help: Perform negated double-precision fused multiply addition. - - name: fnmsub.d + - name: fnmsub.d extension: D template: R4-Double fields: @@ -4156,7 +4149,7 @@ instructions: result = -rs1Number * rs2Number + rs3Number; help: Perform negated double-precision fused multiply subtraction. - - name: fsd + - name: fsd extension: D template: S fields: @@ -4167,14 +4160,13 @@ 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. Zifencei: - - name: fence.i + - name: fence.i extension: D template: Custom type: Syscall @@ -4226,7 +4218,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 diff --git a/creator-assembler b/creator-assembler index 567859473..0531a2707 160000 --- a/creator-assembler +++ b/creator-assembler @@ -1 +1 @@ -Subproject commit 5678594737724c2fcc8b2d25f324ecd6d4aa3599 +Subproject commit 0531a2707011af39e85d78ffd588d14c73861ffd diff --git a/deno.lock b/deno.lock index 36ad7990d..0ea81da64 100644 --- a/deno.lock +++ b/deno.lock @@ -1,6 +1,12 @@ { "version": "5", "specifiers": { + "jsr:@std/assert@^1.0.17": "1.0.19", + "jsr:@std/fs@^1.0.22": "1.0.23", + "jsr:@std/internal@^1.0.12": "1.0.12", + "jsr:@std/path@*": "1.1.4", + "jsr:@std/path@^1.1.4": "1.1.4", + "jsr:@std/testing@*": "1.0.17", "npm:@codemirror/lang-yaml@^6.1.2": "6.1.2", "npm:@codemirror/language@^6.11.3": "6.12.1", "npm:@codemirror/legacy-modes@^6.5.1": "6.5.2", @@ -69,6 +75,35 @@ "npm:xterm@^5.3.0": "5.3.0", "npm:yargs@18": "18.0.0" }, + "jsr": { + "@std/assert@1.0.19": { + "integrity": "eaada96ee120cb980bc47e040f82814d786fe8162ecc53c91d8df60b8755991e" + }, + "@std/fs@1.0.23": { + "integrity": "3ecbae4ce4fee03b180fa710caff36bb5adb66631c46a6460aaad49515565a37", + "dependencies": [ + "jsr:@std/path@^1.1.4" + ] + }, + "@std/internal@1.0.12": { + "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" + }, + "@std/path@1.1.4": { + "integrity": "1d2d43f39efb1b42f0b1882a25486647cb851481862dc7313390b2bb044314b5", + "dependencies": [ + "jsr:@std/internal" + ] + }, + "@std/testing@1.0.17": { + "integrity": "87bdc2700fa98249d48a17cd72413352d3d3680dcfbdb64947fd0982d6bbf681", + "dependencies": [ + "jsr:@std/assert", + "jsr:@std/fs", + "jsr:@std/internal", + "jsr:@std/path@^1.1.4" + ] + } + }, "npm": { "@aesoper/normal-utils@0.1.5": { "integrity": "sha512-LFF/6y6h5mfwhnJaWqqxuC8zzDaHCG62kMRkd8xhDtq62TQj9dM17A9DhE87W7DhiARJsHLgcina/9P4eNCN1w==" diff --git a/docs/dev.md b/docs/dev.md index 15369b840..ede2329b7 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -80,12 +80,23 @@ bun format ``` ### Run Tests + Unit tests (with [Deno](https://deno.com/)) + ```sh deno test -A --unstable-node-globals --parallel ``` +Integration tests use [Deno's snapshot testing](https://docs.deno.com/examples/snapshot_test_tutorial/). +They store the last known good result, and compare new results against the +stored snapshots to verify them (showing the differences if they don't match). +For this reason, the snapshots should always be committed to the repo. They are +run along with the other tests using the command above. The snapshots can be +created/updated automatically with: +```sh +deno test -A --unstable-node-globals --parallel -- --update +``` ## Backend RPC Server This project includes a JSON RPC server that exposes the CREATOR emulator's core functionalities. diff --git a/docs/version-management.md b/docs/version-management.md index 430c839e9..d44655fe3 100644 --- a/docs/version-management.md +++ b/docs/version-management.md @@ -12,7 +12,7 @@ The version is determined using the following priority order: 1. **`CREATOR_VERSION` environment variable** (highest priority) - Allows manual override for testing or special builds - - Example: `export CREATOR_VERSION=6.1.0-rc1` + - Example: `export CREATOR_VERSION=6.1.1-rc1` 2. **`CREATOR_CHANNEL` environment variable** - `CREATOR_CHANNEL=nightly`: Generates `nightly-YYYYMMDD` format @@ -27,7 +27,7 @@ The version is determined using the following priority order: ## Version Formats ### Stable Channel -- Format: `major.minor.patch` (e.g., `6.0.0`, `6.1.0`) +- Format: `major.minor.patch` (e.g., `6.0.0`, `6.1.0`, `6.1.1`) - Source: `package.json` version field - Used for: Official releases with version tags @@ -168,7 +168,7 @@ checkForUpdates(currentVersion); 3. Users will see update notifications daily if they run nightly builds ### For Stable Releases -1. Update `package.json` version to proper semantic version (e.g., `6.0.0`, `6.1.0`) +1. Update `package.json` version to proper semantic version (e.g., `6.0.0`, `6.1.0`, `6.1.1`) 2. Remove prerelease identifiers from package.json version 3. Set `CREATOR_CHANNEL=stable` or leave unset 4. Create a git tag matching the version @@ -183,7 +183,7 @@ checkForUpdates(currentVersion); // For development/beta - keep prerelease: { - "version": "6.1.0-beta" // Automatically treated as nightly + "version": "6.1.1-beta" // Automatically treated as nightly } ``` diff --git a/examples/RISCV-32-Sail-Validation/list.json b/examples/RISCV-32-Sail-Validation/list.json new file mode 100644 index 000000000..a1f9cebb2 --- /dev/null +++ b/examples/RISCV-32-Sail-Validation/list.json @@ -0,0 +1,536 @@ +[ + { + "name": "rv32ua-p-lrsc.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ua-p-lrsc.elf", + "doubleen": false, + "vectoren": true + }, + { + "name": "rv32ud-p-fmin.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ud-p-fmin.elf", + "doubleen": true, + "vectoren": true + }, + { + "name": "rv32mi-p-breakpoint.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32mi-p-breakpoint.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32mi-p-csr.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32mi-p-csr.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32mi-p-illegal.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32mi-p-illegal.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32mi-p-ma_addr.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32mi-p-ma_addr.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32mi-p-ma_fetch.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32mi-p-ma_fetch.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32mi-p-mcsr.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32mi-p-mcsr.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32mi-p-sbreak.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32mi-p-sbreak.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32mi-p-scall.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32mi-p-scall.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32mi-p-shamt.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32mi-p-shamt.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32si-p-csr.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32si-p-csr.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32si-p-dirty.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32si-p-dirty.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32si-p-ma_fetch.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32si-p-ma_fetch.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32si-p-sbreak.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32si-p-sbreak.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32si-p-scall.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32si-p-scall.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32si-p-wfi.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32si-p-wfi.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ua-p-amoadd_w.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ua-p-amoadd_w.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ua-p-amoand_w.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ua-p-amoand_w.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ua-p-amomaxu_w.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ua-p-amomaxu_w.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ua-p-amomax_w.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ua-p-amomax_w.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ua-p-amominu_w.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ua-p-amominu_w.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ua-p-amomin_w.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ua-p-amomin_w.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ua-p-amoor_w.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ua-p-amoor_w.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ua-p-amoswap_w.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ua-p-amoswap_w.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ua-p-amoxor_w.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ua-p-amoxor_w.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32uc-p-rvc.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32uc-p-rvc.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ud-p-fadd.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ud-p-fadd.elf", + "doubleen": true, + "vectoren": false + }, + { + "name": "rv32ud-p-fclass.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ud-p-fclass.elf", + "doubleen": true, + "vectoren": false + }, + { + "name": "rv32ud-p-fcmp.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ud-p-fcmp.elf", + "doubleen": true, + "vectoren": false + }, + { + "name": "rv32ud-p-fcvt.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ud-p-fcvt.elf", + "doubleen": true, + "vectoren": false + }, + { + "name": "rv32ud-p-fcvt_w.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ud-p-fcvt_w.elf", + "doubleen": true, + "vectoren": false + }, + { + "name": "rv32ud-p-fdiv.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ud-p-fdiv.elf", + "doubleen": true, + "vectoren": false + }, + { + "name": "rv32ud-p-fmadd.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ud-p-fmadd.elf", + "doubleen": true, + "vectoren": false + }, + { + "name": "rv32uf-p-fadd.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32uf-p-fadd.elf", + "doubleen": true, + "vectoren": false + }, + { + "name": "rv32uf-p-fclass.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32uf-p-fclass.elf", + "doubleen": true, + "vectoren": false + }, + { + "name": "rv32uf-p-fcmp.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32uf-p-fcmp.elf", + "doubleen": true, + "vectoren": false + }, + { + "name": "rv32uf-p-fcvt.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32uf-p-fcvt.elf", + "doubleen": true, + "vectoren": false + }, + { + "name": "rv32uf-p-fcvt_w.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32uf-p-fcvt_w.elf", + "doubleen": true, + "vectoren": false + }, + { + "name": "rv32uf-p-fdiv.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32uf-p-fdiv.elf", + "doubleen": true, + "vectoren": false + }, + { + "name": "rv32uf-p-fmadd.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32uf-p-fmadd.elf", + "doubleen": true, + "vectoren": false + }, + { + "name": "rv32uf-p-fmin.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32uf-p-fmin.elf", + "doubleen": true, + "vectoren": false + }, + { + "name": "rv32ui-p-add.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-add.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-addi.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-addi.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-and.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-and.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-andi.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-andi.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-auipc.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-auipc.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-beq.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-beq.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-bge.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-bge.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-bgeu.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-bgeu.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-blt.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-blt.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-bltu.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-bltu.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-bne.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-bne.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-fence_i.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-fence_i.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-jal.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-jal.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-jalr.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-jalr.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-lb.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-lb.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-lbu.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-lbu.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-lh.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-lh.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-lhu.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-lhu.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-lui.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-lui.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-lw.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-lw.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-or.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-or.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-ori.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-ori.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-sb.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-sb.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-sh.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-sh.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-simple.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-simple.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-sll.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-sll.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-slli.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-slli.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-slt.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-slt.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-slti.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-slti.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-sltiu.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-sltiu.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-sltu.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-sltu.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-sra.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-sra.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-srai.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-srai.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-srl.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-srl.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-srli.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-srli.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-sub.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-sub.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-sw.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-sw.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-xor.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-xor.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32ui-p-xori.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32ui-p-xori.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32um-p-div.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32um-p-div.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32um-p-divu.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32um-p-divu.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32um-p-mul.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32um-p-mul.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32um-p-mulh.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32um-p-mulh.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32um-p-mulhsu.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32um-p-mulhsu.elf", + "doubleen": true, + "vectoren": true + }, + { + "name": "rv32um-p-mulhu.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32um-p-mulhu.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32um-p-rem.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32um-p-rem.elf", + "doubleen": false, + "vectoren": false + }, + { + "name": "rv32um-p-remu.elf", + "url": "examples/RISCV-32-Sail-Validation/rv32um-p-remu.elf", + "doubleen": false, + "vectoren": false + } +] \ No newline at end of file diff --git a/examples/RISCV-32-Sail-Validation/rv32mi-p-breakpoint.elf b/examples/RISCV-32-Sail-Validation/rv32mi-p-breakpoint.elf new file mode 100644 index 000000000..b05473758 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32mi-p-breakpoint.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32mi-p-csr.elf b/examples/RISCV-32-Sail-Validation/rv32mi-p-csr.elf new file mode 100644 index 000000000..bdd015b69 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32mi-p-csr.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32mi-p-illegal.elf b/examples/RISCV-32-Sail-Validation/rv32mi-p-illegal.elf new file mode 100644 index 000000000..c4175e8cd Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32mi-p-illegal.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32mi-p-ma_addr.elf b/examples/RISCV-32-Sail-Validation/rv32mi-p-ma_addr.elf new file mode 100644 index 000000000..954fcccac Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32mi-p-ma_addr.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32mi-p-ma_fetch.elf b/examples/RISCV-32-Sail-Validation/rv32mi-p-ma_fetch.elf new file mode 100644 index 000000000..523433e63 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32mi-p-ma_fetch.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32mi-p-mcsr.elf b/examples/RISCV-32-Sail-Validation/rv32mi-p-mcsr.elf new file mode 100644 index 000000000..9c15c5890 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32mi-p-mcsr.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32mi-p-sbreak.elf b/examples/RISCV-32-Sail-Validation/rv32mi-p-sbreak.elf new file mode 100644 index 000000000..867e1d76f Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32mi-p-sbreak.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32mi-p-scall.elf b/examples/RISCV-32-Sail-Validation/rv32mi-p-scall.elf new file mode 100644 index 000000000..20c633102 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32mi-p-scall.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32mi-p-shamt.elf b/examples/RISCV-32-Sail-Validation/rv32mi-p-shamt.elf new file mode 100644 index 000000000..5f4964f8d Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32mi-p-shamt.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32si-p-csr.elf b/examples/RISCV-32-Sail-Validation/rv32si-p-csr.elf new file mode 100644 index 000000000..a0f14b7bd Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32si-p-csr.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32si-p-dirty.elf b/examples/RISCV-32-Sail-Validation/rv32si-p-dirty.elf new file mode 100644 index 000000000..693451c60 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32si-p-dirty.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32si-p-ma_fetch.elf b/examples/RISCV-32-Sail-Validation/rv32si-p-ma_fetch.elf new file mode 100644 index 000000000..7a5fc3ccf Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32si-p-ma_fetch.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32si-p-sbreak.elf b/examples/RISCV-32-Sail-Validation/rv32si-p-sbreak.elf new file mode 100644 index 000000000..13af3541b Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32si-p-sbreak.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32si-p-scall.elf b/examples/RISCV-32-Sail-Validation/rv32si-p-scall.elf new file mode 100644 index 000000000..a73522ae9 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32si-p-scall.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32si-p-wfi.elf b/examples/RISCV-32-Sail-Validation/rv32si-p-wfi.elf new file mode 100644 index 000000000..b5471c1c0 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32si-p-wfi.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ua-p-amoadd_w.elf b/examples/RISCV-32-Sail-Validation/rv32ua-p-amoadd_w.elf new file mode 100644 index 000000000..7e01c3580 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ua-p-amoadd_w.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ua-p-amoand_w.elf b/examples/RISCV-32-Sail-Validation/rv32ua-p-amoand_w.elf new file mode 100644 index 000000000..0196fd606 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ua-p-amoand_w.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ua-p-amomax_w.elf b/examples/RISCV-32-Sail-Validation/rv32ua-p-amomax_w.elf new file mode 100644 index 000000000..b6e91a5b3 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ua-p-amomax_w.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ua-p-amomaxu_w.elf b/examples/RISCV-32-Sail-Validation/rv32ua-p-amomaxu_w.elf new file mode 100644 index 000000000..81eeb29a1 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ua-p-amomaxu_w.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ua-p-amomin_w.elf b/examples/RISCV-32-Sail-Validation/rv32ua-p-amomin_w.elf new file mode 100644 index 000000000..959194f68 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ua-p-amomin_w.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ua-p-amominu_w.elf b/examples/RISCV-32-Sail-Validation/rv32ua-p-amominu_w.elf new file mode 100644 index 000000000..c8180700c Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ua-p-amominu_w.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ua-p-amoor_w.elf b/examples/RISCV-32-Sail-Validation/rv32ua-p-amoor_w.elf new file mode 100644 index 000000000..b62c0e82c Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ua-p-amoor_w.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ua-p-amoswap_w.elf b/examples/RISCV-32-Sail-Validation/rv32ua-p-amoswap_w.elf new file mode 100644 index 000000000..3094b78b8 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ua-p-amoswap_w.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ua-p-amoxor_w.elf b/examples/RISCV-32-Sail-Validation/rv32ua-p-amoxor_w.elf new file mode 100644 index 000000000..a893682f4 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ua-p-amoxor_w.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ua-p-lrsc.elf b/examples/RISCV-32-Sail-Validation/rv32ua-p-lrsc.elf new file mode 100644 index 000000000..4f0e3edef Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ua-p-lrsc.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32uc-p-rvc.elf b/examples/RISCV-32-Sail-Validation/rv32uc-p-rvc.elf new file mode 100644 index 000000000..7813b7124 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32uc-p-rvc.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ud-p-fadd.elf b/examples/RISCV-32-Sail-Validation/rv32ud-p-fadd.elf new file mode 100644 index 000000000..d1835614b Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ud-p-fadd.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ud-p-fclass.elf b/examples/RISCV-32-Sail-Validation/rv32ud-p-fclass.elf new file mode 100644 index 000000000..7e67e8ba0 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ud-p-fclass.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ud-p-fcmp.elf b/examples/RISCV-32-Sail-Validation/rv32ud-p-fcmp.elf new file mode 100644 index 000000000..110986d39 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ud-p-fcmp.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ud-p-fcvt.elf b/examples/RISCV-32-Sail-Validation/rv32ud-p-fcvt.elf new file mode 100644 index 000000000..fda1e44f6 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ud-p-fcvt.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ud-p-fcvt_w.elf b/examples/RISCV-32-Sail-Validation/rv32ud-p-fcvt_w.elf new file mode 100644 index 000000000..77b06c093 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ud-p-fcvt_w.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ud-p-fdiv.elf b/examples/RISCV-32-Sail-Validation/rv32ud-p-fdiv.elf new file mode 100644 index 000000000..56fe7eb29 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ud-p-fdiv.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ud-p-fmadd.elf b/examples/RISCV-32-Sail-Validation/rv32ud-p-fmadd.elf new file mode 100644 index 000000000..33a8d1242 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ud-p-fmadd.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ud-p-fmin.elf b/examples/RISCV-32-Sail-Validation/rv32ud-p-fmin.elf new file mode 100644 index 000000000..1ff030465 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ud-p-fmin.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32uf-p-fadd.elf b/examples/RISCV-32-Sail-Validation/rv32uf-p-fadd.elf new file mode 100644 index 000000000..a783f7ae3 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32uf-p-fadd.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32uf-p-fclass.elf b/examples/RISCV-32-Sail-Validation/rv32uf-p-fclass.elf new file mode 100644 index 000000000..3a520ad37 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32uf-p-fclass.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32uf-p-fcmp.elf b/examples/RISCV-32-Sail-Validation/rv32uf-p-fcmp.elf new file mode 100644 index 000000000..b0f64b185 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32uf-p-fcmp.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32uf-p-fcvt.elf b/examples/RISCV-32-Sail-Validation/rv32uf-p-fcvt.elf new file mode 100644 index 000000000..da776a266 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32uf-p-fcvt.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32uf-p-fcvt_w.elf b/examples/RISCV-32-Sail-Validation/rv32uf-p-fcvt_w.elf new file mode 100644 index 000000000..05dc1ab0f Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32uf-p-fcvt_w.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32uf-p-fdiv.elf b/examples/RISCV-32-Sail-Validation/rv32uf-p-fdiv.elf new file mode 100644 index 000000000..481285249 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32uf-p-fdiv.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32uf-p-fmadd.elf b/examples/RISCV-32-Sail-Validation/rv32uf-p-fmadd.elf new file mode 100644 index 000000000..e68a2ce80 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32uf-p-fmadd.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32uf-p-fmin.elf b/examples/RISCV-32-Sail-Validation/rv32uf-p-fmin.elf new file mode 100644 index 000000000..e1774aa45 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32uf-p-fmin.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-add.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-add.elf new file mode 100644 index 000000000..a32ea3309 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-add.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-addi.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-addi.elf new file mode 100644 index 000000000..25f1c02c7 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-addi.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-and.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-and.elf new file mode 100644 index 000000000..f1468e41a Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-and.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-andi.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-andi.elf new file mode 100644 index 000000000..5c02664e0 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-andi.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-auipc.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-auipc.elf new file mode 100644 index 000000000..c50a29c14 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-auipc.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-beq.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-beq.elf new file mode 100644 index 000000000..0d2a410bf Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-beq.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-bge.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-bge.elf new file mode 100644 index 000000000..8979b9ef5 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-bge.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-bgeu.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-bgeu.elf new file mode 100644 index 000000000..80510421f Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-bgeu.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-blt.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-blt.elf new file mode 100644 index 000000000..d46af0447 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-blt.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-bltu.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-bltu.elf new file mode 100644 index 000000000..e4e90ec3f Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-bltu.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-bne.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-bne.elf new file mode 100644 index 000000000..3c3460bb1 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-bne.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-fence_i.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-fence_i.elf new file mode 100644 index 000000000..5a14522fb Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-fence_i.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-jal.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-jal.elf new file mode 100644 index 000000000..2f309033a Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-jal.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-jalr.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-jalr.elf new file mode 100644 index 000000000..78f985d44 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-jalr.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-lb.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-lb.elf new file mode 100644 index 000000000..5e070c89e Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-lb.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-lbu.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-lbu.elf new file mode 100644 index 000000000..b094c86c4 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-lbu.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-lh.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-lh.elf new file mode 100644 index 000000000..348fa069d Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-lh.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-lhu.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-lhu.elf new file mode 100644 index 000000000..2849a586d Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-lhu.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-lui.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-lui.elf new file mode 100644 index 000000000..c38c7f205 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-lui.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-lw.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-lw.elf new file mode 100644 index 000000000..d28a7f2a9 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-lw.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-or.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-or.elf new file mode 100644 index 000000000..0f505c0d7 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-or.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-ori.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-ori.elf new file mode 100644 index 000000000..eb13ca2df Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-ori.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-sb.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-sb.elf new file mode 100644 index 000000000..f51313b36 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-sb.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-sh.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-sh.elf new file mode 100644 index 000000000..5d8c24418 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-sh.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-simple.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-simple.elf new file mode 100644 index 000000000..5880eadeb Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-simple.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-sll.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-sll.elf new file mode 100644 index 000000000..eb8029fc2 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-sll.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-slli.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-slli.elf new file mode 100644 index 000000000..fdaf7c23e Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-slli.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-slt.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-slt.elf new file mode 100644 index 000000000..844410a0a Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-slt.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-slti.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-slti.elf new file mode 100644 index 000000000..faccd5130 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-slti.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-sltiu.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-sltiu.elf new file mode 100644 index 000000000..ada45e2ae Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-sltiu.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-sltu.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-sltu.elf new file mode 100644 index 000000000..893aeb408 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-sltu.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-sra.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-sra.elf new file mode 100644 index 000000000..ab4e4fbbe Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-sra.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-srai.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-srai.elf new file mode 100644 index 000000000..9a21c3501 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-srai.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-srl.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-srl.elf new file mode 100644 index 000000000..996dc3bfa Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-srl.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-srli.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-srli.elf new file mode 100644 index 000000000..19c592783 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-srli.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-sub.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-sub.elf new file mode 100644 index 000000000..90ed5543b Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-sub.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-sw.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-sw.elf new file mode 100644 index 000000000..eb1ae2b99 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-sw.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-xor.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-xor.elf new file mode 100644 index 000000000..1fcbf5b85 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-xor.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32ui-p-xori.elf b/examples/RISCV-32-Sail-Validation/rv32ui-p-xori.elf new file mode 100644 index 000000000..34f87171e Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32ui-p-xori.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32um-p-div.elf b/examples/RISCV-32-Sail-Validation/rv32um-p-div.elf new file mode 100644 index 000000000..121c055ed Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32um-p-div.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32um-p-divu.elf b/examples/RISCV-32-Sail-Validation/rv32um-p-divu.elf new file mode 100644 index 000000000..0c3335f4d Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32um-p-divu.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32um-p-mul.elf b/examples/RISCV-32-Sail-Validation/rv32um-p-mul.elf new file mode 100644 index 000000000..75eebf3e5 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32um-p-mul.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32um-p-mulh.elf b/examples/RISCV-32-Sail-Validation/rv32um-p-mulh.elf new file mode 100644 index 000000000..38e8ca72b Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32um-p-mulh.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32um-p-mulhsu.elf b/examples/RISCV-32-Sail-Validation/rv32um-p-mulhsu.elf new file mode 100644 index 000000000..48f64a141 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32um-p-mulhsu.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32um-p-mulhu.elf b/examples/RISCV-32-Sail-Validation/rv32um-p-mulhu.elf new file mode 100644 index 000000000..5010a3deb Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32um-p-mulhu.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32um-p-rem.elf b/examples/RISCV-32-Sail-Validation/rv32um-p-rem.elf new file mode 100644 index 000000000..605e403a4 Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32um-p-rem.elf differ diff --git a/examples/RISCV-32-Sail-Validation/rv32um-p-remu.elf b/examples/RISCV-32-Sail-Validation/rv32um-p-remu.elf new file mode 100644 index 000000000..6814ffa3c Binary files /dev/null and b/examples/RISCV-32-Sail-Validation/rv32um-p-remu.elf differ diff --git a/examples/RISCV-32-arduino/example10.s b/examples/RISCV-32-arduino/example10.s index 0719e901d..e51c50043 100644 --- a/examples/RISCV-32-arduino/example10.s +++ b/examples/RISCV-32-arduino/example10.s @@ -18,16 +18,16 @@ not_found: lw ra, 0(sp) addi sp, sp, 4 - #li a0, 10000 - #addi sp, sp, -4 - #sw ra, 0(sp) - #jal ra, delay - #lw ra, 0(sp) - #addi sp, sp, 4 + li a0, 10000 + addi sp, sp, -4 + sw ra, 0(sp) + jal ra, delay + lw ra, 0(sp) + addi sp, sp, 4 jal ra, loop -founded: +found_text: la a0, found addi sp, sp, -4 sw ra, 0(sp) @@ -35,12 +35,12 @@ founded: lw ra, 0(sp) addi sp, sp, 4 - #li a0, 10000 - #addi sp, sp, -4 - #sw ra, 0(sp) - #jal ra, delay - #lw ra, 0(sp) - #addi sp, sp, 4 + li a0, 10000 + addi sp, sp, -4 + sw ra, 0(sp) + jal ra, delay + lw ra, 0(sp) + addi sp, sp, 4 jal ra, loop @@ -75,7 +75,7 @@ loop: addi sp, sp, 4 beqz a0, not_found - jal ra, founded + jal ra, found_text diff --git a/examples/RISCV-32-arduino/example11.s b/examples/RISCV-32-arduino/example11.s index 47ee83428..0e16ee683 100644 --- a/examples/RISCV-32-arduino/example11.s +++ b/examples/RISCV-32-arduino/example11.s @@ -1,24 +1,55 @@ -# Creatino Example: Starting Monitor Print + +#Creatino example: parseInt .data - msg: .string "Hello! Serial here" + msg: .string "Enter a integer number:\n" + sol: .string "You entered %d" + lookahead: .string "SKIP_NONE" - msg2: .string "Come soon!!" .text - main: - # ESP-IDF needs to initiate Arduino component first - jal ra, initArduino - # Baud rate depends on the board you are using. Maybe the same values don't fit everywhere - li a0, 115200 - jal ra, serial_begin - la a0, msg - jal ra, serial_printf - - #Now, we will wait all the data is transmitted - jal ra, serial_flush - - #Print again!! - la a0, msg2 - jal ra, serial_printf - - - jr ra \ No newline at end of file + +number: + mv a1, a0 + la a0, sol + addi sp, sp, -4 + sw ra, 0(sp) + jal ra, serial_printf + lw ra, 0(sp) + addi sp, sp, 4 + jal ra, loop + +setup: + li a0, 115200 + addi sp, sp, -4 + sw ra, 0(sp) + jal ra, serial_begin + lw ra, 0(sp) + addi sp, sp, 4 + + jr ra + +loop: + la a0, msg + addi sp, sp, -4 + sw ra, 0(sp) + jal ra, serial_printf + lw ra, 0(sp) + addi sp, sp, 4 + + la a0, lookahead + addi sp, sp, -4 + sw ra, 0(sp) + jal ra, serial_parseInt + lw ra, 0(sp) + addi sp, sp, 4 + bnez a0, number + jal ra, loop + + +main: + jal ra, initArduino + addi sp, sp, -4 + sw ra, 0(sp) + jal ra, setup + lw ra, 0(sp) + addi sp, sp, 4 + j loop \ No newline at end of file diff --git a/examples/RISCV-32-arduino/example12.s b/examples/RISCV-32-arduino/example12.s index cc7e0a446..bb3910e8c 100644 --- a/examples/RISCV-32-arduino/example12.s +++ b/examples/RISCV-32-arduino/example12.s @@ -1,55 +1,40 @@ - -#Creatino example: parse +#Template for Arduino proyects .data - msg: .string "Enter a integer number:\n" - sol: .string "You entered %d" - lookahead: .string "SKIP_NONE" +space: .zero 100 .text - -number: - mv a1, a0 - la a0, sol - addi sp, sp, -4 - sw ra, 0(sp) - jal ra, serial_printf - lw ra, 0(sp) - addi sp, sp, 4 - jal ra, loop - setup: - li a0, 115200 - addi sp, sp, -4 - sw ra, 0(sp) - jal ra, serial_begin - lw ra, 0(sp) - addi sp, sp, 4 - + li a0, 115200 + addi sp, sp, -4 + sw ra, 0(sp) + jal ra, serial_begin + lw ra, 0(sp) + addi sp, sp, 4 jr ra - -loop: - la a0, msg - addi sp, sp, -4 - sw ra, 0(sp) - jal ra, serial_printf - lw ra, 0(sp) - addi sp, sp, 4 - - la a0, lookahead - addi sp, sp, -4 - sw ra, 0(sp) - jal ra, serial_parseInt - lw ra, 0(sp) - addi sp, sp, 4 - bnez a0, number - jal ra, loop - - +loop: + + addi sp, sp, -4 + sw ra, 0(sp) + la a0, space + li a1, 5 + jal ra, serial_readBytes + lw ra, 0(sp) + addi sp, sp, 4 + + + addi sp, sp, -4 + sw ra, 0(sp) + la a0, space + jal ra, serial_printf + lw ra, 0(sp) + addi sp, sp, 4 + + j loop main: - jal ra, initArduino - addi sp, sp, -4 - sw ra, 0(sp) + addi sp, sp, -16 + sw ra, 12(sp) + jal ra, initArduino jal ra, setup - lw ra, 0(sp) - addi sp, sp, 4 + lw ra, 12(sp) + addi sp, sp, 16 j loop \ No newline at end of file diff --git a/examples/RISCV-32-arduino/example13.s b/examples/RISCV-32-arduino/example13.s index 763be1eae..1de9d30b2 100644 --- a/examples/RISCV-32-arduino/example13.s +++ b/examples/RISCV-32-arduino/example13.s @@ -1,10 +1,12 @@ -#Template for Arduino proyects +# Creatino example:readBytes .data -space: .zero 100 + space: .zero 100 #Buffer to place the string + print: .string "%s\n" + char: .byte 65 #A .text setup: - li a0, 11520 + li a0, 115200 addi sp, sp, -4 sw ra, 0(sp) jal ra, serial_begin @@ -13,22 +15,27 @@ setup: jr ra loop: + # read int + la a0, char + lb a0, 0(a0) + la a1, space + la a2, 5 # number of letters it will have + addi sp, sp, -4 - sw ra, 0(sp) - la a0, space - li a1, 5 - jal ra, serial_readBytes - lw ra, 0(sp) + sw ra, 0(sp) + jal ra, serial_readBytesUntil + lw ra, 0(sp) addi sp, sp, 4 - - addi sp, sp, -4 - sw ra, 0(sp) + # print: la a0, space + addi sp, sp, -4 + sw ra, 0(sp) jal ra, serial_printf - lw ra, 0(sp) - addi sp, sp, 4 + lw ra, 0(sp) + addi sp, sp, 4 + # return j loop main: addi sp, sp, -16 diff --git a/examples/RISCV-32-arduino/example14.s b/examples/RISCV-32-arduino/example14.s index af9de2c9e..96972db52 100644 --- a/examples/RISCV-32-arduino/example14.s +++ b/examples/RISCV-32-arduino/example14.s @@ -1,47 +1,96 @@ -# Creatino example:readBytes +# Creatino example: GPIO Interrupts .data - space: .zero 100 #Buffer to place the string - print: .string "%s\n" - char: .byte 65 #A - + ledPin: .byte 4 + interruptpin: .byte 6 + state: .byte 0 #LOW + change: .byte 0x04 .text -setup: - li a0, 11520 +blink: + la t1, ledPin + lb a0, 0(t1) + li a1, 1 addi sp, sp, -4 - sw ra, 0(sp) - jal ra, serial_begin - lw ra, 0(sp) + sw ra,0(sp) + jal ra, digitalWrite# digitalWrite(ledPin, state) + lw ra,0(sp) addi sp, sp, 4 jr ra + + loop: + la t1, ledPin + lb a0, 0(t1) + li a1,0 + addi sp, sp, -4 + sw ra,0(sp) + jal ra, digitalWrite# digitalWrite(ledPin, state) + lw ra,0(sp) + addi sp, sp, 4 + + li a0, 100 + addi sp, sp, -4 + sw ra,0(sp) + jal ra, delay # delay(1000) + lw ra,0(sp) + addi sp, sp, 4 + j loop - # read int - la a0, char - lb a0, 0(a0) - la a1, space - la a2, 5 # number of letters it will have +setup: + #Start pins + la t1, ledPin + lb a0, 0(t1) + li a1, 0x03 #OUTPUT + addi sp, sp, -4 + sw ra,0(sp) + jal ra, pinMode #pinMode(ledPin, OUTPUT); + lw ra,0(sp) + addi sp, sp, 4 + la t1, interruptpin + lb a0, 0(t1) + li a1, 0x05 #INPUT_PULLUP + addi sp, sp, -4 + sw ra,0(sp) + jal ra, pinMode# pinMode(ledPin, INPUT_PULLUP); + lw ra,0(sp) + addi sp, sp, 4 + + la t1, interruptpin + lb a0, 0(t1) + addi sp, sp, -4 + sw ra,0(sp) + jal ra, digitalPinToInterrupt #digitalPinToInterrupt(interruptpin); + lw ra,0(sp) + addi sp, sp, 4 + + la a1, blink + la t1, change + lb a2, 0(t1) + + addi sp, sp, -4 + sw ra,0(sp) + jal ra, attachInterrupt #attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE); + lw ra,0(sp) + addi sp, sp, 4 + jr ra + +main: + # Llamar a cr_initArduino() addi sp, sp, -4 sw ra, 0(sp) - jal ra, serial_readBytesUntil + jal ra, initArduino lw ra, 0(sp) addi sp, sp, 4 - # print: - la a0, space + # Llamar a setup() addi sp, sp, -4 sw ra, 0(sp) - jal ra, serial_printf + jal ra, setup lw ra, 0(sp) - addi sp, sp, 4 + addi sp, sp, 4 - # return + # Bucle infinito j loop -main: - addi sp, sp, -16 - sw ra, 12(sp) - jal ra, initArduino - jal ra, setup - lw ra, 12(sp) - addi sp, sp, 16 - j loop \ No newline at end of file + + + \ No newline at end of file diff --git a/examples/RISCV-32-arduino/example15.s b/examples/RISCV-32-arduino/example15.s deleted file mode 100644 index 96972db52..000000000 --- a/examples/RISCV-32-arduino/example15.s +++ /dev/null @@ -1,96 +0,0 @@ -# Creatino example: GPIO Interrupts -.data - ledPin: .byte 4 - interruptpin: .byte 6 - state: .byte 0 #LOW - change: .byte 0x04 -.text -blink: - la t1, ledPin - lb a0, 0(t1) - li a1, 1 - addi sp, sp, -4 - sw ra,0(sp) - jal ra, digitalWrite# digitalWrite(ledPin, state) - lw ra,0(sp) - addi sp, sp, 4 - jr ra - - -loop: - la t1, ledPin - lb a0, 0(t1) - li a1,0 - addi sp, sp, -4 - sw ra,0(sp) - jal ra, digitalWrite# digitalWrite(ledPin, state) - lw ra,0(sp) - addi sp, sp, 4 - - li a0, 100 - addi sp, sp, -4 - sw ra,0(sp) - jal ra, delay # delay(1000) - lw ra,0(sp) - addi sp, sp, 4 - j loop - -setup: - #Start pins - la t1, ledPin - lb a0, 0(t1) - li a1, 0x03 #OUTPUT - addi sp, sp, -4 - sw ra,0(sp) - jal ra, pinMode #pinMode(ledPin, OUTPUT); - lw ra,0(sp) - addi sp, sp, 4 - la t1, interruptpin - lb a0, 0(t1) - li a1, 0x05 #INPUT_PULLUP - addi sp, sp, -4 - sw ra,0(sp) - jal ra, pinMode# pinMode(ledPin, INPUT_PULLUP); - lw ra,0(sp) - addi sp, sp, 4 - - la t1, interruptpin - lb a0, 0(t1) - addi sp, sp, -4 - sw ra,0(sp) - jal ra, digitalPinToInterrupt #digitalPinToInterrupt(interruptpin); - lw ra,0(sp) - addi sp, sp, 4 - - la a1, blink - - la t1, change - lb a2, 0(t1) - - addi sp, sp, -4 - sw ra,0(sp) - jal ra, attachInterrupt #attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE); - lw ra,0(sp) - addi sp, sp, 4 - jr ra - -main: - # Llamar a cr_initArduino() - addi sp, sp, -4 - sw ra, 0(sp) - jal ra, initArduino - lw ra, 0(sp) - addi sp, sp, 4 - - # Llamar a setup() - addi sp, sp, -4 - sw ra, 0(sp) - jal ra, setup - lw ra, 0(sp) - addi sp, sp, 4 - - # Bucle infinito - j loop - - - \ No newline at end of file diff --git a/examples/RISCV-32-arduino/list.json b/examples/RISCV-32-arduino/list.json index e93c09329..640a1f39b 100644 --- a/examples/RISCV-32-arduino/list.json +++ b/examples/RISCV-32-arduino/list.json @@ -75,30 +75,24 @@ "name": "Example 11", "id": "e11", "url": "examples/RISCV-32-arduino/example11.s", - "description": "Serial Flush example" + "description": "Serial parseInt example" }, { "name": "Example 12", "id": "e12", "url": "examples/RISCV-32-arduino/example12.s", - "description": "Serial parseInt example" + "description": "Serial readBytes example" }, { "name": "Example 13", "id": "e13", "url": "examples/RISCV-32-arduino/example13.s", - "description": "Serial readBytes example" + "description": "Serial readBytesUntil example" }, - { + { "name": "Example 14", "id": "e14", "url": "examples/RISCV-32-arduino/example14.s", - "description": "Serial readBytesUntil example" - }, - { - "name": "Example 15", - "id": "e15", - "url": "examples/RISCV-32-arduino/example15.s", "description": "High level interrupts example" } diff --git a/examples/RISCV-64-Sail-Validation/list.json b/examples/RISCV-64-Sail-Validation/list.json new file mode 100644 index 000000000..831ac9e77 --- /dev/null +++ b/examples/RISCV-64-Sail-Validation/list.json @@ -0,0 +1,490 @@ +[ + { + "name": "rv64mi-p-access.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64mi-p-access.elf" + }, + { + "name": "rv64mi-p-breakpoint.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64mi-p-breakpoint.elf" + }, + { + "name": "rv64mi-p-csr.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64mi-p-csr.elf" + }, + { + "name": "rv64mi-p-illegal.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64mi-p-illegal.elf" + }, + { + "name": "rv64mi-p-ma_addr.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64mi-p-ma_addr.elf" + }, + { + "name": "rv64mi-p-ma_fetch.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64mi-p-ma_fetch.elf" + }, + { + "name": "rv64mi-p-mcsr.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64mi-p-mcsr.elf" + }, + { + "name": "rv64mi-p-sbreak.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64mi-p-sbreak.elf" + }, + { + "name": "rv64mi-p-scall.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64mi-p-scall.elf" + }, + { + "name": "rv64si-p-csr.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64si-p-csr.elf" + }, + { + "name": "rv64si-p-dirty.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64si-p-dirty.elf" + }, + { + "name": "rv64si-p-ma_fetch.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64si-p-ma_fetch.elf" + }, + { + "name": "rv64si-p-sbreak.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64si-p-sbreak.elf" + }, + { + "name": "rv64si-p-scall.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64si-p-scall.elf" + }, + { + "name": "rv64si-p-wfi.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64si-p-wfi.elf" + }, + { + "name": "rv64ua-p-amoadd_d.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amoadd_d.elf" + }, + { + "name": "rv64ua-p-amoadd_w.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amoadd_w.elf" + }, + { + "name": "rv64ua-p-amoand_d.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amoand_d.elf" + }, + { + "name": "rv64ua-p-amoand_w.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amoand_w.elf" + }, + { + "name": "rv64ua-p-amomax_d.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amomax_d.elf" + }, + { + "name": "rv64ua-p-amomaxu_d.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amomaxu_d.elf" + }, + { + "name": "rv64ua-p-amomaxu_w.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amomaxu_w.elf" + }, + { + "name": "rv64ua-p-amomax_w.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amomax_w.elf" + }, + { + "name": "rv64ua-p-amomin_d.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amomin_d.elf" + }, + { + "name": "rv64ua-p-amominu_d.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amominu_d.elf" + }, + { + "name": "rv64ua-p-amominu_w.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amominu_w.elf" + }, + { + "name": "rv64ua-p-amomin_w.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amomin_w.elf" + }, + { + "name": "rv64ua-p-amoor_d.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amoor_d.elf" + }, + { + "name": "rv64ua-p-amoor_w.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amoor_w.elf" + }, + { + "name": "rv64ua-p-amoswap_d.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amoswap_d.elf" + }, + { + "name": "rv64ua-p-amoswap_w.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amoswap_w.elf" + }, + { + "name": "rv64ua-p-amoxor_d.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amoxor_d.elf" + }, + { + "name": "rv64ua-p-amoxor_w.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-amoxor_w.elf" + }, + { + "name": "rv64ua-p-lrsc.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ua-p-lrsc.elf" + }, + { + "name": "rv64uc-p-rvc.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64uc-p-rvc.elf" + }, + { + "name": "rv64ud-p-fadd.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ud-p-fadd.elf" + }, + { + "name": "rv64ud-p-fclass.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ud-p-fclass.elf" + }, + { + "name": "rv64ud-p-fcmp.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ud-p-fcmp.elf" + }, + { + "name": "rv64ud-p-fcvt.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ud-p-fcvt.elf" + }, + { + "name": "rv64ud-p-fcvt_w.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ud-p-fcvt_w.elf" + }, + { + "name": "rv64ud-p-fdiv.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ud-p-fdiv.elf" + }, + { + "name": "rv64ud-p-fmadd.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ud-p-fmadd.elf" + }, + { + "name": "rv64ud-p-fmin.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ud-p-fmin.elf" + }, + { + "name": "rv64ud-p-ldst.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ud-p-ldst.elf" + }, + { + "name": "rv64ud-p-recoding.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ud-p-recoding.elf" + }, + { + "name": "rv64ud-p-structural.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ud-p-structural.elf" + }, + { + "name": "rv64uf-p-fadd.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64uf-p-fadd.elf" + }, + { + "name": "rv64uf-p-fclass.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64uf-p-fclass.elf" + }, + { + "name": "rv64ud-p-move.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ud-p-move.elf" + }, + { + "name": "rv64uf-p-fcmp.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64uf-p-fcmp.elf" + }, + { + "name": "rv64uf-p-fcvt.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64uf-p-fcvt.elf" + }, + { + "name": "rv64uf-p-fcvt_w.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64uf-p-fcvt_w.elf" + }, + { + "name": "rv64uf-p-fdiv.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64uf-p-fdiv.elf" + }, + { + "name": "rv64uf-p-fmadd.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64uf-p-fmadd.elf" + }, + { + "name": "rv64uf-p-fmin.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64uf-p-fmin.elf" + }, + { + "name": "rv64uf-p-ldst.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64uf-p-ldst.elf" + }, + { + "name": "rv64uf-p-move.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64uf-p-move.elf" + }, + { + "name": "rv64uf-p-recoding.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64uf-p-recoding.elf" + }, + { + "name": "rv64ui-p-add.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-add.elf" + }, + { + "name": "rv64ui-p-addi.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-addi.elf" + }, + { + "name": "rv64ui-p-addiw.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-addiw.elf" + }, + { + "name": "rv64ui-p-addw.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-addw.elf" + }, + { + "name": "rv64ui-p-and.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-and.elf" + }, + { + "name": "rv64ui-p-andi.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-andi.elf" + }, + { + "name": "rv64ui-p-auipc.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-auipc.elf" + }, + { + "name": "rv64ui-p-beq.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-beq.elf" + }, + { + "name": "rv64ui-p-bge.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-bge.elf" + }, + { + "name": "rv64ui-p-bgeu.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-bgeu.elf" + }, + { + "name": "rv64ui-p-blt.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-blt.elf" + }, + { + "name": "rv64ui-p-bltu.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-bltu.elf" + }, + { + "name": "rv64ui-p-bne.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-bne.elf" + }, + { + "name": "rv64ui-p-fence_i.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-fence_i.elf" + }, + { + "name": "rv64ui-p-jal.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-jal.elf" + }, + { + "name": "rv64ui-p-jalr.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-jalr.elf" + }, + { + "name": "rv64ui-p-lb.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-lb.elf" + }, + { + "name": "rv64ui-p-lbu.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-lbu.elf" + }, + { + "name": "rv64ui-p-ld.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-ld.elf" + }, + { + "name": "rv64ui-p-lh.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-lh.elf" + }, + { + "name": "rv64ui-p-lhu.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-lhu.elf" + }, + { + "name": "rv64ui-p-lui.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-lui.elf" + }, + { + "name": "rv64ui-p-lw.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-lw.elf" + }, + { + "name": "rv64ui-p-lwu.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-lwu.elf" + }, + { + "name": "rv64ui-p-or.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-or.elf" + }, + { + "name": "rv64ui-p-ori.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-ori.elf" + }, + { + "name": "rv64ui-p-sb.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-sb.elf" + }, + { + "name": "rv64ui-p-sd.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-sd.elf" + }, + { + "name": "rv64ui-p-sh.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-sh.elf" + }, + { + "name": "rv64ui-p-simple.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-simple.elf" + }, + { + "name": "rv64ui-p-sll.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-sll.elf" + }, + { + "name": "rv64ui-p-slli.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-slli.elf" + }, + { + "name": "rv64ui-p-slliw.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-slliw.elf" + }, + { + "name": "rv64ui-p-sllw.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-sllw.elf" + }, + { + "name": "rv64ui-p-slt.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-slt.elf" + }, + { + "name": "rv64ui-p-slti.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-slti.elf" + }, + { + "name": "rv64ui-p-sltiu.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-sltiu.elf" + }, + { + "name": "rv64ui-p-sltu.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-sltu.elf" + }, + { + "name": "rv64ui-p-sra.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-sra.elf" + }, + { + "name": "rv64ui-p-srai.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-srai.elf" + }, + { + "name": "rv64ui-p-sraiw.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-sraiw.elf" + }, + { + "name": "rv64ui-p-sraw.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-sraw.elf" + }, + { + "name": "rv64ui-p-srl.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-srl.elf" + }, + { + "name": "rv64ui-p-srli.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-srli.elf" + }, + { + "name": "rv64ui-p-srliw.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-srliw.elf" + }, + { + "name": "rv64ui-p-srlw.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-srlw.elf" + }, + { + "name": "rv64ui-p-sub.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-sub.elf" + }, + { + "name": "rv64ui-p-subw.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-subw.elf" + }, + { + "name": "rv64ui-p-sw.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-sw.elf" + }, + { + "name": "rv64ui-p-xor.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-xor.elf" + }, + { + "name": "rv64ui-p-xori.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64ui-p-xori.elf" + }, + { + "name": "rv64um-p-div.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64um-p-div.elf" + }, + { + "name": "rv64um-p-divu.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64um-p-divu.elf" + }, + { + "name": "rv64um-p-divuw.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64um-p-divuw.elf" + }, + { + "name": "rv64um-p-divw.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64um-p-divw.elf" + }, + { + "name": "rv64um-p-mul.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64um-p-mul.elf" + }, + { + "name": "rv64um-p-mulh.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64um-p-mulh.elf" + }, + { + "name": "rv64um-p-mulhsu.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64um-p-mulhsu.elf" + }, + { + "name": "rv64um-p-mulhu.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64um-p-mulhu.elf" + }, + { + "name": "rv64um-p-mulw.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64um-p-mulw.elf" + }, + { + "name": "rv64um-p-rem.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64um-p-rem.elf" + }, + { + "name": "rv64um-p-remu.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64um-p-remu.elf" + }, + { + "name": "rv64um-p-remuw.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64um-p-remuw.elf" + }, + { + "name": "rv64um-p-remw.elf", + "url": "examples/RISCV-64-Sail-Validation/rv64um-p-remw.elf" + } +] \ No newline at end of file diff --git a/examples/RISCV-64-Sail-Validation/rv64mi-p-access.elf b/examples/RISCV-64-Sail-Validation/rv64mi-p-access.elf new file mode 100755 index 000000000..6335b6c04 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64mi-p-access.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64mi-p-breakpoint.elf b/examples/RISCV-64-Sail-Validation/rv64mi-p-breakpoint.elf new file mode 100644 index 000000000..571bfd716 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64mi-p-breakpoint.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64mi-p-csr.elf b/examples/RISCV-64-Sail-Validation/rv64mi-p-csr.elf new file mode 100644 index 000000000..be0792258 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64mi-p-csr.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64mi-p-illegal.elf b/examples/RISCV-64-Sail-Validation/rv64mi-p-illegal.elf new file mode 100644 index 000000000..d30104921 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64mi-p-illegal.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64mi-p-ma_addr.elf b/examples/RISCV-64-Sail-Validation/rv64mi-p-ma_addr.elf new file mode 100644 index 000000000..e5eadd5c9 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64mi-p-ma_addr.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64mi-p-ma_fetch.elf b/examples/RISCV-64-Sail-Validation/rv64mi-p-ma_fetch.elf new file mode 100644 index 000000000..4d66e6904 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64mi-p-ma_fetch.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64mi-p-mcsr.elf b/examples/RISCV-64-Sail-Validation/rv64mi-p-mcsr.elf new file mode 100644 index 000000000..796100bc2 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64mi-p-mcsr.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64mi-p-sbreak.elf b/examples/RISCV-64-Sail-Validation/rv64mi-p-sbreak.elf new file mode 100755 index 000000000..4bcd37ceb Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64mi-p-sbreak.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64mi-p-scall.elf b/examples/RISCV-64-Sail-Validation/rv64mi-p-scall.elf new file mode 100644 index 000000000..f82dea52f Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64mi-p-scall.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64si-p-csr.elf b/examples/RISCV-64-Sail-Validation/rv64si-p-csr.elf new file mode 100644 index 000000000..a6290ef67 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64si-p-csr.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64si-p-dirty.elf b/examples/RISCV-64-Sail-Validation/rv64si-p-dirty.elf new file mode 100644 index 000000000..a15a03329 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64si-p-dirty.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64si-p-ma_fetch.elf b/examples/RISCV-64-Sail-Validation/rv64si-p-ma_fetch.elf new file mode 100644 index 000000000..02155e5a3 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64si-p-ma_fetch.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64si-p-sbreak.elf b/examples/RISCV-64-Sail-Validation/rv64si-p-sbreak.elf new file mode 100755 index 000000000..cf0a8ca37 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64si-p-sbreak.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64si-p-scall.elf b/examples/RISCV-64-Sail-Validation/rv64si-p-scall.elf new file mode 100644 index 000000000..5eb47e1f6 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64si-p-scall.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64si-p-wfi.elf b/examples/RISCV-64-Sail-Validation/rv64si-p-wfi.elf new file mode 100644 index 000000000..46e1115bb Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64si-p-wfi.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amoadd_d.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoadd_d.elf new file mode 100644 index 000000000..359f6047d Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoadd_d.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amoadd_w.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoadd_w.elf new file mode 100644 index 000000000..a76f6044d Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoadd_w.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amoand_d.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoand_d.elf new file mode 100644 index 000000000..091e7f715 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoand_d.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amoand_w.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoand_w.elf new file mode 100644 index 000000000..edf0588fc Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoand_w.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amomax_d.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amomax_d.elf new file mode 100644 index 000000000..c8867f8b9 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amomax_d.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amomax_w.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amomax_w.elf new file mode 100644 index 000000000..e7d9ea5cf Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amomax_w.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amomaxu_d.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amomaxu_d.elf new file mode 100644 index 000000000..dab40262a Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amomaxu_d.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amomaxu_w.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amomaxu_w.elf new file mode 100644 index 000000000..6486fa463 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amomaxu_w.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amomin_d.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amomin_d.elf new file mode 100644 index 000000000..425c72ced Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amomin_d.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amomin_w.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amomin_w.elf new file mode 100644 index 000000000..2cdb17e73 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amomin_w.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amominu_d.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amominu_d.elf new file mode 100644 index 000000000..20d1b6fd5 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amominu_d.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amominu_w.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amominu_w.elf new file mode 100644 index 000000000..6a73fc4ee Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amominu_w.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amoor_d.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoor_d.elf new file mode 100644 index 000000000..71a32159b Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoor_d.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amoor_w.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoor_w.elf new file mode 100644 index 000000000..33196ad26 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoor_w.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amoswap_d.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoswap_d.elf new file mode 100644 index 000000000..2b2200cae Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoswap_d.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amoswap_w.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoswap_w.elf new file mode 100644 index 000000000..39ee63f35 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoswap_w.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amoxor_d.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoxor_d.elf new file mode 100644 index 000000000..cb45e313c Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoxor_d.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-amoxor_w.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoxor_w.elf new file mode 100644 index 000000000..c2d3412c1 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-amoxor_w.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ua-p-lrsc.elf b/examples/RISCV-64-Sail-Validation/rv64ua-p-lrsc.elf new file mode 100644 index 000000000..c443cf22c Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ua-p-lrsc.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64uc-p-rvc.elf b/examples/RISCV-64-Sail-Validation/rv64uc-p-rvc.elf new file mode 100644 index 000000000..ee821eba0 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64uc-p-rvc.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ud-p-fadd.elf b/examples/RISCV-64-Sail-Validation/rv64ud-p-fadd.elf new file mode 100644 index 000000000..eaa35c67e Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ud-p-fadd.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ud-p-fclass.elf b/examples/RISCV-64-Sail-Validation/rv64ud-p-fclass.elf new file mode 100644 index 000000000..7c23d4998 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ud-p-fclass.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ud-p-fcmp.elf b/examples/RISCV-64-Sail-Validation/rv64ud-p-fcmp.elf new file mode 100644 index 000000000..4ae6c9bea Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ud-p-fcmp.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ud-p-fcvt.elf b/examples/RISCV-64-Sail-Validation/rv64ud-p-fcvt.elf new file mode 100644 index 000000000..995bc818d Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ud-p-fcvt.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ud-p-fcvt_w.elf b/examples/RISCV-64-Sail-Validation/rv64ud-p-fcvt_w.elf new file mode 100644 index 000000000..4db28d5f3 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ud-p-fcvt_w.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ud-p-fdiv.elf b/examples/RISCV-64-Sail-Validation/rv64ud-p-fdiv.elf new file mode 100644 index 000000000..d62c776cd Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ud-p-fdiv.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ud-p-fmadd.elf b/examples/RISCV-64-Sail-Validation/rv64ud-p-fmadd.elf new file mode 100644 index 000000000..e1b977b38 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ud-p-fmadd.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ud-p-fmin.elf b/examples/RISCV-64-Sail-Validation/rv64ud-p-fmin.elf new file mode 100644 index 000000000..34c1ccbc5 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ud-p-fmin.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ud-p-ldst.elf b/examples/RISCV-64-Sail-Validation/rv64ud-p-ldst.elf new file mode 100755 index 000000000..42e53302c Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ud-p-ldst.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ud-p-move.elf b/examples/RISCV-64-Sail-Validation/rv64ud-p-move.elf new file mode 100755 index 000000000..2f32db96d Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ud-p-move.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ud-p-recoding.elf b/examples/RISCV-64-Sail-Validation/rv64ud-p-recoding.elf new file mode 100755 index 000000000..3fb62d7b0 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ud-p-recoding.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ud-p-structural.elf b/examples/RISCV-64-Sail-Validation/rv64ud-p-structural.elf new file mode 100755 index 000000000..0331e2bf5 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ud-p-structural.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64uf-p-fadd.elf b/examples/RISCV-64-Sail-Validation/rv64uf-p-fadd.elf new file mode 100644 index 000000000..e4c4a5b78 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64uf-p-fadd.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64uf-p-fclass.elf b/examples/RISCV-64-Sail-Validation/rv64uf-p-fclass.elf new file mode 100644 index 000000000..eae8b2788 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64uf-p-fclass.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64uf-p-fcmp.elf b/examples/RISCV-64-Sail-Validation/rv64uf-p-fcmp.elf new file mode 100644 index 000000000..42039b2c0 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64uf-p-fcmp.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64uf-p-fcvt.elf b/examples/RISCV-64-Sail-Validation/rv64uf-p-fcvt.elf new file mode 100644 index 000000000..bfcbcf05b Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64uf-p-fcvt.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64uf-p-fcvt_w.elf b/examples/RISCV-64-Sail-Validation/rv64uf-p-fcvt_w.elf new file mode 100644 index 000000000..2994eb4e2 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64uf-p-fcvt_w.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64uf-p-fdiv.elf b/examples/RISCV-64-Sail-Validation/rv64uf-p-fdiv.elf new file mode 100644 index 000000000..3501db357 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64uf-p-fdiv.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64uf-p-fmadd.elf b/examples/RISCV-64-Sail-Validation/rv64uf-p-fmadd.elf new file mode 100644 index 000000000..bc5121e9d Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64uf-p-fmadd.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64uf-p-fmin.elf b/examples/RISCV-64-Sail-Validation/rv64uf-p-fmin.elf new file mode 100644 index 000000000..b5548fbb3 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64uf-p-fmin.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64uf-p-ldst.elf b/examples/RISCV-64-Sail-Validation/rv64uf-p-ldst.elf new file mode 100755 index 000000000..d08002364 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64uf-p-ldst.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64uf-p-move.elf b/examples/RISCV-64-Sail-Validation/rv64uf-p-move.elf new file mode 100755 index 000000000..5a16f6319 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64uf-p-move.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64uf-p-recoding.elf b/examples/RISCV-64-Sail-Validation/rv64uf-p-recoding.elf new file mode 100755 index 000000000..b8f54ed82 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64uf-p-recoding.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-add.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-add.elf new file mode 100644 index 000000000..74330e9e1 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-add.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-addi.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-addi.elf new file mode 100644 index 000000000..d83a9a79f Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-addi.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-addiw.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-addiw.elf new file mode 100644 index 000000000..1556eea47 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-addiw.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-addw.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-addw.elf new file mode 100644 index 000000000..794963148 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-addw.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-and.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-and.elf new file mode 100644 index 000000000..9dda5d195 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-and.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-andi.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-andi.elf new file mode 100644 index 000000000..39d71d328 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-andi.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-auipc.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-auipc.elf new file mode 100644 index 000000000..cf2211ce8 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-auipc.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-beq.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-beq.elf new file mode 100644 index 000000000..5b8986582 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-beq.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-bge.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-bge.elf new file mode 100644 index 000000000..972d7fabe Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-bge.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-bgeu.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-bgeu.elf new file mode 100644 index 000000000..cd7e7e34f Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-bgeu.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-blt.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-blt.elf new file mode 100644 index 000000000..e3676a33f Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-blt.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-bltu.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-bltu.elf new file mode 100644 index 000000000..e4e6077e9 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-bltu.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-bne.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-bne.elf new file mode 100644 index 000000000..d28d9aaee Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-bne.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-fence_i.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-fence_i.elf new file mode 100644 index 000000000..682802e02 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-fence_i.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-jal.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-jal.elf new file mode 100644 index 000000000..8250b7554 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-jal.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-jalr.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-jalr.elf new file mode 100644 index 000000000..4d111a587 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-jalr.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-lb.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-lb.elf new file mode 100644 index 000000000..13970acc7 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-lb.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-lbu.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-lbu.elf new file mode 100644 index 000000000..b68b1991b Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-lbu.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-ld.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-ld.elf new file mode 100644 index 000000000..b4e659610 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-ld.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-lh.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-lh.elf new file mode 100644 index 000000000..5d6b965e1 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-lh.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-lhu.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-lhu.elf new file mode 100644 index 000000000..1b2550d9b Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-lhu.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-lui.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-lui.elf new file mode 100644 index 000000000..300ef0d20 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-lui.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-lw.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-lw.elf new file mode 100644 index 000000000..6c77ab8c9 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-lw.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-lwu.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-lwu.elf new file mode 100644 index 000000000..b920704cc Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-lwu.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-or.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-or.elf new file mode 100644 index 000000000..b3772ca73 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-or.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-ori.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-ori.elf new file mode 100644 index 000000000..d3a6b6d26 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-ori.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-sb.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-sb.elf new file mode 100644 index 000000000..20fdd3c04 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-sb.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-sd.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-sd.elf new file mode 100644 index 000000000..d3e68eaef Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-sd.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-sh.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-sh.elf new file mode 100644 index 000000000..4a38a063a Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-sh.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-simple.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-simple.elf new file mode 100644 index 000000000..68457c21b Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-simple.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-sll.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-sll.elf new file mode 100644 index 000000000..0c615ca2e Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-sll.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-slli.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-slli.elf new file mode 100644 index 000000000..c5f99f546 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-slli.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-slliw.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-slliw.elf new file mode 100644 index 000000000..cb8909f4d Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-slliw.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-sllw.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-sllw.elf new file mode 100644 index 000000000..e839d1b5b Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-sllw.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-slt.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-slt.elf new file mode 100644 index 000000000..1feb7df6b Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-slt.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-slti.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-slti.elf new file mode 100644 index 000000000..681c96311 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-slti.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-sltiu.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-sltiu.elf new file mode 100644 index 000000000..a52072b12 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-sltiu.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-sltu.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-sltu.elf new file mode 100644 index 000000000..16264ccda Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-sltu.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-sra.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-sra.elf new file mode 100644 index 000000000..fc9a1d975 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-sra.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-srai.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-srai.elf new file mode 100644 index 000000000..8efee5815 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-srai.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-sraiw.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-sraiw.elf new file mode 100644 index 000000000..d3a9099b5 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-sraiw.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-sraw.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-sraw.elf new file mode 100644 index 000000000..2b83afc3f Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-sraw.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-srl.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-srl.elf new file mode 100644 index 000000000..1ca262941 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-srl.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-srli.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-srli.elf new file mode 100644 index 000000000..a8dd4e3f2 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-srli.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-srliw.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-srliw.elf new file mode 100644 index 000000000..452617c0e Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-srliw.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-srlw.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-srlw.elf new file mode 100644 index 000000000..f1e87436b Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-srlw.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-sub.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-sub.elf new file mode 100644 index 000000000..d86768510 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-sub.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-subw.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-subw.elf new file mode 100644 index 000000000..d6c7c3b12 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-subw.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-sw.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-sw.elf new file mode 100644 index 000000000..6ca080c51 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-sw.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-xor.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-xor.elf new file mode 100644 index 000000000..7403f0533 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-xor.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64ui-p-xori.elf b/examples/RISCV-64-Sail-Validation/rv64ui-p-xori.elf new file mode 100644 index 000000000..f759bbafe Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64ui-p-xori.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64um-p-div.elf b/examples/RISCV-64-Sail-Validation/rv64um-p-div.elf new file mode 100644 index 000000000..c33b9549c Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64um-p-div.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64um-p-divu.elf b/examples/RISCV-64-Sail-Validation/rv64um-p-divu.elf new file mode 100644 index 000000000..6c7c99285 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64um-p-divu.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64um-p-divuw.elf b/examples/RISCV-64-Sail-Validation/rv64um-p-divuw.elf new file mode 100644 index 000000000..d28d92d3b Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64um-p-divuw.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64um-p-divw.elf b/examples/RISCV-64-Sail-Validation/rv64um-p-divw.elf new file mode 100644 index 000000000..62998ebe1 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64um-p-divw.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64um-p-mul.elf b/examples/RISCV-64-Sail-Validation/rv64um-p-mul.elf new file mode 100644 index 000000000..7db8e67f2 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64um-p-mul.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64um-p-mulh.elf b/examples/RISCV-64-Sail-Validation/rv64um-p-mulh.elf new file mode 100644 index 000000000..9a7009a03 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64um-p-mulh.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64um-p-mulhsu.elf b/examples/RISCV-64-Sail-Validation/rv64um-p-mulhsu.elf new file mode 100644 index 000000000..eb825f7a8 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64um-p-mulhsu.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64um-p-mulhu.elf b/examples/RISCV-64-Sail-Validation/rv64um-p-mulhu.elf new file mode 100644 index 000000000..b398098ec Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64um-p-mulhu.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64um-p-mulw.elf b/examples/RISCV-64-Sail-Validation/rv64um-p-mulw.elf new file mode 100644 index 000000000..865196096 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64um-p-mulw.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64um-p-rem.elf b/examples/RISCV-64-Sail-Validation/rv64um-p-rem.elf new file mode 100644 index 000000000..45a427e39 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64um-p-rem.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64um-p-remu.elf b/examples/RISCV-64-Sail-Validation/rv64um-p-remu.elf new file mode 100644 index 000000000..ce63b5f65 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64um-p-remu.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64um-p-remuw.elf b/examples/RISCV-64-Sail-Validation/rv64um-p-remuw.elf new file mode 100644 index 000000000..3e1fea532 Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64um-p-remuw.elf differ diff --git a/examples/RISCV-64-Sail-Validation/rv64um-p-remw.elf b/examples/RISCV-64-Sail-Validation/rv64um-p-remw.elf new file mode 100644 index 000000000..e079595ce Binary files /dev/null and b/examples/RISCV-64-Sail-Validation/rv64um-p-remw.elf differ diff --git a/package.json b/package.json index 11d754988..4e04622b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "creator", - "version": "6.1.0", + "version": "6.1.1", "private": true, "type": "module", "scripts": { diff --git a/src/cli/commands/info.mts b/src/cli/commands/info.mts index 3facdd65d..ce6b8805a 100644 --- a/src/cli/commands/info.mts +++ b/src/cli/commands/info.mts @@ -56,7 +56,7 @@ export function handleAboutCommand(): void { "║" + colorText(" 🚀 CREATOR Core Version:", "33") + ` ${creatorVersion}`.padEnd( - 35 - creatorVersion.length + " 6.1.0".length, + 35 - creatorVersion.length + " 6.1.1".length, ) + "║", ); diff --git a/src/cli/commands/instructions.mts b/src/cli/commands/instructions.mts index 7ba9e72ad..62eac4b77 100644 --- a/src/cli/commands/instructions.mts +++ b/src/cli/commands/instructions.mts @@ -50,7 +50,7 @@ function displayInstruction( hideLibrary = false, ): void { const address = instr.Address.padEnd(8); - const label = (instr.Label || "").padEnd(11); + const label = instr.Label.join(",").padEnd(11); let loaded = (instr.loaded || "").padEnd(23); const loadedIsBinary = /^[01]+$/.test(loaded); const rightColumn = instr.user || ""; @@ -100,7 +100,7 @@ export function handleInstructionsCommand(limit?: number): void { : instructions.length; for (let i = 0; i < count; i++) { - displayInstruction(instructions[i], currentPC); + displayInstruction(instructions[i]!, currentPC); } } @@ -117,7 +117,7 @@ export function findInstructionByAddressOrLabel( address = userInput.toLowerCase(); } else { const labelMatch = instructions.find( - instr => instr.Label === userInput, + instr => instr.Label.includes(userInput), ); if (labelMatch) { @@ -159,7 +159,7 @@ export function toggleBreakpoint(index: number): void { console.log( `Breakpoint ${status} at ${instr!.Address}${ - instr!.Label ? ` (${instr!.Label})` : "" + instr!.Label.length > 0 ? ` (${instr!.Label.join(",")})` : "" }: ${instr!.loaded}`, ); } @@ -179,7 +179,7 @@ function listBreakpoints(): void { for (const bp of breakpoints) { console.log( - ` ${bp.Address}${bp.Label ? ` (${bp.Label})` : ""}: ${bp.loaded}`, + ` ${bp.Address}${bp.Label.length > 0 ? ` (${bp.Label.join(",")})` : ""}: ${bp.loaded}`, ); } } diff --git a/src/cli/commands/memory.mts b/src/cli/commands/memory.mts index 48d4d1a88..9f92fb711 100644 --- a/src/cli/commands/memory.mts +++ b/src/cli/commands/memory.mts @@ -36,7 +36,7 @@ function applyHintHighlighting( const colors = getHintColors(); for (let k = hintsInRange.length - 1; k >= 0; k--) { - const { hint, offset } = hintsInRange[k]; + const { hint, offset } = hintsInRange[k]!; if (!hint.sizeInBits) continue; const sizeInBytes = Math.ceil(hint.sizeInBits / 8); @@ -68,7 +68,7 @@ function displayMemory(address: number, count: number): void { const formattedAddr = `0x${currentAddr.toString(16).padStart(8, "0")}`; const hintsInRange: Array<{ - hint: { tag: string; type: string; sizeInBits?: number }; + hint: { tag: string[]; type: string; sizeInBits?: number }; offset: number; }> = []; for (let j = 0; j < wordSize; j++) { @@ -95,8 +95,8 @@ function displayMemory(address: number, count: number): void { const colors = getHintColors(); for (let k = 0; k < hintsInRange.length; k++) { - const { hint, offset } = hintsInRange[k]; - const tag = hint.tag || ""; + const { hint, offset } = hintsInRange[k]!; + const tag = hint.tag.join(","); const type = hint.type || ""; const shortHint = type && tag ? `${tag}:${type}` : type || tag; const sizeInfo = hint.sizeInBits diff --git a/src/cli/types.mts b/src/cli/types.mts index cbe69b2f8..37b0a1b15 100644 --- a/src/cli/types.mts +++ b/src/cli/types.mts @@ -61,7 +61,7 @@ export interface ReturnType { */ export interface Instruction { Address: string; - Label: string | null; + Label: string[]; loaded: string; user: string; Break: boolean | null; diff --git a/src/cli/validator.mts b/src/cli/validator.mts index 219b5623c..56cfce404 100644 --- a/src/cli/validator.mts +++ b/src/cli/validator.mts @@ -23,7 +23,8 @@ import { crex_findReg } from "../../src/core/register/registerLookup.mjs"; import { readRegister } from "../../src/core/register/registerOperations.mjs"; import { raise } from "@/core/capi/validation.mts"; import { ARCH as RISCV } from "@/core/capi/arch/riscv.mjs"; -import { coreEvents, CoreEventTypes } from "@/core/events.mts"; +import { sentinel as sentinelApi } from "@/core/sentinel/sentinel.mts"; +import { coreEvents, CoreEventTypes, type SentinelErrorEvent } from "@/core/events.mts"; interface ExpectedState { registers?: { [name: string]: number }; @@ -58,11 +59,6 @@ export function executeN(n: number): { error: boolean; msg: string } { return ret; } -interface SentinelEvent { - functionName: string; - message: string; - ok: boolean; -} /** * Validates the execution of a program. @@ -79,9 +75,9 @@ export function validate( sentinel: boolean = true, ): { error: boolean; msg: string } { // subscribe to sentinel events - const sentinelErrors: SentinelEvent[] = []; - coreEvents.on(CoreEventTypes.SENTINEL_ERROR, (event: unknown) => { - sentinelErrors.push(event as SentinelEvent); + const sentinelErrors: SentinelErrorEvent[] = []; + coreEvents.on(CoreEventTypes.SENTINEL_ERROR, event => { + sentinelErrors.push(event); }); // execute program @@ -177,7 +173,7 @@ export function validate( error: true, msg: `Found ${sentinelErrors.length} sentinel errors:\n` + - sentinelErrors.map(e => e.message).join("\n"), + sentinelErrors.map(sentinelApi.formatErrors).join("\n"), }; } diff --git a/src/core/assembler/assembler.d.ts b/src/core/assembler/assembler.d.ts index eebd4e3d6..f48b08041 100644 --- a/src/core/assembler/assembler.d.ts +++ b/src/core/assembler/assembler.d.ts @@ -1,7 +1,7 @@ type Instruction = { Address: string; Break: boolean | null; - Label: string; + Label: string[]; binary: string; hide: boolean; loaded: string; @@ -16,3 +16,6 @@ export declare const instructions: Instruction[]; type InstructionTagMap = { [addr: number]: { tag: string; global: boolean } }; export declare let tag_instructions: InstructionTagMap; + +type CompilerFn = (code: string, library: boolean, ansi_color: boolean) + => Promise | object diff --git a/src/core/assembler/assembler.mjs b/src/core/assembler/assembler.mjs index b6021f5ff..c501c99eb 100644 --- a/src/core/assembler/assembler.mjs +++ b/src/core/assembler/assembler.mjs @@ -103,11 +103,20 @@ export function formatErrorWithColors(error) { return htmlMsg; } -export function getCleanErrorMessage(error) { +export function getCleanErrorMessage(error, ansi_color = true) { const errorMsg = String(error); - const parsed = ansicolor.parse(errorMsg); - const cleanMsg = parsed.spans.map(span => span.text).join(""); - return cleanMsg; + if (ansi_color) { + const parsed = ansicolor.parse(errorMsg); + return parsed.spans.map(span => span.text).join(""); + } else { + return errorMsg + .replace(/<.+?>/g, "") + .replace(/&/g, "&") + .replace(/</g, "<") + .replace(/>/g, ">") + .replace(/"/g, '"') + .replace(/'/g, "'"); + } } /** @@ -319,10 +328,11 @@ export function parseDebugSymbols(debugSymbols) { /** * Dispatcher for assembly compilers. * @param {string} code - * @param {any} library - * @param {string} compiler + * @param {boolean} library + * @param {import("./assembler.d.ts").CompilerFn} compiler + * @param {boolean} ansi_color */ -export function assembly_compiler(code, library, compiler) { +export function assembly_compiler(code, library, compiler, ansi_color = false) { // If no compiler is specified, error out if (!compiler) { raise("No compiler specified for assembly compilation"); @@ -333,5 +343,5 @@ export function assembly_compiler(code, library, compiler) { status.executedInstructions = 0; status.clkCycles = 0; - return compiler(code, library); + return compiler(code, library, ansi_color); } diff --git a/src/core/assembler/creatorAssembler/creatorAssemblerBase.mjs b/src/core/assembler/creatorAssembler/creatorAssemblerBase.mjs index 479a06e3a..5abb5cddb 100644 --- a/src/core/assembler/creatorAssembler/creatorAssemblerBase.mjs +++ b/src/core/assembler/creatorAssembler/creatorAssemblerBase.mjs @@ -63,10 +63,11 @@ let libraryInstructions = []; /** * Handle compilation error * @param {String} error - Error message returned by the assembler + * @param {boolean} ansi_color - Whether errors are formatted with ANSI or HTML colors * @returns {Object} Structured error data */ -function handleError(error) { - const cleanErrorText = error.replace(/<.+?>/g, ""); +function handleError(error, ansi_color) { + const cleanErrorText = getCleanErrorMessage(error, ansi_color); const linterInfo = parseErrorForLinter(cleanErrorText); return { errorcode: "101", @@ -141,7 +142,7 @@ function loadLibraryIfPresent(instructions) { // Convert hex string to binary string let binaryString = ""; for (let i = 0; i < loadedLibrary.binary.length; i += 2) { - const hexByte = loadedLibrary.binary.slice(i, i+2); + const hexByte = loadedLibrary.binary.slice(i, i + 2); const byte = parseInt(hexByte, 16); binaryString += byte.toString(2).padStart(8, "0"); } @@ -160,14 +161,17 @@ function loadLibraryIfPresent(instructions) { // Process each instruction let currentAddr = 0; for (let i = 0; i < binaryString.length; i += instructionSizeBits) { - const instructionBinary = binaryString.slice(i, i + instructionSizeBits); + const instructionBinary = binaryString.slice( + i, + i + instructionSizeBits, + ); const symbolName = symbolsByAddr.get(currentAddr); const hasSymbol = symbolName !== undefined; const instruction = { Break: null, Address: `0x${currentAddr.toString(16)}`, - Label: hasSymbol ? symbolName : "", + Label: hasSymbol ? [symbolName] : [], loaded: instructionBinary, user: null, _rowVariant: "", @@ -194,8 +198,7 @@ function loadLibraryIfPresent(instructions) { function loadDataIntoMemory(data_mem, wasmModules) { const { DataCategoryJS } = wasmModules; const wordSizeBytes = - newArchitecture.config.word_size / - newArchitecture.config.byte_size; + newArchitecture.config.word_size / newArchitecture.config.byte_size; for (let i = 0; i < data_mem.length; i++) { const data = data_mem[i]; const addr = data.address(); @@ -374,26 +377,14 @@ function loadDataIntoMemory(data_mem, wasmModules) { break; case DataCategoryJS.String: { - const encoder = new TextEncoder(); - let currentAddr = addr; - - for (const ch_h of data.value(false)) { - const bytes = new Uint8Array(4); - const n = encoder.encodeInto(ch_h, bytes).written; - for (let j = 0; j < n; j++) { - main_memory.write(currentAddr, bytes[j]); - currentAddr++; - } + const bytes = new TextEncoder().encode(data.value(false)); + for (let i = 0n; i < bytes.length; i++) { + main_memory.write(addr + i, bytes[i]); } const stringLength = Number(size); const stringType = "string"; - main_memory.addHint( - addr, - labels, - stringType, - stringLength * 8, - ); + main_memory.addHint(addr, labels, stringType, stringLength * 8); break; } @@ -405,12 +396,7 @@ function loadDataIntoMemory(data_mem, wasmModules) { const spaceType = category === DataCategoryJS.Padding ? "padding" : "space"; - main_memory.addHint( - addr, - labels, - spaceType, - Number(size) * 8, - ); + main_memory.addHint(addr, labels, spaceType, Number(size) * 8); break; } @@ -428,23 +414,20 @@ function writeBinaryToMemory(binary, baseAddr) { // Split into words, reverse order, and concatenate const words = []; for (let j = 0; j < binary.length; j += WORDSIZE) { - words.push(binary.slice(j, j+WORDSIZE)); + words.push(binary.slice(j, j + WORDSIZE)); } const reversedBinary = words.reverse().join(""); for (let j = 0; j < reversedBinary.length; j += WORDSIZE) { - const wordBinary = reversedBinary.slice(j, j+WORDSIZE); + const wordBinary = reversedBinary.slice(j, j + WORDSIZE); const wordBytes = []; for (let k = 0; k < wordBinary.length; k += BYTESIZE) { - const byte = parseInt(wordBinary.slice(k, k+BYTESIZE), 2); + const byte = parseInt(wordBinary.slice(k, k + BYTESIZE), 2); wordBytes.push(byte); } - main_memory.writeWord( - BigInt(baseAddr + j / BYTESIZE), - wordBytes, - ); + main_memory.writeWord(BigInt(baseAddr + j / BYTESIZE), wordBytes); } } @@ -458,7 +441,7 @@ function writeLibraryToMemory() { let binaryString = ""; for (let i = 0; i < loadedLibrary.binary.length; i += 2) { - const hexByte = loadedLibrary.binary.slice(i, i+2); + const hexByte = loadedLibrary.binary.slice(i, i + 2); const byte = parseInt(hexByte, 16); binaryString += byte.toString(2).padStart(8, "0"); } @@ -468,8 +451,11 @@ function writeLibraryToMemory() { const instructionSizeBytes = instructionSizeBits / 8; for (let i = 0; i < binaryString.length; i += instructionSizeBits) { - const instructionBinary = binaryString.slice(i, i+instructionSizeBits); - writeBinaryToMemory(instructionBinary, currentAddr) + const instructionBinary = binaryString.slice( + i, + i + instructionSizeBits, + ); + writeBinaryToMemory(instructionBinary, currentAddr); currentAddr += instructionSizeBytes; } } @@ -483,7 +469,7 @@ function writeInstructionsToMemory(instructions, library_instructions) { for (let i = library_instructions; i < instructions.length; i++) { const instruction = instructions[i]; const addr = parseInt(instruction.Address, 16); - writeBinaryToMemory(instruction.binary, addr) + writeBinaryToMemory(instruction.binary, addr); } } @@ -491,9 +477,10 @@ function writeInstructionsToMemory(instructions, library_instructions) { * Compile assembly code as a library * @param {string} code - Assembly code to compile * @param {WasmModules} wasmModules - Assembler's WASM modules + * @param {boolean} ansi_color - Whether to use ANSI or HTML colors (default: HTML) * @returns {Object} Compilation result */ -export function assembleCreatorLibrary(code, wasmModules) { +export function assembleCreatorLibrary(code, wasmModules, ansi_color) { /* Google Analytics */ creator_ga("compile", "compile.library"); @@ -516,7 +503,7 @@ export function assembleCreatorLibrary(code, wasmModules) { 0, // library_offset (not used for library compilation) "{}", // no library labels true, // library flag - Color.Html, + ansi_color ? Color.Ansi : Color.Html, ); // Library compilation: only binary instructions @@ -543,17 +530,16 @@ export function assembleCreatorLibrary(code, wasmModules) { const data_mem = compiled.data; loadDataIntoMemory(data_mem, wasmModules); } catch (error) { - return handleError(error) + return handleError(error, ansi_color); } // Mark global labels on library instructions for (const instruction of libraryInstructions) { - if (instruction.Label !== "") { - if (label_table[instruction.Label].global === true) { - instruction.globl = true; - } else { - instruction.Label = ""; - } + instruction.Label = instruction.Label.filter( + label => label_table[label].global, + ); + if (instruction.Label.length > 0) { + instruction.globl = true; } } @@ -573,9 +559,10 @@ export function assembleCreatorLibrary(code, wasmModules) { * Compile assembly code as a normal program * @param {string} code - Assembly code to compile * @param {WasmModules} wasmModules - Assembler's WASM modules + * @param {boolean} ansi_color - Whether to use ANSI or HTML colors (default: HTML) * @returns {Object} Compilation result */ -export function assembleCreatorProgram(code, wasmModules) { +export function assembleCreatorProgram(code, wasmModules, ansi_color) { /* Google Analytics */ creator_ga("compile", "compile.assembly"); @@ -604,7 +591,7 @@ export function assembleCreatorProgram(code, wasmModules) { library_offset, labels_json, false, // not a library - Color.Html, + ansi_color ? Color.Ansi : Color.Html, ); // Normal compilation: populate instructions for execution/display @@ -631,7 +618,7 @@ export function assembleCreatorProgram(code, wasmModules) { const data_mem = compiled.data; loadDataIntoMemory(data_mem, wasmModules); } catch (error) { - return handleError(error) + return handleError(error, ansi_color); } // Write library binary to memory if present @@ -666,12 +653,18 @@ export function assembleCreatorProgram(code, wasmModules) { * @param {string} code - Assembly code to compile * @param {boolean} library - Whether this is a library compilation * @param {WasmModules} wasmModules - Assembler's WASM modules + * @param {boolean} ansi_color - Whether to use ANSI or HTML colors (default: HTML) * @returns {Object} Compilation result */ -export function assembleCreatorBase(code, library, wasmModules) { +export function assembleCreatorBase( + code, + library, + wasmModules, + ansi_color = false, +) { if (library) { - return assembleCreatorLibrary(code, wasmModules); + return assembleCreatorLibrary(code, wasmModules, ansi_color); } else { - return assembleCreatorProgram(code, wasmModules); + return assembleCreatorProgram(code, wasmModules, ansi_color); } } diff --git a/src/core/assembler/creatorAssembler/deno/creatorAssembler.mjs b/src/core/assembler/creatorAssembler/deno/creatorAssembler.mjs index 62d02d05c..df9ab5991 100644 --- a/src/core/assembler/creatorAssembler/deno/creatorAssembler.mjs +++ b/src/core/assembler/creatorAssembler/deno/creatorAssembler.mjs @@ -22,13 +22,14 @@ import { assembleCreatorBase } from "../creatorAssemblerBase.mjs"; import * as wasmModules from "./wasm/creator_assembler.js"; /** - * Deno-specific assembly compiler that uses ANSI color configuration + * Deno-specific assembly compiler * WASM is automatically initialized in Deno version * @param {string} code - Assembly code to compile * @param {boolean} library - Whether this is a library compilation + * @param {boolean} ansi_color - Whether to use ANSI or HTML colors (default: ANSI) * @returns {Object} Compilation result */ -export function assembleCreator(code, library) { +export function assembleCreator(code, library, ansi_color = true) { // Call the common base implementation - return assembleCreatorBase(code, library, wasmModules); + return assembleCreatorBase(code, library, wasmModules, ansi_color); } diff --git a/src/core/assembler/creatorAssembler/web/creatorAssembler.mjs b/src/core/assembler/creatorAssembler/web/creatorAssembler.mjs index 0eee173ef..bd1dd1d19 100644 --- a/src/core/assembler/creatorAssembler/web/creatorAssembler.mjs +++ b/src/core/assembler/creatorAssembler/web/creatorAssembler.mjs @@ -32,5 +32,5 @@ export async function assembleCreator(code, library) { await wasm_web_init(); // Call the common base implementation - return assembleCreatorBase(code, library, wasmModules); + return assembleCreatorBase(code, library, wasmModules, false); } diff --git a/src/core/assembler/rasm/deno/rasm.mjs b/src/core/assembler/rasm/deno/rasm.mjs index 8f6699093..e41e7a926 100644 --- a/src/core/assembler/rasm/deno/rasm.mjs +++ b/src/core/assembler/rasm/deno/rasm.mjs @@ -126,7 +126,7 @@ export function rasmAssemble(code) { // Add hints to memory based on the parsed labels for (const [name, addr] of Object.entries(parsedSymbols)) { - main_memory.addHint(addr, name); + main_memory.addHint(addr, [name]); } // Set the tag instructions for the parsed symbols diff --git a/src/core/assembler/rasm/web/rasm.mjs b/src/core/assembler/rasm/web/rasm.mjs index f1190bb74..04fd01ba8 100644 --- a/src/core/assembler/rasm/web/rasm.mjs +++ b/src/core/assembler/rasm/web/rasm.mjs @@ -205,7 +205,7 @@ export async function rasmAssemble(code) { // Add hints to memory based on the parsed labels for (const [name, addr] of Object.entries(parsedSymbols)) { - main_memory.addHint(addr, name); + main_memory.addHint(addr, [name]); } // Set the tag instructions for the parsed symbols diff --git a/src/core/assembler/sailAssembler/web/CNAssambler.mjs b/src/core/assembler/sailAssembler/web/CNAssambler.mjs index 81c969991..d0a8ad000 100644 --- a/src/core/assembler/sailAssembler/web/CNAssambler.mjs +++ b/src/core/assembler/sailAssembler/web/CNAssambler.mjs @@ -897,7 +897,7 @@ export async function dump(file){ instructions.push({ Break: null, Address: "0x" + dumptextinstructions32[i][0], - Label: dumptextinstructions32[i][4], + Label: [dumptextinstructions32[i][4]], loaded: dumptextinstructions32[i][2], user : list_user_instructions[i], L1_I: 0, @@ -959,7 +959,7 @@ export async function dump(file){ instructions.push({ Break: null, Address: "0x" + dumptextinstructions64[i][0], - Label: dumptextinstructions64[i][4], + Label: [dumptextinstructions64[i][4]], loaded: dumptextinstructions64[i][2], user : list_user_instructions[i], L1_I: 0, diff --git a/src/core/assembler/sjasmplus/deno/sjasmplus.mjs b/src/core/assembler/sjasmplus/deno/sjasmplus.mjs index 430bdd2c4..66ad4d0da 100644 --- a/src/core/assembler/sjasmplus/deno/sjasmplus.mjs +++ b/src/core/assembler/sjasmplus/deno/sjasmplus.mjs @@ -84,7 +84,7 @@ export function sjasmplusAssemble(code) { // Now add hints to memory based on the parsed symbols (its a dictionary) for (const [name, addr] of Object.entries(parsedSymbols)) { - main_memory.addHint(addr, name); + main_memory.addHint(addr, [name]); } // Clean up temp files diff --git a/src/core/capi/arch/mips.mjs b/src/core/capi/arch/mips.mjs index e7a62b532..8a62c5692 100644 --- a/src/core/capi/arch/mips.mjs +++ b/src/core/capi/arch/mips.mjs @@ -39,13 +39,14 @@ export const ARCH = { /** * Reads a double precision floating point value from a register pair. - * @param {string} regName - The base register name (must be even, e.g., "f0") + * @param {string} regName - The base register name (must be even, e.g., "f0" or "FP0") * @returns {number} The JavaScript number representation of the double */ readDouble(regName) { this.validateEvenRegister(regName); - const regNumber = parseInt(regName.substring(1), 10); + const offset = regName.substring(0, 2) === "FP"? 2 : 1; + const regNumber = parseInt(regName.substring(offset), 10); const highReg = regName; const lowRegName = "f" + (regNumber + 1); diff --git a/src/core/capi/arch/riscv.mjs b/src/core/capi/arch/riscv.mjs index 27313cd2d..3b10f1114 100644 --- a/src/core/capi/arch/riscv.mjs +++ b/src/core/capi/arch/riscv.mjs @@ -227,4 +227,13 @@ export const ARCH = { NaNBoxed = BigInt(NaNBoxed); return NaNBoxed; }, + /** + * Writes a float32 to a register, using NaN boxing with float64 + * @param {number} value - The JavaScript number to write + * @param {string} regName - The base register name (must be even, e.g., "f0") + **/ + writeFloat(value, regName) { + const bits = this.toBigInt(value, "NaNBfloat32_64") + CAPI.REG.write(bits, regName) + } }; diff --git a/src/core/capi/arduino_functions.mts b/src/core/capi/arduino_functions.mts index f2663dc30..f62388391 100644 --- a/src/core/capi/arduino_functions.mts +++ b/src/core/capi/arduino_functions.mts @@ -796,10 +796,10 @@ export function cr_digitalPinToInterrupt() { }); } export function cr_interrupts() { - //TODO + coreEvents.emit("arduino-interrupts-enabled", true); } export function cr_nointerrupts() { - // TODO + coreEvents.emit("arduino-interrupts-enabled", false); } export function cr_isDigit() { var ret1 = crex_findReg("a0"); @@ -1301,11 +1301,9 @@ export function cr_serial_flush() { }); if (serial_begin != 0 && initArduino != 0) { status.keyboard = ""; - status.display = ""; const root = (document as any).app; if (root) { root.keyboard = ""; - root.display = ""; root.enter = null; } } diff --git a/src/core/capi/memory.mts b/src/core/capi/memory.mts index ef5ef4b38..4c1978c63 100644 --- a/src/core/capi/memory.mts +++ b/src/core/capi/memory.mts @@ -17,11 +17,11 @@ * along with CREATOR. If not, see . */ -import { main_memory, stackTracker, BYTESIZE } from "../core.mjs"; +import { main_memory, stackTracker, BYTESIZE, REGISTERS } from "../core.mjs"; import { exit } from "../executor/executor.mjs"; import { raise } from "./validation.mts"; import { crex_findReg } from "../register/registerLookup.mjs"; -import { sentinel } from "../sentinel/sentinel.mjs"; +import { sentinel } from "../sentinel/sentinel.mts"; import { checkDeviceAddr, devices } from "../executor/devices.mts"; import type { Memory } from "../memory/Memory.mts"; import { toHex } from "../utils/utils.mjs"; @@ -226,7 +226,7 @@ export const MEM = { if (hint) { try { const sizeInBits = bytes * BYTESIZE; - memory.addHint(BigInt(address), "", hint, sizeInBits); + memory.addHint(BigInt(address), [], hint, sizeInBits); } catch (e) { raise( "Failed to add hint for address '0x" + @@ -245,9 +245,10 @@ export const MEM = { const i = ret.indexComp; const j = ret.indexElem; - // Add stack hint if we're writing to the stack segment and have a register name - if (segment === "stack" && reg_name) { - stackTracker.addHint(address, reg_name); + // Add stack hint if we're writing to the stack segment + if (segment === "stack") { + const reg = REGISTERS[i]!.elements[j]!; + stackTracker.addHint(address, reg.name.join(",")); } sentinel.recordMemoryWrite(i, j, address, byteArray.length); @@ -319,10 +320,14 @@ export const MEM = { return ret; }, - alloc(bytes: number): number { - // TODO - raise("MEM.alloc is not implemented"); - return 0; + /** + * Allocates N bytes of memory + * + * @param bytes - Amount of bytes to allocate + * @returns Starting address of the allocation + */ + alloc(bytes: number): bigint { + return main_memory.alloc(bytes, "data"); }, /** @@ -341,7 +346,7 @@ export const MEM = { : devices.get(deviceID)!.memory; try { - memory.addHint(address, "", hint, sizeInBits); + memory.addHint(address, [], hint, sizeInBits); return true; } catch (e) { raise( diff --git a/src/core/capi/stack.mts b/src/core/capi/stack.mts index 4a98abf41..2ca0b5212 100644 --- a/src/core/capi/stack.mts +++ b/src/core/capi/stack.mts @@ -19,7 +19,7 @@ import { architecture, REGISTERS, getPC, stackTracker } from "../core.mjs"; import { tag_instructions } from "../assembler/assembler.mjs"; -import { sentinel } from "../sentinel/sentinel.mjs"; +import { sentinel } from "../sentinel/sentinel.mts"; import { creator_ga } from "../utils/creator_ga.mjs"; import { coreEvents, CoreEventTypes } from "../events.mts"; @@ -47,8 +47,7 @@ export const STACK = { } }, endFrame() { - // stack tracker: pop both frames - stackTracker.popFrame(); + // stack tracker: pop frame stackTracker.popFrame(); // sentinel @@ -56,9 +55,6 @@ export const STACK = { return; } - // get function name - const currentFunction = sentinel.getCurrentFunction() || "unknown"; - const ret = sentinel.leave(); if (ret.ok) { @@ -66,17 +62,13 @@ export const STACK = { } // emit event for GUI - coreEvents.emit(CoreEventTypes.SENTINEL_ERROR, { - functionName: currentFunction, - message: ret.msg, - ok: false, - }); + coreEvents.emit(CoreEventTypes.SENTINEL_ERROR, ret); // Google Analytics creator_ga( "execute", "execute.exception", - "execute.exception.protection_jrra" + ret.msg, + "execute.exception.protection_jrra", ); }, diff --git a/src/core/capi/syscall.mts b/src/core/capi/syscall.mts index 4c2318813..c5708af84 100644 --- a/src/core/capi/syscall.mts +++ b/src/core/capi/syscall.mts @@ -29,7 +29,7 @@ import { kbd_read_char, kbd_read_string, } from "../executor/IO.mjs"; -import { readRegister } from "../register/registerOperations.mjs"; +import { readRegister, writeRegister } from "../register/registerOperations.mjs"; import { creator_ga } from "../utils/creator_ga.mjs"; import type { Memory } from "../memory/Memory.mts"; import { coreEvents, CoreEventTypes } from "../events.mts"; @@ -68,14 +68,16 @@ export const SYSCALL = { break; } case "string": { - const buffer = []; + const bytes = []; // read byte by byte until a null terminator is found for (let i = 0; i < mainMemory.getSize(); i++) { - const byte = mainMemory.read((value as bigint) + BigInt(i)); + const byte = mainMemory.read(BigInt(value) + BigInt(i)); if (byte === 0) break; // null terminator - buffer.push(String.fromCharCode(byte)); + bytes.push(byte); } - const msg = buffer.join(""); + // Decode the UTF-8 data to a string + const buffer = new Uint8Array(bytes); + const msg = new TextDecoder().decode(buffer); display_print(msg); break; } @@ -158,30 +160,36 @@ export const SYSCALL = { } }, - sbrk(value1: string, value2: string) { - // TODO: this is (probably) broken + /** + * Allocates N bytes of memory + * + * @param size - Name of the register with the size to allocate + * @param ret_addr - Name of the register where the address of the beginning + * of the allocation should be placed + */ + sbrk(size: string, ret_addr: string) { /* Google Analytics */ creator_ga("execute", "execute.syscall", "execute.syscall.sbrk"); /* Get register id */ - const ret1 = crex_findReg(value1); - if (ret1.match === 0) { - throw new Error("capi_syscall: register " + value1 + " not found"); + const size_reg = crex_findReg(size); + if (size_reg.match === 0) { + throw new Error("capi_syscall: register " + size + " not found"); } - const ret2 = crex_findReg(value2); - if (ret2.match === 0) { - throw new Error("capi_syscall: register " + value2 + " not found"); + const ret_addr_reg = crex_findReg(ret_addr); + if (ret_addr_reg.match === 0) { + throw new Error("capi_syscall: register " + ret_addr + " not found"); } /* Request more memory */ - const new_size = readRegister(ret1.indexComp, ret1.indexElem); + const new_size = readRegister(size_reg.indexComp, size_reg.indexElem); if (new_size < 0) { throw new Error("capi_syscall: negative size"); } - // const new_addr = creator_memory_alloc(new_size); - // writeRegister(new_addr, ret2.indexComp, ret2.indexElem); + const new_addr = CAPI.MEM.alloc(Number(new_size)); + writeRegister(new_addr, ret_addr_reg.indexComp, ret_addr_reg.indexElem); }, get_clk_cycles(): number { diff --git a/src/core/capi/validation.mts b/src/core/capi/validation.mts index dd4276e07..4fe2c40c5 100644 --- a/src/core/capi/validation.mts +++ b/src/core/capi/validation.mts @@ -18,6 +18,7 @@ */ import { capi_uint2int } from "./fp.mts"; +import { architecture } from "../core.mjs"; type Document = { app: { exception(msg: string): unknown } }; @@ -44,8 +45,15 @@ export function isOverflow(op1: bigint, op2: bigint, res_u: bigint) { ); } -export function isMisaligned(addr: bigint, type: string) { - return false; +/** + * Checks whether an address is misaligned + * @param addr - Base address to read/write + * @param size - Size of the element being read/written + **/ +export function isMisaligned(addr: bigint, size: bigint|number) { + const config = architecture.config; + const word_size_bytes = BigInt(config.word_size / config.byte_size); + return addr % word_size_bytes !== 0n && addr % BigInt(size) !== 0n; } // Object export for initCAPI spreading diff --git a/src/core/core.mjs b/src/core/core.mjs index b22d072c3..4b281b26e 100644 --- a/src/core/core.mjs +++ b/src/core/core.mjs @@ -16,6 +16,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with CREATOR. If not, see . */ +import yaml from "js-yaml"; import { initCAPI } from "./capi/initCAPI.mts"; import { getHexTwosComplement } from "./utils/utils.mjs"; import { logger } from "./utils/creator_logger.mjs"; @@ -34,7 +35,7 @@ import { import { readRegister, writeRegister } from "./register/registerOperations.mjs"; import { StackTracker } from "./memory/StackTracker.mts"; import { creator_ga } from "./utils/creator_ga.mjs"; -import { sentinel } from "./sentinel/sentinel.mjs"; +import { sentinel } from "./sentinel/sentinel.mts"; import { resetStats } from "./executor/stats.mts"; import { resetDecoderCache } from "./executor/decoder.mjs"; import { coreEvents } from "./events.mts"; @@ -95,7 +96,6 @@ export let BYTESIZE; export let ENDIANNESSARR = []; /** @type {import("./core.d.ts").RegisterBank[]} */ export let REGISTERS; -export let REGISTERS_BACKUP = []; export const register_size_bits = 32; //TODO: load from architecture /** @type {Memory} */ export let main_memory; @@ -111,7 +111,7 @@ export let interruptManager; export function setInterruptManager(value) { interruptManager = value; } -/** @type {Memory} */ +/** @type {MemoryBackup} */ export let main_memory_backup; export function updateMainMemoryBackup(value) { main_memory_backup = value; @@ -226,10 +226,6 @@ export function loadArchitecture(architectureYaml, isa = []) { stackTracker = new StackTracker(); interruptManager = new InterruptManager(status.interrupt_handler); - // Create deep copy backup of REGISTERS after all initialization is complete - // This ensures the backup contains the correct values for all registers, including SP - REGISTERS_BACKUP = JSON.parse(JSON.stringify(REGISTERS)); - PC_REG_INDEX = crex_findReg_bytag("program_counter"); SP_REG_INDEX = crex_findReg_bytag("stack_pointer"); @@ -255,14 +251,12 @@ export function loadArchitecture(architectureYaml, isa = []) { */ export function load_library(lib_str) { // Parse YAML library format - import("js-yaml") - .then(yaml => { - loadedLibrary = yaml.load(lib_str); - coreEvents.emit("library-loaded"); - }) - .catch(error => { - throw new SyntaxError(`Invalid library format: ${error.message}`); - }); + try { + loadedLibrary = yaml.load(lib_str); + coreEvents.emit("library-loaded"); + } catch (error) { + throw new SyntaxError(`Invalid library format: ${error.message}`); + }; } /** * Loads a library to Sail simulator. @@ -307,17 +301,24 @@ export async function load_CREATino() { // compilation -export async function assembly_compile(code, compiler) { +/** + * Compiles an assembly code with the chosen compiler + * @param {string} code + * @param {import("./assembler/assembler.d.ts").CompilerFn} compiler + * @param {boolean} ansi_color - Whether to format errors with ANSI escape sequences + * (`true`) or HTML tags (`false`) + **/ +export async function assembly_compile(code, compiler, ansi_color = false) { var ret; if (architecture.config.name.includes("SRV")){ if (Object.keys(loadedLibrary).length === 0) - ret = await assembly_compiler(code, false, compiler); + ret = await assembly_compiler(code, false, compiler, ansi_color); else - ret = await assembly_compiler(code, true, compiler); + ret = await assembly_compiler(code, true, compiler, ansi_color); } else{ - ret = await assembly_compiler(code, false, compiler); + ret = await assembly_compiler(code, false, compiler, ansi_color); } switch (ret.status) { @@ -371,15 +372,10 @@ export function reset() { status.display = ""; // reset registers - // Restore register values from backup, preserving BigInt types - for (let i = 0; i < REGISTERS.length; i++) { - for (let j = 0; j < REGISTERS[i].elements.length; j++) { - // Copy value from backup, ensuring it's a BigInt - const backupValue = REGISTERS_BACKUP[i].elements[j].value; - REGISTERS[i].elements[j].value = - typeof backupValue === "bigint" - ? backupValue - : BigInt(backupValue); + // Restore register default values + for (const file of REGISTERS) { + for (const register of file.elements) { + register.value = register.default_value } } crex_clearRegisterCache(); @@ -682,11 +678,10 @@ export function getRegisterInfo(regName) { } export function getPC() { - const pc_address = readRegister( + return readRegister( PC_REG_INDEX.indexComp, PC_REG_INDEX.indexElem, ); - return BigInt(pc_address); } export function getSP() { diff --git a/src/core/events.mts b/src/core/events.mts index 3b44da169..53de4d76c 100644 --- a/src/core/events.mts +++ b/src/core/events.mts @@ -39,6 +39,7 @@ export const CoreEventTypes = { ARDUINO_PIN_CHANGED: "arduino-pin-write", ARDUINO_RESET: "arduino-reset", ARDUINO_PIN_INTERRUPT: "arduino-pin-interrupt", + VALIDATION_UPDATE: "update-validation", } as const; /** @@ -51,14 +52,26 @@ export interface RegisterUpdatedEvent { indexElem: number; } +/** + * Calling convention violation information + */ +export interface SentinelErrorData { + /** ID of the rule broken */ + rule: string, + /** Register in which the rule was broken, if applicable */ + register?: string[], + /** Full error message */ + message: string +} + /** * Emitted when calling convention violations are detected */ export interface SentinelErrorEvent { /** Name of the function that had violations */ functionName: string; - /** Full error message */ - message: string; + /** Violations found on the function */ + errors: SentinelErrorData[]; /** Whether the check passed (always false for error events) */ ok: boolean; } @@ -137,6 +150,8 @@ export type CoreEvents = { "arduino-find-vector-slot": ArduinoFindSlotEvent; /** Emitted when the simulator requests to get the pin assigned to an interrupt vector slot */ "arduino-get-pin-from-slot": ArduinoGetPinFromSlotEvent; + /** Emitted when interrupts are enabled/disabled */ + "arduino-interrupts-enabled": boolean; }; /** * Emitted when the simulator sends text to the Arduino Terminal diff --git a/src/core/executor/IO.mjs b/src/core/executor/IO.mjs index 1f545e932..a9857c6aa 100644 --- a/src/core/executor/IO.mjs +++ b/src/core/executor/IO.mjs @@ -33,6 +33,13 @@ import { coreEvents, CoreEventTypes } from "../events.mts"; import { crex_findReg } from "../register/registerLookup.mjs"; import { Memory } from "../memory/Memory.mts"; +/** Keyboard data override. Intended exclusively for running interactive tests */ +export const testKeyboard = { + enable: false, + /** @type {string[]} */ + data: [], +} + export function display_print(info) { if (typeof document !== "undefined" && document.app) { document.app.$data.display += info; @@ -42,7 +49,8 @@ export function display_print(info) { if (typeof info !== "string") { info = info.toString(); } - process.stdout.write(info); + if (!testKeyboard.enable) // Don't print in tests + process.stdout.write(info); } status.display += info; @@ -54,11 +62,11 @@ export function kbd_read_char(keystroke, params) { sailexec._send_char_to_C(value); document.app.$data.execution_mode_run = document.app.$data.last_execution_mode_run; - document.app.$data.last_execution_mode_run = -1; + document.app.$data.last_execution_mode_run = -1; } writeRegister(BigInt(value), params.indexComp, params.indexElem); - return value; + return keystroke[0] || ""; } export function kbd_read_int(keystroke, params) { @@ -84,7 +92,7 @@ export function kbd_read_int(keystroke, params) { sailexec._send_int_to_C(value); document.app.$data.execution_mode_run = document.app.$data.last_execution_mode_run; - document.app.$data.last_execution_mode_run = -1; + document.app.$data.last_execution_mode_run = -1; } value = BigInt(value); @@ -109,14 +117,21 @@ export function kbd_read_float(keystroke, params) { document.app.$data.execution_mode_run = document.app.$data.last_execution_mode_run; - document.app.$data.last_execution_mode_run = -1; + document.app.$data.last_execution_mode_run = -1; } - const buffer = new ArrayBuffer(4); - const view = new DataView(buffer); - view.setFloat32(0,value, false); - const bits = view.getUint32(0, false); - writeRegister(BigInt(("0x" + bits.toString(16).padStart(8, "0"))), params.indexComp, params.indexElem); + // If the current architecture has a write float specialization, use it. + // Otherwise, fallback to writing the bits directly + if (CAPI.ARCH.writeFloat !== undefined) { + const reg = architecture.components[params.indexComp].elements[params.indexElem] + CAPI.ARCH.writeFloat(value, reg.name[0]) + } else { + const buffer = new ArrayBuffer(4); + const view = new DataView(buffer); + view.setFloat32(0,value, false); + const bits = BigInt(view.getUint32(0, false)); + writeRegister(bits, params.indexComp, params.indexElem); + } return value; } @@ -125,7 +140,7 @@ export function kbd_read_double(keystroke, params) { const value = parseFloat(keystroke, 10); // validate input - if (typeof document.app !== "undefined" && isNaN(value)) { + if (typeof document !== "undefined" && document.app && isNaN(value)) { show_notification( `Invalid input: '${keystroke}' is not a double`, "danger", @@ -137,9 +152,20 @@ export function kbd_read_double(keystroke, params) { sailexec._send_double_to_C(value); document.app.$data.execution_mode_run = document.app.$data.last_execution_mode_run; - document.app.$data.last_execution_mode_run = -1; + document.app.$data.last_execution_mode_run = -1; + } + // If the current architecture has a write float specialization, use it. + // Otherwise, fallback to writing the bits directly + if (CAPI.ARCH.writeDouble !== undefined) { + const reg = architecture.components[params.indexComp].elements[params.indexElem] + CAPI.ARCH.writeDouble(value, reg.name[0]) + } else { + const buffer = new ArrayBuffer(8); + const view = new DataView(buffer); + view.setFloat64(0, value, false); + const bits = view.getBigUint64(0, false); + writeRegister(bits, params.indexComp, params.indexElem); } - writeRegister(value, params.indexComp, params.indexElem, "DFP-Reg"); return value; } @@ -149,8 +175,8 @@ export function kbd_read_string(keystroke, params) { const bytes = new TextEncoder().encode(keystroke); // Write the string to memory byte by byte - for (let i = 0n; i < keystroke.length && i < params.size; i++) { - main_memory.write(BigInt(addr + BigInt(i)), bytes[i]); + for (let i = 0n; i < bytes.length && i < params.size; i++) { + main_memory.write(addr + i, bytes[i]); } if (architecture.config.name.includes("SRV")) { @@ -170,7 +196,7 @@ export function kbd_read_string(keystroke, params) { } document.app.$data.execution_mode_run = document.app.$data.last_execution_mode_run; - document.app.$data.last_execution_mode_run = -1; + document.app.$data.last_execution_mode_run = -1; } return keystroke; } @@ -192,6 +218,10 @@ function checkEnter(buf) { * @returns {string} - The user input without extra space or newline */ function rawPrompt() { + if (testKeyboard.enable) { + const data = testKeyboard.data.shift() || "" + return data + } // Build input character by character until we hit Enter const chunks = []; const decoder = new TextDecoder(); @@ -247,7 +277,7 @@ export function keyboard_parseInt(fn_post_read, fn_post_params) { const addr = readRegister(ret1.indexComp, ret1.indexElem); // Get the memory instance const memory = main_memory; - + // Validate address is within memory bounds if (addr >= BigInt(memory.getSize())) { throw packExecute( @@ -278,10 +308,10 @@ export function keyboard_parseInt(fn_post_read, fn_post_params) { var regex = new RegExp("^\\s*(-?\\d+)"); } - - // Deno / CLI mode + + // Deno / CLI mode if (typeof Deno !== "undefined") { let keystroke = rawPrompt(); var match = regex.exec(keystroke); @@ -385,7 +415,7 @@ export function keyboard_read(fn_post_read, fn_post_params) { if (typeof Deno !== "undefined") { const keystroke = rawPrompt(); const value = fn_post_read(keystroke, fn_post_params); - status.keyboard = status.keyboard + " " + value; + status.keyboard += " " + value; status.run_program = 0; // Reset run_program status return null; @@ -400,8 +430,6 @@ export function keyboard_read(fn_post_read, fn_post_params) { } const val = fn_post_read(document.app.$data.keyboard, fn_post_params); - // Important: Final line char (/=) couns also as a char in lenght - writeRegister(BigInt(val.length), fn_post_params.indexComp, fn_post_params.indexElem); document.app.$data.keyboard = ""; // clear input @@ -485,9 +513,9 @@ export function keyboard_read_until(fn_post_read, fn_post_params, fn_post_until) if (idx !== -1) { keystroke = keystroke.slice(0, idx); } - + } - // console.log("Extracted keystroke until 'until':", `"${keystroke}"`); + // console.log("Extracted keystroke until 'until':", `"${keystroke}"`); const value = fn_post_read(keystroke, fn_post_params); status.keyboard = status.keyboard + " " + value; status.run_program = 0; // Reset run_program status @@ -590,7 +618,7 @@ export function keyboard_read_find(fn_post_read, fn_post_params,fn_post_length,f const addr = readRegister(ret1.indexComp, ret1.indexElem); // Get the memory instance const memory = main_memory; - + // Validate address is within memory bounds if (addr >= BigInt(memory.getSize())) { throw packExecute( @@ -623,6 +651,9 @@ export function keyboard_read_find(fn_post_read, fn_post_params,fn_post_length,f ); } length = readRegister(ret2.indexComp, ret2.indexElem); + if (length <= 0) { + length = Infinity; // No length limit + } } @@ -659,26 +690,27 @@ export function keyboard_read_find(fn_post_read, fn_post_params,fn_post_length,f memoryAddr++; } - // console.log("Until string: ", until); + // console.log("Until string: ", until); } - // Deno / CLI mode + // Deno / CLI mode if (typeof Deno !== "undefined") { let keystroke = rawPrompt(); - if (until && typeof until === "string") { + if (until && typeof until === "string" && until !== "" ) { const idx = keystroke.indexOf(until); if (idx !== -1) { keystroke = keystroke.substring(0, idx); } } - - if (keystroke.includes(target) && keystroke.length <= (length || keystroke.length) && !keystroke.includes(until)) { + if (keystroke.includes(target) && keystroke.length <= length) { writeRegister(1n, ret1.indexComp, ret1.indexElem); } else { writeRegister(0n, ret1.indexComp, ret1.indexElem); } + + status.run_program = 0; return packExecute( false, @@ -706,7 +738,13 @@ export function keyboard_read_find(fn_post_read, fn_post_params,fn_post_length,f // Find logic // console.log("keystroke:", `"${keystroke}"`, keystroke.length); // console.log("until:", `"${until}"`, until.length); - if (keystroke.includes(target) && keystroke.length <= (length || keystroke.length) && !keystroke.includes(until)) { + if (until && typeof until === "string" && until !== "" ) { + const idx = keystroke.indexOf(until); + if (idx !== -1) { + keystroke = keystroke.substring(0, idx); + } + } + if (keystroke.includes(target) && keystroke.length <= length) { writeRegister(1n, ret1.indexComp, ret1.indexElem); } else { writeRegister(0n, ret1.indexComp, ret1.indexElem); diff --git a/src/core/executor/devices.mts b/src/core/executor/devices.mts index ec0d285d0..4c16fb46f 100644 --- a/src/core/executor/devices.mts +++ b/src/core/executor/devices.mts @@ -243,14 +243,17 @@ class ConsoleDevice extends Device { // read byte by byte until a null terminator is found const mainMemory = main_memory as Memory; - const buffer = []; + const bytes = []; for (let i = 0; i < mainMemory.getSize(); i++) { const byte = mainMemory.read(BigInt(addr + i)); if (byte === 0) break; // null terminator - buffer.push(String.fromCharCode(byte)); + bytes.push(byte); } - this.#write(buffer.join(""), DataType.String); + // Decode the UTF-8 data to a string + const buffer = new Uint8Array(bytes) + const msg = new TextDecoder().decode(buffer); + this.#write(msg, DataType.String); break; @@ -304,7 +307,7 @@ class ConsoleDevice extends Device { const bytes = new TextEncoder().encode(keystroke); // Write the string to memory byte by byte - for (let i = 0; i < keystroke.length && i < length; i++) { + for (let i = 0; i < bytes.length && i < length; i++) { mainMemory.write(BigInt(addr + i), bytes[i]!); } }); @@ -364,7 +367,7 @@ class OSDriver extends Device { const addr = MEM.alloc(size); // save addr - this.writeValue(this.data.start, addr); + this.writeValue(this.data.start, Number(addr)); break; } diff --git a/src/core/executor/executor.mjs b/src/core/executor/executor.mjs index 987fbabeb..577ca2f90 100644 --- a/src/core/executor/executor.mjs +++ b/src/core/executor/executor.mjs @@ -367,16 +367,6 @@ function executeInstructionCycle() { logger.debug("Execution Index:" + status.execution_index); logger.debug("PC Register: " + getPC()); - // Special check for stack visualization purposes - if ( - status.execution_index === - instructions.findIndex( - i => parseInt(i.Address, 16) === get_entrypoint(), - ) - ) { - stackTracker.newFrame(tag_instructions[getPC()]?.tag || ""); - } - // Check for conditions that would stop execution const inLoopCheckResult = performExecutionChecks(); if (inLoopCheckResult !== null) { @@ -478,44 +468,20 @@ export function writeStackLimit(stackLimit) { // Get memory segments from the Memory object const segments = main_memory.getMemorySegments(); - // // Check if stack pointer would be placed in data segment - // if ( - // dataSegment && - // stackLimitBigInt <= dataSegment.end && - // stackLimitBigInt >= dataSegment.start - // ) { - // draw.danger.push(status.execution_index); - // throw packExecute( - // true, - // "Stack pointer cannot be placed in the data segment", - // "danger", - // null, - // ); - // } - - // // Check if stack pointer would be placed in text segment - // if ( - // textSegment && - // stackLimitBigInt <= textSegment.end && - // stackLimitBigInt >= textSegment.start - // ) { - // draw.danger.push(status.execution_index); - // throw packExecute( - // true, - // "Stack pointer cannot be placed in the text segment", - // "danger", - // null, - // ); - // } - // Get current stack pointer from memory segments const stackSegment = segments.get("stack"); - - // Check if stack pointer would be placed in stack segment + // Check if stack pointer would be above stack end if (stackSegment && stackLimitBigInt > stackSegment.end) { throw new Error("Stack pointer cannot be outside the stack segment"); } + // Check if stack pointer would be placed in text/data segments + for (const [name, value] of segments) { + if (name === "stack") continue; + if (value.start <= stackLimitBigInt && stackLimitBigInt <= value.end) + throw new Error(`Stack pointer cannot be placed in the ${name} segment`); + } + stackTracker.updateCurrentFrame(stackLimit); // Update the stack segment in the memory layout if it exists diff --git a/src/core/executor/sailSimRV/sailExecutor.mjs b/src/core/executor/sailSimRV/sailExecutor.mjs index ed6208cc5..2720d63ee 100644 --- a/src/core/executor/sailSimRV/sailExecutor.mjs +++ b/src/core/executor/sailSimRV/sailExecutor.mjs @@ -3,7 +3,150 @@ import sail32sim from "./wasm/riscv_sim_RV32.js" import sail64sim from "./wasm/riscv_sim_RV64.js" import sail32vdsim from "./wasm/riscv_sim_RV32vd.js" import { vectoren, doubleen } from "../../assembler/sailAssembler/web/CNAssambler.mjs"; +import { coreEvents } from "../../events.mts"; + export var sailexec; +var programs = []; + +async function cargarProgramas32(jsonPath) { + + const response = await fetch(jsonPath); + const lista = await response.json(); + + const programas = await Promise.all( + lista.map(async entry => { + + const binResponse = await fetch(entry.url); + const buffer = await binResponse.arrayBuffer(); + + const programa = { + name: entry.name, + binary: new Uint8Array(buffer) + }; + + if ("doubleen" in entry) programa.doubleen = entry.doubleen; + if ("vectoren" in entry) programa.vectoren = entry.vectoren; + + return programa; + }) + ); + + return programas; +} + +async function cargarProgramas64(jsonPath){ + + const response = await fetch(jsonPath); + const lista = await response.json(); + + const programas = await Promise.all( + lista.map(async entry => { + + const binResponse = await fetch(entry.url); + const buffer = await binResponse.arrayBuffer(); + + const programa = { + name: entry.name, + binary: new Uint8Array(buffer) + }; + + return programa; + }) + ); + + return programas; +} + +export async function SailTest32(){ + // Reset de las variables test + document.app.$data.passed_test = 0; + document.app.$data.failed_test = 0; + document.app.$data.testing = true; + document.app.$data.c_kernel = false; + if (programs.length === 0) + programs = await cargarProgramas32("examples/RISCV-32-Sail-Validation/list.json"); + + for (let index = 0; index < programs.length; index++) { + + document.app.$data.execution_mode_run = -1; + const element = programs[index]; + let depsLeft = Infinity; + if (element.vectoren && element.doubleen) { + sailexec = await sail32vdsim({ + noInitialRun: true, + // print: (t) => console.log('[sim32]', t), + // printErr: (t) => console.warn('[sim32:err]', t), + // onAbort: (t) => console.error("[sim32:abort]", t), + monitorRunDependencies(left) { + depsLeft = left; + console.log("[sim32] deps pending:", left); + }, + }); + } else { + sailexec = await sail32sim({ + noInitialRun: true, + // print: (t) => console.log('[sim32]', t), + // printErr: (t) => console.warn('[sim32:err]', t), + // onAbort: (t) => console.error("[sim32:abort]", t), + monitorRunDependencies(left) { + depsLeft = left; + console.log("[sim32] deps pending:", left); + }, + }); + } + + await new Promise((resolve) => { + const check = () => { + if (depsLeft === 0) resolve(); + else setTimeout(check, 100); + }; + check(); + }); + document.app.$data.execution_mode_run = 0; + sailexec.run([element.binary, "--entry-address", "0x80000000", "--cache-pol", "1", "-p", "output.elf"]); + coreEvents.emit("update-validation"); + + + } + + document.app.$data.testing = false; + +} +export async function SailTest64(){ + var filed_tests = []; + document.app.$data.passed_test = 0; + document.app.$data.failed_test = 0; + document.app.$data.testing = true; + document.app.$data.c_kernel = false; + if (programs.length === 0) + programs = await cargarProgramas64("examples/RISCV-64-Sail-Validation/list.json"); + + for (let index = 0; index < programs.length; index++) { + + document.app.$data.execution_mode_run = -1; + const element = programs[index]; + let depsLeft = Infinity; + sailexec = await sail64sim({ + noInitialRun: true, + monitorRunDependencies(left) { + depsLeft = left; + console.log("[sim64] deps pending:", left); + }, + }); + await new Promise((resolve) => { + const check = () => { + if (depsLeft === 0) resolve(); + else setTimeout(check, 100); + }; + check(); + }); + document.app.$data.execution_mode_run = 0; + sailexec.run([element.binary, "--entry-address", "0x80000000", "--cache-pol", "1", "-p", "output.elf"]); + coreEvents.emit("update-validation"); + } + + document.app.$data.testing = false; +} export async function SailExecute(binary, flags){ let depsLeft = Infinity; if (architecture.config.name === "SRV32") { @@ -64,7 +207,6 @@ export async function SailExecute(binary, flags){ // Once it is initialized, lets run the program // document.app.$data.execution_mode_run = 0; - console.log(flags); sailexec.run([binary, ...flags]); diff --git a/src/core/executor/sailSimRV/wasm/riscv_sim_RV32.js b/src/core/executor/sailSimRV/wasm/riscv_sim_RV32.js index 47887970b..d801f29b1 100644 --- a/src/core/executor/sailSimRV/wasm/riscv_sim_RV32.js +++ b/src/core/executor/sailSimRV/wasm/riscv_sim_RV32.js @@ -16,7 +16,7 @@ var Module = (() => { var insn_number; return function (Module) { - document.app.$data.is_breakpoint = instructions[0].Break; + document.app.$data.is_breakpoint = (instructions.length !== 0) ? instructions[0].Break : false; var pc_sail = crex_findReg_bytag("program_counter"); var pc_min = architecture.memory_layout.text.start; var pc_max = architecture.memory_layout.text.end; @@ -1194,8 +1194,7 @@ var Module = (() => { console.warn(message); } - var out = Module["print"] /*|| console.log.bind(console)*/; - // var out = console.log.bind(console); + var out = (document.app.$data.testing === true ) ? console.log.bind(console) : Module["print"]; var err = Module["printErr"] /*|| console.warn.bind(console)*/; Object.assign(Module, moduleOverrides); @@ -7824,27 +7823,33 @@ var Module = (() => { } if (keepRuntimeAlive()) { if (!implicit) { - - for (let i = 0; i < instructions.length; i++){ - instructions[i]._rowVariant = ''; - } - status.run_program = -1; // program finished - if (statusw !== 0){ - coreEvents.emit("executor-buttons-update", { - reset_disable: false, - instruction_disable: true, - run_disable: true, - stop_disable: false, - }); - show_notification("Your program has finished with errors.", "danger"); + if (!document.app.$data.testing) { + for (let i = 0; i < instructions.length; i++){ + instructions[i]._rowVariant = ''; + } + status.run_program = -1; // program finished + if (statusw !== 0){ + coreEvents.emit("executor-buttons-update", { + reset_disable: false, + instruction_disable: true, + run_disable: true, + stop_disable: false, + }); + show_notification("Your program has finished with errors.", "danger"); + } else { + coreEvents.emit("executor-buttons-update", { + reset_disable: false, + instruction_disable: false, + run_disable: false, + stop_disable: true, + isFinished: true, + }); + } } else { - coreEvents.emit("executor-buttons-update", { - reset_disable: false, - instruction_disable: false, - run_disable: false, - stop_disable: true, - isFinished: true, - }); + if (statusw === 0) + document.app.$data.passed_test += 1; + else + document.app.$data.failed_test += 1; } var msg = "program exited (with status: " + diff --git a/src/core/executor/sailSimRV/wasm/riscv_sim_RV32.wasm b/src/core/executor/sailSimRV/wasm/riscv_sim_RV32.wasm index 23c080166..8be9b78e0 100755 Binary files a/src/core/executor/sailSimRV/wasm/riscv_sim_RV32.wasm and b/src/core/executor/sailSimRV/wasm/riscv_sim_RV32.wasm differ diff --git a/src/core/executor/sailSimRV/wasm/riscv_sim_RV32vd.js b/src/core/executor/sailSimRV/wasm/riscv_sim_RV32vd.js index b119bc7b5..650cf91e2 100644 --- a/src/core/executor/sailSimRV/wasm/riscv_sim_RV32vd.js +++ b/src/core/executor/sailSimRV/wasm/riscv_sim_RV32vd.js @@ -16,7 +16,8 @@ var Module = (() => { var _scriptName = import.meta.url; var insn_number; - return async function (moduleArg = {}) {document.app.$data.is_breakpoint = instructions[0].Break; + return async function (moduleArg = {}) { + document.app.$data.is_breakpoint = (instructions.length !== 0) ? instructions[0].Break : false; var pc_sail = crex_findReg_bytag("program_counter"); var pc_min = architecture.memory_layout.text.start; var pc_max = architecture.memory_layout.text.end; @@ -957,8 +958,7 @@ var Module = (() => { console.warn(message); } - var out = Module["print"] /*|| console.log.bind(console)*/; - // var out = console.log.bind(console); + var out = (document.app.$data.testing === true ) ? console.log.bind(console) : Module["print"]; var err = Module["printErr"] /*|| console.warn.bind(console)*/; @@ -4290,26 +4290,33 @@ var Module = (() => { EXITSTATUS = statusw; checkUnflushedContent(); if (keepRuntimeAlive() && !implicit) { - for (let i = 0; i < instructions.length; i++){ - instructions[i]._rowVariant = ''; - } - status.run_program = -1; // program finished - if (statusw !== 0){ - coreEvents.emit("executor-buttons-update", { - reset_disable: false, - instruction_disable: true, - run_disable: true, - stop_disable: false, - }); - show_notification("Your program has finished with errors.", "danger"); + if (!document.app.$data.testing){ + for (let i = 0; i < instructions.length; i++){ + instructions[i]._rowVariant = ''; + } + status.run_program = -1; // program finished + if (statusw !== 0){ + coreEvents.emit("executor-buttons-update", { + reset_disable: false, + instruction_disable: true, + run_disable: true, + stop_disable: false, + }); + show_notification("Your program has finished with errors.", "danger"); + } else { + coreEvents.emit("executor-buttons-update", { + reset_disable: false, + instruction_disable: false, + run_disable: false, + stop_disable: true, + isFinished: true, + }); + } } else { - coreEvents.emit("executor-buttons-update", { - reset_disable: false, - instruction_disable: false, - run_disable: false, - stop_disable: true, - isFinished: true, - }); + if (statusw === 0) + document.app.$data.passed_test += 1; + else + document.app.$data.failed_test += 1; } var msg = `program exited (with status: ${statusw}), but keepRuntimeAlive() is set (counter=${runtimeKeepaliveCounter}) due to an async operation, so halting execution but not exiting the runtime or preventing further async execution (you can use emscripten_force_exit, if you want to force a true shutdown)`; readyPromiseReject(msg); diff --git a/src/core/executor/sailSimRV/wasm/riscv_sim_RV32vd.wasm b/src/core/executor/sailSimRV/wasm/riscv_sim_RV32vd.wasm index b9574ecfd..ae74c3de3 100755 Binary files a/src/core/executor/sailSimRV/wasm/riscv_sim_RV32vd.wasm and b/src/core/executor/sailSimRV/wasm/riscv_sim_RV32vd.wasm differ diff --git a/src/core/executor/sailSimRV/wasm/riscv_sim_RV64.js b/src/core/executor/sailSimRV/wasm/riscv_sim_RV64.js index 1ceffd49f..1ba5bacf6 100644 --- a/src/core/executor/sailSimRV/wasm/riscv_sim_RV64.js +++ b/src/core/executor/sailSimRV/wasm/riscv_sim_RV64.js @@ -16,7 +16,7 @@ var Module = (() => { var insn_number; return async function (moduleArg = {}) { - document.app.$data.is_breakpoint = instructions[0].Break; + document.app.$data.is_breakpoint = (instructions.length !== 0) ? instructions[0].Break : false; var pc_sail = crex_findReg_bytag("program_counter"); var pc_min = architecture.memory_layout.text.start; var pc_max = architecture.memory_layout.text.end; @@ -1009,7 +1009,7 @@ var Module = (() => { } - var out = Module["print"] /*|| console.log.bind(console)*/; + var out = (document.app.$data.testing === true ) ? console.log.bind(console) : Module["print"]; var err = Module["printErr"] /*|| console.error.bind(console)*/; @@ -4341,27 +4341,33 @@ var Module = (() => { EXITSTATUS = statusw; checkUnflushedContent(); if (keepRuntimeAlive() && !implicit) { - - for (let i = 0; i < instructions.length; i++){ - instructions[i]._rowVariant = ''; - } - status.run_program = -1; // program finished - if (statusw !== 0){ - coreEvents.emit("executor-buttons-update", { - reset_disable: false, - instruction_disable: true, - run_disable: true, - stop_disable: false, - }); - show_notification("Your program has finished with errors.", "danger"); + if (!document.app.$data.testing) { + for (let i = 0; i < instructions.length; i++){ + instructions[i]._rowVariant = ''; + } + status.run_program = -1; // program finished + if (statusw !== 0){ + coreEvents.emit("executor-buttons-update", { + reset_disable: false, + instruction_disable: true, + run_disable: true, + stop_disable: false, + }); + show_notification("Your program has finished with errors.", "danger"); + } else { + coreEvents.emit("executor-buttons-update", { + reset_disable: false, + instruction_disable: false, + run_disable: false, + stop_disable: true, + isFinished: true, + }); + } } else { - coreEvents.emit("executor-buttons-update", { - reset_disable: false, - instruction_disable: false, - run_disable: false, - stop_disable: true, - isFinished: true, - }); + if (statusw === 0) + document.app.$data.passed_test += 1; + else + document.app.$data.failed_test += 1; } var msg = `program exited (with status: ${statusw}), but keepRuntimeAlive() is set (counter=${runtimeKeepaliveCounter}) due to an async operation, so halting execution but not exiting the runtime or preventing further async execution (you can use emscripten_force_exit, if you want to force a true shutdown)`; readyPromiseReject(msg); diff --git a/src/core/executor/sailSimRV/wasm/riscv_sim_RV64.wasm b/src/core/executor/sailSimRV/wasm/riscv_sim_RV64.wasm index eea7771a3..4b9eb37bc 100755 Binary files a/src/core/executor/sailSimRV/wasm/riscv_sim_RV64.wasm and b/src/core/executor/sailSimRV/wasm/riscv_sim_RV64.wasm differ diff --git a/src/core/memory/Memory.mts b/src/core/memory/Memory.mts index d690075cc..45c68e151 100644 --- a/src/core/memory/Memory.mts +++ b/src/core/memory/Memory.mts @@ -136,8 +136,8 @@ * Interface for processed memory segment information */ interface MemorySegment { - start: bigint; // Parsed start address - end: bigint; // Parsed end address + start: number; // Parsed start address + end: number; // Parsed end address size: bigint; } @@ -168,7 +168,7 @@ export interface MemoryBackup { values: number[]; bitsPerByte: number; size: number; - hints?: { + hints: { address: string; tag: string[]; type: string; @@ -261,12 +261,11 @@ export class Memory { * * @example Memory with layout segments * ```typescript - * const layout = [ - * { name: "text start", value: "0x0000" }, - * { name: "text end", value: "0x1000" }, - * { name: "data start", value: "0x1010" }, - * { name: "data end", value: "0x2000" } - * ]; + * const layout = new Map([ + * [ "text", { start: 0x0000, end: 0x1000 } ], + * [ "data", { start: 0x1010, end: 0x2000 } ], + * [ "stack", { start: 0xFFFF, end: 0xFFFF } ], + * ]); * const memory = new Memory({ * sizeInBytes: 0x10000, * memoryLayout: layout, @@ -340,7 +339,7 @@ export class Memory { } // Initialize memory layout and segments - this.memoryLayout = memoryLayout; + this.memoryLayout = new Map(memoryLayout); this.segmentCache = new Map(); // Initialize hints system @@ -368,6 +367,30 @@ export class Memory { this.uint8View.fill(0); } + /** + * Gets the index of the address within the memory + * + * @param address - Memory address to use + * @returns Index of the address within the memory + * @throws Error if the address is outside of the range of the memory + */ + getIndex(address: bigint): number { + if (address < this.baseAddress) { + throw new Error( + `Address ${address} is below base address ${this.baseAddress}`, + ); + } + + const addrIndex = Number(address - this.baseAddress); + if (addrIndex >= this.size) { + throw new Error( + `Address ${addrIndex} exceeds memory size ${this.size} (+${this.baseAddress})`, + ); + } + + return addrIndex; + } + /** * Reads a single byte from memory at the specified address. * @@ -395,19 +418,7 @@ export class Memory { * ``` */ read(address: bigint): number { - // check address - if (address < this.baseAddress) { - throw new Error( - `Address ${address} is below base address ${this.baseAddress}`, - ); - } - - const addrIndex = Number(address - this.baseAddress); - if (addrIndex >= this.size) { - throw new Error( - `Address ${addrIndex} exceeds memory size ${this.size} (+${this.baseAddress})`, - ); - } + const addrIndex = this.getIndex(address); if (this.bitsPerByte === 8) { return this.uint8View[addrIndex]!; @@ -480,19 +491,8 @@ export class Memory { * ``` */ write(address: bigint, value: number): void { - // check address - if (address < this.baseAddress) { - throw new Error( - `Address ${address} is below base address ${this.baseAddress}`, - ); - } + const addrIndex = this.getIndex(address); - const addrIndex = Number(address - this.baseAddress); - if (addrIndex >= this.size) { - throw new Error( - `Address ${address} exceeds memory size ${this.size} (+${this.baseAddress})`, - ); - } if (value > this.maxByteValue || value < 0) { throw new Error( `Value ${value} exceeds byte size (max: ${this.maxByteValue})`, @@ -548,6 +548,34 @@ export class Memory { } } + + /** + * Extends a memory segment by N bytes from the end + * + * @param bytes - Amount of bytes to extend the segment by + * @param segmentName - Name of the segment to extend + * @returns Starting address of the allocation + * + * @throws Error if the segment name doesn't exist on the layout + */ + alloc(bytes: number, segmentName: string): bigint { + const segment = this.memoryLayout.get(segmentName); + if (!segment) + throw new Error(`Segment "${segmentName}" doesn't exist`); + const addr = BigInt(segment.end) + 1n; + const end = BigInt(segment.end) + BigInt(bytes); + const idx = Number(end - this.baseAddress); + if (idx >= this.size) { + // Address is outside of the memory, we need to grow the buffer + this.size = idx + 1; + this.buffer = this.buffer.transfer(this.size); + this.uint8View = new Uint8Array(this.buffer); + } + // Update the segment data + segment.end = Number(end); + return addr; + } + /** * Loads ROM data into memory starting at the specified offset. * This method only works with 8-bit byte memories for direct compatibility @@ -621,33 +649,36 @@ export class Memory { readBytes(address: bigint, count: number): number[] { const result: number[] = []; for (let i = 0; i < count; i++) { - result.push(this.read(BigInt(address) + BigInt(i))); + result.push(this.read(address + BigInt(i))); } return result; } /** - * Returns the addresses that have been written + * Returns an array of all addresses that have been written to. + * + * @returns Array of written addresses (number), sorted in ascending order. + * + * @example + * ```typescript + * const memory = new Memory({ sizeInBytes: 100 }); + * memory.write(5n, 123); + * memory.write(10n, 255); + * const written = memory.getWrittenAddresses(); // [5, 10] + * ``` */ - getWritten(): Array<{ addr: number; value: number }> { - return ( - Array.from(this.writtenAddresses) - // Sort addresses to ensure consistent output - .sort((a, b) => a - b) - .map((addr, _i, _arr) => ({ - addr, - value: this.read(BigInt(addr)), - })) - ); + getWrittenAddresses(): number[] { + // Sort addresses to ensure consistent output + return Array.from(this.writtenAddresses).sort((a, b) => a - b); } /** - * Returns all memory addresses and values. + * Returns the addresses that have been written to, along with their value */ - getAll(): Array<{ addr: number; value: number }> { - return Array.from(this.uint8View).map((value, i) => ({ - addr: Number(this.baseAddress) + i, - value, + getWritten(): Array<{ addr: number; value: number }> { + return this.getWrittenAddresses().map(addr => ({ + addr, + value: this.read(BigInt(addr)), })); } @@ -663,7 +694,7 @@ export class Memory { * const memory = new Memory({ sizeInBytes: 1000000 }); * memory.write(100n, 123); * memory.write(50000n, 456); - * memory.addHint(100n, "int32", 32); + * memory.addHint(100n, [], "int32", 32); * * const snapshot = memory.dump(); // Only contains 2 entries, not 1M, plus hints * memory.restore(snapshot); @@ -674,9 +705,7 @@ export class Memory { const values: number[] = []; // Sort addresses to ensure consistent output - const sortedAddresses = Array.from(this.writtenAddresses).sort( - (a, b) => a - b, - ); + const sortedAddresses = this.getWrittenAddresses(); for (const addr of sortedAddresses) { addresses.push(addr); @@ -720,14 +749,14 @@ export class Memory { * @example Restoring memory state * ```typescript * const memory = new Memory({ sizeInBytes: 100000, bitsPerByte: 8 }); - * memory.addHint(0x100n, "int32", 32); + * memory.addHint(0x100n, [], "int32", 32); * const snapshot = memory.dump(); * // ... modify memory ... * memory.restore(snapshot); // Back to original state with hints * ``` */ restore(dump: MemoryBackup): void { - if (dump.bitsPerByte !== this.bitsPerByte || dump.size !== this.size) { + if (dump.bitsPerByte !== this.bitsPerByte || dump.size > this.size) { throw new Error( "Dump metadata does not match current memory configuration", ); @@ -752,17 +781,15 @@ export class Memory { } } - // Restore hints if they exist in the dump + // Restore hints this.hints.clear(); - if (dump.hints) { - for (const hint of dump.hints) { - this.hints.set(BigInt(hint.address), { - address: BigInt(hint.address), - tag: hint.tag, - type: hint.type, - sizeInBits: hint.sizeInBits, - }); - } + for (const hint of dump.hints) { + this.hints.set(BigInt(hint.address), { + address: BigInt(hint.address), + tag: hint.tag, + type: hint.type, + sizeInBits: hint.sizeInBits, + }); } } @@ -910,12 +937,7 @@ export class Memory { } // Sort addresses from highest to lowest - usedAddresses.sort((a, b) => { - if (a > b) return -1; - if (a < b) return 1; - return 0; - }); - + usedAddresses.sort((a, b) => Number(b - a)); return usedAddresses; } @@ -953,20 +975,6 @@ export class Memory { throw new Error(`Value must be a bigint, got ${typeof value}`); } - // Special case for 8-bit bytes - use standard approach - if (this.bitsPerByte === 8) { - const bytes: number[] = []; - let remainingValue = value; - - while (remainingValue > 0n) { - bytes.unshift(Number(remainingValue & 0xffn)); - remainingValue >>= 8n; - } - - return bytes.length === 0 ? [0] : bytes; - } - - // For custom byte sizes const bytes: number[] = []; let remainingValue = value; const maxByteValueBigInt = BigInt(this.maxByteValue); @@ -1012,18 +1020,7 @@ export class Memory { */ readWord(address: bigint): number[] { // check address - if (address < this.baseAddress) { - throw new Error( - `Address ${address} is below base address ${this.baseAddress}`, - ); - } - - const addrIndex = Number(address - this.baseAddress); - if (addrIndex >= this.size) { - throw new Error( - `Address ${addrIndex} exceeds memory size ${this.size} (+${this.baseAddress})`, - ); - } + this.getIndex(address); const bytes: number[] = []; for (let i = 0n; i < this.wordSize; i++) { @@ -1083,18 +1080,7 @@ export class Memory { */ writeWord(address: bigint, word: number[]): void { // check address - if (address < this.baseAddress) { - throw new Error( - `Address ${address} is below base address ${this.baseAddress}`, - ); - } - - const addrIndex = Number(address - this.baseAddress); - if (addrIndex >= this.size) { - throw new Error( - `Address ${addrIndex} exceeds memory size ${this.size} (+${this.baseAddress})`, - ); - } + this.getIndex(address); if (word.length !== this.wordSize) { throw new Error( @@ -1332,23 +1318,22 @@ export class Memory { * @example Adding hints * ```typescript * const memory = new Memory({ sizeInBytes: 1024 }); - * memory.addHint(0x100n, "", "double", 64); // No tag, just type - * memory.addHint(0x200n, "myVar", "int32", 32); - * memory.addHint(0x300n, "myString", "string"); // No size specified + * memory.addHint(0x100n, [], "double", 64); // No tag, just type + * memory.addHint(0x200n, ["myVar"], "int32", 32); + * memory.addHint(0x300n, ["myString"], "string"); // No size specified + * memory.addHint(0x400n, ["foo", "bar"], "int32", 32); // Multiple tags * ``` */ addHint( address: bigint, - tag: string|string[], + tag: string | string[], type: string, sizeInBits?: number, ): void { // If no tag is provided and a hint exists, preserve the existing tag let finalTag; - if (typeof tag === "string") - finalTag = tag === ""? [] : [tag] - else - finalTag = tag; + if (typeof tag === "string") finalTag = tag === "" ? [] : [tag]; + else finalTag = tag; const existing = this.hints.get(address); if (tag.length === 0 && existing) { finalTag = existing.tag; @@ -1370,7 +1355,7 @@ export class Memory { * @example Removing hints * ```typescript * const memory = new Memory({ sizeInBytes: 1024 }); - * memory.addHint(0x100n, "double", 64); + * memory.addHint(0x100n, [], "double", 64); * const removed = memory.removeHint(0x100n); // true * const notFound = memory.removeHint(0x200n); // false * ``` @@ -1388,7 +1373,7 @@ export class Memory { * @example Getting hints * ```typescript * const memory = new Memory({ sizeInBytes: 1024 }); - * memory.addHint(0x100n, "double", 64); + * memory.addHint(0x100n, [], "double", 64); * * const hint = memory.getHint(0x100n); * if (hint) { @@ -1411,8 +1396,8 @@ export class Memory { * @example Getting all hints * ```typescript * const memory = new Memory({ sizeInBytes: 1024 }); - * memory.addHint(0x200n, "int32", 32); - * memory.addHint(0x100n, "double", 64); + * memory.addHint(0x200n, [], "int32", 32); + * memory.addHint(0x100n, [], "double", 64); * * const hints = memory.getAllHints(); * for (const hint of hints) { @@ -1425,11 +1410,7 @@ export class Memory { */ getAllHints(): MemoryHint[] { const hints = Array.from(this.hints.values()); - hints.sort((a, b) => { - if (a.address < b.address) return -1; - if (a.address > b.address) return 1; - return 0; - }); + hints.sort((a, b) => Number(a.address - b.address)); return hints; } @@ -1439,8 +1420,8 @@ export class Memory { * @example Clearing hints * ```typescript * const memory = new Memory({ sizeInBytes: 1024 }); - * memory.addHint(0x100n, "double", 64); - * memory.addHint(0x200n, "int32", 32); + * memory.addHint(0x100n, [], "double", 64); + * memory.addHint(0x200n, [], "int32", 32); * * console.log(memory.getAllHints().length); // 2 * memory.clearHints(); @@ -1451,23 +1432,6 @@ export class Memory { this.hints.clear(); } - /** - * Returns an array of all addresses that have been written to. - * - * @returns Array of written addresses (number), sorted in ascending order. - * - * @example - * ```typescript - * const memory = new Memory({ sizeInBytes: 100 }); - * memory.write(5n, 123); - * memory.write(10n, 255); - * const written = memory.getWrittenAddresses(); // [5, 10] - * ``` - */ - getWrittenAddresses(): number[] { - return Array.from(this.writtenAddresses).sort((a, b) => a - b); - } - /** * Gets hints within a specified address range. * @@ -1478,9 +1442,9 @@ export class Memory { * @example Getting hints in range * ```typescript * const memory = new Memory({ sizeInBytes: 1024 }); - * memory.addHint(0x100n, "double", 64); - * memory.addHint(0x200n, "int32", 32); - * memory.addHint(0x300n, "string"); + * memory.addHint(0x100n, [], "double", 64); + * memory.addHint(0x200n, [], "int32", 32); + * memory.addHint(0x300n, [], "string"); * * const hintsInRange = memory.getHintsInRange(0x150n, 0x250n); * console.log(hintsInRange.length); // 1 (only the int32 at 0x200) @@ -1493,11 +1457,7 @@ export class Memory { hintsInRange.push(hint); } } - hintsInRange.sort((a, b) => { - if (a.address < b.address) return -1; - if (a.address > b.address) return 1; - return 0; - }); + hintsInRange.sort((a, b) => Number(a.address - b.address)); return hintsInRange; } } diff --git a/src/core/memory/StackTracker.mts b/src/core/memory/StackTracker.mts index cc462fa56..1843f23c3 100644 --- a/src/core/memory/StackTracker.mts +++ b/src/core/memory/StackTracker.mts @@ -17,7 +17,7 @@ * along with CREATOR. If not, see . */ -import { REGISTERS } from "../core.mjs"; +import { architecture, REGISTERS } from "../core.mjs"; /** * Represents a stack frame, with a begin and end address @@ -71,6 +71,7 @@ export class StackTracker { public reset() { this.frames.length = 0; this.hints.clear(); + this.newFrame(architecture.config.main_function); } /** diff --git a/src/core/register/registerOperations.mjs b/src/core/register/registerOperations.mjs index f402fbe25..be6d578b9 100644 --- a/src/core/register/registerOperations.mjs +++ b/src/core/register/registerOperations.mjs @@ -20,7 +20,7 @@ import { architecture, status, REGISTERS } from "../core.mjs"; import { writeStackLimit } from "../executor/executor.mjs"; import { instructions } from "../assembler/assembler.mjs"; -import { sentinel } from "../sentinel/sentinel.mjs"; +import { sentinel } from "../sentinel/sentinel.mts"; import { packExecute } from "../utils/utils.mjs"; import { coreEvents } from "../events.mts"; import { setRegisterGlow } from "./registerGlowState.mjs"; @@ -119,12 +119,7 @@ export function writeRegister(value, indexComp, indexElem) { } draw.danger.push(status.execution_index); - throw packExecute( - true, - "The register " + elementName + " is not writeable", - "danger", - null, - ); + throw new Error(`The register ${elementName} is not writeable`); } element.value = value; diff --git a/src/core/sentinel/sentinel.mjs b/src/core/sentinel/sentinel.mjs deleted file mode 100644 index 52eadac62..000000000 --- a/src/core/sentinel/sentinel.mjs +++ /dev/null @@ -1,499 +0,0 @@ -/** - * Copyright 2018-2026 CREATOR Team. - * - * This file is part of CREATOR. - * - * CREATOR is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CREATOR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with CREATOR. If not, see . - */ - -import { architecture, REGISTERS } from "../core.mjs"; -import { console_log } from "../utils/creator_logger.mjs"; - -/** - * Event types that can occur during function execution - */ -const EventType = { - WRITE_MEMORY: "write_memory", - READ_MEMORY: "read_memory", - WRITE_REGISTER: "write_register", - READ_REGISTER: "read_register", -}; - -// Helpers for safe BigInt conversions and comparisons -function toBigIntSafe(v) { - if (v === null || typeof v === "undefined") return null; - if (typeof v === "bigint") return v; - if (typeof v === "number") { - if (!Number.isInteger(v)) return null; - return BigInt(v); - } - // strings and other types that BigInt accepts - try { - return BigInt(v); - } catch (_e) { - return null; - } -} - -function bigintsEqual(a, b) { - const A = toBigIntSafe(a); - const B = toBigIntSafe(b); - if (A === null || B === null) return false; - return A === B; -} - -function valuesEqual(a, b) { - // Handle null/undefined - if (a === null || a === undefined || b === null || b === undefined) { - return a === b; - } - - // Try BigInt comparison first - const A = toBigIntSafe(a); - const B = toBigIntSafe(b); - if (A !== null && B !== null) { - return A === B; - } - - // Fallback to strict equality - return a === b; -} - -/** - * Represents a single event in the register lifecycle - */ -class RegisterEvent { - constructor(type, regIndex, elemIndex, address = null, size = null) { - this.type = type; - this.regIndex = regIndex; - this.elemIndex = elemIndex; - // Normalize address/size to BigInt when possible to avoid mixed-type comparisons - this.address = toBigIntSafe(address); - this.size = toBigIntSafe(size); - this.timestamp = Date.now(); - } - - get registerName() { - return ( - REGISTERS[this.regIndex]?.elements[this.elemIndex]?.name || - "unknown" - ); - } - - toString() { - const addr = - this.address !== null ? ` @0x${this.address.toString(16)}` : ""; - const size = this.size !== null ? ` (${this.size} bytes)` : ""; - return `${this.type}: ${this.registerName}${addr}${size}`; - } -} - -/** - * Represents a function call frame with register state tracking - */ -class CallFrame { - constructor(functionName, stackPointer) { - this.functionName = functionName; - this.enterStackPointer = stackPointer; - this.events = []; - this.initialRegisterValues = CallFrame._captureRegisterValues(); - } - - static _captureRegisterValues() { - const values = []; - for (let i = 0; i < REGISTERS.length; i++) { - values.push([]); - for (let j = 0; j < REGISTERS[i].elements.length; j++) { - values[i].push(REGISTERS[i].elements[j].value); - } - } - return values; - } - - addEvent(event) { - this.events.push(event); - console_log( - `[EVENT] ${this.functionName}: ${event.toString()}`, - "INFO", - ); - } - - /** - * Get all events for a specific register - */ - getRegisterEvents(regIndex, elemIndex) { - return this.events.filter( - e => e.regIndex === regIndex && e.elemIndex === elemIndex, - ); - } - - /** - * Find the first save event for a register - */ - getFirstSave(regIndex, elemIndex) { - return this.events.find( - e => - e.regIndex === regIndex && - e.elemIndex === elemIndex && - e.type === EventType.WRITE_MEMORY, - ); - } - - /** - * Find the last restore event for a register - */ - getLastRestore(regIndex, elemIndex) { - const restores = this.events.filter( - e => - e.regIndex === regIndex && - e.elemIndex === elemIndex && - e.type === EventType.READ_MEMORY, - ); - return restores[restores.length - 1]; - } -} - -/** - * Validation rules for calling convention - */ -class ConventionRules { - /** - * Check if a saved register follows proper save/restore pattern - */ - static validateSavedRegister(frame, regIndex, elemIndex) { - const violations = []; - const register = REGISTERS[regIndex].elements[elemIndex]; - const events = frame.getRegisterEvents(regIndex, elemIndex); - - // Rule 1: Saved registers must be saved before modification - const firstSave = frame.getFirstSave(regIndex, elemIndex); - const modifications = events.filter( - e => - e.type === EventType.WRITE_REGISTER || - e.type === EventType.READ_REGISTER, - ); - - if (modifications.length > 0 && !firstSave) { - violations.push({ - rule: "SAVE_BEFORE_USE", - register: register.name, - message: `Register ${register.name} was used but never saved to memory`, - }); - } - - if (firstSave && modifications.length > 0) { - const firstMod = modifications[0]; - if (firstMod.timestamp < firstSave.timestamp) { - violations.push({ - rule: "SAVE_BEFORE_USE", - register: register.name, - message: `Register ${register.name} was modified before being saved`, - }); - } - } - - // Rule 2: Saved registers must be restored from the same address - const lastRestore = frame.getLastRestore(regIndex, elemIndex); - if (firstSave && !lastRestore) { - violations.push({ - rule: "RESTORE_REQUIRED", - register: register.name, - message: `Register ${register.name} was saved but never restored`, - }); - } - - if (firstSave && lastRestore) { - if (!bigintsEqual(firstSave.address, lastRestore.address)) { - const saveAddr = toBigIntSafe(firstSave.address); - const restoreAddr = toBigIntSafe(lastRestore.address); - const saveStr = - saveAddr !== null - ? `0x${saveAddr.toString(16)}` - : String(firstSave.address); - const restoreStr = - restoreAddr !== null - ? `0x${restoreAddr.toString(16)}` - : String(lastRestore.address); - violations.push({ - rule: "RESTORE_ADDRESS_MISMATCH", - register: register.name, - message: `Register ${register.name} saved at ${saveStr} but restored from ${restoreStr}`, - }); - } - } - - // Rule 3: Save and restore sizes must match - if (firstSave && lastRestore) { - const s1 = toBigIntSafe(firstSave.size); - const s2 = toBigIntSafe(lastRestore.size); - if (s1 === null || s2 === null || s1 !== s2) { - const s1Str = - s1 !== null ? s1.toString() : String(firstSave.size); - const s2Str = - s2 !== null ? s2.toString() : String(lastRestore.size); - violations.push({ - rule: "SIZE_MISMATCH", - register: register.name, - message: `Register ${register.name} saved with ${s1Str} bytes but restored with ${s2Str} bytes`, - }); - } - } - - // Rule 4: Value must be restored (if the register was modified) - const currentValue = REGISTERS[regIndex].elements[elemIndex].value; - const initialValue = frame.initialRegisterValues[regIndex]?.[elemIndex]; - - const valueChanged = !valuesEqual(currentValue, initialValue); - - if (valueChanged && modifications.length > 0) { - violations.push({ - rule: "VALUE_NOT_RESTORED", - register: register.name, - message: `Register ${register.name} value changed but not properly restored`, - }); - } - - return violations; - } - - /** - * Check stack pointer restoration - */ - static validateStackPointer(frame, currentStackPointer) { - const spEnter = toBigIntSafe(frame.enterStackPointer); - const spNow = toBigIntSafe(currentStackPointer); - if (spEnter === null || spNow === null || spEnter !== spNow) { - const enterStr = - spEnter !== null - ? `0x${spEnter.toString(16)}` - : String(frame.enterStackPointer); - const nowStr = - spNow !== null - ? `0x${spNow.toString(16)}` - : String(currentStackPointer); - return [ - { - rule: "STACK_NOT_RESTORED", - message: `Stack pointer not restored: entered at ${enterStr}, exited at ${nowStr}`, - }, - ]; - } - return []; - } -} - -/** - * Main validator class for calling conventions - */ -class CallingConventionValidator { - constructor() { - this.callStack = []; - } - - /** - * Enter a new function - */ - enter(functionName) { - const stackPointer = architecture.memory_layout.stack.start; - const frame = new CallFrame(functionName, stackPointer); - this.callStack.push(frame); - console_log(`[SENTINEL] Entering function: ${functionName}`, "INFO"); - return { ok: true, msg: "" }; - } - - /** - * Leave current function and validate - */ - leave() { - if (this.callStack.length === 0) { - return { - ok: false, - msg: "Cannot leave function: call stack is empty", - }; - } - - const frame = this.callStack[this.callStack.length - 1]; - console_log( - `[SENTINEL] Leaving function: ${frame.functionName}`, - "INFO", - ); - - const violations = []; - - // Validate stack pointer - const spViolations = ConventionRules.validateStackPointer( - frame, - architecture.memory_layout.stack.start, - ); - violations.push(...spViolations); - - // Validate each saved register - for (let i = 0; i < REGISTERS.length; i++) { - for (let j = 0; j < REGISTERS[i].elements.length; j++) { - const register = REGISTERS[i].elements[j]; - - // Only check registers that should be saved - if (register.properties.includes("saved")) { - const regViolations = ConventionRules.validateSavedRegister( - frame, - i, - j, - ); - violations.push(...regViolations); - } - } - } - - // Pop the frame - this.callStack.pop(); - - // Return result - if (violations.length > 0) { - const messages = violations.map(v => ` - ${v.message}`).join("\n"); - return { - ok: false, - msg: `Calling convention violations in ${frame.functionName}:\n${messages}`, - }; - } - - return { ok: true, msg: "" }; - } - - /** - * Record a memory write event - */ - recordMemoryWrite(regIndex, elemIndex, address, size) { - if (this.callStack.length === 0) { - console_log( - "[SENTINEL] Warning: Memory write outside function context", - "WARN", - ); - return; - } - - const frame = this.callStack[this.callStack.length - 1]; - const event = new RegisterEvent( - EventType.WRITE_MEMORY, - regIndex, - elemIndex, - address, - size, - ); - frame.addEvent(event); - } - - /** - * Record a memory read event - */ - recordMemoryRead(regIndex, elemIndex, address, size) { - if (this.callStack.length === 0) { - console_log( - "[SENTINEL] Warning: Memory read outside function context", - "WARN", - ); - return; - } - - const frame = this.callStack[this.callStack.length - 1]; - const event = new RegisterEvent( - EventType.READ_MEMORY, - regIndex, - elemIndex, - address, - size, - ); - frame.addEvent(event); - } - - /** - * Record a register write event - */ - recordRegisterWrite(regIndex, elemIndex) { - if (this.callStack.length === 0) { - return; - } - - const frame = this.callStack[this.callStack.length - 1]; - const event = new RegisterEvent( - EventType.WRITE_REGISTER, - regIndex, - elemIndex, - ); - frame.addEvent(event); - } - - /** - * Record a register read event - */ - recordRegisterRead(regIndex, elemIndex) { - if (this.callStack.length === 0) { - return; - } - - const frame = this.callStack[this.callStack.length - 1]; - const event = new RegisterEvent( - EventType.READ_REGISTER, - regIndex, - elemIndex, - ); - frame.addEvent(event); - } - - /** - * Reset the validator - */ - reset() { - this.callStack = []; - this.enter("main"); - return { ok: true, msg: "" }; - } - - /** - * Get current call depth - */ - getCallDepth() { - return this.callStack.length; - } - - /** - * Get current function name - */ - getCurrentFunction() { - if (this.callStack.length === 0) { - return null; - } - return this.callStack[this.callStack.length - 1].functionName; - } -} - -// Global instance -const validator = new CallingConventionValidator(); - -// Public API - Direct validator interface -// yes, it HAS to be with arrow functions -export const sentinel = { - enter: functionName => validator.enter(functionName), - leave: () => validator.leave(), - recordMemoryWrite: (regIndex, elemIndex, address, size) => - validator.recordMemoryWrite(regIndex, elemIndex, address, size), - recordMemoryRead: (regIndex, elemIndex, address, size) => - validator.recordMemoryRead(regIndex, elemIndex, address, size), - recordRegisterWrite: (regIndex, elemIndex) => - validator.recordRegisterWrite(regIndex, elemIndex), - recordRegisterRead: (regIndex, elemIndex) => - validator.recordRegisterRead(regIndex, elemIndex), - reset: () => validator.reset(), - getCallDepth: () => validator.getCallDepth(), - getCurrentFunction: () => validator.getCurrentFunction(), -}; diff --git a/src/core/sentinel/sentinel.mts b/src/core/sentinel/sentinel.mts new file mode 100644 index 000000000..ef0a0ab0a --- /dev/null +++ b/src/core/sentinel/sentinel.mts @@ -0,0 +1,473 @@ +/** + * Copyright 2018-2026 CREATOR Team. + * + * This file is part of CREATOR. + * + * CREATOR is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CREATOR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CREATOR. If not, see . + */ + +import { architecture, REGISTERS } from "../core.mjs"; +import { console_log } from "../utils/creator_logger.mjs"; +import type { SentinelErrorEvent, SentinelErrorData } from "../events.mts"; + +/** + * Event types that can occur during function execution + */ +const EventType = { + WRITE_MEMORY: "write_memory", + READ_MEMORY: "read_memory", + WRITE_REGISTER: "write_register", + READ_REGISTER: "read_register", +}; + +/** + * Represents a single event in the register lifecycle + */ +class RegisterEvent { + type: string; + regIndex: number; + elemIndex: number; + address: bigint | null; + size: number | null; + timestamp: number; + + constructor( + type: string, + regIndex: number, + elemIndex: number, + address: bigint|null = null, + size: number|null = null + ) { + this.type = type; + this.regIndex = regIndex; + this.elemIndex = elemIndex; + this.address = address; + this.size = size; + this.timestamp = Date.now(); + } + + get registerName() { + return ( + REGISTERS[this.regIndex]!.elements[this.elemIndex]!.name + ); + } + + toString() { + const addr = + this.address !== null ? ` @0x${this.address.toString(16)}` : ""; + const size = this.size !== null ? ` (${this.size} bytes)` : ""; + return `${this.type}: ${this.registerName}${addr}${size}`; + } +} + +/** + * Represents a function call frame with register state tracking + */ +class CallFrame { + functionName: string; + enterStackPointer: number; + events: RegisterEvent[]; + initialRegisterValues: bigint[][]; + + constructor(functionName: string, stackPointer: number) { + this.functionName = functionName; + this.enterStackPointer = stackPointer; + this.events = []; + this.initialRegisterValues = CallFrame._captureRegisterValues(); + } + + static _captureRegisterValues() { + const values: bigint[][] = []; + for (const file of REGISTERS) { + const curr = []; + for (const reg of file.elements) { + curr.push(reg.value); + } + values.push(curr); + } + return values; + } + + addEvent(event: RegisterEvent) { + this.events.push(event); + console_log( + `[EVENT] ${this.functionName}: ${event.toString()}`, + "INFO", + ); + } + + /** + * Get all events for a specific register + */ + getRegisterEvents(regIndex: number, elemIndex: number) { + return this.events.filter( + e => e.regIndex === regIndex && e.elemIndex === elemIndex, + ); + } + + /** + * Find the first save event for a register + */ + getFirstSave(regIndex: number, elemIndex: number) { + return this.events.find( + e => + e.regIndex === regIndex && + e.elemIndex === elemIndex && + e.type === EventType.WRITE_MEMORY, + ); + } + + /** + * Find the last restore event for a register + */ + getLastRestore(regIndex: number, elemIndex: number) { + const restores = this.events.filter( + e => + e.regIndex === regIndex && + e.elemIndex === elemIndex && + e.type === EventType.READ_MEMORY, + ); + return restores[restores.length - 1]; + } +} + +/** + * Validation rules for calling convention + */ +class ConventionRules { + /** + * Check if a saved register follows proper save/restore pattern + */ + static validateSavedRegister( + frame: CallFrame, + regIndex: number, + elemIndex: number + ): SentinelErrorData[] { + const violations = []; + const register = REGISTERS[regIndex]!.elements[elemIndex]!; + const events = frame.getRegisterEvents(regIndex, elemIndex); + + // Rule 1: Saved registers must be saved before modification + const firstSave = frame.getFirstSave(regIndex, elemIndex); + const modifications = events.filter( + e => + e.type === EventType.WRITE_REGISTER || + e.type === EventType.READ_REGISTER, + ); + + if (modifications.length > 0 && !firstSave) { + violations.push({ + rule: "SAVE_BEFORE_USE", + register: register.name, + message: `Register ${register.name} was used but never saved to memory`, + }); + } + + const firstMod = modifications[0]; + if (firstSave && firstMod) { + if (firstMod.timestamp < firstSave.timestamp) { + violations.push({ + rule: "SAVE_BEFORE_USE", + register: register.name, + message: `Register ${register.name} was modified before being saved`, + }); + } + } + + // Rule 2: Saved registers must be restored from the same address + const lastRestore = frame.getLastRestore(regIndex, elemIndex); + if (firstSave && !lastRestore) { + violations.push({ + rule: "RESTORE_REQUIRED", + register: register.name, + message: `Register ${register.name} was saved but never restored`, + }); + } + + if (firstSave && lastRestore) { + if (firstSave.address !== lastRestore.address) { + const saveAddr = firstSave.address; + const restoreAddr = lastRestore.address; + const saveStr = + saveAddr !== null + ? `0x${saveAddr.toString(16)}` + : String(firstSave.address); + const restoreStr = + restoreAddr !== null + ? `0x${restoreAddr.toString(16)}` + : String(lastRestore.address); + violations.push({ + rule: "RESTORE_ADDRESS_MISMATCH", + register: register.name, + message: `Register ${register.name} saved at ${saveStr} but restored from ${restoreStr}`, + }); + } + } + + // Rule 3: Save and restore sizes must match + if (firstSave && lastRestore) { + const s1 = firstSave.size; + const s2 = lastRestore.size; + if (s1 !== s2) { + violations.push({ + rule: "SIZE_MISMATCH", + register: register.name, + message: `Register ${register.name} saved with ${s1} bytes but restored with ${s2} bytes`, + }); + } + } + + // Rule 4: Value must be restored (if the register was modified) + const currentValue = register.value; + const initialValue = frame.initialRegisterValues[regIndex]![elemIndex]!; + + if (currentValue !== initialValue && modifications.length > 0) { + violations.push({ + rule: "VALUE_NOT_RESTORED", + register: register.name, + message: `Register ${register.name} value changed but not properly restored`, + }); + } + + return violations; + } + + /** + * Check stack pointer restoration + */ + static validateStackPointer( + frame: CallFrame, + currentStackPointer: number + ): SentinelErrorData[] { + const spEnter = frame.enterStackPointer; + const spNow = currentStackPointer; + if (spEnter !== spNow) { + const enterStr = `0x${spEnter.toString(16)}`; + const nowStr = `0x${spNow.toString(16)}`; + return [ + { + rule: "STACK_NOT_RESTORED", + message: `Stack pointer not restored: entered at ${enterStr}, exited at ${nowStr}`, + }, + ]; + } + return []; + } +} + +/** + * Main validator class for calling conventions + */ +class CallingConventionValidator { + private callStack: CallFrame[]; + + constructor() { + this.callStack = []; + } + + /** + * Enter a new function + */ + enter(functionName: string) { + const stackPointer = architecture.memory_layout.stack.start; + const frame = new CallFrame(functionName, stackPointer); + this.callStack.push(frame); + console_log(`[SENTINEL] Entering function: ${functionName}`, "INFO"); + } + + /** + * Leave current function and validate + */ + leave(): SentinelErrorEvent { + // Pop the frame + const frame = this.callStack.pop(); + + if (frame === undefined) { + return { + ok: false, + functionName: "unknown", + errors: [ + { + rule: "EMPTY_CALLSTACK", + message: "Cannot leave function: call stack is empty", + }, + ], + }; + } + + console_log( + `[SENTINEL] Leaving function: ${frame.functionName}`, + "INFO", + ); + + const errors: SentinelErrorData[] = []; + + // Validate stack pointer + const spViolations = ConventionRules.validateStackPointer( + frame, + architecture.memory_layout.stack.start, + ); + errors.push(...spViolations); + + // Validate each saved register + for (const [i, file] of REGISTERS.entries()) { + for (const [j, register] of file.elements.entries()) { + // Only check registers that should be saved + if (register.properties.includes("saved")) { + const regViolations = ConventionRules.validateSavedRegister( + frame, + i, + j, + ); + errors.push(...regViolations); + } + } + } + + return { + ok: errors.length === 0, + functionName: frame.functionName, + errors, + }; + } + + /** + * Record a memory write event + */ + recordMemoryWrite(regIndex: number, elemIndex: number, address: bigint, size: number) { + const frame = this.callStack[this.callStack.length - 1]; + if (frame === undefined) { + console_log( + "[SENTINEL] Warning: Memory write outside function context", + "WARN", + ); + return; + } + + const event = new RegisterEvent( + EventType.WRITE_MEMORY, + regIndex, + elemIndex, + address, + size, + ); + frame.addEvent(event); + } + + /** + * Record a memory read event + */ + recordMemoryRead(regIndex: number, elemIndex: number, address: bigint, size: number) { + const frame = this.callStack[this.callStack.length - 1]; + if (frame === undefined) { + console_log( + "[SENTINEL] Warning: Memory read outside function context", + "WARN", + ); + return; + } + + const event = new RegisterEvent( + EventType.READ_MEMORY, + regIndex, + elemIndex, + address, + size, + ); + frame.addEvent(event); + } + + /** + * Record a register write event + */ + recordRegisterWrite(regIndex: number, elemIndex: number) { + const frame = this.callStack[this.callStack.length - 1]; + if (frame === undefined) { + return; + } + + const event = new RegisterEvent( + EventType.WRITE_REGISTER, + regIndex, + elemIndex, + ); + frame.addEvent(event); + } + + /** + * Record a register read event + */ + recordRegisterRead(regIndex: number, elemIndex: number) { + const frame = this.callStack[this.callStack.length - 1]; + if (frame === undefined) { + return; + } + + const event = new RegisterEvent( + EventType.READ_REGISTER, + regIndex, + elemIndex, + ); + frame.addEvent(event); + } + + /** + * Reset the validator + */ + reset() { + this.callStack = []; + this.enter(architecture.config.main_function); + } + + /** + * Get current call depth + */ + getCallDepth() { + return this.callStack.length; + } + + /** + * Get current function name + */ + getCurrentFunction() { + return this.callStack[this.callStack.length - 1]?.functionName; + } +} + +// Global instance +const validator = new CallingConventionValidator(); + +// Public API - Direct validator interface +// yes, it HAS to be with arrow functions +export const sentinel = { + enter: (functionName: string) => validator.enter(functionName), + leave: () => validator.leave(), + recordMemoryWrite: (regIndex: number, elemIndex: number, address: bigint, size: number) => + validator.recordMemoryWrite(regIndex, elemIndex, address, size), + recordMemoryRead: (regIndex: number, elemIndex: number, address: bigint, size: number) => + validator.recordMemoryRead(regIndex, elemIndex, address, size), + recordRegisterWrite: (regIndex: number, elemIndex: number) => + validator.recordRegisterWrite(regIndex, elemIndex), + recordRegisterRead: (regIndex: number, elemIndex: number) => + validator.recordRegisterRead(regIndex, elemIndex), + reset: () => validator.reset(), + getCallDepth: () => validator.getCallDepth(), + getCurrentFunction: () => validator.getCurrentFunction(), + formatErrors: (frameResult: SentinelErrorEvent) => { + const messages = frameResult.errors + .map(v => ` - ${v.message}`) + .join("\n"); + return `Calling convention violations in ${frameResult.functionName}:\n${messages}`; + }, +}; diff --git a/src/core/utils/architectureProcessor.mjs b/src/core/utils/architectureProcessor.mjs index a8d992a9a..053942d07 100644 --- a/src/core/utils/architectureProcessor.mjs +++ b/src/core/utils/architectureProcessor.mjs @@ -423,20 +423,16 @@ function convertElementValuesToBigInt(architectureObj) { } for (const element of component.elements) { + // Convert function using two's complement + const convert = (x) => BigInt.asUintN(element.nbits, BigInt(x)); // Convert value to BigInt if it exists and is not already a BigInt - if ( - element.value !== undefined && - typeof element.value !== "bigint" - ) { - element.value = BigInt(element.value); + if (typeof element.value !== "bigint") { + element.value = convert(element.value); } // Convert default_value to BigInt if it exists and is not already a BigInt - if ( - element.default_value !== undefined && - typeof element.default_value !== "bigint" - ) { - element.default_value = BigInt(element.default_value); + if (typeof element.default_value !== "bigint") { + element.default_value = convert(element.default_value); } } } @@ -514,7 +510,7 @@ function calculateRequiredISAs( ); if (nonExistentISAs.length > 0) { - const message = `There are nonexistant dependencies in the architecture: ${nonExistentISAs.join( + const message = `There are nonexistent dependencies in the architecture: ${nonExistentISAs.join( ", ", )}`; logger.error(message); diff --git a/src/core/utils/float_bigint.mjs b/src/core/utils/float_bigint.mjs index a4b022ead..08f523a04 100644 --- a/src/core/utils/float_bigint.mjs +++ b/src/core/utils/float_bigint.mjs @@ -47,11 +47,6 @@ export function bi_BigIntTofloat(big_int_value) { */ export function bi_BigIntTodouble(big_int_value) { const hex = big_int_value.toString(16).padStart(16, "0"); - // if the first 8 characters are 0, it's a 32-bit float, not a double - if (hex.substring(0, 8) === "00000000") { - return hex2float("0x" + hex.substring(8, 16)); - } - return hex2double("0x" + hex); } diff --git a/src/rpc/server.mts b/src/rpc/server.mts index ae73d9ea5..848a619c2 100644 --- a/src/rpc/server.mts +++ b/src/rpc/server.mts @@ -84,7 +84,7 @@ interface EmulatorState { }; instructions: Array<{ address: string; - label?: string; + label: string[]; asm: string; machineCode: string; }>; @@ -597,13 +597,13 @@ class CreatorRpcServer { baseAddress: bigint, wordSize: number, ): Array<{ - tag: string; + tag: string[]; type: string; offset: number; sizeInBits?: number; }> { const hints: Array<{ - tag: string; + tag: string[]; type: string; offset: number; sizeInBits?: number; @@ -730,7 +730,7 @@ class CreatorRpcServer { // Get instruction list with better debugging info const instructionList = instructions.map((instr, index) => ({ address: instr.Address, - label: instr.Label || "", + label: instr.Label, asm: instr.loaded || instr.user || "", machineCode: instr.binary || instr.loaded || "", instructionIndex: index, @@ -767,7 +767,7 @@ class CreatorRpcServer { currentInstruction?: { index: number; address: string; - label?: string; + label: string[]; asm: string; machineCode: string; isBreakpoint?: boolean; @@ -775,7 +775,7 @@ class CreatorRpcServer { nextInstruction?: { index: number; address: string; - label?: string; + label: string[]; asm: string; machineCode: string; }; @@ -824,7 +824,7 @@ class CreatorRpcServer { currentInstruction = { index: i, address: instr.Address, - label: instr.Label || undefined, + label: instr.Label, asm: instr.loaded || instr.user || "", machineCode: instr.binary || instr.loaded || "", isBreakpoint: instr.Break === true, @@ -836,7 +836,7 @@ class CreatorRpcServer { nextInstruction = { index: i + 1, address: nextInstr.Address, - label: nextInstr.Label || undefined, + label: nextInstr.Label, asm: nextInstr.loaded || nextInstr.user || "", machineCode: nextInstr.binary || nextInstr.loaded || "", @@ -877,7 +877,7 @@ class CreatorRpcServer { }): Promise<{ index: number; address: string; - label?: string; + label: string[]; asm: string; machineCode: string; visible: boolean; @@ -918,7 +918,7 @@ class CreatorRpcServer { return { index, address: instruction.Address, - label: instruction.Label || undefined, + label: instruction.Label, asm: instruction.loaded || instruction.user || "", machineCode: instruction.binary || instruction.loaded || "", visible: instruction.visible !== false, @@ -980,7 +980,7 @@ class CreatorRpcServer { instruction: { index, address: instruction.Address, - label: instruction.Label || undefined, + label: instruction.Label, asm: instruction.loaded || instruction.user || "", machineCode: instruction.binary || instruction.loaded || "", isBreakpoint: instruction.Break === true, @@ -1001,7 +1001,7 @@ class CreatorRpcServer { Array<{ index: number; address: string; - label?: string; + label?: string[]; asm: string; machineCode: string; visible: boolean; @@ -1024,7 +1024,7 @@ class CreatorRpcServer { return instructions.map((instr, index) => ({ index, address: instr.Address, - label: instr.Label || undefined, + label: instr.Label, asm: instr.loaded || instr.user || "", user: instr.user || "", loaded: instr.loaded || "", diff --git a/src/web/App.vue b/src/web/App.vue index adbd361dc..60ec9a6bc 100644 --- a/src/web/App.vue +++ b/src/web/App.vue @@ -354,6 +354,14 @@ export default { target_port: "", target_location: "~/creator", flash_url: "http://localhost:8080", + + /* Validation test */ + // Stats + passed_test: 0, + failed_test: 0, + + // Check testing execution + testing: false, }; }, diff --git a/src/web/components/ArchitectureView.vue b/src/web/components/ArchitectureView.vue index dd07d67af..2eb25c016 100644 --- a/src/web/components/ArchitectureView.vue +++ b/src/web/components/ArchitectureView.vue @@ -30,6 +30,8 @@ import Instructions from "./architecture/instructions/Instructions.vue"; import Directives from "./architecture/directives/Directives.vue"; import Pseudoinstructions from "./architecture/pseudoinstructions/Pseudoinstructions.vue"; import CacheMemory from "./architecture/cache_memory/CacheMemory.vue"; +import { SailTest32, SailTest64 } from "@/core/executor/sailSimRV/sailExecutor.mjs"; +import { coreEvents } from "@/core/events.mts"; export default defineComponent({ props: { browser: { type: String, required: true }, @@ -55,6 +57,12 @@ export default defineComponent({ return { architecture, activeTab: "instructions", + validate: false, + showValidationModal: false, + running: false, + runned: 0, + result_test: 0, + result_log: "" }; }, computed: { @@ -71,6 +79,42 @@ export default defineComponent({ return `# yaml-language-server: $schema=${document.URL.replace(/\/#$/, "/")}schema/architecture.json\n${this.arch_code}`; }, }, + methods:{ + runValidationTest(arch_type: Number){ + this.runned = 0; + this.result_test = 0; + this.running = true; + this.result_log = ""; + if (arch_type === 32){ + SailTest32(); + } else { + SailTest64(); + } + }, + updateState(){ + this.result_test = document.app.$data.passed_test; + if (this.result_test + document.app.$data.failed_test === ((architecture.config.name === 'SRV32' ? 89 : 122)) ){ + this.result_log = "Validation completed.\n Your architecture passed the " + (this.result_test / (architecture.config.name === 'SRV32' ? 89 : 122)) * 100 + "%\n of the validation tests."; + } + + }, + resetValidationState(){ + this.runned = 0; + this.result_test = 0; + this.running = true; + this.result_log = ""; + document.app.$data.passed_test = 0; + document.app.$data.failed_test = 0; + document.app.$data.testing = false; + }, + }, + mounted(){ + coreEvents.on("update-validation", this.updateState); + }, + beforeUnmount() { + coreEvents.off("update-validation", this.updateState); + + }, }); @@ -174,6 +218,19 @@ export default defineComponent({ Cache Memory + + + @@ -222,6 +279,36 @@ export default defineComponent({ :cache_policy="$root.$data.cache_policy" > + + This validation test runs {{(architecture.config.name === 'SRV32' ? 89 : 122)}} RISC-V programs.
+ These programs are taken from the official RISC-V test repository (riscv-tests), where the correct operation
+ of the full instruction set of the RISC-V specification is verified. +

+ + + + Run tests + + + +
+
{{ result_log }}
+
+
+ +
+ +
+ diff --git a/src/web/components/assembly/SaveLibrary.vue b/src/web/components/assembly/SaveLibrary.vue index a564efd44..2441418c5 100644 --- a/src/web/components/assembly/SaveLibrary.vue +++ b/src/web/components/assembly/SaveLibrary.vue @@ -91,10 +91,11 @@ export default defineComponent({ } // Check for main symbol (not allowed in libraries) + const main = architecture.config.main_function; for (const instruction of libraryInstructions) { - if (instruction.Label === "main") { + if (instruction.Label.includes(main)) { show_notification( - 'You cannot use the "main" label in a library', + `You cannot use the "${main}" label in a library`, "danger", ); return false; @@ -114,16 +115,17 @@ export default defineComponent({ // Add symbol if instruction has a global label if ( - instruction.Label && - instruction.Label !== "" && + instruction.Label.length > 0 && instruction.globl === true ) { const addr = parseInt(instruction.Address, 16); - symbols.push({ - name: instruction.Label, - addr, - }); + for (const label of instruction.Label) { + symbols.push({ + name: label, + addr, + }); + } } } diff --git a/src/web/components/general/AboutModal.vue b/src/web/components/general/AboutModal.vue index 6c852beba..546958768 100644 --- a/src/web/components/general/AboutModal.vue +++ b/src/web/components/general/AboutModal.vue @@ -29,7 +29,7 @@ interface Props { defineProps(); const contactMail = "creator.arcos.inf.uc3m.es@gmail.com"; -const projectVersion = "6.1.0"; +const projectVersion = "6.1.1"; const projectLicense = "LGPL-3.0"; const repositoryUrl = "https://github.com/creatorsim/creator"; diff --git a/src/web/components/general/NavbarCREATOR.vue b/src/web/components/general/NavbarCREATOR.vue index 1f138f757..f546180bd 100644 --- a/src/web/components/general/NavbarCREATOR.vue +++ b/src/web/components/general/NavbarCREATOR.vue @@ -32,7 +32,7 @@ import SentinelErrorsDropdown from "../simulator/SentinelErrorsDropdown.vue"; import ThemeToggle from "./ThemeToggle.vue"; import type { Instruction } from "@/core/assembler/assembler"; import type { BDropdown } from "bootstrap-vue-next"; -import { coreEvents, CoreEventTypes } from "../../../core/events.mts"; +import { coreEvents, CoreEventTypes, type SentinelErrorEvent } from "../../../core/events.mts"; import { remove_library, architecture, load_CREATino } from "@/core/core.mjs"; import { createFile } from "../assembly/MultifileEditor.mjs"; @@ -67,17 +67,9 @@ export default defineComponent({ typeof SentinelErrorsDropdown > | null>(null); - const handleSentinelError = (event: unknown) => { - const errorEvent = event as { - functionName: string; - message: string; - ok: boolean; - }; + const handleSentinelError = (event: SentinelErrorEvent) => { if (sentinelDropdownRef.value) { - sentinelDropdownRef.value.checkForErrors( - { ok: errorEvent.ok, msg: errorEvent.message }, - errorEvent.functionName, - ); + sentinelDropdownRef.value.checkForErrors(event); } }; diff --git a/src/web/components/mobile/MobileInstructionsView.vue b/src/web/components/mobile/MobileInstructionsView.vue index 499014cb2..7911c89fe 100644 --- a/src/web/components/mobile/MobileInstructionsView.vue +++ b/src/web/components/mobile/MobileInstructionsView.vue @@ -28,7 +28,11 @@ import TableExecution from "@/web/components/simulator/TableExecution.vue"; import SimulatorControls from "@/web/components/simulator/SimulatorControls.vue"; import SentinelErrorsDropdown from "@/web/components/simulator/SentinelErrorsDropdown.vue"; import type { Instruction } from "@/core/assembler/assembler"; -import { coreEvents, CoreEventTypes } from "../../../core/events.mts"; +import { + coreEvents, + CoreEventTypes, + type SentinelErrorEvent, +} from "../../../core/events.mts"; export default defineComponent({ props: { @@ -52,17 +56,9 @@ export default defineComponent({ typeof SentinelErrorsDropdown > | null>(null); - const handleSentinelError = (event: unknown) => { - const errorEvent = event as { - functionName: string; - message: string; - ok: boolean; - }; + const handleSentinelError = (event: SentinelErrorEvent) => { if (sentinelDropdownRef.value) { - sentinelDropdownRef.value.checkForErrors( - { ok: errorEvent.ok, msg: errorEvent.message }, - errorEvent.functionName, - ); + sentinelDropdownRef.value.checkForErrors(event); } }; diff --git a/src/web/components/simulator/ArduinoTerminal.vue b/src/web/components/simulator/ArduinoTerminal.vue index 1fb4d9179..cba81efe3 100644 --- a/src/web/components/simulator/ArduinoTerminal.vue +++ b/src/web/components/simulator/ArduinoTerminal.vue @@ -154,6 +154,7 @@ import { } from "../../../core/register/registerOperations.mjs"; import { crex_findReg } from "../../../core/register/registerLookup.mjs"; + export default { setup() { return { @@ -180,6 +181,7 @@ export default { isResizing: false, chipStyles: {}, interrupt: {}, + isInterruptsEnabled: true, }; }, @@ -239,6 +241,7 @@ export default { }); coreEvents.on("arduino-pin-interrupt", pinName => { + if (!this.isInterruptsEnabled) return; this.interrupt[pinName.pin] = true; esp32vect.value[pinName.position] = [ BigInt(pinName.pin.replace(/\D/g, "")), @@ -247,8 +250,12 @@ export default { ]; }); coreEvents.on("arduino-pin-detach-interrupt", pinName => { + if (!this.isInterruptsEnabled) return; delete this.interrupt[pinName.pin]; }); + coreEvents.on("arduino-interrupts-enabled", enabled => { + this.isInterruptsEnabled = enabled; + }); }, beforeUnmount() { diff --git a/src/web/components/simulator/Calculator.vue b/src/web/components/simulator/Calculator.vue index 587e9f769..1c6896dee 100644 --- a/src/web/components/simulator/Calculator.vue +++ b/src/web/components/simulator/Calculator.vue @@ -107,7 +107,7 @@ export default defineComponent({ convertFromDecimal() { try { this.error = ""; - const value = parseFloat(this.decimalInput); + const value = parseFloat(this.decimalInput || 0); if (isNaN(value)) { this.error = "Invalid decimal number"; @@ -152,23 +152,22 @@ export default defineComponent({ this.error = ""; let hexStr = this.hexInput.replace(/^0x/i, "").replace(/\s/g, ""); - if (!/^[0-9a-fA-F]+$/.test(hexStr)) { + if (!/^[0-9a-fA-F]*$/.test(hexStr)) { this.error = "Invalid hexadecimal value"; return; } + const size = Math.ceil(this.formatBits / 4); + hexStr = hexStr.padStart(size, "0").slice(-size); if (this.format === "ieee32") { - hexStr = hexStr.padStart(8, "0").substring(0, 8); this.decimalValue = hex2float("0x" + hexStr); this.binaryValue = float2bin(this.decimalValue); - this.hexValue = "0x" + hexStr.toUpperCase(); } else { // IEEE 64 - hexStr = hexStr.padStart(16, "0").substring(0, 16); this.decimalValue = hex2double("0x" + hexStr); this.binaryValue = double2bin(this.decimalValue); - this.hexValue = "0x" + hexStr.toUpperCase(); } + this.hexValue = "0x" + hexStr.toUpperCase(); this.updateBreakdown(); this.updateInputs(); @@ -182,13 +181,13 @@ export default defineComponent({ this.error = ""; let binStr = this.binaryInput.replace(/\s/g, ""); - if (!/^[01]+$/.test(binStr)) { + if (!/^[01]*$/.test(binStr)) { this.error = "Invalid binary value"; return; } const expectedBits = this.formatBits; - binStr = binStr.padStart(expectedBits, "0").substring(0, expectedBits); + binStr = binStr.padStart(expectedBits, "0").slice(-expectedBits); this.binaryValue = binStr; diff --git a/src/web/components/simulator/HexViewer.vue b/src/web/components/simulator/HexViewer.vue index 47f18c2d0..ec280ce99 100644 --- a/src/web/components/simulator/HexViewer.vue +++ b/src/web/components/simulator/HexViewer.vue @@ -536,7 +536,7 @@ export default defineComponent({ // Add hint for this instruction hints.push({ address: addr.toString(), - tag: instruction.loaded || instruction.user, + tag: [instruction.loaded || instruction.user], type: "instruction", sizeInBits: instructionSizeInBits, }); @@ -603,7 +603,7 @@ export default defineComponent({ for (let i = 0; i < sizeInBytes; i++) { this.hintMap.set(address + i, { - tag: typeof hint.tag === "string" ? hint.tag : hint.tag.join(", "), + tag: hint.tag.join(", "), type: hint.type, sizeInBits: hint.sizeInBits, colorIndex: hintColorIndex, diff --git a/src/web/components/simulator/SentinelErrorsDropdown.vue b/src/web/components/simulator/SentinelErrorsDropdown.vue index b980eff3a..1052b340d 100644 --- a/src/web/components/simulator/SentinelErrorsDropdown.vue +++ b/src/web/components/simulator/SentinelErrorsDropdown.vue @@ -20,16 +20,16 @@ along with CREATOR. If not, see .