ASM, copy carry flag to APSR


Thorium

Still Fresh
Joined
Nov 17, 2010
Messages
81
I need to copy the carry flag from a general purpose register to APSR.


As i understand it with the MSR instruction i can only copy all flags. However all other flags need to stay untouched.


Is there a way to do it with just one instruction?


I thought about using LSRS to shift the bit out and get it copied to the carry flag. But that would update the zero flag too, wouldnt it?
 
Your only options for flag modification are to set N + Z, N + Z + C, N + Z + C + V or no flags. You can't set C in isolation.


MRS is serializing and MSR both causes serialization and a pipeline flush, so it's best to avoid them. Instead, you many want to use conditional instructions to set up some input to properly preserve N and Z based on their current state. For instance, let's say the bit you want to load into carry is in the LSB of r0 and all the other bits are 0. Then you could do:



Code:
orrne r0, r0, #2

orrmi r0, r0, #(1 << 31)

movs r0, r0, asr #1
 
In the dynamic recompiler that I did for yabause, I often save and restore the carry flag with adc/lsrs. This does set the N and Z flags (and adc also sets V).


If you want to set the carry flag, you can use:



Code:
cmp reg, #0
Similarly, cmn #0 will clear the carry flag (and V flag). This will set N and Z, but if you still have the result that previously set N and Z, then you can use the same register and get the same result in N and Z.



If it's sufficient to preserve the zero flag, you could do something like:



Code:
mov r0, #0

movne r0, #1

 (set/clear carry)

tst r0, r0
 
Thanks for the info, i may need it later.


For now i guess i just found a 1 instruction solution which solves my problem.


I started work on a x86 to ARMv7 recompiler that only recompiles 32bit user mode code. It's actualy my first recompiler so i am more in some kind of prototyping phase right now. I am not even sure if i will make it static or dynamic. Right now i prefer static because i dont need to care about instruction decoding and encoding just get the input from a disassembler and feed the output to a assembler. Would save me a lot of work. Plus i have some optimizations in mind which drastically slow down recompilation. But as i am unexperienced in recompilation i dont know if thats realy a big issue for a dynamic recompiler.


Back to my problem:


I need to emulate the 8 and 16 bit registers. So i generate some code to copy the part that needs access to another register and let the operation operate on that and copy the result back to the original register. But i need to get the status flags updated correctly. Today i got it: I just shift left until the carry flag shifts out. For example for a 8bit register i would use LSLS to shift 24 bits left. The carry flag thats original on bit 8 would be copied to ASPR and the sign bit thats original on bit 7 would be now on bit 31 and update the sign bit on ASPR. Zero bit would also update correctly.
 
I would like to know which platform(s) you're looking at recompiling. With older 8/16-bit platforms it's hard to imagine there won't be self-modifying code (unless it's a Harvard arch like PIC or something) which would be an instant kill for static rec. If you're planning on depending on existing disassemblers and assemblers anyway I'm sure you can get library-versions of at least some of those, but it's hard to imagine that parsing and generating strings is that much nicer than instructions.


A lot of emulators of 8-bit platforms written for ARM will keep the registers in the most-significant 8-bits of the register and only shift out where necessary (and combine the shifts with other instructions where possible).


I made a post on emutalk with some suggestions for flags emulation in recompilers, maybe some of it might be useful to you. Here's the relevant snippet:

1) Flags


You update flags in 8080 format every time they're executed. This is much more expensive than the ALU operations themselves. To mitigate this you can employ three techniques (I'm using all of them in an x86-targeting ARM recompiler I have):


a) Dead flag elimination: This is a subset of a more general "dead assignment elimination" that falls out from "liveness analysis." This means that you don't update flags if a latter instruction in the block is going to overwrite the flags anyway. It does require a scan forward and then backwards before processing instructions to see what the liveness status is of flags before you go.


B) Host flags caching: This is where you use the x86 flags to directly hold the state of the 8080 flags for as long as possible. When the x86 flags have to be used for other things you write back the ones that are necessary.


c) Changing representation: The actual flags state doesn't have to look like the 8080 state until the 8080 code loads the flags into a register or memory (which is relatively uncommon). Until then you can store flags in a format that's quicker to write to.

The original thread is here: http://www.emutalk.net/threads/52849-Space-Invaders-Recompiler
 
Last edited by a moderator:
Thanks again, actualy i also use that 3 technics. I just call them different or dont gave them names at all. ^^


Well most of the stuff isnt implemented yet. I am still on the very basics, just finished the translation of the addressing.


I will do the dead flag elimination by something i gave the name: dynamic accuracy of emulation


Dynamic dont refering to runtime dynamic but to recompilation time dynamic. Basicly the code runs through a interpreter that determines how inaccurate emulation can be and saves hints for the translator. So the translater can do some sweet optimizations like update flags only if they are needed by the following code or expand 8 and 16 bit register accesses to 32 bit if possible, etc. Well thats all theoretical for now, didnt implemented it.


Do you actualy mean that by "liveness analysis"? If not please explain me what it is. Sounds interessting.


I have to say, i realy like the ARM design. Especialy the none destructive instruction design is awesome. Only problem my head is still thinking in x86 mode. ^^


I constantly need to go back and change my code because i forgot that i can use shifts in many instructions, etc. ^^
 
Last edited by a moderator:
Yeah, "liveness analysis" is just determining what variables will be read from in the future. If a variable is never read from before being overwritten by a new result that variable is considered "dead", otherwise it is "live." An operation that results in a dead result doesn't have to be performed at all, like generating flags that are later overwritten. A lot of optimizations can potentially cause operations to become dead.


You don't have to have an interpreter for liveness analysis, and I don't really recommend it either since it'll just make the interpreter unnecessarily slower. You just have to scan ahead while recompiling, probably from the end of a basic block to the beginning, to determine what's live at what points.


Expanding 8 or 16-bit register access to 32-bit sounds like it involves a whole class of optimizations and may get difficult. Of course I can't say much else without knowing what you want to emulate. Then again, maybe something I considered here is applicable to you..


http://www.emutalk.net/threads/42433-Recompiling-8bit-CISC-CPUs-%28especially-6502-family%29
 
Expanding 8 or 16-bit register access to 32-bit sounds like it involves a whole class of optimizations and may get difficult. Of course I can't say much else without knowing what you want to emulate. Then again, maybe something I considered here is applicable to you..
I overlooked the question for the plattform, sorry.


Basicly i want to emulate windows 32 bit games. So the goal is to make a good optimizing recompiler, which emulates only needed windows stuff, for example it does not emulate the segment registers, just using constants for them, as only 1 is used by windows anyway.


Second part of it are wrappers for the whole API stuff, like a DirectDraw to Open GL ES wrapper. Idealy no hardware other than the CPU would be needed to emulate. So no copy protection would work, but thats fine. And no applications that rely on specific drivers would work.


If i go static no selfmodifieng code would work, but thats no issue for windows games. Again copy protections wouldnt work and PE compressors like UPX wouldnt work. They need to be unpacked manualy.


The first game i will try to recompile will be Master of Orion 2, because it's a early Win95 game and as it's turn based it does not need to run fullspeed. And then i will see how far i get.


For the expansion of registers, yes it would need to do some complicated analysis, thats why i wrote my optimizations would slow down recompilation drasticly. But i see a lot of code which uses for example cl, which could just use ecx without any impact on execution. The tricky part is to write the analyser for that.
 
Last edited by a moderator:
Sounds like you want to do fixed-program partially-manual recompiles like what M-HT does, but against Windows. Since you're targeting Pandora you shouldn't get caught up in inserting code to handle unaligned memory accesses like he has, the CPU will handle unaligned accesses okay on its own.


I imagine you'll want to link this with winelib to get the Windows emulation part of it, otherwise you're going to have a really long road ahead of you.


I don't expect that the kind of 8/16-bit operations where the upper bits are known to be zero/sign-extensions of the lower ones will happen that much on x86.. since normally there wouldn't be a reason to be using sub-32bit operations. Sure, there are a few instructions that only operate on 8-bit registers, the variable shifts and setcc instructions come to mind, but I don't think those will be frequent enough for you to bother doing this kind of special analysis for. Since you're on ARMv7a you can use the bfi and ubfx/sbfx instructions to insert and extract bit-fields for the 8/16-bit instructions.
 
Sounds like you want to do fixed-program partially-manual recompiles like what M-HT does, but against Windows.
Yes, his work inspired me.


I posted the idea about it some time ago on this forum and now i started the project.

I imagine you'll want to link this with winelib to get the Windows emulation part of it, otherwise you're going to have a really long road ahead of you.
Thats the plan. I dont looked at it in detail, dont know if it has a Open GL ES wrapper.

I don't expect that the kind of 8/16-bit operations where the upper bits are known to be zero/sign-extensions of the lower ones will happen that much on x86.. since normally there wouldn't be a reason to be using sub-32bit operations. Sure, there are a few instructions that only operate on 8-bit registers, the variable shifts and setcc instructions come to mind, but I don't think those will be frequent enough for you to bother doing this kind of special analysis for.
Actualy it's common. Most compilers will allways use the 32bit registers, however handwritten ASM code often uses 8bit registers, i have even seen 16bit register accesses (which are terribily slow on current gen x86). You would think that handwritten ASM is a very small part of a game, and yes it is. But it's the most important part, because developers will only hand write ASM if it's a performance critcal code.


A real life example is in the game Sacred Underworld, which uses 16bit registers to process UTF-16 text strings.


I know that because i did a inoffical patch for that game with a assembler level debugger.


There are even some optimization guides out there that state that 8bit register accesses are faster than 32bit on x86. Which in my experience isnt true. 8bit and 32bit are exactly the same speed on my systems and 16bit is in some cases up to 70% slower.

Since you're on ARMv7a you can use the bfi and ubfx/sbfx instructions to insert and extract bit-fields for the 8/16-bit instructions.
I do use them. First i dont got for what they are in the instruction set. I mean, why bfi, bfc if i have orr, and etc., but than i realized you only can use 12bit constants with orr and many other instructions.


Right now i need 1 additional instruction for 8/16bit register reads and 2 additional instructions for 8/16bit writes. Without updating the status flags.


In a performance critical loop that has several 8bit reads/writes it can make a big impact on performance i guess.
 
Last edited by a moderator:
I'm sure 8-bit and 16-bit registers are used, it's just a question of how often they're used when not packed together or not relying on flag generation. I guess if the program doesn't switch from partial registers to their complete registers it may be better keeping the registers separate. But you'll have to be careful with what you decide to allocate more registers for. I wonder if some functions won't benefit from having some stack elements allocated to registers.


bfi isn't the same as shift + OR. It replaces the bits it's inserting. Therefore, you should be able to use to update an 8 or 16-bit part of a register in one instruction. ubfx is the same as shift + AND, but only if you have the bit-mask in a register, which you typically wouldn't want.
 
I wonder if some functions won't benefit from having some stack elements allocated to registers.
Thats a good idea, many functions could benefit from that, but it's not easy to determin which stack variables are important and which not. But keeping lokal variables in registers could be a big improvement.


Right now i have the x86 registers staticly mapped to the ARM registers and keep the 8/16 bit registers as part of there 32bit parents. That leaves me 5 registers to dynamicly work with, as i dont need to map the segement registers and i dont need to keep track of cycles for timing. Windows games dont care about timings, with a few exceptions that can be easiely addressed manualy.


Do you think its usefull to map the x86 registers dynamicaly? I guess its rare that a register is actualy unused for a longer time.
 
Last edited by a moderator:
Expanding 8 or 16-bit register access to 32-bit sounds like it involves a whole class of optimizations and may get difficult. Of course I can't say much else without knowing what you want to emulate. Then again, maybe something I considered here is applicable to you..
I did this for the 64-bit registers in mupen64plus. Basically it does a seperate liveness analysis on each half of the register. If it determines that only the lower 32 bits are used, then it can discard the rest. The same can be done for 8 and 16 bit registers.
 
I did this for the 64-bit registers in mupen64plus. Basically it does a seperate liveness analysis on each half of the register. If it determines that only the lower 32 bits are used, then it can discard the rest. The same can be done for 8 and 16 bit registers.

See, here what I thought he was talking about is turning 16 or 32-bit arithmetic over 8 or 16-bit registers into native 16 or 32-bit arithmetic. Not determining that only part of a larger register is used. Since he's made it clear he's doing x86 this is obviously not what he was talking about.


Since x86 has explicit 8-bit and 16-bit registers I doubt nearly as much analysis is needed to track this.
 
See, here what I thought he was talking about is turning 16 or 32-bit arithmetic over 8 or 16-bit registers into native 16 or 32-bit arithmetic. Not determining that only part of a larger register is used. Since he's made it clear he's doing x86 this is obviously not what he was talking about.
I thought he meant replacing something like



Code:
mov memory,%ax

add $1,%ax

mov %ax,memory
with



Code:
movzwl memory,%eax

add $1,%eax

mov %ax,memory
or



Code:
ldrh r0, [r1]

add r0, r0, #1

strh r0, [r1]

To do that, you need to determine that nothing will read the upper half of %eax. Then the 16-bit add can be replaced with a 32-bit add.
 
I've been thinking on emulating windows 32-bit games for some time and it's one of the projects I'm working on.


Here are some points and my opinions about it.


It's better to do dynamic recompilation (DR) than static recompilation (SR), unless you are doing some things in SR that can't be done in DR or you are using information specific to one executable.


Some windows executables don't contain relocation information without which doing SR is practically impossible and DR is possible only by loading the executable to the memory at an address specified in the executable.


Master of Orion 2 (my copy) doesn't contain relocation information.


If you use SR then you're tying the game to a single version of the executable. Game can have different versions (language, region, patches - official and unofficial, ...).


My copy of Master of Orion 2 has version number 1.31, but it's not the same executable as in the official patch to version 1.31.


If you use DR then it should work on any executable, but with SR you must do specific work for each executable.


Contrary to what you wrote some windows games do use self-modifying code (and I don't mean copy protections and PE compressors).


This is easier than in dos games, because self-modifying code can be only in memory block which are explicitly marked as writable and executable.


What you said about segment registers is mostly right. Registers cs, ds, es and ss have segment base 0 and segment limit 4GB and these registers shouldn't be changed by the application.


Register fs points to the TIB (Thread Information Block) and also shouldn't be changed.


Register gs can be freely used by the application, but I don't know if some games use this register beside saving and restoring it's value.


(TIB is complicated by the fact that TIB contains pointer (with segment base 0) to itself which the application can read and use.)


For windows API you can make you own implementation (only implementing functions and parameters which are really used by the games you are recompiling) or you can try using winelib.


With your own implementation, you can implement the API as you want it - better/faster than winelib, but it's a lot of work and it's impractical if you want to recompile more games.


With winelib you have the API implemented, but potentially not the way you want/need it (for example Direct3D is wrapped to OpenGL which can't be used on Pandora).


And lastly, threads. Some windows games are multi-threaded. You can limit yourself to single-threaded applications or you can support multi-threaded applications from the start. (Starting with single-threaded applications and adding support for multi-threaded applications is not simple and definitely not ideal).


If you're curious, here's some information about my project.


I'm using dynamic recompilation.


I handle self-modifying code (SMC) by running memory blocks which are writable and executable in the interpreter instead of recompiling it. This makes SMC slow(er), but the normal code si just as fast as if I didn't support SMC. (Other solutions can make SMC faster, but normal code would be slower.)


I have my own implementation of windows API (there wasn't winelib for ARM when I started working on the project).


I'm only supporting single-threaded applications.


Because of this and windows API, only two games are working (a game and it's sequel to be precise).


I'm working on it to release a beta version, but I'm not planning to support more than the two games.


I'm thinking on starting a new project which will use winelib, it will support multi-threaded applications and it will use different dynamic recompiler.
 
I thought he meant replacing something like



Code:
mov memory,%ax

add $1,%ax

mov %ax,memory
with



Code:
movzwl memory,%eax

add $1,%eax

mov %ax,memory
or



Code:
ldrh r0, [r1]

add r0, r0, #1

strh r0, [r1]

To do that, you need to determine that nothing will read the upper half of %eax. Then the 16-bit add can be replaced with a 32-bit add.
Exactly what i meant.

I've been thinking on emulating windows 32-bit games for some time and it's one of the projects I'm working on.


Here are some points and my opinions about it.
Nice to read you are working on that, i thought nobody would work on that right now.

Some windows executables don't contain relocation information without which doing SR is practically impossible and DR is possible only by loading the executable to the memory at an address specified in the executable.


Master of Orion 2 (my copy) doesn't contain relocation information.
I know, next to none .exe has the relocation table. However i think it's possible to do some relocation magic. I do have some ideas, but they need some testing to see if they work reliable.

Contrary to what you wrote some windows games do use self-modifying code (and I don't mean copy protections and PE compressors).


This is easier than in dos games, because self-modifying code can be only in memory block which are explicitly marked as writable and executable.
Can you give me a example game?


I guess it can be solved manualy, but would be additional work. Using self modifieing code in a windows game is stupid as it will actualy slow the execution down and if you dont do it poperly it can happen that the code is actualy not updated because it's allready prefetched. So eleminating self modifieing code could be a good thing anyway.

What you said about segment registers is mostly right. Registers cs, ds, es and ss have segment base 0 and segment limit 4GB and these registers shouldn't be changed by the application.


Register fs points to the TIB (Thread Information Block) and also shouldn't be changed.


Register gs can be freely used by the application, but I don't know if some games use this register beside saving and restoring it's value.


(TIB is complicated by the fact that TIB contains pointer (with segment base 0) to itself which the application can read and use.)
I know about TIB, i did wrote that windows uses one segment register, however i didnt knew about the free use of GS. Thanks for that important info.

And lastly, threads. Some windows games are multi-threaded. You can limit yourself to single-threaded applications or you can support multi-threaded applications from the start. (Starting with single-threaded applications and adding support for multi-threaded applications is not simple and definitely not ideal).
Multithreading is a must for me and i keep it in mind right from the start. But as i am just on the very start and basics of the project it didnt give it a lot of tought for now.

If you're curious, here's some information about my project.


I'm using dynamic recompilation.


I handle self-modifying code (SMC) by running memory blocks which are writable and executable in the interpreter instead of recompiling it. This makes SMC slow(er), but the normal code si just as fast as if I didn't support SMC. (Other solutions can make SMC faster, but normal code would be slower.)


I have my own implementation of windows API (there wasn't winelib for ARM when I started working on the project).


I'm only supporting single-threaded applications.


Because of this and windows API, only two games are working (a game and it's sequel to be precise).


I'm working on it to release a beta version, but I'm not planning to support more than the two games.


I'm thinking on starting a new project which will use winelib, it will support multi-threaded applications and it will use different dynamic recompiler.
I would love to join your project, but i think it wouldnt do any good. As i never did a recompiler befor or even a emulator, so i guess my actual project is needed for me to build up the needed knowlege and experience.


So your new project is aiming at running any game, not just specific ones?


It might be a good idea to share information on what games we are working to get running, so we could split some work. So if you have some games in mind, it would be stupid for me if i would work on them.
 
Last edited by a moderator:
Some windows executables don't contain relocation information without which doing SR is practically impossible and DR is possible only by loading the executable to the memory at an address specified in the executable.


Master of Orion 2 (my copy) doesn't contain relocation information.
I know, next to none .exe has the relocation table. However i think it's possible to do some relocation magic. I do have some ideas, but they need some testing to see if they work reliable.
Like I said, it's not really a problem for dynamic recompilation. But if your ideas work for static recompilation, I would like to know more about them.

Contrary to what you wrote some windows games do use self-modifying code (and I don't mean copy protections and PE compressors).


This is easier than in dos games, because self-modifying code can be only in memory block which are explicitly marked as writable and executable.
Can you give me a example game?


I guess it can be solved manualy, but would be additional work. Using self modifieing code in a windows game is stupid as it will actualy slow the execution down and if you dont do it poperly it can happen that the code is actualy not updated because it's allready prefetched. So eleminating self modifieing code could be a good thing anyway.
For instance Fallout. Here it's used in playing ingame videos (video decoding to be precise).


Eliminating self-modifying code is possible, I did it in Albion, but in Fallout it's much more complicated. Eliminating it might not be feasible.

And lastly, threads. Some windows games are multi-threaded. You can limit yourself to single-threaded applications or you can support multi-threaded applications from the start. (Starting with single-threaded applications and adding support for multi-threaded applications is not simple and definitely not ideal).
Multithreading is a must for me and i keep it in mind right from the start. But as i am just on the very start and basics of the project it didnt give it a lot of tought for now.
I didn't give it a lot of thought initially in my project and later it turned out to be more complicated than I thought and adding support for it in the current project would be a lot of work.

So your new project is aiming at running any game, not just specific ones?
Ideally yes, but at the moment I'm not sure it will work at all - too many unknowns.


Also, I'm not sure when I'll begin working on it, could be a long time.
 
It's not hard to think of situations where self-modifying code would be a huge win performance-wise, especially on a cache coherent platform like x86. But you do probably see less and less of it these days because it's pretty taboo.
 
Back
Top