#MINTIA (not vibecoded)

1 messages · Page 16 of 1

twilit smelt
#

i think the emulator has reached a point where i can squeeze out little bits here and there but the only major gain left to be had is to have conditionalized code for basically an alternate whole memory access structure

#

which discards the realism and is geared for performance

#

and ill probably do that

#

i was kind of intentionally waiting to do that so that the "realistic" emulation would see performance work too

#

and i managed to get wayyyy higher with that than i anticipated

warm mural
#

watch me make a jit and get 2x performance

blissful smelt
#

kvm trl

warm mural
#

nah kvm is for native archs

#

the point is you run code natively

twilit smelt
#

i wasnt counting that

warm mural
#

a jit with an existing library would work

#

and be not that hard to do

dense vigil
#

especially for such an easily jittable thing

#

2x is like just unrolling a switch into asm calling into C

warm mural
#

yeah idk i just said a random number

#

idk if libgccjit would be useful here tho

#

or something more low level

dense vigil
#

not sure but sounds like a cool project

#

either that or a TCC backend would be based af

#

for qemu

warm mural
#

TCC?

#

you mean TCG?

dense vigil
#

TCC/TCG yeah

#

iirc they use the same thing

warm mural
#

more like a tcg frontend

dense vigil
#

yeah

warm mural
#

well qemu has been ported to so much shit I dont think it would be that hard

dense vigil
#

probs

safe hollow
#

mapping their ll/sc stuff over xrarch would be annoying

#

as on xrarch every other store causes the pair to fail i think?

dense vigil
#

u can sacrifice precision

twilit smelt
#

so id be surprised if they have no way to model it

#

on Alpha even device DMA will cause an ll/sc pair to fail

#

and they use this

#

extensively

safe hollow
#

i guess it just kills the reservation unconditionally?

twilit smelt
#

the ll/sc pair will fail if the device does a DMA write to the cache line iirc

#

so its the same as if any processor did a store

teal trench
#

since if you disable caches ll/sc will fail indefinitely for example

twilit smelt
#

on at least alpha and mips

teal trench
#

ah

twilit smelt
#

and that was the preferred way to release a spinlock for example because it was faster than sc

#

only worked cuz itd cause the ll/sc pair to fail

#

actually no i dont think it matters in that specific case

warm mural
#

Yea I don't understand that stuff so I'm not qualified to do a qemu port

#

I should learn more about that kind of cpu stuff

blissful smelt
#

does abbix mean anything

#

Application Binary Interface BIX

warm mural
#

No I chose it when I was like 10

#

It's the buttons on an Xbox controller

#

ABYX

#

But rewritten

#

It's too late now to change my username I think

dense vigil
#

what is rustc

warm mural
#

rust compiler

dense vigil
#

ah

#

i thought it was like rust C

warm mural
#

No it's the actual name of the rust compiler

dense vigil
#

yeah i remember now

blissful smelt
#

crusty

mortal barn
#

does xremu work on Big Endian hosts
I'll run it on a Wii and report how many KHz it gets trl

twilit smelt
#

in the readme

mortal barn
#

oh 💀

#

damn

#

so no

#

oh well

#

I can guess that the answer would probably be pretty low

#

last I checked, it runs at around 1/200th the effective speed of a Core 2 Duo E8400

heady bobcat
#

just stick a le32toh around every read from memory and hope for the best :-)

mortal barn
#

lmao

mortal thunder
#

so...

#

i suppose you could theoretically just turn on LE for the emulator portion and then turn on BE for everything else?

#

are instructions byte-reversed in little endian mode?

mortal barn
#

yes but it can't really run anything useful

#

the chance that xremu builds with Visual C++ 4.0 RISC Edition for PowerPC is...... basically 0

#

and no other compiler exists for NT PPC

mortal thunder
#

I said NT, a little endian OS, can run on the wii, so any little endian application could run on the wii

mortal barn
#

yes, you can turn on MSR[LE]

#

but then everything else breaks

#

Linux was never designed to work like that, it has 0 little endian PPC32 support

#

libogc is the same deal

#

except it'd be an even harder port because you gets basically nothing representitive of a real OS worth a damn

mortal thunder
#

or is it the same byte format regardless

#

if not, then it shouldn't be that hard to just turn it off before every syscall

#

if it is, then it's actually pretty difficult, i agree

mortal barn
#

one sec I can check

#

yes it would appear to be

#

same bytes are interpreted different in BE vs LE

#

you also need supervisor access to flip modes

twilit smelt
#

There was a bug in early discord like 10 years ago in 2015 where the "X is typing..." indicator at the bottom of a chat could get jammed on and say that for weeks straight even if they typed something else

#

Often channels would just accumulate these over time until they constantly said "several people are typing..." at all times

#

Sometimes I miss that.

hot shadow
#

It's moderately difficult afaik, you can look into avr target in target/avr and hw/avr - there's a couple thousand lines of code and from a glance the arch is super simple
translate.c does most of the heavy lifting

tulip anchor
#

Marvin (autotools pest control) is typing…

twilit smelt
#

try again again

#

this time build it with make FASTMEMORY=1

#

i now get this on my m1 macbook air lol

#

its executing 0.7-0.8 guest BIPS

twilit smelt
#
706880126 cycles per second
704879603 cycles per second
703879696 cycles per second
703879239 cycles per second
704879466 cycles per second
702879764 cycles per second
702880129 cycles per second
#

i declare the emulator saga closed

#

i brought it up from 40mips peak to 700mips

#

and when its only doing 20mips it now only uses like 30% of one efficiency core on my m1 mba. it used to use 50% of a performance core

#

on my shitty 2015 intel imac it uses 10% of a core while doing 20mips

oak spade
#

damn very nice

twilit smelt
#

now that this saga is over i can return to mintia2 io system

#

in like idk a few months whenever i have a break

#

lolz

dense vigil
twilit smelt
#

Its an alternate memory subsystem optimized for performance

#

Rather than realism

#

The original realistic one is still pretty fast on its own, 300 MIPS

#

or so

dense vigil
#

Ah cool

blissful smelt
blissful smelt
#

awesome sauce!!!!

#

wow this is like amd athlon 64 speeds now

#

didnt that have a base of 1ghz

#

blisteringly fast

twilit smelt
blissful smelt
#

HUGE

twilit smelt
#

we can just round that up and claim 1 BIPS on your machine

blissful smelt
#

or I can just test on a 11th gen i7 and try to get bigger number

twilit smelt
#

I managed to make paging incredibly speedy is where most of that came from

#

I used a very very neat trick though I do say so myself

blissful smelt
#

hmmm this is on wsl, i'll try to see if i can get it natively running

#

should work fine

twilit smelt
#

that's probably just as fast as it runs

#

When you get to speeds like that it gets extremely sensitive to cache configurations and stuff

#

So there's probably just something unlucky happening on chip

blissful smelt
#

I'll hop back over to my mac and see if i can get good rng over there

twilit smelt
#

By pure chance

#

Of how the cache on that particular chip is laid out

#

If the exact bottleneck was discovered it could be changed but then there'd be some other rng bottleneck on other machines

#

It's like trying to flatten a carpet and every time you flatten the bulge it just pops up somewhere else

blissful smelt
#

I'll cache align things and see if that does anything

#

__attribute__((aligned(64))) my beloved

twilit smelt
#

Could help

#

The hot structures are in xr.h

#

In particular some fields in XrProcessor and also the structures XrIblock (which caches a run of decoded instructions) and XrCachedInst (which holds a decoded instruction) and stuff

#

Play around and if you find something that gets a consistent improvement I'll try it out and potentially merge

icy bridge
#

this is what i get on native linux (ryzen 5800X)

twilit smelt
#

About 600 MIPS

#

Highest so far is 1 BIPS on gummi's machine. Second highest is 700 MIPS on my m1 MacBook Air

twilit smelt
icy bridge
#

yeah

twilit smelt
#

On latest commit

#

ok

icy bridge
#

oh not latest commit, it's from like 1 or 2 days ago i think

#

i'll try latest commit 2s

twilit smelt
#

Major improvements may have occurred in that time

#

I don't remember though lol

icy bridge
#

oh btw the cmdline i'm using is ./graphical.sh -dks mintia-XRstation-fre.img -threads 16 -cpuhz 4000000000, anything obvious i should change there?

twilit smelt
#

Just do a single thread

#

There's only 1 cpu anyway

#

UI is still in a separate thread

#

Old mintia doesn't support smp so adding more CPUs will be ineffectual, it doesn't see them and can't use them

#

It predates SMP actually

icy bridge
#

this is with latest commit CC=clang FASTMEMORY=1, -threads 1

twilit smelt
#

Another unlucky case I guess

#

I hate cache rng lol

#

Which I'm assuming is causing the seeming lack of correlation between host processor speed and max performance of this emulator

#

whether the host cache happens to be configured such that it plays nicely with the emulator may be a much greater factor than anything else

#

In any case that's far faster than it even needs to run lol

blissful smelt
#

ok for some reason it now starts giving 700MIPS whereas it was doing 920MIPS prior, and I thought it was because I did the attribute aligned, but I removed that and it was the same

icy bridge
#

that doesn't seem right

#

only thing i changed is 10x the number of runs

twilit smelt
#

It overflowed

icy bridge
#

ahhh

twilit smelt
#

A 32 bit integer inside dhrystone

#

While calculating the score

#

Use fewer runs lol

icy bridge
#

note to self don't do 20M runs

twilit smelt
#

Downside of 1-to-1 translation of a benchmark program that was popular in 1986

blissful smelt
#

nvm it's back

#

I will try to cache align a few things instead of everything then lol

twilit smelt
#

Packing it in the cache I suspect is more beneficial than cache aligning

#

In this case

#

But idrk and u can try

warm pine
twilit smelt
#

Yeah I figured out how to make accesses with paging enabled extremely quick

#

It inlines to like 15 instructions in the fast path

#

Inlined into the execute routines for the load and store instructions

#

That gave most of the speed up

blissful smelt
#

cache aligning the icache and dcache in the emulator helped a bit

#

consistently better by a bit

twilit smelt
#

But the icache and dcache are compiled out entirely when FASTMEMORY=1

blissful smelt
#

hmmm i guess this is rng again

twilit smelt
#

Lmfao

#

It's fast enough already

twilit smelt
#

1 BIP is beyond my wildest dreams when I set out

#

I expected 2-6x improvement

#

I got 18x at least

#

Job is done

#

Staticsaga guessed the theoretical limit for a cached interpreter at around 340 MIPS lol

#

More than doubled that so I'm happy

#

@safe hollow @acoustic sparrow this guy got ~960 guest MIPS on my emulator

#

Can we round that up to 1 BIPS

twilit smelt
blissful smelt
#

M4

#

64 byte alignment

twilit smelt
#

It seems that it has a ludicrously good indirect branch predictor

#

(saga's words)

blissful smelt
#

i wonder if closing other things on the system helps

#

i shall vanish for a bit

twilit smelt
#

Anyway I have to sleep bye

twilit smelt
#

I consistently get better performance on my Intel iMac if I pause my music while I run dhrystone lol

#

The system audio threads take enough cpu time to notice on the dhrystone results

blissful smelt
#

biggest number yet i think

#

well that's pretty great

icy bridge
#

this is what i get with nothing else running on the system and taskset -c 0

blissful smelt
#

ryzen 5800x too wow

icy bridge
#

for reference previous numbers were with like 15 firefox tabs open, one of which doing video playback, and my system's file indexer running in the background

blissful smelt
#

well I guess That's The Run then

#

inb4 abbix tells us all how they could get xremu to run 5 morbillion times faster than the host CPU with a JIT

warm mural
#

But it'd be fun to do

twilit smelt
warm mural
#

Yeah sure

#

A JIT isn't really needed now but it'd def speed it up even more

mortal thunder
#

cause instructions are fixed 4 bytes etc

warm mural
#

it's not really luck tho meme

dense vigil
#

btw what's the state of your Linux port atm

twilit smelt
icy bridge
twilit smelt
twilit smelt
#

I hope this is at least educational for you lol

#

Retargeting all this stuff

icy bridge
#

Oh yeah definitely

warm mural
#

write a jackal-to-C tool and rewrite mintia in C

#

and get free perf boost with gcc optimizations

icy bridge
#

it's how jackal-written host tools are compiled

warm mural
#

ohh right

blissful smelt
#

like it started off with lua

#

very interesting 👍

queen torrent
#

Real hardware xrarch linux when

blissful smelt
#

they got close with the real hardware part

#

someone half implemented it in verilog for an fpga

#

it got far enough to reach the boot console

warm mural
#

didnt pitust get it to work using a baremetal emulator

sterile frost
icy bridge
#
/base_dir/sources/binutils/gprofng/libcollector/configure: line 18421: syntax error near unexpected token `-Wno-nonnull-compare,'
/base_dir/sources/binutils/gprofng/libcollector/configure: line 18421: `ACX_PROG_CC_WARNING_OPTS(-Wno-nonnull-compare, GPROFNG_NO_NONNULL_COMPARE_CFLAGS)'```
sterile frost
#

it looks like it's parallelizing it incorrectly or something, it's weird

icy bridge
#

hm

sterile frost
#

oh i didn't see that :^)

icy bridge
#

can you send sources/binutils/gprofng/libcollector/configure.ac and sources/binutils/gprofng/libcollector/configure?

#

i want to diff them with my versions

twilit smelt
#

Ouroboros

sterile frost
twilit smelt
#

So was the old assembler and linker

sterile frost
#

what was the bootstrap jackal compiler written in

twilit smelt
#

But all are now in jackal

icy bridge
#
$ sha256sum configure configure.2 configure.ac configure.ac.2
caf82c618b3aaec7d038a25523bd202439b15a76f1bbfbbe78e0ffc6b07d5bc9  configure
caf82c618b3aaec7d038a25523bd202439b15a76f1bbfbbe78e0ffc6b07d5bc9  configure.2
71ddf5f329b89c1e4e0e33114f021ed3758aa341be6f3b324a3859d6602eddbf  configure.ac
71ddf5f329b89c1e4e0e33114f021ed3758aa341be6f3b324a3859d6602eddbf  configure.ac.2``` well then
#

that isn't the issue

sterile frost
#

ouch

warm mural
#

writing a bootstrap compiler in an "easy language" is the way

sterile frost
#

or even better

#

don't mess up your build and just do it on a fresh clone :^)

twilit smelt
sterile frost
#

i literally just cloned it and that's what i get, i also tried building it few days ago on a different system and it failed in the same way

twilit smelt
#

no preprocessor support other than includes

#

The whole jackal compiler was written with it before it could compile itself

sterile frost
#

btw @icy bridge is the autoconf patch supposed to say UNAME_MACINE? looks like a misspelling of UNAME_MACHINE, it's on line 9 of the patch

twilit smelt
#

It now uses features not implemented by the bootstrap compiler but only by itself so the bootstrap compiler cant compile the real compiler anymore. It stands fully on itself and if all functional jackal compiler binaries disappeared from the earth id be in BIG trouble

sterile frost
#

considering the patch context includes lines for xtensa linux which reference UNAME_MACHINE i am guessing it's wrong :^)

twilit smelt
#

So the toolchain is fully self contained

#

No OS project is complete without a self hosting toolchain developed alongside it

#

Just ask Linux and NT

#

(and almost all OS projects between 1965 and 1985)

#

I think self hosting a toolchain is among the 10 most satisfying things you can do with a computer

icy bridge
#

@sterile frost cannot reproduce

sterile frost
#

wtf

icy bridge
#

tried a clean clone and everything

#

what was your jinx init cmdline?

sterile frost
#

mkdir build; cd build; ../jinx init ..

icy bridge
#

try ../jinx init ARCH=xr17032

#

should probably add a readme

sterile frost
#

oh wow

#

yeah meme

icy bridge
#

also fair warning, the binutils port is functional but not complete

#

in particular the assembler:

  • does not emit any warnings or errors when values don't fit in immediate fields
  • does not implement any pseudo instructions
  • does not infer immediate versions of instructions if the non-immediate mnemonic is used with an immediate operand
sterile frost
#
iretq@DESKTOP-TAQSOFJ:~/xrlinux/build$ ls -la host-pkgs/binutils/usr/local/bin/
total 81236
drwxr-xr-x 2 iretq iretq    4096 Aug 19 17:57 .
drwxr-xr-x 6 iretq iretq    4096 Aug 19 17:57 ..
-rwxr-xr-x 1 iretq iretq 4669432 Aug 19 17:57 xr17032-unknown-linux-gnu-addr2line
-rwxr-xr-x 2 iretq iretq 4843960 Aug 19 17:57 xr17032-unknown-linux-gnu-ar
-rwxr-xr-x 2 iretq iretq 6298872 Aug 19 17:57 xr17032-unknown-linux-gnu-as
-rwxr-xr-x 1 iretq iretq 4617936 Aug 19 17:57 xr17032-unknown-linux-gnu-c++filt
-rwxr-xr-x 1 iretq iretq  117488 Aug 19 17:57 xr17032-unknown-linux-gnu-elfedit
-rwxr-xr-x 1 iretq iretq 5229408 Aug 19 17:57 xr17032-unknown-linux-gnu-gprof
-rwxr-xr-x 4 iretq iretq 7844976 Aug 19 17:57 xr17032-unknown-linux-gnu-ld
-rwxr-xr-x 4 iretq iretq 7844976 Aug 19 17:57 xr17032-unknown-linux-gnu-ld.bfd
-rwxr-xr-x 2 iretq iretq 4734624 Aug 19 17:57 xr17032-unknown-linux-gnu-nm
-rwxr-xr-x 2 iretq iretq 5454240 Aug 19 17:57 xr17032-unknown-linux-gnu-objcopy
-rwxr-xr-x 2 iretq iretq 7818920 Aug 19 17:57 xr17032-unknown-linux-gnu-objdump
-rwxr-xr-x 2 iretq iretq 4843992 Aug 19 17:57 xr17032-unknown-linux-gnu-ranlib
-rwxr-xr-x 2 iretq iretq 4041240 Aug 19 17:57 xr17032-unknown-linux-gnu-readelf
-rwxr-xr-x 1 iretq iretq 4658552 Aug 19 17:57 xr17032-unknown-linux-gnu-size
-rwxr-xr-x 1 iretq iretq 4681552 Aug 19 17:57 xr17032-unknown-linux-gnu-strings
-rwxr-xr-x 2 iretq iretq 5454240 Aug 19 17:57 xr17032-unknown-linux-gnu-strip```
#

perfect :^)

twilit smelt
#

I think the weirdest thing about it is that all the load instructions zero extend and there's no sign extending versions so you have to left shift and arithmetic right shift for sign extension

#

That's the opposite of typical and is basically by accident

#

But there is a reason which is that people usually write C programs with tons of signed types and so that's what ends up usually being fastest which is why loads are always sign extending on like MIPS. but df and jackal programs tend to use almost all unsigned types

icy bridge
#

it's pretty nice in general, the two things that mainly stand out to me are:

  • regular jumps/calls (not indirect or beq zero, <target>) having absolute targets instead of pcrel ones is weird imo. for jumps this can be mitigated by using beq zero, but there is no equivalent way to get a pcrel call. this fucks up ELF dynamic linking because it's impossible to get your own pc and means pre-relocation code (aka the code that relocates the dynamic linker) cannot involve any function calls
  • the comparing branch instructions don't have signed versions
#

also pcrel targets for j/jal would mean the weird "upper bit of target is upper bit of pc" thing doesn't have to exist

#

but that's not a super big deal

twilit smelt
#

Which resolves this

icy bridge
twilit smelt
#

That's how riscv does it

#

Would that be helpful

icy bridge
#

yeah that'd work

twilit smelt
#

Yaoi pc instruction

icy bridge
sterile frost
#

very nice, thanks 🙏

twilit smelt
#

I don't think I use that immediate offset on jalr literally ever

#

So I don't think that'd break anything lol

icy bridge
#

it isn't?

#

oops

#

docs say it is

twilit smelt
#

Lmao

icy bridge
# icy bridge yeah that'd work

actually now that i think about it this doesn't really work because that would have a granularity of 64K while relocation has a granularity of 4K (page size)

twilit smelt
#

It has a byte granularity

icy bridge
#

auipc presumably only loads the top half of the register

#

that's what it does on riscv at least

twilit smelt
#

No it shifts the immediate left by 16 and adds it to pc and stores the full result in the register

icy bridge
#

ah ok

twilit smelt
#

Then the immediate offset on jalr provides the lower 16 bits

icy bridge
#

yeah nevermind that'd work then

twilit smelt
#

So this instruction pair does a full 32+32 add of pc+immediate

icy bridge
#

if it were a perfect world i'd prefer j/jal being made pcrel instead of (or in addition to) auipc being added but that'd break abi

sterile frost
#

what abi

twilit smelt
#

The one followed by the like 200kloc of guest code that runs currently

#

Wdym what abi

icy bridge
#

also is there a reason why j and jal are two different actual instructions instead of j being a pseudoinstruction for jal zero, x

sterile frost
#

oh you want to

#

i see

icy bridge
sterile frost
#

i misread the message sorry...

twilit smelt
icy bridge
#

they're both (pc & 0x80000000) | (imm29 << 2)

sterile frost
#

wouldn't that simply be an assembler change though

twilit smelt
#

They have 29 bit immediates

#

You're suggesting I encode a register number in JAL

icy bridge
#

oh wait yeah that'd need a new register number

twilit smelt
#

That takes up 5 bits

twilit smelt
# mortal thunder cause instructions are fixed 4 bytes etc

Also this doesn't help at all because that only speeds up decoding which is what I'm caching anyway. What actually helps is that the icache is incoherent so I don't need to watch for writes into cached basic blocks cuz every time the instruction stream is dynamically modified there's a manual icache flush which I can hook for basic block cache flushing

icy bridge
twilit smelt
#

Also your suggestion wouldn't cover the entire 2GB of kernel and user space

#

Which was the nice property I liked

icy bridge
#

is this the jal zero, x suggestion or the pcrel one

twilit smelt
#

pcrel

icy bridge
#

yeah fair enough

twilit smelt
#

It'd only cover +-1GB from current pc

#

This works better with my dynamic linking scheme which is more like PE than ELF

icy bridge
#

yeah fair enough

twilit smelt
#

I considered stuff I just made different trade offs from the ones linux would prefer sometimes

#

Cuz I was running notlinux

#

The zero extended loads are an example of optimizing for running not-C as well lol

icy bridge
sterile frost
#

does xr3278143128 have some way to sign extend?

#

sorry i dont know the numbers

#

xr10374

icy bridge
#

xr17032

sterile frost
#

close enough tf

twilit smelt
sterile frost
#

got one digit wrong and in the wrong order

icy bridge
twilit smelt
#

so you should see how they do it

#

They might just always use auipc in that case

twilit smelt
icy bridge
#

they have the jal x, target thing

#

where target is pcrel

#

and j is a pseudoinstruction

twilit smelt
#

MIPS definitely has absolute jal target

icy bridge
#

alright i'll take a look

twilit smelt
#

You can generate calls with the auipc jalr sequence always if something is compiled as PIE

#

I can make my emulator do fusion on this pair doing funny cached interpreter tricks so it's not any slower

glossy leaf
twilit smelt
#

Can't say the same for a real in order chip implementation

icy bridge
#

This is a PC-region branch (not PC-relative); the effective target address is in the “current” 256MB-aligned region huh this really is just xr17032's j/jal except a smaller region

twilit smelt
twilit smelt
#

SPARC's calls work similarly as well

glossy leaf
#

ah wait yeah, its not pc relative its just within the same region as the pc

icy bridge
twilit smelt
#

can you show me

icy bridge
#

so i'll probably do that

#

first is fPIC, second is without

twilit smelt
#

I have a gap between classes today and I'll use that to clean up the documentation mistakes you pointed out and probably implement auipc

icy bridge
#

sounds good

twilit smelt
#

Also I think what I thought was inconsistent was the jalr immediate being left shifted by 2 cuz that's inconsistent with the other arithmetic immediates and is also unnecessary because auipc provides a whole upper 16 bits anyway

sterile frost
#

let me ask again but this time let me actually be respectful: does xr17032 have a way to sign extend a value?

twilit smelt
#

So rather than making the emulator left shift it, I might change the specification for it to lack the shift

twilit smelt
sterile frost
#

interesting, thanks

twilit smelt
icy bridge
twilit smelt
#

True enough, I think the sign extension is unique though

icy bridge
#

it is yeah

#

i have a simm16_2 operand type specifically for jalr

#

making it zero-extended makes sense but imo removing the left shift doesn't

dense vigil
dense vigil
#

Also I thought u only had like a demo userspace that couldn't do much

icy bridge
#

that's mintia2

twilit smelt
#

mintia2 has no userspace

#

at all lol

icy bridge
#

old mintia is fairly complete and there are other oses targeting xr17032

dense vigil
#

What sort of apps did it have?

twilit smelt
#

Also I don't want to make every person who ever downloaded the emulator be confused why everything broke suddenly

#

Breaking changes are just annoying

icy bridge
dense vigil
#

Damn

twilit smelt
#

Plus it had like a userspace server or two

#

It had a userspace server for like logon and user management

#

amssrv.exe

#

But don't remind me how much work I discarded

icy bridge
twilit smelt
#

Look at the not pseudoinstruction

icy bridge
#

i don't see a not pseudoinstruction in the handbook

#

let me look at newsdk

icy bridge
#

i don't see it in XrRegisterKeywords either

twilit smelt
#

It uses NOR

icy bridge
#

ohh nor ra, rb, zero

#

makes sense

#

i was wondering why there was a dedicated nor instruction, that's not a particularly common operation

twilit smelt
icy bridge
#

progress on gcc port: $ echo 'void _start(){}' | host-pkgs/gcc-bootstrap/usr/local/bin/xr17032-unknown-linux-gnu-gcc -x c -S -o /dev/stdout - .file "<stdin>" .text .p2align 2 .globl _start .type _start, @function _start: subi sp,sp,8 mov long [sp + 4],s0 mov long [sp],lr addi s0,sp,8 addi zero,zero,0 mov s0,long [sp + 4] mov lr,long [sp] addi sp,sp,8 jalr zero,lr,0 .size _start, .-_start .ident "GCC: (GNU) 15.2.0"

acoustic sparrow
#

what happens if you run with -O3?

icy bridge
#

internal compiler error because i haven't defined instructions for some operations yet, but here's -O1 $ echo 'void _start(){}' | host-pkgs/gcc-bootstrap/usr/local/bin/xr17032-unknown-linux-gnu-gcc -x c -S -o /dev/stdout - -O1 .file "<stdin>" .text .p2align 2 .globl _start .type _start, @function _start: jalr zero,lr,0 .size _start, .-_start .ident "GCC: (GNU) 15.2.0"

#

and -O0 -fomit-frame-pointer: $ echo 'void _start(){}' | host-pkgs/gcc-bootstrap/usr/local/bin/xr17032-unknown-linux-gnu-gcc -x c -S -o /dev/stdout - -fomit-frame-pointer .file "<stdin>" .text .p2align 2 .globl _start .type _start, @function _start: addi zero,zero,0 jalr zero,lr,0 .size _start, .-_start .ident "GCC: (GNU) 15.2.0"

#

compiling into an object file also works: ```
$ host-pkgs/binutils/usr/local/bin/xr17032-unknown-linux-gnu-objdump -d test.o

test.o: file format elf32-xr17032

Disassembly of section .text:

00000000 <_start>:
0: b4 f7 08 00 subi sp,sp,0x8
4: aa 5f 01 00 mov long [sp + 0x4],s0
8: f9 07 1e 90 mov long [zero + sp LSH 0],lr
c: fc f2 08 00 addi s0,sp,0x8
10: 3c 00 00 00 addi zero,zero,0x0
14: eb f2 01 00 mov s0,long [sp + 0x4]
18: f9 07 1e d0 mov lr,long [zero + sp LSH 0]
1c: bc f7 08 00 addi sp,sp,0x8
20: 38 f8 00 00 jalr zero,lr,0x0```

dense vigil
#

how good is gcc's per arch abstraction?

icy bridge
#

it's decent ig? there's still a decent amount of stuff that's effectively duplicated (for example i had to "write" (read: copy from riscv) stack layout computation, prologue/epilogue generation, that kinda stuff)

queen torrent
#

kind of on a tangent here but where did you learn how to port gcc and binutils to a new architecture? I've always been curious of the process

dense vigil
#

you would think after porting it to 9999 arches it would be streamlined

icy bridge
#

from there i just kept compiling and fixing whatever error i got until it worked

#

same with runtime errors really

dense vigil
#

would be funny to add a jackal frontend lol

#

all of a sudden the entire mintia would probably get optimized out

icy bridge
#

a very-long-term goal is to add a xr17032 backend to llvm as well then build a jackal compiler on top of that

dense vigil
#

damn

icy bridge
#

i don't think it'd be able to compile mintia2 though

dense vigil
#

it probably relies on the compiler being primitive in a lot of places

icy bridge
#

i've come across a few places in that codebase where it makes some assumptions about compiler codegen behavior that llvm would definitely violate

dense vigil
#

yep

icy bridge
#

for example backtracing

dense vigil
#

well at O0 might work

icy bridge
#

thats some funny codegen but the assembler accepts it so who cares

icy bridge
# icy bridge internal compiler error because i haven't defined instructions for some operatio...

for reference this is the specific error (it's the same for O2 and O3) $ echo 'void _start(){}' | host-pkgs/gcc-bootstrap/usr/local/bin/xr17032-unknown-linux-gnu-gcc -x c -S -o /dev/stdout - -O2 .file "<stdin>" .text during RTL pass: compgotos <stdin>: In function '_start': <stdin>:1:15: internal compiler error: in invalid_rtx, at ./insn-target-def.h:48 0x172d0b1 internal_error(char const*, ...) /base_dir/sources/gcc/gcc/diagnostic-global-context.cc:517 0x60ecc1 fancy_abort(char const*, int, char const*) /base_dir/sources/gcc/gcc/diagnostic.cc:1749 0x603006 invalid_rtx ./insn-target-def.h:48 0x14d79db get_uncond_jump_length() /base_dir/sources/gcc/gcc/bb-reorder.cc:1408 0x14d7adc duplicate_computed_gotos /base_dir/sources/gcc/gcc/bb-reorder.cc:2769 0x14d7adc execute /base_dir/sources/gcc/gcc/bb-reorder.cc:2836 Please submit a full bug report, with preprocessed source (by using -freport-bug). Please include the complete backtrace with any bug report. See <https://gcc.gnu.org/bugs/> for instructions.

#

not actually sure what operation it wants but i'll figure that out some other time

dense vigil
#

damn RTX in gcc meme

twilit smelt
#

In fact not really at all

twilit smelt
icy bridge
#

oh right

#

that's an issue

#

actually I wonder why that was accepted at all, the constraints I put on mov shouldn't allow negative immediate offsets

twilit smelt
twilit smelt
#

Which should at least be a good start

icy bridge
#

Yeah I don't think it'd be a massive undertaking to adapt it to llvm codegen or anything like that but it definitely won't work unchanged

twilit smelt
icy bridge
#

Nothing concrete off the top of my head, I just remember thinking "oh this seems like it relies on codegen details" at times when looking through it

twilit smelt
#

slander!

twilit smelt
icy bridge
#

Ehh I don't think it'll be a huge issue

twilit smelt
#

Especially cuz there's no real reason for it to be zero extended it has just always been that way

icy bridge
#

I can just make it so the frame pointer (s0) points at the lowest address of the frame instead of the highest, then all stack accesses should have positive offsets regardless of -fomit-frame-pointer presence

twilit smelt
#

gcc has to support other architectures that have only unsigned offsets

mortal thunder
icy bridge
#

And GCC's generic codegen stuff should be able to deal with the rare cases where negative offsets really are necessary by spilling the offset into a register

mortal thunder
#

ah

#

so lowest as the "down" in "stack grows down"

icy bridge
mortal thunder
#

mighty impressive work anyway

#

i cant wait to see how it turns out

icy bridge
#

@twilit smelt is there any detailed documentation on the call convention that the jackal compiler uses? e.g. what register contains the return value (a0?), how are arguments and return values >32 bits handled (stack? 2 registers if <=64 bits, stack otherwise? etc), how are the stack locations for stack-passed arguments determined (lowest address for first stack argument, with each argument aligned to 32 bit boundary?), etc

twilit smelt
#

are you hoping to be ABI compatible

icy bridge
#

yes

twilit smelt
#

return value is in a3, OUT parameters are subsequent return values and are passed out in a2, a1, a0 in descending order and after that on the stack

#

arguments and return values >32 bits are not handled you cant do that in jackal

#

you can only deal in machine words

icy bridge
#

ah okay

twilit smelt
#

so on a 64 bit machine you could do 64 bit but not 128 bit

icy bridge
#

that makes things easier because i can effectively make up whatever i want

twilit smelt
#

for stack passed arguments and return values, thats a good question

#

i dont remmber

#

you may need to toy with writing little jackal programs to see what it emits

icy bridge
#

fair enough

#

oh and for arguments <32 bits does the callee expect the upper bits to be zeroed, sign extended, garbage..?

twilit smelt
#

NOTESFORSPEC in the jackal compiler codebase may be illuminating, contains notes on all kinds of weird junk i wanted to keep track of for when i wrote a spec (never happened (yet))

#

including what you just asked

icy bridge
#

alr i'll take a look at that

twilit smelt
#

see note 2

icy bridge
#

ah ok

acoustic sparrow
icy bridge
#

does point 6 mean that for signed args/return values the upper bits need to be sign extended or does it only apply to locals

dense vigil
#

i didnt really understand what it meant by the wrapping bit

#

so if u do u8 x = 0; x += 256 what will it contain

icy bridge
#

the register/stack slot it's allocated to will contain 256 but the code is generated in a way where it acts as if it contains 0

#

that's how i interpret it at least

dense vigil
#

so its basically saying there's no extra code to mask the value or whatever

icy bridge
#

yea

dense vigil
#

oh

twilit smelt
dense vigil
#

lol

#

ur not even gonna ask which part is cursed?

icy bridge
#

i do have to admit the whole "int is 16 bit" part tripped me up a bit when writing the assembler

dense vigil
#

me when i learned about GAS .long

twilit smelt
acoustic sparrow
#

because it uses more bytes

twilit smelt
#

its probably an artifact of me being 15 when i started

#

and just doing dumb things

icy bridge
#

tbf that is the specified minimum for C's basic types

#

char is min 8, int min 16, long min 32

twilit smelt
#

maybe thats where i got it then

dense vigil
#

is there an add with carry for 64-bit math?

acoustic sparrow
#

you can compute the carry in one instruction anyway

twilit smelt
# dense vigil is there an add with carry for 64-bit math?

no you have to do the mips type sequence with slt, which jackal compiler can generate from this

#MACRO RtlAddUquadToUquad ( destquad, srcquad ) [
    srclow := (srcquad)^.Low
    low := (destquad)^.Low + srclow
    NOTHING (destquad)^.Low = low
    NOTHING (destquad)^.High += (low < srclow) + (srcquad)^.High
]
dense vigil
#

ah

#

because iirc long long must be 64-bits

#

(at least)

acoustic sparrow
#

kinda silly that your compiler doesnt have u64 on 32 bit platforms too

twilit smelt
#

@icy bridge btw theres already a (planned to be) much better compiler with a jackal frontend being designed/written rn by sandwichman, called coyote. it uses their "iron" compiler infrastructure theyre developing for their own fantasy computer Aphelion

#

if im a kernel autist, sandwichman is a compiler autist

#

so those will probably be the respective strengths of our projects lol

acoustic sparrow
#

and its not like the extra masking is expensive, you can do some tricks to do it with little penalty

icy bridge
#

ah okay

twilit smelt
#

their frontend can already parse the entire OG jackal parser (which is like 5000 lines)

icy bridge
#

is that compiler capable of passing >word-size arguments/return values? if so i'll probably try to make my gcc port use their calling conventions for what your jackal compiler doesn't support

#

or have they not gotten to that point yet

twilit smelt
#

well, its not actually to the point of generating code from jackal programs

#

theyre doing a weird outside-in development where theyre doing the frontend and the backend at the same time (using hand-written IR to test the backend) and filling in the middle

#

lol

#

the middle isnt filled in yet

#

but theyve parsed complicated jackal programs and generated xr17032 assembly

#

they just havent translated jackal to xr17032 assembly

#

yet

acoustic sparrow
#

neat

icy bridge
#

that's neat yeah

acoustic sparrow
#

but also the middle is like 99% of the work

icy bridge
#

but for call convention purposes it's the ir-to-assembly stuff i need to be compatible with

#

unless their ir only deals with words?

twilit smelt
#

rather than for any like methodology reason

#

idk tho

twilit smelt
#

@lucid umbra can comment more

twilit smelt
#

im unsure the full scope

#

none of it has been backwards incompatible

#

just adding QoL stuff the old compiler doesnt allow (including potentially >word size stuff)

acoustic sparrow
#

tbf im working on my own compiler meme (alongside 3 other projects lol) and rn im on spill slot allocation

icy bridge
#

i'm looking at the src for iron rn and it does seem like their ir has types but i can't find any code dealing with call conventions

twilit smelt
#

yeah it might just not be there yet

#

they took a break from it to work on their own architecture

#

theyre polishing up their ISA manual rn

icy bridge
#

fair enough

twilit smelt
#

i told them ill switch to their compiler once its self hosting (which will occur after they rewrite it in their language it is primarily meant to compile, mars) and can build mintia2 and my linker and assembler

#

cuz its likely to be way better than mine

#

im bad at comper

#

good at kernel

#

they bad at kernel good at comper

#

so theres a mutually beneficial arrangement to be had here

acoustic sparrow
twilit smelt
icy bridge
#

unless they already have something else and i just can't find it i'll probably go with this

  • arguments: <= 2 words in registers if possible (no splitting between registers and stack), >2 words always on stack, successive stack arguments have increasing addresses, each argument aligned to 32 bit boundary
  • return values: <= 4 words in registers (so jackal functions with out arguments can be "translated" by making the c signature have a struct as return type), >4 words written to pointer passed as first argument
twilit smelt
#

oh also keep in mind jackal has varargs stuff

icy bridge
#

is that like with most c abis where varargs have the exact same call convention as normal arguments?

twilit smelt
#

but i think the way jackal does it doesnt play nice with the way C does it so you might just decide those arent directly compatible

twilit smelt
#

it compiles to storing the varargs in a stack-allocated array and then a pointer to the array is passed as a virtual argument

#

along with a count

#

of the number of elements in the array

icy bridge
#

oh that's very different from c varargs yeah

flint shard
twilit smelt
#

and custom language

#

kind of have to

#

at that point

flint shard
icy bridge
#

like void some_jackal_function_with_varargs(void *args, size_t count)

flint shard
#

If you want an actual compiler that can compile useful software; consider adding a new LLVM backend

icy bridge
#

and have a separate abi for c varargs

flint shard
#

There is literally a tutorial on how to do that

twilit smelt
twilit smelt
#

with its own native 100% NIHed userland

#

so thats not super useful to me

icy bridge
twilit smelt
#

monkuous is porting linux rn though

flint shard
icy bridge
#

on that note i fixed the -O3 compiler crash (it was missing the instruction definition for unconditional jumps) $ echo 'void foo(){}' | host-pkgs/gcc-bootstrap/usr/local/bin/xr17032-unknown-linux-gnu-gcc -x c -S -o /dev/stdout - -O3 .file "<stdin>" .text .p2align 2 .globl foo .type foo, @function foo: jalr zero,lr,0 .size foo, .-foo .ident "GCC: (GNU) 15.2.0"

flint shard
#

I'm fairly sure that LLVM should be easier to make a backend for

twilit smelt
flint shard
twilit smelt
#

they already decided on gcc

flint shard
#

So you'll need to make documentation then

twilit smelt
#

or you can go away youre annoying me

icy bridge
#

making an llvm backend is another future goal though

flint shard
#

There is a libgcc replacement

#

For LLVM

#

Ignore the fact its a gentoo package

icy bridge
#

hm

#

well still

#

i've already gotten most of the hard work in writing a gcc backend done

#

at this point it's mostly just implementing the call convention hooks and adding the various instruction definitions

#

writing an llvm backend is probably easier than a gcc backend but probably not easier than finishing my current gcc backend

flint shard
#

As in; is it RISC or CISC

#

Or EPIC

icy bridge
#

RISC

flint shard
flint shard
acoustic sparrow
#

but llvm is better anyway

flint shard
#

IIRC someone made a literal 6502 LLVM backend

#

/65C816

twilit smelt
#

can you build llvm with gcc

acoustic sparrow
#

yes

flint shard
acoustic sparrow
#

ofc

flint shard
#

LLVM is quite easily able to be built with any semi-recent GCC/LLVM

#

Any C++20 compliant compiler is fine

icy bridge
# icy bridge RISC

it has some properties that aren't common for RISCs (most things are zero extended instead of sign extended, most arithmetic operations can also apply an immediate shift operation on one of the operands, memory operands have SIB) but for the most part it's a pretty normal RISC

flint shard
#

Zero extension is hell

acoustic sparrow
icy bridge
#

riscv just has base and an immediate offset

flint shard
#

Most C software is built with the idea of sign extension a lot of the time

icy bridge
#

i think theres an extension that adds proper indexed addressing but idk

acoustic sparrow
#

ok yeah

#

i think xr17032 is the same tho

flint shard
#

(int32_t)(int8_t)-49 should be (int32_t)-49

icy bridge
flint shard
#

Not 207

twilit smelt
#

keep in mind i already have like 200k lines of non-C code

#

running on this thing

#

C rules and conventions do not necessarily apply

icy bridge
icy bridge
#

sure on most riscs that operation's a noop but just because it isn't on xr17032 shouldn't affect the code's behavior

icy bridge
#

hell even on x86_64 that isn't a noop

twilit smelt
flint shard
twilit smelt
#

i feel like you took this as a fledgling baby project when you offered advice but theres already a large mass of stuff running on it, its a 7 yr old project

#

its not particularly useful but it sure is large

twilit smelt
flint shard
twilit smelt
#

yeah

flint shard
twilit smelt
#

custom

#

theres a language called jackal which has a fully NIH self hosting compiler

#

its not a particularly good compiler but its there

acoustic sparrow
#

whats your aliasing model trl

twilit smelt
#

pee

flint shard
#

Hmm

I'm sure that if you use GCC/LLVM with a custom backend; you could get more performance

twilit smelt
#

right

flint shard
#

Considering these have shitloads of optimizations built-in

twilit smelt
#

other than explicitly stack allocated stuff

acoustic sparrow
twilit smelt
#

the goal isnt performance

#

its to be 100% NIHed

#

for no particular reason

#

other than its cool

flint shard
#

@twilit smelt also are you considering implementing the CPU core on an FPGA using Verilog/VHDL

twilit smelt
#

yes thats a long term goal

#

someone already implemented enough of it on an fpga to run the boot rom prompt

#

no mass storage or mmu though so it couldnt boot the OSes

flint shard
#

That should work

#

You can also consider implementing an USB PHY and using that

acoustic sparrow
#

"just"

twilit smelt
teal trench
flint shard
acoustic sparrow
teal trench
#

for usb ls/fs it seems pretty easy from what i've seen

flint shard
#

Its not really hard

#

You don't even need an expensive FPGA

#

Just a cheap one will suffice

twilit smelt
#

i tend to not know anything about anything until i do the thing

#

and then i know lots of stuff

#

but i have to do the thing

#

thats a thing i havent done and dont plan to until well after the OS has a sizable userspace

#

(again)

#

so itll be some time until any of that is relevant to me

#

and ill forget everything youre saying rn

teal trench
#

qspi phy should be simple too, and should only need 1 extra pll output for a 180 deg phase shifted clock

twilit smelt
#

@icy bridge oh crap i forgot to add the yaoi pc instruction

#

and fix the jalr sign extension thing

icy bridge
#

its fine i havent gotten to the point where that matters yet

#

(aka i havent implemented pic yet)

twilit smelt
#

the manuals are actually in kind of a messed up state on my end because i got like halfway through an aborted restyling and i stupidly did a bunch of content changes inline with that cuz im an idiot

#

and now i need to go through and merge the good content changes into the old styled stuff

#

which is gonna be really boring and annoying so ive been stalling

#

any architectural changes are kind of blocked on me doing that

#

well, i guess i can change the old manuals as they exist in the books repo and then the process of merging will just be a little more complicated lol

#

hoped to avoid that though

#

heres my immediate todo list:

  1. finish up most recent emulator polishings
  2. finish replacing pre-rendered png diagrams in the manuals with new svg versions
  3. merge good content changes (including new diagrams) into old-styled manuals
  4. integrate monkuous comments (mistaken hex opcodes and other mistakes) into manuals
  5. specify auipc instruction and remove sign extension from jalr immediate in manuals
  6. implement 5 in emulator
#

@icy bridge if i dont finish these by next weekend you may force feed me drano

#

as im sure youll want to due to the pure hatred my failure will create in your heart

#

i might call it something like adr rather than auipc because the former is what arm calls it and the latter is what riscv calls it

#

and i dont want to be associated with riscv.

#

🤮

icy bridge
#

so it'd be ADR RA, IMM21 (RA = PC + (SignExtend(IMM21) << 11))?

twilit smelt
#

something like that

#

well

#

idk why youre sign extending the immediate

#

just to shift the bits you extended

#

out

icy bridge
#

clarity but yeah that's redundant

twilit smelt
#

it bothers me to have a special branch format instruction with a shifted operand but whatever

#

everything is already evil

#

an alternative is to have a special reg-imm format instruction like

ADR RD, RA, IMM16

which is RD = PC + (IMM16 << 16)

#

RB is left as MBZ

#

and is implicitly the program counter instead

#

and its basically just an add with an implicit pc operand

#

or a lui

#

or something

#

idk

icy bridge
#

i think that's better yeah

twilit smelt
#

well idk why i put RA there just to not use it

#

RA and RB would both be MBZ i suppose

icy bridge
#

well reg-imm only has two reg fields, one is the destination and one is mbz

twilit smelt
#

wait no

#

im retarded

#

yeah

icy bridge
#

could also make it ra = rb + pc + (imm16 << 16) but idk if that'd actually be useful for anything

twilit smelt
#

it would also require a weird third adder input

icy bridge
#

ah true i didn't consider it from an actual hw design perspective

twilit smelt
#

im not a digital design person but i know enough to avoid dumb stuff like that at least

icy bridge
#

in an emulator that wouldn't be a particularly big deal but ig in hardware it's more so

twilit smelt
#

ADR RD, IMM16 RD = PC + (IMM16 << 16) is probably the move

#

whwere adr is encoded as reg-imm with RA being mbz (or ignored)

#

least evil way to do it

icy bridge
#

that seems good yeah

#

i'd make it mbz instead of ignored so if necessary in the future you can use that field as opcode space

#

however unlikely that is to be necessary

twilit smelt
#

im scared of shifting the jalr immediate left by two

#

i think that may mess up the twos complement

#

of a full twos complement 32 bit addend

#

nvm it doesnt

#

i forgot that -4 also has the low 2 bits clear

#

so you can encode -128 for example as 0xFFFF in the ADR part and then 0x3FFF in the JALR part

#

er

#

i said -128 and then started doing the math for -4

#

silly

mortal thunder
#

f ex within a file

twilit smelt
#

itd be 0xFFFF in the ADR part and then 0x3FE0 in the JALR part, i guess

#

and this forms (0xFFFF << 16) + (0x3FE0 << 2) = 0xFFFFFF80

#

which is -128

icy bridge
#

yeah that sounds good

#

this does mean i will have to actually implement operand modifiers in GAS instead of relying on bits outside of the operand field to be silently masked

#

but i should be doing that anyway so i will take it as motivation

twilit smelt
#

it is a single UQUAD on 64 bit targets and two ULONGs otherwise

#

time is an RtlUquad of milliseconds for example

#

theres a bunch of macros for comparisons and arithmetic with this

#

which just Do The Thing on 64 bit and synthesize it on 32 bit

icy bridge
#

alr i've edited binutils so that jalr takes an unsigned immediate instead of signed

#

i will do adr once the opcode has been decided on

twilit smelt
#

ill decide it rn

#

that only requires me to find a free slot in a big spreadsheet

#

it shall be 0b110000

icy bridge
#

these should be the only binutils changes necessary, i will commit once tested ```patch
diff --git a/patches/binutils/jinx-working-patch.patch b/patches/binutils/jinx-working-patch.patch
index 35dc189..5ca179a 100644
--- a/patches/binutils/jinx-working-patch.patch
+++ b/patches/binutils/jinx-working-patch.patch
@@ -2357,7 +2357,7 @@ diff -urN --no-dereference binutils-clean/opcodes/xr17032-dis.c binutils-workdir
diff -urN --no-dereference binutils-clean/opcodes/xr17032-opc.c binutils-workdir/opcodes/xr17032-opc.c
--- binutils-clean/opcodes/xr17032-opc.c 1970-01-01 01:00:00.000000000 +0100
+++ binutils-workdir/opcodes/xr17032-opc.c
-@@ -0,0 +1,232 @@
+@@ -0,0 +1,234 @@
+/* xr17032-opc.c -- Table of opcodes for the XR/17032 processor.

  • Copyright (C) 2025-2025 Free Software Foundation, Inc.
  • Contributed by monkuous
    @@ -2406,6 +2406,7 @@ diff -urN --no-dereference binutils-clean/opcodes/xr17032-opc.c binutils-workdir
    +#define OPC_MOVLLI 0x0000002b
    +#define OPC_SLTI 0x0000002c
    +#define OPC_BLT 0x0000002d
    ++#define OPC_ADR 0x00000030
    +#define OPC_SYS 0x00000031
    +#define OPC_MOVSIIR 0x00000032
    +#define OPC_MOVLII 0x00000033
    @@ -2468,6 +2469,7 @@ diff -urN --no-dereference binutils-clean/opcodes/xr17032-opc.c binutils-workdir
  • {"andi", 0, OPC06, OPC_ANDI, {regA, regB, imm16}},
  • {"xori", 0, OPC06, OPC_XORI, {regA, regB, imm16}},
  • {"ori", 0, OPC06, OPC_ORI, {regA, regB, imm16}},
    ++ {"adr", 0, OPC06, OPC_ADR, {regA, imm16_16}},
  • {"lui", 0, OPC06, OPC_LUI, {regA, regB,
  •                           imm16_16}},
    
  • {"jalr", 0, OPC06, OPC_JALR, {regA, regB,
icy bridge
twilit smelt
#

i might do something a little weird

#

adr might be rd = (pc + 4) + (imm16 << 16)

#

so youd have to account for this by subtracting 4 from the overall offset

#

the reason is that whenever pc's value is taken on a data path eventually stored into a register, its always pc + 4

#

so it would be a special case to need just pc here

icy bridge
twilit smelt
#

jal and jalr

icy bridge
#

ohh right

twilit smelt
#

an implementation might do that as feeding pc+4 into the alu with the operation being an add with 0 or something, and then the result goes on the common result path for storage into the register file

icy bridge
#

sounds reasonable

twilit smelt
#

and then theres a common way to give pc+4 to the alu

#

which is reused by adr

#

even the branches probably should have been relative to pc+4 rather than relative to pc

#

(which is also what dec alpha does)

#

but that ship has sailed

icy bridge
#

hm i'm having trouble finding out how bfd wants people to represent this

mortal thunder
#

so akin to a LARGE_INTEGER on nt

twilit smelt
#

and NT used it for the same reason

icy bridge
mortal thunder
#

they probably also didnt have native 64 bit int support in the language

twilit smelt
#

not all C compilers when they started designing it in 1988 let you use 64 bit values directly

twilit smelt
#

how they do relocations for alpha's branches

#

youll find the answer there prob

#

cuz alpha did branches relative to pc+4

#

well. iirc at least

#

oh i made a big woopsie

#

apparently this is common to almost all risc architectures lol

#

not just alpha

icy bridge
#

i386 does it as well

twilit smelt
#

oh welllll

icy bridge
#

actually it might be the responsibility of whoever creates the relocation to apply the offset in the addend

twilit smelt
#

if this were 2022 i would just change that right now and recompile stuff to use the new branch encoding but i feel like i dont have liberty to do that anymore

icy bridge
#

the horror of having to maintain abi compatibility

twilit smelt
#

this branch thing seems like a pretty egregious silliness

#

on my part

#

the reason is obvious too

#

its because of pipelining

icy bridge
#

ah i think it's this in the assembler code

twilit smelt
#

by the time you calculate the branch target, the next instruction has been fetched and pc has been incremented

#

is why

icy bridge
#

that should be pretty easy considering fixp contains reloc type

twilit smelt
#

doing it my way isnt actually thaaaaat bad, you do have to maintain a shadow pc that the old pc is stored into before being incremented

#

and you calculate the branch target relative to the shadow pc

#

but thats still extra logic

#

for no good reason

icy bridge
#

oh actually this is making an earlier decision bite me in the ass

#

i opted to use REL style relocs instead of RELA which leave the addend in the target field

#

but that doesnt work well when the addend isn't representable in the target field like this

twilit smelt
#

you need to know the address of an instruction that can cause an exception that might not materialize until a later pipeline stage

#

so youre already storing that somewhere

#

so its maybe not that big of a deal perhaps

#

i also have a feeling that this entire notion disintegrates when you do OoO anyway and it begins to make almost no difference because OoO maybe necessitates pc<->instruction association bookkeeping that fulfills this role anyway

#

so this might actually be nearly inconsequential

#

still embarrassing

#

@wicked lichen are you embarrassed too

#

@icy bridge how furious would you be if i actually make this change to the branches

#

this seems fairly bad actually and i might want to do it as a last second base architecture change

#

i might slip in other breaking changes too since im already doing one

icy bridge
#

i wouldn't really mind

#

i think it'd make my job easier actually if all pcrel relocs behaved the same

twilit smelt
#

its quite strange to me that in like riscv

#

the branches have the +4 bias

#

but auipc does not

#

i was about to do the exact reverse

#

auipc should have the same bias by my understanding of the reasoning for it being there in the branches

#

for the same reason

icy bridge
#

riscv has a lot of nonsensical design decisions

twilit smelt
#

but arm adr also does not do the +4 bias

icy bridge
#

might just be that whichever architecture is at the root of the "inspiration tree" (don't know the right term) did it, and they did it for the exact same reason you almost got into the opposite situation

twilit smelt
#

this is weird

#

arm's branches are encoded two instructions ahead

#

+8 instead of +4

#

because of historical uarch reasons in like an 80s arm chip or something

#

im starting to think this doesnt actually matter

#

and people just smooth it over anyway

safe hollow
#

iirc thumb2 on arm does something cursed and it's +5, since it does +4 for backwards compat and lsb is the mode

twilit smelt
#

f

#

i have a hunch that in an OoO design the cleanest thing would just be to always use the unbiased pc

#

and the +4 might actually introduce "extra" logic when youre doing OoO

#

im unsure though

#

my understanding is that in OoO the sequential association between instructions is completely broken down (ensuring dependencies are satisfied, notwithstanding)

#

so then possibly youd have to store a shadow PC for each of these while theyre inflight and youd need the unbiased PC because thats usually how its reported if an exception were to occur

#

if you dont use a biased offset in the encoding then you can reuse the unbiased shadow PC you were already storing. otherwise you need to fiddle it a little bit

#

this could be complete nonsense though im not a uarch engineer

#

that specific example might be nonsense but it does sound like the reason for the PC+4 bias is usually for uarch reasons that dont necessarily hold on different designs and could even introduce extra logic

#

so basically what im saying is that it might just not actually matter

#

because you need to pave over it anyway in the uarch logic

#

two seconds later

#

no matter what you pick

#

i do think it could be valuable to keep it consistent at least

#

so for that reason

#

ill leave the pc used by adr unbiased

#

to align with the branches

#

and not do this breaking change

icy bridge
#

sounds good

twilit smelt
#

if anybody knows uarch and knows my reasoning is faulty for some reason and im about to make a huge mistake pls inform

twilit smelt
#

WAIT

#

okay i made a goof

#

heres something interesting

#

ARM had the PC+8 bias

#

aarch64 has

#

wait for it

#

NO BIAS

#

in the offset encoding!

mortal thunder
#

when i was looking at darwin/iOS stacktraces on arm i found that the addresses were 4 bytes before the relevant jump

raven drift
icy bridge
#

overall, sure, but that says more about other mainstream arches than it says about riscv

lucid umbra
#

i have been summoned somewhere

icy bridge
#

hello i have heard that you are working on a compiler targeting xr17032 and i was wondering if you've decided on a call convention for arguments/return values larger than a word yet

raven drift
#

fwiw the riscv docs give the rationale why exactly the jump encoding was chosen

icy bridge
#

because if so i would like to make my gcc port compatible with it

raven drift
lucid umbra
#

although with aggregate OUT parameters those might just be passed by pointer regardless

lucid umbra
#

oh so you just translate the returns and OUT params into a c struct

#

that makes sense

icy bridge
#

yeah jackal rn treats out parameters as extra return values and passes them through a3, a2, ...

lucid umbra
#

yea yea

icy bridge
#

i don't want to extend the actual c syntax so i thought making structs pass through those regs would be a better option

lucid umbra
#

what happens if you have a function that returns 5 values

#

does the last one get passed as a pointer arg

#

or does the whole thing get passed as a pointer

#

as a ‘return value’ struct

icy bridge
#

personally i think i'll pass the whole thing through a pointer

#

but that's not what jackal does rn

#

jackal puts the first 4 in regs, and the others in the incoming argument area on the stack

lucid umbra
#

hm

icy bridge
#

i don't like sacrificing abi compatibility but there's not much i can do without extending the c syntax or making all structs >4 words be split between regs and stack when returned which seems ugly

lucid umbra
#

i just find the idea of treating all the returns as a single struct like

#

it makes sense for C

icy bridge
#

yeah but not so much for jackal

lucid umbra
#

but it feels weird to bend around the native calling convention for what C wants and i dont necessarily want to sacrifice jackal performance for c compatibility

#

realistically its probably not a huge deal

#

it just feels like a step backwards from jackal by treating everything like a single return value

#

then again, it probably wont actually affect existing jackal code

#

i dont know of any functions that return 5 things so its probably fine

icy bridge
#

i don't like it all that much either but imo making sure all c functions can call all jackal functions and vice versa is important

lucid umbra
#

yeah

icy bridge
#

there's not really many good solutions since c just lacks the concept of multiple returned values

lucid umbra
#

such is the story of many languages forced through the funnel of the c abi

lucid umbra
twilit smelt
#

once a pointer to a local escapes it gets way more difficult for the compiler to figure out if it can keep using the same value across function calls or if it needs to reload it

#

basically requires whole program analysis

#

or whatever its called

#

unless you annotate it somehow

icy bridge
lucid umbra
#

this change shouldnt affect existing code afaik

twilit smelt
#

=5 looks like a scary angry face

lucid umbra
#

ture

twilit smelt
#

and no probably not

lucid umbra
#

scary

twilit smelt
#

also df had multiple return thru registers as well and i needed to be sure the transition to jackal didnt cause accidental performance regressions due to jackal only having C-like multiple return with pointer passing

#

which is slower

icy bridge
#

yeah that makes sense

twilit smelt
#

a number of things jackal does are direct analogues to dragonfruit features or syntax

#

like the function pointer syntax

#

is one to one dragonfruit

#

also the preference for unsigned types rather than signed types

#

is another carry over (and aligns with xr17032's zero extension)

#

but thats more of a convention than a language thing

icy bridge
#

alr so this is the pseudocode for what i'm imagining ```
allocateArgument(size) {
num_registers = ceil(size / WORD_SIZE);

if (num_registers <= 2 && current_arg_register + num_registers <= total_arg_registers) {
    reg = current_arg_register;
    current_arg_register += num_registers;
    return REG(reg);
} else {
    stack_offset = current_stack_offset;
    current_stack_offset += align_up(size, WORD_SIZE);
    return STACK(stack_offset);
}

}

/* note: if this returns REG(...), allocate in reverse */
allocateReturnValues(total_size) {
num_registers = ceil(total_size / WORD_SIZE);

if (num_registers <= total_arg_registers) {
    return REG(total_arg_registers - num_registers);
} else {
    return POINTER_IN_FIRST_ARG;
}

}

#
  • return values treated as a single struct (first return value is first field of struct, each field is aligned to word size)
  • caller allocates stack space for arguments and potentially return value if there's no better location (up to the compiler's discretion)
  • nothing is split between regs and stack
  • each argument is rounded up to word size before allocation
  • arguments that are allocated on the stack have increasing addresses
  • arguments can take at most two registers, return value does not have this limit
  • if return value doesn't fit in registers, a pointer to the output location is passed as the first argument (this must not overlap stack-allocated incoming args), and this pointer is returned in a3
  • if return value is passed through registers, the registers are allocated backwards (a3 contains first word)
  • varargs are always passed on the stack
#

i'm still not sure about the last point since passing a pointer to put it in would improve stack usage with large return values (this is common in e.g. rust)

#

but putting it on the stack at offset 0 would better match existing jackal behavior

lucid umbra
icy bridge
#

yeah it just seemed like the easiest way to do the whole reverse register allocation thing jackal does

lucid umbra
#

hm im not sure it would make a difference

#

hm

#

does the reverse register allocation for args thing actually make a difference btw? i thought it would be so that commonly used arguments dont get overwritten by calls but they get clobbered anyways

#

at least the jackal compiler treats them like they do

icy bridge
#

idk

#

i would guess not

#

the reason i'm maintaining it is abi compatibility, not actual codegen impact

lucid umbra
#

@twilit smelt whats the reasoning behind the reversed return value registers again

twilit smelt
#

to minimize regalloc hinting collisions with the arguments being passed in