about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--linux/bootstrap/017jump_disp8.cc24
-rw-r--r--linux/bootstrap/018jump_disp32.cc24
-rw-r--r--linux/branches.mu40
-rw-r--r--linux/branches.out161
-rwxr-xr-xlinux/mubin607182 -> 608328 bytes
-rw-r--r--linux/mu.subx248
-rw-r--r--mu_instructions25
-rw-r--r--subx_opcodes4
8 files changed, 517 insertions, 9 deletions
diff --git a/linux/bootstrap/017jump_disp8.cc b/linux/bootstrap/017jump_disp8.cc
index 30e60a74..37df6d5b 100644
--- a/linux/bootstrap/017jump_disp8.cc
+++ b/linux/bootstrap/017jump_disp8.cc
@@ -405,3 +405,27 @@ void test_jle_disp8_greater() {
   );
   CHECK_TRACE_DOESNT_CONTAIN("run: jump 5");
 }
+
+//:: jump if overflow
+
+:(before "End Initialize Op Names")
+put_new(Name, "70", "jump disp8 bytes away if OF is set (jcc/jo)");
+put_new(Name, "71", "jump disp8 bytes away if OF is unset (jcc/jno)");
+
+:(before "End Single-Byte Opcodes")
+case 0x70: {  // jump disp8 if OF is set
+  const int8_t offset = static_cast<int>(next());
+  if (OF) {
+    trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end();
+    EIP += offset;
+  }
+  break;
+}
+case 0x71: {  // jump disp8 if OF is unset
+  const int8_t offset = static_cast<int>(next());
+  if (!OF) {
+    trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end();
+    EIP += offset;
+  }
+  break;
+}
diff --git a/linux/bootstrap/018jump_disp32.cc b/linux/bootstrap/018jump_disp32.cc
index e77bc584..75fb576a 100644
--- a/linux/bootstrap/018jump_disp32.cc
+++ b/linux/bootstrap/018jump_disp32.cc
@@ -405,3 +405,27 @@ void test_jle_disp32_greater() {
   );
   CHECK_TRACE_DOESNT_CONTAIN("run: jump 5");
 }
+
+//:: jump if overflow
+
+:(before "End Initialize Op Names")
+put_new(Name_0f, "80", "jump disp32 bytes away if OF is set (jcc/jo)");
+put_new(Name_0f, "81", "jump disp32 bytes away if OF is unset (jcc/jno)");
+
+:(before "End Two-Byte Opcodes Starting With 0f")
+case 0x80: {  // jump disp8 if OF is set
+  const int32_t offset = next32();
+  if (OF) {
+    trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end();
+    EIP += offset;
+  }
+  break;
+}
+case 0x81: {  // jump disp8 if OF is unset
+  const int32_t offset = next32();
+  if (!OF) {
+    trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end();
+    EIP += offset;
+  }
+  break;
+}
diff --git a/linux/branches.mu b/linux/branches.mu
new file mode 100644
index 00000000..411eaa0d
--- /dev/null
+++ b/linux/branches.mu
@@ -0,0 +1,40 @@
+fn foo {
+  $foo: {
+    break-if-=
+    break-if-= $foo
+    break-if-!=
+    break-if-!= $foo
+    break-if-<=
+    break-if-<= $foo
+    break-if->=
+    break-if->= $foo
+    break-if-<
+    break-if-< $foo
+    break-if->
+    break-if-> $foo
+    break-if-carry
+    break-if-carry $foo
+    break-if-overflow
+    break-if-overflow $foo
+    loop-if-=
+    loop-if-= $foo
+    loop-if-!=
+    loop-if-!= $foo
+    loop-if-<=
+    loop-if-<= $foo
+    loop-if->=
+    loop-if->= $foo
+    loop-if-<
+    loop-if-< $foo
+    loop-if->
+    loop-if-> $foo
+    loop-if-carry
+    loop-if-carry $foo
+    loop-if-not-carry
+    loop-if-not-carry $foo
+    loop-if-overflow
+    loop-if-overflow $foo
+    loop-if-not-overflow
+    loop-if-not-overflow $foo
+  }
+}
diff --git a/linux/branches.out b/linux/branches.out
new file mode 100644
index 00000000..878a91e5
--- /dev/null
+++ b/linux/branches.out
@@ -0,0 +1,161 @@
+== code
+foo:
+  # . prologue
+  55/push-ebp
+  89/<- %ebp 4/r32/esp
+  {
+$foo:0x00000001:loop:
+    {
+$foo:loop:
+      {
+        0f 85/jump-if-!= break/disp32
+        e9/jump $foo:break/disp32
+      }
+      {
+        0f 85/jump-if-!= break/disp32
+        e9/jump $foo:break/disp32
+      }
+      {
+        0f 84/jump-if-= break/disp32
+        e9/jump $foo:break/disp32
+      }
+      {
+        0f 84/jump-if-= break/disp32
+        e9/jump $foo:break/disp32
+      }
+      {
+        0f 8f/jump-if-> break/disp32
+        e9/jump $foo:break/disp32
+      }
+      {
+        0f 8f/jump-if-> break/disp32
+        e9/jump $foo:break/disp32
+      }
+      {
+        0f 8c/jump-if-< break/disp32
+        e9/jump $foo:break/disp32
+      }
+      {
+        0f 8c/jump-if-< break/disp32
+        e9/jump $foo:break/disp32
+      }
+      {
+        0f 8d/jump-if->= break/disp32
+        e9/jump $foo:break/disp32
+      }
+      {
+        0f 8d/jump-if->= break/disp32
+        e9/jump $foo:break/disp32
+      }
+      {
+        0f 8e/jump-if-<= break/disp32
+        e9/jump $foo:break/disp32
+      }
+      {
+        0f 8e/jump-if-<= break/disp32
+        e9/jump $foo:break/disp32
+      }
+      {
+        0f 83/jump-if-addr>= break/disp32
+        e9/jump $foo:break/disp32
+      }
+      {
+        0f 83/jump-if-addr>= break/disp32
+        e9/jump $foo:break/disp32
+      }
+      {
+        0f 81/jump-if-not-overflow break/disp32
+        e9/jump $foo:break/disp32
+      }
+      {
+        0f 81/jump-if-not-overflow break/disp32
+        e9/jump $foo:break/disp32
+      }
+      {
+        0f 85/jump-if-!= break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 85/jump-if-!= break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 84/jump-if-= break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 84/jump-if-= break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 8f/jump-if-> break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 8f/jump-if-> break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 8c/jump-if-< break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 8c/jump-if-< break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 8d/jump-if->= break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 8d/jump-if->= break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 8e/jump-if-<= break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 8e/jump-if-<= break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 83/jump-if-addr>= break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 83/jump-if-addr>= break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 82/jump-if-addr< break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 82/jump-if-addr< break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 81/jump-if-not-overflow break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 81/jump-if-not-overflow break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 80/jump-if-overflow break/disp32
+        e9/jump $foo:loop/disp32
+      }
+      {
+        0f 80/jump-if-overflow break/disp32
+        e9/jump $foo:loop/disp32
+      }
+    }
+$foo:break:
+  }
+$foo:0x00000001:break:
+  # . epilogue
+  89/<- %esp 5/r32/ebp
+  5d/pop-to-ebp
+  c3/return
diff --git a/linux/mu b/linux/mu
index 74374bee..2508cda4 100755
--- a/linux/mu
+++ b/linux/mu
Binary files differdiff --git a/linux/mu.subx b/linux/mu.subx
index 07ba75a8..93065326 100644
--- a/linux/mu.subx
+++ b/linux/mu.subx
@@ -27610,9 +27610,9 @@ $emit-reverse-break:end:
 # Table from Mu branch instructions to the reverse SubX opcodes for them.
 Reverse-branch:  # (table (handle array byte) (handle array byte))
   # a table is a stream
-  0x1c0/imm32/write
+  0x240/imm32/write
   0/imm32/read
-  0x1c0/imm32/size
+  0x240/imm32/size
   # data
   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
@@ -27642,6 +27642,14 @@ Reverse-branch:  # (table (handle array byte) (handle array byte))
   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
+  0x11/imm32/alloc-id   _string-break-if-carry/imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
+  0x11/imm32/alloc-id   _string-loop-if-carry/imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
+  0x11/imm32/alloc-id   _string-break-if-not-carry/imm32        0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
+  0x11/imm32/alloc-id   _string-loop-if-not-carry/imm32         0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
+  0x11/imm32/alloc-id   _string-break-if-overflow/imm32         0x11/imm32/alloc-id   _string_0f_81_jump_label/imm32
+  0x11/imm32/alloc-id   _string-loop-if-overflow/imm32          0x11/imm32/alloc-id   _string_0f_81_jump_label/imm32
+  0x11/imm32/alloc-id   _string-break-if-not-overflow/imm32     0x11/imm32/alloc-id   _string_0f_80_jump_label/imm32
+  0x11/imm32/alloc-id   _string-loop-if-not-overflow/imm32      0x11/imm32/alloc-id   _string_0f_80_jump_label/imm32
 
 == code
 
@@ -32836,6 +32844,82 @@ _Primitive-break-if->:  # (payload primitive)
     0/imm32/no-xm32
     0/imm32/no-x32
     0x11/imm32/alloc-id:fake
+    _Primitive-break-if-carry/imm32/next
+_Primitive-break-if-carry:  # (payload primitive)
+    0x11/imm32/alloc-id:fake:payload
+    0x11/imm32/alloc-id:fake
+    _string-break-if-carry/imm32/name
+    0/imm32/no-inouts
+    0/imm32/no-inouts
+    0/imm32/no-outputs
+    0/imm32/no-outputs
+    0x11/imm32/alloc-id:fake
+    _string_0f_82_jump_break/imm32/subx-name
+    0/imm32/no-rm32
+    0/imm32/no-r32
+    0/imm32/no-imm32
+    0/imm32/no-imm8
+    0/imm32/no-disp32
+    0/imm32/no-xm32
+    0/imm32/no-x32
+    0x11/imm32/alloc-id:fake
+    _Primitive-break-if-not-carry/imm32/next
+_Primitive-break-if-not-carry:  # (payload primitive)
+    0x11/imm32/alloc-id:fake:payload
+    0x11/imm32/alloc-id:fake
+    _string-break-if-not-carry/imm32/name
+    0/imm32/no-inouts
+    0/imm32/no-inouts
+    0/imm32/no-outputs
+    0/imm32/no-outputs
+    0x11/imm32/alloc-id:fake
+    _string_0f_83_jump_break/imm32/subx-name
+    0/imm32/no-rm32
+    0/imm32/no-r32
+    0/imm32/no-imm32
+    0/imm32/no-imm8
+    0/imm32/no-disp32
+    0/imm32/no-xm32
+    0/imm32/no-x32
+    0x11/imm32/alloc-id:fake
+    _Primitive-break-if-overflow/imm32/next
+_Primitive-break-if-overflow:  # (payload primitive)
+    0x11/imm32/alloc-id:fake:payload
+    0x11/imm32/alloc-id:fake
+    _string-break-if-overflow/imm32/name
+    0/imm32/no-inouts
+    0/imm32/no-inouts
+    0/imm32/no-outputs
+    0/imm32/no-outputs
+    0x11/imm32/alloc-id:fake
+    _string_0f_80_jump_break/imm32/subx-name
+    0/imm32/no-rm32
+    0/imm32/no-r32
+    0/imm32/no-imm32
+    0/imm32/no-imm8
+    0/imm32/no-disp32
+    0/imm32/no-xm32
+    0/imm32/no-x32
+    0x11/imm32/alloc-id:fake
+    _Primitive-break-if-not-overflow/imm32/next
+_Primitive-break-if-not-overflow:  # (payload primitive)
+    0x11/imm32/alloc-id:fake:payload
+    0x11/imm32/alloc-id:fake
+    _string-break-if-not-overflow/imm32/name
+    0/imm32/no-inouts
+    0/imm32/no-inouts
+    0/imm32/no-outputs
+    0/imm32/no-outputs
+    0x11/imm32/alloc-id:fake
+    _string_0f_81_jump_break/imm32/subx-name
+    0/imm32/no-rm32
+    0/imm32/no-r32
+    0/imm32/no-imm32
+    0/imm32/no-imm8
+    0/imm32/no-disp32
+    0/imm32/no-xm32
+    0/imm32/no-x32
+    0x11/imm32/alloc-id:fake
     _Primitive-break/imm32/next
 _Primitive-break:  # (payload primitive)
     0x11/imm32/alloc-id:fake:payload
@@ -33045,6 +33129,82 @@ _Primitive-loop-if->:  # (payload primitive)
     0/imm32/no-xm32
     0/imm32/no-x32
     0x11/imm32/alloc-id:fake
+    _Primitive-loop-if-carry/imm32/next
+_Primitive-loop-if-carry:  # (payload primitive)
+    0x11/imm32/alloc-id:fake:payload
+    0x11/imm32/alloc-id:fake
+    _string-loop-if-carry/imm32/name
+    0/imm32/no-inouts
+    0/imm32/no-inouts
+    0/imm32/no-outputs
+    0/imm32/no-outputs
+    0x11/imm32/alloc-id:fake
+    _string_0f_82_jump_loop/imm32/subx-name
+    0/imm32/no-rm32
+    0/imm32/no-r32
+    0/imm32/no-imm32
+    0/imm32/no-imm8
+    0/imm32/no-disp32
+    0/imm32/no-xm32
+    0/imm32/no-x32
+    0x11/imm32/alloc-id:fake
+    _Primitive-loop-if-not-carry/imm32/next
+_Primitive-loop-if-not-carry:  # (payload primitive)
+    0x11/imm32/alloc-id:fake:payload
+    0x11/imm32/alloc-id:fake
+    _string-loop-if-not-carry/imm32/name
+    0/imm32/no-inouts
+    0/imm32/no-inouts
+    0/imm32/no-outputs
+    0/imm32/no-outputs
+    0x11/imm32/alloc-id:fake
+    _string_0f_83_jump_loop/imm32/subx-name
+    0/imm32/no-rm32
+    0/imm32/no-r32
+    0/imm32/no-imm32
+    0/imm32/no-imm8
+    0/imm32/no-disp32
+    0/imm32/no-xm32
+    0/imm32/no-x32
+    0x11/imm32/alloc-id:fake
+    _Primitive-loop-if-overflow/imm32/next
+_Primitive-loop-if-overflow:  # (payload primitive)
+    0x11/imm32/alloc-id:fake:payload
+    0x11/imm32/alloc-id:fake
+    _string-loop-if-overflow/imm32/name
+    0/imm32/no-inouts
+    0/imm32/no-inouts
+    0/imm32/no-outputs
+    0/imm32/no-outputs
+    0x11/imm32/alloc-id:fake
+    _string_0f_80_jump_loop/imm32/subx-name
+    0/imm32/no-rm32
+    0/imm32/no-r32
+    0/imm32/no-imm32
+    0/imm32/no-imm8
+    0/imm32/no-disp32
+    0/imm32/no-xm32
+    0/imm32/no-x32
+    0x11/imm32/alloc-id:fake
+    _Primitive-loop-if-not-overflow/imm32/next
+_Primitive-loop-if-not-overflow:  # (payload primitive)
+    0x11/imm32/alloc-id:fake:payload
+    0x11/imm32/alloc-id:fake
+    _string-loop-if-not-overflow/imm32/name
+    0/imm32/no-inouts
+    0/imm32/no-inouts
+    0/imm32/no-outputs
+    0/imm32/no-outputs
+    0x11/imm32/alloc-id:fake
+    _string_0f_81_jump_loop/imm32/subx-name
+    0/imm32/no-rm32
+    0/imm32/no-r32
+    0/imm32/no-imm32
+    0/imm32/no-imm8
+    0/imm32/no-disp32
+    0/imm32/no-xm32
+    0/imm32/no-x32
+    0x11/imm32/alloc-id:fake
     _Primitive-loop/imm32/next  # we probably don't need an unconditional break
 _Primitive-loop:  # (payload primitive)
     0x11/imm32/alloc-id:fake:payload
@@ -33891,6 +34051,26 @@ _string-break-if-float>=:  # (payload array byte)
     # "break-if-float>="
     0x10/imm32/size
     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> 0x3d/=
+_string-break-if-carry:  # (payload array byte)
+    0x11/imm32/alloc-id:fake:payload
+    # "break-if-carry"
+    0xe/imm32/size
+    0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y
+_string-break-if-not-carry:  # (payload array byte)
+    0x11/imm32/alloc-id:fake:payload
+    # "break-if-not-carry"
+    0x12/imm32/size
+    0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y
+_string-break-if-overflow:  # (payload array byte)
+    0x11/imm32/alloc-id:fake:payload
+    # "break-if-overflow"
+    0x11/imm32/size
+    0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
+_string-break-if-not-overflow:  # (payload array byte)
+    0x11/imm32/alloc-id:fake:payload
+    # "break-if-not-overflow"
+    0x15/imm32/size
+    0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
 _string-compare:  # (payload array byte)
     0x11/imm32/alloc-id:fake:payload
     # "compare"
@@ -33910,12 +34090,12 @@ _string-copy-byte:
     0x11/imm32/alloc-id:fake:payload
     # "copy-byte"
     0x9/imm32/size
-    0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e
+    0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x62/b 0x79/y 0x74/t 0x65/e
 _string-copy-byte-to:
     0x11/imm32/alloc-id:fake:payload
     # "copy-byte-to"
     0xc/imm32/size
-    0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x74/t 0x6f/o
+    0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/dash 0x74/t 0x6f/o
 _string-decrement:  # (payload array byte)
     0x11/imm32/alloc-id:fake:payload
     # "decrement"
@@ -34001,6 +34181,26 @@ _string-loop-if-float>=:  # (payload array byte)
     # "loop-if-float>="
     0xf/imm32/size
     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> 0x3d/=
+_string-loop-if-carry:  # (payload array byte)
+    0x11/imm32/alloc-id:fake:payload
+    # "loop-if-carry"
+    0xd/imm32/size
+    0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y
+_string-loop-if-not-carry:  # (payload array byte)
+    0x11/imm32/alloc-id:fake:payload
+    # "loop-if-not-carry"
+    0x11/imm32/size
+    0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y
+_string-loop-if-overflow:  # (payload array byte)
+    0x11/imm32/alloc-id:fake:payload
+    # "loop-if-overflow"
+    0x10/imm32/size
+    0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
+_string-loop-if-not-overflow:  # (payload array byte)
+    0x11/imm32/alloc-id:fake:payload
+    # "loop-if-not-overflow"
+    0x14/imm32/size
+    0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
 _string-multiply:  # (payload array byte)
     0x11/imm32/alloc-id:fake:payload
     # "multiply"
@@ -34045,12 +34245,12 @@ _string-square-root:
     0x11/imm32/alloc-id:fake:payload
     # "square-root"
     0xb/imm32/size
-    0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
+    0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t
 _string-inverse-square-root:
     0x11/imm32/alloc-id:fake:payload
     # "inverse-square-root"
     0x13/imm32/size
-    0x69/i 0x6e/n 0x76/v 0x65/e 0x72/r 0x73/s 0x65/e 0x2d/- 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
+    0x69/i 0x6e/n 0x76/v 0x65/e 0x72/r 0x73/s 0x65/e 0x2d/dash 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t
 _string-negate:  # (payload array byte)
     0x11/imm32/alloc-id:fake:payload
     # "negate"
@@ -34133,6 +34333,36 @@ _string_0d_or_with_eax:  # (payload array byte)
     # "0d/or-with-eax"
     0xe/imm32/size
     0x30/0 0x64/d 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h 0x2d/dash 0x65/e 0x61/a 0x78/x
+_string_0f_80_jump_label:  # (payload array byte)
+    0x11/imm32/alloc-id:fake:payload
+    # "0f 80/jump-if-overflow"
+    0x16/imm32/size
+    0x30/0 0x66/f 0x20/space 0x38/8 0x30/0 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
+_string_0f_80_jump_break:  # (payload array byte)
+    0x11/imm32/alloc-id:fake:payload
+    # "0f 80/jump-if-overflow break/disp32"
+    0x23/imm32/size
+    0x30/0 0x66/f 0x20/space 0x38/8 0x30/0 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
+_string_0f_80_jump_loop:  # (payload array byte)
+    0x11/imm32/alloc-id:fake:payload
+    # "0f 80/jump-if-overflow loop/disp32"
+    0x22/imm32/size
+    0x30/0 0x66/f 0x20/space 0x38/8 0x30/0 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
+_string_0f_81_jump_label:  # (payload array byte)
+    0x11/imm32/alloc-id:fake:payload
+    # "0f 81/jump-if-not-overflow"
+    0x1a/imm32/size
+    0x30/0 0x66/f 0x20/space 0x38/8 0x31/1 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
+_string_0f_81_jump_break:  # (payload array byte)
+    0x11/imm32/alloc-id:fake:payload
+    # "0f 81/jump-if-not-overflow break/disp32"
+    0x27/imm32/size
+    0x30/0 0x66/f 0x20/space 0x38/8 0x31/1 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
+_string_0f_81_jump_loop:  # (payload array byte)
+    0x11/imm32/alloc-id:fake:payload
+    # "0f 81/jump-if-not-overflow loop/disp32"
+    0x26/imm32/size
+    0x30/0 0x66/f 0x20/space 0x38/8 0x31/1 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
 _string_0f_82_jump_label:  # (payload array byte)
     0x11/imm32/alloc-id:fake:payload
     # "0f 82/jump-if-addr<"
@@ -34176,7 +34406,7 @@ _string_0f_84_jump_break:  # (payload array byte)
 _string_0f_84_jump_loop:  # (payload array byte)
     0x11/imm32/alloc-id:fake:payload
     # "0f 84/jump-if-= loop/disp32"
-    0x1b/imm32/size
+    0x1a/imm32/size
     0x30/0 0x66/f 0x20/space 0x38/8 0x34/4 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/= 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
 _string_0f_85_jump_label:  # (payload array byte)
     0x11/imm32/alloc-id:fake:payload
@@ -34527,12 +34757,12 @@ _string_8a_copy_byte:
     0x11/imm32/alloc-id:fake:payload
     # "8a/byte->"
     0x9/imm32/size
-    0x38/8 0x61/a 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x3e/>
+    0x38/8 0x61/a 0x2f/slash 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/dash 0x3e/>
 _string_88_copy_byte:
     0x11/imm32/alloc-id:fake:payload
     # "88/byte<-"
     0x9/imm32/size
-    0x38/8 0x38/8 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
+    0x38/8 0x38/8 0x2f/slash 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
 _string_8d_copy_address:  # (payload array byte)
     0x11/imm32/alloc-id:fake:payload
     # "8d/copy-address"
diff --git a/mu_instructions b/mu_instructions
index 10d00f10..7a458660 100644
--- a/mu_instructions
+++ b/mu_instructions
@@ -293,6 +293,31 @@ Similar float variants like `break-if-float<` are aliases for the corresponding
 `addr` equivalents. The x86 instruction set stupidly has floating-point
 operations only update a subset of flags.
 
+Four sets of conditional jumps are useful for detecting overflow.
+
+break-if-carry                    => "0f 82/jump-if-carry break/disp32"
+break-if-carry label              => "0f 82/jump-if-carry " label "/disp32"
+loop-if-carry                     => "0f 82/jump-if-carry break/disp32"
+loop-if-carry label               => "0f 82/jump-if-carry " label "/disp32"
+
+break-if-not-carry                => "0f 83/jump-if-not-carry break/disp32"
+break-if-not-carry label          => "0f 83/jump-if-not-carry " label "/disp32"
+loop-if-not-carry                 => "0f 83/jump-if-not-carry break/disp32"
+loop-if-not-carry label           => "0f 83/jump-if-not-carry " label "/disp32"
+
+break-if-overflow                 => "0f 80/jump-if-overflow break/disp32"
+break-if-overflow label           => "0f 80/jump-if-overflow " label ":break/disp32"
+loop-if-overflow                  => "0f 80/jump-if-overflow loop/disp32"
+loop-if-overflow label            => "0f 80/jump-if-overflow " label ":loop/disp32"
+
+break-if-not-overflow             => "0f 81/jump-if-not-overflow break/disp32"
+break-if-not-overflow label       => "0f 81/jump-if-not-overflow " label ":break/disp32"
+loop-if-not-overflow              => "0f 81/jump-if-not-overflow loop/disp32"
+loop-if-not-overflow label        => "0f 81/jump-if-not-overflow " label ":loop/disp32"
+
+All this relies on a convention that every `{}` block is delimited by labels
+ending in `:loop` and `:break`.
+
 ## Returns
 
 The `return` instruction cleans up variable declarations just like an unconditional
diff --git a/subx_opcodes b/subx_opcodes
index f8bdc045..19fa1dbd 100644
--- a/subx_opcodes
+++ b/subx_opcodes
@@ -51,6 +51,8 @@ Opcodes currently supported by SubX:
   5f: pop top of stack to EDI (pop)
   68: push imm32 to stack (push)
   69: multiply rm32 by imm32 and store result in r32 (imul)
+  70: jump disp8 bytes away if OF is set (jcc/jo)
+  71: jump disp8 bytes away if OF is unset (jcc/jno)
   72: jump disp8 bytes away if lesser (addr, float), if CF is set (jcc/jb/jnae)
   73: jump disp8 bytes away if greater or equal (addr, float), if CF is unset (jcc/jae/jnb)
   74: jump disp8 bytes away if equal, if ZF is set (jcc/jz/je)
@@ -91,6 +93,8 @@ Opcodes currently supported by SubX:
   f7: negate/multiply/divide rm32 (with EAX and EDX if necessary) depending on subop (neg/mul/idiv)
   ff: increment/decrement/jump/push/call rm32 based on subop (inc/dec/jmp/push/call)
   0f 2f: compare: set CF if x32 < xm32 (comiss)
+  0f 80: jump disp32 bytes away if OF is set (jcc/jo)
+  0f 81: jump disp32 bytes away if OF is unset (jcc/jno)
   0f 82: jump disp32 bytes away if lesser (addr, float), if CF is set (jcc/jb/jnae)
   0f 83: jump disp32 bytes away if greater or equal (addr, float), if CF is unset (jcc/jae/jnb)
   0f 84: jump disp32 bytes away if equal, if ZF is set (jcc/jz/je)