GBA ASM

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
GBA ASM
by on (#138162)
Does anyone know of any good documents or tutorials for programing for the GBA using ASM? I looked on Google, but all I found was one not so helpful tutorial that didn't even appear to be finished on a website called patater.com. I also found a website called gbadev.org, but it only really has documentation on using C. The only thing I found was a GBA assembler called GoldRoad, I haven't even found a list with all the different registers, so I can't really do anything.

And out of curiosity, how many GBA games were even programed in ASM? I imagine most were written in C, as most people probably thought it is easier to write in C and hardly anything had still used ASM, so they didn't feel like learning it.
Re: GBA ASM
by on (#138166)
Apparently the GBA uses an ARM7 as its CPU, from the popular ARM family, so it shouldn't be so hard to find tools for it. As with any other console though, the CPU is the least of your worries... it's much more important to understand how graphics, sound and input work. Knowing the assembly language is useless if you don't know how to communicate with those other systems.

As for C vs. ASM, I think that the commitment to the platforms died after the 16-bit era. CPUs became fast enough to run games written in C, so there was no point in using assembly languages few programmers knew.

A lot of Game Boy Color games show that game companies didn't know how to work with 8/16-bit platforms anymore, because the graphics in several games didn't have any of the magic tricks from the NES days, and the gameplay was really stiff, almost like something you'd expect from chinese pirates. That was probably because of a total lack of commitment to the platform, which resulted in frustrated programmers trying to squeeze something out of ancient hardware.
Re: GBA ASM
by on (#138167)
Some companies were still committed enough to write their audio mixers and soft 3D texture mappers in asm, freeing up CPU time for C game logic.
Re: GBA ASM
by on (#138168)
The problem is that I don't know any of the registers or anything, and I've looked at some code written in C, but it looks like some sort of alien language. It doesn't even look like you directly load or store registers or anything. It's really sad, but I don't even know what this code is that I found that just turns the screen red. (in the assembler I'm using, "r" oddly represents the accumulator instead of "a")

Code:
.text
main:
   mov r0, #0x4000000
   mov r1, #0x400
   add r1, r1, #3
   str r1, [r0]

   mov r0, #0x6000000
   mov r1, #0xFF
   mov r2, #0x9600
loop1:
   strh r1, [r0], #2
   subs r2, r2, #1
   bne loop1

infin:
   b infin

About the "hardware is fast enough to not worry about ASM" ideology, it is, of course, still always going to be more efficient if it is written in ASM no matter what. I imagine that a game with a game with as many characters, explosions, and bullets you could just about put on screen would slow down the GBA a bit if it were written in C unlike if it were written in ASM. Although It is probably a hard comparison, about how much faster is ASM than C assuming that they are both being used efficiently? One and half times as fast? Twice as fast?
Re: GBA ASM
by on (#138169)
Espozo wrote:
The problem is that I don't know any of the registers or anything, and I've looked at some code written in C, but it looks like some sort of alien language. It doesn't even look like you directly load or store registers or anything.

C is a high-level language, so you don't deal with registers and stuff directly.

Quote:
About the "hardware is fast enough to not worry about ASM" ideology, it is, of course, still always going to be more efficient if it is written in ASM no matter what.

I completely agree, but I'm a hobbyist who codes games for fun, while the guys that program the games you buy at the store are payed to make them. Doing things at the lowest level (assembly) requires more specialized people, more time, and, consequently, more money. Companies, which have the goal of making money, not making the best possible games, do not see any benefit in spending more money.
Re: GBA ASM
by on (#138170)
Code:
mov r0, #0x4000000

$04000000 is the base address of a large block of MMIO (memory-mapped input/output) ports. Consider it as a rough counterpart to $2000 and $4000 on NES or $002100 and $004200 on Super NES.

Code:
mov r1, #0x400
add r1, r1, #3

ARM uses fixed-length instructions. This means constants sometimes have to be built a byte at a time. This forms the value $00000403 in r1.

Code:
str r1, [r0]

This writes $00000403 to the PPU control port at $04000000. According to GBATEK, this sets the display mode to 3 (240x160 hi-color bitmap), disables forced blanking, and enables BG2.

Code:
mov r0, #0x6000000

$06000000 is the start of video memory. Unlike the NES, the GBA PPU allows writing to video memory at any time.

Code:
mov r1, #0xFF

$00FF is %0_00000_00111_11111, which is a color value.

Code:
mov r2, #0x9600

$9600 is 240 times 160, the number of pixels on the screen.

Code:
strh r1, [r0], #2

This stores the value in R1 at the address in R0 and advances R0 by 2 bytes. Because R0 points at video memory, this has the effect of plotting one pixel.

Code:
subs r2, r2, #1

In 6502 this'd be dec r2.

Code:
bne loop1

Keep looping until the number of bytes to clear becomes 0.

Code:
infin:
  b infin

In 6502 this'd be forever: jmp forever

Espozo wrote:
About the "hardware is fast enough to not worry about ASM" ideology, it is, of course, still always going to be more efficient if it is written in ASM no matter what.

By that point, time efficiency for programmers had become more important than runtime efficiency. If C helped your company get the game out the door a year earlier, then you'd use C.

Quote:
Although It is probably a hard comparison, about how much faster is ASM than C assuming that they are both being used efficiently? One and half times as fast? Twice as fast?

It depends on what brand of compiler you use. I'm told the official GBA SDK came with GCC, and over the course of the GBA's life, GCC became somewhat better at generating code for ARM7TDMI. Some companies instead sprang for proprietary $6000/seat compilers from ARM, Green Hills, etc.
Re: GBA ASM
by on (#138171)
tepples wrote:
Some companies were still committed enough to write their audio mixers and soft 3D texture mappers in asm, freeing up CPU time for C game logic.

This was common in the mid-'90s too, use asm for very tight routines (usually anything that deals with some sort of rendering) and make everything else in C.

Espozo wrote:
(in the assembler I'm using, "r" oddly represents the accumulator instead of "a")

Something makes me think that you don't understand how ARM processors work...
Re: GBA ASM
by on (#138173)
Sik wrote:
Something makes me think that you don't understand how ARM processors work...


You're completely right. To be honest with you, I've never even heard of ARM before the GBA.

Oh, and tepples, thank you for figuring out the code! (In about 5 minutes, nonetheless :shock: ) One thing that really threw me off is how the registers are called using "#" instead of "$". Is this with all ARM processors and is there some sort of universal ARM handbook or something that would help me? I don't know why, but I assumed that the GBA used custom parts like the SNES. Speaking of the SNES, why are the GBA and SNES often compared? The GBA seems WAY more powerful (4 8bpp BG layers and 5x sprite overdraw FTW!), and not only that, It doesn't even appear to have been made even remotely the same way as the SNES. Actually, now that I think about it, they are both the only systems I know that use window layers and have BG mosaic capabilities.
Re: GBA ASM
by on (#138174)
The bullet points here should give you a quick rundown of what ARM is from a programming perspective: https://en.wikipedia.org/wiki/ARM_architecture#Instruction_set

There's no "accumulator", you can use arithmetic instructions on any register. The downside, though, is that you can't use arithmetic instructions directly with memory.
Re: GBA ASM
by on (#138175)
Espozo wrote:
One thing that really threw me off is how the registers are called using "#" instead of "$". Is this with all ARM processors and is there some sort of universal ARM handbook or something that would help me?

Each processor has its own unique syntax.

Espozo wrote:
I don't know why, but I assumed that the GBA used custom parts like the SNES.

It does, just not the CPU =P (but one thing to take note of: the ROM is using a 16-bit bus, so using thumb mode will be faster most of the time, I think only a portion of RAM has a 32-bit bus... consider learning how to jump to thumb mode and write most of your code with it if you want to have more performance)

Espozo wrote:
Speaking of the SNES, why are the GBA and SNES often compared? The GBA seems WAY more powerful (4 8bpp BG layers and 5x sprite overdraw FTW!), and not only that, It doesn't even appear to have been made even remotely the same way as the SNES.

GBA is like a more powerful counterpart to the SNES, but if you look at it, you'll notice that it's for the most part a similar feature set to the SNES, just with better numbers. The one part that's really off would be the bitmap modes.

Espozo wrote:
Actually, now that I think about it, they are both the only systems I know that use window layers and have BG mosaic capabilities.

Mega Drive has a window layer, as does the original Game Boy... It's way more common than you think (although probably not implemented in the same way).
Re: GBA ASM
by on (#138194)
rainwarrior wrote:
The bullet points here should give you a quick rundown of what ARM is from a programming perspective: https://en.wikipedia.org/wiki/ARM_architecture#Instruction_setquote]
So this is basically what I got from each bullet point:

ARM processors use loading and storing. (I thought every processor used loading and storing and if they didn't, how could you even do anything?)

Early ARM processors didn't support 8bit and 16bit instructions?

I really have no clue as to what this is saying but I guess that it just means that you can put 16 and 32 bit instructions in the stack?

Isn't this bullet point the exact same thing as 2?

This means that there's no weird 21 megahertz (I think that's the number) speed that's really only about 3.5 megahertz like the on the Super Nintendo because everything needs to have been gone over a couple times?

How does this make any sense? It is saying that there is conditional instructions instead of conditional branching? Would it be like add if equal instead of branch if equal? (beq)

Kind of like the last bullet point except that it says that you don't actually need to do anything after you did a comparison? what would even be the point?

The next one says that you can easily multiply and divide 32bit instructions by 2 without much performance loss?

This just means it's easy to access different registers? I don't see how LDA $xxxx could be made any easier or harder.

What is a leaf instruction?

I don't know what the last one is saying but It appears to be talking about bank switching.

rainwarrior wrote:
There's no "accumulator", you can use arithmetic instructions on any register.

So that's why it's ld"R" instead of ld"A". Oh, and I wonder, is there still x and y?

rainwarrior wrote:
The downside, though, is that you can't use arithmetic instructions directly with memory.

could you give me an example as to what you mean?

Sik wrote:
Mega Drive has a window layer, as does the original Game Boy... It's way more common than you think (although probably not implemented in the same way).


I guess Window layers are a lot more common than I thought... :lol: Why is it that I don't ever see any kind of special effects like the keyhole in Super Mario World or the portal on level 6 of r-type 3? Is it because there's only 1 window layer instead of 2 like the SNES? Now that I think about it, I guess that the water in the Sonic The Hedgehog games are a window layer? I don't think I've ever seen any fancy tricks that look like a window layer on the GB except maybe the slime climb level on Donkey Kong Land 2.

Sik wrote:
the ROM is using a 16-bit bus, so using thumb mode will be faster most of the time, I think only a portion of RAM has a 32-bit bus... consider learning how to jump to thumb mode and write most of your code with it if you want to have more performance

Either I'm crazy, or you said that I should learn C because it's faster on the GBA than ASM.
Re: GBA ASM
by on (#138197)
Espozo wrote:
ARM processors use loading and storing. (I thought every processor used loading and storing and if they didn't, how could you even do anything?)

In RISC processors, the only instructions that support a memory operand are load and store. The rest work entirely on registers and immediate values.

Quote:
Early ARM processors didn't support 8bit and 16bit instructions?

Thumb and MIPS16 were introduced because ARM and MIPS felt that their architectures' code density on binary-size-constrained architectures couldn't compete with 8- and 16-bit MCUs.

Quote:
I really have no clue as to what this is saying but I guess that it just means that you can put 16 and 32 bit instructions in the stack?

Programs use 16-bit instructions, which can't efficiently do all the things 32-bit instructions can, because it takes two reads to get a 32-bit instruction out of ROM or main RAM. But there's a fast RAM called IWRAM, normally used for the stack, where you can copy 32-bit code such as an audio mixer or a texture mapper.

Quote:
Isn't this bullet point the exact same thing as 2?

What "2"? Could you please use the quote markup if you're going to be referring to a particular point of an article? A Wikipedia article may change between the day you write your post and the day when someone else reads your post, possibly months or years later.

Quote:
This means that there's no weird 21 megahertz (I think that's the number) speed that's really only about 3.5 megahertz like the on the Super Nintendo because everything needs to have been gone over a couple times?

There's the 16.78 MHz master clock. And as on the Super NES, different memory regions have different speeds: divide by 3 cycles to read or write main RAM and 2 or 4 cycles to read ROM.

Quote:
It is saying that there is conditional instructions instead of conditional branching? Would it be like add if equal instead of branch if equal? (beq)

Yes. In 32-bit ARM instructions (but not Thumb), any instruction can have the equivalent of branch conditions on it.

Quote:
The next one says that you can easily multiply and divide 32bit instructions by 2 without much performance loss?

Yes. In 32-bit ARM instructions, you can multiply or divide one operand of each instruction by 2 as part of the same clock cycle.

Quote:
This just means it's easy to access different registers? I don't see how LDA $xxxx could be made any easier or harder.

I think "Has powerful indexed addressing modes." refers to being able to add two different registers, one with a shift amount, to form an address.

Quote:
What is a leaf instruction?

Where do you get "leaf instruction"? The Wikipedia article as of today refers to a "leaf function", which is a subroutine or function that does not call any other subroutines or functions.

Quote:
I don't know what the last one is saying but It appears to be talking about bank switching.

Nope, it's talking about having a separate set of registers to be used during interrupt handlers, so you don't have to waste time pushing the values of all registers to memory at the start of an interrupt handler and pulling them back.

Quote:
Oh, and I wonder, is there still x and y?

There are 14 numbered registers that can be used for data (like 6502 A) or address (like 6502 X and Y). The other two are reserved for the stack pointer (like 6502 S) and the program counter (like 6502 PC).

Quote:
rainwarrior wrote:
The downside, though, is that you can't use arithmetic instructions directly with memory.

could you give me an example as to what you mean?

You can't ADC with an address as an operand; you instead have to load the value from that address into memory.

I wonder if part of the problem is that forum.gbadev.org has made itself invisible to external search engines to deter spambots from finding it, registering, and posting.
Re: GBA ASM
by on (#138199)
tepples wrote:
Quote:
Isn't this bullet point the exact same thing as 2?

What "2"? Could you please use the quote markup if you're going to be referring to a particular point of an article? A Wikipedia article may change between the day you write your post and the day when someone else reads your post, possibly months or years later.

I meant the second bullet point I commented on, but you're right in that I really should have quoted it.

tepples wrote:
I wonder if part of the problem is that forum.gbadev.org has made itself invisible to external search engines to deter spambots from finding it, registering, and posting.

I really wasn't aware that that website even had a forum. :oops: But by the look of the website, It looks like it's been long forgotten by most people in that it doesn't seem to have been updated in quite some time. (The "hardware" tab on the home page just loaded perpetually when I clicked it.)
Re: GBA ASM
by on (#138200)
Espozo wrote:
rainwarrior wrote:
The downside, though, is that you can't use arithmetic instructions directly with memory.

could you give me an example as to what you mean?


This is to do with load/store architecture. On something like the 6502 where there are few registers, it wouldn't have been sensible to require all your operands to be in a register. For that reason, a lot of the time the operand is memory. On an ARM, you have to load it into a register first. When trying to optimize ARM code, it can be helpful to chose an algorithm that minimizes loads and stores, e.g. try to do a chain of operations before writing a variable back to RAM, instead of writing it back after each step.

Code:
; A contains value to be added to
ADC $0341
; A contains result


VS

Code:
; r0 contains value to be added to
LDR r1, $0341
ADC r2, r1, r0
; r2 contains result


As for whether assembly is faster than C, well, yes it is. As a human who knows more about what your code does than the compiler, you can produce better optimized code than that compiler. A human optimizer takes vastly more time to do its work than a compiler does, though, so in that respect it is slower to write.

On some platforms (like 6502), the C compilers available may not have very strong optimizers, in which case the performance difference might be magnified greatly.

The other thing to take into consideration is that usually only a small amount of the code in the game needs much optimization. Often the bulk of CPU time is spent in many repitions of a few specific tasks, and the rest of the code it won't make much of a difference if it's optimized. Spend your coding time wisely, and try not to waste a lot of effort optimizing things that aren't a perfomance problem. The most important part of optimization is measuring the time your code takes. This lets you know what should be optimized, and it also lets you know whether your optimization attempt was a success.
Re: GBA ASM
by on (#138201)
First of all, you seem to know only 6502 and 65c816 assembly at the time of your first post. You should be aware that every family of processors use completely different mechanisms for their registers, instruction sets and notation of their instructions. Think of every family of processors using different assembly languages.

The ARM family is extremely popular, unfortunately not thanks to the GBA but thanks to telephones and tablets (who I despise but that's another story). Thus it should be relatively easy to find ARM assembly language tutorials. You should learn ARM assembly from scratch even if you know 6502/65c816, because it's a completely different language. The ARM is also one of the most complex assembly language I know off, but one of the most elegant also. Don't worry it's still much simpler than pretty much any high-level languages to learn, though very difficult to master (I don't master it).

THUMB is yet another different assembly language, but it's similar to ARM with features taken off. It was designed to be more compact for code density (ARM is extremely bad in this respect, as all instructions are 32-bit, with THUMB all instructions are 16-bit instead, but you need to use more instructions to do the same task).

Something which is especially complex with ARM is the conditional status flag setting (-s suffix), the conditional execution of the instructions (-eq, etc.. suffix) and the stack management, along with the pseudo-instructions. The number of instructions themselves is quite small, but because of the pseudo-instructions and the suffixes, you might think there is way more instructions there actually is when seeing some example code.
There is also many different addressing modes.

In addition to pseudo instructions, there is also the shorthand notations for instructions. For example add r1, r2 will be a shorthand for add r1, r1, r2, LSL #0.

For instance, "beq" looks like it's the exact same as the 6502, but there is no "beq" instruction on ARM, it's a "b" instruction with "-eq" suffix. You can also do "addeq" or "moveq" for instance. With THUMB you will probably feel more at home because the instructions are more 6502 like, as the "-s" suffix is implied in all instructions and only branches are conditional. However, we are still limited to load-store architecture, we can't have an arbitrary constant in the code, and it's still only a compression of ARM assembly, which is more interesting to know to code really fast part in assembly.

If you are serious about coding a large-sized GBA game you don't want to do it all in assembly. You should also learn a mid/high level language (it doesn't have to be C).
Unlike 6502 and it's derivative, the ARM processor is very "C language friendly". Depending on the task you're doing, today's optimizers can be really good for normal code that doesn't do anything fancy, and therefore there is no significant loss in neither speed or code size when coding in C (or another mid level language). However, for specific tasks, such as bit shift or rotation, or additions with overflow checking in large loops, the C language can be terrible.
Re: GBA ASM
by on (#138395)
Sweet, I started with GBA dev just 3 days ago!
Look for "Programming the GBA" by Jonathan S. Harbour. It's online in PDF format in various places, google around for it a little bit. Learn C also. The only reason C would look strange compared to any kind of ASM, is because you just never learned anything about C. You should be able to learn enough C to get going with the GBA book in a weekend, focus on pointers and type casting. The last chapter in the book is about using inline ASM in your C code.

http://jharbour.com/gba/ham-280-full-win32.zip Dev tool-chain
http://jharbour.com/gba/gba_files.zip Example code from book
Re: GBA ASM
by on (#138550)
Whoa, Jonathan S. Harbour is the same author for a old Allegro game programming library book.

Anyway, back when I did GBA programing, tonc and gbatek were the only things I used, and they helped a lot.
Re: GBA ASM
by on (#138661)
Ah yeah, I remember the HAM devkit. I host a copy of the installer since ngine.de went dead a long time ago. I have a decent tutorial PDF for the hamlib, but it would be nice to dig through actual documentation. I haven't looked at that since 2005 or so!
Re: GBA ASM
by on (#139954)
Bump! Everyone going to hate me for asking such a stupid question on an old thread, but I'm not going to start a new one for something as simple as this. What is the difference between mov and ldr? It seems that with mov, you can't load a very specific number and have to add latter to get the number you want, while with ldr, no such restriction exists. What is the point of mov then? Unlike the SNES, ARM processors are apparently supposed to do every instruction using one cycle, so you would have wasted twice as much time using mov than ldr. I even took the code from earlier:

Code:
.text
main:
   mov r0, #0x4000000
   mov r1, #0x400
   add r1, r1, #3
   str r1, [r0]

   mov r0, #0x6000000
   mov r1, #0xFF
   mov r2, #0x9600
loop1:
   strh r1, [r0], #2
   subs r2, r2, #1
   bne loop1

infin:
   b infin

and made it...

Code:
.text
main:
   ldr r0, =#0x4000000
   ldr r1, =#0x403
   str r1, [r0]

   ldr r0, =#0x6000000
   ldr r1, =#0xFF
   ldr r2, =##0x9600
loop1:
   strh r1, [r0], #2
   subs r2, r2, #1
   bne loop1

infin:
   b infin

And it works exactly the same way. (By the way, is there a good SNES Starterkit equivalent for the GBA? I think I saw the HAM Devkit thing was using C, and all of the other ones I've seen are too. Another thing, if THUMB is supposedly faster on the GBA than ARM, then why is just about every single tutorial/document regarding GBA development exclusively using ARM instead of THUMB?)
Re: GBA ASM
by on (#139959)
LDR ("LoaD Relative") takes an extra memory access cycle.
And the assembler is supposed to convert it to a MOV if possible.

LDR actually stores your literal number somewhere else in memory, and instead stores a pointer to it, and tells it to load that value from memory.

See also http://www.coranac.com/tonc/text/asm.htm , scroll down to "PC-Relative specials"; or http://www.raspberrypi.org/forums/viewtopic.php?t=16528
Re: GBA ASM
by on (#140021)
Espozo wrote:
Everyone going to hate me for asking such a stupid question on an old thread


Actually, keep the questions coming. For the past 6+ months, I've been doing GBA dev. Personally, I'd be more than happy to answer anything.

Espozo wrote:
What is the difference between mov and ldr? It seems that with mov, you can't load a very specific number and have to add latter to get the number you want, while with ldr, no such restriction exists. What is the point of mov then?


MOV is just as it sounds, it moves a value into a register, however, the value is not from memory. In ARM, MOV's 2nd operand can be a register, a register shifted by another register, a register shifted by an immediate, an 8-bit immediate value, or a shifted 8-bit immediate value. Yes, it's a lot of options, but it explains why you can't load some of those "specific" values.

Any value you want to put into a register through MOV must 1) already exist in another register, or 2) can be created using bit-shifts of existing registers or immediates. LDR does not have this restriction since it's just taking bytes from memory, and memory values are generally arbitrary; they can be whatever.

To illustrate this, it's easy enough to use MOV to put the value 0x4000000 into R0. The assembler just specifies (when writing the actual ARM opcode), that the instruction will use an immediate value of 0x1 and perform a Rotate-Right shift of 6 (R0 is a 32-bit register, so the 1 wraps around to the top of the register, look up what ROR is if you're curious). On the other hand, putting something like 0x13371337 is not something you should tackle with MOV.

So what's the point of MOV? It doesn't use a memory access like lidnariq said, although MOV can take as long as some LDR instructions if you specify the Program Counter (R15) as the 1st operand and use a register shifted by another register as the second operand. MOV is nice and quick for setting registers to equal one another, or for many of the GBA's key addresses in the memory map (0x5000000 for Palette VRAM, for example). I use it a lot to clear out registers by setting them to zero. MOV can also affect the CPSR (Current Program Status Register) e.g. it sets the flags based on the result of the operation.

Espozo wrote:
Unlike the SNES, ARM processors are apparently supposed to do every instruction using one cycle


Where did you hear that? At least for the GBA and DS, there are 4 different cycles. N-cycles (Non-sequential memory accesses), S-cycles (Sequential memory accesses), I-cycles (Internal cycles, generally the same length as 1 S-cycle) and C-cycles (Coprocessor stuff, applicable to the DS, but not the GBA). You can find instruction timings for the GBA's ARM7TDMI here -> http://infocenter.arm.com/help/index.js ... 02180.html

As you can see, only a few cases occupy a single type of cycle (generally 1S). A single instruction on the GBA can actually run for multiple CPU cycles depending on the Wait State (basically how long the CPU waits on a memory access). It is possible to write some code that runs exactly for 1Hz of the GBA's CPU clock, but most (at least any code that you want to do anything interesting with) will take more than one cycle. But when you see what MOV is in comparison to LDR, MOV is faster for what it is designed to do.

Espozo wrote:
Another thing, if THUMB is supposedly faster on the GBA than ARM, then why is just about every single tutorial/document regarding GBA development exclusively using ARM instead of THUMB?)


Probably because most people aren't worried about following the development practices used for commercial games (e.g. ARM instructions executed in RAM, THUMB for most other things). ROM space likely isn't an issue when testing/distribution is going to be done on flashcarts or emulators, so the fact that ARM opcodes are twice as long as THUMB ones is probably not a concern. People doing ARM ASM on the GBA may also prefer the flexibility that ARM opcodes provide over the simplicity of THUMB opcodes. Then there is the possibility that for the programs they are making, speed just isn't an issue. Lastly, some people just don't like switching between ARM and THUMB. I'm one of them, but I'm a "THUMB everywhere" kinda person.
Re: GBA ASM
by on (#140025)
Personally, I kind of like it simple. Trying to memorize 50,000 different instructions seems more like taking a quiz than doing something as a pastime. :roll:
Re: GBA ASM
by on (#140029)
Shonumi wrote:
I'm a "THUMB everywhere" kinda person.
(Tangent) Many years ago I was doing some development on Nokia's N800 tablet, and someone went and recompiled the entire userland to use THUMB instead of ARM. Just the smaller instructions helped speed things up and reduce memory consumption by a couple percent both. With the GBA's comparatively narrow and high latency memory bus, I have to assume it'd be even more useful.
Re: GBA ASM
by on (#140036)
Espozo wrote:
Personally, I kind of like it simple. Trying to memorize 50,000 different instructions seems more like taking a quiz than doing something as a pastime. :roll:


Well, there are really only a handful of ARM and THUMB instructions. See GBATEK for a nice breakdown. You can even go further an lump some of them generically as Loading, Storing, Branching, etc. Trust me, before I started digging into the GBA's ARM CPU, I was equally overwhelmed. Just immerse yourself slowly, one piece at a time. I originally came from the GB's Z80-like CPU, so you can imagine what a shock ARM was to me.
Re: GBA ASM
by on (#140038)
On the GBA, I've found ARM instructions useful for three things: fixed-point multiplication (where you need to get a 64-bit result and then shift it down), IRQ handlers (which the BIOS calls in ARM mode), and signal processing inner loops executed in IWRAM, such as audio mixers. For everything else, Thumb is faster over the 16-bit bus of EWRAM, VRAM, and ROM.
Re: GBA ASM
by on (#140048)
Quote:
Unlike the SNES, ARM processors are apparently supposed to do every instruction using one cycle

Thanks to the processor pipeline, if you are using a memory where the processor can fetch instructions every cycle (in GBA's case read IWRAM), then most instructions that does not deal with memory and that does not branch should appear to be 1 cycle (including when there is bitshifts involved for example).

However the GBA is a bit werid because the processor will spend it's time waiting on memory most of it's time when executing from ROM or EWRAM.

Also the reason the tutorial teaches ARM assembly is that assembly is most likely used for the speed critical parts of a game engine, which should be coded in ARM and lay in IWRAM for maximum speed. If you want to save memory however, executing from ROM in THUMB is definitely the choice. Executing THUMB in IWRAM will be faster than ROM, but slower than ARM, and saving a lot of memory, and it also a good options for parts of the programs which are not too badly affected by the restrictions of the THUMB instruction set.
Re: GBA ASM
by on (#140053)
Bregalad wrote:
most instructions that does not deal with memory and that does not branch should appear to be 1 cycle (including when there is bitshifts involved for example).


With ARM.5, you'll be doing anything greater than 1S cycle as soon as the 2nd operand is a register shifted by another register. Only shifts by immediates will avoid adding a 1I-cycle penalty, but shifting by a register rather than immediate is not something I do often. THUMB.4 has a similar rule about shifting. Essentially, any PSR transfer or ALU operation (THUMB and ARM) that doesn't shift by a register or use the PC as the destination register will have an execution time of 1S which is as fast as you're going to get in any memory location. THUMB.12 and THUMB.13 probably act a lot like specific cases of ADD/SUB, so that explains their 1S execution time as well.

Before I forget, unexecuted code also takes 1S cycle. The GBA will skip them at the speed of light ;)