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) {