diff options
Diffstat (limited to '')
-rw-r--r-- | luxc/src/lux/compiler/jvm/rt.clj | 59 |
1 files changed, 48 insertions, 11 deletions
diff --git a/luxc/src/lux/compiler/jvm/rt.clj b/luxc/src/lux/compiler/jvm/rt.clj index a1b171a25..aa0c881d0 100644 --- a/luxc/src/lux/compiler/jvm/rt.clj +++ b/luxc/src/lux/compiler/jvm/rt.clj @@ -368,17 +368,54 @@ (.visitInsn Opcodes/LRETURN) (.visitMaxs 0 0) (.visitEnd)) - _ (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "div_deg" "(JJ)J" nil nil) - (.visitCode) - ;; Based on: http://stackoverflow.com/a/8510587/6823464 - (.visitVarInsn Opcodes/LLOAD 0) - (.visitVarInsn Opcodes/LLOAD 2) high-4b - (.visitInsn Opcodes/LDIV) - (.visitLdcInsn (int 32)) - (.visitInsn Opcodes/LSHL) - (.visitInsn Opcodes/LRETURN) - (.visitMaxs 0 0) - (.visitEnd)) + _ (let [$loop-start (new Label) + $done (new Label)] + (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "count_leading_zeros" "(J)I" nil nil) + (.visitCode) + (.visitLdcInsn (int 64)) + (.visitLabel $loop-start) + (.visitVarInsn Opcodes/LLOAD 0) + (.visitLdcInsn (long 0)) + (.visitInsn Opcodes/LCMP) + (.visitJumpInsn Opcodes/IFEQ $done) + (.visitVarInsn Opcodes/LLOAD 0) + (.visitLdcInsn (int 1)) + (.visitInsn Opcodes/LUSHR) + (.visitVarInsn Opcodes/LSTORE 0) + (.visitLdcInsn (int 1)) + (.visitInsn Opcodes/ISUB) + (.visitJumpInsn Opcodes/GOTO $loop-start) + (.visitLabel $done) + (.visitInsn Opcodes/IRETURN) + (.visitMaxs 0 0) + (.visitEnd))) + _ (let [$same (new Label)] + (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "div_deg" "(JJ)J" nil nil) + (.visitCode) + (.visitVarInsn Opcodes/LLOAD 0) + (.visitVarInsn Opcodes/LLOAD 2) + (.visitInsn Opcodes/LCMP) + (.visitJumpInsn Opcodes/IFEQ $same) + ;; Based on: http://stackoverflow.com/a/8510587/6823464 + ;; Shifting the operands as much as possible can help + ;; avoid some loss of precision later. + (.visitVarInsn Opcodes/LLOAD 0) + (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "count_leading_zeros" "(J)I") + (.visitVarInsn Opcodes/LLOAD 2) + (.visitMethodInsn Opcodes/INVOKESTATIC "lux/LuxRT" "count_leading_zeros" "(J)I") + (.visitMethodInsn Opcodes/INVOKESTATIC "java/lang/Math" "min" "(II)I") + (.visitVarInsn Opcodes/ISTORE 4) + (.visitVarInsn Opcodes/LLOAD 0) (.visitVarInsn Opcodes/ILOAD 4) (.visitInsn Opcodes/LSHL) + (.visitVarInsn Opcodes/LLOAD 2) (.visitVarInsn Opcodes/ILOAD 4) (.visitInsn Opcodes/LSHL) high-4b + (.visitInsn Opcodes/LDIV) + (.visitLdcInsn (int 32)) + (.visitInsn Opcodes/LSHL) + (.visitInsn Opcodes/LRETURN) + (.visitLabel $same) + (.visitLdcInsn (long -1)) ;; ~= 1.0 DEG + (.visitInsn Opcodes/LRETURN) + (.visitMaxs 0 0) + (.visitEnd))) _ (doto (.visitMethod =class (+ Opcodes/ACC_PUBLIC Opcodes/ACC_STATIC) "deg-to-real" "(J)D" nil nil) (.visitCode) ;; Translate high bytes |