Repository: Decompollaborate/rabbitizer (language: python)

Issue:
vcallms is supposed to have a constant with it
but it doesn't. I tried to figure it out but I saw this and now im dead

<img width="646" alt="image" src="https://github.com/Decompollaborate/rabbitizer/assets/2985314/2aef54c9-3c33-4799-9d5e-132672de6a64">

I need to figure out how to nab the imm15

<img width="460" alt="image" src="https://github.com/Decompollaborate/rabbitizer/assets/2985314/db0d88fb-9697-4f55-90ef-303d92912e30">



Discussion / hints:

Fix patch:
diff --git a/.github/workflows/check_format.yml b/.github/workflows/check_format.yml
index 82d7126b..3fe04b70 100644
--- a/.github/workflows/check_format.yml
+++ b/.github/workflows/check_format.yml
@@ -10,9 +10,7 @@ jobs:
 
     steps:
     - name: Checkout reposistory
-      uses: actions/checkout@v3
-      with:
-        ref: ${{ github.head_ref }}
+      uses: actions/checkout@v4
 
     - name: Install dependencies
       run: sudo apt install clang-format-11
@@ -37,9 +35,7 @@ jobs:
 
     steps:
     - name: Checkout reposistory
-      uses: actions/checkout@v3
-      with:
-        ref: ${{ github.head_ref }}
+      uses: actions/checkout@v4
 
     - name: Install dependencies
       run: sudo apt install clang-tidy-11
diff --git a/.github/workflows/check_tables.yml b/.github/workflows/check_tables.yml
index 2dc2450e..d80b41d9 100644
--- a/.github/workflows/check_tables.yml
+++ b/.github/workflows/check_tables.yml
@@ -10,9 +10,7 @@ jobs:
 
     steps:
     - name: Checkout reposistory
-      uses: actions/checkout@v3
-      with:
-        ref: ${{ github.head_ref }}
+      uses: actions/checkout@v4
 
     - name: Setup Rust toolchain
       uses: actions-rs/toolchain@v1
diff --git a/.github/workflows/isolated_python_build.yml b/.github/workflows/isolated_python_build.yml
index c30dc8ad..f5b1e187 100644
--- a/.github/workflows/isolated_python_build.yml
+++ b/.github/workflows/isolated_python_build.yml
@@ -10,7 +10,7 @@ jobs:
 
     steps:
     - name: Checkout reposistory
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
 
     - name: Install dependencies
       run: sudo apt update && sudo apt install -y python3-venv
diff --git a/.github/workflows/make.yml b/.github/workflows/make.yml
index 22647a36..88f84e2d 100644
--- a/.github/workflows/make.yml
+++ b/.github/workflows/make.yml
@@ -10,7 +10,7 @@ jobs:
 
     steps:
     - name: Checkout reposistory
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
 
     - name: make
       run: make -j $(nproc) WERROR=1
diff --git a/.github/workflows/publish_crate.yml b/.github/workflows/publish_crate.yml
index 94505eb8..cfdb8113 100644
--- a/.github/workflows/publish_crate.yml
+++ b/.github/workflows/publish_crate.yml
@@ -10,7 +10,7 @@ jobs:
 
     steps:
     - name: Checkout reposistory
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
 
     - name: Setup Rust toolchain
       uses: actions-rs/toolchain@v1
diff --git a/.github/workflows/pypi_upload.yml b/.github/workflows/pypi_upload.yml
index 7a7ac31a..f8f2dc19 100644
--- a/.github/workflows/pypi_upload.yml
+++ b/.github/workflows/pypi_upload.yml
@@ -16,7 +16,7 @@ jobs:
         os: [ubuntu-latest, macos-latest, windows-latest]
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
 
       - name: Build wheels
         uses: pypa/cibuildwheel@v2.12.3
@@ -33,7 +33,7 @@ jobs:
     name: Build source distribution
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
 
       - name: Build sdist
         run: pipx run build --sdist
diff --git a/Cargo.toml b/Cargo.toml
index 27d1bd9d..a1ae6441 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,7 +4,7 @@
 [package]
 name = "rabbitizer"
 # Version should be synced with include/common/RabbitizerVersion.h
-version = "1.7.7"
+version = "1.7.8"
 edition = "2021"
 authors = ["Anghelo Carvajal <angheloalf95@gmail.com>"]
 description = "MIPS instruction decoder"
diff --git a/cplusplus/include/generated/OperandType_enum_class.hpp b/cplusplus/include/generated/OperandType_enum_class.hpp
index ccdc0f7d..34fac662 100644
--- a/cplusplus/include/generated/OperandType_enum_class.hpp
+++ b/cplusplus/include/generated/OperandType_enum_class.hpp
@@ -80,6 +80,7 @@ enum class OperandType {
     r5900_vit_postincr,
     r5900_vid_postincr,
     r5900_immediate5,
+    r5900_immediate15,
     ALL_MAX,
 };
 
diff --git a/include/common/RabbitizerConfig.h b/include/common/RabbitizerConfig.h
index f8de6bc1..b6000db4 100644
--- a/include/common/RabbitizerConfig.h
+++ b/include/common/RabbitizerConfig.h
@@ -37,7 +37,7 @@ typedef struct RabbitizerConfig_PseudoInstr {
 } RabbitizerConfig_PseudoInstr;
 
 typedef struct RabbitizerConfig_ToolchainTweaks {
-    bool treatJAsUnconditionalBranch; //! @deprecated
+    bool treatJAsUnconditionalBranch;
     /**
      * Enables a few fixes for SN64's assembler related to div/divu instructions
      *
diff --git a/include/common/RabbitizerVersion.h b/include/common/RabbitizerVersion.h
index 2b55d680..621fe612 100644
--- a/include/common/RabbitizerVersion.h
+++ b/include/common/RabbitizerVersion.h
@@ -14,7 +14,7 @@ extern "C" {
 // Header version
 #define RAB_VERSION_MAJOR 1
 #define RAB_VERSION_MINOR 7
-#define RAB_VERSION_PATCH 7
+#define RAB_VERSION_PATCH 8
 
 #define RAB_VERSION_STR RAB_STRINGIFY(RAB_VERSION_MAJOR) "." RAB_STRINGIFY(RAB_VERSION_MINOR) "." RAB_STRINGIFY(RAB_VERSION_PATCH)
 
diff --git a/include/generated/InstrDescriptor_Descriptors_array.h b/include/generated/InstrDescriptor_Descriptors_array.h
index 1a1d6bf8..dd8a085e 100644
--- a/include/generated/InstrDescriptor_Descriptors_array.h
+++ b/include/generated/InstrDescriptor_Descriptors_array.h
@@ -107,7 +107,7 @@ const RabbitizerInstrDescriptor RabbitizerInstrDescriptor_Descriptors[] = {
     [RABBITIZER_INSTR_ID_cpu_daddu] = { .operands={RAB_OPERAND_cpu_rd, RAB_OPERAND_cpu_rs, RAB_OPERAND_cpu_rt}, .instrType=RABBITIZER_INSTR_TYPE_R, .modifiesRd=true, .readsRs=true, .readsRt=true, .maybeIsMove=true },
     [RABBITIZER_INSTR_ID_cpu_dsub] = { .operands={RAB_OPERAND_cpu_rd, RAB_OPERAND_cpu_rs, RAB_OPERAND_cpu_rt}, .instrType=RABBITIZER_INSTR_TYPE_R, .modifiesRd=true, .readsRs=true, .readsRt=true },
     [RABBITIZER_INSTR_ID_cpu_dsubu] = { .operands={RAB_OPERAND_cpu_rd, RAB_OPERAND_cpu_rs, RAB_OPERAND_cpu_rt}, .instrType=RABBITIZER_INSTR_TYPE_R, .modifiesRd=true, .readsRs=true, .readsRt=true },
-    [RABBITIZER_INSTR_ID_cpu_syscall] = { .operands={RAB_OPERAND_cpu_code_lower}, .instrType=RABBITIZER_INSTR_TYPE_R },
+    [RABBITIZER_INSTR_ID_cpu_syscall] = { .operands={RAB_OPERAND_cpu_code_lower}, .instrType=RABBITIZER_INSTR_TYPE_R, .notEmittedByCompilers=true },
     [RABBITIZER_INSTR_ID_cpu_break] = { .operands={RAB_OPERAND_cpu_code}, .instrType=RABBITIZER_INSTR_TYPE_R },
     [RABBITIZER_INSTR_ID_cpu_sync] = { .operands={0}, .instrType=RABBITIZER_INSTR_TYPE_R },
     [RABBITIZER_INSTR_ID_cpu_mult] = { .operands={RAB_OPERAND_cpu_rs, RAB_OPERAND_cpu_rt}, .instrType=RABBITIZER_INSTR_TYPE_R, .readsRs=true, .readsRt=true, .modifiesHI=true, .modifiesLO=true },
@@ -644,7 +644,7 @@ const RabbitizerInstrDescriptor RabbitizerInstrDescriptor_Descriptors[] = {
     [RABBITIZER_INSTR_ID_r5900_viaddi] = { .operands={RAB_OPERAND_r5900_vit, RAB_OPERAND_r5900_vis, RAB_OPERAND_r5900_immediate5} },
     [RABBITIZER_INSTR_ID_r5900_viand] = { .operands={RAB_OPERAND_r5900_vid, RAB_OPERAND_r5900_vis, RAB_OPERAND_r5900_vit} },
     [RABBITIZER_INSTR_ID_r5900_vior] = { .operands={RAB_OPERAND_r5900_vid, RAB_OPERAND_r5900_vis, RAB_OPERAND_r5900_vit} },
-    [RABBITIZER_INSTR_ID_r5900_vcallms] = { .operands={0} },
+    [RABBITIZER_INSTR_ID_r5900_vcallms] = { .operands={RAB_OPERAND_r5900_immediate15} },
     [RABBITIZER_INSTR_ID_r5900_vcallmsr] = { .operands={RAB_OPERAND_r5900_vis} },
     [RABBITIZER_INSTR_ID_r5900_vaddax] = { .operands={RAB_OPERAND_r5900_ACCxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn}, .instrSuffix=RABINSTRSUFFIX_R5900_xyzw, .isFloat=true },
     [RABBITIZER_INSTR_ID_r5900_vadday] = { .operands={RAB_OPERAND_r5900_ACCxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn}, .instrSuffix=RABINSTRSUFFIX_R5900_xyzw, .isFloat=true },
@@ -677,7 +677,7 @@ const RabbitizerInstrDescriptor RabbitizerInstrDescriptor_Descriptors[] = {
     [RABBITIZER_INSTR_ID_r5900_vmulaq] = { .operands={RAB_OPERAND_r5900_ACCxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_Q}, .instrSuffix=RABINSTRSUFFIX_R5900_xyzw },
     [RABBITIZER_INSTR_ID_r5900_vabs] = { .operands={RAB_OPERAND_r5900_vftxyzw, RAB_OPERAND_r5900_vfsxyzw}, .instrSuffix=RABINSTRSUFFIX_R5900_xyzw, .isFloat=true },
     [RABBITIZER_INSTR_ID_r5900_vmulai] = { .operands={RAB_OPERAND_r5900_ACCxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_I}, .instrSuffix=RABINSTRSUFFIX_R5900_xyzw },
-    [RABBITIZER_INSTR_ID_r5900_vclipw] = { .operands={RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn}, .instrSuffix=RABINSTRSUFFIX_R5900_xyzw, .isFloat=true },
+    [RABBITIZER_INSTR_ID_r5900_vclipw] = { .operands={RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn}, .isFloat=true },
     [RABBITIZER_INSTR_ID_r5900_vaddaq] = { .operands={RAB_OPERAND_r5900_ACCxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_Q}, .instrSuffix=RABINSTRSUFFIX_R5900_xyzw, .isFloat=true },
     [RABBITIZER_INSTR_ID_r5900_vmaddaq] = { .operands={RAB_OPERAND_r5900_ACCxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_Q}, .instrSuffix=RABINSTRSUFFIX_R5900_xyzw, .isFloat=true },
     [RABBITIZER_INSTR_ID_r5900_vaddai] = { .operands={RAB_OPERAND_r5900_ACCxyzw, RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_I}, .instrSuffix=RABINSTRSUFFIX_R5900_xyzw, .isFloat=true },
diff --git a/include/generated/OperandType_enum.h b/include/generated/OperandType_enum.h
index 20a0c4d2..b46fd6c8 100644
--- a/include/generated/OperandType_enum.h
+++ b/include/generated/OperandType_enum.h
@@ -80,6 +80,7 @@ typedef enum RabbitizerOperandType {
     RAB_OPERAND_r5900_vit_postincr,
     RAB_OPERAND_r5900_vid_postincr,
     RAB_OPERAND_r5900_immediate5,
+    RAB_OPERAND_r5900_immediate15,
     RAB_OPERAND_ALL_MAX,
 } RabbitizerOperandType;
 
diff --git a/include/generated/OperandType_function_declarations.h b/include/generated/OperandType_function_declarations.h
index 3e38f02d..b5fdc8ca 100644
--- a/include/generated/OperandType_function_declarations.h
+++ b/include/generated/OperandType_function_declarations.h
@@ -78,5 +78,6 @@
     size_t RabbitizerOperandType_process_r5900_vit_postincr (const struct RabbitizerInstruction *self, char *dst, const char *immOverride, size_t immOverrideLength);
     size_t RabbitizerOperandType_process_r5900_vid_postincr (const struct RabbitizerInstruction *self, char *dst, const char *immOverride, size_t immOverrideLength);
     size_t RabbitizerOperandType_process_r5900_immediate5 (const struct RabbitizerInstruction *self, char *dst, const char *immOverride, size_t immOverrideLength);
+    size_t RabbitizerOperandType_process_r5900_immediate15 (const struct RabbitizerInstruction *self, char *dst, const char *immOverride, size_t immOverrideLength);
 
 #endif
diff --git a/include/generated/instrOpercandCallbacks_array.h b/include/generated/instrOpercandCallbacks_array.h
index b11e4394..05041189 100644
--- a/include/generated/instrOpercandCallbacks_array.h
+++ b/include/generated/instrOpercandCallbacks_array.h
@@ -79,6 +79,7 @@ const OperandCallback instrOpercandCallbacks[] = {
     [RAB_OPERAND_r5900_vit_postincr] = RabbitizerOperandType_process_r5900_vit_postincr,
     [RAB_OPERAND_r5900_vid_postincr] = RabbitizerOperandType_process_r5900_vid_postincr,
     [RAB_OPERAND_r5900_immediate5] = RabbitizerOperandType_process_r5900_immediate5,
+    [RAB_OPERAND_r5900_immediate15] = RabbitizerOperandType_process_r5900_immediate15,
 };
 
 #endif
diff --git a/include/instructions/RabbitizerInstructionR5900.h b/include/instructions/RabbitizerInstructionR5900.h
index 5f5db0b3..1ab6c2de 100644
--- a/include/instructions/RabbitizerInstructionR5900.h
+++ b/include/instructions/RabbitizerInstructionR5900.h
@@ -32,6 +32,7 @@ extern "C" {
 #define RAB_INSTR_R5900_GET_vid(self)                   (SHIFTR((self)->word,  6,  5))
 
 #define RAB_INSTR_R5900_GET_imm5(self)                  (SHIFTR((self)->word,  6,  5))
+#define RAB_INSTR_R5900_GET_imm15(self)                 (SHIFTR((self)->word,  6, 15))
 
 
 #define RAB_INSTR_R5900_PACK_mmi_function(word, value)  (BITREPACK((word), (value),  6,  5))
@@ -54,6 +55,7 @@ extern "C" {
 #define RAB_INSTR_R5900_PACK_vid(word, value)           (BITREPACK((word), (value),  6,  5))
 
 #define RAB_INSTR_R5900_PACK_imm5(word, value)          (BITREPACK((word), (value),  6,  5))
+#define RAB_INSTR_R5900_PACK_imm15(word, value)         (BITREPACK((word), (value),  6, 15))
 
 
 NON_NULL(1)
diff --git a/pyproject.toml b/pyproject.toml
index 2a0f4bf6..8a30466f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@
 [project]
 name = "rabbitizer"
 # Version should be synced with include/common/RabbitizerVersion.h
-version = "1.7.7"
+version = "1.7.8"
 description = "MIPS instruction decoder"
 # license = "MIT"
 readme = "README.md"
diff --git a/rabbitizer/OperandType.pyi b/rabbitizer/OperandType.pyi
index 351e106b..da8fde93 100644
--- a/rabbitizer/OperandType.pyi
+++ b/rabbitizer/OperandType.pyi
@@ -81,4 +81,5 @@ class OperandType:
     r5900_vit_postincr: Enum
     r5900_vid_postincr: Enum
     r5900_immediate5: Enum
+    r5900_immediate15: Enum
     ALL_MAX: Enum
diff --git a/rabbitizer/rabbitizer_type_Instruction.c b/rabbitizer/rabbitizer_type_Instruction.c
index bb0fc020..967cc16b 100644
--- a/rabbitizer/rabbitizer_type_Instruction.c
+++ b/rabbitizer/rabbitizer_type_Instruction.c
@@ -485,9 +485,19 @@ static PyObject *rabbitizer_type_Instruction_disassemble(PyRabbitizerInstruction
 
     disassembledSize = RabbitizerInstruction_disassemble(&self->instr, buffer, immOverride, immOverrideLength, extraLJust);
     if (disassembledSize > bufferSize) {
-        PyErr_SetString(PyExc_AssertionError, "Decoded instruction does not fit in the allocated buffer.\n"
-                                              "This will produce a memory corruption error.\n"
-                                              "This is not an user error, please report this bug.");
+        PyErr_Format(PyExc_AssertionError, "Decoded instruction does not fit in the allocated buffer.\n"
+                                           "This will produce a memory corruption error.\n"
+                                           "This is not an user error, please report this bug.\n"
+                                           "    word:              0x%x\n"
+                                           "    immOverride:       %s\n"
+                                           "    immOverrideLength: %i\n"
+                                           "    extraLJust:        %i\n"
+                                           "    bufferSize:        %zu\n"
+                                           "    disassembledSize:  %zu\n",
+                                           self->instr.word,
+                                           immOverride != NULL ? immOverride : "(nil)",
+                                           immOverrideLength,
+                                           extraLJust, bufferSize, disassembledSize);
         free(buffer);
         return NULL;
     }
@@ -641,9 +651,13 @@ static PyObject *rabbitizer_type_Instruction_repr(PyRabbitizerInstruction *self)
 
     disassembledSize = RabbitizerInstruction_disassemble(&self->instr, buffer, NULL, 0, 0);
     if (disassembledSize > bufferSize) {
-        PyErr_SetString(PyExc_AssertionError, "Decoded instruction does not fit in the allocated buffer.\n"
-                                              "This will produce a memory corruption error.\n"
-                                              "This is not an user error, please report this bug.");
+        PyErr_Format(PyExc_AssertionError, "Decoded instruction does not fit in the allocated buffer.\n"
+                                           "This will produce a memory corruption error.\n"
+                                           "This is not an user error, please report this bug.\n"
+                                           "    word:              0x%x\n"
+                                           "    bufferSize:        %zu\n"
+                                           "    disassembledSize:  %zu\n",
+                                           self->instr.word, bufferSize, disassembledSize);
         free(bufferStart);
         return NULL;
     }
diff --git a/rust/src/operand_type_enum.rs b/rust/src/operand_type_enum.rs
index d6ffa08f..f5876a2e 100644
--- a/rust/src/operand_type_enum.rs
+++ b/rust/src/operand_type_enum.rs
@@ -80,5 +80,6 @@ pub enum OperandType {
     r5900_vit_postincr,
     r5900_vid_postincr,
     r5900_immediate5,
+    r5900_immediate15,
     ALL_MAX,
 }
diff --git a/src/instructions/RabbitizerInstrDescriptor.c b/src/instructions/RabbitizerInstrDescriptor.c
index 0d45d052..3bec55b9 100644
--- a/src/instructions/RabbitizerInstrDescriptor.c
+++ b/src/instructions/RabbitizerInstrDescriptor.c
@@ -478,6 +478,9 @@ bool RabbitizerInstrDescriptor_hasOperandAlias(const RabbitizerInstrDescriptor *
 
         case RAB_OPERAND_r5900_immediate5:
             break;
+
+        case RAB_OPERAND_r5900_immediate15:
+            break;
             /* r5900 */
 
         case RAB_OPERAND_ALL_INVALID:
diff --git a/src/instructions/RabbitizerInstruction/RabbitizerInstruction.c b/src/instructions/RabbitizerInstruction/RabbitizerInstruction.c
index 3fd83ecd..6467d12d 100644
--- a/src/instructions/RabbitizerInstruction/RabbitizerInstruction.c
+++ b/src/instructions/RabbitizerInstruction/RabbitizerInstruction.c
@@ -425,6 +425,10 @@ void RabbitizerInstruction_blankOut(RabbitizerInstruction *self) {
             case RAB_OPERAND_r5900_immediate5:
                 self->word = RAB_INSTR_R5900_PACK_imm5(self->word, 0);
                 break;
+
+            case RAB_OPERAND_r5900_immediate15:
+                self->word = RAB_INSTR_R5900_PACK_imm15(self->word, 0);
+                break;
                 /* r5900 */
 
             case RAB_OPERAND_ALL_INVALID:
diff --git a/src/instructions/RabbitizerInstruction/RabbitizerInstruction_Disassemble.c b/src/instructions/RabbitizerInstruction/RabbitizerInstruction_Disassemble.c
index 500fa812..2492a9e8 100644
--- a/src/instructions/RabbitizerInstruction/RabbitizerInstruction_Disassemble.c
+++ b/src/instructions/RabbitizerInstruction/RabbitizerInstruction_Disassemble.c
@@ -145,9 +145,12 @@ size_t RabbitizerInstruction_getSizeForBuffer(const RabbitizerInstruction *self,
 
         if (RabbitizerConfig_Cfg.misc.unknownInstrComment) {
             totalSize += 40;
-            totalSize += 3;
+            totalSize += 3; // " # "
             totalSize += RabbitizerInstruction_getSizeForBufferInstrDisasm(self, immOverrideLength, extraLJust);
-            totalSize += 11;
+            totalSize += strlen(" # 00000000"); // " # %08X"
+
+            totalSize += strlen(" <InstrIdType: %s>");
+            totalSize += strlen(RabInstrIdType_getName(self->instrIdType));
         }
         return totalSize;
     }
diff --git a/src/instructions/RabbitizerInstruction/RabbitizerInstruction_Examination.c b/src/instructions/RabbitizerInstruction/RabbitizerInstruction_Examination.c
index e17004ce..e5f3491e 100644
--- a/src/instructions/RabbitizerInstruction/RabbitizerInstruction_Examination.c
+++ b/src/instructions/RabbitizerInstruction/RabbitizerInstruction_Examination.c
@@ -474,6 +474,10 @@ uint32_t RabbitizerInstruction_getValidBits(const RabbitizerInstruction *self) {
             case RAB_OPERAND_r5900_immediate5:
                 validbits = RAB_INSTR_R5900_PACK_imm5(validbits, ~0);
                 break;
+
+            case RAB_OPERAND_r5900_immediate15:
+                validbits = RAB_INSTR_R5900_PACK_imm15(validbits, ~0);
+                break;
                 /* r5900 */
 
             case RAB_OPERAND_ALL_INVALID:
diff --git a/src/instructions/RabbitizerInstructionR5900/RabbitizerInstructionR5900_OperandType.c b/src/instructions/RabbitizerInstructionR5900/RabbitizerInstructionR5900_OperandType.c
index c39fbd7e..616524a0 100644
--- a/src/instructions/RabbitizerInstructionR5900/RabbitizerInstructionR5900_OperandType.c
+++ b/src/instructions/RabbitizerInstructionR5900/RabbitizerInstructionR5900_OperandType.c
@@ -15,7 +15,11 @@ size_t RabbitizerOperandType_process_r5900_I(UNUSED const RabbitizerInstruction
                                              UNUSED const char *immOverride, UNUSED size_t immOverrideLength) {
     size_t totalSize = 0;
 
-    RABUTILS_BUFFER_CPY(dst, totalSize, "I");
+    if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
+        RABUTILS_BUFFER_CPY(dst, totalSize, "$I");
+    } else {
+        RABUTILS_BUFFER_CPY(dst, totalSize, "I");
+    }
 
     return totalSize;
 }
@@ -24,7 +28,11 @@ size_t RabbitizerOperandType_process_r5900_Q(UNUSED const RabbitizerInstruction
                                              UNUSED const char *immOverride, UNUSED size_t immOverrideLength) {
     size_t totalSize = 0;
 
-    RABUTILS_BUFFER_CPY(dst, totalSize, "Q");
+    if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
+        RABUTILS_BUFFER_CPY(dst, totalSize, "$Q");
+    } else {
+        RABUTILS_BUFFER_CPY(dst, totalSize, "Q");
+    }
 
     return totalSize;
 }
@@ -33,7 +41,11 @@ size_t RabbitizerOperandType_process_r5900_R(UNUSED const RabbitizerInstruction
                                              UNUSED const char *immOverride, UNUSED size_t immOverrideLength) {
     size_t totalSize = 0;
 
-    RABUTILS_BUFFER_CPY(dst, totalSize, "R");
+    if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
+        RABUTILS_BUFFER_CPY(dst, totalSize, "$R");
+    } else {
+        RABUTILS_BUFFER_CPY(dst, totalSize, "R");
+    }
 
     return totalSize;
 }
@@ -42,7 +54,11 @@ size_t RabbitizerOperandType_process_r5900_ACC(UNUSED const RabbitizerInstructio
                                                UNUSED const char *immOverride, UNUSED size_t immOverrideLength) {
     size_t totalSize = 0;
 
-    RABUTILS_BUFFER_CPY(dst, totalSize, "ACC");
+    if (RabbitizerConfig_Cfg.toolchainTweaks.gnuMode) {
+        RABUTILS_BUFFER_CPY(dst, totalSize, "$ACC");
+    } else {
+        RABUTILS_BUFFER_CPY(dst, totalSize, "ACC");
+    }
 
     return totalSize;
 }
@@ -455,3 +471,37 @@ size_t RabbitizerOperandType_process_r5900_immediate5(const RabbitizerInstructio
     }
     return totalSize;
 }
+
+size_t RabbitizerOperandType_process_r5900_immediate15(const RabbitizerInstruction *self, char *dst,
+                                                       const char *immOverride, size_t immOverrideLength) {
+    size_t totalSize = 0;
+    int32_t number;
+
+    if ((immOverride != NULL) && (immOverrideLength > 0)) {
+        memcpy(dst, immOverride, immOverrideLength);
+        return immOverrideLength;
+    }
+
+    number = RAB_INSTR_R5900_GET_imm15(self) * 8;
+    if (RabbitizerConfig_Cfg.misc.omit0XOnSmallImm) {
+        if (number > -10 && number < 10) {
+            RABUTILS_BUFFER_SPRINTF(dst, totalSize, "%i", number);
+            return totalSize;
+        }
+    }
+    if (number < 0) {
+        if (RabbitizerConfig_Cfg.misc.upperCaseImm) {
+            RABUTILS_BUFFER_SPRINTF(dst, totalSize, "-0x%X", -number);
+        } else {
+            RABUTILS_BUFFER_SPRINTF(dst, totalSize, "-0x%x", -number);
+        }
+    } else {
+        if (RabbitizerConfig_Cfg.misc.upperCaseImm) {
+            RABUTILS_BUFFER_SPRINTF(dst, totalSize, "0x%X", number);
+        } else {
+            RABUTILS_BUFFER_SPRINTF(dst, totalSize, "0x%x", number);
+        }
+    }
+
+    return totalSize;
+}
diff --git a/tables/tables/instr_id/cpu/cpu_special.inc b/tables/tables/instr_id/cpu/cpu_special.inc
index 1d086ad1..c10af371 100644
--- a/tables/tables/instr_id/cpu/cpu_special.inc
+++ b/tables/tables/instr_id/cpu/cpu_special.inc
@@ -387,7 +387,8 @@
     RABBITIZER_DEF_INSTR_ID(
         cpu, 0x0C, syscall,
         .operands={RAB_OPERAND_cpu_code_lower},
-        .instrType=RABBITIZER_INSTR_TYPE_R
+        .instrType=RABBITIZER_INSTR_TYPE_R,
+        .notEmittedByCompilers=true
     ) // SYStem CALL
     RABBITIZER_DEF_INSTR_ID(
         cpu, 0x0D, break,
diff --git a/tables/tables/instr_id/r5900/r5900_cop2_special1.inc b/tables/tables/instr_id/r5900/r5900_cop2_special1.inc
index a59dd60f..b0931ac6 100644
--- a/tables/tables/instr_id/r5900/r5900_cop2_special1.inc
+++ b/tables/tables/instr_id/r5900/r5900_cop2_special1.inc
@@ -332,10 +332,9 @@
         .operands={RAB_OPERAND_r5900_vid, RAB_OPERAND_r5900_vis, RAB_OPERAND_r5900_vit}
     ) // Integer OR
 
-    // TODO: operands and properties
     RABBITIZER_DEF_INSTR_ID(
         r5900, 0x38, vcallms,
-        .operands={0}
+        .operands={RAB_OPERAND_r5900_immediate15}
     )
     RABBITIZER_DEF_INSTR_ID(
         r5900, 0x39, vcallmsr,
diff --git a/tables/tables/instr_id/r5900/r5900_cop2_special2.inc b/tables/tables/instr_id/r5900/r5900_cop2_special2.inc
index b8edbced..b57d68c8 100644
--- a/tables/tables/instr_id/r5900/r5900_cop2_special2.inc
+++ b/tables/tables/instr_id/r5900/r5900_cop2_special2.inc
@@ -216,7 +216,6 @@ Note: opcode is flo | (
     RABBITIZER_DEF_INSTR_ID(
         r5900, 0x1F, vclipw,
         .operands={RAB_OPERAND_r5900_vfsxyzw, RAB_OPERAND_r5900_vftn},
-        .instrSuffix=RABINSTRSUFFIX_R5900_xyzw,
         .isFloat=true
     ) // Clip
 
diff --git a/tables/tables/operands/RabbitizerOperandType_r5900.inc b/tables/tables/operands/RabbitizerOperandType_r5900.inc
index a5896648..9b60b939 100644
--- a/tables/tables/operands/RabbitizerOperandType_r5900.inc
+++ b/tables/tables/operands/RabbitizerOperandType_r5900.inc
@@ -31,3 +31,4 @@
     RAB_DEF_OPERAND(r5900, vit_postincr)
     RAB_DEF_OPERAND(r5900, vid_postincr)
     RAB_DEF_OPERAND(r5900, immediate5)
+    RAB_DEF_OPERAND(r5900, immediate15)


Test patch:
diff --git a/tests/asm/r5900/Makefile b/tests/asm/r5900/Makefile
new file mode 100644
index 00000000..11e94d52
--- /dev/null
+++ b/tests/asm/r5900/Makefile
@@ -0,0 +1,5 @@
+CROSS := mips-linux-gnu-
+AS    := $(CROSS)as
+
+%.o: %.s
+	$(AS) -march=r5900 -mabi=eabi -o $@ $^
diff --git a/tests/asm/r5900/vcallms.s b/tests/asm/r5900/vcallms.s
new file mode 100644
index 00000000..6a31ae02
--- /dev/null
+++ b/tests/asm/r5900/vcallms.s
@@ -0,0 +1,22 @@
+.set noreorder
+
+.section .text
+
+.global vcallms_test
+vcallms_test:
+.ent vcallms_test
+    vcallms 0x0000
+    vcallms 0x0800
+    vcallms 0x1000
+    vcallms 0x1100
+    vcallms 0x1200
+    vcallms 0x1300
+    vcallms 0x1400
+    vcallms 0xFFF8
+    vcallms 0x10000
+    vcallms 0x3F000
+    vcallms 0x3FFF0
+    jr $ra
+    nop
+
+.end vcallms_test
diff --git a/tests/c/build_info_checks/version_number.c b/tests/c/build_info_checks/version_number.c
index e4f18a87..5b9adf4e 100644
--- a/tests/c/build_info_checks/version_number.c
+++ b/tests/c/build_info_checks/version_number.c
@@ -19,14 +19,29 @@ const char *const tomlPaths[] = {
 };
 
 
+// returns negative value on error
 long getFileSize(FILE *file) {
     long current = ftell(file);
     long totalSize;
+    int temp;
 
-    fseek(file, 0L, SEEK_END);
+    if (current == -1L) {
+        return -1;
+    }
+
+    temp = fseek(file, 0L, SEEK_END);
+    if (temp != 0) {
+        return -1;
+    }
     totalSize = ftell(file);
+    if (totalSize == -1L) {
+        return -1;
+    }
 
-    fseek(file, current, SEEK_SET);
+    temp = fseek(file, current, SEEK_SET);
+    if (temp != 0) {
+        return -1;
+    }
 
     return totalSize;
 }
@@ -85,6 +100,13 @@ int main() {
         }
 
         fileSize = getFileSize(file);
+        if (fileSize < 0) {
+            fclose(file);
+            fprintf(stderr, "Failed to get the size of file '%s'\n", path);
+            errorCount++;
+            continue;
+        }
+
         buffer = malloc(fileSize * sizeof(char));
         if (buffer == NULL) {
             fclose(file);
diff --git a/tests/c/instruction_checks/r5900_vcallms.c b/tests/c/instruction_checks/r5900_vcallms.c
new file mode 100644
index 00000000..e77467d5
--- /dev/null
+++ b/tests/c/instruction_checks/r5900_vcallms.c
@@ -0,0 +1,70 @@
+/* SPDX-FileCopyrightText: © 2023 Decompollaborate */
+/* SPDX-License-Identifier: MIT */
+
+#include "rabbitizer.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+size_t strlen_null(const char *string) {
+    if (string == NULL) {
+        return 0;
+    }
+    return strlen(string);
+}
+
+typedef struct TestEntry {
+    uint32_t word;
+    const char *immOverride;
+    const char *expectedStr;
+} TestEntry;
+
+const TestEntry entries[] = {
+    { 0x4A000038, NULL, "vcallms     0x0" },
+    { 0x4A004038, NULL, "vcallms     0x800" },
+    { 0x4A008038, NULL, "vcallms     0x1000" },
+    { 0x4A008838, NULL, "vcallms     0x1100" },
+    { 0x4A009038, NULL, "vcallms     0x1200" },
+    { 0x4A009838, NULL, "vcallms     0x1300" },
+    { 0x4A00a038, NULL, "vcallms     0x1400" },
+    { 0x4A07FFF8, NULL, "vcallms     0xFFF8" },
+    { 0x4A080038, NULL, "vcallms     0x10000" },
+    { 0x4A1F8038, NULL, "vcallms     0x3F000" },
+    { 0x4A1FFFB8, NULL, "vcallms     0x3FFF0" },
+};
+
+int main() {
+    int errorCount = 0;
+    size_t i;
+
+    for (i = 0; i < ARRAY_COUNT(entries); i++) {
+        const TestEntry *entry = &entries[i];
+        RabbitizerInstruction instr;
+        char *buffer;
+        size_t bufferSize;
+        size_t immOverrideLength = strlen_null(entry->immOverride);
+
+        RabbitizerInstructionR5900_init(&instr, entry->word, 0);
+        RabbitizerInstructionR5900_processUniqueId(&instr);
+
+        bufferSize = RabbitizerInstruction_getSizeForBuffer(&instr, immOverrideLength, 0);
+        buffer = malloc(bufferSize + 1);
+        assert(buffer != NULL);
+
+        RabbitizerInstruction_disassemble(&instr, buffer, entry->immOverride, immOverrideLength, 0);
+
+        if (entry->expectedStr == NULL) {
+            printf("Word '0x%08X' doesn't have a expected str, got '%s'\n", entry->word, buffer);
+            errorCount++;
+        } else if (strcmp(buffer, entry->expectedStr) != 0) {
+            fprintf(stderr, "Error on word '0x%08X'. Expected '%s', got '%s'\n", entry->word, entry->expectedStr, buffer);
+            errorCount++;
+        }
+
+        free(buffer);
+        RabbitizerInstructionR5900_destroy(&instr);
+    }
+
+    return errorCount;
+}
diff --git a/tests/run_instruction_checks.sh b/tests/run_instruction_checks.sh
index f7203a5b..75bde261 100755
--- a/tests/run_instruction_checks.sh
+++ b/tests/run_instruction_checks.sh
@@ -9,3 +9,4 @@ set -e
 ./build/tests/c/instruction_checks/plain_disassembly.elf
 ./build/tests/c/instruction_checks/r3000gte_disasm.elf
 ./build/tests/c/instruction_checks/r5900_trunc_cvt.elf
+./build/tests/c/instruction_checks/r5900_vcallms.elf