Skip to content

Commit 4ca9caf

Browse files
committed
Make opcodes test more thorough
1 parent f0851c7 commit 4ca9caf

File tree

1 file changed

+30
-26
lines changed

1 file changed

+30
-26
lines changed

t/opcodes.js

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { test } from "node:test";
2+
import assert from "node:assert";
23

34
import { execSync } from "node:child_process";
45
import { readFileSync } from "node:fs";
@@ -48,7 +49,7 @@ function makeOperand(catcher, size, index, type = catcher.type) {
4849
case OPT.IMM: return value === null ? '$' + (1 << (size - 4)) : '$' + value;
4950
case OPT.MASK: return '%k' + id;
5051
case OPT.REL: return '.+' + (1 << (size - 4));
51-
case OPT.MEM: return catcher.moffset ? '' + (1 << (size - 4)) : '64(%' + regNames[24 + id] +')';
52+
case OPT.MEM: return catcher.moffset ? '' + (1 << (size - 4)) : [`1(%${regNames[24 + id]})`, "32(%rsp)", "128(%r12)"];
5253
case OPT.ST: return '%st' + (id ? '(' + id + ')' : '');
5354
case OPT.SEG: return '%' + regNames[32 + id];
5455
case OPT.IP: return size == 32 ? '%eip' : '%rip';
@@ -60,6 +61,27 @@ function makeOperand(catcher, size, index, type = catcher.type) {
6061
throw `Unknown operand type '${type}'`;
6162
}
6263

64+
function* generateInstructionVariations(mnemonic, sizeSuffix, operands, asterisk, maskRequired = false) {
65+
for(let i in operands)
66+
if(Array.isArray(operands[i])) {
67+
for(const opVar of operands[i]) {
68+
operands[i] = opVar;
69+
yield *generateInstructionVariations(mnemonic, sizeSuffix, operands, asterisk, maskRequired);
70+
}
71+
return;
72+
}
73+
74+
let prefix = "";
75+
if(sizeSuffix == 'addr32') {
76+
prefix = 'addr32 ';
77+
sizeSuffix = '';
78+
}
79+
yield prefix + mnemonic + sizeSuffix + ' '
80+
+ (asterisk ? '*' : '')
81+
+ operands.join(', ')
82+
+ (maskRequired ? ' {%k1}' : '');
83+
}
84+
6385
/**
6486
* @typedef {Object} GenConfig
6587
* @property {import('@defasm/core/mnemonics.js').MnemonicInterpretation} interp
@@ -119,11 +141,8 @@ function* generateInstrs(mnemonic, {
119141
if(operands[i] === undefined)
120142
operands[i] = makeOperand(opCatchers[i], 32, i + 1);
121143
}
122-
let instruction =
123-
mnemonic + ' ' +
124-
(mnemonic == 'lcall' || mnemonic == 'ljmp' ? '*' : '') +
125-
operands.join(', ');
126-
yield instruction;
144+
145+
yield *generateInstructionVariations(mnemonic, '', operands, mnemonic == 'lcall' || mnemonic == 'ljmp');
127146
return;
128147
}
129148
else {
@@ -184,28 +203,17 @@ function* generateInstrs(mnemonic, {
184203
if(canTryBroadcast) {
185204
if(!triedBroadcast) {
186205
if(operation.evexPermits?.BROADCAST_32)
187-
operands[i] = operands[i] + ` {1to${(size & ~7) / 32}}`;
206+
operands[i] = operands[i].map(x => x + ` {1to${(size & ~7) / 32}}`);
188207
if(operation.evexPermits?.BROADCAST_64)
189-
operands[i] = operands[i] + ` {1to${(size & ~7) / 64}}`;
208+
operands[i] = operands[i].map(x => x + ` {1to${(size & ~7) / 64}}`);
190209
triedBroadcast = true;
191210
}
192211
}
193212
canTryBroadcast = true;
194213
}
195214

196-
if(total + 1 >= opCatchers.length) {
197-
let instruction = "";
198-
if(sizeSuffix == 'addr32')
199-
{
200-
instruction += 'addr32 ';
201-
sizeSuffix = '';
202-
}
203-
instruction += mnemonic + sizeSuffix + ' ' +
204-
(interp.relative && type !== OPT.REL ? '*' : '')
205-
+ operands.join(', ')
206-
+ (operation.requireMask ? ' {%k1}' : '')
207-
yield instruction;
208-
}
215+
if(total + 1 >= opCatchers.length)
216+
yield *generateInstructionVariations(mnemonic, sizeSuffix, operands, interp.relative && type !== OPT.REL, operation.requireMask);
209217
else
210218
yield *generateInstrs(mnemonic, {
211219
interp,
@@ -283,10 +291,6 @@ test("All opcodes test", { skip: process.platform != 'linux' }, async () => {
283291
}
284292
});
285293

286-
throw `Discrepancies detected:\n${
287-
discrepancies.join('\n')
288-
}\n\n${
289-
execSync('as --version').toString()
290-
}`;
294+
assert.fail(`Discrepancies detected:\n${discrepancies.join('\n')}`);
291295
}
292296
});

0 commit comments

Comments
 (0)