Add Glulxe and Git. They compile but don't work yet.
[projects/chimara/chimara.git] / interpreters / git / operands.c
diff --git a/interpreters/git/operands.c b/interpreters/git/operands.c
new file mode 100644 (file)
index 0000000..a4b6e0b
--- /dev/null
@@ -0,0 +1,307 @@
+// $Id: operands.c,v 1.11 2004/02/02 00:13:46 iain Exp $
+
+#include "git.h"
+#include <assert.h>
+
+git_uint32 parseLoad (git_uint32 * pc, LoadReg reg, int mode, TransferSize size, git_sint32 * constVal)
+{
+    git_uint32 value;
+
+    switch (mode)
+    {
+        case 0x0: // Constant zero. (Zero bytes)
+            value = 0;
+            goto load_const;
+
+        case 0x1: // Constant, -80 to 7F. (One byte)
+            value = (git_sint32) ((git_sint8) memRead8(*pc));
+            *pc += 1;
+            goto load_const;
+
+        case 0x2: // Constant, -8000 to 7FFF. (Two bytes)
+            value = (git_sint32) ((git_sint16) memRead16(*pc));
+            *pc += 2;
+            goto load_const;
+
+        case 0x3: // Constant, any value. (Four bytes)
+            value = memRead32(*pc);
+            *pc += 4;
+            goto load_const;
+
+        case 0x5: // Contents of address 00 to FF. (One byte)
+            value = memRead8(*pc);
+            *pc += 1;
+            goto load_addr;
+
+        case 0x6: // Contents of address 0000 to FFFF. (Two bytes)
+            value = memRead16(*pc);
+            *pc += 2;
+            goto load_addr;
+
+        case 0x7: // Contents of any address. (Four bytes)
+            value = memRead32(*pc);
+            *pc += 4;
+            goto load_addr;
+
+        case 0x8: // Value popped off stack. (Zero bytes)
+            goto load_stack;
+
+        case 0x9: // Call frame local at address 00 to FF. (One byte)
+            value = memRead8(*pc);
+            *pc += 1;
+            goto load_local;
+
+        case 0xA: // Call frame local at address 0000 to FFFF. (Two bytes)
+            value = memRead16(*pc);
+            *pc += 2;
+            goto load_local;
+
+        case 0xB: // Call frame local at any address. (Four bytes)
+            value = memRead32(*pc);
+            *pc += 4;
+            goto load_local;
+
+        case 0xD: // Contents of RAM address 00 to FF. (One byte)
+            value = memRead8(*pc) + gRamStart;
+            *pc += 1;
+            goto load_addr;
+
+        case 0xE: // Contents of RAM address 0000 to FFFF. (Two bytes)
+            value = memRead16(*pc) + gRamStart;
+            *pc += 2;
+            goto load_addr;
+
+        case 0xF: // Contents of RAM, any address. (Four bytes)
+            value = memRead32(*pc) + gRamStart;
+            *pc += 4;
+            goto load_addr;
+
+        default: // Illegal addressing mode
+            abortCompilation();
+            break;
+
+        // ------------------------------------------------------
+
+        load_const:
+            if (constVal)
+            {
+                *constVal = value;
+                return 1;
+            }
+            else
+            {
+                emitCode (label_L1_const + reg);
+                emitData (value);
+            }
+            break;
+
+        load_stack:
+                       emitCode (label_L1_stack + reg);
+                       break;
+
+        load_addr:
+            if (value < gRamStart)
+            {
+                if (size == size32)
+                    value = memRead32(value);
+                else if (size == size16)
+                    value = memRead16(value);
+                else
+                    value = memRead8(value);
+                               goto load_const;
+            }
+                       switch (size)
+                       {
+                               case size8:
+                                       assert (reg == reg_L1);
+                                       emitCode (label_L1_addr8);
+                                       break;
+
+                               case size16:
+                                       assert (reg == reg_L1);
+                                       emitCode (label_L1_addr16);
+                                       break;
+
+                               case size32:
+                                       emitCode (label_L1_addr + reg);
+                                       break;
+                       }
+                       emitData (value);
+                       break;
+
+        load_local:
+            emitCode (label_L1_local + reg);
+            emitData (value / 4); // Convert byte offset to word offset.
+            break;
+    }
+
+    return 0;
+}
+
+void parseStore (git_uint32 * pc, StoreReg reg, int mode, TransferSize size)
+{
+    git_uint32 value;
+
+    switch (mode)
+    {
+        case 0x0: // Discard
+            break;
+
+        case 0x5: // Contents of address 00 to FF. (One byte)
+            value = memRead8(*pc);
+            *pc += 1;
+            goto store_addr;
+
+        case 0x6: // Contents of address 0000 to FFFF. (Two bytes)
+            value = memRead16(*pc);
+            *pc += 2;
+            goto store_addr;
+
+        case 0x7: // Contents of any address. (Four bytes)
+            value = memRead32(*pc);
+            *pc += 4;
+            goto store_addr;
+
+        case 0x8: // Value popped off stack. (Zero bytes)
+            goto store_stack;
+
+        case 0x9: // Call frame local at store_address 00 to FF. (One byte)
+            value = memRead8(*pc);
+            *pc += 1;
+            goto store_local;
+
+        case 0xA: // Call frame local at store_address 0000 to FFFF. (Two bytes)
+            value = memRead16(*pc);
+            *pc += 2;
+            goto store_local;
+
+        case 0xB: // Call frame local at any store_address. (Four bytes)
+            value = memRead32(*pc);
+            *pc += 4;
+            goto store_local;
+
+        case 0xD: // Contents of RAM address 00 to FF. (One byte)
+            value = memRead8(*pc) + gRamStart;
+            *pc += 1;
+            goto store_addr;
+
+        case 0xE: // Contents of RAM address 0000 to FFFF. (Two bytes)
+            value = memRead16(*pc) + gRamStart;
+            *pc += 2;
+            goto store_addr;
+
+        case 0xF: // Contents of RAM, any address. (Four bytes)
+            value = memRead32(*pc) + gRamStart;
+            *pc += 4;
+            goto store_addr;
+
+        // ------------------------------------------------------
+
+        store_stack:
+            emitCode (reg == reg_S1 ? label_S1_stack : label_S2_stack);
+            break;
+
+        store_addr:
+            if (size == size32)
+                       {
+                emitCode (reg == reg_S1 ? label_S1_addr : label_S2_addr);
+            }
+                       else
+                       {
+                               assert (reg == reg_S1);
+                               emitCode (size == size16 ? label_S1_addr16 : label_S1_addr8);
+                       }
+            emitData (value);
+            break;
+
+        store_local:
+            emitCode (reg == reg_S1 ? label_S1_local : label_S2_local);
+            emitData (value / 4); // Convert byte offset to word offset.
+            break;
+    }
+}
+
+static void parseStub (git_uint32 * pc, int mode, Label discardOp)
+{
+    git_uint32 value;
+    switch (mode)
+    {
+        case 0x0: // Discard
+            goto store_discard;
+        case 0x5: // Contents of address 00 to FF. (One byte)
+            value = memRead8(*pc);
+            *pc += 1;
+            goto store_addr;
+        case 0x6: // Contents of address 0000 to FFFF. (Two bytes)
+            value = memRead16(*pc);
+            *pc += 2;
+            goto store_addr;
+        case 0x7: // Contents of any address. (Four bytes)
+            value = memRead32(*pc);
+            *pc += 4;
+            goto store_addr;
+        case 0x8: // Value popped off stack. (Zero bytes)
+            goto store_stack;
+        case 0x9: // Call frame local at store_address 00 to FF. (One byte)
+            value = memRead8(*pc);
+            *pc += 1;
+            goto store_local;
+        case 0xA: // Call frame local at store_address 0000 to FFFF. (Two bytes)
+            value = memRead16(*pc);
+            *pc += 2;
+            goto store_local;
+        case 0xB: // Call frame local at any store_address. (Four bytes)
+            value = memRead32(*pc);
+            *pc += 4;
+            goto store_local;
+        case 0xD: // Contents of RAM address 00 to FF. (One byte)
+            value = memRead8(*pc) + gRamStart;
+            *pc += 1;
+            goto store_addr;
+        case 0xE: // Contents of RAM address 0000 to FFFF. (Two bytes)
+            value = memRead16(*pc) + gRamStart;
+            *pc += 2;
+            goto store_addr;
+        case 0xF: // Contents of RAM, any address. (Four bytes)
+            value = memRead32(*pc) + gRamStart;
+            *pc += 4;
+            goto store_addr;
+        // ------------------------------------------------------
+        store_discard:
+            emitCode (discardOp);
+            break;
+        store_stack:
+            emitCode (discardOp + (label_call_stub_stack - label_call_stub_discard));
+            break;
+        store_addr:
+            emitCode (discardOp + (label_call_stub_addr - label_call_stub_discard));
+            emitData (value);
+            break;
+        store_local:
+            emitCode (discardOp + (label_call_stub_local - label_call_stub_discard));
+            emitData (value); // Convert byte offset to word offset.
+            break;
+    }
+    
+    // Every call stub ends with the glulx return address.
+    emitData (*pc);
+
+    // ...which means that every call stub references the next instruction.
+    nextInstructionIsReferenced ();
+}
+void parseCallStub (git_uint32 * pc, int mode)
+{
+    parseStub (pc, mode, label_call_stub_discard);
+}
+void parseCatchStub (git_uint32 * pc, int mode)
+{
+    parseStub (pc, mode, label_catch_stub_discard);
+}
+void parseSaveStub (git_uint32 * pc, int mode)
+{
+    parseStub (pc, mode, label_save_stub_discard);
+}
+void parseUndoStub (git_uint32 * pc, int mode)
+{
+    parseStub (pc, mode, label_undo_stub_discard);
+}