You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

679 lines
12 KiB
JavaScript

/*
RISC-V Code Mirror Mode
Based on the mode present in the Venus Simulator
Author: kvakil
Source: https://github.com/kvakil/venus
Forked by Matthew Nielsen (github.com/matthewnielsen27)
*/
const CodeMirror = require('codemirror')
CodeMirror.defineMode('riscv', function (/* config */) {
function regexFromWords(words, ins) {
return new RegExp('^(?:' + words.join('|') + ')$', ins)
}
// Instructions
// Part 1) Base Integer Instructions
// a) Loads
// b) Stores
// c) Shifts
// d) Arithmetic
// e) Logical
// f) Compare
// g) Branches
// h) Jump & Link
// i) Synch
// j) System
// k) Counters
// Part 2) RV Priveleged Instructions
// a) CSR Access
// b) Change Level
// c) Trap Redirect
// Part 3) Optional Multiply-Divide Instruction Extension: RVM
// a) Multiply
// b) Divide
// c) Remainder
// Part 4) Pseudo Instructions
// a) Standard
// b) Non-Standard
// Part 5) Optional Compressed (16-bit) Instruction Extension: RVC
// a) Loads
// b) Stores
// c) Arithmetic
// d) Shifts
// e) Branches
// f) Jump
// g) Jump & Link
// h) System
// Part 6) Optional Atomic Instruction Extension: RVA
// a) Load
// b) Store
// c) Swap
// d) Add
// e) Logical
// f) Min\Max
// Part 7) Optional Floating-Point Instruction Extension: RVF, RVD, & RVQ
// a) Move
// b) Convert
// c) Load
// d) Store
// e) Arithmetic
// f) Mui-Add
// g) Sign Inject
// h) Min/Max
// i) Compare
// j) Categorization
// k) Configuration
var instructions = regexFromWords(
[
// Part 1) Base Integer Instructions
// a) Loads
// I) RV32I
'lb',
'lh',
'lw',
'lbu',
'lhu',
// II) RV64I and RV128I
'ld',
'lq',
'lwu',
'ldu',
// b) Stores
// I) RV32I
'sb',
'sh',
'sw',
// II) RV64I and RV128I
'sd',
'sq',
// c) Shifts
// I) RV32I
'sll',
'slli',
'srl',
'srli',
'sra',
'srai',
// II) RV64I and RV128I
'sllw',
'slliw',
'srlw',
'srliw',
'sraw',
'sraiw',
'slld',
'sllid',
'srld',
'srlid',
'srad',
'sraid',
// d) Arithmetic
// I) RV32I
'add',
'addi',
'sub',
'lui',
'auipc',
// II) RV64I and RV128I
'addw',
'addiw',
'subw',
'addd',
'addid',
'subd',
// e) Logical
'xor',
'xori',
'or',
'ori',
'and',
'andi',
// f) Compare
'slt',
'slti',
'sltu',
'sltiu',
// g) Branches
'beq',
'bne',
'blt',
'bge',
'bltu',
'bgeu',
// h) Jump & Link
'jal',
'jalr',
// i) Synch
'fence',
'fence.i',
// j) System
'scall',
'sbreak',
// k) Counters
'rdcycle',
'rdcycleh',
'rdtime',
'rdtimeh',
'rdinstret',
'rdinstreth',
// Part 2) RV Priveleged Instructions
// a) CSR Access
'csrrw',
'csrrs',
'csrrc',
'csrrwi',
'csrrsi',
'csrrci',
// b) Change Level
'ecall',
'ebreak',
'eret',
// c) Trap Redirect
'mrts',
'mrth',
'hrts',
// Part 3) Optional Multiply-Divide Instruction Extension: RVM
// a) Multiply
// I) RV32M
'mul',
'mulh',
'mulhsu',
// II) RV64M and RV128M
'mulw',
'muld',
// b) Divide
// I) RV32M
'div',
'divu',
// II) RV64M and RV128M
'divw',
'divd',
// c) Remainder
// I) RV32M
'rem',
'remu',
// II) RV64M and RV128M
'remw',
'remuw',
'remd',
'remud',
// Part 4) Pseudo Instructions
// a) Standard Pseudo Instructions
'beqz',
'bgez',
'bgt',
'bgtu',
'bgtz',
'ble',
'bleu',
'blez',
'bltz',
'bnez',
'call',
'j',
'jr',
'la',
'li',
'mv',
'neg',
'nop',
'ret',
'not',
'ret',
'seqz',
'sgtz',
'sltz',
'snez',
'tail',
// b) Non-Standard Pseudo Instructions
'seq',
'sge',
'sgeu',
'sgt',
'sgtu',
'sle',
'sleu',
'sne',
// Part 5) Optional Compressed (16-bit) Instruction Extension: RVC
// a) Loads
'c.lw',
'c.lwsp',
'c.ld',
'c.ldsp',
'c.lq',
'c.lqsp',
// b) Stores
'c.sw',
'c.swsp',
'c.sd',
'c.sdsp',
'c.sq',
'c.sqsp',
// c) Arithmetic
'c.add',
'c.addw',
'c.addi',
'c.addiw',
'c.addi16sp',
'c.addi2spn',
'c.li',
'c.lui',
'c.mv',
'c.sub',
// d) Shifts
'c.slli',
// e) Branches
'c.beqz',
'c.bnez',
// f) Jump
'c.j',
'c.jr',
// g) Jump & Link
'c.jal',
'c.jalr',
// h) System
'c.ebreak',
// Part 6) Optional Atomic Instruction Extrnsion: RVA
// a) Load
// I) RV32A
'lr.w',
// II) RV64A and RV128A
'lr.d',
'lr.q',
// b) Store
// I) RV32A
'sc.w',
// II) RV64A and RV128A
'sc.d',
'sc.q',
// c) Swap
// I) RV32A
'amoswap.w',
// II) RV64A and RV128A
'amoswap.d',
'amoswap.q',
// d) Add
// I) RV32A
'amoadd.w',
// II) RV64A and RV128A
'amoadd.d',
'amoadd.q',
// e) Logical
// I) RV32A
'amoxor.w',
'amoand.w',
'amoor.w',
// II) RV64A and RV128A
'amoxor.d',
'amoand.d',
'amoor.d',
'amoxor.q',
'amoand.q',
'amoor.q',
// f) Min\Max
// I) RV32A
'amomin.w',
'amomax.w',
'amominu.w',
'amomax.w',
// II) RV64A and RV128A
'amomin.d',
'amomax.d',
'amominu.d',
'amomax.d',
'amomin.q',
'amomax.q',
'amominu.q',
'amomax.q',
// Part 7) Optional Floating-Point Instruction Extension: RVF, RVD, & RVQ
// a) Move
// I) RV32-
'fmv.h.x',
'fmv.s.s',
'fmv.x.h',
'fmv.x.s',
// II) RV64- and RV128-
'fmv.d.x',
'fmv.q.s',
'fmv.d.h',
'fmv.q.s',
// b) Convert
// I) RV32-
'fcvt.h.w',
'fcvt.s.w',
'fcvt.d.w',
'fcvt.q.w',
'fcvt.h.wu',
'fcvt.s.wu',
'fcvt.d.wu',
'fcvt.q.wu',
'fcvt.w.h',
'fcvt.w.s',
'fcvt.w.d',
'fcvt.w.q',
'fcvt.wu.h',
'fcvt.w.s',
'fcvt.w.d',
'fcvt.w.q',
// II) RV64- and RV128-
'fcvt.h.l',
'fcvt.h.t',
'fcvt.h.lu',
'fcvt.h.tu',
'fcvt.s.l',
'fcvt.s.t',
'fcvt.s.lu',
'fcvt.s.tu',
'fcvt.d.l',
'fcvt.d.t',
'fcvt.d.lu',
'fcvt.d.tu',
'fcvt.q.l',
'fcvt.q.t',
'fcvt.q.lu',
'fcvt.q.tu',
'fcvt.l.h',
'fcvt.t.h',
'fcvt.lu.h',
'fcvt.tu.h',
'fcvt.l.s',
'fcvt.t.s',
'fcvt.lu.s',
'fcvt.tu.s',
'fcvt.l.d',
'fcvt.t.d',
'fcvt.lu.d',
'fcvt.tu.d',
'fcvt.l.q',
'fcvt.t.q',
'fcvt.lu.q',
'fcvt.tu.q',
// c) Load
'flw',
'fld',
'flq',
// d) Store
'fsw',
'fsd',
'fsq',
// e) Arithmetic
'fadd.s',
'fsub.s',
'fmul.s',
'fdiv.s',
'fsqrt.s',
'fadd.d',
'fsub.d',
'fmul.d',
'fdiv.d',
'fsqrt.d',
'fadd.q',
'fsub.q',
'fmul.q',
'fdiv.q',
'fsqrt.q',
// f) Mul-Add
'fmadd.d',
'fmsub.d',
'fnmsub.d',
'fnmadd.d',
'fmadd.d',
'fmsub.d',
'fnmsub.d',
'fnmadd.d',
'fmadd.q',
'fmsub.q',
'fnmsub.q',
'fnmadd.q',
// g) Sign Inject
'fsgnj.s',
'fsgnjn.s',
'fsgnjx.s',
'fsgnj.d',
'fsgnjn.d',
'fsgnjx.d',
'fsgnj.q',
'fsgnjn.q',
'fsgnjx.q',
// h) Min/Max
'fmin.s',
'fmax.s',
'fmin.d',
'fmax.d',
'fmin.q',
'fmax.q',
// i) Compare
'feq.s',
'flt.s',
'fle.s',
'feq.d',
'flt.d',
'fle.d',
'feq.q',
'flt.q',
'fle.q',
// j) Categorization
'fclass.s',
'fclass.d',
'fclass.q',
// k) Configuration
'frcsr',
'frrm',
'frflags',
'fscsr',
'fsrm',
'fsflags',
'fsrmi',
'fsflagsi',
],
'i'
)
// Registers
// Part 1) Actual Register Values
// Part 2) Application Binary Interface
var registers = regexFromWords(
[
// Part 1) Actual Register Values
'x0',
'x1',
'x2',
'x3',
'x4',
'x5',
'x6',
'x7',
'x8',
'x9',
'x10',
'x11',
'x12',
'x13',
'x14',
'x15',
'x16',
'x17',
'x18',
'x19',
'x20',
'x21',
'x22',
'x23',
'x24',
'x25',
'x26',
'x27',
'x28',
'x29',
'x30',
'x31',
// Part 2) Application Binary Interface
'zero',
'ra',
'sp',
'gp',
'tp',
't0',
't1',
't2',
's0',
's1',
'a0',
'a1',
'a2',
'a3',
'a4',
'a5',
'a6',
'a7',
's2',
's3',
's4',
's5',
's6',
's7',
's8',
's9',
's10',
's11',
't3',
't4',
't5',
't6',
'pc',
],
''
)
// Keywords
// Part 1) Pseudo Operations
var keywords = regexFromWords(
[
// Part 1) Pseudo Operations
'.align',
'.file',
'.globl',
'.local',
'.comm',
'.common',
'.ident',
'.section',
'.size',
'.text',
'.data',
'.rodata',
'.bss',
'.string',
'.asciz',
'.asciiz',
'.equ',
'.macro',
'.endm',
'.type',
'.option',
'.byte',
'.2byte',
'.half',
'.short',
'.4byte',
'.word',
'.long',
'.8byte',
'.dword',
'.quad',
'.dtprelword',
'.dtpreldword',
'.sleb128',
'.uleb128',
'.p2align',
'.balign',
'.zero',
'.float',
'.double',
],
'i'
)
function normal(stream, state) {
var ch = stream.next()
if (ch == '#') {
stream.skipToEnd()
return 'comment'
}
if (ch == '"' || ch == "'") {
state.cur = string(ch)
return state.cur(stream, state)
}
if (/\d/.test(ch)) {
stream.eatWhile(/[\w.%]/)
// Handle numeric labels
if (stream.peek() === ':') {
return 'variable'
}
return 'number'
}
if (/[.\w_]/.test(ch)) {
stream.eatWhile(/[\w\\\-_.]/)
return 'variable'
}
return null
}
function string(quote) {
return function (stream, state) {
var escaped = false,
ch
while ((ch = stream.next()) != null) {
if (ch == quote && !escaped) break
escaped = !escaped && ch == '\\'
}
if (!escaped) state.cur = normal
return 'string'
}
}
return {
startState: function (basecol) {
return { basecol: basecol || 0, indentDepth: 0, cur: normal }
},
token: function (stream, state) {
if (stream.eatSpace()) return null
var style = state.cur(stream, state)
var word = stream.current()
if (style == 'variable') {
if (keywords.test(word)) style = 'keyword'
else if (instructions.test(word)) style = 'builtin'
else if (registers.test(word)) style = 'variable-2'
}
return style
},
}
})
CodeMirror.defineMIME('text/riscv', 'riscv')