about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--308allocate-array.subx19
-rwxr-xr-xapps/mubin347319 -> 352146 bytes
-rw-r--r--apps/mu.subx305
-rw-r--r--mu.md16
-rw-r--r--mu_instructions8
5 files changed, 346 insertions, 2 deletions
diff --git a/308allocate-array.subx b/308allocate-array.subx
new file mode 100644
index 00000000..7040106c
--- /dev/null
+++ b/308allocate-array.subx
@@ -0,0 +1,19 @@
+# 2-arg version of allocate-array.
+
+allocate-array2:  # ad: (addr allocation-descriptor), elem-size: int, array-len: int, out: (addr handle array _)
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+    50/push-eax
+    #
+    8b/-> *(ebp+0xc) 0/r32/eax
+    f7 4/subop/multiply-into 0/r32/eax *(ebp+0x10)
+    (allocate-array *(ebp+8) %eax *(ebp+0x14))
+$allocate-array2:end:
+    # . restore registers
+    58/pop-to-eax
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
diff --git a/apps/mu b/apps/mu
index 156e0400..2cfa2ea6 100755
--- a/apps/mu
+++ b/apps/mu
Binary files differdiff --git a/apps/mu.subx b/apps/mu.subx
index af7f04a5..91f270db 100644
--- a/apps/mu.subx
+++ b/apps/mu.subx
@@ -1179,6 +1179,51 @@ test-convert-function-with-local-var-in-reg:
     5d/pop-to-ebp
     c3/return
 
+test-convert-function-with-allocate:
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # setup
+    (clear-stream _test-input-stream)
+    (clear-stream $_test-input-buffered-file->buffer)
+    (clear-stream _test-output-stream)
+    (clear-stream $_test-output-buffered-file->buffer)
+    #
+    (write _test-input-stream "fn foo {\n")
+    (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
+    (write _test-input-stream "  allocate x\n")
+    (write _test-input-stream "}\n")
+    # convert
+    (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
+    (flush _test-output-buffered-file)
+#?     # dump _test-output-stream {{{
+#?     (write 2 "^")
+#?     (write-stream 2 _test-output-stream)
+#?     (write 2 "$\n")
+#?     (rewind-stream _test-output-stream)
+#?     # }}}
+    # check output
+    (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
+    (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
+    (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
+    (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
+    (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
+    (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
+    (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
+    (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 test-initializer-in-hex:
     # . prologue
     55/push-ebp
@@ -3654,6 +3699,51 @@ test-array-size-in-hex:
     5d/pop-to-ebp
     c3/return
 
+test-convert-function-with-populate:
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # setup
+    (clear-stream _test-input-stream)
+    (clear-stream $_test-input-buffered-file->buffer)
+    (clear-stream _test-output-stream)
+    (clear-stream $_test-output-buffered-file->buffer)
+    #
+    (write _test-input-stream "fn foo {\n")
+    (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
+    (write _test-input-stream "  populate x, 7\n")
+    (write _test-input-stream "}\n")
+    # convert
+    (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
+    (flush _test-output-buffered-file)
+#?     # dump _test-output-stream {{{
+#?     (write 2 "^")
+#?     (write-stream 2 _test-output-stream)
+#?     (write 2 "$\n")
+#?     (rewind-stream _test-output-stream)
+#?     # }}}
+    # check output
+    (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-populate/0")
+    (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
+    (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
+    (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
+    (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
+    (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
+    (check-next-stream-line-equal _test-output-stream "    (allocate-array2 Heap 0x00000004 7 %ecx)"  "F - test-convert-function-with-populate/8")  # 4 = size-of(int)
+    (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
+    (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
+    (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 # special-case for size(byte) when allocating array
 test-convert-function-with-local-array-of-bytes-in-mem:
     # . prologue
@@ -11176,11 +11266,19 @@ has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
     # if (name == "compute-offset") return true
     (string-equal? %esi "compute-offset")  # => eax
     3d/compare-eax-and 0/imm32/false
-    75/jump-if-!= $has-primitive-name?:end/disp8
+    0f 85/jump-if-!= $has-primitive-name?:end/disp32
     # if (name == "lookup") return true
     (string-equal? %esi "lookup")  # => eax
     3d/compare-eax-and 0/imm32/false
-    75/jump-if-!= $has-primitive-name?:end/disp8
+    0f 85/jump-if-!= $has-primitive-name?:end/disp32
+    # if (name == "allocate") return true
+    (string-equal? %esi "allocate")  # => eax
+    3d/compare-eax-and 0/imm32/false
+    0f 85/jump-if-!= $has-primitive-name?:end/disp32
+    # if (name == "populate") return true
+    (string-equal? %esi "populate")  # => eax
+    3d/compare-eax-and 0/imm32/false
+    0f 85/jump-if-!= $has-primitive-name?:end/disp32
     # var curr/ecx: (addr primitive) = Primitives
     b9/copy-to-ecx Primitives/imm32
     {
@@ -11294,6 +11392,22 @@ check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffer
       (check-mu-lookup-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
       e9/jump $check-mu-primitive:end/disp32
     }
+    # if (op == "allocate") check-mu-allocate-stmt
+    {
+      (string-equal? %ecx "allocate")  # => eax
+      3d/compare-eax-and 0/imm32/false
+      74/jump-if-= break/disp8
+      (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
+      e9/jump $check-mu-primitive:end/disp32
+    }
+    # if (op == "populate") check-mu-populate-stmt
+    {
+      (string-equal? %ecx "populate")  # => eax
+      3d/compare-eax-and 0/imm32/false
+      74/jump-if-= break/disp8
+      (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
+      e9/jump $check-mu-primitive:end/disp32
+    }
     # otherwise check-numberlike-stmt
     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
 $check-mu-primitive:end:
@@ -11861,6 +11975,30 @@ $check-mu-lookup-stmt:end:
     5d/pop-to-ebp
     c3/return
 
+check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+$check-mu-allocate-stmt:end:
+    # . restore registers
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+$check-mu-populate-stmt:end:
+    # . restore registers
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
     # . prologue
     55/push-ebp
@@ -13747,6 +13885,24 @@ emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (ad
       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
       e9/jump $emit-subx-stmt:end/disp32
     }
+    # allocate scalar
+    {
+      # if (!string-equal?(stmt->operation, "allocate")) break
+      (string-equal? %ecx "allocate")  # => eax
+      3d/compare-eax-and 0/imm32
+      0f 84/jump-if-= break/disp32
+      (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
+      e9/jump $emit-subx-stmt:end/disp32
+    }
+    # allocate array
+    {
+      # if (!string-equal?(stmt->operation, "populate")) break
+      (string-equal? %ecx "populate")  # => eax
+      3d/compare-eax-and 0/imm32
+      0f 84/jump-if-= break/disp32
+      (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
+      e9/jump $emit-subx-stmt:end/disp32
+    }
     # - if stmt matches a primitive, emit it
     {
 $emit-subx-stmt:check-for-primitive:
@@ -14482,6 +14638,151 @@ $translate-mu-get-stmt:end:
     5d/pop-to-ebp
     c3/return
 
+translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+    50/push-eax
+    56/push-esi
+    57/push-edi
+    # esi = stmt
+    8b/-> *(ebp+0xc) 6/r32/esi
+    # var target/edi: (addr stmt-var) = stmt->inouts[0]
+    (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
+    89/<- %edi 0/r32/eax
+    #
+    (emit-indent *(ebp+8) *Curr-block-depth)
+    (write-buffered *(ebp+8) "(allocate Heap ")
+    (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
+    (write-int32-hex-buffered *(ebp+8) %eax)
+    (emit-subx-call-operand *(ebp+8) %edi)
+    (write-buffered *(ebp+8) ")\n")
+$translate-mu-allocate-stmt:end:
+    # . restore registers
+    5f/pop-to-edi
+    5e/pop-to-esi
+    58/pop-to-eax
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # var t/eax: (addr type-tree) = s->value->type
+    8b/-> *(ebp+8) 0/r32/eax
+    (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
+    (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
+    # TODO: check eax != 0
+    # TODO: check !t->is-atom?
+    # TODO: check t->left == addr
+    # t = t->right
+$addr-handle-payload-size:skip-addr:
+    (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
+    # TODO: check eax != 0
+    # TODO: check !t->is-atom?
+    # TODO: check t->left == handle
+    # t = t->right
+$addr-handle-payload-size:skip-handle:
+    (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
+    # TODO: check eax != 0
+    # if !t->is-atom? t = t->left
+    81 7/subop/compare *eax 0/imm32/false
+    {
+      75/jump-if-!= break/disp8
+      (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
+    }
+    # TODO: check t->is-atom?
+    # return size(t->value)
+    (size-of-type-id *(eax+4))  # Type-tree-value => eax
+$addr-handle-payload-size:end:
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+    50/push-eax
+    51/push-ecx
+    56/push-esi
+    57/push-edi
+    # esi = stmt
+    8b/-> *(ebp+0xc) 6/r32/esi
+    # var target/edi: (addr stmt-var) = stmt->inouts[0]
+    (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
+    89/<- %edi 0/r32/eax
+    # var len/ecx: (addr stmt-var) = stmt->inouts[1]
+    (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
+    89/<- %ecx 0/r32/eax
+    #
+    (emit-indent *(ebp+8) *Curr-block-depth)
+    (write-buffered *(ebp+8) "(allocate-array2 Heap ")
+    (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
+    (write-int32-hex-buffered *(ebp+8) %eax)
+    (emit-subx-call-operand *(ebp+8) %ecx)
+    (emit-subx-call-operand *(ebp+8) %edi)
+    (write-buffered *(ebp+8) ")\n")
+$translate-mu-populate-stmt:end:
+    # . restore registers
+    5f/pop-to-edi
+    5e/pop-to-esi
+    59/pop-to-ecx
+    58/pop-to-eax
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # var t/eax: (addr type-tree) = s->value->type
+    8b/-> *(ebp+8) 0/r32/eax
+    (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
+    (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
+    # TODO: check eax != 0
+    # TODO: check !t->is-atom?
+    # TODO: check t->left == addr
+    # t = t->right
+$addr-handle-array-payload-size:skip-addr:
+    (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
+    # TODO: check eax != 0
+    # TODO: check !t->is-atom?
+    # TODO: check t->left == handle
+    # t = t->right
+$addr-handle-array-payload-size:skip-handle:
+    (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
+    # TODO: check eax != 0
+    # TODO: check !t->is-atom?
+    # TODO: check t->left == array
+    # t = t->right
+$addr-handle-array-payload-size:skip-array:
+    (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
+    # TODO: check eax != 0
+    # if !t->is-atom? t = t->left
+    81 7/subop/compare *eax 0/imm32/false
+    {
+      75/jump-if-!= break/disp8
+      (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
+    }
+$addr-handle-array-payload-size:compute-size:
+    # TODO: check t->is-atom?
+    # return size(t->value)
+    (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
+$addr-handle-array-payload-size:end:
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
     # precondition: n is positive
     # . prologue
diff --git a/mu.md b/mu.md
index 70932baa..429f2034 100644
--- a/mu.md
+++ b/mu.md
@@ -445,6 +445,22 @@ var y/reg: (addr handle T) <- index arr: (addr array handle T), n
 copy-handle-to *y, x
 ```
 
+To create handles to non-array types, use `allocate`:
+
+```
+var x: (addr handle T)
+... initialize x ...
+allocate x
+```
+
+To create handles to array types, use `populate`:
+
+```
+var x: (addr handle array T)
+... initialize x ...
+populate x, 3  # array of 3 T's
+```
+
 You can copy handles to another variable on the stack like this:
 
 ```
diff --git a/mu_instructions b/mu_instructions
index 7b38a1f8..c23606ec 100644
--- a/mu_instructions
+++ b/mu_instructions
@@ -258,4 +258,12 @@ out/reg: (addr T) <- lookup in: (handle T)
      "8b/-> *(epb+" (in.stack-offset+4) ") " reg "/r32"
      "81 0/subop/add %" reg " 4/imm32"  # skip payload->allocid
 
+# Allocating memory
+
+allocate in: (addr handle T)
+  => "(allocate Heap " size-of(T) " " in ")"
+
+populate in: (addr handle array T), num  # can be literal or variable on stack or register
+  => "(allocate-array2 Heap " size-of(T) " " num " " in ")"
+
 vim:ft=mu:nowrap:textwidth=0
3: 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) 75: jump disp8 bytes away if not equal, if ZF is not set (jcc/jnz/jne) 76: jump disp8 bytes away if lesser or equal (addr, float), if ZF is set or CF is set (jcc/jbe/jna) 77: jump disp8 bytes away if greater (addr, float), if ZF is unset and CF is unset (jcc/ja/jnbe) 7c: jump disp8 bytes away if lesser, if SF != OF (jcc/jl/jnge) 7d: jump disp8 bytes away if greater or equal, if SF == OF (jcc/jge/jnl) 7e: jump disp8 bytes away if lesser or equal, if ZF is set or SF != OF (jcc/jle/jng) 7f: jump disp8 bytes away if greater, if ZF is unset and SF == OF (jcc/jg/jnle) 81: combine rm32 with imm32 based on subop (add/sub/and/or/xor/cmp) 87: swap the contents of r32 and rm32 (xchg) 88: copy r8 to r8/m8-at-r32 89: copy r32 to rm32 (mov) 8a: copy r8/m8-at-r32 to r8 8b: copy rm32 to r32 (mov) 8d: copy address in rm32 into r32 (lea) 8f: pop top of stack to rm32 (pop) 99: sign-extend EAX into EDX (cdq) b8: copy imm32 to EAX (mov) b9: copy imm32 to ECX (mov) ba: copy imm32 to EDX (mov) bb: copy imm32 to EBX (mov) bc: copy imm32 to ESP (mov) bd: copy imm32 to EBP (mov) be: copy imm32 to ESI (mov) bf: copy imm32 to EDI (mov) c1: shift rm32 by imm8 bits depending on subop (sal/sar/shl/shr) c3: return from most recent unfinished call (ret) c6: copy imm8 to r8/m8-at-r32 with subop 0 (mov) c7: copy imm32 to rm32 with subop 0 (mov) cd: software interrupt (int) d3: shift rm32 by CL bits depending on subop (sal/sar/shl/shr) e8: call disp32 (call) e9: jump disp32 bytes away (jmp) eb: jump disp8 bytes away (jmp) f4: halt (hlt) 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) 0f 85: jump disp32 bytes away if not equal, if ZF is not set (jcc/jnz/jne) 0f 86: jump disp32 bytes away if lesser or equal (addr, float), if ZF is set or CF is set (jcc/jbe/jna) 0f 87: jump disp32 bytes away if greater (addr, float), if ZF is unset and CF is unset (jcc/ja/jnbe) 0f 8c: jump disp32 bytes away if lesser, if SF != OF (jcc/jl/jnge) 0f 8d: jump disp32 bytes away if greater or equal, if SF == OF (jcc/jge/jnl) 0f 8e: jump disp32 bytes away if lesser or equal, if ZF is set or SF != OF (jcc/jle/jng) 0f 8f: jump disp32 bytes away if greater, if ZF is unset and SF == OF (jcc/jg/jnle) 0f 92: set r8/m8-at-rm32 to 1 if lesser (addr, float), if CF is set, 0 otherwise (setcc/setb/setnae) 0f 93: set r8/m8-at-rm32 to 1 if greater or equal (addr, float), if CF is unset, 0 otherwise (setcc/setae/setnb) 0f 94: set r8/m8-at-rm32 to 1 if equal, if ZF is set, 0 otherwise (setcc/setz/sete) 0f 95: set r8/m8-at-rm32 to 1 if not equal, if ZF is not set, 0 otherwise (setcc/setnz/setne) 0f 96: set r8/m8-at-rm32 to 1 if lesser or equal (addr, float), if ZF is set or CF is set, 0 otherwise (setcc/setbe/setna) 0f 97: set r8/m8-at-rm32 to 1 if greater (addr, float), if ZF is unset and CF is unset, 0 otherwise (setcc/seta/setnbe) 0f 9c: set r8/m8-at-rm32 to 1 if lesser, if SF != OF, 0 otherwise (setcc/setl/setnge) 0f 9d: set r8/m8-at-rm32 to 1 if greater or equal, if SF == OF, 0 otherwise (setcc/setge/setnl) 0f 9e: set r8/m8-at-rm32 to 1 if lesser or equal, if ZF is set or SF != OF, 0 otherwise (setcc/setle/setng) 0f 9f: set r8/m8-at-rm32 to 1 if greater, if ZF is unset and SF == OF, 0 otherwise (setcc/setg/setnle) 0f af: multiply rm32 into r32 (imul) f3 0f 10: copy xm32 to x32 (movss) f3 0f 11: copy x32 to xm32 (movss) f3 0f 2a: convert integer to floating-point (cvtsi2ss) f3 0f 2c: truncate floating-point to int (cvttss2si) f3 0f 2d: convert floating-point to int (cvtss2si) f3 0f 51: square root of float (sqrtss) f3 0f 52: inverse square root of float (rsqrtss) f3 0f 53: reciprocal of float (rcpss) f3 0f 58: add floats (addss) f3 0f 59: multiply floats (mulss) f3 0f 5c: subtract floats (subss) f3 0f 5d: minimum of two floats (minss) f3 0f 5e: divide floats (divss) f3 0f 5f: maximum of two floats (maxss) Run `bootstrap help instructions` for details on words like 'r32' and 'disp8'. For complete details on these instructions, consult the IA-32 manual (volume 2). There's various versions of it online, such as https://c9x.me/x86. The mnemonics in brackets will help you locate each instruction.