CPU with x86-ish instruction set, 10 IPS [Factorio 1.x compatible]

This board is to show, discuss and archive useful combinator- and logic-creations.
Smart triggering, counters and sensors, useful circuitry, switching as an art :), computers.
Please provide if possible always a blueprint of your creation.
mmmPI
Smart Inserter
Smart Inserter
Posts: 4256
Joined: Mon Jun 20, 2016 6:10 pm
Contact:

Re: CPU with x86-ish instruction set, 10 IPS [Factorio 1.x compatible]

Post by mmmPI »

Nidan wrote: Fri Apr 25, 2025 1:52 am I see the objective was hidden in an earlier post.
Change "objective" for "explanation" and i can relate :P
Nidan wrote: Fri Apr 25, 2025 1:52 am The instructions in the OP for transcribing the assembly look pretty straightforward to me; "dumb" manual labor, no thinking or guessing involved. Likely influenced by our different perspectives. Sentences like "set these bits in that register to the values given in this table" are not hard to find in the datasheets and protocol specifications I occasionally have to work with.
I take all the blame here, the instructions look pretty straightforward indeed, that's part of why i tried to do something with the CPU in the first place. But then when i read "register" , i also needed to watch a 20 minutes video to be explained what it means because with the 8 minutes one wasn't enough. That doesn't feel like manual labor to me in that you do not have this constant/immediate feeback.

Then there's :

Code: Select all

Source/destination values:
Value Meaning
0 imm32
1 RAM address (see "Addressing modes" below)
2 EAX
3 EBX
4 ECX
5 EDX
6 EBP
7 ESP
8 EDI
9 ESI

Addressing modes (only valid when the operand location is a RAM address; use 0 otherwise):
Value Meaning
0 [imm32]
1 [ECX+imm32]
2 [EBP+imm32]
3 [EBP+ECX+imm32] 
That's a lot of room to guess/mess when you have an approximate understanding of things :)

The thinking in my perspective is , but why are all those there, why they are named differently , in videos i could learn about their existence , what the letter stand for, and how some were introduced over time, but it's a bit different perspective than how to use them in a precise situation ( and why), it's not easy to answer for myself the question of "is this there because it serve a particular function in the cpu logic and should be used for this purpose(only)" or "is this there because that's how physical x86 were designed over time and if one wants to make a virtual x86 in factorio it needs be there to so players can use their assembly knowledge ingame without re-learning a set of instruction /method". and when it is the same.
Nidan wrote: Fri Apr 25, 2025 1:52 am Anyways, I added the opcodes and put them into a constant combinator:
Worked fine, thanks, another demo program i can look at to try to understand :)
Nidan wrote: Fri Apr 25, 2025 1:52 am Your assembly looks correct, it would just be a bit slower. (My main reason the optimizing was simplifying it so the function of the code is easier to see.)
Thanks for confirmation, i may end up succeeding in making the proper OPCODE for the unoptimized program as an exercise, id be really proud x)) makes me wish i could use the CPU to make music, i think i'm far from it, but as a distant plan it helps maps out the different step, i think the next one would be to try and understand how the input works, to pause and/or reset the loop before 314 with a constant combinator outside the CPU. That sound trivial in the one hand, but on the other hand, i'd give myself no less than 8 hours.
Nidan wrote: Fri Apr 25, 2025 1:52 am There are instructions, both in OPs CPU and irl, that have the registers they work with hardcoded, but none of the instructions we used fall into that category. clobber ~ overwrite, destroy. An instruction, section of code or function is said to clobber a register when, after the function has finished, the value of that register has changed, but that value is not (part of) the result of that function.
thanks !
Altarus wrote: Fri Apr 25, 2025 3:48 am One of the few things that rather annoys me on the real x86 is the DIV/IDIV instruction: a lot of the time when it is used, you only need one of the 2 results that it generates (either the result or the remainder), but the unwanted result still ends up in the other register and destroys its previous value.
Many of your latter explanations are beyond my current level of understanding, but this part i understand because that's where a lot of the "guessing" went, what values goes where after an instruction.
Altarus wrote: Fri Apr 25, 2025 3:48 am However, even here there are still some opcodes (such as LOOP, MOVSD, etc.) where fixed registers or pairs of registers are used - which is because these instructions require specific additional logic (that is, combinators) attached to these particular registers, and it would require a significant amount of additional complexity (extra combinators) to allow arbitrary registers to be used instead... and even worse, that would totally fail to work when a memory location is selected as an operand instead, since it is clearly impractical to attach a whole bunch of extra combinators to every single RAM cell.
Thanks for the informations, although i don't understand everything , it helps me wonder less about why things are the way they are. If i can spot by myself what you mentionned earlier, a place where i can use another register in the virtual CPU than the one i would have been forced to use on a physical x86, it would feel like a meaningful step in my understanding. The quoted part feels like going even one step further, which would be trying to understand the CPU's architecture, not just "how to use it", but i'm far from there.
Altarus
Burner Inserter
Burner Inserter
Posts: 9
Joined: Sun Jun 16, 2024 7:13 pm
Contact:

Re: CPU with x86-ish instruction set, 10 IPS [Factorio 1.x compatible]

Post by Altarus »

mmmPI wrote: Sat Apr 26, 2025 10:07 am The thinking in my perspective is , but why are all those there, why they are named differently , in videos i could learn about their existence , what the letter stand for, and how some were introduced over time, but it's a bit different perspective than how to use them in a precise situation ( and why), it's not easy to answer for myself the question of "is this there because it serve a particular function in the cpu logic and should be used for this purpose(only)" or "is this there because that's how physical x86 were designed over time and if one wants to make a virtual x86 in factorio it needs be there to so players can use their assembly knowledge ingame without re-learning a set of instruction /method". and when it is the same.
I was not aiming for a 100% accurate/identical reproduction of the real x86, that would be hugely complex (even by Factorio CPUs standards of "complexity") - and anyway, a lot of the real x86's features would go largely or entirely unused in any realistically feasible Factorio CPU program.

For example, the segment registers of the real x86 - which are mostly relics from the 16 bit era, dating all the way back to the original 8086 chip.
But in the context of writing typical 32-bit code targeted for Windows operating systems, the segment registers have little (if any) real use.
Obviously, attempting to recreate such "features" of the x86 in Factorio would be of little more than academic interest at best, while only serving to needlessly bloat the design.

But despite the various differences from the real x86, one of the main design considerations for this CPU was that anyone already familiar with x86 assembly should be able to write usable code without needing to relearn literally everything from scratch.
And of course I picked x86 as the basis simply because it's what basically every PC in the world runs on, so it's far more common for programmers to be familiar with the x86 assembly - as opposed to some of the more "exotic" platforms, such as typical embedded microcontrollers (AVR, STM, PIC, etc) which have a comparatively tiny and rather specialized userbase.
Even though thematically, an embedded microcontroller platform would have been more appropriate given the practical usage considerations of Factorio CPUs... but I felt that this would have come at too steep a cost (in terms of learning curve) for most of the people who would actually want to use it.

mmmPI wrote: Sat Apr 26, 2025 10:07 ammakes me wish i could use the CPU to make music, i think i'm far from it, but as a distant plan it helps maps out the different step, i think the next one would be to try and understand how the input works, to pause and/or reset the loop before 314 with a constant combinator outside the CPU. That sound trivial in the one hand, but on the other hand, i'd give myself no less than 8 hours.
Well, here are some hints for the music part:
A single output port can control up to 32 programmable speakers (ie. play up to 32 different notes) at the same time by writing just a single value. Some assembly required (the additional combinators needed are not included in the package). How exactly to wire this up is left as an exercise for the reader.
The most trivial code implementation then becomes a simple list of MOV instructions (think of it like a music sheet), perhaps with some do-nothing (NOP) instructions interspersed to adjust the timing.
For delays of more than about 2 dozen ticks, you should probably use a simple LOOP which spinwaits for the desired amount, this way it uses less ROM space than long strings of NOPs. Incidentally, this kind of looping delay is the same as how "blocking wait" times are usually implemented on embedded microcontrollers.
With this kind of approach you have 1/10th of a second of timing resolution for the notes that you wish to play, which should be good enough to reproduce simple MIDI-esque music.
Post Reply

Return to “Combinator Creations”