Справица:DiagramGenerator/microcode.js — разлика између измена
Пређи на навигацију
Пређи на претрагу
(Modul za parsiranje mikrokoda) |
м (Prijavljivanje više od jedne greške u parsiranju i korišćenje sistemskih poruka) |
||
| Ред 165: | Ред 165: | ||
address: parseAddress(preparedLine), | address: parseAddress(preparedLine), | ||
comment: comment, | comment: comment, | ||
errors: [], | |||
line: line | line: line | ||
}; | }; | ||
| Ред 192: | Ред 193: | ||
// Check for multiple branches. | // Check for multiple branches. | ||
if (isBranch && hadBranch) { | if (isBranch && hadBranch) { | ||
instruction.error | instruction.errors.push(lib.msg('error-more-1-cond')); | ||
} else if (isBranch) { | } else if (isBranch) { | ||
hadBranch = true; | hadBranch = true; | ||
| Ред 209: | Ред 210: | ||
res = CONDITIONAL_BRANCH.exec(arg); | res = CONDITIONAL_BRANCH.exec(arg); | ||
if (!res) { | if (!res) { | ||
instruction.error | instruction.errors.push(lib.msg('error-invalid-cond-branch')); | ||
return; | return; | ||
} | } | ||
| Ред 217: | Ред 218: | ||
instruction.condition = complement + splitCondition[splitCondition.length - 1]; | instruction.condition = complement + splitCondition[splitCondition.length - 1]; | ||
if (!conditionsLowercase.includes(instruction.condition)) { | if (!conditionsLowercase.includes(instruction.condition)) { | ||
instruction.error | instruction.errors.push(lib.msg('error-unknown-condition', instruction.condition)); | ||
return; | return; | ||
} | } | ||
| Ред 225: | Ред 226: | ||
res = UNCONDITIONAL_BRANCH.exec(arg); | res = UNCONDITIONAL_BRANCH.exec(arg); | ||
if (!res) { | if (!res) { | ||
instruction.error | instruction.errors.push(lib.msg('error-invalid-uncond-branch')); | ||
return; | return; | ||
} | } | ||
| Ред 232: | Ред 233: | ||
// TODO: Destination validation | // TODO: Destination validation | ||
} else { | } else { | ||
instruction.error | instruction.errors.push(lib.msg('error-unknown-operation', arg)); | ||
} | } | ||
}); | }); | ||
| Ред 244: | Ред 245: | ||
var lines = contents.split('\n'); | var lines = contents.split('\n'); | ||
var labels = {}; | var labels = {}; | ||
var errors = []; | |||
for (var i = 0, l = lines.length; i < l; ++i) { | for (var i = 0, l = lines.length; i < l; ++i) { | ||
var line = lines[i].trim(); | var line = lines[i].trim(); | ||
| Ред 257: | Ред 259: | ||
var label = instruction.labels[j]; | var label = instruction.labels[j]; | ||
if (labels[label]) { | if (labels[label]) { | ||
instruction. | instruction.errors.push(lib.msg('duplicate-label', label)); | ||
break; | break; | ||
} | } | ||
labels[label] = instruction.address; | labels[label] = instruction.address; | ||
} | } | ||
if (instruction. | if (instruction.errors.length > 0) { | ||
errors = errors.concat(instruction.errors.map(function(lineNum, error) { | |||
error | return lib.msg('error-microcode', error, lineNum); | ||
}; | }.bind(null, i + 1))); | ||
errors.push(); | |||
} else { | |||
instructions.push(instruction); | |||
} | } | ||
} | } | ||
} | } | ||
return { | return { | ||
errors: errors, | |||
result: instructions | result: instructions | ||
}; | }; | ||
Тренутна верзија на датум 4. фебруар 2023. у 22:31
/* eslint {"max-statements": ["error", 40]} */
(function() {
'use strict';
var lib = mw.libs.diagramGenerator;
var signals = [
'MOST1_2',
'MOST1_3',
'MOST2_1',
'MOST3_2',
'rdCPU',
'wrCPU',
'ldMDR',
'mxMDR',
'MDRout1',
'eMDR',
'ldMAR',
'incMAR',
'eMAR',
'ldDWL',
'ldDWH',
'DWout2',
'wrGPR',
'GPRout1',
'ldGPRAR',
'incGPRAR',
'ldSP',
'SPout2',
'incSP',
'decSP',
'ldCW',
'CWout3',
'ADDout2',
'ldPC',
'incPC',
'PCHout3',
'PCLout3',
'PCout1',
'ldIR0',
'ldIR1',
'ldIR2',
'ldIR3',
'IRPOMout3',
'IRJAout2',
'IRDAout3',
'IRBRout3',
'add',
'sub',
'inc',
'dec',
'and',
'or',
'xor',
'not',
'ALUout1',
'ldAB',
'ABout3',
'shr',
'shl',
'ldBB',
'BBout2',
'ldAW',
'AWout3',
'AWHout3',
'ldBW',
'BWout2',
'ldPSWH',
'ldPSWL',
'ldN',
'ldZ',
'ldC',
'ldV',
'ldL',
'stPSWI',
'clPSWI',
'stPSWT',
'clPSWT',
'PSWHout3',
'PSWLout3',
'clSTART',
'ldIMR',
'IMRout2',
'ldBR',
'IVTDSPout3',
'ldIVTP',
'IVTPout1',
'UINTout3',
'UEXTout3',
'stPRCOD',
'stPRADR',
'stPRINS',
'clPRCOD',
'clPRADR',
'clPRINS',
'clPRINM',
'clINTR',
'stPSWR',
'clPSWR'
];
var BranchType = {
NONE: 'none',
CONDITIONAL: 'conditional',
UNCONDITIONAL: 'unconditional',
BRADR: 'bradr',
BROPR: 'bropr'
};
var CONDITIONAL_BRANCH = /^br\s*\(\s*if\s+(\S+)\s+then\s+(\S+)\s*\)$/;
var UNCONDITIONAL_BRANCH = /^br\s+(\S+)$/;
function prepareLine(line) {
return line
.toLowerCase()
.replace(/\(/g, ' ( ')
.replace(/\)/g, ' ) ')
.replace(/\s+/g, ' ')
.replace(/if !/g, 'if #')
.replace(/(.*?)!.*/g, '$1')
.replace(/(.*?);.*/, '$1')
.replace(/\t/g, ' ')
.replace(/\s+:/g, ': ')
.replace(/\s+/g, ' ')
.trim();
}
function parseAddress(line) {
if (line === '') {
return -1;
}
var addressLine = line.split(' ')[0];
if (addressLine.endsWith(':') || !addressLine.startsWith('madr')) {
return -1;
}
var address = parseInt(addressLine.substring(4), 16);
if (isNaN(address)) {
return -1;
}
return address;
}
function parseLabels(line) {
var labels = [];
var splitLine = line.split(' ');
for (var i = 0, l = splitLine.length; i < l; ++i) {
if (!splitLine[i].endsWith(':')) {
break;
}
var label = splitLine[i].slice(0, -1);
if (!labels.includes(label)) {
labels.push(label);
}
}
return labels;
}
function fixSignalNames(signalsToFix) {
return signalsToFix.map(function(signal) {
return signals.find(function(signal2) {
return signal.toLowerCase() === signal2.toLowerCase();
}) || signal;
});
}
function parseLine(comment, line, config) {
var preparedLine = prepareLine(line);
var instruction = {
address: parseAddress(preparedLine),
comment: comment,
errors: [],
line: line
};
var unparsedLine = preparedLine;
if (instruction.address >= 0) {
unparsedLine = unparsedLine.split(' ').slice(1).join(' ');
}
instruction.labels = parseLabels(unparsedLine);
instruction.signals = [];
instruction.branchType = BranchType.NONE;
unparsedLine = unparsedLine.split(' ').slice(instruction.labels.length).join(' ');
var hadBranch = false;
var conditionsLowercase = lib.parseConditions(config).map(function(condition) {
return condition.toLowerCase();
});
unparsedLine.split(',').map(function(segment) {
return segment.trim();
}).forEach(function(arg) {
var isBropr = arg === 'bropr';
var isBradr = arg === 'bradr';
var isAddressBranch = arg.includes('br ');
var isConditional = arg.includes('if ');
var isBranch = isBropr || isBradr || isAddressBranch;
var isSignal = signals.find(function(signal) {
return signal.toLowerCase() === arg;
});
// Check for multiple branches.
if (isBranch && hadBranch) {
instruction.errors.push(lib.msg('error-more-1-cond'));
} else if (isBranch) {
hadBranch = true;
}
// Set relevant instruction fields.
var res;
if (isSignal) {
if (!instruction.signals.includes(arg)) {
instruction.signals.push(arg);
}
} else if (isBropr) {
instruction.branchType = BranchType.BROPR;
} else if (isBradr) {
instruction.branchType = BranchType.BRADR;
} else if (isBranch && isConditional) {
res = CONDITIONAL_BRANCH.exec(arg);
if (!res) {
instruction.errors.push(lib.msg('error-invalid-cond-branch'));
return;
}
instruction.branchType = BranchType.CONDITIONAL;
var splitCondition = res[1].split('.');
var complement = res[1].startsWith('#') && splitCondition.length > 1 ? '#' : '';
instruction.condition = complement + splitCondition[splitCondition.length - 1];
if (!conditionsLowercase.includes(instruction.condition)) {
instruction.errors.push(lib.msg('error-unknown-condition', instruction.condition));
return;
}
instruction.destination = res[2];
// TODO: Destination validation
} else if (isBranch && !isConditional) {
res = UNCONDITIONAL_BRANCH.exec(arg);
if (!res) {
instruction.errors.push(lib.msg('error-invalid-uncond-branch'));
return;
}
instruction.branchType = BranchType.UNCONDITIONAL;
instruction.destination = res[1];
// TODO: Destination validation
} else {
instruction.errors.push(lib.msg('error-unknown-operation', arg));
}
});
instruction.signals = fixSignalNames(instruction.signals);
return instruction;
}
function getInstructions(config, contents) {
var instructions = [];
var comment = '';
var lines = contents.split('\n');
var labels = {};
var errors = [];
for (var i = 0, l = lines.length; i < l; ++i) {
var line = lines[i].trim();
if (!line) {
continue;
}
if (line.startsWith('!')) {
comment = line;
} else {
var instruction = parseLine(comment, line, config);
comment = '';
for (var j = 0, l2 = instruction.labels.length; j < l2; ++j) {
var label = instruction.labels[j];
if (labels[label]) {
instruction.errors.push(lib.msg('duplicate-label', label));
break;
}
labels[label] = instruction.address;
}
if (instruction.errors.length > 0) {
errors = errors.concat(instruction.errors.map(function(lineNum, error) {
return lib.msg('error-microcode', error, lineNum);
}.bind(null, i + 1)));
errors.push();
} else {
instructions.push(instruction);
}
}
}
return {
errors: errors,
result: instructions
};
}
window.mw = $.extend(true, window.mw, {
libs: {
diagramGenerator: {
BranchType: BranchType,
getInstructions: getInstructions
}
}
});
})();