Skip to content

Commit ab26660

Browse files
committed
more feature-complete for cond
1 parent fa74058 commit ab26660

5 files changed

Lines changed: 708 additions & 9 deletions

File tree

codegen/arm64_encoder.js

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ function mapOperandType(operand) {
184184
} else if (hoverLower.includes('general-purpose')) {
185185
const is64bit = hoverLower.includes('64-bit') || link.startsWith('x');
186186
return { type: 'reg', size: is64bit ? 64 : 32 };
187+
} else if (link.startsWith('cond') || link === 'nzcv') {
188+
return { type: 'imm' };
187189
} else if (link === 'imm' || link === 'amount' || link === 'shift' || link === 'extend' || link.startsWith('pimm') || link.startsWith('simm') || link.startsWith('imm')) {
188190
const match = hover.match(/\[(\d+)-(\d+)\]/);
189191
if (match) {
@@ -271,6 +273,22 @@ function findVariable(inst, name) {
271273
return inst.variables.find(v => v.name === name) || null;
272274
}
273275

276+
/**
277+
* Parse a bitdiffs string like "sf == 1 && N == 1 && imms == 111111"
278+
* into a map { sf: 1, N: 1, imms: 63 }
279+
*/
280+
function parseBitdiffs(bitdiffs) {
281+
if (!bitdiffs) return {};
282+
const result = {};
283+
const parts = bitdiffs.split('&&').map(s => s.trim());
284+
for (const part of parts) {
285+
const match = part.match(/^(\w+)\s*==\s*([01]+)$/);
286+
if (!match) continue;
287+
result[match[1]] = parseInt(match[2], 2);
288+
}
289+
return result;
290+
}
291+
274292
/**
275293
* Generate a bit mask expression for a given width
276294
* @param {number} width - Bit width
@@ -1822,7 +1840,7 @@ for (const [mnemonic, variants] of Object.entries(byMnemonic)) {
18221840
output += ` }\n`;
18231841

18241842
} else if (format === 'reg_reg_imm') {
1825-
const immVarNames = ['imm12', 'imm9', 'imm6', 'imm5', 'imm4', 'imm3', 'imm'];
1843+
const immVarNames = ['imm12', 'imm9', 'imm6', 'imm5', 'imm4', 'imm3', 'immr', 'cond', 'nzcv', 'imm'];
18261844
const immVarName = immVarNames.find(name => findVariable(inst, name));
18271845
const immVar = immVarName ? findVariable(inst, immVarName) : null;
18281846
const hasImmediateField = fields.some(field => field && field.startsWith('imm'));
@@ -1861,6 +1879,31 @@ for (const [mnemonic, variants] of Object.entries(byMnemonic)) {
18611879
if (useRuntimeCheck) {
18621880
output += ` int sf = arm64_is_64bit(dst.reg) ? 1 : 0;\n`;
18631881
output += ` instr |= (sf << 31);\n`;
1882+
1883+
// For bitfield instructions (UBFM/SBFM), additional bits differ
1884+
// between 32-bit and 64-bit variants (e.g. N bit, imms high bit).
1885+
// Parse bitdiffs to find and apply them.
1886+
const inst32entry = variantGroup.find(v => v.inst.bitdiffs && v.inst.bitdiffs.includes('sf == 0'));
1887+
const inst64entry = variantGroup.find(v => v.inst.bitdiffs && v.inst.bitdiffs.includes('sf == 1'));
1888+
if (inst32entry && inst64entry) {
1889+
const diffs32 = parseBitdiffs(inst32entry.inst.bitdiffs);
1890+
const diffs64 = parseBitdiffs(inst64entry.inst.bitdiffs);
1891+
for (const [fieldName, val64] of Object.entries(diffs64)) {
1892+
if (fieldName === 'sf') continue;
1893+
const val32 = diffs32[fieldName];
1894+
if (val32 === undefined || val32 === val64) continue;
1895+
const fieldVar = findVariable(inst, fieldName);
1896+
if (!fieldVar) continue;
1897+
const extraBits = val64 & ~val32;
1898+
if (extraBits) {
1899+
output += ` if (sf) instr |= (${extraBits}u << ${fieldVar.lo});\n`;
1900+
}
1901+
const clearBits = val32 & ~val64;
1902+
if (clearBits) {
1903+
output += ` if (sf) instr &= ~(${clearBits}u << ${fieldVar.lo});\n`;
1904+
}
1905+
}
1906+
}
18641907
} else if (has64bit) {
18651908
output += ` instr |= (1 << 31);\n`;
18661909
}
@@ -1894,6 +1937,12 @@ for (const [mnemonic, variants] of Object.entries(byMnemonic)) {
18941937
output += ` instr |= ((sh & ${bitMask(shField.width)}) << ${shField.lo});\n`;
18951938
}
18961939

1940+
// General immediate encoding: if immVar was found and not already
1941+
// handled by the imm12 special case, encode it into its field.
1942+
if (immVar && immVarName !== 'imm12') {
1943+
output += ` instr |= ((imm & ${bitMask(immVar.width)}) << ${immVar.lo});\n`;
1944+
}
1945+
18971946
output += ` cj_add_u32(ctx, instr);\n`;
18981947
output += ` return;\n`;
18991948
output += ` }\n`;
@@ -2246,7 +2295,7 @@ for (const [mnemonic, variants] of Object.entries(byMnemonic)) {
22462295
output += ` return;\n`;
22472296
output += ` }\n`;
22482297
} else if (format === 'reg_imm') {
2249-
const immVarNames = ['imm', 'imm12', 'imm9', 'imm6', 'imm5', 'imm4', 'imm3'];
2298+
const immVarNames = ['imm', 'imm12', 'imm9', 'imm6', 'imm5', 'imm4', 'imm3', 'cond', 'nzcv'];
22502299
const immVarName = immVarNames.find(name => findVariable(inst, name));
22512300
const immVar = immVarName ? findVariable(inst, immVarName) : null;
22522301
const hasImmediateField = fields.some(field => field && field.startsWith('imm'));
@@ -2266,7 +2315,7 @@ for (const [mnemonic, variants] of Object.entries(byMnemonic)) {
22662315
const parseFunc = isFP ? 'arm64_parse_fp_reg' : 'arm64_parse_reg';
22672316
const hasRdVar = !!findVariable(inst, 'Rd');
22682317
const hasRnVar = !!findVariable(inst, 'Rn');
2269-
const immField = fields.find(field => field && field.startsWith('imm'));
2318+
const immField = fields.find(field => field && (field.startsWith('imm') || field === 'cond' || field === 'nzcv'));
22702319
const immVar = immField ? findVariable(inst, immField) : null;
22712320
const hwVar = findVariable(inst, 'hw');
22722321

0 commit comments

Comments
 (0)