diff --git a/source/m3_compile.c b/source/m3_compile.c index 88372b1..7a4f77c 100644 --- a/source/m3_compile.c +++ b/source/m3_compile.c @@ -198,6 +198,11 @@ bool IsRegisterAllocated (IM3Compilation o, u32 i_register) } +bool IsRegisterTypeAllocated (IM3Compilation o, u8 i_type) +{ + return IsRegisterAllocated (o, IsFpType (i_type)); +} + void AllocateRegister (IM3Compilation o, u32 i_register, u16 i_stackIndex) { d_m3Assert (not IsRegisterAllocated (o, i_register)); o->regStackIndexPlusOne [i_register] = i_stackIndex + 1; @@ -1356,7 +1361,8 @@ _ (PreserveRegisterIfOccupied (o, type)); EmitOp (o, op); for (u32 i = 0; i < 3; i++) { - if (slots [i] != c_slotUnused) + if (IsValidSlot (slots [i])) +// if (slots [i] != c_slotUnused) EmitConstant (o, slots [i]); } _ (PushRegister (o, type)); @@ -1406,32 +1412,32 @@ M3Result Compile_Operator (IM3Compilation o, u8 i_opcode) { if (IsStackTopInRegister (o)) { - operation = op->operation_sr; + operation = op->operations [0]; } else { _ (PreserveRegisterIfOccupied (o, op->type)); - operation = op->operation_rs; + operation = op->operations [1]; } } else { if (IsStackTopInRegister (o)) { - operation = op->operation_sr; // printf ("r <- s+r\n"); + operation = op->operations [0]; // printf ("r <- s+r\n"); } else if (IsStackTopMinus1InRegister (o)) { - operation = op->operation_rs; + operation = op->operations [1]; if (not operation) // must be commutative, then - operation = op->operation_sr; + operation = op->operations [0]; // printf ("r <- r+s\n"); } else { _ (PreserveRegisterIfOccupied (o, op->type)); - operation = op->operation_ss; // printf ("r <- s+s\n"); + operation = op->operations [2]; // printf ("r <- s+s\n"); } } @@ -1439,26 +1445,47 @@ _ (PreserveRegisterIfOccupied (o, op->type)); { _ (EmitOp (o, operation)); -// if (op->type != c_m3Type_none) - { -_ (EmitTopSlotAndPop (o)); +_ (EmitTopSlotAndPop (o)); - if (op->stackOffset < 0) -_ (EmitTopSlotAndPop (o)); + if (op->stackOffset < 0) +_ (EmitTopSlotAndPop (o)); - if (op->type != c_m3Type_none) -_ (PushRegister (o, op->type)); - } + if (op->type != c_m3Type_none) +_ (PushRegister (o, op->type)); } else { - result = ErrorCompile ("no operation", o, "'%s'", op->name); + result = ErrorCompile ("no operation found for opcode", o, "'%s'", op->name); } _catch: return result; } +M3Result Compile_Convert (IM3Compilation o, u8 i_opcode) +{ + M3Result result = c_m3Err_none; + + const M3OpInfo * opInfo = & c_operations [i_opcode]; + + bool destInSlot = IsRegisterTypeAllocated (o, opInfo->type); + bool sourceInSlot = IsStackTopInSlot (o); + + IM3Operation op = opInfo->operations [destInSlot * 2 + sourceInSlot]; + +_ (EmitOp (o, op)); +_ (EmitTopSlotAndPop (o)); + + if (destInSlot) +_ (PushAllocatedSlotAndEmit (o, opInfo->type)) + else +_ (PushRegister (o, opInfo->type)) + + _catch: return result; +} + + + M3Result Compile_Load_Store (IM3Compilation o, u8 i_opcode) { M3Result result; @@ -1468,6 +1495,11 @@ M3Result Compile_Load_Store (IM3Compilation o, u8 i_opcode) _ (ReadLEB_u32 (& alignHint, & o->wasm, o->wasmEnd)); _ (ReadLEB_u32 (& offset, & o->wasm, o->wasmEnd)); m3log (compile, d_indent "%s (offset = %d)", get_indention_string (o), offset); + const M3OpInfo * op = & c_operations [i_opcode]; + + if (IsFpType (op->type)) +_ (PreserveRegisterIfOccupied (o, c_m3Type_f64)); + _ (Compile_Operator (o, i_opcode)); EmitConstant (o, offset); @@ -1475,12 +1507,13 @@ _ (Compile_Operator (o, i_opcode)); } -#define d_singleOp(OP) op_##OP, NULL, NULL // these aren't actually used by the compiler, just codepage decoding -#define d_emptyOpList() NULL, NULL, NULL -#define d_unaryOpList(TYPE, NAME) op_##TYPE##_##NAME##_r, op_##TYPE##_##NAME##_s, NULL -#define d_binOpList(TYPE, NAME) op_##TYPE##_##NAME##_sr, op_##TYPE##_##NAME##_rs, op_##TYPE##_##NAME##_ss -#define d_commutativeBinOpList(TYPE, NAME) op_##TYPE##_##NAME##_sr, NULL, op_##TYPE##_##NAME##_ss +#define d_singleOp(OP) { op_##OP, NULL, NULL, NULL } // these aren't actually used by the compiler, just codepage decoding +#define d_emptyOpList() { NULL, NULL, NULL, NULL } +#define d_unaryOpList(TYPE, NAME) { op_##TYPE##_##NAME##_r, op_##TYPE##_##NAME##_s, NULL, NULL } +#define d_binOpList(TYPE, NAME) { op_##TYPE##_##NAME##_sr, op_##TYPE##_##NAME##_rs, op_##TYPE##_##NAME##_ss, NULL } +#define d_commutativeBinOpList(TYPE, NAME) { op_##TYPE##_##NAME##_sr, NULL, op_##TYPE##_##NAME##_ss, NULL } +#define d_convertOpList(OP) { op_##OP##_r_r, op_##OP##_r_s, op_##OP##_s_r, op_##OP##_s_s } const M3OpInfo c_operations [] = { @@ -1495,7 +1528,7 @@ const M3OpInfo c_operations [] = M3OP( "end", 0, none, d_emptyOpList(), Compile_Else_End ), // 0x0b M3OP( "br", 0, none, d_singleOp (Branch), Compile_Branch ), // 0x0c - M3OP( "br_if", -1, none, op_BranchIf_r, op_BranchIf_s, NULL, Compile_Branch ), // 0x0d + M3OP( "br_if", -1, none, { op_BranchIf_r, op_BranchIf_s, NULL, NULL }, Compile_Branch ), // 0x0d M3OP( "br_table", -1, none, d_singleOp (BranchTable), Compile_BranchTable ), // 0x0e M3OP( "return", 0, any, d_singleOp (Return), Compile_Return ), // 0x0f M3OP( "call", 0, any, d_singleOp (Call), Compile_Call ), // 0x10 @@ -1666,65 +1699,59 @@ const M3OpInfo c_operations [] = M3OP( "f64.max", -1, f_64, d_commutativeBinOpList (f64, Max) ), // 0xa5 M3OP( "f64.copysign", -1, f_64, d_binOpList (f64, CopySign) ), // 0xa6 - M3OP( "i32.wrap/i64", 0, i_32, d_unaryOpList(i32, Wrap_i64) ), // 0xa7 - M3OP( "i32.trunc_s/f32", 0, i_32, d_unaryOpList(i32, Trunc_f32) ), // 0xa8 - M3OP( "i32.trunc_u/f32", 0, i_32, d_unaryOpList(u32, Trunc_f32) ), // 0xa9 - M3OP( "i32.trunc_s/f64", 0, i_32, d_unaryOpList(i32, Trunc_f64) ), // 0xaa - M3OP( "i32.trunc_u/f64", 0, i_32, d_unaryOpList(u32, Trunc_f64) ), // 0xab - - M3OP( "i64.extend_s/i32", 0, i_64, d_unaryOpList(i64, Extend_i32) ), // 0xac - M3OP( "i64.extend_u/i32", 0, i_64, d_unaryOpList(i64, Extend_u32) ), // 0xad - M3OP( "i64.trunc_s/f32", 0, i_64, d_unaryOpList(i64, Trunc_f32) ), // 0xae - M3OP( "i64.trunc_u/f32", 0, i_64, d_unaryOpList(u64, Trunc_f32) ), // 0xaf - M3OP( "i64.trunc_s/f64", 0, i_64, d_unaryOpList(i64, Trunc_f64) ), // 0xb0 - M3OP( "i64.trunc_u/f64", 0, i_64, d_unaryOpList(u64, Trunc_f64) ), // 0xb1 - - M3OP( "f32.convert_s/i32", 0, f_32, d_unaryOpList(f32, Convert_i32) ), // 0xb2 - M3OP( "f32.convert_u/i32", 0, f_32, d_unaryOpList(f32, Convert_u32) ), // 0xb3 - M3OP( "f32.convert_s/i64", 0, f_32, d_unaryOpList(f32, Convert_i64) ), // 0xb4 - M3OP( "f32.convert_u/i64", 0, f_32, d_unaryOpList(f32, Convert_u64) ), // 0xb5 - M3OP( "f32.demote/f64", 0, f_32, d_unaryOpList(f32, Demote_f64) ), // 0xb6 - - M3OP( "f64.convert_s/i32", 0, f_64, d_unaryOpList(f64, Convert_i32) ), // 0xb7 - M3OP( "f64.convert_u/i32", 0, f_64, d_unaryOpList(f64, Convert_u32) ), // 0xb8 - M3OP( "f64.convert_s/i64", 0, f_64, d_unaryOpList(f64, Convert_i64) ), // 0xb9 - M3OP( "f64.convert_u/i64", 0, f_64, d_unaryOpList(f64, Convert_u64) ), // 0xba - M3OP( "f64.promote/f32", 0, f_64, d_unaryOpList(f64, Promote_f32) ), // 0xbb - - M3OP( "i32.reinterpret/f32", 0, i_32, d_unaryOpList(i32, Reinterpret_f32) ), // 0xbc - M3OP( "i64.reinterpret/f64", 0, i_64, d_unaryOpList(i64, Reinterpret_f64) ), // 0xbd - M3OP( "f32.reinterpret/i32", 0, f_32, d_unaryOpList(f32, Reinterpret_i32) ), // 0xbe - M3OP( "f64.reinterpret/i64", 0, f_64, d_unaryOpList(f64, Reinterpret_i64) ), // 0xbf + M3OP( "i32.wrap/i64", 0, i_32, d_unaryOpList (i32, Wrap_i64) ), // 0xa7 + M3OP( "i32.trunc_s/f32", 0, i_32, d_convertOpList (i32_Trunc_f32), Compile_Convert ), // 0xa8 + M3OP( "i32.trunc_u/f32", 0, i_32, d_convertOpList (u32_Trunc_f32), Compile_Convert ), // 0xa9 + M3OP( "i32.trunc_s/f64", 0, i_32, d_convertOpList (i32_Trunc_f64), Compile_Convert ), // 0xaa + M3OP( "i32.trunc_u/f64", 0, i_32, d_convertOpList (u32_Trunc_f64), Compile_Convert ), // 0xab + + M3OP( "i64.extend_s/i32", 0, i_64, d_unaryOpList (i64, Extend_i32) ), // 0xac + M3OP( "i64.extend_u/i32", 0, i_64, d_unaryOpList (i64, Extend_u32) ), // 0xad + + M3OP( "i64.trunc_s/f32", 0, i_64, d_convertOpList (i64_Trunc_f32), Compile_Convert ), // 0xae + M3OP( "i64.trunc_u/f32", 0, i_64, d_convertOpList (u64_Trunc_f32), Compile_Convert ), // 0xaf + M3OP( "i64.trunc_s/f64", 0, i_64, d_convertOpList (i64_Trunc_f64), Compile_Convert ), // 0xb0 + M3OP( "i64.trunc_u/f64", 0, i_64, d_convertOpList (u64_Trunc_f64), Compile_Convert ), // 0xb1 + + M3OP( "f32.convert_s/i32", 0, f_32, d_convertOpList (f32_Convert_i32), Compile_Convert ), // 0xb2 + M3OP( "f32.convert_u/i32", 0, f_32, d_convertOpList (f32_Convert_u32), Compile_Convert ), // 0xb3 + M3OP( "f32.convert_s/i64", 0, f_32, d_convertOpList (f32_Convert_i64), Compile_Convert ), // 0xb4 + M3OP( "f32.convert_u/i64", 0, f_32, d_convertOpList (f32_Convert_u64), Compile_Convert ), // 0xb5 + + M3OP( "f32.demote/f64", 0, f_32, d_unaryOpList (f32, Demote_f64) ), // 0xb6 + + M3OP( "f64.convert_s/i32", 0, f_64, d_convertOpList (f64_Convert_i32), Compile_Convert ), // 0xb7 + M3OP( "f64.convert_u/i32", 0, f_64, d_convertOpList (f64_Convert_u32), Compile_Convert ), // 0xb8 + M3OP( "f64.convert_s/i64", 0, f_64, d_convertOpList (f64_Convert_i64), Compile_Convert ), // 0xb9 + M3OP( "f64.convert_u/i64", 0, f_64, d_convertOpList (f64_Convert_u64), Compile_Convert ), // 0xba + + M3OP( "f64.promote/f32", 0, f_64, d_unaryOpList (f64, Promote_f32) ), // 0xbb + + M3OP( "i32.reinterpret/f32", 0, i_32, d_convertOpList (i32_Reinterpret_f32), Compile_Convert ), // 0xbc + M3OP( "i64.reinterpret/f64", 0, i_64, d_convertOpList (i64_Reinterpret_f64), Compile_Convert ), // 0xbd + M3OP( "f32.reinterpret/i32", 0, f_32, d_convertOpList (f32_Reinterpret_i32), Compile_Convert ), // 0xbe + M3OP( "f64.reinterpret/i64", 0, f_64, d_convertOpList (f64_Reinterpret_i64), Compile_Convert ), // 0xbf # ifdef DEBUG // for codepage logging: - M3OP( "Const", 1, any, op_Const ), - M3OP( "Entry", 0, none, op_Entry ), - M3OP( "Compile", 0, none, op_Compile), - M3OP( "Bridge", 0, none, op_Bridge), - - M3OP( "SetGlobal_s", 0, none, op_SetGlobal_s), - - M3OP( "ContinueLoop", 0, none, op_ContinueLoop), - M3OP( "ContinueLoopIf", 0, none, op_ContinueLoopIf), - - M3OP( "PreserveCopySlot", 0, none, op_PreserveCopySlot_64), - M3OP( "CopySlot", 0, none, op_CopySlot_64), - M3OP( "SetSlot_i32", 0, none, op_SetSlot_i32), - M3OP( "SetSlot_i64", 0, none, op_SetSlot_i64), - M3OP( "SetSlot_f32", 0, none, op_SetSlot_f32), - M3OP( "SetSlot_f64", 0, none, op_SetSlot_f64), +# define d_m3DebugOp(OP) M3OP (#OP, 0, none, op_##OP) + + d_m3DebugOp (Const), d_m3DebugOp (Entry), d_m3DebugOp (Compile), + d_m3DebugOp (Bridge), d_m3DebugOp (End), d_m3DebugOp (SetGlobal_s), - M3OP( "SetRegister_i32", 0, none, op_SetRegister_i32), - M3OP( "SetRegister_i64", 0, none, op_SetRegister_i64), - M3OP( "SetRegister_f32", 0, none, op_SetRegister_f32), - M3OP( "SetRegister_f64", 0, none, op_SetRegister_f64), + d_m3DebugOp (ContinueLoop), d_m3DebugOp (ContinueLoopIf), - M3OP( "i32_BranchIf_rs", 0, none, op_i32_BranchIf_rs), - M3OP( "i32_BranchIf_ss", 0, none, op_i32_BranchIf_ss), - M3OP( "i64_BranchIf_rs", 0, none, op_i64_BranchIf_rs), - M3OP( "i64_BranchIf_ss", 0, none, op_i64_BranchIf_ss), + d_m3DebugOp (CopySlot_64), d_m3DebugOp (PreserveCopySlot_64), + + d_m3DebugOp (SetSlot_i32), + d_m3DebugOp (SetSlot_i64), + d_m3DebugOp (SetSlot_f32), + d_m3DebugOp (SetSlot_f64), + + d_m3DebugOp (SetRegister_i32), d_m3DebugOp (i32_BranchIf_rs), + d_m3DebugOp (SetRegister_i64), d_m3DebugOp (i32_BranchIf_ss), + d_m3DebugOp (SetRegister_f32), d_m3DebugOp (i64_BranchIf_rs), + d_m3DebugOp (SetRegister_f64), d_m3DebugOp (i64_BranchIf_ss), - M3OP( "End", 0, none, op_End ), # endif M3OP( "termination", 0, c_m3Type_void ) // termination for find_operation_info () diff --git a/source/m3_compile.h b/source/m3_compile.h index 9545e2e..299db27 100644 --- a/source/m3_compile.h +++ b/source/m3_compile.h @@ -93,7 +93,7 @@ typedef struct u16 wasmStack [c_m3MaxFunctionStackHeight]; u8 typeStack [c_m3MaxFunctionStackHeight]; - // this array just contains single bit allocation flags. could be fused with the typeStack to conserve space + // OPTZ: this array just contains single bit allocation flags. could be fused with the typeStack to conserve space u8 m3Slots [c_m3MaxFunctionStackHeight]; u16 numAllocatedExecSlots; @@ -122,10 +122,10 @@ typedef struct M3OpInfo i8 stackOffset; u8 type; - IM3Operation operation_sr; // top operand in register - IM3Operation operation_rs; // top operand in stack - IM3Operation operation_ss; // both operands in stack - + // for most operations: + // [0]= top operand in register, [1]= top operand in stack, [2]= both operands in stack + IM3Operation operations [4]; + M3Compiler compiler; } M3OpInfo; diff --git a/source/m3_exec.h b/source/m3_exec.h index f0f480c..87c9dcf 100644 --- a/source/m3_exec.h +++ b/source/m3_exec.h @@ -268,16 +268,29 @@ d_m3UnaryOp_i (u64, Popcnt, __builtin_popcountll) d_m3UnaryOp_i (i32, Wrap_i64, OP_WRAP_I64) -#define d_m3TruncMacro(RES, REG, TYPE, NAME, FROM, OP, ...) \ -d_m3Op(TYPE##_##NAME##_##FROM##_r) \ +#define d_m3TruncMacro(DEST, SRC, TYPE, NAME, FROM, OP, ...) \ +d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ { \ - OP((RES), (FROM) REG, ##__VA_ARGS__); \ + OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ return nextOp (); \ } \ -d_m3Op(TYPE##_##NAME##_##FROM##_s) \ +d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ { \ - FROM * stack = (FROM *) (_sp + immediate (i32));\ - OP((RES), (* stack), ##__VA_ARGS__); \ + FROM * stack = slot_ptr (FROM); \ + OP((DEST), (* stack), ##__VA_ARGS__); \ + return nextOp (); \ +} \ +d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ +{ \ + TYPE * dest = slot_ptr (TYPE); \ + OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ + return nextOp (); \ +} \ +d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ +{ \ + FROM * stack = slot_ptr (FROM); \ + TYPE * dest = slot_ptr (TYPE); \ + OP((* dest), (* stack), ##__VA_ARGS__); \ return nextOp (); \ } @@ -292,7 +305,7 @@ d_m3TruncMacro(_r0, _fp0, i64, Trunc, f64, OP_I64_TRUNC_F64) d_m3TruncMacro(_r0, _fp0, u64, Trunc, f64, OP_U64_TRUNC_F64) -#define d_m3TypeConvertOp(REG_TO, REG_FROM, TO, NAME, FROM) \ +#define d_m3TypeModifyOp(REG_TO, REG_FROM, TO, NAME, FROM) \ d_m3Op(TO##_##NAME##_##FROM##_r) \ { \ REG_TO = (TO) ((FROM) REG_FROM); \ @@ -307,39 +320,84 @@ d_m3Op(TO##_##NAME##_##FROM##_s) \ } // Int to int -d_m3TypeConvertOp(_r0, _r0, i64, Extend, i32); -d_m3TypeConvertOp(_r0, _r0, i64, Extend, u32); +d_m3TypeModifyOp (_r0, _r0, i64, Extend, i32); +d_m3TypeModifyOp (_r0, _r0, i64, Extend, u32); + +// Float to float +d_m3TypeModifyOp (_fp0, _fp0, f32, Demote, f64); +d_m3TypeModifyOp (_fp0, _fp0, f64, Promote, f32); + + +#define d_m3TypeConvertOp(REG_TO, REG_FROM, TO, NAME, FROM) \ +d_m3Op(TO##_##NAME##_##FROM##_r_r) \ +{ \ + REG_TO = (TO) ((FROM) REG_FROM); \ + return nextOp (); \ +} \ + \ +d_m3Op(TO##_##NAME##_##FROM##_s_r) \ +{ \ + slot (TO) = (TO) ((FROM) REG_FROM); \ + return nextOp (); \ +} \ + \ +d_m3Op(TO##_##NAME##_##FROM##_r_s) \ +{ \ + FROM from = slot (FROM); \ + REG_TO = (TO) (from); \ + return nextOp (); \ +} \ + \ +d_m3Op(TO##_##NAME##_##FROM##_s_s) \ +{ \ + FROM from = slot (FROM); \ + slot (TO) = (TO) (from); \ + return nextOp (); \ +} // Int to float -d_m3TypeConvertOp(_fp0, _r0, f64, Convert, i32); -d_m3TypeConvertOp(_fp0, _r0, f64, Convert, u32); -d_m3TypeConvertOp(_fp0, _r0, f64, Convert, i64); -d_m3TypeConvertOp(_fp0, _r0, f64, Convert, u64); +d_m3TypeConvertOp (_fp0, _r0, f64, Convert, i32); +d_m3TypeConvertOp (_fp0, _r0, f64, Convert, u32); +d_m3TypeConvertOp (_fp0, _r0, f64, Convert, i64); +d_m3TypeConvertOp (_fp0, _r0, f64, Convert, u64); -d_m3TypeConvertOp(_fp0, _r0, f32, Convert, i32); -d_m3TypeConvertOp(_fp0, _r0, f32, Convert, u32); -d_m3TypeConvertOp(_fp0, _r0, f32, Convert, i64); -d_m3TypeConvertOp(_fp0, _r0, f32, Convert, u64); +d_m3TypeConvertOp (_fp0, _r0, f32, Convert, i32); +d_m3TypeConvertOp (_fp0, _r0, f32, Convert, u32); +d_m3TypeConvertOp (_fp0, _r0, f32, Convert, i64); +d_m3TypeConvertOp (_fp0, _r0, f32, Convert, u64); -// Float to float -d_m3TypeConvertOp(_fp0, _fp0, f32, Demote, f64); -d_m3TypeConvertOp(_fp0, _fp0, f64, Promote, f32); #define d_m3ReinterpretOp(REG, TO, SRC, FROM) \ -d_m3Op(TO##_Reinterpret_##FROM##_r) \ +d_m3Op(TO##_Reinterpret_##FROM##_r_r) \ { \ union { FROM c; TO t; } u; \ - u.c = (FROM)SRC; \ + u.c = (FROM) SRC; \ REG = u.t; \ return nextOp (); \ } \ \ -d_m3Op(TO##_Reinterpret_##FROM##_s) \ +d_m3Op(TO##_Reinterpret_##FROM##_r_s) \ { \ union { FROM c; TO t; } u; \ - u.c = *(FROM *) (_sp + immediate (i32)); \ + u.c = slot (FROM); \ REG = u.t; \ return nextOp (); \ +} \ + \ +d_m3Op(TO##_Reinterpret_##FROM##_s_r) \ +{ \ + union { FROM c; TO t; } u; \ + u.c = (FROM) SRC; \ + slot (TO) = u.t; \ + return nextOp (); \ +} \ + \ +d_m3Op(TO##_Reinterpret_##FROM##_s_s) \ +{ \ + union { FROM c; TO t; } u; \ + u.c = slot (FROM); \ + slot (TO) = u.t; \ + return nextOp (); \ } d_m3ReinterpretOp (_r0, i32, _fp0, f32) @@ -649,15 +707,6 @@ d_m3Op (PreserveCopySlot_64) } -//d_m3Op (SwapRegister_i) -//{ -// slot (u64) = _r0; -// _r0 = slot (u64); -// -// return nextOp (); -//} - - #define d_m3SetRegisterSetSlot(TYPE, REG) \ d_m3Op (SetRegister_##TYPE) \ { \ diff --git a/source/m3_info.c b/source/m3_info.c index 1593725..6803940 100644 --- a/source/m3_info.c +++ b/source/m3_info.c @@ -134,13 +134,14 @@ OpInfo find_operation_info (IM3Operation i_operation) if (oi->type != c_m3Type_void) { - if (oi->operation_rs == i_operation or - oi->operation_sr == i_operation or - oi->operation_ss == i_operation) + for (u32 o = 0; o < 4; ++o) { - opInfo.info = oi; - opInfo.opcode = i; - break; + if (oi->operations [o] == i_operation) + { + opInfo.info = oi; + opInfo.opcode = i; + break; + } } } else break;