11import { test } from "node:test" ;
2+ import assert from "node:assert" ;
23
34import { execSync } from "node:child_process" ;
45import { 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