| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
| |
Yet another redrawing of responsibilities between convert and its helpers.
In the process I discovered a bug in `write-stream-buffered` which ended
up taking me through a detour to extract `browse_trace` into its own tool.
It turns out just having long buffers is enough to need browse_trace. Simple
operations like clearing a stream swamp a flat view of the trace.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I've extracted it into a separate binary, independent of my Mu prototype.
I also cleaned up my tracing layer to be a little nicer. Major improvements:
- Realized that incremental tracing really ought to be the default.
And to minimize printing traces to screen.
- Finally figured out how to combine layers and call stack frames in a
single dimension of depth. The answer: optimize for the experience of
`browse_trace`. Instructions occupy a range of depths based on their call
stack frame, and minor details of an instruction lie one level deeper
in each case.
Other than that, I spent some time adjusting levels everywhere to make
`browse_trace` useful.
|
|
|
|
|
|
| |
Now that our test runs are getting longer, debugging is again becoming a
bottleneck. Time to start using trace depths along with `mu browse-trace`
from the top-level.
|
| |
|
| |
|
| |
|
| |
|
|
|
|
|
| |
Bugfix: I forgot about ELF segment offsets when implementing VMAs. Eventually
segments grew large enough that I started seeing overlaps.
|
|
|
|
| |
Fix CI.
|
|
|
|
| |
Raise an error when we fall off the end of the code segment.
|
|
|
|
|
| |
Make segment management a little more consistent between initial segments
and add-on segments (using `mmap`).
|
|
|
|
| |
Detect overlapping segments when loading ELF binaries.
|
|
|
|
|
|
|
|
|
|
|
| |
Now simulated 'Memory' isn't just a single flat array. Instead it knows
about segments and VMAs.
The code segment will always be first, and the data/heap segment will always
be second. The brk() syscall knows about the data segment.
One nice side-effect is that I no longer need to mess with Memory initialization
regardless of where I place my segments.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Streamline the factorial function; we don't need to save a stack variable
into a register before operating on it. All instructions can take a stack
variable directly.
In the process we found two bugs:
a) Opcode f7 was not implemented correctly. It was internally consistent
but I'd never validated it against a natively running program. Turns out
it encodes multiple instructions, not just 'not'.
b) The way we look up imm32 operands was sometimes reading them before
disp8/disp32 operands.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Turns out I had totally the wrong idea. The stack at the start of the program
doesn't contain 2 words, one for argc and a second for argv that must then
be dereferenced to get to its contents (each a pointer to a string). It
contains a word for argc, one for argv[0], another for argv[1], and so
on.
Many thanks to Jeremiah Orians and the #bootstrappable channel on freenode
for showing me https://github.com/oriansj/mescc-tools/blob/master/test/test5/exec_enable_amd64.M1
which set me straight. I could just pop the args like that example does,
but it seems slightly more elegant, given the current calling convention,
to assume the imaginary caller handles the popping.
|
|
|
|
|
|
|
|
|
|
|
| |
The new example ex9 doesn't yet work natively.
In the process I've emulated the kernel's role in providing args, implemented
a couple of instructions acting on 8-bit operands (useful for ASCII string
operations), and begun the start of the standard library (ascii_length
is the same as strlen).
At the level of SubX we're just only going to support ASCII.
|
| |
|
|
|