Browse Source

jit shr32

Fabian 3 years ago
parent
commit
d3082cff3b
1 changed files with 56 additions and 7 deletions
  1. 56 7
      src/rust/jit_instructions.rs

+ 56 - 7
src/rust/jit_instructions.rs

@@ -1116,6 +1116,16 @@ impl ShiftCount {
             ShiftCount::Immediate(i) => builder.const_i32(*i),
         }
     }
+    pub fn gen_get_minus_one(builder: &mut WasmBuilder, count: &ShiftCount) {
+        match &count {
+            ShiftCount::Local(l) => {
+                builder.get_local(l);
+                builder.const_i32(1);
+                builder.sub_i32()
+            },
+            ShiftCount::Immediate(i) => builder.const_i32(*i - 1),
+        }
+    }
 }
 
 fn gen_shl32(
@@ -1192,21 +1202,60 @@ fn gen_shr32(
     dest_operand: &WasmLocal,
     source_operand: &LocalOrImmediate,
 ) {
-    builder.get_local(dest_operand);
-    match source_operand {
+    let count = match source_operand {
         LocalOrImmediate::WasmLocal(l) => {
+            let exit = builder.block_void();
             builder.get_local(l);
-            builder.const_i32(31);
+            builder.const_i32(31); // Note: mask can probably be avoided since wasm has the same semantics on shl_i32
             builder.and_i32();
+            let count = builder.tee_new_local();
+            builder.eqz_i32();
+            builder.br_if(exit);
+            ShiftCount::Local(count)
         },
         LocalOrImmediate::Immediate(i) => {
-            builder.const_i32(*i & 31);
+            if *i & 31 == 0 {
+                return;
+            }
+            ShiftCount::Immediate(*i & 31)
         },
-    }
-    builder.const_i32(31);
+    };
+
+    builder.const_i32(global_pointers::flags as i32);
+    codegen::gen_get_flags(builder);
+    builder.const_i32(!(FLAG_CARRY | FLAG_OVERFLOW));
     builder.and_i32();
-    builder.call_fn2_ret("shr32");
+    {
+        builder.get_local(dest_operand);
+        ShiftCount::gen_get_minus_one(builder, &count);
+        builder.shr_u_i32();
+        builder.const_i32(1);
+        builder.and_i32();
+        builder.or_i32()
+    }
+    {
+        builder.get_local(dest_operand);
+        builder.const_i32(20);
+        builder.shr_u_i32();
+        builder.const_i32(FLAG_OVERFLOW);
+        builder.and_i32();
+        builder.or_i32()
+    }
+    builder.store_aligned_i32(0);
+
+    builder.get_local(dest_operand);
+    ShiftCount::gen_get(builder, &count);
+    builder.shr_u_i32();
     builder.set_local(dest_operand);
+
+    codegen::gen_set_last_result(builder, dest_operand);
+    codegen::gen_set_last_op_size(builder, OPSIZE_32);
+    codegen::gen_set_flags_changed(builder, FLAGS_ALL & !FLAG_CARRY & !FLAG_OVERFLOW);
+
+    if let ShiftCount::Local(l) = count {
+        builder.block_end();
+        builder.free_local(l);
+    }
 }
 fn gen_sar32(
     builder: &mut WasmBuilder,