Home | Notifications | New Note | Local | Federated | Search | Logout
David Chisnall (*Now with 50% more sarcasm!*)@david_chisnall@infosec.exchange
I am Director of System Architecture at SCI Semiconductor and a Visiting Researcher at the University of Cambridge Computer Laboratory. I remain actively involved in the #CHERI project, where I led the early language / compiler strand of the research, and am the maintainer of the #CHERIoT Platform.
I was on the FreeBSD Core Team for two terms, have been an LLVM developer since 2008, am the author of the GNUstep Objective-C runtime (libobjc2 and associated clang support), and am responsible for libcxxrt and the BSD-licensed device tree compiler.
Opinions expressed by me are not necessarily opinions. In all probability they are random ramblings and should be ignored. Failure to ignore may result in severe boredom and / or confusion. Shake well before opening. Keep refrigerated.
Warning: May contain greater than the recommended daily allowance of sarcasm.
No license, implied or explicit, is granted to use any of my posts for training AI models.
Joined: 2026-07-21 00:31:10
6 notes, 0 following, 0 followers
Reply to @koakuma@uwu.social
David Chisnall (*Now with 50% more sarcasm!*)@david_chisnall@infosec.exchange (2026-08-17 01:53:18)
@koakuma
SPARC had a few things for working with Smalltalk-like tagged integers. I wonder if Smalltalk on SPARC used this. You could load the values unconditionally early on in a function and then use them after the tag checks.
David Chisnall (*Now with 50% more sarcasm!*)@david_chisnall@infosec.exchange (2026-07-29 21:00:58)
When Arm introduced AArch64, they removed most predication. Conditional moves are very useful (and they added a fairly rich selection of these) and can significantly reduce the amount of branch predictor state that you need, but most other predicated instructions aren't that useful on modern pipelines. The cost of an ALU operation is so low that doing an ALU operation followed by a conditional move is still a big win over a branch in a lot of cases.
The one exception that caused a lot of discussion was memory operations. Predicated loads are really useful because you can replace a load of null-guarded things with them: do the null check and conditionally load if the check failed, and avoid the branch.
I've been pondering a few alternatives for a while and one I keep coming back to is a non-trapping load. A load that will give 0 and set a bit in the condition codes register if it would trap. This requires burning a PTE bit in not-present PTEs, because you need to differentiate between not-present-physically-but-present-logically pages (e.g. lazily allocated or swapped out pages), which should trap, and really-not-present pages (which should not trap in this mechanism).
I'm not 100% sure it would be a win, because a lot of TLBs don't bother caching not-present mappings, so you might trigger a page-table walk, but if a non-trapping load were followed by a conditional move, it could retire immediately once the condition was known and skip the load.
I still think there's probably a better approach somewhere.
Reply to @catsalad@infosec.exchange
David Chisnall (*Now with 50% more sarcasm!*)@david_chisnall@infosec.exchange (2026-07-20 22:01:04)
@catsalad Cyberquantum cloud!
David Chisnall (*Now with 50% more sarcasm!*)@david_chisnall@infosec.exchange (2026-07-20 20:08:13)
Are you doing quantum AI on the blockchain 4.0 yet?
David Chisnall (*Now with 50% more sarcasm!*)@david_chisnall@infosec.exchange (2026-07-17 05:15:44)
The Free Software movement never escaped from its origins: the early ‘80s MIT AI Lab. Two things were true in this environment:
Back when most computers had tens of KiBs of RAM and 1 MiB was a huge amount, programs were simple. Very few programs were so complex that one person could not completely understand them.
The AI Lab was full of some of the most talented programmers in the world.
This meant that the only obstacles for these people being able to fix bugs and add features to any program were access to the source code and the legal rights to modify it. Once you have those, any program was understandable by that group and they could modify it however they wished.
For the next 40 years, the FSF focused on these two things. The world around them changed. These two prerequisites were never enough for most people (what do 90% of computer users do if you give them even a modest 10,000 line C codebase and tell them they can change it however they like?) and now they aren’t enough even for competent programmers.
When Linus says ‘fork it’ to folks who don’t want LLM-extruded code in their kernel, he knows full well that it is almost impossible to fork a 40 MLoC C (and Rust now) codebase that averages more than one CVE per day and have something useful.
The Free Software movement is struggling now because it obsessed over licenses, which was never a path that would succeed, and ignored the hard problems:
How do you design environments that enable end users to modify their software?
How do you engineer software so that it is cheap and easy for a random user to maintain a fork that meets their specific needs?
How do you foster communities where people want to share improvements, so forks don’t proliferate even when it’s easy?
How do you create an environment where everyone sees the benefits of user-modifiable code to such a degree that trying to sell anything that doesn’t come with these rights is commercially impossible?
Instead of tackling any of these problems, t
David Chisnall (*Now with 50% more sarcasm!*)@david_chisnall@infosec.exchange (2026-04-24 19:05:41)
Fun thing I've learned about RISC-V recently:
There is no easy way of writing a 32-bit nop in RISC-V assembly.
RISC-V tries to make the C extension transparent. You don't need to write compressed variants of instructions, you just write as if you're targeting the 32-bit encoding and the assembler transparently shrinks some things for you. The C extension is entirely duplicated instructions: every 16-bit instruction in the C extension can also be written as a 32-bit instruction and this leaves it to the assembler to figure out which.
The exact same logic is applied to NOPs (which aren't really nops, they're add 0 to 0 and store the result in the zero register). There is a NOP and a C.NOP variant, but because NOP is an alias for ADDI x0, x0, 0 and C.NOP is an alias for C.ADDI x0, 0 (which is equivalent), the assembler will always emit C.NOP (a.k.a. C.ADDI x0, 0) if you write NOP. You can generate a non-canonical nop by doing something like ADDI x0, x15, 0x200, which can't be compressed (currently), but that's fragile.
This is an issue if you want to guarantee padding space in the instruction stream for later patching or linker relaxations.
As far as I am aware, RISC-V is the only variable-length architecture whose assembler makes this mistake. x86 and Thumb-2, for example, both have explicit mnemonics for longer nops. Thumb-2 has NOP and NOP.W. x86 has a baroque list of arguments you add to NOP to make it 2-15 bytes (it's one byte with no operands).