AArch64, or 64bit ARM


notaz

Certified Guru
Joined
Aug 23, 2005
Messages
4,913
Location
Lithuania
Website
notaz.gp2x.de
Being a huge ARM architecture fan, and occasional assembly programmer, I'm somewhat disappointed with 64bit incarnation of it, so I'd like to hear some opinions about it from visitors of this forum. For those who don't know, the overview is available from ARM for a while now (you'll need to create an account to download):


http://infocenter.ar...197a/index.html


I'll start with things I think they have done wrong:

  • First of all, getting rid of conditional execution. This was main thing that made ARM unique, and I'm really sad to see it go. I used conditional stores heavily in PicoDrive renderers, and is one of main reasons GP2X version at 200MHz would kick ass of PSP version at 333MHz.. Well at least there is still conditional select, but I'm not sure how useful it's going to be.
  • Removing STM/LDM - are they crazy? Do they like long function prologues/epilogues and icache bloat? You usually need to load/store at least 10 registers (now there will be more because of larger register file), so at least 5 pair instructions (or more) instead of just 1 STM/LDM will have to be used..
  • Making a "zero" register, why? Isn't zero immediate available any more for ALU instructions? What a waste.
  • Making PC no longer accessible. I understand that writing to PC is slow on most modern CPUs because of long pipelines and other complications, but being able to read it anytime with any ALU instruction was handy.
  • +-1MB conditional branches, +-128MB unconditional branches - sucks for recompilers. Direct block linking will be hard with just 1MB (much worse then current +-32MB), calling helper code from translation cache, while better than now with +-32MB, will still be problematic if you hope to use 1 instruction.


Things I like:

  • Larger register file (32 registers) - oh yeah, always a good thing, especially for recompilers, although 1 of them is "wasted" by having zero register..
  • Larger PC-relative load offsets. They say less literal pools will be needed with this (one of larger ARM problems), but I doubt gcc will make use of it (it's much easier to just drop them after each function..).
  • Divide instruction - at last.
  • Most useful addressing modes seem to still be there.
  • Still using fixed-size 32bit instructions.
  • compare-jump instructions.


So in general it's becoming more MIPS64-like, and I'm mourning loss of conditional execution (they could have left it for ALU and stores at least..) plus loss of STM/LDM. I'm not sure the new immediate encoding for ALU instructions is any better too.


I suppose it's not worth thinking about it too much until any real CPUs come out, who knows, the situation may change dramatically and ARM no longer be relevant by then, but I still would much prefer coding for this than for messed up x86_64 instruction set.
 
Last edited by a moderator:
Maybe, like high-level languages, they tend to rely on horsepower and compilers, not letting a big margin over hand-optimization ?


Is there some protests over ARM forums ?


Is it possible that manufacturers like TI alters a bit the design to allow, ie PC (program counter if i remember right ?).
 
I actually like AArch64 quite a bit (except the name, I usually call it ARM64 ;p) I think ARM was in a good position here because they could reflect back on two key things over the last 25 years: what did and didn't have a big impact on the efficiency of typical programs, and what is and isn't a good fit for current and future CPU designs. Some people say that it's now MIPS and I think that's going way too far, it still has lots of little things that sets it apart..


I do miss conditional stores, but you have to look at its performance usefulness in those context of things like wide vectors - if I'm going to write a software renderer for AArch64 it's going to be using NEON. What you really want is a mask store instruction like x86 got. That and a gather if not scatter instruction would all be very useful, and I hope we get them eventually. The other conditional stuff isn't nearly as much as a loss - the select instruction is pretty powerful, letting you do conditional move, increment, negate, and invert as well. The full form of the select itself lets you merge two if branches with one instruction (assuming no side effects), which makes it close to as good as full predication in a lot of cases. I like predication too, but ARM was wasting an entire 4 bits of the instruction, that is just too much. So I would have at least wanted them to move to something that used less conditions.


The original block memory instructions were problematic for CPU design because they intrinsically take a variable (and potentially long) number of clock cycles to execute. The load/store pair instructions are a fair compromise IMO. I'm not sure what the code bloat will be like but I doubt most functions actually need to save/restore 10 registers, in compiled code anyway..


Zero register is more useful than you think, for instance it means you don't have to encode flags-only instructions and some other similar instructions (immediate can't be used everywhere).. Besides that, it works as stack pointer for some instructions.. since the vast majority of ARM code kept r13 as stack pointer and didn't do strange operations on it that AArch64 doesn't support there's really no loss. PC seemed like more of a waste of a register, I think it just seemed elegant at the time - with the new PC relative immediate instructions it loses one of its bigger uses.


And hard to say they did something wrong just because it's a pain for recompilers (how much other code would be hurt by 1MB conditional branches..?).. sure it sucks for us of course ;p But it's not that big of a deal, just means having some trampolines within every ~2MB of recompiled code for conditional calls to helper functions and direct block linking (latter requiring some tracking if you want to reuse them). You'll probably find that most recompiled blocks conditionally linking to each other end up being used near enough to each other to end up within that 2MB span.


Here's a big post about architecture details: http://forum.beyond3...89&postcount=67 Most of this stuff separates it from MIPS.. when I first saw the original slides about AArch64 I was really nervous since it looked like they were taking out the most important differentiating features. But really they mostly just scaled it back to more basic forms and added a lot of new stuff.
 
Last edited by a moderator:
The original block memory instructions were problematic for CPU design because they intrinsically take a variable (and potentially long) number of clock cycles to execute. The load/store pair instructions are a fair compromise IMO. I'm not sure what the code bloat will be like but I doubt most functions actually need to save/restore 10 registers, in compiled code anyway..
I've disassembled PCSX and grepped all 'push' pseudo-ops (which are STMs really) and got this:



Code:
funcs regcount

269 2

175 4

160 9 // 14.6%

114 6

114 1

78 8

65 5

58 3

43 7

21 10

1097 total

Let's try pandora's kernel too:



Code:
3671 4

3279 2

2278 6

1272 8 // 9.4%

1126 9 // 8.3%

522 10

443 3

373 5

295 7

293 12

13552 total

for both around a quarter of functions are stacking 7 registers or more, so even with pair instructions they will need at least 4 insns instead of 1 before. And this is not even taking larger register file into account, we know gcc's register allocator is not optimal and might feel more liberal with a larger register file to use more registers (but hopefully that's not the case).


Maybe this is not horrible but it's not good either, they could have maybe split those STMs in pipeline or something (I'll admit I don't know much about processor design though).

Zero register is more useful than you think
I've been reading lots of IA32 assembly for another project and noticed compilers tend to sacrifice one of the registers to make a zero register, even with huge register pressure on IA32. It's used mostly for NULL (and other) compares and filling stuff with 0 there, although this arm64 now has compare-branch to cover the former.. But yeah, as it's also a stack pointer now, it can be seen as extra use of "reserved" stack pointer register, so thinking about it again, it's quite a good idea actually.

And hard to say they did something wrong just because it's a pain for recompilers (how much other code would be hurt by 1MB conditional branches..?)..
I agree with that too, that was rather egoistic, in global context it's very minor. It's probably even enough for most interpreters (something like Cyclone is 135KB of code).
 
I think they've done a good job with the instruction set. It's a shame to be loosing the predicated instruction set but I see their point about it not being worth the op-code space that it requires.


I do find strange the naming of condition code 1111b as being NV, it's directly equivalent to 1110b which is AL (always), and the footnote says "The condition code NV exists only to provide a valid disassembly of the ‘1111b’ encoding, and otherwise behaves identically to AL." But to me I read NV as never, which is the exact opposite and fits in with the pairing of all the codes, where the odd numbered condition code is direct inversion of the preceding even code.
 
Back
Top