diff --git a/keymap/vim.js b/keymap/vim.js
index 6ff5edce4c578d86db712c77abeca5903372e6e9..ab61e17afb5b42ddf41855f00ff8ea93ddd89501 100644
--- a/keymap/vim.js
+++ b/keymap/vim.js
@@ -1858,6 +1858,8 @@
       },
       // delete is a javascript keyword.
       'delete': function(cm, operatorArgs, vim, curStart, curEnd) {
+        // Save the '>' mark before cm.replaceRange clears it.
+        var selectionEnd = vim.visualMode ? vim.marks['>'].find() : null;
         // If the ending line is past the last line, inclusive, instead of
         // including the trailing \n, include the \n before the starting line
         if (operatorArgs.linewise &&
@@ -1876,6 +1878,10 @@
         } else {
           cm.replaceRange('', curStart, curEnd);
         }
+        // restore the saved bookmark
+        if (selectionEnd) {
+          vim.marks['>'] = cm.setBookmark(selectionEnd);
+        }
         if (operatorArgs.linewise) {
           cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm));
         } else {
@@ -2085,7 +2091,6 @@
           curStart = cm.getCursor('anchor');
           curEnd = cm.getCursor('head');
           if (vim.visualLine) {
-            vim.visualLine = false;
             if (actionArgs.blockwise) {
               // This means Ctrl-V pressed in linewise visual
               vim.visualBlock = true;
@@ -2097,8 +2102,8 @@
             } else {
               exitVisualMode(cm);
             }
+            vim.visualLine = false;
           } else if (vim.visualBlock) {
-            vim.visualBlock = false;
             if (actionArgs.linewise) {
               // Shift-V pressed in blockwise visual mode
               vim.visualLine = true;
@@ -2118,6 +2123,7 @@
             } else {
               exitVisualMode(cm);
             }
+            vim.visualBlock = false;
           } else if (actionArgs.linewise) {
               // Shift-V pressed in characterwise visual mode. Switch to linewise
               // visual mode instead of exiting visual mode.
@@ -2142,27 +2148,40 @@
             : curStart);
       },
       reselectLastSelection: function(cm, _actionArgs, vim) {
+        var curStart = vim.marks['<'].find();
+        var curEnd = vim.marks['>'].find();
         var lastSelection = vim.lastSelection;
         if (lastSelection) {
-          var curStart = lastSelection.curStartMark.find();
-          var curEnd = lastSelection.curEndMark.find();
-          cm.setSelection(curStart, curEnd);
+          // Set the selections as per last selection
+          var selectionStart = lastSelection.curStartMark.find();
+          var selectionEnd = lastSelection.curEndMark.find();
+          var blockwise = lastSelection.visualBlock;
+          // update last selection
+          updateLastSelection(cm, vim, curStart, curEnd);
+          if (blockwise) {
+            cm.setCursor(selectionStart);
+            selectionStart = selectBlock(cm, selectionEnd);
+          } else {
+            cm.setSelection(selectionStart, selectionEnd);
+            selectionStart = cm.getCursor('anchor');
+            selectionEnd = cm.getCursor('head');
+          }
           if (vim.visualMode) {
-            updateLastSelection(cm, vim);
-            var selectionStart = cm.getCursor('anchor');
-            var selectionEnd = cm.getCursor('head');
             updateMark(cm, vim, '<', cursorIsBefore(selectionStart, selectionEnd) ? selectionStart
-            : selectionEnd);
+              : selectionEnd);
             updateMark(cm, vim, '>', cursorIsBefore(selectionStart, selectionEnd) ? selectionEnd
-            : selectionStart);
+              : selectionStart);
           }
+          // Last selection is updated now
+          vim.visualMode = true;
           if (lastSelection.visualLine) {
-            vim.visualMode = true;
             vim.visualLine = true;
-          }
-          else {
-            vim.visualMode = true;
+            vim.visualBlock = false;
+          } else if (lastSelection.visualBlock) {
             vim.visualLine = false;
+            vim.visualBlock = true;
+          } else {
+            vim.visualBlock = vim.visualLine = false;
           }
           CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : ""});
         }
@@ -2552,6 +2571,10 @@
         }
         start++;
       }
+      // Update selectionEnd and selectionStart
+      // after selection crossing
+      selectionEnd.ch = selections[0].head.ch;
+      selectionStart.ch = selections[0].anchor.ch;
       cm.setSelections(selections, primIndex);
       return selectionStart;
     }
@@ -2586,22 +2609,27 @@
       }
       return [selectionStart, selectionEnd];
     }
-    function updateLastSelection(cm, vim) {
-      // We need the vim mark '<' to get the selection in case of yank and put
-      var selectionStart =  vim.marks['<'].find() || cm.getCursor('anchor');
-      var selectionEnd =  vim.marks['>'].find() ||cm.getCursor('head');
-      // To accommodate the effect lastPastedText in the last selection
+    function updateLastSelection(cm, vim, selectionStart, selectionEnd) {
+      if (!selectionStart || !selectionEnd) {
+        selectionStart = vim.marks['<'].find() || cm.getCursor('anchor');
+        selectionEnd = vim.marks['>'].find() || cm.getCursor('head');
+      }
+      // To accommodate the effect of lastPastedText in the last selection
       if (vim.lastPastedText) {
-        selectionEnd = cm.posFromIndex(cm.indexFromPos(selectionStart) + vim.lastPastedText.length-1);
+        selectionEnd = cm.posFromIndex(cm.indexFromPos(selectionStart) + vim.lastPastedText.length);
         vim.lastPastedText = null;
       }
+      var ranges = cm.listSelections();
+      // This check ensures to set the cursor
+      // position where we left off in previous selection
+      var swap = getIndex(ranges, selectionStart) > -1;
       // can't use selection state here because yank has already reset its cursor
       // Also, Bookmarks make the visual selections robust to edit operations
-      vim.lastSelection = {'curStartMark': cm.setBookmark(selectionStart), 'curEndMark': cm.setBookmark(selectionEnd), 'visualMode': vim.visualMode, 'visualLine': vim.visualLine};
-      if (cursorIsBefore(selectionEnd, selectionStart)) {
-        vim.lastSelection.curStartMark = cm.setBookmark(selectionEnd);
-        vim.lastSelection.curEndMark = cm.setBookmark(selectionStart);
-      }
+      vim.lastSelection = {'curStartMark': cm.setBookmark(swap ? selectionEnd : selectionStart),
+                           'curEndMark': cm.setBookmark(swap ? selectionStart : selectionEnd),
+                           'visualMode': vim.visualMode,
+                           'visualLine': vim.visualLine,
+                           'visualBlock': vim.visualBlock};
     }
 
     function exitVisualMode(cm) {
diff --git a/test/vim_test.js b/test/vim_test.js
index b09d730d50a19e6469e59cb617a23c9d366f962d..1c9e8c3c9a13d6dc2f4df46c621994428205bdcc 100644
--- a/test/vim_test.js
+++ b/test/vim_test.js
@@ -1655,7 +1655,8 @@ testVim('reselect_visual', function(cm, vim, helpers) {
   eq('123456\n2345\nbar', cm.getValue());
   cm.setCursor(0, 0);
   helpers.doKeys('g', 'v');
-  helpers.assertCursorAt(1, 3);
+  // here the fake cursor is at (1, 3)
+  helpers.assertCursorAt(2, 0);
   eqPos(makeCursor(1, 0), cm.getCursor('anchor'));
   helpers.doKeys('v');
   cm.setCursor(2, 0);
@@ -1669,17 +1670,32 @@ testVim('reselect_visual', function(cm, vim, helpers) {
 }, { value: '123456\nfoo\nbar' });
 testVim('reselect_visual_line', function(cm, vim, helpers) {
   helpers.doKeys('l', 'V', 'j', 'j', 'V', 'g', 'v', 'd');
-  eq('\nfoo\nand\nbar', cm.getValue());
+  eq('foo\nand\nbar', cm.getValue());
   cm.setCursor(1, 0);
   helpers.doKeys('V', 'y', 'j');
   helpers.doKeys('V', 'p' , 'g', 'v', 'd');
-  eq('\nfoo\nbar', cm.getValue());
+  eq('foo\nand', cm.getValue());
 }, { value: 'hello\nthis\nis\nfoo\nand\nbar' });
+testVim('reselect_visual_block', function(cm, vim, helpers) {
+  cm.setCursor(1, 2);
+  helpers.doKeys('<C-v>', 'k', 'h', '<C-v>');
+  cm.setCursor(2, 1);
+  helpers.doKeys('v', 'l', 'g', 'v');
+  helpers.assertCursorAt(0, 1);
+  // Ensure selection is done with visual block mode rather than one
+  // continuous range.
+  eq(cm.getSelections().join(''), '23oo')
+  helpers.doKeys('g', 'v');
+  helpers.assertCursorAt(2, 3);
+  // Ensure selection of deleted range
+  cm.setCursor(1, 1);
+  helpers.doKeys('v', '<C-v>', 'j', 'd', 'g', 'v');
+  eq(cm.getSelections().join(''), 'or');
+}, { value: '123456\nfoo\nbar' });
 testVim('s_normal', function(cm, vim, helpers) {
   cm.setCursor(0, 1);
   helpers.doKeys('s');
   helpers.doInsertModeKeys('Esc');
-  helpers.assertCursorAt(0, 0);
   eq('ac', cm.getValue());
 }, { value: 'abc'});
 testVim('s_visual', function(cm, vim, helpers) {