Mercurial > p > unluac > hgcode
changeset 529:dfb89dc8cc21
Disassembler preserves data in unused ops
(except 5.0 with incomplete bitfield coverage -- should I care?)
author | tehtmi |
---|---|
date | Tue, 04 Mar 2025 21:23:40 -0800 |
parents | 7f0adf71d57c |
children | bda008aa963b |
files | src/unluac/decompile/CodeExtract.java src/unluac/decompile/Op.java |
diffstat | 2 files changed, 80 insertions(+), 43 deletions(-) [+] |
line wrap: on
line diff
--- a/src/unluac/decompile/CodeExtract.java Tue Mar 04 02:09:07 2025 -0800 +++ b/src/unluac/decompile/CodeExtract.java Tue Mar 04 21:23:40 2025 -0800 @@ -4,13 +4,24 @@ public class CodeExtract { -public static class Field { - - public Field(int size, int shift) { - this(size, shift, 0); + public static final int BITFIELD_OPCODE = 1; + public static final int BITFIELD_A = 2; + public static final int BITFIELD_B = 4; + public static final int BITFIELD_C = 8; + public static final int BITFIELD_K = 16; + + public static final int BITFIELD_BX = BITFIELD_B | BITFIELD_C | BITFIELD_K; + public static final int BITFIELD_AX = BITFIELD_A | BITFIELD_B | BITFIELD_C | BITFIELD_K; + public static final int BITFIELD_X = BITFIELD_OPCODE | BITFIELD_A | BITFIELD_B | BITFIELD_C | BITFIELD_K; + + public static class Field { + + public Field(int slot, int size, int shift) { + this(slot, size, shift, 0); } - public Field(int size, int shift, int offset) { + public Field(int slot, int size, int shift, int offset) { + this.slot = slot; this.size = size; this.shift = shift; this.mask = size_to_mask(size); @@ -41,6 +52,17 @@ return mask << shift; } + public String defaultname() { + switch(slot) { + case BITFIELD_A: return "a"; + case BITFIELD_B: return "b"; + case BITFIELD_C: return "c"; + case BITFIELD_K: return "k"; + default: throw new IllegalStateException(); + } + } + + public final int slot; public final int size; private final int shift; private final int mask; @@ -51,40 +73,40 @@ public CodeExtract(Version version, int sizeOp, int sizeA, int sizeB, int sizeC) { switch(version.instructionformat.get()) { case LUA50: - op = new Field(sizeOp, 0); - A = new Field(sizeA, sizeB + sizeC + sizeOp); - B = new Field(sizeB, sizeB + sizeOp); - C = new Field(sizeC, sizeOp); + op = new Field(BITFIELD_OPCODE, sizeOp, 0); + A = new Field(BITFIELD_A, sizeA, sizeB + sizeC + sizeOp); + B = new Field(BITFIELD_B, sizeB, sizeB + sizeOp); + C = new Field(BITFIELD_C, sizeC, sizeOp); k = null; Ax = null; sJ = null; - Bx = new Field(sizeB + sizeC, sizeOp); - sBx = new Field(sizeB + sizeC, sizeOp, size_to_mask(sizeB + sizeC) / 2); - x = new Field(32, 0); + Bx = new Field(BITFIELD_BX, sizeB + sizeC, sizeOp); + sBx = new Field(BITFIELD_BX, sizeB + sizeC, sizeOp, size_to_mask(sizeB + sizeC) / 2); + x = new Field(BITFIELD_X, 32, 0); break; case LUA51: - op = new Field(6, 0); - A = new Field(8, 6); - B = new Field(9, 23); - C = new Field(9, 14); + op = new Field(BITFIELD_OPCODE, 6, 0); + A = new Field(BITFIELD_A, 8, 6); + B = new Field(BITFIELD_B, 9, 23); + C = new Field(BITFIELD_C, 9, 14); k = null; - Ax = new Field(26, 6); + Ax = new Field(BITFIELD_AX, 26, 6); sJ = null; - Bx = new Field(18, 14); - sBx = new Field(18, 14, 131071); - x = new Field(32, 0); + Bx = new Field(BITFIELD_BX, 18, 14); + sBx = new Field(BITFIELD_BX, 18, 14, 131071); + x = new Field(BITFIELD_X, 32, 0); break; case LUA54: - op = new Field(7, 0); - A = new Field(8, 7); - B = new Field(8, 16); - C = new Field(8, 24); - k = new Field(1, 15); - Ax = new Field(25, 7); - sJ = new Field(25, 7, (1 << 24) - 1); - Bx = new Field(17, 15); - sBx = new Field(17, 15, (1 << 16) - 1); - x = new Field(32, 0); + op = new Field(BITFIELD_OPCODE, 7, 0); + A = new Field(BITFIELD_A, 8, 7); + B = new Field(BITFIELD_B, 8, 16); + C = new Field(BITFIELD_C, 8, 24); + k = new Field(BITFIELD_K, 1, 15); + Ax = new Field(BITFIELD_AX, 25, 7); + sJ = new Field(BITFIELD_AX, 25, 7, (1 << 24) - 1); + Bx = new Field(BITFIELD_BX, 17, 15); + sBx = new Field(BITFIELD_BX, 17, 15, (1 << 16) - 1); + x = new Field(BITFIELD_X, 32, 0); break; default: throw new IllegalStateException(); @@ -119,6 +141,15 @@ default: throw new IllegalStateException("Unhandled field: " + f); } } + + public Field get_field_for_slot(int slot) { + if((slot & BITFIELD_OPCODE) == 0) return op; + if((slot & BITFIELD_A) == 0) return A; + if((slot & BITFIELD_B) == 0) return B; + if((slot & BITFIELD_C) == 0) return C; + if((slot & BITFIELD_K) == 0) return k; // may be null, okay when checking last + return null; + } public final Field op; public final Field A;
--- a/src/unluac/decompile/Op.java Tue Mar 04 02:09:07 2025 -0800 +++ b/src/unluac/decompile/Op.java Tue Mar 04 21:23:40 2025 -0800 @@ -360,21 +360,11 @@ for(int i = 0; i < width - name.length(); i++) { b.append(' '); } + int slot = CodeExtract.BITFIELD_OPCODE; String[] parameters = new String[operands.length]; for(int i = 0; i < operands.length; ++i) { - CodeExtract.Field field; - switch(operands[i].field) { - case A: field = ex.A; break; - case B: field = ex.B; break; - case C: field = ex.C; break; - case k: field = ex.k; break; - case Ax: field = ex.Ax; break; - case sJ: field = ex.sJ; break; - case Bx: field = ex.Bx; break; - case sBx: field = ex.sBx; break; - case x: field = ex.x; break; - default: throw new IllegalStateException(); - } + CodeExtract.Field field = ex.get_field(operands[i].field); + slot |= field.slot; int x = field.extract(codepoint); switch(operands[i].format) { case IMMEDIATE_INTEGER: @@ -431,6 +421,22 @@ } b.append(parameter); } + + while(true) { + CodeExtract.Field extra = ex.get_field_for_slot(slot); + if(extra == null) break; + slot |= extra.slot; + int x = extra.extract(codepoint); + if(x != 0) { + b.append(' '); + String parameter = extra.defaultname() + "= " + fixedOperand(x); + for(int i = 0; i < 5 - parameter.length(); i++) { + b.append(' '); + } + b.append(parameter); + } + } + if(upvalue) { b.append(" ; upvalue declaration"); } else if(function != null && constant >= 0) {