This is an article about arm structure in IOS. It has simple words, clear logic, and humor. Non-developers are also worth reading, and the right to increase knowledge.
When I wrote "getting started with the neon iPhone", I thought that the reader had a better understanding of the processor knowledge of iOS devices. However, after reading some discussions on the internet, I found that the original knowledge is not popular, and it is my fault. In addition, I think understanding these things is helpful for iPhone programming (not just for those who like neon). Even if you are using objective-C, even if you are not familiar with it, it will not affect your work, but this knowledge will make you a better iPhone programmer.
Basic
So far, all IOS devices use ARM-based processors, which are somewhat different from x86 and PowerPC on desktops. However, they are definitely not "special" or "niche" products. Almost all mobile phones (not just smartphones) are based on ARM, such as almost all iPod, almost all MP3 players, PDAs, and Pocket PCs, not to mention. Nintendo has been transferred from GBA to arm, and it has even penetrated into the graphics calculator's territory and appeared in some deyi and HP calculators. If you want to continue tracing the source, Newton uses arm (Apple was an early investor in arm ). In addition, there are only a few gadgets mentioned above, and countless arm processors are running in embedded systems.
Arm is famous for its low power consumption and small size, and its performance is also outstanding in products with the same power consumption. This structure (at least on the iOS platform) uses little-Endian sorting, just like x86. Like MIPS and PowerPC, it belongs to a 32-bit RISC structure. Note that the simulator does not run arm code, and the software is compiled into instructions that can be run on x86. Therefore, the following content applies to the target device, not the simulator.
ARMv7, ARM11, Cortex A8, and A4, dear!
Over the years, the arm structure has evolved into several different versions. Each version has added new commands and maintained backward compatibility. The first-generation iPhone uses the armv6 processor (abbreviated as arm 6), while the latest iPhone 4 supports armv7. Therefore, different commands are generated according to the instruction set of the target version during code compilation. The same is true for assembler programs. The commands used in the Code must be compatible with specific versions. Finally, generate the machine code corresponding to armv6 or armv7 (or armv5 and V4, but armv6 is the bottom line of iOS development, so you don't need to consider the two ). The target file and the executable file have their own versions. You can view the version by running otool-Foo. O.
However, it is wrong to say that "the first-generation iPhone 4 was equipped with the armv6 processor" because armv6 is not a specific processor, but an instruction set that can be run by the processor. The first generation of iPhone uses the arm 11 core (ARM1176JZF-S, but it doesn't matter, as long as you remember it is a member of the arm 11 family), as I mentioned earlier, this processor uses the armv6 instruction set. Later iOS devices still use arm11, until the iPhone 3gs was released, Apple began to switch as much as possible to the core of the cortex A8 processor (although not sure yet, the iPhone 4 is likely to use A8 ). This core uses the armv7 instruction set. In this case, it supports armv7.
As I have already said, Do not implant device judgment code in a program, and then detect the arm structure supported by the device through known information. This code is extremely unreliable and runs on a new device that is released only after the software is complete, resulting in interruptions. So please do not do this, otherwise I swear, I will go to your house to waste you. The above knowledge is used to give you a rough understanding. Some devices support armv7 and some devices support armv6. As for how to detect it, I will talk about it now.
However, you may think, "the iPad and iPhone 4 Use A4, not cortex A8, right ?」 Otherwise, A4 is actually a complete single-chip system (SOC), not only the cortex A8 kernel, but also the graphic hardware, audio and video coding accelerator and other digital modules. A single-chip system and a processor are two very different concepts. The processor does not even occupy the main space on the silicon chip.
If you do not know how to use it, even if the device supports ARMv7, it will not help. Of course, there is no problem with applying the new instruction set, but if you do this all the time, the early devices won't be able to run the code you wrote. I guess this may not be the result you want. So how should we detect the structures supported by the device? -You can make good use of ARMv7 only by determining whether it supports ARMv7. The answer is: no need to know. Instead, compile the code twice, one for ARMv6, and the other for ARMv7, and then package these two executable files into a cool binary file. Okay. When running, the device determines which one is better to open. Yes, Mach-O can not only be used to combine completely different CPU Structures (such as PowerPC and Intel), but also 32-bit and 64-bit versions with the same structure, it can also deal with two variants of the same structure. In the Mach-O term, this is called the CPU subclass. From the programmer's point of view, the result is: Compilation determines everything. Code Compiled for ARMv6 only runs on ARMv6 devices. Similarly, the Code Compiled for ARMv7 only runs on ARMv7 (or better) devices.
If you have read the NEON Post I wrote, you may remember that I have recommended a method for detecting and selecting structures at Runtime. If you try again, you will find that I have removed the part. Now, I do not recommend that you do this, because although this is indeed useful, it cannot be ensured (or, the skills required are too complex to ensure that errors are not met.) It will be able to run stably on future ARMv8 processors. The status of related APIs in this document is not important (not on the iOS manual page). If you want to run on ARMv6 and want to use ARM7v, use the method you just mentioned.
Note: In iOS, the ARM structure may not reflect the processor model. For example, the iOS code corresponding to ARMv6 requires the support of floating point commands (VFPv2, to be precise). For ARMv6, although this is optional, however, it has existed since the first generation of the iPhone was released. Therefore, if ARMv6 is mentioned in iOS development (such as the compiler-arch setting or a CPU subclass of an executable file), it means hardware floating point support is required. This is also true for ARMv7 and NEON: Although NEON is actually an option for ARMv7-A configuration, because it appears on all iOS devices that support ARMv7, when it comes to iOS NEON, it refers to ARMv7.
Conditional execution
A practical function of the ARM structure is that most commands can be executed conditionally-if the conditions are not met, the commands are invalid. This can shorten the process and make the block deployment more effective. The general method is to skip this step if the block does not meet the conditions, but this step is skipped by inserting the judgment command into the block.
If this is just a way for the compiler to improve code efficiency, I will not mention it here. Although this is indeed a function of Debugging, it is mentioned because it may be surprising when Debugging (Debugging. In fact, sometimes you will find that the debugger will enter a false condition block (if block, for example, early error return) or two branches of if-else. This is because, although the Code passes through the processor as much as possible, some of the Code is not actually executed, that is, conditional execution. In addition, if you place a breakpoint in such a condition block, even if the status is false, it may still be executed.
Even so, in my limited test, the compiler seems to refuse to generate conditional execution commands in the debugging configuration. Therefore, it should only happen after debugging and optimization code. Unfortunately, sometimes you have no choice but to do so.
Thumb
The Thumb instruction set is a subset of the ARM instruction set. After compression, the command is only 16 bits (the size of all ARM commands is 32 bits, and it is still a 32-bit structure, this is not a completely different structure, but should be regarded as the abbreviation of common ARM commands and functions. Its advantage is obviously to greatly reduce the code size, save memory, cache, and code bandwidth. Although it is more suitable for memory-intensive microcontroller-type applications, it is still useful on iOS devices, and because of this, Xcode enables this feature in iOS projects by default. Although the code size is greatly reduced, it cannot reach 50%, because sometimes two Thumb commands are required to complete an ARM command. The ARM and Thumb commands cannot be mixed at will. The processor needs to switch the two to different modes, which can only occur when a function is called or returned.
When the target platform is ARMv6, the compilation of the Thumb command is facing a lot of trade-offs. The Thumb code of ARMv6 has fewer registers and lacks conditional commands. In particular, it cannot use floating point hardware, such as floating point addition, subtraction, multiplication, and so on. To use the floating point Thumb code, you must call the system function. That's right. It sounds like a very slow process. For this reason, we recommend disabling the Thumb mode for ARMv6, but if you insist on this, make sure to analyze the code first. If some parts are slow, at least disable Thumb (it is easy to use the command line parameter-mno-thumb in Xcode ). Remember that floating point operations are common in iOS, because Quartz and Core Animation use floating point coordinate systems.
When the target is changed to ARMv7, all these shortcomings disappear: ARMv7 contains Thumb-2, which is an extension set of the Thumb command, added conditional execution and 32-bit Thumb commands that can access all ARM registers and hardware floating point and NEON. Using Thumb-2 to reduce the code cost is almost zero, so it is best to turn it on (if it is turned off, please open it again ). In the condition generation option of Xcode, enable ARMv7 and disable ARMv6.
You may hear people say on the Internet that the Code needs Interworking to use Thumb. Don't worry unless you want to write assembly code, because all the code on the iOS platform is interconnected. When the Assembly is displayed, it may be difficult for the Shark to determine whether the function is ARM or Thumb. If you see invalid or meaningless commands, you 'd better check each other.
Alignment
IOS supports non-alignment access, but it is slower than alignment access. We recommend that you do not use it. In some special cases (involving loading/storing multiple commands, if you are interested), non-alignment access may be a hundred times slower than alignment access because the processor cannot process it, in addition, you must request assistance from the operating system (refer to this article, which is the same as that of non-alignment Double Precision Floating Point Numbers that become too slow on PowerPC ). So be careful, and alignment is still important.
Division
This guy always surprised everyone. Open the ARM structure Manual (if you do not have one, refer to the structure overview section of "NEON iPhone getting started") and find the integer division command. Let's go. I will wait for you. Not found? Normal and normal. Yes, the ARM structure does not support hardware integer division and must be executed by software. If you compile the following code:
int ThousandDividedBy(int divisor) { return 1000/divisor; }
In the assembly code, you will see that the compiler inserts a "___ divsi3" that calls the function-this is a system function used to execute the software division (note that the divisor cannot be constant, otherwise, Division may be converted to multiplication ). This means that in ARM, integer division actually represents the performance of the operating system.
However, after reading the manual, you may say, "You are wrong! There are even two ARM division commands in it! Here, sdiv and udiv !」 Sorry for the cool water, these commands can only be used for ARMv7-R and ARMv7-M configuration (both for real-time and embedded environments-such as motor microcontroller and watches ), iOS device ARMv7-A is not supported, sorry!
GCC
The quality of ARM code generated by GCC is no longer a secret. On other ARM-based platforms, professional developers use the RVDS tool chain provided by ARM itself. However, RVDS does not support Mach-O running for OSX, but only ELF running. But at least there are alternatives to GCC, such as LLVM. Although I didn't test it much, but when using LLVM, at least we saw significant improvements in 64-bit full-Digital (this is especially weak in GCC on ARM ). In time, LLVM surpassed GCC in all aspects.
You see, now you are a better iOS developer!
[Original article; Author: Pierre Lebeaupin]