📄 psr.html
字号:
</dl><p><dl> <dt> AL : Always <dd> The default condition, so does not need to be explicity stated.</dl><p><dl> <dt> NV : Never <dd> Not particularly useful, it states that the instruction should never be executed. A kind of Poor Mans' NOP.<br> NV was included for completeness (as the reverse of AL), but you should not use it in your own code.</dl>There is a final conditional code which works in the reverse way. <code>S</code>, when appliedto an instruction, causes the status flags to be updated. This does <i>not</i> happenautomatically - except for those instructions whose purpose is to set the status.For example:<pre> ADD R0, R0, R1 ADDS R0, R0, R1 ADDEQS R0, R0, R1</pre>The first example shows us a basic addition (adding the value of R1 to R0) which does not affectthe status registers.<p>The second example shows us the same addition, only this time it will cause the status registersto be updated.<p>The last example shows us the addition again, updating the status registers. The difference hereis that it is a conditional instruction. It will only be executed if the result of a previousoperation was EQual (if the Z flag is set).<p> <p> <p>Here is an example of conditional execution at work. You want to compare register zero with thecontents of something stored in register ten. If not equal to R10, then call a softwareinterrupt, increment and branch back to do it again. Otherwise clear R10 and return to a callingpiece of code (whose address is stored in R14).<pre> \ An example of conditional execution .loop ; Mark the loop start position CMP R0, R10 ; Compare R0 with R10 SWINE &40017 ; Not equal: Call SWI &40017 ADDNE R0, R0, #1 ; Add 1 to R0 BNE loop ; Branch to 'loop' MOV R10, #0 ; Equal : Set R10 to zero LDMFD R13!, {R0-R12,PC} ; Return to caller</pre>Notes:<ul> <li> The SWI number was made up as I was writing this. Under RISC OS, it is the number for <i>Econet_DoImmediate</i>. Don't take it literally, its only an example! <li> If you've not see <code>LDMFD</code> before, it loads multiple registers from the stack. In this example, we are loading R0 to R12 and R14 from a fully descending stack. Refer to <a href="str.html"><i>str.html</i></a> for more on register loading and storing. <li> Yes, I did just say we load R14. So why put it in the PC? Because the value of R14 when stored contains the return address. We can give happily:<br> <code>LDMFD R13!, {R0-R12,R14}<br>MOV PC, R14</code><br> However by reloading straight into PC, we can omit the <code>MOV</code> statement. <li> Finally, it is very likely that registers will be corrupted by a SWI call (dependant upon the code executed during the call), so you might like to push the important registers on the stack, to restore them later.</ul><p> <p> <p><a name="32bit"></a><h2>The 32 bit PSR</h2>As described in <a href = "32bit.html">this document</a>, processors after the ARM 3 provide a32 bit addressing space by moving the PSR out of R15 and giving R15 a full 32 bits in which tostore the address of the current position.<br>Currently, RISC OS works in 26 bit mode, except for a few special cases which is unlikely to beencountered.<br>The 32 bit mode is important because 26 bits (as in the old PSR) restricts the maximum amount ofaddressable memory per-application to 28Mb. That is why you can't drag the Next slot beyond 28Mbirrespective of how much memory you have installed.<p>The allocation of the bits within the CPSR (and the SPSR registers to which it is saved) is:<pre> 31 30 29 28 --- 7 6 - 4 3 2 1 0 N Z C V I F M4 M3 M2 M1 M0 0 0 0 0 0 User26 mode 0 0 0 0 1 FIQ26 mode 0 0 0 1 0 IRQ26 mode 0 0 0 1 1 SVC26 mode 1 0 0 0 0 User mode 1 0 0 0 1 FIQ mode 1 0 0 1 0 IRQ mode 1 0 0 1 1 SVC mode 1 0 1 1 1 ABT mode 1 1 0 1 1 UND mode</pre><p> <p>Typically, the processor will be operating in User26, FIQ26, IRQ26 or SVC26 mode. It is possibleto enter a 32 bit mode, but extreme care must be taken. RISC OS won't expect it, and will sulkgreatly if it finds itself in it!<p>You cannot use <code>MOVS PC, R14</code> or <code>LDMFD R13!, {<i>registers</i>, PC}^</code> in32 bit code. Neither can you use <code>ORRS PC, R14, #1<<28</code> to set the V flag.<br>All of this is now possible using <code>MRS</code> and <code>MSR</code>.<p><pre>Copy a register into the PSR MSR CPSR, R0 ; Copy R0 into CPSR MSR SPSR, R0 ; Copy R0 into SPSR MSR CPSR_flg, R0 ; Copy flag bits of R0 into CPSR MSR CPSR_flg, #1<<28 ; Copy flag bits (immediate) into CPSR</pre><pre>Copy the PSR into a register MRS R0, CPSR ; Copy CPSR into R0 MRS R0, SPSR ; Copy SPSR into R0</pre>You have two PSRs - <code>CPSR</code> which is the Current Program Status Register and<code>SPSR</code> which is the Saved Program Status Register (the previous processor mode's PSR).<br>Each privileged mode has its own PSR, so the total available selection of PSR is:<ul> <li> CPSR_all - current <li> SPSR_svc - saved, SVC(32) mode <li> SPSR_irq - saved, IRQ(32) mode <li> SPSR_abt - saved, ABT(32) mode <li> SPSR_und - saved, UND(32) mode <li> SPSR_fiq - saved, FIQ(32) mode</ul>It appears as if you cannot explicitly specify to save the current PSR in, say, SPSR_fiq.Instead, you should change to FIQ mode and then save to SPSR. In other words, you can only alterthe SPSR of the mode you are in.<br>Using the <code>_flg</code> suffix allows you to alter the flag bits without affecting thecontrol bits.<p>In user(32) mode, the control bits of CPSR are protected, you can only alter the condition flags.In other modes, the entire CPSR is available. You should not specify R15 as a source ordestination register. And finally, you must not attempt to access the SPSR in user(32) mode asit doesn't exist!<p>To set the V flag:<pre> MSR CPSR_flg, #&10000000</pre>This sets the V flag and doesn't affect the control bits.<p>To change mode:<pre> MRS R0, CPSR_all ; Copy the PSR BIC R0, R0, #&1F ; Clear the mode bits ORR R0, R0, #new_mode ; Set bits for new mode MSR CPSR_all, R0 ; write PSR back, changing mode</pre><p> <p>What we shall do now is to enter the SVC32 mode and set the Z flag. Then we'll return to SVC26mode and 'test' if the Z flag is set.<br>RISC OS will not be expecting to find itself in 32 bit mode, so we'll disable all interrupts andkeep them that way. Though this code should execute fast enough, we don't want to take anychances...<p>Before we begin, I just want to say that you <i>will</i> need Darren Salt's<code>ExtBASICasm</code> module to allow BASIC to assemble the MSR/MRS instructions. It isentirely possible to insert these instructions using EQUD, but it is messy and hard to follow.<br>If you use !Zap, you'll find it as <i>!Zap.Code.Extensions.ExtAsm</i>, in the v1.40 distribution.<p><pre><font size = 2>REM >32bittestREMREM Short example to go into 32 bit mode, set theREM Z flag, and return to a conditional based uponREM this.REMREM Downloaded from http://www.heyrick.co.uk/assembler/REMREM We need to ensure the required hardware is present...emsg$ = "Sorry, you'll need a RiscPC or later, with a 32 bit capable "emsg$+= "processor in order to use this software."ON ERROR SYS "OS_PrettyPrint", emsg$ : PRINT : ENDSYS "OS_Memory", 6ON ERROR PRINT REPORT$+" at "+STR$(ERL/10) : ENDDIM code% 1024PRINT "Assembling code"FOR l% = 0 TO 2 STEP 2 P% = code% [ OPT l% EXT 1 ; Enable ExtBASICAsm \ Preserve our R14 and then enter SVC mode STMFD R13!, {R14} SWI "OS_EnterOS" ADR R0, entering SWI "OS_Write0" SWI "OS_NewLine" \ Turn off all interrupts, because RISC OS won't be expecting 32 bit mode! SWI "OS_IntOff" \ User32 code MOV R0, #%10011 MSR CPSR_all, R0 ; Select CPSR mode, clear all the bits MOV R0, R0 MRS R0, CPSR_all ; Read CPSR BIC R0, R0, #&F0000000 ; Clear the flag bits BIC R0, R0, #&1F ; Clear the mode bits ORR R0, R0, #1<<30 ; Set the Z flag ORR R0, R0, #%11 ; Set SVC26 mode MSR CPSR_all, R0 ; Do it! MOV R0, R0 \ Turn interrupts back on again. SWI "OS_IntOn" ADR R0, exiting SWI "OS_Write0" SWI "OS_NewLine" \ If Z set, print Z set else print Z unset ADR R0, zunset ADREQ R0, zset SWI "OS_Write0" SWI "OS_NewLine" \ Return to USR mode BIC R14, PC, #3 TEQP R14, #0 MOV R0, R0 \ And get out of here. LDMFD R13!, {PC} .zunset EQUS " Z flag is not set (this ain't right!)" EQUB 0 ALIGN .zset EQUS " Z flag is set (as expected!)" EQUB 0 ALIGN .entering EQUS " About to enter 32 bit mode, cross your fingers!" EQUB 0 ALIGN .exiting EQUS " Returned to 26 bit mode. Phew!" EQUB 0 ALIGN ]NEXTPRINT "Executing code"CALL code%PRINT "Finished"END</font></pre><div align = right><a href="sw/32bittest.basic"><i>Download this example</i></a></div><p>You might have got the idea that 32 bit code is not terribly useful. Under current versions ofRISC OS, this is true. In fact, as far as I'm aware, the only thing that 32 bit mode will giveyou is:<ul> <li> Access to areas larger than 28Mb. Never really been much of an issue on RISC OS, where a web browser fits into a meg or two and serious art programs provide their own virtual memory system for those seriously huge images.</ul><p>The original version of this document, and the original ARM assembler guide includes...<ul> <li> The StrongARM provides two instructions (UMUL and UMLA, IIRC) which deal with 64 bit multiplication. This is only available in 32 bit mode.</ul>This is <i>incorrect</i>. The extended multiply can be used from 26 bit mode; it's how the MP3decoders use it!<p>While the benefits may not seem to be an awful lot, newer processors (such as Xscale) do notsupport 26 bit mode, so RISC OS and it's applications will need to be modified to work in 32 bitenvironment.<br>It may not sound like much, but given that <i>all</i> references to amending/altering the PSRbits in R15 have to be changed to refer to a seperate PSR not in R15, it suddenly becomes a muchbigger issue. Also, you can no longer restore the PSR and branch back to the caller in oneinstruction, as these are now two seperate operations. For that reason, code must be rewritten.You can't simply bodge in another instruction...<p> <p> <p><hr size = "3"><a href="index.html#02">Return to assembler index</a><hr size = "3"><address>Copyright © 2001 Richard Murray</address></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -