>rbsrc   Richard Murray ( Monday, 23rd October 2000 2 <5 Based upon a game I downloaded (or cover disc?) F P Z = &8000 + (128*1024) d n $+" at "+(/10) : x  code% 2048   loop% = 8 10 2  P% = code%  L% = code% + 2048  [ OPT loop%  ; Program entry  = ; R1 = memory limit, so set this to be stack pointer. E MOV R13, R1 ; *** TESTING FROM BASIC *** D STMFD R13!, {R14} ; (you must patch it out)  T ; Check FPEmulator is loaded. This checks to see if "FPEmulator" is present. [ ; Don't know if other versions of FPE call themselves "FPEmulator". A quick hack of W ; SharedCLibrary suggests that "_kernel_fpavailable" uses a very similar way of ; ; detecting if floating point maths is available... "+ ; Is anybody STILL using RISC OS 2? , MOV R0, #18 6 ADR R1, fpemulator @ SWI "XOS_Module" JX BVS fpe_not_loaded ; Report an error if error returned (module not found...) T ^3 ; Store current <255> character definition. h MOV R0, #10 r# ADR R1, chartwofivefive | SWI "OS_Word"  ( ; Set up seed to be more random.  ADR R1, seed & SWI "OS_ReadMonotonicTime"  STR R0, [R1]  8 ; Redefine character 255 to be a rounded square.  SWI &100 + 23  SWI &100 + 255  SWI &100 + 126  SWI &100 + 255  SWI &100 + 255  SWI &100 + 255  SWI &100 + 255  SWI &100 + 255  SWI &100 + 255 & SWI &100 + 126 0 : .restart DB \ Program is re-entered here if user wishes to play again. N X b, ; Select 1, and switch off cursor. l SWI &100 + 22 v SWI &100 + 1 " SWI "OS_RemoveCursors"   \ The main game loop. .game_loop  BL draw_screen  BL game  CMP R0, #0  BEQ game_lost  B game_won    .draw_screen , \ This sets up the screen for a game   \ Corrupts R0-R5. $ \ Returns via stacked R14.   * STMFD R13!, {R14} 4 >( SWI &100 + 12 ; H R, SWI &100 + 18 ; 0,2 \ SWI &100 + 0 f SWI &100 + 2 p zT MOV R4, #0 ; Draw a three-sided border (left, top, bottom) # ADR R5, border_commands .border_loop I LDMIA R5!, {R0-R2} ; Border commands are stored as data O SWI "OS_Plot" ; to allow this to work a little faster...  ADD R4, R4, #1  CMP R4, #4  BLT border_loop  ) ; Now set up and plot the blocks.  MOV R3, #0 .block_loop H MOV R0, #63 ; Need >31, so use 63 as next range  BL random I CMP R0, #34 ; Now constrain to within 34 by ing N GT R0, R0, #31 ; the larger numbers to be in range 0...31. X ADD R0, R0, #4 ; Add four, to push away from the left hand border. $> MOV R4, R0 ; Preserve X random in R4 . MOV R0, #31 8 BL random B> MOV R5, R0 ; Preserve Y random in R5 L V9 SWI &100 + 31 ; 31,,,255 ` MOV R0, R4 j SWI "OS_WriteC" t MOV R0, R5 ~ SWI "OS_WriteC"  SWI &100 + 255   ADD R3, R3, #1 I CMP R3, #70 ; This is the number of blocks drawn W BLT block_loop ; 50 is suggested minimum, 90 is suggested maximum  & ; Draw left-hand border blocks  MOV R0, #0 .left_block_loop 6 SWI &100 + 31 ; 31,0,,255 H SWI &100 ; Which is "TAB(0,);CHR$(255);"  SWI "OS_WriteC"  SWI &100 + 255   ADD R0, R0, #3  CMP R0, #32  BLT left_block_loop ( 28 MOV R0, #15 ; Flush all buffers < MOV R1, #0 F SWI "OS_Byte" P Z@ LDMFD R13!, {PC} ; Return to game_loop code. d n x .border_commands S \ A sequence of commands for the OS_Plot loop, to draw a three-sided border 2 EQUD 4 ; 1279,1023 : EQUD 1279 ; (move to top right)  EQUD 1023 / EQUD 5 ; 0,1023 9 EQUD 0 ; (draw to top left)  EQUD 1023 , EQUD 5 ; 0,0 < EQUD 0 ; (draw to bottom left)  EQUD 0 / EQUD 5 ; 1279,0 = EQUD 1279 ; (draw to bottom right)  EQUD 0   " , .game 6 \ This is the game loop. @! \ Corrupts R0-R2,R5-R8. J \ Corrupts F0-F7. T$ \ Returns via stacked R14. ^ \ h" \ Returns the score in R0. r \ |[ \ Once set up, all FP operations are performed in the seven available FP registers. _ \ Values are FIXed to the ARM processor for SWI calls, but there is no repeated loading [ \ and storing of data from/to memory. This might not have a tremendous impact on an K \ emulated FPA, but should help a real hardware FPA perform well...   STMFD R13!, {R14}  ) ; Set up floating point registers  ADR R0, acceleration 7fp("LDFS F1,[R0]") ; F1 = acceleration  MOV R0, #4 Gfp("FLTS F2,R0") ; F2 = x (nb. F3 is below) (= 4) Gfp("FLTS F4,R0") ; F4 = xs (= 4) Gfp("MVFS F5,#0") ; F5 = ys (= 0) Gfp("MVFS F6,#0") ; F6 = sc (= 0)  ADR R0, gravity -fp("LDFS F7,[R0]") ; F7 = gr & 0% ; Calculate starting position :.start_point_loop D ; Get a random offset N MOV R0, #512 X SUB R0, R0, #1 b BL random l4 ADD R8, R0, #256 ; R8 is temp. Y v, ; Read that point, and +/- 8 from it  MOV R0, #4  MOV R1, R8  SWI "OS_ReadPoint" 2 MOV R5, R2 ; R5 is x,y)  ADD R1, R1, #8  SWI "OS_ReadPoint" 4 MOV R6, R2 ; R6 is x,y+8)  SUB R1, R1, #16  SWI "OS_ReadPoint" 4 MOV R7, R2 ; R7 is x,y-8)  - ; Did all points return zero (black)?  CMP R5, #0  BNE start_point_loop   CMP R6, #0  BNE start_point_loop   CMP R7, #0 * BNE start_point_loop 4 >+ ; Get here, R8 is good for Y offset H,fp("FLTS F3,R8") ; F3 = y R \/ MOV R0, #4 ; 0, f MOV R1, #0 p MOV R2, R8 z SWI "OS_Plot"  , SWI &100 + 18 ; 0,1  SWI &100 + 0  SWI &100 + 1  .game_loop 5 MOV R0,#19 ; Wait for VSync 5 SWI "OS_Byte" ; Corrupts R1,R2  -fp("ADFS F6,F6,#1") ; sc += 1   ; Draw next bit of line 0 MOV R0, #5 ; , Efp("FIXS R1,F2") ; Takes X and Y from FP registers fp("FIXS R2,F3")  SWI "OS_Plot" $ . ; Increment offsets 8,fp("ADFS F2,F2,F4") ; x=x+xs B,fp("ADFS F3,F3,F5") ; y=y+ys L V ; Read x+xs,y) `-fp("ADFS F0,F2,F4") ; F0=x+xs j+fp("FIXS R0,F0") ; Get X t+fp("FIXS R1,F3") ; Get Y ~ SWI "OS_ReadPoint" 2 CMP R2,#3 ; Colour = 3? 2fp("MVFEQS F0,F4") ; Conditional: 4fp("SUFEQS F4,F4,F4") ; xs - xs - xs =fp("SUFEQS F4,F4,F0") ; (which equals "xs=-xs") ? MOV R6, R2 ; It'll be needed later...  \ ; Time delay (comment out this block to run it at full speed (processor dependent)). & SWI "OS_ReadMonotonicTime" 5 ADD R1, R0, #2 ; 2 centiseconds O.time_delay_loop ; Not much, but enough... 3cs is too slow. & SWI "OS_ReadMonotonicTime"  CMP R0, R1  BLT time_delay_loop   ; ESC pressed? $ SWI "OS_ReadEscapeState" (E BCS abort_exit ; Abort if ESC has been pressed. 2 < ; Space pressed? F MOV R0, #121 PG MOV R1, #226 ; 98 &80, = check LY for Space. Z SWI "OS_Byte" dE CMP R1, #255 ; Returns 255 if key is pressed. n:fp("ADFEQS F5,F5,F1") ; ys=ys+ x _fp("SUFS F5,F5,F7") ; ys=ys+gr - add a little gravity into the mix! Blub! Blub!  \ CMN R6, #1 ; If not off-screen (told you it'd be needed again!)... 3 BNE game_loop ; ...carry on.  -fp("ADFS F0,F2,F4") ; F0=x+xs +fp("FIXS R0,F0") ; Get X # ADR R2, onetwoeightzero  LDR R1, [R2] 0 CMP R0, R1 ; X < 1280? @ MOVLT R0, #0 ; If yes, return score = 0. 8fp("FIXGES R0,F6") ; Else, get score... ? LDMFD R13!, {PC} ; ...and return from game.    ".abort_exit ,! \ This will abort tidily. 6 \ @_ \ Whenever this is called, there should be TWO R14's on the stack. This will load both, JO \ discard the more recent and use the older - thus returning correctly. T] \ It is nicer, if you are running this from a BASIC shell (ie, when testing), than to ^; \ call "OS_Exit" (which will exit from BASIC too!). hV \ Gives a message, but it isn't presented as an error. This is tidy, remember? r |( SWI &100 + 12 ; 6 ADR R0, abort_message ; Print a message  SWI "OS_Write0" 6 MOV R0, #126 ; Acknowledge ESC  SWI "OS_Byte" ? BL restore_character ; Restore <255> character. _ LDMFD R13!, {R0,PC} ; Exit (should load two stored R14, junk 1st, use 2nd...).    .fpe_not_loaded J \ If FPEmulator module is not loaded, then return a (fatal) error. ( ADR R0, fpemulator_not_found " SWI "OS_GenerateError"    &M \ ******************************************************************* 0J \ , vaguely (?) in the middle so can be accessed from all code... :M \ ******************************************************************* D N.onetwoeightzero X EQUD 1280 b l.abort_message v, EQUS "ESCAPE pressed, exiting..."  EQUB 10  EQUB 0  .msg_press_space 0 EQUS " Press SPACE for another game "  EQUB 0  EQUB 0  .msg_bad_luck  EQUS "Bad luck..."  EQUB 0  .msg_well_done  EQUS "Well Done!"  EQUB 0  EQUB 0  *.msg_score 4 EQUS "Score: " > EQUB 0 H R.msg_high_score \ EQUS "High score: " f EQUD 0 p z.msg_new_high_score " EQUS "New high score: "  EQUD 0  .msg_enter_name " EQUS "Enter your name:"  EQUD 0  .fpemulator  EQUS "FPEmulator"  EQUB 0  EQUB 0  .fpemulator_not_found  EQUD 0 D EQUS "The FPEmulator module does not appear to be loaded"  EQUB 0 $ EQUB 0 . 8.seed_pointer B EQUD seed L V .seed ` EQUD &55555555 j EQUD &55555555 t ~ .buffer  EQUD 0  EQUD 0  .high_score T EQUD 320 ; Straight line across is approx. 318 points...  .high_name T EQUS "Richard Murray" ; Yeah, well... I wrote it, okay? Deal with it! - EQUB 0 ;  EQUB 0 Q EQUD 0 ; 20 bytes (16 used, 1 terminator, 3 wasted)   .emanon  S EQUS "" ; Default name if user doesn't enter anything.  EQUD 0  (U.chartwofivefive ; 12 byte block for stored character definition. 2R EQUB 255 ; Only 9 bytes are needed, but word alignment  \ 31 30..................23 22...............0 ,> \ Sign Exponent (excess-128?) msb Fraction lsb 6 @ J T .game_won ^S \ If user wins (ie, score non-zero), then this will sort out "done good" vs h \ "new high score". r \ | \ Corrupts R0-R1,R8. ' \ Sets R8 to score when done. = \ Does not return, calls one of two other routines.  : MOV R8, R0 ; Preserve high score  * MOV R0, #0 ; 3  MOV R1, #3  SWI "OS_SetColour"  - SWI &100 + 31 ; 14,8)  SWI &100 + 14  SWI &100 + 8 ; ADR R0, msg_well_done ; Print congratulation  SWI "OS_Write0"  9 ADR R1, high_score ; Compare high score & LDR R0, [R1] 0 CMP R8, R0 : BGT new_high_score DD ; B good_score ; ...but_not_good_enough N& ; ** ENTIONAL FALL THROUGH ** X b l v.good_score Q \ If user has a good score (not won, not lost), then give them a message. G \ Corrupts R0-R2,R10, and expects a value to be stored in R8. 1 \ Does not return, calls another routine.  * MOV R0, #0 ; 2  MOV R1, #2  SWI "OS_SetColour"  . SWI &100 + 31 ; 14,10)  SWI &100 + 14  SWI &100 + 10  7 ADR R0, msg_score ; Print your score  SWI "OS_Write0"   MOV R0, R8  ADR R1, buffer   MOV R2, #8 *$ SWI "OS_BinaryToDecimal" 4 ADR R0, buffer > MOV R1, R2 H SWI "OS_WriteN" R \* MOV R0, #0 ; 1 f MOV R1, #1 p SWI "OS_SetColour" z  MOV R10, #12 ! B print_high_scorer    .new_high_score T \ If user has a won, give them a message, get their name, update high score. C \ Corrupts R0-R3, and expects a value to be stored in R8. 1 \ Does not return, calls another routine.  * MOV R0, #0 ; 2  MOV R1, #2  SWI "OS_SetColour"  . SWI &100 + 31 ; 12,10)  SWI &100 + 12 $ SWI &100 + 10 . 8C ADR R0, msg_new_high_score ; Print congratulatory score B SWI "OS_Write0" L MOV R0, R8 V ADR R1, buffer ` MOV R2, #8 j$ SWI "OS_BinaryToDecimal" t ADR R0, buffer ~ MOV R1, R2  SWI "OS_WriteN"  . SWI &100 + 31 ; 12,12)  SWI &100 + 12  SWI &100 + 12  5 ADR R0, msg_enter_name ; Mortier prompt  SWI "OS_Write0"  8 MOV R0, #15 ; Flush all buffers  MOV R1, #0  SWI "OS_Byte"   . SWI &100 + 31 ; 12,14)  SWI &100 + 12  SWI &100 + 14 ( 28 ADR R1, high_score ; Update high score < STR R8, [R1] F P/ SWI "OS_RestoreCursors" ; Get name Z ADR R0, high_name dW ADD R0, R0, #&80000000 ; Set bit 31, echo only characters entering buffer n MOV R1, #16 x MOV R2, #(" ")  MOV R3, #("z")  SWI "XOS_ReadLine" 3 BCS abort_exit ; Esc pressed? " SWI "OS_RemoveCursors"  A CMP R1, #0 ; User entered a blank name?  BEQ handle_emanon  O ADR R0, high_name ; Patch in a null byte instead of newline.  ADD R0, R0, R1  MOV R1, #0  STRB R1, [R0]  .return_after_emanon 8 ADR R1, high_score ; Update high score  STR R8, [R1] " ,.empty_keybuffer 6R MOV R0, #121 ; Dispatch stacked keypresses by the mightily @S MOV R1, #16 ; technical way of simply junking them. J SWI "OS_Byte" T> CMP R1, #255 ; If something pressed... ^7 BNE empty_keybuffer ; ...keep looping. h r B new_game |   .handle_emanon L \ This handles a case of no name entered, by copying a default name.  \ Corrupts R0-R2. A \ Returns by branching to a point in the calling routine.   ADR R1, emanon  ADR R2, high_name .emanon_loop  LDRB R0, [R1], #1  STRB R0, [R2], #1  CMP R0, #0  BNE emanon_loop # B return_after_emanon  & 0 :.game_lost DQ \ If user has a good score (not won, not lost), then give them a message. N \ Corrupts R0,R1,R10. X1 \ Does not return, calls another routine. b l* MOV R0, #0 ; 1 v MOV R1, #1  SWI "OS_SetColour"  - SWI &100 + 31 ; 14,8)  SWI &100 + 14  SWI &100 + 8 : ADR R0, msg_bad_luck ; Print commiseration  SWI "OS_Write0"  * MOV R0, #0 ; 2  MOV R1, #2  SWI "OS_SetColour"   MOV R10, #10 ! B print_high_scorer      *.print_high_scorer 43 \ Prints the name/score of the high scorer. > \ Corrupts R0-R2,R5 HD \ Expects R10 to be Y position for printing this stuff at. R1 \ Does not return, calls another routine. \ f9 ADR R1, high_score ; Convert high score p LDR R0, [R1] z ADR R1, buffer  MOV R2, #8 $ SWI "OS_BinaryToDecimal" = MOV R5, R2 ; Preserve string length  / ; Now we count up the string lengths... ; MOV R0, #13 ; Misc. string lengths 3 ADD R0, R0, R2 ; Score length G ADR R2, high_name ; Calculate high score name length  .glsll  LDRB R1, [R2], #1  CMP R1, #0  ADDNE R0, R0, #1  BNE glsll 7 MOV R1, #40 ; Calculate offset  SUB R1, R1, R0 ) MOV R0, R1, ASR#1 ; /2 $ ./ SWI &100 + 31 ; ,10) 8 SWI "OS_WriteC" B MOV R0, R10 L SWI "OS_WriteC" V `2 ADR R0, msg_high_score ; Print title j SWI "OS_Write0" t2 ADR R0, buffer ; Print score ~ MOV R1, R5  SWI "OS_WriteN" 5 SWI &100 + 32 ; Output a space A ADR R0, high_name ; Print name of high scorer.  SWI "OS_Write0"   B new_game     .new_game N \ Does the user want to play again? SPACE if yes, anything else quits.  \ Corrupts R0-R1. 1 \ Expects stacked R14 to be exit pointer.  B \ Also expects stacked keypresses to have been dealt with.  8 MOV R0, #15 ; Flush all buffers ( MOV R1, #0 2 SWI "OS_Byte" < F* MOV R0, #0 ; 3 P MOV R1, #3 Z SWI "OS_SetColour" d n- SWI &100 + 31 ; 5,30) x SWI &100 + 5  SWI &100 + 30 3 ADR R0, msg_press_space ; Print prompt  SWI "OS_Write0" .await_keypress  MOV R0, #121 L MOV R1, #16 ; Skip checking for modifier keys/mouse  SWI "OS_Byte" : CMP R1, #255 ; If HING pressed... 7 BEQ await_keypress ; ...keep looping. : CMP R1, #98 ; If Space pressed... 7 BEQ restart ; ...play again... 0 MVN R0, #0 ; [ R0 = -1 \ SWI "XWimp_CommandWindow"; will cause "Press Space" message to be suppressed ] B BL restore_character ; [ Restore <255> character ] 4 LDMFD R13!, {PC} ; ...else exit.  " , 6.restore_character @K \ Restores the <255> character to its original state, upon an exit. J \ Corrupts R0-R2. T \ Returns via R14. ^ h# ADR R1, chartwofivefive r MOV R2, #0 | SWI &100 + 23 .restore_loop  LDRB R0, [R1], #1  SWI "OS_WriteC"  ADD R2, R2, #1  CMP R2, #9  BLT restore_loop   MOV PC, R14     .random 9 \ Generates a random number and returns it in R0. X \ Expects a range in R0 upon entry, which must contain all bits in wanted range. ) \ Uses R1-R5, and preserves them.  \ &X \ Taken from the "random.s" example on the ARM development demonstration CD-ROM: 0U \ This uses a 33-bit feedback shift register to generate a pseudo-randomly :T \ ordered sequence of numbers which repeats in a cycle of length 2^33 - 1 D \ N1 \ Corrupts R0 (returns a value in it!). X3 \ Preserves other registers used (R1-R4). b$ \ Returns via stacked R14. l v" STMFD R13!, {R1-R4, R14}  ADR R4, seed_pointer  LDMIA R4, {R1, R2} 8 TST R2, R2, LSR#1 ; to bit into carry : MOVS R3, R1, RRX ; 33-bit rotate right ; ADC R2, R2, R2 ; carry into LSB of a2 0 R3, R3, R1, LSL#12 ; (involved!) : R1, R3, R3, LSR#20 ; (similarly involved!)  STMIA R4, {R1, R2} U R0, R1, R0 ; random number with range, and store the result C LDMFD R13!, {R1-R4, PC} ; in R0 ready for returning...   ]    _p$="IDEFS::Amy.$._ENTRY.Willow.Coding.Projects.Assembler.asmarea.apcsstuff.rebound.rebound" /("Save "+p$+" "+~code%+" +"+~(P%-code%))  ("SetType "+p$+" FF8") * 4Hcode%!0 = &E1A00000 : Patch out R13 set with "MOV R0, R0" (NOP)... > REPEAT H code% R IF INKEY(-3) THEN END \ UNTIL 0 f p z   ݤfp(a2$) 7 i%,c$,prec%,fd%,fn%,fm%,rd%,t$,op%,addr%,a$,noch%  M "Error during assembly of instruction """+a2$+""" : """+$+"""":  a$=a2$  prec%=0  noch%= : M a$,5)<>"CMFEQ" a$,5)<>"CNFEQ" a$,5)<>"CMFE " a$,5)<>"CNFE "  t$=a$,4)  Ȏ t$  "CMFE","CNFE": (i%=%00001110000100001111000100010000  a$=a$,5) fd%=0:fn%=1:fm%=2:rd%=0 $ Ȏ t$ . "CMFE":op%=%110 8 "CNFE":op%=%111 B Li%=i% (op%<<21) V ` j: t i%=0 ~ t$=a$,3)  Ȏ t$ T "ADF","MUF","SUF","RSF","DVF","RDF","POW","RPW","RMF","FML","FDV","FRD","POL": (i%=%00001110000000000000000100000000  a$=a$,4) fd%=1:fn%=2:fm%=3:rd%=0  Ȏ t$  "ADF":op%=%00000 $ "MUF":op%=%10010 : op%=%00010  "SUF":op%=%00100  "RSF":op%=%00110 $ "DVF":op%=%10100 : op%=%01000  "RDF":op%=%01010  "POW":op%=%01100   "RPW":op%=%01110  "RMF":op%=%10000  "FML":op%=%10010 ( "FDV":op%=%10100 2 "FRD":op%=%10110 < "POL":op%=%11000 F Pi%=i% (op%<<19) Z* "FLT","FIX","WFS","RFS","WFC","RFC": d(i%=%00001110000000000000000100010000 n a$=a$,4) x Ȏ t$ - "FLT":op%=%0000:fd%=0:fn%=1:fm%=0:rd%=2 - "FIX":op%=%0001:fd%=0:fn%=0:fm%=2:rd%=1 - "WFS":op%=%0010:fd%=0:fn%=0:fm%=0:rd%=1 - "RFS":op%=%0011:fd%=0:fn%=0:fm%=0:rd%=1 - "WFC":op%=%0100:fd%=0:fn%=0:fm%=0:rd%=1 - "RFC":op%=%0101:fd%=0:fn%=0:fm%=0:rd%=1  i%=i% (op%<<20)  "LDF","STF":noch%= (i%=%00001100000000000000000100000000  a$=a$,4)  Ȏ t$ ) "LDF":op%=1:fd%=1:fn%=0:fm%=0:rd%=0 ) "STF":op%=0:fd%=1:fn%=0:fm%=0:rd%=0   addr%=2 " prec%=1 ,i%=i% (op%<<20) 6Z "MVF","MNF","ABS","RND","SQT","LOG","LGN","EXP","SIN","COS","TAN","ASN","ACS","ATN": @(i%=%00001110000000000000000100000000 J a$=a$,4) Tfd%=1:fn%=0:fm%=2:rd%=0 ^ Ȏ t$ h "MVF":op%=%0000 r "MNF":op%=%0001 | "ABS":op%=%0010  "RND":op%=%0011  "SQT":op%=%0100  "LOG":op%=%0101  "LGN":op%=%0110  "EXP":op%=%0111  "SIN":op%=%1000  "COS":op%=%1001  "TAN":op%=%1010  "ASN":op%=%1011  "ACS":op%=%1100  "ATN":op%=%1101  i%=i% (op%<<20) i%=i% (1<<15)  "CMF","CNF": (i%=%00001110000100001111000100010000 & a$=a$,4) 0fd%=0:fn%=1:fm%=2:rd%=0 : Ȏ t$ D "CMF":op%=%100 N "CNF":op%=%101 X bi%=i% (op%<<21) l v : " i%=0 78,"Unknown mnemonic" : c$=a$,2) W (c$,1)="S" c$,1)="D" c$,1)="E" c$,1)="P" c$,1)=" ") c$,2)<>"EQ" *i%=i% (%1110<<28): Set AL condition  Ȏ c$  "AL":i%=i% (%1110<<28)  "CC":i%=i% (%0011<<28)  "CS":i%=i% (%0010<<28)  "EQ":i%=i% (%0000<<28)  "GE":i%=i% (%1010<<28) ! "GT":i%=i% (%1100<<28) !  "HI":i%=i% (%1000<<28) ! "LE":i%=i% (%1101<<28) !  "LS":i%=i% (%1001<<28) !* "LT":i%=i% (%1011<<28) !4 "MI":i%=i% (%0100<<28) !> "NE":i%=i% (%0001<<28) !H "NV":i%=i% (%1111<<28) !R "PL":i%=i% (%0101<<28) !\ "VC":i%=i% (%0111<<28) !f "VS":i%=i% (%0110<<28) !p "LO":i%=i% (%0011<<28) !z "HS":i%=i% (%0010<<28) !#: 78,"Unknown condition code" ! ! a$=a$,3) ! !: ! c$=a$,1) ! a$=a$,2) ! noch%= ! prec%=0 ! Ȏ c$ ! "S": No change needed ! "D":i%=i% (1<<7) ! "E":i%=i% (1<<19) "( "P":i%=i% (1<<7):i%=i% (1<<19) "(: 78,"Missing precision indicator" " "$ ". Ȏ c$ "8 "S": No change needed "B "D":i%=i% (1<<15) "L "E":i%=i% (1<<22) "V) "P":i%=i% (1<<15):i%=i% (1<<22) "`(: 78,"Missing precision indicator" "j "t "~ ": " a$,1)<>" " " c$=a$,1) " a$=a$,2) " Ȏ c$ " "P":i%=i% (1<<5) " "M":i%=i% (1<<6) "' "Z":i%=i% (1<<5):i%=i% (1<<6) "': 78,"Unknown rounding attribute" " " ": #a$=a$,2): Remove space # c$=a$,a$,",")): 1st reg # a$,",")=0 c$=a$ #a$=a$,a$,",")+1) #(l (fd%=1 fn%=1 fm%=1) c$,1)<>"F" 78,"First register must be a FP register for this instruction" #2[ rd%=1 c$,1)<>"R" 78,"First register must be a ARM register for this instruction" #<( fd%=1 i%=i% ((fpconst(c$))<<12) #F( fn%=1 i%=i% ((fpconst(c$))<<16) #P$ fm%=1 i%=i% ((fpconst(c$))) #Z( rd%=1 i%=i% ((fpconst(c$))<<12) #d: #n addr%=2 #x1 c$="[Rx]<,#offset>" or c$="[Rx,#offset]" # a$=a$,2) #c$=a$,a$,",")-1) # a$,",")=0 c$=a$ #i%=i% (fpconst(c$)<<16) #: # a$,",")<>0 # c$,1)="]" # post-index #c$=a$,a$,",")+1) #E c$,1)<>"#" 78,"Only constants can be specified as an offset" # c$=c$,2) #9 (c$)>1020 (c$)<-1020 78,"Offset out of range" #i%=i% (((c$)) 4) $ (c$)>=0 i%=i% (1<<23) $ $ pre-index $"i%=i% (1<<24) $,c$=a$,a$,",")+1) $6E c$,1)<>"#" 78,"Only constants can be specified as an offset" $@ c$=c$,2) $J9 (c$)>1020 (c$)<-1020 78,"Offset out of range" $Ti%=i% (((c$)) 4) $^ (c$)>=0 i%=i% (1<<23) $h a$,1)="!" i%=i% (1<<21) $r $| $ $: $'c$=a$,a$,",")): 2nd reg OR value $ a$,",")=0 c$=a$ $ a$="" 78,"Not supported" $a$=a$,a$,",")+1) $e (fd%=2 fn%=2) c$,1)<>"F" 78,"Second register must be a FP register for this instruction" $u fm%=2 c$,1)<>"F" c$,1)<>"#" 78,"Second register must be a FP register or constant for this instruction" $\ rd%=2 c$,1)<>"R" 78,"Second register must be a ARM register for this instruction" $( fn%=2 i%=i% ((fpconst(c$))<<16) $$ fm%=2 i%=i% ((fpconst(c$))) $( rd%=2 i%=i% ((fpconst(c$))<<12) $' fm%=2 c$,1)="#" i%=i% (1<<3) % a$="" 78,"Not supported" % c$=a$ %t fm%=3 c$,1)<>"F" c$,1)<>"#" 78,"Third register must be a FP register or constant for this instruction" %&$ fm%=3 i%=i% ((fpconst(c$))) %0' fm%=3 c$,1)="#" i%=i% (1<<3) %: %D: %N[OPT loop% %X EQUD i% %b] %l PRINT %v( OSCLI "MemoryI "+STR$~(O%-4)+" +4" %=0 %: % fpconst(c$) %Ȏ c$,1) % "#": % (c$,2))=10.0 =7 % (c$,2))=0.5 =6 %o (c$,2))<0 (c$,2))>5 78,"No FP constant other than 0.0,1.0,2.0,3.0,4.0,5.0,0.5,10.0 are allowed" %M ((c$,2)))<>(c$,2)) 78,"No FP fraction other than 0.5 is allowed" %=(c$,2)) % "R": %W (c$,2))>15 (c$,2))<0 78,"ARM Register references must be between 0 and 7" %=(c$,2)) & "F": & U (c$,2))>7 (c$,2))<0 78,"FP Register references must be between 0 and 7" &=(c$,2)) &  &*=0 &4: &> dfp &H "F0: ";|(fpblk+0) &R "F1: ";|(fpblk+8) &\ "F2: ";|(fpblk+16) &f "F3: ";|(fpblk+24) &p "F4: ";|(fpblk+32) &z "F5: ";|(fpblk+40) & "F6: ";|(fpblk+48) & "F7: ";|(fpblk+56) & &: & rad &[OPT loop% &adr(0,pi) &fp("LDFD F5,[R0,#0]") &fp("MUFD F7,F5,F7") &adr(0,oneeighty) &fp("LDFD F6,[R0,#0]") &fp("DVFD F7,F7,F6") &] '=0 ' ' '$ '. MOV R0, R1 '8 ADR R1, buffer 'B MOV R2, #8 'L& SWI "OS_BinaryToDecimal" 'V ADR R0, buffer '` MOV R1, R2 'j SWI "OS_WriteN" 't SWI "OS_NewLine"