; Copyright 1999 Pace Micro Technology plc ; ; Licensed under the Apache License, Version 2.0 (the "License"); ; you may not use this file except in compliance with the License. ; You may obtain a copy of the License at ; ; http://www.apache.org/licenses/LICENSE-2.0 ; ; Unless required by applicable law or agreed to in writing, software ; distributed under the License is distributed on an "AS IS" BASIS, ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ; See the License for the specific language governing permissions and ; limitations under the License. ; SUBT Generic 32-bit CPU Specific Definitions OldOpt SETA {OPT} OPT OptNoList+OptNoP1List [ :LNOT: :DEF: Included_Hdr_CPU_Generic32 GBLL Included_Hdr_CPU_Generic32 Included_Hdr_CPU_Generic32 SETL {TRUE} ; *********************************** ; *** C h a n g e L i s t *** ; *********************************** ; ; Date Name Description ; ---- ---- ----------- ; 05-Nov-99 KBracey Moved from ARM600. ; 32-bit versions of Generic26 macros created. [ :LNOT: :DEF: Included_Hdr_Machine_Machine GET Hdr:Machine. ] ; 32-bit PSR transfer macros ; New positions of bits in 32-bit PSR Q32_bit * 1 :SHL: 27 IT32_bits * &0600FC00 J32_bit * 1 :SHL: 24 GE3_bit * 1 :SHL: 19 GE2_bit * 1 :SHL: 18 GE1_bit * 1 :SHL: 17 GE0_bit * 1 :SHL: 16 GE32_bits * 2_1111 :SHL: 16 E32_bit * 1 :SHL: 9 A32_bit * 1 :SHL: 8 I32_bit * 1 :SHL: 7 F32_bit * 1 :SHL: 6 T32_bit * 1 :SHL: 5 M32_bits * 2_11111 IF32_26Shift * 26-6 ; Processor mode numbers USR26_mode * 2_00000 FIQ26_mode * 2_00001 IRQ26_mode * 2_00010 SVC26_mode * 2_00011 USR32_mode * 2_10000 FIQ32_mode * 2_10001 IRQ32_mode * 2_10010 SVC32_mode * 2_10011 MON32_mode * 2_10110 ABT32_mode * 2_10111 UND32_mode * 2_11011 SYS32_mode * 2_11111 ; New register names r13_mon RN 13 r14_mon RN 14 lr_mon RN 14 r13_abort RN 13 r14_abort RN 14 lr_abort RN 14 r13_abt RN 13 r14_abt RN 14 lr_abt RN 14 r13_undef RN 13 r14_undef RN 14 lr_undef RN 14 r13_und RN 13 r14_und RN 14 lr_und RN 14 [ :LNOT: No32bitCode ; 32 bit versions of the macros in Generic26 GBLA CPU32_bits GBLA CPU32_set GBLA CPU32_clr ; *************************************************** ; *** PSRto32 - Convert a PSR constant to a *** ; *** 32-bit PSR value in variable psr32 *** ; *** Shifts I and F into their 32-bit positions *** ; *************************************************** MACRO $psr32 PSRto32 $psr [ (($psr) :AND: (:NOT: ARM_CC_Mask)) <> 0 ! 1, "Illegal PSR bits" ] $psr32 SETA (($psr) :AND: :NOT: (I_bit:OR:F_bit)) :OR: ((($psr) :AND: (I_bit:OR:F_bit)) :SHR: IF32_26Shift) MEND ; ************************************************ ; *** CLC - Clear carry flag - will set nzcv *** ; ************************************************ MACRO $label CLC $cond $label MSR$cond CPSR_f, #0 MEND ; *********************************************** ; *** CLRPSR - Clear bits in PSR from the *** ; *** mask in $bits, using register $regtmp *** ; *********************************************** MACRO $label CLRPSR $bits, $regtmp, $cond, $oldpsr LCLS srcreg [ "$oldpsr"="" srcreg SETS "$regtmp" | srcreg SETS "$oldpsr" ] CPU32_bits PSRto32 $bits ; Map to 32 bit PSR $label MRS$cond $srcreg, CPSR [ (CPU32_bits :AND: &F0000000) <> 0 :LAND: (CPU32_bits :AND: &F0) <> 0 ; Can't be expressed as a single ARM immediate constant BIC$cond $regtmp, $srcreg, #CPU32_bits :AND: &F0000000 BIC$cond $regtmp, $regtmp, #CPU32_bits :AND: &0FFFFFFF | BIC$cond $regtmp, $srcreg, #CPU32_bits ] somemsr $cond, CPSR, $regtmp, CPU32_bits, unsafe MEND ; ************************************************** ; *** CLRV - Clear overflow flag - will set nzCv *** ; ************************************************** MACRO $label CLRV $cond $label MSR$cond CPSR_f, #C_bit MEND ; ********************************************************************************** ; *** PHPSEI - Disable IRQs, saving an old interrupt state indicator in a *** ; *** register, default R14. Note that this code preserves the C and V flags. *** ; *** Don't have to supply regtmp, but if you do, we save an instruction. *** ; ********************************************************************************** MACRO $label PHPSEI $register=R14, $regtmp LCLS usereg [ "$register" = "" usereg SETS "R14" | usereg SETS "$register" ] $label [ "$regtmp" = "" :LOR: StrongARM_MSR_bug MRS $usereg, CPSR TST $usereg, #I32_bit ; is I32_bit set? ORREQ $usereg, $usereg, #I32_bit ; no, then set it mymsr EQ, CPSR_c, $usereg, , safe BICEQ $usereg, $usereg, #I32_bit ; $register contains original PSR | MRS $usereg, CPSR TST $usereg, #I32_bit ; is I32_bit set? ORREQ $regtmp, $usereg, #I32_bit ; no, then set it mymsr EQ, CPSR_c, $regtmp ; $register contains original PSR ] MEND ; ************************************************************************** ; *** PLP - Restore IRQ state from the indicator in a register (set up *** ; *** by PHPSEI). Note that this code preserves the C and V flags. *** ; ************************************************************************** MACRO $label PLP $register=R14 LCLS usereg [ "$register" = "" usereg SETS "R14" | usereg SETS "$register" ] $label MSR CPSR_c, $usereg MEND ; ****************** ; *** RETURNVC *** ; ****************** MACRO $label RETURNVC $cond $label [ "$cond" = "NV" ! 1, "Deprecated use of NV condition code in RETURNVC" ] [ "$cond" = "VC" MOVVC pc, lr ] [ "$cond" = "NE" :LOR: "$cond"="CC" :LOR: "$cond"="LO" :LOR: "$cond"="PL" :LOR: "$cond"="LS" :LOR: "$cond"="GE" :LOR: "$cond"="GT" :LOR: "$cond"="AL" :LOR: "$cond"="" MSR$cond CPSR_f, #0 MOV$cond pc, lr ] [ "$cond" = "EQ" :LOR: "$cond"="CS" :LOR: "$cond"="HS" :LOR: "$cond"="MI" :LOR: "$cond"="LT" :LOR: "$cond"="LE" MSR$cond CPSR_f, #N_bit + Z_bit + C_bit MOV$cond pc, lr ] [ "$cond" = "HI" MSR$cond CPSR_f, #C_bit MOV$cond pc, lr ] [ "$cond" = "VS" BVC %FT01 ; Skip on opposite condition MSR CPSR_f, #0 MOV pc, lr 01 ] MEND ; ****************** ; *** RETURNVS *** ; ****************** MACRO $label RETURNVS $cond $label [ "$cond" = "NV" ! 1, "Deprecated use of NV condition code in RETURNVC" ] [ "$cond" = "VS" MOVVS pc, lr ] [ "$cond" = "NE" :LOR: "$cond"="CC" :LOR: "$cond"="LO" :LOR: "$cond"="PL" :LOR: "$cond"="LS" :LOR: "$cond"="AL" :LOR: "$cond"="" MSR$cond CPSR_f, #V_bit ; Condition is still satisfied MOV$cond pc, lr ] [ "$cond" = "EQ" :LOR: "$cond"="CS" :LOR: "$cond"="HS" :LOR: "$cond"="MI" :LOR: "$cond"="GE" :LOR: "$cond"="LE" MSR$cond CPSR_f, #N_bit + Z_bit + C_bit + V_bit MOV$cond pc, lr ] [ "$cond" = "HI" :LOR: "$cond"="LT" MSR$cond CPSR_f, #C_bit + V_bit MOV$cond pc, lr ] [ "$cond" = "GT" MSR$cond CPSR_f, #N_bit + V_bit MOV$cond pc, lr ] [ "$cond" = "VC" BVS %FT01 ; Skip on opposite condition MSR CPSR_f, #V_bit MOV pc, lr 01 ] MEND ; **************************************************** ; *** SCPSR - Set and clear bits in PSR from the *** ; *** masks $set, $clr, using register $regtmp *** ; **************************************************** MACRO $label SCPSR $set, $clr, $regtmp, $cond, $oldpsr LCLS srcreg CPU32_set PSRto32 $set CPU32_clr PSRto32 $clr [ "$oldpsr"="" srcreg SETS "$regtmp" | srcreg SETS "$oldpsr" ] [ (($set) :AND: ($clr)) <> 0 ! 1, "Attempt to simultaneously set and clear a bit in SCPSR" ] $label MRS$cond $srcreg, CPSR [ (CPU32_set :AND: &F0000000) <> 0 :LAND: (CPU32_set :AND: &F0) <> 0 ORR$cond $regtmp, $srcreg, #CPU32_set :AND: &F0000000 ORR$cond $regtmp, $regtmp, #CPU32_set :AND: &0FFFFFFF srcreg SETS "$regtmp" | [ CPU32_set <> 0 ORR$cond $regtmp, $srcreg, #CPU32_set srcreg SETS "$regtmp" ] ] [ (CPU32_clr :AND: &F0000000) <> 0 :LAND: (CPU32_clr :AND: &F0) <> 0 BIC$cond $regtmp, $srcreg, #CPU32_clr :AND: &F0000000 BIC$cond $regtmp, $regtmp, #CPU32_clr :AND: &0FFFFFFF srcreg SETS "$regtmp" | [ CPU32_clr <> 0 BIC$cond $regtmp, $srcreg, #CPU32_clr srcreg SETS "$regtmp" ] ] somemsr $cond, CPSR,$srcreg, CPU32_set:OR:CPU32_clr, unsafe MEND ; **************************************************** ; *** SavePSR - Save the PSR in a register, to be *** ; *** restored later using RestPSR *** ; **************************************************** MACRO $label SavePSR $reg, $cond $label MRS$cond $reg, CPSR MEND ; **************************************************** ; *** RestPSR - Restore the PSR from a register *** ; *** set up by SavePSR *** ; *** $fields may be set to "f" if the PSR fields *** ; *** c,x,s do not need restoring, which will *** ; *** save a few cycles on newer ARMs (but the *** ; *** No32bitCode version of the macro will set *** ; *** the c field anyway). Values other than "f", *** ; *** "cf", "fc" and unset are deprecated for *** ; *** compatibility with No32bitCode. *** ; **************************************************** MACRO $label RestPSR $reg, $cond, $fields LCLS field [ "$fields"="" :LOR: "$fields"="cf" :LOR: "$fields"="fc" field SETS "cf" | [ "$fields"="f" field SETS "f" | ! 0, "Unpredictable behaviour due to deprecated RestPSR fields parameter" field SETS "$fields" ] ] $label mymsr $cond, CPSR_$field, $reg, , unsafe MEND ; ********************************************** ; *** SEC - Set carry flag - will set nzCv *** ; ********************************************** MACRO $label SEC $cond $label MSR$cond CPSR_f, #C_bit MEND ; ************************************************ ; *** SETPSR - Set bits in PSR from the mask *** ; *** in $bits, using register $regtmp *** ; ************************************************ MACRO $label SETPSR $bits, $regtmp, $cond, $oldpsr LCLS srcreg [ "$oldpsr"="" srcreg SETS "$regtmp" | srcreg SETS "$oldpsr" ] CPU32_bits PSRto32 $bits ; Map to 32 bit PSR $label MRS$cond $srcreg, CPSR [ (CPU32_bits :AND: &F0000000) <> 0 :LAND: (CPU32_bits :AND: &F0) <> 0 ; Can't be expressed as a single ARM immediate constant ORR$cond $regtmp, $srcreg, #CPU32_bits :AND: &F0000000 ORR$cond $regtmp, $regtmp, #CPU32_bits :AND: &0FFFFFFF | ORR$cond $regtmp, $srcreg, #CPU32_bits ] somemsr $cond, CPSR, $regtmp, CPU32_bits, unsafe MEND ; ************************************************** ; *** SETV - Set overflow flag - will set NzcV *** ; ************************************************** MACRO $label SETV $cond $label MSR$cond CPSR_f, #N_bit+V_bit MEND ; ********************************************************* ; *** TOGPSR - Toggle bits in PSR from the *** ; *** immediate mask in $bits, using register $regtmp *** ; ********************************************************* MACRO $label TOGPSR $bits, $regtmp, $cond, $oldpsr LCLS srcreg [ "$oldpsr"="" srcreg SETS "$regtmp" | srcreg SETS "$oldpsr" ] CPU32_bits PSRto32 $bits ; Map to 32 bit PSR $label MRS$cond $srcreg, CPSR EOR$cond $regtmp, $srcreg, #CPU32_bits somemsr $cond, CPSR, $regtmp, CPU32_bits, unsafe MEND ; ************************************************ ; *** TOGPSRR - Toggle bits in PSR from the *** ; *** mask in $regtog, using register $regtmp *** ; ************************************************ MACRO $label TOGPSRR $regtog, $regtmp, $cond, $oldpsr, $fields LCLS srcreg LCLS field [ "$fields"="" field SETS "cxsf" | field SETS "$fields" ] [ "$oldpsr"="" srcreg SETS "$regtmp" | srcreg SETS "$oldpsr" ] $label MRS$cond $srcreg, CPSR EOR$cond $regtmp, $srcreg, $regtog mymsr $cond, CPSR_$field, $regtmp, , unsafe MEND ; ************************************************* ; *** WritePSRc - Set the PSR control bits to *** ; *** an absolute value. *** ; *** Sets I,F,M[0:1], corrupts NZVC. *** ; *** Preserves 32-bitness. *** ; *** Only use in IRQ26/32,FIQ26/32,SVC26/32 *** ; *** Ignored in USR modes, illegal in others *** ; *** Use instead of TEQP PC,#$value *** ; ************************************************* MACRO $label WritePSRc $value, $regtmp, $cond, $oldpsr [ ($value :AND::NOT: (I_bit+F_bit+SVC_mode)) <> 0 ! 1, "Illegal flags for WritePSRc" ] $label SCPSR $value, (I_bit+F_bit+SVC_mode):EOR:($value), $regtmp, $cond, $oldpsr MEND ] ; :LNOT: No32bitCode ; **************************************************** ; *** mrs/msr - Lowercase funny names for aasm. *** ; *** Due for retirement, aasm is redundant now. *** ;***************************************************** MACRO $label mrs $cond, $rd, $psrs $label MRS$cond $rd, $psrs MEND MACRO $label msr $cond, $psrl, $op2a, $op2b $label mymsr $cond, $psrl, $op2a, $op2b MEND ; *************************************************** ; *** somemsr - Set some fields of the PSR from *** ; *** $op, according to $mask. The mask should *** ; *** indicate which bits have been modified. *** ; *** This saves us writing the control field, *** ; *** when it hasn't been modified, for example, *** ; *** saving 2 cycles on some processors. *** ; *************************************************** MACRO $label somemsr $cond, $psr, $op, $mask, $sabug LCLS s s SETS "$psr._" [ (($mask) :AND: &FF) <> 0 s SETS s:CC:"c" ] [ (($mask) :AND: &FF00) <> 0 s SETS s:CC:"x" ] [ (($mask) :AND: &FF0000) <> 0 s SETS s:CC:"s" ] [ (($mask) :AND: &FF000000) <> 0 s SETS s:CC:"f" ] $label mymsr $cond, $s, $op, , $sabug MEND ; **************************************************** ; *** mymrs - Perform an MRS operation. *** ; *** Due for retirement, objasm supports MRS now. *** ;***************************************************** MACRO $label mymrs $cond, $rd, $psrs $label LCLA psrtype psrtype SETA -1 [ "$psrs" = "CPSR_all" :LOR: "$psrs" = "SPSR_all" ! 0, "Deprecated form of PSR field specifier used (use no suffix)" ] [ "$psrs" = "CPSR" :LOR: "$psrs" = "CPSR_all" psrtype SETA 0 :SHL: 22 ] [ "$psrs" = "SPSR" :LOR: "$psrs" = "SPSR_all" psrtype SETA 1 :SHL: 22 ] ASSERT psrtype <> -1 ASSERT $rd <> 15 DCI Cond_$cond :OR: 2_00000001000011110000000000000000 :OR: psrtype :OR: ($rd :SHL: 12) MEND ; **************************************************** ; *** mymsr - Perform an MSR operation. *** ; *** If $sabug is set to "safe", it's assumed the *** ; *** code around this operation is sufficiently *** ; *** protected against the StrongARM conditional *** ; *** MSR CPSR_c bug. *** ; *** If $sabug is set to "unsafe", a NOP will *** ; *** automatically be inserted when generating an *** ; *** MSR that could trigger the bug (and we're *** ; *** targeting a StrongARM machine type). *** ; *** If $sabug is left unset, a warning and a NOP *** ; *** will be produced whenever a dangerous MSR is *** ; *** requested (if we're targeting StrongARM) *** ; **************************************************** MACRO $label mymsr $cond, $psrl, $op2a, $op2b, $sabug $label LCLA psrtype LCLS op2as LCLA op LCLA shift LCLS s s SETS "$psrl" [ s:RIGHT:4 = "_ctl" :LOR: s:RIGHT:4 = "_flg" ! 0, "Deprecated form of PSR field specifier used (use _cxsf)" s SETS s:LEFT:(:LEN:s-2) ] [ s:RIGHT:4 = "_all" ! 0, "Deprecated form of PSR field specifier used (use _cxsf)" s SETS s:LEFT:(:LEN:s-3) :CC: "cf" ] [ s:RIGHT:3 = "PSR" ! 0, "Deprecated form of PSR field specifier used (use _cxsf)" s SETS s:CC:"_cf" ] psrtype SETA 0 [ s:RIGHT:1 = "f" psrtype SETA psrtype :OR: (1:SHL:19) s SETS s :LEFT: (:LEN:s-1) ] [ s:RIGHT:1 = "s" psrtype SETA psrtype :OR: (1:SHL:18) s SETS s :LEFT: (:LEN:s-1) ] [ s:RIGHT:1 = "x" psrtype SETA psrtype :OR: (1:SHL:17) s SETS s :LEFT: (:LEN:s-1) ] [ s:RIGHT:1 = "c" psrtype SETA psrtype :OR: (1:SHL:16) s SETS s :LEFT: (:LEN:s-1) ] ASSERT s = "CPSR_" :LOR: s = "SPSR_" [ s = "SPSR_" psrtype SETA psrtype :OR: (1:SHL:22) | psrtype SETA psrtype :OR: (0:SHL:22) ] [ (psrtype :AND: (15:SHL:16)) = 0 ! 0, "MSR that sets no fields" ] [ ("$op2a" :LEFT: 1) = "#" ; Immediate operand op2as SETS "$op2a" :RIGHT: ((:LEN: "$op2a")-1) op SETA $op2as [ "$op2b" = "" ; Rotate not specified in immediate operand shift SETA 0 WHILE (op :AND: &FFFFFF00)<>0 :LAND: shift<16 op SETA ((op:SHR:30):AND:3):OR:(op:SHL:2) shift SETA shift + 1 WEND ASSERT (op :AND: &FFFFFF00)=0 | ; Rotate of immediate operand specified explicitly ASSERT (($op2b):AND:&FFFFFFE1)=0 shift SETA ($opt2b):SHR:1 ] op SETA (shift :SHL: 8) :OR: op :OR: (1:SHL:25) | ; Not an immediate operand [ "$op2b" = "" ; Unshifted register op SETA ($op2a) :OR: (0:SHL:25) | ! 1, "Shifted register not yet implemented in this macro!" ] ] DCI Cond_$cond :OR: 2_00000001001000001111000000000000 :OR: op :OR: psrtype [ StrongARM_MSR_bug :LAND: "$sabug" <> "safe" :LAND: "$cond" <> "AL" :LAND: "$cond" <> "" :LAND: ((psrtype :AND: &410000) = &10000) [ "$sabug" <> "unsafe" ! 0, "mymsr inserting NOP for StrongARM MSR CPSR_c bug" ] NOP ] MEND ; **************************************************** ; *** SetMode - sets processor mode to constant *** ; *** value newmode using register regtmp as a *** ; *** temporary. *** ; **************************************************** MACRO SetMode $newmode, $regtmp, $oldpsr [ "$oldpsr"="" MRS $regtmp, CPSR BIC $regtmp, $regtmp, #M32_bits ORR $regtmp, $regtmp, #$newmode MSR CPSR_c, $regtmp | MRS $oldpsr, CPSR BIC $regtmp, $oldpsr, #M32_bits ORR $regtmp, $regtmp, #$newmode MSR CPSR_c, $regtmp ] MEND ] ; :LNOT: :DEF: Included_Hdr_CPU_Generic32 OPT OldOpt END