about summary refs log tree commit diff stats
path: root/linux/survey_baremetal.subx
Commit message (Collapse)AuthorAgeFilesLines
* .Kartik K. Agaram2021-07-201-4/+4
|
* insert a compile phase to emit some debug infoKartik K. Agaram2021-05-141-2297/+56
|
* .Kartik K. Agaram2021-05-141-0/+1
| | | | | Fix a stack bug in survey_baremetal. I'm not sure how my tests weren't crashing, but I won't bother digging further.
* .Kartik K. Agaram2021-05-091-31/+31
| | | | | Yet another step in the slow divergence of survey_baremetal from its survey_elf roots.
* .Kartik Agaram2021-03-291-1/+1
|
* .Kartik K. Agaram2021-03-151-16/+63
|
* .Kartik K. Agaram2021-03-141-14/+0
|
* .Kartik K. Agaram2021-03-141-1/+28
|
* treat boot.hex as a SubX fileKartik K. Agaram2021-03-141-45/+45
|
* survey_baremetal: padding between segmentsKartik K. Agaram2021-03-141-10/+552
| | | | Optional.
* survey_baremetal: support /imm8Kartik K. Agaram2021-03-141-2/+14
|
* survey: document starting address of each segmentKartik K. Agaram2021-03-141-15/+80
|
* some cleanup in a translation phaseKartik K. Agaram2021-03-131-24/+9
|
* 7867Kartik K. Agaram2021-03-071-26/+26
|
* 7847Kartik K. Agaram2021-03-041-2/+2
|
* 7842 - new directory organizationKartik K. Agaram2021-03-031-0/+2720
Baremetal is now the default build target and therefore has its sources at the top-level. Baremetal programs build using the phase-2 Mu toolchain that requires a Linux kernel. This phase-2 codebase which used to be at the top-level is now under the linux/ directory. Finally, the phase-2 toolchain, while self-hosting, has a way to bootstrap from a C implementation, which is now stored in linux/bootstrap. The bootstrap C implementation uses some literate programming tools that are now in linux/bootstrap/tools. So the whole thing has gotten inverted. Each directory should build one artifact and include the main sources (along with standard library). Tools used for building it are relegated to sub-directories, even though those tools are often useful in their own right, and have had lots of interesting programs written using them. A couple of things have gotten dropped in this process: - I had old ways to run on just a Linux kernel, or with a Soso kernel. No more. - I had some old tooling for running a single test at the cursor. I haven't used that lately. Maybe I'll bring it back one day. The reorg isn't done yet. Still to do: - redo documentation everywhere. All the README files, all other markdown, particularly vocabulary.md. - clean up how-to-run comments at the start of programs everywhere - rethink what to do with the html/ directory. Do we even want to keep supporting it? In spite of these shortcomings, all the scripts at the top-level, linux/ and linux/bootstrap are working. The names of the scripts also feel reasonable. This is a good milestone to take stock at.
.highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
# Helper to check an array's bounds, and to abort if they're violated.
# Really only intended to be called from code generated by mu.subx.

== code

__check-mu-array-bounds:  # index: int, elem-size: int, arr-size: int, function-name: (addr array byte), array-name: (addr array byte)
    # . prologue
    55/push-ebp
    89/<- %ebp 4/r32/esp
    # . save registers
    50/push-eax
    51/push-ecx
    52/push-edx
    # . not bothering saving ebx; it's only clobbered if we're going to abort
    # ecx = arr-size
    8b/-> *(ebp+0x10) 1/r32/ecx
    # var overflow/edx: int = 0
    ba/copy-to-edx 0/imm32
    # var offset/eax: int = index * elem-size
    8b/-> *(ebp+8) 0/r32/eax
    f7 4/subop/multiply-eax-with *(ebp+0xc)
    # check for overflow
    81 7/subop/compare %edx 0/imm32
    0f 85/jump-if-!= __check-mu-array-bounds:overflow/disp32
    # check bounds
    39/compare %eax 1/r32/ecx
    0f 82/jump-if-unsigned< $__check-mu-array-bounds:end/disp32  # negative index should always abort
    # abort if necessary
    (write-buffered Stderr "fn ")
    (write-buffered Stderr *(ebp+0x14))
    (write-buffered Stderr ": offset ")
    (write-int32-hex-buffered Stderr %eax)
    (write-buffered Stderr " is too large for array '")
    (write-buffered Stderr *(ebp+0x18))
    (write-buffered Stderr "'\n")
    (flush Stderr)
    # exit(1)
    bb/copy-to-ebx 1/imm32
    e8/call syscall_exit/disp32
    # never gets here
$__check-mu-array-bounds:end:
    # . restore registers
    5a/pop-to-edx
    59/pop-to-ecx
    58/pop-to-eax
    # . epilogue
    89/<- %esp 5/r32/ebp
    5d/pop-to-ebp
    c3/return

__check-mu-array-bounds:overflow:
    # "fn " function-name ": offset to array '" array-name "' overflowed 32 bits\n"
    (write-buffered Stderr "fn ")
    (write-buffered Stderr *(ebp+0x14))
    (write-buffered Stderr ": offset to array '")
    (write-buffered Stderr *(ebp+0x18))
    (write-buffered Stderr "' overflowed 32 bits\n")
    (flush Stderr)
    # exit(1)
    bb/copy-to-ebx 1/imm32
    e8/call syscall_exit/disp32
    # never gets here

# potential alternative

#? __bounds-check:  # msg: (addr array byte)
#?   (write-buffered Stderr "abort: array bounds exceeded in fn ")
#?   8b/-> *(esp+4) 0/r32/eax  # we're going to abort, so just clobber away
#?   (write-buffered Stderr %eax)
#?   (write-buffered Stderr Newline)
#?   # exit(1)
#?   bb/copy-to-ebx 1/imm32
#?   e8/call syscall_exit/disp32

# to be called as follows:
#   var/reg <- index arr/rega: (addr array T), idx/regi: int
#     | if size-of(T) is 1, 2, 4 or 8
#         => # temporarily save array size to reg to check bounds
#            "8b/-> *" rega " " reg "/r32"
#            "c1/shift 5/subop/right %" reg " " log2(size-of(T)) "/imm32"
#            "3b/compare " reg "/r32 *" rega
#            "68/push \"" function "\"/imm32"  # pass function name to error message
#            "0f 8d/jump-if->= __bounds_check/disp32"
#            "81 0/subop/add %esp 4/imm32"  # drop function name
#            # actually save the index addr in reg
#            "8d/copy-address *(" rega "+" regi "<<" log2(size-of(T)) "+4) " reg "/r32"

__mu-abort-null-index-base-address:
    (write-buffered Stderr "null address in 'index'\n")
    (flush Stderr)
    # exit(1)
    bb/copy-to-ebx 1/imm32
    e8/call syscall_exit/disp32
    # never gets here

__mu-abort-null-get-base-address:
    (write-buffered Stderr "null address in 'get'\n")
    (flush Stderr)
    # exit(1)
    bb/copy-to-ebx 1/imm32
    e8/call syscall_exit/disp32
    # never gets here