|Ernest Unrau wrote:|
|Gunnar von Boehn wrote:|
Recently we brainstormed about options to enhance the 68K instruction set...
This made me wonder if generally adding instructions which the x86 has but 68K lacks would be a good idea, as this might help us to reuse compiler tricks on x86 for us.
I'm not really an x86 expert and my x86 ASM days are also over decade ago.
So maybe someone can step in here and help us a bit...
Are there any really cool instructions on x86 which are damn useful - that would make sense to "borrow" for our new 68K-family?
Gunnar - I'm not a programmer at all on on the level that you guys are. But I have had a fair bit of communication with a fellow who is - but then he's also nearing completion of his own entire x86 OS and his own compiler. He's the fellow who has ported Ghostscript (latest version 8.60) for amiga, and you can find out more here:
EXTERNAL LINK - - ghostscript page at "www.whoosh777.pwp.blueyonder.co.uk"
EXTERNAL LINK - - x86 os project at "www.whoosh777.pwp.blueyonder.co.uk/os.html"
Okay, I alerted Whoosh as to the tenor of this thread, and he took the time and effort to send the following, which I am "forwarding" here. I suggest, though, if you have questions, that you contact him directly at the above links, because I am way over my head here :-)
well you can forward the following reply provided you clearly note that
it is forwarded
Gunnar von Boehn (Natami Team Member) posed this question:
GVB>Recently we brainstormed about options to enhance the 68K
GVB>During this discussion we found some instructions which the x86-CPUs
GVB>do have but the 68K-CPUs is missing.
GVB>Examples were MOVEcc or SHIFT #imm,Reg with a immediate higher than 8.
68020 upwards has bfffo which finds the leftmost 1 of the operand
bsr (bit scan reverse) which finds the leftmost 1
but also has
bsf (bit scan forwards) which finds the rightmost 1,
x86 being little endian regards «--- as forwards and ---» as reverse
x86 counts both bits and bytes thus: ... 5, 4, 3, 2, 1, 0
ie for x86 the entire memory is one gigantic number, which is demarcated
leftwards either in bits, bytes, words, ints, or quads.
much more logical than big endian where bits are done in the opposite
direction from bytes.
bfffo has more options than bsr, but 68k doesnt appear to have an equivalent
of bsf (maybe it does but a cursory look at the docs I only found bfffo)
x86 has HUGE amounts of supervisor things which 68k doesnt, x86 supervisor
is literally a lot of apps.
68k has 2 MMU tables, one for user and one for supervisor, which is a
much better idea than x86's having just 1 MMU table.
very tricky to make a total change of the VM mapping with x86 whereas
straightforward with 68k as you switch to the supervisor table and
then change the user table and then switch back.
also 68k allows you to use physical memory directly, whereas 64 bit x86
doesnt. (I think 32 bit x86 does)
64 bit x86 can only be done with an MMU, whereas 68k and 32 bit x86 IIRC can
be used without an MMU.
but supervisor and bit scans are typically not used by compilers,
they are more for handcoded asm.
TBH at the user level 68k is fine for compilers, but see the later comments.
the BIG thing x86 has which 68k doesnt is 64 bit. if 64 bit versions of the
68k registers can be done then 68k would catch up with x86 at the user and
the way x86 extends things is with prefix bytes called REX prefixes, these are
only relevant to assemblers and are implicit at the user asm level.
the REX prefix has the binary form: 0100WRXB
if W is 1 it means the instruction is promoted to 64 bit.
(R X and B are very complicated, x86 specific and not relevant to 68k)
user asm will say eg
add rax, rbx ; rax = rax + rbx, 64 bit registers
but the ACTUAL asm will be 32 bit with a REX prefix with W set to promote it
to 64 bit,
more precisely the above compiles to the following bits:
4801d8 in hex
and the 32 bit version
add eax, ebx
the 64 bit version is just the 32 bit version with the promotion prefix
in x86 asm the 8 bit, 16 bit, 32 bit, 64 bit versions of register a are
denoted al, ax, eax, and rax respectively.
similarly bl, bx, ebx and rbx for b etc.
68k denotes the size at the opcode:
add.w d0, d1 ; 68k
add.l d0, d1 ; 68k
x86 denotes it at the register:
add eax, ebx ; x86
add rax, rbx ; x86
the 68k notation is more efficient as it regards size as an opcode attribute
and not a register attribute.
also with 68k the dest is the right operand, and with x86 it is the left
if you reflect 68k you get k86 which looks like x86!
x86 is a reflection of 68k,
I have written an entire pre-emptive multi processor kernel in 64 bit x86 asm
so x86 64 bit asm is pretty good at the notational level. At the bit level
it is enormously cumbersome. at the user asm level it is like a 64 bit version
of 68k asm. but at the bit level 68k is a much better design.
x86 instructions have LOTS of prefixes and the total size of a 64 bit x86
instruction can be up to 15 bytes.
using amigaos pattern matching notation an x86 instruction is:
#legacy_prefix (rex_prefix | ) opcode1 opcode2? (ModRM SIB?)? ( | (disp) |
(disp disp) | (disp disp disp disp) ) ( | imm | (imm imm ) | (imm imm imm imm)
but REX.W is the only one relevant here.
the success of x86 is based on brute force hackwork to catch up with other
systems. instead of giving up which Motorola did, x86 patched a design much worse than
68k and have maintained backwards compatibility all the way to around 1980. when you
switch the newest PC on, it starts off in 1980 as a 16 bit computer with about 1MB of
ram, and bootstraps in stages to modernity. when you use the early startup on a PC
you are in 1980 on a 1MB 16 bit PC with 64K ROM.
the Amiga abandoned backwards compatibility right at the A600 where they
changed some disk interface chip, some games no longer functioned. todays PCs have
maintained backwards compatibility all the way back to 1980.
x86 is an EXTREME form of CISC, but is based on a RISC core.
if you code x86 supervisor asm you soon realise that x86 is an app, ie it is
done in software in the microcode. eg when an interrupt occurs, x86 literally runs
some microcode software to enact the interrupt. the microcode software at the end
of each instruction polls for interrupts, ie x86 interrupts are not true
interrupts but are polled by the microcode. but that makes them well behaved,
the other major advantage of x86 asm is that ALL registers are gpr,
ALL can be used for addresses AND numbers,
with 68k a0 to a7 are address registers, and d0 to d7 are data registers
eg with 68k you cannot do * and / with address registers,
whereas with x86 you can do anything with everything which doubles the power
of the registers.
and 64 bit x86 has 16 registers, just like 68k. 32 bit x86 has just 8
registers which arguably is worse than 68k. 8 gprs versus 16 nongprs
"64 bit" and "promotion to gprs" perhaps could be done using a promotion
prefix, 68k uses 16 bit aligned instructions, so for 68k you could use a 16 bit
promotion prefix using an undefined instruction (if any are left, you are supposed to
always leave SOME instructions unallocated!)
that would still be just 4 bytes, much less than the 15 x86 can use.
a sweet feature of x86 is that some instructions are just one byte!
x86 instructions also are completely unaligned, eg the above "add rax, rbx" is
3 bytes. with caches alignment isnt such a big problem, unalignment has ZERO cost IF
its all within a cache line.
x86 is completely at odds with RISC principles, it flouts ALL the principles
of RISC and yet is the most successful CPU ever.
GVB>We know that GCC support for x86 is actually good. This made me
GVB>wonder if generally adding instructions which the x86 has but 68K
GVB>lacks would be a good idea, as this might help us to reuse compiler
GVB>tricks on x86 for us.
GVB>I'm not really an x86 expert and my x86 ASM days are also over
GVB>So maybe someone can step in here and help us a bit.
GVB>Are there any really cool instructions on x86 which are damn useful
GVB>- that would make sense to "borrow" for our new 68K-family?
the main way to catch up with x86 at the user level are
make all the registers into 64 bit gprs using the same methodology x86 has
used which is modifier prefices.
see above for how its done.
the modifier prefix is only used where the original 68k cannot express the
muls.l a0, a1
would use a modifier
mul.q d0, d1
I would say 68k is better than user level 32 bit x86
***END FORWARDED REPLY***