-
-
Save jnthn/faa05a408bd94321a623d197740f4da0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/jit/graph.c b/src/jit/graph.c | |
index 1efcd66..77a8b66 100644 | |
--- a/src/jit/graph.c | |
+++ b/src/jit/graph.c | |
@@ -1912,6 +1912,7 @@ start: | |
case MVM_OP_sp_add_bi: | |
case MVM_OP_sp_sub_bi: | |
case MVM_OP_sp_mul_bi: | |
+ case MVM_OP_sp_gcd_bi: | |
case MVM_OP_sp_unbox_bi: | |
case MVM_OP_sp_takewrite_bi: | |
case MVM_OP_sp_materialize_bi: | |
diff --git a/src/jit/x64/emit.dasc b/src/jit/x64/emit.dasc | |
index 9d37026..2441e76 100644 | |
--- a/src/jit/x64/emit.dasc | |
+++ b/src/jit/x64/emit.dasc | |
@@ -2461,7 +2461,8 @@ void MVM_jit_emit_primitive(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJ | |
} | |
case MVM_OP_sp_add_bi: | |
case MVM_OP_sp_sub_bi: | |
- case MVM_OP_sp_mul_bi: { | |
+ case MVM_OP_sp_mul_bi: | |
+ case MVM_OP_sp_gcd_bi: { | |
MVMint16 a = ins->operands[1].reg.orig; | |
MVMint16 b = ins->operands[2].reg.orig; | |
MVMint16 c = ins->operands[0].reg.orig; | |
@@ -2474,8 +2475,7 @@ void MVM_jit_emit_primitive(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJ | |
| cmp TMP1d, MVM_BIGINT_32_FLAG; | |
| jne >1; | |
- /* Both smallint, so try to do the calculation. If it overflows, fall | |
- * back to the slow path. */ | |
+ /* Both smallint, so try to do the calculation. */ | |
| mov TMP4d, dword [WORK + 8 * a + 4] | |
switch (op) { | |
case MVM_OP_sp_add_bi: | |
@@ -2487,8 +2487,38 @@ void MVM_jit_emit_primitive(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJ | |
case MVM_OP_sp_mul_bi: | |
| imul TMP4d, dword [WORK + 8 * b + 4] | |
break; | |
+ case MVM_OP_sp_gcd_bi: | |
+ /* Need absolute values first. We'll want the first value in | |
+ * eax for the GCD itself, but need eax for the absolute too, | |
+ * so process the second operand first and move it into ecx. */ | |
+ | mov eax, dword [WORK + 8 * b + 4] | |
+ | cdq | |
+ | xor eax, edx | |
+ | sub eax, edx | |
+ | mov ecx, eax | |
+ | mov eax, TMP4d | |
+ | cdq | |
+ | xor eax, edx | |
+ | sub eax, edx | |
+ | |
+ /* We now have the values to do the GCD on in eax and ecx (we | |
+ * avoid ebx since that is WORK); only eax matters since it's | |
+ * the implicit argument to div. */ | |
+ |4: | |
+ | xor edx, edx | |
+ | div ecx | |
+ | mov eax, ecx | |
+ | mov ecx, edx | |
+ | test ecx, ecx | |
+ | jnz >4 | |
+ | mov TMP4d, eax | |
+ break; | |
} | |
- | jo >1 | |
+ | |
+ /* If it overflows, fall back to the slow path. (Some operations | |
+ * always produce a smaller value than the input, so cannot.) */ | |
+ if (op != MVM_OP_sp_gcd_bi) | |
+ | jo >1 | |
/* No overflow; store the result. */ | |
| mov dword [WORK + 8 * c], MVM_BIGINT_32_FLAG | |
@@ -2513,6 +2543,9 @@ void MVM_jit_emit_primitive(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJ | |
case MVM_OP_sp_mul_bi: | |
| callp &MVM_bigint_fallback_mul; | |
break; | |
+ case MVM_OP_sp_gcd_bi: | |
+ | callp &MVM_bigint_fallback_gcd; | |
+ break; | |
} | |
|3: | |
break; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment