├── !UCDebug ├── !Run,feb ├── !RunImage,e1f ├── !Sprites └── !Sprites22 ├── AUTHORS.md ├── LICENSE ├── Makefile ├── README.md ├── Tests ├── Makefile ├── Modes │ ├── Enter │ │ ├── abt.s │ │ ├── fiq.s │ │ ├── irq.s │ │ ├── sys.s │ │ └── und.s │ └── Leave │ │ ├── abt.s │ │ ├── fiq.s │ │ ├── irq.s │ │ ├── sys.s │ │ └── und.s ├── Reset │ ├── CPSR_Reset │ │ ├── check_cpsr.s │ │ └── modify_cpsr.s │ ├── Mode_Reset │ │ ├── abt.s │ │ ├── check_mode.s │ │ ├── fiq.s │ │ ├── irq.s │ │ ├── readme.txt │ │ ├── svc.s │ │ ├── sys.s │ │ └── und.s │ └── Stack_Reset │ │ ├── check_stacks.s │ │ ├── modify_stacks.s │ │ └── readme.txt ├── SWI │ ├── 001_exit_def.s │ ├── 101_writec.s │ ├── 201_write0.s │ ├── 301_readc.s │ ├── 302_readc_nonblock.s │ ├── 401_enteros.s │ ├── 501_leaveos.s │ ├── 601_convert_int.s │ ├── 701_hardware.s │ ├── 801_claim_release.s │ ├── 802_claim_without_release.s │ └── 803_release_without_claim.s ├── compileTests,feb └── documentation.txt ├── c ├── CodeWin ├── ConsWin ├── DataWin ├── Debug ├── FPRegsWin ├── Interpreter ├── RegsWin └── ibar ├── compile,feb ├── h ├── CodeWin ├── ConsWin ├── DataWin ├── FPRegsWin ├── Help ├── Interpreter ├── RegsWin ├── ibar └── main └── s ├── Brkpts ├── Constants ├── ExecMod ├── Handler └── Misc /!UCDebug/!Run,feb: -------------------------------------------------------------------------------- 1 | 2 | WimpSlot -min 64M -max 64M 3 | Run .!RunImage -------------------------------------------------------------------------------- /!UCDebug/!RunImage,e1f: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuentesp/UCDebug/78c89c71bd80b7ebdeedc49f854bc3bf8a255c96/!UCDebug/!RunImage,e1f -------------------------------------------------------------------------------- /!UCDebug/!Sprites: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuentesp/UCDebug/78c89c71bd80b7ebdeedc49f854bc3bf8a255c96/!UCDebug/!Sprites -------------------------------------------------------------------------------- /!UCDebug/!Sprites22: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuentesp/UCDebug/78c89c71bd80b7ebdeedc49f854bc3bf8a255c96/!UCDebug/!Sprites22 -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | # !UCDebug, ARM debugger for RISC OS. 2 | [https://github.com/fuentesp/UCDebug](https://github.com/fuentesp/UCDebug) 3 | Copyright (C) 2018 University of Cantabria 4 | 5 | This debugger has been developed by the **Computer Architecture and 6 | Technology Group** - *Grupo de Arquitectura y Tecnología de 7 | Computadores (ATC)*, at the [University of Cantabria](https://web.unican.es/en). 8 | 9 | ###### Main Developers: 10 | 11 | - Cristóbal Camarero Coterillo 12 | - Fernando Vallejo Alonso 13 | - David Herreros Cerro 14 | - Pablo Fuentes Sáez 15 | 16 | ###### Contributors: 17 | 18 | - Carmen Martínez Fernández, head of the project that has led to the 19 | development of this debugger. 20 | - Jesús Gutiérrez Preciado, Elena Zaira Suárez Santamaría and 21 | Adrián Barredo Ferreira, prior work with RISC OS and the Raspberry Pi. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # !UCDebug, ARM debugger for RISC OS. 2 | # https://github.com/fuentesp/UCDebug 3 | # Copyright (C) 2018 University of Cantabria 4 | # 5 | # !UCDebug was developed by the Computer Architecture and Technology 6 | # Group at the University of Cantabria. A comprehensive list of authors 7 | # can be found in the file AUTHORS.txt. 8 | # 9 | # You can reach the main developers at {fernando.vallejo, cristobal.camarero, 10 | # pablo.fuentes}@unican.es. 11 | # 12 | # This program is free software: you can redistribute it and/or modify 13 | # it under the terms of the GNU General Public License as published by 14 | # the Free Software Foundation, either version 3 of the License, or 15 | # (at your option) any later version. 16 | # 17 | # This program is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program. If not, see . 24 | 25 | .PHONY: all clean 26 | 27 | all: !UCDebug/!RunImage 28 | 29 | FLAGS=-O2 30 | 31 | HEADERS=CodeWin.h ConsWin.h DataWin.h FPRegsWin.h ibar.h Interpreter.h main.h RegsWin.h 32 | MSG_HEADERS=Help.h 33 | HEADERSS=Constants.s 34 | 35 | ib.o: ibar.c $(HEADERS) 36 | gcc $(FLAGS) -mfpu=vfp -c -IOSLib: -o ib.o ibar.c 37 | 38 | CWin.o: CodeWin.c $(HEADERS) 39 | gcc $(FLAGS) -mfpu=vfp -c -IOSLib: -o CWin.o CodeWin.c 40 | 41 | DWin.o: DataWin.c $(HEADERS) 42 | gcc $(FLAGS) -mfpu=vfp -c -IOSLib: -o DWin.o DataWin.c 43 | 44 | RWin.o: RegsWin.c $(HEADERS) 45 | gcc $(FLAGS) -mfpu=vfp -c -IOSLib: -o RWin.o RegsWin.c 46 | 47 | FPWin.o: FPRegsWin.c $(HEADERS) 48 | gcc $(FLAGS) -mfpu=vfp -c -IOSLib: -o FPWin.o FPRegsWin.c 49 | 50 | CoWin.o: ConsWin.c $(HEADERS) 51 | gcc $(FLAGS) -mfpu=vfp -c -IOSLib: -o CoWin.o ConsWin.c 52 | 53 | In.o: Interpreter.c $(HEADERS) $(MSG_HEADERS) 54 | gcc $(FLAGS) -mfpu=vfp -c -IOSLib: -o In.o Interpreter.c 55 | 56 | Dbg.o: Debug.c $(HEADERS) 57 | gcc $(FLAGS) -mfpu=vfp -c -IOSLib: -o Dbg.o Debug.c 58 | 59 | Exec.o: ExecMod.s $(HEADERSS) 60 | as -mfpu=vfpv2 -o Exec.o ExecMod.s 61 | 62 | Brkp.o: Brkpts.s $(HEADERSS) 63 | as -mfpu=vfpv2 -o Brkp.o Brkpts.s 64 | 65 | Hand.o: Handler.s $(HEADERSS) 66 | as -mfpu=vfpv2 -o Hand.o Handler.s 67 | 68 | Misc.o: Misc.s $(HEADERSS) 69 | as -mfpu=vfpv2 -o Misc.o Misc.s 70 | 71 | !UCDebug/!RunImage: ib.o CWin.o DWin.o RWin.o FPWin.o CoWin.o In.o Dbg.o Exec.o Brkp.o Hand.o Misc.o 72 | gcc -Wl,--no-warn-mismatch -mfpu=vfp -LOSLib: -lOSLib32 -o !UCDebug/!RunImage Dbg.o ib.o CoWin.o CWin.o DWin.o RWin.o FPWin.o In.o Exec.o Brkp.o Hand.o Misc.o 73 | 74 | clean: 75 | remove !UCDebug.!RunImage 76 | remove o.Exec 77 | remove o.Brkp 78 | remove o.Hand 79 | remove o.Misc 80 | remove o.Dbg 81 | remove o.In 82 | remove o.CoWin 83 | remove o.FPWin 84 | remove o.RWin 85 | remove o.DWin 86 | remove o.CWin 87 | remove o.ib 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # !UCDebug, ARM debugger for RISC OS. 2 | Copyright (C) 2018 University of Cantabria. 3 | 4 | **!UCDebug** is an ARM debugger with a window-based interface that allows to run codes in a 5 | controlled manner, displaying the behavior and changes in the register set and memory. A 6 | simple list of commands (and their syntax) can be found by typying `help` at the 7 | Console window of the debugger. 8 | 9 | **!UCDebug** runs in a Raspberry Pi 1B+ under version 5.24 of RISC OS (released on 10 | 16-April-2018). A working copy of the application is provided for ease of use. In order 11 | to compile, you need to run the "compile" Obey file. **!UCDebug** has been compiled with GCC4 12 | and requires OSLib and C shared libraries in order to recompile (all available in the 13 | !Packman package manager). Depending on the medium employed to copy the files to the 14 | Raspberry Pi, it may be necessary to set the file type for certain files (!Run as 'Obey', 15 | !RunImage as 'ELF', !Sprites and !Sprites22 as 'Sprite'). 16 | 17 | **!UCDebug** works with ELF-format executables, and ***needs*** them to be linked to address 0x18000. 18 | To obtain a !UCDebug-compatible executable from an assembly code, run the following lines: 19 | ``` 20 | as -o file.o file.s 21 | ld -Ttext=18088 exec file.o 22 | ``` 23 | **!UCDebug** supports the use of VFPv2 floating-point instructions. To assemble an ARM source 24 | code that uses these instructions, the `[-mfpu=vfpv2]` option needs to be used with the `as` 25 | command. 26 | 27 | -------------------------------------------------------------------------------- /Tests/Makefile: -------------------------------------------------------------------------------- 1 | # !UCDebug, ARM debugger for RISC OS. 2 | # https://github.com/fuentesp/UCDebug 3 | # Copyright (C) 2018 University of Cantabria 4 | # 5 | # !UCDebug was developed by the Computer Architecture and Technology 6 | # Group at the University of Cantabria. A comprehensive list of authors 7 | # can be found in the file AUTHORS.txt. 8 | # 9 | # You can reach the main developers at {fernando.vallejo, cristobal.camarero, 10 | # pablo.fuentes}@unican.es. 11 | # 12 | # This program is free software: you can redistribute it and/or modify 13 | # it under the terms of the GNU General Public License as published by 14 | # the Free Software Foundation, either version 3 of the License, or 15 | # (at your option) any later version. 16 | # 17 | # This program is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program. If not, see . 24 | 25 | all: s001 s101 s201 s301 s302 s401 s501 s601 s701 s801 s802 s803 mo001 mo002 mo101 mo102 mo201 mo202 mo301 mo302 mo401 mo402 r101 r102 r200 r201 r202 r203 r204 r205 r206 r301 r302 26 | 27 | CC = ld -Ttext=18088 28 | 29 | $(*:=.o): %.o 30 | $(CC) -o $(@) $(@.o) 31 | 32 | #SWI tests 33 | s001.o: SWI.001_exit_def/s 34 | as -o s001.o SWI.001_exit_def/s 35 | s101.o: SWI.101_writec/s 36 | as -o s101.o SWI.101_writec/s 37 | s201.o: SWI.201_write0/s 38 | as -o s201.o SWI.201_write0/s 39 | s301.o: SWI.301_readc/s 40 | as -o s301.o SWI.301_readc/s 41 | s302.o: SWI.302_readc_nonblock/s 42 | as -o s302.o SWI.302_readc_nonblock/s 43 | s401.o: SWI.401_enteros/s 44 | as -o s401.o SWI.401_enteros/s 45 | s501.o: SWI.501_leaveos/s 46 | as -o s501.o SWI.501_leaveos/s 47 | s601.o: SWI.601_convert_int/s 48 | as -o s601.o SWI.601_convert_int/s 49 | s701.o: SWI.701_hardware/s 50 | as -o s701.o SWI.701_hardware/s 51 | s801.o: SWI.801_claim_release/s 52 | as -o s801.o SWI.801_claim_release/s 53 | s802.o: SWI.802_claim_without_release/s 54 | as -o s802.o SWI.802_claim_without_release/s 55 | s803.o: SWI.803_release_without_claim/s 56 | as -o s803.o SWI.803_release_without_claim/s 57 | 58 | #Mode tests 59 | mo001.o: Modes.Enter.abt/s 60 | as -o mo001.o Modes.Enter.abt/s 61 | mo002.o: Modes.Leave.abt/s 62 | as -o mo002.o Modes.Leave.abt/s 63 | mo101.o: Modes.Enter.fiq/s 64 | as -o mo101.o Modes.Enter.fiq/s 65 | mo102.o: Modes.Leave.fiq/s 66 | as -o mo102.o Modes.Leave.fiq/s 67 | mo201.o: Modes.Enter.irq/s 68 | as -o mo201.o Modes.Enter.irq/s 69 | mo202.o: Modes.Leave.irq/s 70 | as -o mo202.o Modes.Leave.irq/s 71 | mo301.o: Modes.Enter.sys/s 72 | as -o mo301.o Modes.Enter.sys/s 73 | mo302.o: Modes.Leave.sys/s 74 | as -o mo302.o Modes.Leave.sys/s 75 | mo401.o: Modes.Enter.und/s 76 | as -o mo401.o Modes.Enter.und/s 77 | mo402.o: Modes.Leave.und/s 78 | as -o mo402.o Modes.Leave.und/s 79 | 80 | #Reset tests 81 | r101.o: Reset.CPSR_Reset.modify_cpsr/s 82 | as -o r101.o Reset.CPSR_Reset.modify_cpsr/s 83 | r102.o: Reset.CPSR_Reset.check_cpsr/s 84 | as -o r102.o Reset.CPSR_Reset.check_cpsr/s 85 | r200.o: Reset.Mode_Reset.check_mode/s 86 | as -o r200.o Reset.Mode_Reset.check_mode/s 87 | r201.o: Reset.Mode_Reset.sys/s 88 | as -o r201.o Reset.Mode_Reset.sys/s 89 | r202.o: Reset.Mode_Reset.abt/s 90 | as -o r202.o Reset.Mode_Reset.abt/s 91 | r203.o: Reset.Mode_Reset.svc/s 92 | as -o r203.o Reset.Mode_Reset.svc/s 93 | r204.o: Reset.Mode_Reset.und/s 94 | as -o r204.o Reset.Mode_Reset.und/s 95 | r205.o: Reset.Mode_Reset.irq/s 96 | as -o r205.o Reset.Mode_Reset.irq/s 97 | r206.o: Reset.Mode_Reset.fiq/s 98 | as -o r206.o Reset.Mode_Reset.fiq/s 99 | r301.o: Reset.Stack_Reset.modify_stacks/s 100 | as -o r301.o Reset.Stack_Reset.modify_stacks/s 101 | r302.o: Reset.Stack_Reset.check_stacks/s 102 | as -o r302.o Reset.Stack_Reset.check_stacks/s 103 | 104 | clean: 105 | wipe s* 106 | wipe mo* 107 | wipe r* 108 | -------------------------------------------------------------------------------- /Tests/Modes/Enter/abt.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of entering abort mode 2 | 3 | @ The program saves the value of SP, LR and CPSR in the var Context (in the last three words). 4 | @ After that, it overwrites the values of register R0 through R12 with the first thirteen words of the var Context. 5 | @ Then it uses the SWI 0x16 to enter Supervisor mode. 6 | @ Once you are in supervisor mode check register R0-12 maintain their values, registers SP, LR and CPSR have different values that the ones stored in the var Context, and that SPSR is equal to the stored CPSR. 7 | @ If there was an error it will notify the user with a message indicating the first register in which it detected the first error. 8 | @ If there was no error it should end with no message at the end. 9 | 10 | .data 11 | .align 2 12 | Context: .word 0x11111110, 0x22222221, 0xF5823992, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0, 0, 0 13 | Context2: .word 0xFFFF0000, 0x11221122, 0x12345678, 0xa, 0xb, 0xc, 0xd, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0, 0, 0 14 | Error_Msg: .asciz "There has been an error on the reg: " 15 | Success_Msg: .asciz "Test ended successfully\n" 16 | 17 | Error_Reg: .ascii "Rg00 Rg01 Rg02 Rg03 Rg04 Rg05 Rg06 Rg07 Rg08 Rg09 Rg10 Rg11 Rg12 RgSP RgLR CPSR SPSR" 18 | 19 | 20 | .text 21 | .globl _start 22 | _start: 23 | @ Enter OS Mode 24 | swi 0x16 25 | 26 | @ Store in Context var current values of SP, LR, and CPSR 27 | ldr r0, =Context+52 @ Address of the 3 last words of Context 28 | stmia r0!, {sp, lr} 29 | mrs r1, cpsr 30 | str r1, [r0] 31 | @ Bring values from Context (regs 0 - 12) to supervisor mode registers 32 | ldr r0, =Context 33 | ldm r0, {r0-r12} 34 | 35 | 36 | 37 | @ Enter ABT Mode 38 | mrs r0,CPSR 39 | bic r0,r0,#0x1F 40 | orr r0,r0,#0x17 41 | msr CPSR,r0 @ We must use a reg for changing mode 42 | 43 | @ Check the values of registers 1 - r10 44 | stmdb sp!, {r11-r12} @ Store the value of R11 and R12 for preservation (we need 2 free registers to check the values) 45 | ldr r11, =Context 46 | ldr r12, [r11, #4] @ Bring r1 from Context 47 | add r11, r11, #8 @ Advance pointer to r2 48 | cmp r1, r12 49 | movne r0, #1 50 | bne Error 51 | ldr r12, [r11], #4 @ Bring r2 from Context, and advance pointer to r3 52 | cmp r2, r12 53 | movne r0, #2 54 | bne Error 55 | ldr r12, [r11], #4 @ Bring r3 from Context, and advance pointer to r4 56 | cmp r3, r12 57 | movne r0, #3 58 | bne Error 59 | ldr r12, [r11], #4 @ Bring r4 from Context, and advance pointer to r5 60 | cmp r4, r12 61 | movne r0, #4 62 | bne Error 63 | ldr r12, [r11], #4 @ Bring r5 from Context, and advance pointer to r6 64 | cmp r5, r12 65 | movne r0, #5 66 | bne Error 67 | ldr r12, [r11], #4 @ Bring r6 from Context, and advance pointer to r7 68 | cmp r6, r12 69 | movne r0, #6 70 | bne Error 71 | ldr r12, [r11], #4 @ Bring r7 from Context, and advance pointer to r8 72 | cmp r7, r12 73 | movne r0, #7 74 | bne Error 75 | ldr r12, [r11], #4 @ Bring r8 from Context, and advance pointer to r9 76 | cmp r8, r12 77 | movne r0, #8 78 | bne Error 79 | ldr r12, [r11], #4 @ Bring r9 from Context, and advance pointer to r10 80 | cmp r9, r12 81 | movne r0, #9 82 | bne Error 83 | ldr r12, [r11], #4 @ Bring r10 from Context, and advance pointer to r11 84 | cmp r10, r12 85 | movne r0, #10 86 | bne Error 87 | 88 | @ Check the values of registers r11 - r12 89 | mov r0, r11 90 | ldr r1, [r0], #4 @ Bring r11 from Context, and advance pointer to r12 91 | ldmia sp!, {r11-r12} @ We recover from the stack the stored values of R11 and R12 92 | cmp r11, r1 93 | movne r0, #11 94 | bne Error 95 | ldr r1, [r0], #4 @ Bring r12 from Context, and advance pointer to sp 96 | cmp r12, r1 97 | movne r0, #12 98 | bne Error 99 | 100 | @ Check the values of sp & lr, they need to be different 101 | ldr r1, [r0], #4 @ Bring SP from Context, and advance pointer to LR 102 | cmp r1, sp 103 | moveq r0, #13 104 | beq Error 105 | ldr r1, [r0], #4 @ Bring LR from Context, and advance pointer to CPSR 106 | cmp r1, lr 107 | moveq r0, #14 108 | beq Error 109 | @ Check the values of SPSR & CPSR 110 | ldr r1, [r0] @ Bring CPSR from Context 111 | @ Check the value of the CPSR is different to the one saved in Context 112 | mrs r2, cpsr 113 | cmp r1, r2 114 | moveq r0, #15 115 | beq Error 116 | @ Check the SPSR is equal to the old value of the CPSR 117 | mrs r2, spsr 118 | cmp r1, r2 119 | movne r0, #16 120 | 121 | @ Exit ABT Mode and enter Supervisor mode 122 | mrs r0,CPSR 123 | bic r0,r0,#0x1F 124 | orr r0,r0,#0x13 125 | msr CPSR,r0 126 | 127 | @ Bring value of R0 from Context 128 | ldr r0, =Context 129 | ldr r0, [r0] 130 | 131 | @ Re-enter ABT Mode for checking r0 132 | mrs r1,CPSR 133 | bic r1,r1,#0x1F 134 | orr r1,r1,#0x17 135 | msr CPSR,r1 136 | 137 | ldr r1, =Context 138 | ldr r1, [r1] @ Bring r0 from Context 139 | cmp r0, r1 140 | movne r0, #0 141 | bne Error 142 | 143 | NoError: 144 | @Print the success message 145 | ldr r0, =Success_Msg 146 | swi 0x2 @OS_Write0 147 | swi 0x11 148 | 149 | @Print the error and exit the program 150 | Error: 151 | mov r1, #5 152 | mul r4, r0, r1 153 | ldr r1, =Error_Reg @ Load the string with the names of the registers 154 | add r4, r4, r1 @ Get the position of the reg name 155 | @ Print the error message 156 | ldr r0, =Error_Msg 157 | swi 0x2 @OS_Write0 158 | @ Print the name of the register that failed the check 159 | ldrb r0, [r4] 160 | swi 0x00 @OS_WriteC 161 | add r4, r4, #1 162 | ldrb r0, [r4] 163 | swi 0x00 164 | add r4, r4, #1 165 | ldrb r0, [r4] 166 | swi 0x00 167 | add r4, r4, #1 168 | ldrb r0, [r4] 169 | swi 0x00 170 | swi 0x11 171 | -------------------------------------------------------------------------------- /Tests/Modes/Enter/fiq.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of entering fast interrupt mode 2 | 3 | @ The program saves the value of SP, LR and CPSR in the var Context (in the last three words). 4 | @ After that, it overwrites the values of register R0 through R12 with the first thirteen words of the var Context. 5 | @ Then it uses the SWI 0x16 to enter Supervisor mode. 6 | @ Once you are in supervisor mode check register R0-7 maintain their values, register R8-12, registers SP, LR and CPSR have different values that the ones stored in the var Context, and that SPSR is equal to the stored CPSR. 7 | @ If there was an error it will notify the user with a message indicating the first register in which it detected the first error. 8 | @ If there was no error it should end with no message at the end. 9 | 10 | .data 11 | .align 2 12 | Context: .word 0x11111110, 0x22222221, 0xF5823992, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0, 0, 0 13 | Error_Msg: .asciz "There has been an error on the reg: " 14 | Success_Msg: .asciz "Test ended successfully\n" 15 | 16 | Error_Reg: .ascii "Rg00 Rg01 Rg02 Rg03 Rg04 Rg05 Rg06 Rg07 Rg08 Rg09 Rg10 Rg11 Rg12 RgSP RgLR CPSR SPSR" 17 | 18 | 19 | .text 20 | .globl _start 21 | _start: 22 | @ Enter OS Mode 23 | swi 0x16 24 | 25 | @ Store in Context var current values of SP, LR, and CPSR 26 | ldr r0, =Context+52 @ Address of the 3 last words of Context 27 | stmia r0!, {sp, lr} 28 | mrs r1, cpsr 29 | str r1, [r0] 30 | @ Bring values from Context (regs 0 - 12) to supervisor mode registers 31 | ldr r0, =Context 32 | ldm r0, {r0-r12} 33 | 34 | 35 | 36 | @ Enter FIQ Mode 37 | mrs r0,CPSR 38 | bic r0,r0,#0x1F 39 | orr r0,r0,#0x11 40 | msr CPSR,r0 @ We must use a reg for changing mode 41 | 42 | @ Check the values of registers 1 - r10 43 | stmdb sp!, {r11-r12} @ Store the value of R11 and R12 for preservation (we need 2 free registers to check the values) 44 | ldr r11, =Context 45 | ldr r12, [r11, #4] @ Bring r1 from Context 46 | add r11, r11, #8 @ Advance pointer to r2 47 | cmp r1, r12 48 | movne r0, #1 49 | bne Error 50 | ldr r12, [r11], #4 @ Bring r2 from Context, and advance pointer to r3 51 | cmp r2, r12 52 | movne r0, #2 53 | bne Error 54 | ldr r12, [r11], #4 @ Bring r3 from Context, and advance pointer to r4 55 | cmp r3, r12 56 | movne r0, #3 57 | bne Error 58 | ldr r12, [r11], #4 @ Bring r4 from Context, and advance pointer to r5 59 | cmp r4, r12 60 | movne r0, #4 61 | bne Error 62 | ldr r12, [r11], #4 @ Bring r5 from Context, and advance pointer to r6 63 | cmp r5, r12 64 | movne r0, #5 65 | bne Error 66 | ldr r12, [r11], #4 @ Bring r6 from Context, and advance pointer to r7 67 | cmp r6, r12 68 | movne r0, #6 69 | bne Error 70 | ldr r12, [r11], #4 @ Bring r7 from Context, and advance pointer to r8 71 | cmp r7, r12 72 | movne r0, #7 73 | bne Error 74 | ldr r12, [r11], #4 @ Bring r8 from Context, and advance pointer to r9 75 | cmp r8, r12 76 | moveq r0, #8 77 | beq Error 78 | ldr r12, [r11], #4 @ Bring r9 from Context, and advance pointer to r10 79 | cmp r9, r12 80 | moveq r0, #9 81 | beq Error 82 | ldr r12, [r11], #4 @ Bring r10 from Context, and advance pointer to r11 83 | cmp r10, r12 84 | moveq r0, #10 85 | beq Error 86 | 87 | @ Check the values of registers r11 - r12 88 | mov r0, r11 89 | ldr r1, [r0], #4 @ Bring r11 from Context, and advance pointer to r12 90 | ldmia sp!, {r11-r12} @ We recover from the stack the stored values of R11 and R12 91 | cmp r11, r1 92 | moveq r0, #11 93 | beq Error 94 | ldr r1, [r0], #4 @ Bring r12 from Context, and advance pointer to sp 95 | cmp r12, r1 96 | moveq r0, #12 97 | beq Error 98 | 99 | @ Check the values of sp & lr, they need to be different 100 | ldr r1, [r0], #4 @ Bring SP from Context, and advance pointer to LR 101 | cmp r1, sp 102 | moveq r0, #13 103 | beq Error 104 | ldr r1, [r0], #4 @ Bring LR from Context, and advance pointer to CPSR 105 | cmp r1, lr 106 | moveq r0, #14 107 | beq Error 108 | @ Check the values of SPSR & CPSR 109 | ldr r1, [r0] @ Bring CPSR from Context 110 | @ Check the value of the CPSR is different to the one saved in Context 111 | mrs r2, cpsr 112 | cmp r1, r2 113 | moveq r0, #15 114 | beq Error 115 | @ Check the SPSR is equal to the old value of the CPSR 116 | mrs r2, spsr 117 | cmp r1, r2 118 | movne r0, #16 119 | 120 | @ Exit FIQ Mode ad enter Supervisor mode 121 | mrs r0,CPSR 122 | bic r0,r0,#0x1F 123 | orr r0,r0,#0x13 124 | msr CPSR,r0 125 | 126 | @ Bring value of R0 from Context 127 | ldr r0, =Context 128 | ldr r0, [r0] 129 | 130 | @ Re-enter FIQ Mode for checking r0 131 | mrs r1,CPSR 132 | bic r1,r1,#0x1F 133 | orr r1,r1,#0x11 134 | msr CPSR,r1 135 | 136 | ldr r1, =Context 137 | ldr r1, [r1] @ Bring r0 from Context 138 | cmp r0, r1 139 | movne r0, #0 140 | bne Error 141 | NoError: 142 | @Print the success message 143 | ldr r0, =Success_Msg 144 | swi 0x2 @OS_Write0 145 | swi 0x11 146 | 147 | @Print the error and exit the program 148 | Error: 149 | mov r1, #5 150 | mul r4, r0, r1 151 | ldr r1, =Error_Reg @ Load the string with the names of the registers 152 | add r4, r4, r1 @ Get the position of the reg name 153 | @ Print the error message 154 | ldr r0, =Error_Msg 155 | swi 0x2 @OS_Write0 156 | @ Print the name of the register that failed the check 157 | ldrb r0, [r4] 158 | swi 0x00 @OS_WriteC 159 | add r4, r4, #1 160 | ldrb r0, [r4] 161 | swi 0x00 162 | add r4, r4, #1 163 | ldrb r0, [r4] 164 | swi 0x00 165 | add r4, r4, #1 166 | ldrb r0, [r4] 167 | swi 0x00 168 | swi 0x11 169 | -------------------------------------------------------------------------------- /Tests/Modes/Enter/irq.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of entering interrupt mode 2 | 3 | @ The program saves the value of SP, LR and CPSR in the var Context (in the last three words). 4 | @ After that, it overwrites the values of register R0 through R12 with the first thirteen words of the var Context. 5 | @ Then it uses the SWI 0x16 to enter Supervisor mode. 6 | @ Once you are in supervisor mode check register R0-12 maintain their values, registers SP, LR and CPSR have different values that the ones stored in the var Context, and that SPSR is equal to the stored CPSR. 7 | @ If there was an error it will notify the user with a message indicating the first register in which it detected the first error. 8 | @ If there was no error it should end with no message at the end. 9 | 10 | .data 11 | .align 2 12 | Context: .word 0x11111110, 0x22222221, 0xF5823992, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0, 0, 0 13 | Error_Msg: .asciz "There has been an error on the reg: " 14 | Success_Msg: .asciz "Test ended successfully\n" 15 | 16 | Error_Reg: .ascii "Rg00 Rg01 Rg02 Rg03 Rg04 Rg05 Rg06 Rg07 Rg08 Rg09 Rg10 Rg11 Rg12 RgSP RgLR CPSR SPSR" 17 | 18 | 19 | .text 20 | .globl _start 21 | _start: 22 | @ Enter OS Mode 23 | swi 0x16 24 | 25 | @ Store in Context var current values of SP, LR, and CPSR 26 | ldr r0, =Context+52 @ Address of the 3 last words of Context 27 | stmia r0!, {sp, lr} 28 | mrs r1, cpsr 29 | str r1, [r0] 30 | @ Bring values from Context (regs 0 - 12) to supervisor mode registers 31 | ldr r0, =Context 32 | ldm r0, {r0-r12} 33 | 34 | 35 | 36 | @ Enter IRQ Mode 37 | mrs r0,CPSR 38 | bic r0,r0,#0x1F 39 | orr r0,r0,#0x12 40 | msr CPSR,r0 @ We must use a reg for changing mode 41 | 42 | @ Check the values of registers 1 - r10 43 | stmdb sp!, {r11-r12} @ Store the value of R11 and R12 for preservation (we need 2 free registers to check the values) 44 | ldr r11, =Context 45 | ldr r12, [r11, #4] @ Bring r1 from Context 46 | add r11, r11, #8 @ Advance pointer to r2 47 | cmp r1, r12 48 | movne r0, #1 49 | bne Error 50 | ldr r12, [r11], #4 @ Bring r2 from Context, and advance pointer to r3 51 | cmp r2, r12 52 | movne r0, #2 53 | bne Error 54 | ldr r12, [r11], #4 @ Bring r3 from Context, and advance pointer to r4 55 | cmp r3, r12 56 | movne r0, #3 57 | bne Error 58 | ldr r12, [r11], #4 @ Bring r4 from Context, and advance pointer to r5 59 | cmp r4, r12 60 | movne r0, #4 61 | bne Error 62 | ldr r12, [r11], #4 @ Bring r5 from Context, and advance pointer to r6 63 | cmp r5, r12 64 | movne r0, #5 65 | bne Error 66 | ldr r12, [r11], #4 @ Bring r6 from Context, and advance pointer to r7 67 | cmp r6, r12 68 | movne r0, #6 69 | bne Error 70 | ldr r12, [r11], #4 @ Bring r7 from Context, and advance pointer to r8 71 | cmp r7, r12 72 | movne r0, #7 73 | bne Error 74 | ldr r12, [r11], #4 @ Bring r8 from Context, and advance pointer to r9 75 | cmp r8, r12 76 | movne r0, #8 77 | bne Error 78 | ldr r12, [r11], #4 @ Bring r9 from Context, and advance pointer to r10 79 | cmp r9, r12 80 | movne r0, #9 81 | bne Error 82 | ldr r12, [r11], #4 @ Bring r10 from Context, and advance pointer to r11 83 | cmp r10, r12 84 | movne r0, #10 85 | bne Error 86 | 87 | @ Check the values of registers r11 - r12 88 | mov r0, r11 89 | ldr r1, [r0], #4 @ Bring r11 from Context, and advance pointer to r12 90 | ldmia sp!, {r11-r12} @ We recover from the stack the stored values of R11 and R12 91 | cmp r11, r1 92 | movne r0, #11 93 | bne Error 94 | ldr r1, [r0], #4 @ Bring r12 from Context, and advance pointer to sp 95 | cmp r12, r1 96 | movne r0, #12 97 | bne Error 98 | 99 | @ Check the values of sp & lr, they need to be different 100 | ldr r1, [r0], #4 @ Bring SP from Context, and advance pointer to LR 101 | cmp r1, sp 102 | moveq r0, #13 103 | beq Error 104 | ldr r1, [r0], #4 @ Bring LR from Context, and advance pointer to CPSR 105 | cmp r1, lr 106 | moveq r0, #14 107 | beq Error 108 | @ Check the values of SPSR & CPSR 109 | ldr r1, [r0] @ Bring CPSR from Context 110 | @ Check the value of the CPSR is different to the one saved in Context 111 | mrs r2, cpsr 112 | cmp r1, r2 113 | moveq r0, #15 114 | beq Error 115 | @ Check the SPSR is equal to the old value of the CPSR 116 | mrs r2, spsr 117 | cmp r1, r2 118 | movne r0, #16 119 | 120 | @ Exit IRQ Mode ad enter Supervisor mode 121 | mrs r0,CPSR 122 | bic r0,r0,#0x1F 123 | orr r0,r0,#0x13 124 | msr CPSR,r0 125 | 126 | @ Bring value of R0 from Context 127 | ldr r0, =Context 128 | ldr r0, [r0] 129 | 130 | @ Re-enter IRQ Mode for checking r0 131 | mrs r1,CPSR 132 | bic r1,r1,#0x1F 133 | orr r1,r1,#0x12 134 | msr CPSR,r1 135 | 136 | ldr r1, =Context 137 | ldr r1, [r1] @ Bring r0 from Context 138 | cmp r0, r1 139 | movne r0, #0 140 | bne Error 141 | NoError: 142 | @Print the success message 143 | ldr r0, =Success_Msg 144 | swi 0x2 @OS_Write0 145 | swi 0x11 146 | 147 | @Print the error and exit the program 148 | Error: 149 | mov r1, #5 150 | mul r4, r0, r1 151 | ldr r1, =Error_Reg @ Load the string with the names of the registers 152 | add r4, r4, r1 @ Get the position of the reg name 153 | @ Print the error message 154 | ldr r0, =Error_Msg 155 | swi 0x2 @OS_Write0 156 | @ Print the name of the register that failed the check 157 | ldrb r0, [r4] 158 | swi 0x00 @OS_WriteC 159 | add r4, r4, #1 160 | ldrb r0, [r4] 161 | swi 0x00 162 | add r4, r4, #1 163 | ldrb r0, [r4] 164 | swi 0x00 165 | add r4, r4, #1 166 | ldrb r0, [r4] 167 | swi 0x00 168 | swi 0x11 169 | -------------------------------------------------------------------------------- /Tests/Modes/Enter/sys.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of entering system mode 2 | 3 | @ The program saves the value of SP, LR and CPSR in the var Context (in the last three words). 4 | @ After that, it overwrites the values of register R0 through R12 with the first thirteen words of the var Context. 5 | @ Then it uses the SWI 0x16 to enter Supervisor mode. 6 | @ Once you are in supervisor mode check register R0-12 maintain their values, registers SP, LR and CPSR have different values that the ones stored in the var Context, and that SPSR is equal to the stored CPSR. 7 | @ If there was an error it will notify the user with a message indicating the first register in which it detected the first error. 8 | @ If there was no error it should end with no message at the end. 9 | 10 | .data 11 | .align 2 12 | Context: .word 0x11111110, 0x22222221, 0xF5823992, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0, 0, 0 13 | Error_Msg: .asciz "There has been an error on the reg: " 14 | Success_Msg: .asciz "Test ended successfully\n" 15 | 16 | Error_Reg: .ascii "Rg00 Rg01 Rg02 Rg03 Rg04 Rg05 Rg06 Rg07 Rg08 Rg09 Rg10 Rg11 Rg12 RgSP RgLR CPSR" 17 | 18 | 19 | .text 20 | .globl _start 21 | _start: 22 | @ Enter OS Mode 23 | swi 0x16 24 | 25 | @ Store in Context var current values of SP, LR, and CPSR 26 | ldr r0, =Context+52 @ Address of the 3 last words of Context 27 | stmia r0!, {sp, lr} 28 | mrs r1, cpsr 29 | str r1, [r0] 30 | @ Bring values from Context (regs 0 - 12) to supervisor mode registers 31 | ldr r0, =Context 32 | ldm r0, {r0-r12} 33 | 34 | 35 | 36 | @ Enter SYS Mode 37 | mrs r0,CPSR 38 | and r0,r0,#0x1F 39 | orr r0,r0,#0x17 40 | msr CPSR,r0 @ We must use a reg for changing mode 41 | 42 | @ Check the values of registers 1 - r10 43 | stmdb sp!, {r11-r12} @ Store the value of R11 and R12 for preservation (we need 2 free registers to check the values) 44 | ldr r11, =Context 45 | ldr r12, [r11, #4] @ Bring r1 from Context 46 | add r11, r11, #8 @ Advance pointer to r2 47 | cmp r1, r12 48 | movne r0, #1 49 | bne Error 50 | ldr r12, [r11], #4 @ Bring r2 from Context, and advance pointer to r3 51 | cmp r2, r12 52 | movne r0, #2 53 | bne Error 54 | ldr r12, [r11], #4 @ Bring r3 from Context, and advance pointer to r4 55 | cmp r3, r12 56 | movne r0, #3 57 | bne Error 58 | ldr r12, [r11], #4 @ Bring r4 from Context, and advance pointer to r5 59 | cmp r4, r12 60 | movne r0, #4 61 | bne Error 62 | ldr r12, [r11], #4 @ Bring r5 from Context, and advance pointer to r6 63 | cmp r5, r12 64 | movne r0, #5 65 | bne Error 66 | ldr r12, [r11], #4 @ Bring r6 from Context, and advance pointer to r7 67 | cmp r6, r12 68 | movne r0, #6 69 | bne Error 70 | ldr r12, [r11], #4 @ Bring r7 from Context, and advance pointer to r8 71 | cmp r7, r12 72 | movne r0, #7 73 | bne Error 74 | ldr r12, [r11], #4 @ Bring r8 from Context, and advance pointer to r9 75 | cmp r8, r12 76 | movne r0, #8 77 | bne Error 78 | ldr r12, [r11], #4 @ Bring r9 from Context, and advance pointer to r10 79 | cmp r9, r12 80 | movne r0, #9 81 | bne Error 82 | ldr r12, [r11], #4 @ Bring r10 from Context, and advance pointer to r11 83 | cmp r10, r12 84 | movne r0, #10 85 | bne Error 86 | 87 | @ Check the values of registers r11 - r12 88 | mov r0, r11 89 | ldr r1, [r0], #4 @ Bring r11 from Context, and advance pointer to r12 90 | ldmia sp!, {r11-r12} @ We recover from the stack the stored values of R11 and R12 91 | cmp r11, r1 92 | movne r0, #11 93 | bne Error 94 | ldr r1, [r0], #4 @ Bring r12 from Context, and advance pointer to sp 95 | cmp r12, r1 96 | movne r0, #12 97 | bne Error 98 | 99 | @ Check the values of sp & lr, they need to be different 100 | ldr r1, [r0], #4 @ Bring SP from Context, and advance pointer to LR 101 | cmp r1, sp 102 | moveq r0, #13 103 | beq Error 104 | ldr r1, [r0], #4 @ Bring LR from Context, and advance pointer to CPSR 105 | cmp r1, lr 106 | moveq r0, #14 107 | beq Error 108 | @ Check the value of CPSR 109 | ldr r1, [r0] @ Bring CPSR from Context 110 | @ Check the value of the CPSR is different to the one saved in Context 111 | mrs r2, cpsr 112 | cmp r1, r2 113 | moveq r0, #15 114 | beq Error 115 | 116 | @ Exit SYS Mode and enter Supervisor mode 117 | mrs r0,CPSR 118 | and r0,r0,#0x1F 119 | orr r0,r0,#0x13 120 | msr CPSR,r0 121 | 122 | @ Bring value of R0 from Context 123 | ldr r0, =Context 124 | ldr r0, [r0] 125 | 126 | @ Re-enter SYS Mode for checking r0 127 | mrs r1,CPSR 128 | and r1,r1,#0x1F 129 | orr r1,r1,#0x17 130 | msr CPSR,r1 131 | 132 | ldr r1, =Context 133 | ldr r1, [r1] @ Bring r0 from Context 134 | cmp r0, r1 135 | movne r0, #0 136 | bne Error 137 | 138 | bne Error 139 | NoError: 140 | @Print the success message 141 | ldr r0, =Success_Msg 142 | swi 0x2 @OS_Write0 143 | swi 0x11 144 | 145 | @Print the error and exit the program 146 | Error: 147 | mov r1, #5 148 | mul r4, r0, r1 149 | ldr r1, =Error_Reg @ Load the string with the names of the registers 150 | add r4, r4, r1 @ Get the position of the reg name 151 | @ Print the error message 152 | ldr r0, =Error_Msg 153 | swi 0x2 @OS_Write0 154 | @ Print the name of the register that failed the check 155 | ldrb r0, [r4] 156 | swi 0x00 @OS_WriteC 157 | add r4, r4, #1 158 | ldrb r0, [r4] 159 | swi 0x00 160 | add r4, r4, #1 161 | ldrb r0, [r4] 162 | swi 0x00 163 | add r4, r4, #1 164 | ldrb r0, [r4] 165 | swi 0x00 166 | swi 0x11 167 | -------------------------------------------------------------------------------- /Tests/Modes/Enter/und.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of entering undefined mode 2 | 3 | @ The program saves the value of SP, LR and CPSR in the var Context (in the last three words). 4 | @ After that, it overwrites the values of register R0 through R12 with the first thirteen words of the var Context. 5 | @ Then it uses the SWI 0x16 to enter Supervisor mode. 6 | @ Once you are in supervisor mode check register R0-12 maintain their values, registers SP, LR and CPSR have different values that the ones stored in the var Context, and that SPSR is equal to the stored CPSR. 7 | @ If there was an error it will notify the user with a message indicating the first register in which it detected the first error. 8 | @ If there was no error it should end with no message at the end. 9 | 10 | .data 11 | .align 2 12 | Context: .word 0x11111110, 0x22222221, 0xF5823992, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0, 0, 0 13 | Error_Msg: .asciz "There has been an error on the reg: " 14 | Success_Msg: .asciz "Test ended successfully\n" 15 | 16 | Error_Reg: .ascii "Rg00 Rg01 Rg02 Rg03 Rg04 Rg05 Rg06 Rg07 Rg08 Rg09 Rg10 Rg11 Rg12 RgSP RgLR CPSR SPSR" 17 | 18 | 19 | .text 20 | .globl _start 21 | _start: 22 | @ Enter OS Mode 23 | swi 0x16 24 | 25 | @ Store in Context var current values of SP, LR, and CPSR 26 | ldr r0, =Context+52 @ Address of the 3 last words of Context 27 | stmia r0!, {sp, lr} 28 | mrs r1, cpsr 29 | str r1, [r0] 30 | @ Bring values from Context (regs 0 - 12) to supervisor mode registers 31 | ldr r0, =Context 32 | ldm r0, {r0-r12} 33 | 34 | 35 | 36 | @ Enter UND Mode 37 | mrs r0,CPSR 38 | bic r0,r0,#0x1F 39 | orr r0,r0,#0x1B 40 | msr CPSR,r0 @ We must use a reg for changing mode 41 | 42 | @ Check the values of registers 1 - r10 43 | stmdb sp!, {r11-r12} @ Store the value of R11 and R12 for preservation (we need 2 free registers to check the values) 44 | ldr r11, =Context 45 | ldr r12, [r11, #4] @ Bring r1 from Context 46 | add r11, r11, #8 @ Advance pointer to r2 47 | cmp r1, r12 48 | movne r0, #1 49 | bne Error 50 | ldr r12, [r11], #4 @ Bring r2 from Context, and advance pointer to r3 51 | cmp r2, r12 52 | movne r0, #2 53 | bne Error 54 | ldr r12, [r11], #4 @ Bring r3 from Context, and advance pointer to r4 55 | cmp r3, r12 56 | movne r0, #3 57 | bne Error 58 | ldr r12, [r11], #4 @ Bring r4 from Context, and advance pointer to r5 59 | cmp r4, r12 60 | movne r0, #4 61 | bne Error 62 | ldr r12, [r11], #4 @ Bring r5 from Context, and advance pointer to r6 63 | cmp r5, r12 64 | movne r0, #5 65 | bne Error 66 | ldr r12, [r11], #4 @ Bring r6 from Context, and advance pointer to r7 67 | cmp r6, r12 68 | movne r0, #6 69 | bne Error 70 | ldr r12, [r11], #4 @ Bring r7 from Context, and advance pointer to r8 71 | cmp r7, r12 72 | movne r0, #7 73 | bne Error 74 | ldr r12, [r11], #4 @ Bring r8 from Context, and advance pointer to r9 75 | cmp r8, r12 76 | movne r0, #8 77 | bne Error 78 | ldr r12, [r11], #4 @ Bring r9 from Context, and advance pointer to r10 79 | cmp r9, r12 80 | movne r0, #9 81 | bne Error 82 | ldr r12, [r11], #4 @ Bring r10 from Context, and advance pointer to r11 83 | cmp r10, r12 84 | movne r0, #10 85 | bne Error 86 | 87 | @ Check the values of registers r11 - r12 88 | mov r0, r11 89 | ldr r1, [r0], #4 @ Bring r11 from Context, and advance pointer to r12 90 | ldmia sp!, {r11-r12} @ We recover from the stack the stored values of R11 and R12 91 | cmp r11, r1 92 | movne r0, #11 93 | bne Error 94 | ldr r1, [r0], #4 @ Bring r12 from Context, and advance pointer to sp 95 | cmp r12, r1 96 | movne r0, #12 97 | bne Error 98 | 99 | @ Check the values of sp & lr, they need to be different 100 | ldr r1, [r0], #4 @ Bring SP from Context, and advance pointer to LR 101 | cmp r1, sp 102 | moveq r0, #13 103 | beq Error 104 | ldr r1, [r0], #4 @ Bring LR from Context, and advance pointer to CPSR 105 | cmp r1, lr 106 | moveq r0, #14 107 | beq Error 108 | @ Check the values of SPSR & CPSR 109 | ldr r1, [r0] @ Bring CPSR from Context 110 | @ Check the value of the CPSR is different to the one saved in Context 111 | mrs r2, cpsr 112 | cmp r1, r2 113 | moveq r0, #15 114 | beq Error 115 | @ Check the SPSR is equal to the old value of the CPSR 116 | mrs r2, spsr 117 | cmp r1, r2 118 | movne r0, #16 119 | 120 | @ Exit UND Mode ad enter Supervisor mode 121 | mrs r0,CPSR 122 | bic r0,r0,#0x1F 123 | orr r0,r0,#0x13 124 | msr CPSR,r0 125 | 126 | @ Bring value of R0 from Context 127 | ldr r0, =Context 128 | ldr r0, [r0] 129 | 130 | @ Re-enter UND Mode for checking r0 131 | mrs r1,CPSR 132 | bic r1,r1,#0x1F 133 | orr r1,r1,#0x1B 134 | msr CPSR,r1 135 | 136 | ldr r1, =Context 137 | ldr r1, [r1] @ Bring r0 from Context 138 | cmp r0, r1 139 | movne r0, #0 140 | bne Error 141 | NoError: 142 | @Print the success message 143 | ldr r0, =Success_Msg 144 | swi 0x2 @OS_Write0 145 | swi 0x11 146 | 147 | @Print the error and exit the program 148 | Error: 149 | mov r1, #5 150 | mul r4, r0, r1 151 | ldr r1, =Error_Reg @ Load the string with the names of the registers 152 | add r4, r4, r1 @ Get the position of the reg name 153 | @ Print the error message 154 | ldr r0, =Error_Msg 155 | swi 0x2 @OS_Write0 156 | @ Print the name of the register that failed the check 157 | ldrb r0, [r4] 158 | swi 0x00 @OS_WriteC 159 | add r4, r4, #1 160 | ldrb r0, [r4] 161 | swi 0x00 162 | add r4, r4, #1 163 | ldrb r0, [r4] 164 | swi 0x00 165 | add r4, r4, #1 166 | ldrb r0, [r4] 167 | swi 0x00 168 | swi 0x11 169 | -------------------------------------------------------------------------------- /Tests/Modes/Leave/abt.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of leaving from abort mode 2 | 3 | @ The program saves the value of SP, LR and CPSR in the var Context (in the last three words). 4 | @ After that, it overwrites the values of register R0 through R12 with the first thirteen words of the var Context. 5 | @ Then it uses the SWI 0x16 to enter Supervisor mode. 6 | @ Once you are in supervisor mode check register R0-12 maintain their values, registers SP, LR and CPSR have different values that the ones stored in the var Context, and that SPSR is equal to the stored CPSR. 7 | @ If there was an error it will notify the user with a message indicating the first register in which it detected the first error. 8 | @ If there was no error it should end with no message at the end. 9 | 10 | .data 11 | .align 2 12 | Context: .word 0x11111110, 0x22222221, 0xF5823992, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0, 0, 0 13 | Context2: .word 0xFFFF0000, 0x11221122, 0x12345678, 0xa, 0xb, 0xc, 0xd, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0, 0, 0 14 | Error_Msg: .asciz "There has been an error on the reg: " 15 | Success_Msg: .asciz "Test ended successfully\n" 16 | 17 | Error_Reg: .ascii "Rg00 Rg01 Rg02 Rg03 Rg04 Rg05 Rg06 Rg07 Rg08 Rg09 Rg10 Rg11 Rg12 RgSP RgLR CPSR SPSR" 18 | 19 | 20 | .text 21 | .globl _start 22 | _start: 23 | @ Enter OS Mode 24 | swi 0x16 25 | 26 | @ Enter ABT Mode 27 | mrs r0,CPSR 28 | bic r0,r0,#0x1F 29 | orr r0,r0,#0x17 30 | msr CPSR,r0 @ We must use a reg for changing mode 31 | 32 | @ Store in Context var current values of SP, LR, and CPSR 33 | ldr r0, =Context+52 @ Address of the 3 last words of Context 34 | stmia r0!, {sp, lr} 35 | mrs r1, cpsr 36 | str r1, [r0] 37 | @ Bring values from Context (regs 0 - 12) to supervisor mode registers 38 | ldr r0, =Context 39 | ldm r0, {r0-r12} 40 | 41 | @ Exit ABT Mode and enter Supervisor mode 42 | mrs r0,CPSR 43 | bic r0,r0,#0x1F 44 | orr r0,r0,#0x13 45 | msr CPSR,r0 46 | 47 | @ Check the values of registers 1 - r10 48 | stmdb sp!, {r11-r12} @ Store the value of R11 and R12 for preservation (we need 2 free registers to check the values) 49 | ldr r11, =Context 50 | ldr r12, [r11, #4] @ Bring r1 from Context 51 | add r11, r11, #8 @ Advance pointer to r2 52 | cmp r1, r12 53 | movne r0, #1 54 | bne Error 55 | ldr r12, [r11], #4 @ Bring r2 from Context, and advance pointer to r3 56 | cmp r2, r12 57 | movne r0, #2 58 | bne Error 59 | ldr r12, [r11], #4 @ Bring r3 from Context, and advance pointer to r4 60 | cmp r3, r12 61 | movne r0, #3 62 | bne Error 63 | ldr r12, [r11], #4 @ Bring r4 from Context, and advance pointer to r5 64 | cmp r4, r12 65 | movne r0, #4 66 | bne Error 67 | ldr r12, [r11], #4 @ Bring r5 from Context, and advance pointer to r6 68 | cmp r5, r12 69 | movne r0, #5 70 | bne Error 71 | ldr r12, [r11], #4 @ Bring r6 from Context, and advance pointer to r7 72 | cmp r6, r12 73 | movne r0, #6 74 | bne Error 75 | ldr r12, [r11], #4 @ Bring r7 from Context, and advance pointer to r8 76 | cmp r7, r12 77 | movne r0, #7 78 | bne Error 79 | ldr r12, [r11], #4 @ Bring r8 from Context, and advance pointer to r9 80 | cmp r8, r12 81 | movne r0, #8 82 | bne Error 83 | ldr r12, [r11], #4 @ Bring r9 from Context, and advance pointer to r10 84 | cmp r9, r12 85 | movne r0, #9 86 | bne Error 87 | ldr r12, [r11], #4 @ Bring r10 from Context, and advance pointer to r11 88 | cmp r10, r12 89 | movne r0, #10 90 | bne Error 91 | 92 | @ Check the values of registers r11 - r12 93 | mov r0, r11 94 | ldr r1, [r0], #4 @ Bring r11 from Context, and advance pointer to r12 95 | ldmia sp!, {r11-r12} @ We recover from the stack the stored values of R11 and R12 96 | cmp r11, r1 97 | movne r0, #11 98 | bne Error 99 | ldr r1, [r0], #4 @ Bring r12 from Context, and advance pointer to sp 100 | cmp r12, r1 101 | movne r0, #12 102 | bne Error 103 | 104 | @ Check the values of sp & lr, they need to be different 105 | ldr r1, [r0], #4 @ Bring SP from Context, and advance pointer to LR 106 | cmp r1, sp 107 | moveq r0, #13 108 | beq Error 109 | ldr r1, [r0], #4 @ Bring LR from Context, and advance pointer to CPSR 110 | cmp r1, lr 111 | moveq r0, #14 112 | beq Error 113 | @ Check the values of SPSR & CPSR 114 | ldr r1, [r0] @ Bring CPSR from Context 115 | @ Check the value of the CPSR is different to the one saved in Context 116 | mrs r2, cpsr 117 | cmp r1, r2 118 | moveq r0, #15 119 | beq Error 120 | @ Check the SPSR is equal to the old value of the CPSR 121 | mrs r2, spsr 122 | cmp r1, r2 123 | movne r0, #16 124 | 125 | @ Enter ABT Mode 126 | mrs r0,CPSR 127 | bic r0,r0,#0x1F 128 | orr r0,r0,#0x17 129 | msr CPSR,r0 130 | 131 | @ Bring value of R0 from Context 132 | ldr r0, =Context 133 | ldr r0, [r0] 134 | 135 | @ Exit ABT Mode for checking r0 136 | mrs r1,CPSR 137 | bic r1,r1,#0x1F 138 | orr r1,r1,#0x13 139 | msr CPSR,r1 140 | 141 | ldr r1, =Context 142 | ldr r1, [r1] @ Bring r0 from Context 143 | cmp r0, r1 144 | movne r0, #0 145 | bne Error 146 | 147 | NoError: 148 | @Print the success message 149 | ldr r0, =Success_Msg 150 | swi 0x2 @OS_Write0 151 | swi 0x11 152 | 153 | @Print the error and exit the program 154 | Error: 155 | mov r1, #5 156 | mul r4, r0, r1 157 | ldr r1, =Error_Reg @ Load the string with the names of the registers 158 | add r4, r4, r1 @ Get the position of the reg name 159 | @ Print the error message 160 | ldr r0, =Error_Msg 161 | swi 0x2 @OS_Write0 162 | @ Print the name of the register that failed the check 163 | ldrb r0, [r4] 164 | swi 0x00 @OS_WriteC 165 | add r4, r4, #1 166 | ldrb r0, [r4] 167 | swi 0x00 168 | add r4, r4, #1 169 | ldrb r0, [r4] 170 | swi 0x00 171 | add r4, r4, #1 172 | ldrb r0, [r4] 173 | swi 0x00 174 | swi 0x11 175 | -------------------------------------------------------------------------------- /Tests/Modes/Leave/fiq.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of leaving fast interrupt mode 2 | 3 | @ The program saves the value of SP, LR and CPSR in the var Context (in the last three words). 4 | @ After that, it overwrites the values of register R0 through R12 with the first thirteen words of the var Context. 5 | @ Then it uses the SWI 0x16 to enter Supervisor mode. 6 | @ Once you are in supervisor mode check register R0-7 maintain their values, register R8-12, registers SP, LR and CPSR have different values that the ones stored in the var Context, and that SPSR is equal to the stored CPSR. 7 | @ If there was an error it will notify the user with a message indicating the first register in which it detected the first error. 8 | @ If there was no error it should end with no message at the end. 9 | 10 | .data 11 | .align 2 12 | Context: .word 0x51515150, 0x25252221, 0xF5823952, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaA, 0xaB, 0xaC, 0xa0, 0xa0, 0x0 13 | Error_Msg: .asciz "There has been an error on the reg: " 14 | Success_Msg: .asciz "Test ended successfully\n" 15 | 16 | Error_Reg: .ascii "Rg00 Rg01 Rg02 Rg03 Rg04 Rg05 Rg06 Rg07 Rg08 Rg09 Rg10 Rg11 Rg12 RgSP RgLR CPSR SPSR" 17 | 18 | 19 | .text 20 | .globl _start 21 | _start: 22 | @ Enter OS Mode 23 | swi 0x16 24 | 25 | @ Enter FIQ Mode 26 | mrs r0,CPSR 27 | bic r0,r0,#0x1F 28 | orr r0,r0,#0x11 29 | msr CPSR,r0 @ We must use a reg for changing mode 30 | 31 | @ Store in Context var current values of SP, LR, and CPSR 32 | ldr r0, =Context+52 @ Address of the 3 last words of Context 33 | stmia r0!, {sp, lr} 34 | mrs r1, cpsr 35 | str r1, [r0] 36 | @ Bring values from Context (regs 0 - 12) to supervisor mode registers 37 | ldr r0, =Context 38 | ldm r0, {r0-r12} 39 | 40 | @ Exit FIQ Mode ad enter Supervisor mode 41 | mrs r0,CPSR 42 | bic r0,r0,#0x1F 43 | orr r0,r0,#0x13 44 | msr CPSR,r0 45 | 46 | @ Check the values of registers 1 - r10 47 | stmdb sp!, {r11-r12} @ Store the value of R11 and R12 for preservation (we need 2 free registers to check the values) 48 | ldr r11, =Context 49 | ldr r12, [r11, #4] @ Bring r1 from Context 50 | add r11, r11, #8 @ Advance pointer to r2 51 | cmp r1, r12 52 | movne r0, #1 53 | bne Error 54 | ldr r12, [r11], #4 @ Bring r2 from Context, and advance pointer to r3 55 | cmp r2, r12 56 | movne r0, #2 57 | bne Error 58 | ldr r12, [r11], #4 @ Bring r3 from Context, and advance pointer to r4 59 | cmp r3, r12 60 | movne r0, #3 61 | bne Error 62 | ldr r12, [r11], #4 @ Bring r4 from Context, and advance pointer to r5 63 | cmp r4, r12 64 | movne r0, #4 65 | bne Error 66 | ldr r12, [r11], #4 @ Bring r5 from Context, and advance pointer to r6 67 | cmp r5, r12 68 | movne r0, #5 69 | bne Error 70 | ldr r12, [r11], #4 @ Bring r6 from Context, and advance pointer to r7 71 | cmp r6, r12 72 | movne r0, #6 73 | bne Error 74 | ldr r12, [r11], #4 @ Bring r7 from Context, and advance pointer to r8 75 | cmp r7, r12 76 | movne r0, #7 77 | bne Error 78 | ldr r12, [r11], #4 @ Bring r8 from Context, and advance pointer to r9 79 | cmp r8, r12 80 | moveq r0, #8 81 | beq Error 82 | ldr r12, [r11], #4 @ Bring r9 from Context, and advance pointer to r10 83 | cmp r9, r12 84 | moveq r0, #9 85 | beq Error 86 | ldr r12, [r11], #4 @ Bring r10 from Context, and advance pointer to r11 87 | cmp r10, r12 88 | moveq r0, #10 89 | beq Error 90 | 91 | @ Check the values of registers r11 - r12 92 | mov r0, r11 93 | ldr r1, [r0], #4 @ Bring r11 from Context, and advance pointer to r12 94 | ldmia sp!, {r11-r12} @ We recover from the stack the stored values of R11 and R12 95 | cmp r11, r1 96 | moveq r0, #11 97 | beq Error 98 | ldr r1, [r0], #4 @ Bring r12 from Context, and advance pointer to sp 99 | cmp r12, r1 100 | moveq r0, #12 101 | beq Error 102 | 103 | @ Check the values of sp & lr, they need to be different 104 | ldr r1, [r0], #4 @ Bring SP from Context, and advance pointer to LR 105 | cmp r1, sp 106 | moveq r0, #13 107 | beq Error 108 | ldr r1, [r0], #4 @ Bring LR from Context, and advance pointer to CPSR 109 | cmp r1, lr 110 | moveq r0, #14 111 | beq Error 112 | @ Check the values of SPSR & CPSR 113 | ldr r1, [r0] @ Bring CPSR from Context 114 | @ Check the value of the CPSR is different to the one saved in Context 115 | mrs r2, cpsr 116 | cmp r1, r2 117 | moveq r0, #15 118 | beq Error 119 | @ Check the SPSR is equal to the old value of the CPSR 120 | mrs r2, spsr 121 | cmp r1, r2 122 | movne r0, #16 123 | 124 | @ Re-enter FIQ Mode for checking r0 125 | mrs r0,CPSR 126 | bic r0,r0,#0x1F 127 | orr r0,r0,#0x11 128 | msr CPSR,r0 129 | 130 | @ Bring value of R0 from Context 131 | ldr r0, =Context 132 | ldr r0, [r0] 133 | 134 | @ Exit FIQ Mode ad enter Supervisor mode 135 | mrs r1,CPSR 136 | bic r1,r1,#0x1F 137 | orr r1,r1,#0x13 138 | msr CPSR,r1 139 | 140 | ldr r1, =Context 141 | ldr r1, [r1] @ Bring r0 from Context 142 | cmp r0, r1 143 | movne r0, #0 144 | bne Error 145 | NoError: 146 | @Print the success message 147 | ldr r0, =Success_Msg 148 | swi 0x2 @OS_Write0 149 | swi 0x11 150 | 151 | @Print the error and exit the program 152 | Error: 153 | mov r1, #5 154 | mul r4, r0, r1 155 | ldr r1, =Error_Reg @ Load the string with the names of the registers 156 | add r4, r4, r1 @ Get the position of the reg name 157 | @ Print the error message 158 | ldr r0, =Error_Msg 159 | swi 0x2 @OS_Write0 160 | @ Print the name of the register that failed the check 161 | ldrb r0, [r4] 162 | swi 0x00 @OS_WriteC 163 | add r4, r4, #1 164 | ldrb r0, [r4] 165 | swi 0x00 166 | add r4, r4, #1 167 | ldrb r0, [r4] 168 | swi 0x00 169 | add r4, r4, #1 170 | ldrb r0, [r4] 171 | swi 0x00 172 | swi 0x11 173 | -------------------------------------------------------------------------------- /Tests/Modes/Leave/irq.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of leaving interrupt mode 2 | 3 | @ The program saves the value of SP, LR and CPSR in the var Context (in the last three words). 4 | @ After that, it overwrites the values of register R0 through R12 with the first thirteen words of the var Context. 5 | @ Then it uses the SWI 0x16 to enter Supervisor mode. 6 | @ Once you are in supervisor mode check register R0-12 maintain their values, registers SP, LR and CPSR have different values that the ones stored in the var Context, and that SPSR is equal to the stored CPSR. 7 | @ If there was an error it will notify the user with a message indicating the first register in which it detected the first error. 8 | @ If there was no error it should end with no message at the end. 9 | 10 | .data 11 | .align 2 12 | Context: .word 0x11111110, 0x22222221, 0xF5823992, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0, 0, 0 13 | Error_Msg: .asciz "There has been an error on the reg: " 14 | Success_Msg: .asciz "Test ended successfully\n" 15 | 16 | Error_Reg: .ascii "Rg00 Rg01 Rg02 Rg03 Rg04 Rg05 Rg06 Rg07 Rg08 Rg09 Rg10 Rg11 Rg12 RgSP RgLR CPSR SPSR" 17 | 18 | 19 | .text 20 | .globl _start 21 | _start: 22 | @ Enter OS Mode 23 | swi 0x16 24 | 25 | @ Enter IRQ Mode 26 | mrs r0,CPSR 27 | bic r0,r0,#0x1F 28 | orr r0,r0,#0x12 29 | msr CPSR,r0 @ We must use a reg for changing mode 30 | 31 | @ Store in Context var current values of SP, LR, and CPSR 32 | ldr r0, =Context+52 @ Address of the 3 last words of Context 33 | stmia r0!, {sp, lr} 34 | mrs r1, cpsr 35 | str r1, [r0] 36 | @ Bring values from Context (regs 0 - 12) to supervisor mode registers 37 | ldr r0, =Context 38 | ldm r0, {r0-r12} 39 | 40 | @ Exit IRQ Mode ad enter Supervisor mode 41 | mrs r0,CPSR 42 | bic r0,r0,#0x1F 43 | orr r0,r0,#0x13 44 | msr CPSR,r0 45 | 46 | 47 | 48 | @ Check the values of registers 1 - r10 49 | stmdb sp!, {r11-r12} @ Store the value of R11 and R12 for preservation (we need 2 free registers to check the values) 50 | ldr r11, =Context 51 | ldr r12, [r11, #4] @ Bring r1 from Context 52 | add r11, r11, #8 @ Advance pointer to r2 53 | cmp r1, r12 54 | movne r0, #1 55 | bne Error 56 | ldr r12, [r11], #4 @ Bring r2 from Context, and advance pointer to r3 57 | cmp r2, r12 58 | movne r0, #2 59 | bne Error 60 | ldr r12, [r11], #4 @ Bring r3 from Context, and advance pointer to r4 61 | cmp r3, r12 62 | movne r0, #3 63 | bne Error 64 | ldr r12, [r11], #4 @ Bring r4 from Context, and advance pointer to r5 65 | cmp r4, r12 66 | movne r0, #4 67 | bne Error 68 | ldr r12, [r11], #4 @ Bring r5 from Context, and advance pointer to r6 69 | cmp r5, r12 70 | movne r0, #5 71 | bne Error 72 | ldr r12, [r11], #4 @ Bring r6 from Context, and advance pointer to r7 73 | cmp r6, r12 74 | movne r0, #6 75 | bne Error 76 | ldr r12, [r11], #4 @ Bring r7 from Context, and advance pointer to r8 77 | cmp r7, r12 78 | movne r0, #7 79 | bne Error 80 | ldr r12, [r11], #4 @ Bring r8 from Context, and advance pointer to r9 81 | cmp r8, r12 82 | movne r0, #8 83 | bne Error 84 | ldr r12, [r11], #4 @ Bring r9 from Context, and advance pointer to r10 85 | cmp r9, r12 86 | movne r0, #9 87 | bne Error 88 | ldr r12, [r11], #4 @ Bring r10 from Context, and advance pointer to r11 89 | cmp r10, r12 90 | movne r0, #10 91 | bne Error 92 | 93 | @ Check the values of registers r11 - r12 94 | mov r0, r11 95 | ldr r1, [r0], #4 @ Bring r11 from Context, and advance pointer to r12 96 | ldmia sp!, {r11-r12} @ We recover from the stack the stored values of R11 and R12 97 | cmp r11, r1 98 | movne r0, #11 99 | bne Error 100 | ldr r1, [r0], #4 @ Bring r12 from Context, and advance pointer to sp 101 | cmp r12, r1 102 | movne r0, #12 103 | bne Error 104 | 105 | @ Check the values of sp & lr, they need to be different 106 | ldr r1, [r0], #4 @ Bring SP from Context, and advance pointer to LR 107 | cmp r1, sp 108 | moveq r0, #13 109 | beq Error 110 | ldr r1, [r0], #4 @ Bring LR from Context, and advance pointer to CPSR 111 | cmp r1, lr 112 | moveq r0, #14 113 | beq Error 114 | @ Check the values of SPSR & CPSR 115 | ldr r1, [r0] @ Bring CPSR from Context 116 | @ Check the value of the CPSR is different to the one saved in Context 117 | mrs r2, cpsr 118 | cmp r1, r2 119 | moveq r0, #15 120 | beq Error 121 | @ Check the SPSR is equal to the old value of the CPSR 122 | mrs r2, spsr 123 | cmp r1, r2 124 | movne r0, #16 125 | 126 | @ Re-enter IRQ Mode for checking r0 127 | mrs r0,CPSR 128 | bic r0,r0,#0x1F 129 | orr r0,r0,#0x12 130 | msr CPSR,r0 131 | 132 | @ Bring value of R0 from Context 133 | ldr r0, =Context 134 | ldr r0, [r0] 135 | 136 | @ Exit IRQ Mode ad enter Supervisor mode 137 | mrs r1,CPSR 138 | bic r1,r1,#0x1F 139 | orr r1,r1,#0x13 140 | msr CPSR,r1 141 | 142 | ldr r1, =Context 143 | ldr r1, [r1] @ Bring r0 from Context 144 | cmp r0, r1 145 | movne r0, #0 146 | bne Error 147 | NoError: 148 | @Print the success message 149 | ldr r0, =Success_Msg 150 | swi 0x2 @OS_Write0 151 | swi 0x11 152 | 153 | @Print the error and exit the program 154 | Error: 155 | mov r1, #5 156 | mul r4, r0, r1 157 | ldr r1, =Error_Reg @ Load the string with the names of the registers 158 | add r4, r4, r1 @ Get the position of the reg name 159 | @ Print the error message 160 | ldr r0, =Error_Msg 161 | swi 0x2 @OS_Write0 162 | @ Print the name of the register that failed the check 163 | ldrb r0, [r4] 164 | swi 0x00 @OS_WriteC 165 | add r4, r4, #1 166 | ldrb r0, [r4] 167 | swi 0x00 168 | add r4, r4, #1 169 | ldrb r0, [r4] 170 | swi 0x00 171 | add r4, r4, #1 172 | ldrb r0, [r4] 173 | swi 0x00 174 | swi 0x11 175 | -------------------------------------------------------------------------------- /Tests/Modes/Leave/sys.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behaviorof leaving system mode 2 | 3 | @ The program saves the value of SP, LR and CPSR in the var Context (in the last three words). 4 | @ After that, it overwrites the values of register R0 through R12 with the first thirteen words of the var Context. 5 | @ Then it uses the SWI 0x16 to enter Supervisor mode. 6 | @ Once you are in supervisor mode check register R0-12 maintain their values, registers SP, LR and CPSR have different values that the ones stored in the var Context, and that SPSR is equal to the stored CPSR. 7 | @ If there was an error it will notify the user with a message indicating the first register in which it detected the first error. 8 | @ If there was no error it should end with no message at the end. 9 | 10 | .data 11 | .align 2 12 | Context: .word 0x11111110, 0x22222221, 0xF5823992, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0, 0, 0 13 | Error_Msg: .asciz "There has been an error on the reg: " 14 | Success_Msg: .asciz "Test ended successfully\n" 15 | 16 | Error_Reg: .ascii "Rg00 Rg01 Rg02 Rg03 Rg04 Rg05 Rg06 Rg07 Rg08 Rg09 Rg10 Rg11 Rg12 RgSP RgLR CPSR" 17 | 18 | 19 | .text 20 | .globl _start 21 | _start: 22 | @ Enter OS Mode 23 | swi 0x16 24 | 25 | @ Store in Context var current values of SP, LR, and CPSR 26 | ldr r0, =Context+52 @ Address of the 3 last words of Context 27 | stmia r0!, {sp, lr} 28 | mrs r1, cpsr 29 | str r1, [r0] 30 | @ Bring values from Context (regs 0 - 12) to supervisor mode registers 31 | ldr r0, =Context 32 | ldm r0, {r0-r12} 33 | 34 | 35 | 36 | @ Enter SYS Mode 37 | mrs r0,CPSR 38 | and r0,r0,#0x1F 39 | orr r0,r0,#0x17 40 | msr CPSR,r0 @ We must use a reg for changing mode 41 | 42 | @ Check the values of registers 1 - r10 43 | stmdb sp!, {r11-r12} @ Store the value of R11 and R12 for preservation (we need 2 free registers to check the values) 44 | ldr r11, =Context 45 | ldr r12, [r11, #4] @ Bring r1 from Context 46 | add r11, r11, #8 @ Advance pointer to r2 47 | cmp r1, r12 48 | movne r0, #1 49 | bne Error 50 | ldr r12, [r11], #4 @ Bring r2 from Context, and advance pointer to r3 51 | cmp r2, r12 52 | movne r0, #2 53 | bne Error 54 | ldr r12, [r11], #4 @ Bring r3 from Context, and advance pointer to r4 55 | cmp r3, r12 56 | movne r0, #3 57 | bne Error 58 | ldr r12, [r11], #4 @ Bring r4 from Context, and advance pointer to r5 59 | cmp r4, r12 60 | movne r0, #4 61 | bne Error 62 | ldr r12, [r11], #4 @ Bring r5 from Context, and advance pointer to r6 63 | cmp r5, r12 64 | movne r0, #5 65 | bne Error 66 | ldr r12, [r11], #4 @ Bring r6 from Context, and advance pointer to r7 67 | cmp r6, r12 68 | movne r0, #6 69 | bne Error 70 | ldr r12, [r11], #4 @ Bring r7 from Context, and advance pointer to r8 71 | cmp r7, r12 72 | movne r0, #7 73 | bne Error 74 | ldr r12, [r11], #4 @ Bring r8 from Context, and advance pointer to r9 75 | cmp r8, r12 76 | movne r0, #8 77 | bne Error 78 | ldr r12, [r11], #4 @ Bring r9 from Context, and advance pointer to r10 79 | cmp r9, r12 80 | movne r0, #9 81 | bne Error 82 | ldr r12, [r11], #4 @ Bring r10 from Context, and advance pointer to r11 83 | cmp r10, r12 84 | movne r0, #10 85 | bne Error 86 | 87 | @ Check the values of registers r11 - r12 88 | mov r0, r11 89 | ldr r1, [r0], #4 @ Bring r11 from Context, and advance pointer to r12 90 | ldmia sp!, {r11-r12} @ We recover from the stack the stored values of R11 and R12 91 | cmp r11, r1 92 | movne r0, #11 93 | bne Error 94 | ldr r1, [r0], #4 @ Bring r12 from Context, and advance pointer to sp 95 | cmp r12, r1 96 | movne r0, #12 97 | bne Error 98 | 99 | @ Check the values of sp & lr, they need to be different 100 | ldr r1, [r0], #4 @ Bring SP from Context, and advance pointer to LR 101 | cmp r1, sp 102 | moveq r0, #13 103 | beq Error 104 | ldr r1, [r0], #4 @ Bring LR from Context, and advance pointer to CPSR 105 | cmp r1, lr 106 | moveq r0, #14 107 | beq Error 108 | @ Check the values of CPSR 109 | ldr r1, [r0] @ Bring CPSR from Context 110 | @ Check the value of the CPSR is different to the one saved in Context 111 | mrs r2, cpsr 112 | cmp r1, r2 113 | moveq r0, #15 114 | beq Error 115 | 116 | @ Exit SYS Mode ad enter Supervisor mode 117 | mrs r0,CPSR 118 | and r0,r0,#0x1F 119 | orr r0,r0,#0x13 120 | msr CPSR,r0 121 | 122 | @ Bring value of R0 from Context 123 | ldr r0, =Context 124 | ldr r0, [r0] 125 | 126 | @ Re-enter SYS Mode for checking r0 127 | mrs r1,CPSR 128 | and r1,r1,#0x1F 129 | orr r1,r1,#0x17 130 | msr CPSR,r1 131 | 132 | ldr r1, =Context 133 | ldr r1, [r1] @ Bring r0 from Context 134 | cmp r0, r1 135 | movne r0, #0 136 | bne Error 137 | 138 | bne Error 139 | NoError: 140 | @Print the success message 141 | ldr r0, =Success_Msg 142 | swi 0x2 @OS_Write0 143 | swi 0x11 144 | 145 | @Print the error and exit the program 146 | Error: 147 | mov r1, #5 148 | mul r4, r0, r1 149 | ldr r1, =Error_Reg @ Load the string with the names of the registers 150 | add r4, r4, r1 @ Get the position of the reg name 151 | @ Print the error message 152 | ldr r0, =Error_Msg 153 | swi 0x2 @OS_Write0 154 | @ Print the name of the register that failed the check 155 | ldrb r0, [r4] 156 | swi 0x00 @OS_WriteC 157 | add r4, r4, #1 158 | ldrb r0, [r4] 159 | swi 0x00 160 | add r4, r4, #1 161 | ldrb r0, [r4] 162 | swi 0x00 163 | add r4, r4, #1 164 | ldrb r0, [r4] 165 | swi 0x00 166 | swi 0x11 167 | -------------------------------------------------------------------------------- /Tests/Modes/Leave/und.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of leaving undefined mode 2 | 3 | @ The program saves the value of SP, LR and CPSR in the var Context (in the last three words). 4 | @ After that, it overwrites the values of register R0 through R12 with the first thirteen words of the var Context. 5 | @ Then it uses the SWI 0x16 to enter Supervisor mode. 6 | @ Once you are in supervisor mode check register R0-12 maintain their values, registers SP, LR and CPSR have different values that the ones stored in the var Context, and that SPSR is equal to the stored CPSR. 7 | @ If there was an error it will notify the user with a message indicating the first register in which it detected the first error. 8 | @ If there was no error it should end with no message at the end. 9 | 10 | .data 11 | .align 2 12 | Context: .word 0x11111110, 0x22222221, 0xF5823992, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0, 0, 0 13 | Error_Msg: .asciz "There has been an error on the reg: " 14 | Success_Msg: .asciz "Test ended successfully\n" 15 | 16 | Error_Reg: .ascii "Rg00 Rg01 Rg02 Rg03 Rg04 Rg05 Rg06 Rg07 Rg08 Rg09 Rg10 Rg11 Rg12 RgSP RgLR CPSR SPSR" 17 | 18 | 19 | .text 20 | .globl _start 21 | _start: 22 | @ Enter OS Mode 23 | swi 0x16 24 | 25 | @ Enter UND Mode 26 | mrs r0,CPSR 27 | bic r0,r0,#0x1F 28 | orr r0,r0,#0x1B 29 | msr CPSR,r0 @ We must use a reg for changing mode 30 | 31 | @ Store in Context var current values of SP, LR, and CPSR 32 | ldr r0, =Context+52 @ Address of the 3 last words of Context 33 | stmia r0!, {sp, lr} 34 | mrs r1, cpsr 35 | str r1, [r0] 36 | @ Bring values from Context (regs 0 - 12) to supervisor mode registers 37 | ldr r0, =Context 38 | ldm r0, {r0-r12} 39 | 40 | @ Exit UND Mode ad enter Supervisor mode 41 | mrs r0,CPSR 42 | bic r0,r0,#0x1F 43 | orr r0,r0,#0x13 44 | msr CPSR,r0 45 | 46 | 47 | 48 | @ Check the values of registers 1 - r10 49 | stmdb sp!, {r11-r12} @ Store the value of R11 and R12 for preservation (we need 2 free registers to check the values) 50 | ldr r11, =Context 51 | ldr r12, [r11, #4] @ Bring r1 from Context 52 | add r11, r11, #8 @ Advance pointer to r2 53 | cmp r1, r12 54 | movne r0, #1 55 | bne Error 56 | ldr r12, [r11], #4 @ Bring r2 from Context, and advance pointer to r3 57 | cmp r2, r12 58 | movne r0, #2 59 | bne Error 60 | ldr r12, [r11], #4 @ Bring r3 from Context, and advance pointer to r4 61 | cmp r3, r12 62 | movne r0, #3 63 | bne Error 64 | ldr r12, [r11], #4 @ Bring r4 from Context, and advance pointer to r5 65 | cmp r4, r12 66 | movne r0, #4 67 | bne Error 68 | ldr r12, [r11], #4 @ Bring r5 from Context, and advance pointer to r6 69 | cmp r5, r12 70 | movne r0, #5 71 | bne Error 72 | ldr r12, [r11], #4 @ Bring r6 from Context, and advance pointer to r7 73 | cmp r6, r12 74 | movne r0, #6 75 | bne Error 76 | ldr r12, [r11], #4 @ Bring r7 from Context, and advance pointer to r8 77 | cmp r7, r12 78 | movne r0, #7 79 | bne Error 80 | ldr r12, [r11], #4 @ Bring r8 from Context, and advance pointer to r9 81 | cmp r8, r12 82 | movne r0, #8 83 | bne Error 84 | ldr r12, [r11], #4 @ Bring r9 from Context, and advance pointer to r10 85 | cmp r9, r12 86 | movne r0, #9 87 | bne Error 88 | ldr r12, [r11], #4 @ Bring r10 from Context, and advance pointer to r11 89 | cmp r10, r12 90 | movne r0, #10 91 | bne Error 92 | 93 | @ Check the values of registers r11 - r12 94 | mov r0, r11 95 | ldr r1, [r0], #4 @ Bring r11 from Context, and advance pointer to r12 96 | ldmia sp!, {r11-r12} @ We recover from the stack the stored values of R11 and R12 97 | cmp r11, r1 98 | movne r0, #11 99 | bne Error 100 | ldr r1, [r0], #4 @ Bring r12 from Context, and advance pointer to sp 101 | cmp r12, r1 102 | movne r0, #12 103 | bne Error 104 | 105 | @ Check the values of sp & lr, they need to be different 106 | ldr r1, [r0], #4 @ Bring SP from Context, and advance pointer to LR 107 | cmp r1, sp 108 | moveq r0, #13 109 | beq Error 110 | ldr r1, [r0], #4 @ Bring LR from Context, and advance pointer to CPSR 111 | cmp r1, lr 112 | moveq r0, #14 113 | beq Error 114 | @ Check the values of SPSR & CPSR 115 | ldr r1, [r0] @ Bring CPSR from Context 116 | @ Check the value of the CPSR is different to the one saved in Context 117 | mrs r2, cpsr 118 | cmp r1, r2 119 | moveq r0, #15 120 | beq Error 121 | @ Check the SPSR is equal to the old value of the CPSR 122 | mrs r2, spsr 123 | cmp r1, r2 124 | movne r0, #16 125 | 126 | @ Re-enter UND Mode for checking r0 127 | mrs r0,CPSR 128 | bic r0,r0,#0x1F 129 | orr r0,r0,#0x1B 130 | msr CPSR,r0 131 | 132 | @ Bring value of R0 from Context 133 | ldr r0, =Context 134 | ldr r0, [r0] 135 | 136 | @ Exit UND Mode ad enter Supervisor mode 137 | mrs r1,CPSR 138 | bic r1,r1,#0x1F 139 | orr r1,r1,#0x13 140 | msr CPSR,r1 141 | 142 | ldr r1, =Context 143 | ldr r1, [r1] @ Bring r0 from Context 144 | cmp r0, r1 145 | movne r0, #0 146 | bne Error 147 | NoError: 148 | @Print the success message 149 | ldr r0, =Success_Msg 150 | swi 0x2 @OS_Write0 151 | swi 0x11 152 | 153 | @Print the error and exit the program 154 | Error: 155 | mov r1, #5 156 | mul r4, r0, r1 157 | ldr r1, =Error_Reg @ Load the string with the names of the registers 158 | add r4, r4, r1 @ Get the position of the reg name 159 | @ Print the error message 160 | ldr r0, =Error_Msg 161 | swi 0x2 @OS_Write0 162 | @ Print the name of the register that failed the check 163 | ldrb r0, [r4] 164 | swi 0x00 @OS_WriteC 165 | add r4, r4, #1 166 | ldrb r0, [r4] 167 | swi 0x00 168 | add r4, r4, #1 169 | ldrb r0, [r4] 170 | swi 0x00 171 | add r4, r4, #1 172 | ldrb r0, [r4] 173 | swi 0x00 174 | swi 0x11 175 | -------------------------------------------------------------------------------- /Tests/Reset/CPSR_Reset/check_cpsr.s: -------------------------------------------------------------------------------- 1 | @ Checks the CPSR has its default value when running a new program. 2 | @ This program should be run after other program which changes some of the flags 3 | @ which this program checks. 4 | 5 | .data 6 | Default_CPSR: .word 0x80000110 @ Default value of the CPSR (only care about flags Q, GE, A, I and F) 7 | Error_Msg: .asciz "There has been an error on the flag: " 8 | Error_Flag: .ascii "FIAGQ" 9 | Success_Msg: .asciz "Test ended succesfully\n" 10 | 11 | .text 12 | .globl _start 13 | _start: 14 | mrs r0,CPSR @ Get value of start CPSR in r0 15 | ldr r1, =Default_CPSR 16 | ldr r1, [r1] 17 | and r1, r1, r0 18 | @ Check bit F 19 | lsr r1, r1, #6 20 | and r0, r1, #0x1 21 | mov r4, #0 22 | cmp r0, #1 23 | beq error 24 | @ Check bit I 25 | lsr r1, r1, #1 26 | and r0, r1, #0x1 27 | mov r4, #1 28 | cmp r0, #1 29 | beq error 30 | @ Check bit A 31 | lsr r1, r1, #1 32 | and r0, r1, #0x1 33 | mov r4, #2 34 | cmp r0, #0 35 | beq error 36 | @ Check bit GE[0] 37 | lsr r1, r1, #8 38 | and r0, r1, #0x1 39 | mov r4, #3 40 | cmp r0, #1 41 | beq error 42 | @ Check bit GE[1] 43 | lsr r1, r1, #1 44 | and r0, r1, #0x1 45 | mov r4, #3 46 | cmp r0, #1 47 | beq error 48 | @ Check bit GE[2] 49 | lsr r1, r1, #1 50 | and r0, r1, #0x1 51 | mov r4, #3 52 | cmp r0, #1 53 | beq error 54 | @ Check bit GE[3] 55 | lsr r1, r1, #1 56 | and r0, r1, #0x1 57 | mov r4, #3 58 | cmp r0, #1 59 | beq error 60 | @ Check bit Q 61 | lsr r1, r1, #8 62 | and r0, r1, #0x1 63 | mov r4, #4 64 | cmp r0, #1 65 | beq error 66 | Success: 67 | @ Print the success message 68 | ldr r0, =Success_Msg 69 | swi 0x2 @OS_Write0 70 | swi 0x11 71 | 72 | error: 73 | @ Print the error message 74 | ldr r0, =Error_Msg 75 | swi 0x02 76 | @ Print the name of the flag that failed the check 77 | ldr r0, =Error_Flag 78 | add r0, r0, r4 79 | ldrb r0, [r0] 80 | swi 0x00 81 | swi 0x11 82 | 83 | .end 84 | -------------------------------------------------------------------------------- /Tests/Reset/CPSR_Reset/modify_cpsr.s: -------------------------------------------------------------------------------- 1 | @ Changes the value of the CPSR register 2 | 3 | .data 4 | 5 | .text 6 | .globl _start 7 | _start: 8 | 9 | @ Set the bits Q, GE, A, I and F to 1 10 | mrs r0,CPSR 11 | orr r0,r0,#0x00000100 12 | orr r0,r0,#0x000F0000 13 | orr r0,r0,#0x000000C0 14 | orr r0,r0,#0x08000000 15 | msr CPSR,r0 16 | swi 0x11 17 | 18 | .end 19 | 20 | -------------------------------------------------------------------------------- /Tests/Reset/Mode_Reset/abt.s: -------------------------------------------------------------------------------- 1 | .data 2 | 3 | .text 4 | .globl _start 5 | _start: 6 | @ Enter OS Mode 7 | swi 0x16 8 | 9 | @ Enter ABT Mode 10 | mrs r0,CPSR 11 | bic r0,r0,#0x1F 12 | orr r0,r0,#0x17 13 | msr CPSR,r0 14 | 15 | @ End the program in Supervisor mode 16 | swi 0x11 17 | -------------------------------------------------------------------------------- /Tests/Reset/Mode_Reset/check_mode.s: -------------------------------------------------------------------------------- 1 | .data 2 | 3 | Error_Msg: .asciz "The program didn't start in user mode\n" 4 | Success_Msg: .asciz "Test ended successfully\n" 5 | 6 | .text 7 | .globl _start 8 | _start: 9 | mrs r0, cpsr 10 | and r0, r0, #0x1f 11 | cmp r0, #0x10 12 | beq no_error 13 | error: 14 | mov r1, r0 15 | ldr r0, =Error_Msg 16 | swi 0x2 @OS_Write0 17 | no_error: 18 | @Print the success message 19 | ldr r0, =Success_Msg 20 | swi 0x2 @OS_Write0 21 | swi 0x11 22 | -------------------------------------------------------------------------------- /Tests/Reset/Mode_Reset/fiq.s: -------------------------------------------------------------------------------- 1 | .data 2 | 3 | .text 4 | .globl _start 5 | _start: 6 | @ Enter OS Mode 7 | swi 0x16 8 | 9 | @ Enter FIQ Mode 10 | mrs r0,CPSR 11 | bic r0,r0,#0x1F 12 | orr r0,r0,#0x11 13 | msr CPSR,r0 14 | 15 | @ End the program in Supervisor mode 16 | swi 0x11 17 | -------------------------------------------------------------------------------- /Tests/Reset/Mode_Reset/irq.s: -------------------------------------------------------------------------------- 1 | .data 2 | 3 | .text 4 | .globl _start 5 | _start: 6 | @ Enter OS Mode 7 | swi 0x16 8 | 9 | @ Enter IRQ Mode 10 | mrs r0,CPSR 11 | bic r0,r0,#0x1F 12 | orr r0,r0,#0x12 13 | msr CPSR,r0 14 | 15 | @ End the program in Supervisor mode 16 | swi 0x11 17 | -------------------------------------------------------------------------------- /Tests/Reset/Mode_Reset/readme.txt: -------------------------------------------------------------------------------- 1 | This directory contains the programs to test if the mode is reset to user mode after ending a program in a different mode. 2 | For testing all the modes you must run 1 of the programs that changes the mode (abt, fiq, irq, svc, sys or und) and then immediately (without closing the debugger or loading another program) run the program check_mode. 3 | Any of the first programs only changes mode and ends. 4 | The second program checks a new program starts in user mode. 5 | If the mode didn't reset the second program will print an error message. -------------------------------------------------------------------------------- /Tests/Reset/Mode_Reset/svc.s: -------------------------------------------------------------------------------- 1 | .data 2 | 3 | .text 4 | .globl _start 5 | _start: 6 | @ Enter OS Mode 7 | swi 0x16 8 | @ End the program in Supervisor mode 9 | swi 0x11 10 | -------------------------------------------------------------------------------- /Tests/Reset/Mode_Reset/sys.s: -------------------------------------------------------------------------------- 1 | .data 2 | 3 | .text 4 | .globl _start 5 | _start: 6 | @ Enter OS Mode 7 | swi 0x16 8 | 9 | @ Enter SYS Mode 10 | mrs r0,CPSR 11 | bic r0,r0,#0x1F 12 | orr r0,r0,#0x1F 13 | msr CPSR,r0 14 | 15 | @ End the program in Supervisor mode 16 | swi 0x11 17 | -------------------------------------------------------------------------------- /Tests/Reset/Mode_Reset/und.s: -------------------------------------------------------------------------------- 1 | .data 2 | 3 | .text 4 | .globl _start 5 | _start: 6 | @ Enter OS Mode 7 | swi 0x16 8 | 9 | @ Enter UND Mode 10 | mrs r0,CPSR 11 | bic r0,r0,#0x1F 12 | orr r0,r0,#0x1B 13 | msr CPSR,r0 14 | 15 | @ End the program in Supervisor mode 16 | swi 0x11 17 | -------------------------------------------------------------------------------- /Tests/Reset/Stack_Reset/check_stacks.s: -------------------------------------------------------------------------------- 1 | @ Checks Stack Pointers from modes supervisor, abort, undefined, interrupt and fast interrupt 2 | @ reset their value after loading a new program. 3 | @ This program should be executed after another program which ends with the stack values of all modes changed. 4 | 5 | .data 6 | 7 | Error_Msg1: .asciz "Error: " 8 | Error_Msg2: .asciz " stack pointer didn't reset\n" 9 | Error_Msg3: .asciz "Error: AuxFile not found. Have you previously run \"modify_stacks\"?" 10 | Success_Msg: .asciz "Test ended successfully\n" 11 | List_modes: .asciz "svc abt und irq fiq" 12 | AuxFileName: .asciz "AuxFile/txt" 13 | .align 2 14 | @ This list contains the default values of the stack pointers of all modes 15 | @ svc abt und irq fiq 16 | Stack_def_values: .space 21 17 | 18 | 19 | 20 | .text 21 | .globl _start 22 | _start: 23 | @ Check if auxiliary file exists 24 | mov r0, #5 25 | ldr r1, =AuxFileName 26 | swi 0x8 @ OS_File 5 (read info) 27 | cmp r0, #0 28 | beq aux_file_error 29 | 30 | open_existing_file: 31 | mov r0, #0x40 @ Open existing file in RO mode 32 | orr r0, r0, #8 @ Return error if non-existent file, and use current filepath 33 | ldr r1, =AuxFileName 34 | swi 0x0D @ OS_Find 35 | b load_stack_addr 36 | @ Here could be checked if file correctly created 37 | 38 | load_stack_addr: 39 | mov r1, r0 @ Save copy of file handler 40 | mov r0, #3 41 | ldr r2, =Stack_def_values 42 | mov r3, #21 @Space for 5 words and a NULL char 43 | mov r4, #0 @ Read from beginning of file 44 | swi 0x0C @ OS_GBPB 3 45 | 46 | mov r0, #0 @ Close file 47 | swi 0x0D @ OS_Find 48 | 49 | @ Remove auxiliary file 50 | mov r0, #6 @ Delete file 51 | ldr r1, =AuxFileName 52 | swi 0x8 @ OS_File 6 53 | 54 | @ Check supervisor SP 55 | swi 0x16 @ Enter OS Mode 56 | 57 | ldr r2, =Stack_def_values 58 | ldr r1, [r2], #4 @ Load the default value of supervisor SP and increase the pointer to abt SP default value 59 | cmp sp, r1 60 | movne r4, #0 61 | bne error 62 | 63 | @ Check abort SP 64 | @ Enter ABT Mode 65 | mrs r0,CPSR 66 | bic r0,r0,#0x1F 67 | orr r0,r0,#0x17 68 | msr CPSR,r0 69 | 70 | ldr r1, [r2], #4 @ Load the default value of abort SP and increase the pointer to und SP default value 71 | cmp sp, r1 72 | movne r4, #1 73 | bne error 74 | 75 | @ Check undefined SP 76 | @ Enter UND Mode 77 | mrs r0,CPSR 78 | bic r0,r0,#0x1F 79 | orr r0,r0,#0x1B 80 | msr CPSR,r0 81 | 82 | ldr r1, [r2], #4 @ Load the default value of undefined SP and increase the pointer to irq SP default value 83 | cmp sp, r1 84 | movne r4, #2 85 | bne error 86 | 87 | @ Check interrupt SP 88 | @ Enter IRQ Mode 89 | mrs r0,CPSR 90 | bic r0,r0,#0x1F 91 | orr r0,r0,#0x12 92 | msr CPSR,r0 93 | 94 | ldr r1, [r2], #4 @ Load the default value of interrupt SP and increase the pointer to fiq SP default value 95 | cmp sp, r1 96 | movne r4, #3 97 | bne error 98 | 99 | @ Check fast interrupt SP 100 | @ Enter FIQ Mode 101 | mrs r0,CPSR 102 | bic r0,r0,#0x1F 103 | orr r0,r0,#0x11 104 | msr CPSR,r0 105 | 106 | ldr r1, [r2] @ Load the default value of fast interrupt SP 107 | cmp sp, r1 108 | movne r4, #4 109 | bne error 110 | no_error: 111 | @Print the success message 112 | ldr r0, =Success_Msg 113 | swi 0x2 @OS_Write0 114 | swi 0x11 115 | 116 | @Print the error and exit the program 117 | error: 118 | mov r1, #4 119 | mul r2, r4, r1 120 | ldr r1, =List_modes @ Load the string with the names of the mode 121 | add r4, r2, r1 @ Get the position of the reg name 122 | @ Print the first part of the error message 123 | ldr r0, =Error_Msg1 124 | swi 0x2 @OS_Write0 125 | @ Print the name of the mode that failed the check 126 | ldrb r0, [r4] 127 | swi 0x00 @OS_WriteC 128 | add r4, r4, #1 129 | ldrb r0, [r4] 130 | swi 0x00 131 | add r4, r4, #1 132 | ldrb r0, [r4] 133 | swi 0x00 134 | @ Print the second part of the error message 135 | ldr r0, =Error_Msg2 136 | swi 0x2 @OS_Write0 137 | swi 0x11 138 | 139 | aux_file_error: 140 | ldr r0, =Error_Msg3 141 | swi 0x2 142 | swi 0x11 143 | -------------------------------------------------------------------------------- /Tests/Reset/Stack_Reset/modify_stacks.s: -------------------------------------------------------------------------------- 1 | @ This program modifies the stack of supervisor mode, abort mode, undefined mode, 2 | @ interrupt mode and fast interrupt mode, and ends without returning them to their 3 | @ initial state. 4 | @ Another program should check after this program execution that all stacks have reset their values. 5 | 6 | .data 7 | AuxFileName: .asciz "AuxFile/txt" 8 | .align 2 9 | Stack_def_values: .space 21 10 | 11 | .text 12 | .globl _start 13 | _start: 14 | @ Open buffer to later store original SP values 15 | ldr r4, =Stack_def_values 16 | 17 | @ Enter OS Mode 18 | swi 0x16 19 | str sp, [r4], #4 @ Save stack pointer in buffer 20 | 21 | @ Modify the stack saving the regs 0 - 12 22 | stmdb sp!, {r0-r12} 23 | 24 | @ Enter ABT Mode 25 | mrs r0,CPSR 26 | bic r0,r0,#0x1F 27 | orr r0,r0,#0x17 28 | msr CPSR,r0 29 | str sp, [r4], #4 @ Save stack pointer in buffer 30 | 31 | @ Modify the stack saving the regs 0 - 12 32 | stmdb sp!, {r0-r12} 33 | 34 | @ Enter UND Mode 35 | mrs r0,CPSR 36 | bic r0,r0,#0x1F 37 | orr r0,r0,#0x1B 38 | msr CPSR,r0 39 | str sp, [r4], #4 @ Save stack pointer in buffer 40 | 41 | @ Modify the stack saving the regs 0 - 12 42 | stmdb sp!, {r0-r12} 43 | 44 | @ Enter IRQ Mode 45 | mrs r0,CPSR 46 | bic r0,r0,#0x1F 47 | orr r0,r0,#0x12 48 | msr CPSR,r0 49 | str sp, [r4], #4 @ Save stack pointer in buffer 50 | 51 | @ Modify the stack saving the regs 0 - 12 52 | stmdb sp!, {r0-r12} 53 | 54 | @ Enter FIQ Mode 55 | mrs r0,CPSR 56 | bic r0,r0,#0x1F 57 | orr r0,r0,#0x11 58 | msr CPSR,r0 59 | str sp, [r4], #4 @ Save stack pointer in buffer 60 | mov r2, #0 61 | strb r2, [r4] 62 | 63 | @ Modify the stack saving the regs 0 - 12 64 | stmdb sp!, {r0-r12} 65 | 66 | @ Check if auxiliary file exists and, if not, create it 67 | mov r0, #5 68 | ldr r1, =AuxFileName 69 | swi 0x8 @ OS_File 5 (read info) 70 | cmp r0, #0 71 | beq open_new_file 72 | 73 | open_existing_file: 74 | mov r0, #0xC0 @ Open existing file in R/W mode 75 | orr r0, r0, #8 @ Return error if non-existent file, and use current filepath 76 | ldr r1, =AuxFileName 77 | swi 0x0D @ OS_Find 78 | b store_stack_addr 79 | @ Here could be checked if file correctly created 80 | 81 | open_new_file: 82 | mov r0, #0x80 @ Open new file in R/W mode 83 | orr r0, r0, #8 @ Return error if non-existent file, and use current filepath 84 | ldr r1, =AuxFileName 85 | swi 0x0D @ OS_Find 86 | @ Here could be checked if file correctly created 87 | 88 | store_stack_addr: 89 | mov r1, r0 @ Save copy of file handler 90 | mov r0, #2 91 | ldr r2, =Stack_def_values 92 | mov r3, #21 @Space for 5 words and a NULL char 93 | swi 0x0C @ OS_GBPB 2 94 | 95 | mov r0, #0 @ Close file 96 | swi 0x0D @ OS_Find 97 | 98 | swi 0x11 99 | -------------------------------------------------------------------------------- /Tests/Reset/Stack_Reset/readme.txt: -------------------------------------------------------------------------------- 1 | Los programas modify_stacks y check_stacks componen un unico test. 2 | Para realizar el test debemos ejecutar primero el programa modify_stacks y despues check_stacks (sin cerrar el depurador o cargar otro programa en medio). 3 | El primer programa modifica los stacks de los modos supervisor, abort, undefined, interrupt y fast interrupt, y termina sin restaurar sus valores iniciales. 4 | El segundo programa comprueba que los stacks de los modos previamente modificados en el programa anterior han recuperado su valor por defecto tras cargar un nuevo programa. 5 | En caso de que el segundo programa detecte que alguno de los stacks no se ha reseteado imprimira por pantalla un mensaje de error especificando el primer stack que ha detectado que no ha retomado su valor por defecto. 6 | -------------------------------------------------------------------------------- /Tests/SWI/001_exit_def.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of OS_ExitOS (0x11). Checks the case of the program ending by calling the SWI 0x11. 2 | @ The return code should be 0 when the program ends. 3 | 4 | .data 5 | 6 | .text 7 | .globl _start 8 | _start: 9 | swi 0x11 10 | 11 | .end 12 | -------------------------------------------------------------------------------- /Tests/SWI/101_writec.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of OS_WriteC (0x00) 2 | @ This test prints all the characters of the variable "Chars". 3 | 4 | .data 5 | 6 | @ Characters: 1@* +;[_Ftñáçº 7 | Chars: .byte 0x31, 0x40, 0x2a, 0x20, 0x2b, 0x3b, 0x5b, 0x5f, 0x46, 0x74, 0xf1, 0xe1, 0xe7, 0xba 8 | 9 | .equ Num_chars, 13 10 | 11 | 12 | .text 13 | .globl _start 14 | _start: 15 | ldr r5, =Chars 16 | mov r4, #0 17 | @ This loop prints all the characters of the var Chars. 18 | loop: 19 | ldrb r0, [r5] @ Read the character 20 | swi 0x00 21 | add r5, r5, #1 @ Advance the pointer to the next character 22 | add r4, r4, #1 23 | cmp r4, #Num_chars 24 | bne loop 25 | end: 26 | swi 0x11 27 | 28 | .end 29 | -------------------------------------------------------------------------------- /Tests/SWI/201_write0.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of OS_Write0 (0x02) 2 | @ We load the address of the first string and call the SWI. This should update the address, 3 | @ which now should point to the second string. We call the SWI again to check that this has happened. 4 | 5 | .data 6 | 7 | String1: .asciz "Test " 8 | String2: .asciz "Text " 9 | String3: .asciz "1@* +;[_Ftñáçº" 10 | 11 | .text 12 | .globl _start 13 | _start: 14 | ldr r0, =String1 15 | swi 0x02 16 | swi 0x02 17 | swi 0x02 18 | swi 0x11 19 | -------------------------------------------------------------------------------- /Tests/SWI/301_readc.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of OS_ReadC (0x04) 2 | @ This test requires the user input to fully check the functionality of this SWI. 3 | 4 | .data 5 | 6 | Instruction_message: .asciz "Insert the following characters:\n1@* +;[_Ftñáçº\n" 7 | .equ Num_chars, 14 8 | 9 | .text 10 | .globl _start 11 | _start: 12 | mov r4, #0 13 | ldr r0, =Instruction_message 14 | swi 0x2 @ Print the instruction message 15 | loop: 16 | swi 0x4 @ Read the character 17 | swi 0x0 @ Print the character 18 | add r4, r4, #1 19 | cmp r4, #Num_chars 20 | bne loop 21 | swi 0x11 22 | 23 | .end 24 | -------------------------------------------------------------------------------- /Tests/SWI/302_readc_nonblock.s: -------------------------------------------------------------------------------- 1 | @ Test to check the handling of CPSR variations during the execution of a non-captured SWI such as OS_Byte 145 (0x6), which reads a char from the keyboard in a non-blocking fashion. 2 | @ If the behavior is properly captured, it should display the key pressed. 3 | @ In case of error, execution should end after ~3 seconds without showing which key was pressed. 4 | 5 | 6 | 7 | 8 | .data 9 | MSG: .asciz "Pulsa una tecla:" 10 | MSG2: .asciz "Has pulsado la tecla " 11 | 12 | .text 13 | .globl _start 14 | _start: 15 | ldr r0,=MSG 16 | swi 2 17 | ldr r4, =10000 @ Consume time in a loop 18 | mov r2, #0 19 | loop: @ Print the key that is pressed 20 | subs r4, r4, #1 21 | beq end 22 | mov r0, #145 23 | mov r1, #0 24 | swi 0x6 25 | bcs loop 26 | mov r4, r2 27 | ldr r0, =MSG2 28 | swi 0x2 29 | mov r0, r4 30 | swi 0x0 31 | end: 32 | swi 0x11 33 | 34 | .end 35 | 36 | -------------------------------------------------------------------------------- /Tests/SWI/401_enteros.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of OS_EnterOS (0x16) 2 | 3 | @ The program saves the value of SP, LR and CPSR in the var Context (in the last three words). 4 | @ After that, it overwrites the values of register R0 through R12 with the first thirteen words of the var Context. 5 | @ Then it uses the SWI 0x16 to enter Supervisor mode. 6 | @ Once you are in supervisor mode check register R0-12 maintain their values, registers SP, LR and CPSR have different values that the ones stored in the var Context, and that SPSR is equal to the stored CPSR. 7 | @ If there was an error it will notify the user with a message indicating the first register in which it detected the first error. 8 | @ If there was no error it should end with no message at the end. 9 | 10 | .data 11 | .align 2 12 | Context: .word 0x11111110, 0x22222221, 0xF5823992, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0, 0, 0 13 | Error_Msg: .asciz "There has been an error on the reg: " 14 | Error_Reg: .asciz "Rg00 Rg01 Rg02 Rg03 Rg04 Rg05 Rg06 Rg07 Rg08 Rg09 Rg10 Rg11 Rg12 RgSP RgLR CPSR" 15 | success_text: .asciz "Test ended without errors" 16 | 17 | 18 | 19 | .text 20 | .globl _start 21 | _start: 22 | @ Store in Context var current values of SP, LR, and CPSR 23 | ldr r0, =Context+52 @ Address of the 3 last words of Context 24 | stmia r0!, {sp, lr} 25 | mrs r1, cpsr 26 | str r1, [r0] 27 | @ Bring values from Context (regs 0 - 12) to user mode registers 28 | ldr r0, =Context 29 | ldm r0, {r0-r12} 30 | 31 | @ Enter OS Mode 32 | swi 0x16 33 | 34 | @ Check the values of registers 0 - r10 35 | stmdb sp!, {r11-r12} @ Store the value of R11 and R12 for preservation (we need 2 free registers to check the values) 36 | ldr r11, =Context 37 | ldr r12, [r11], #4 @ Bring r0 from Context, and advance pointer to r1 38 | cmp r0, r12 39 | movne r0, #0 40 | bne Error 41 | ldr r12, [r11], #4 @ Bring r1 from Context, and advance pointer to r2 42 | cmp r1, r12 43 | movne r0, #1 44 | bne Error 45 | ldr r12, [r11], #4 @ Bring r2 from Context, and advance pointer to r3 46 | cmp r2, r12 47 | movne r0, #2 48 | bne Error 49 | ldr r12, [r11], #4 @ Bring r3 from Context, and advance pointer to r4 50 | cmp r3, r12 51 | movne r0, #3 52 | bne Error 53 | ldr r12, [r11], #4 @ Bring r4 from Context, and advance pointer to r5 54 | cmp r4, r12 55 | movne r0, #4 56 | bne Error 57 | ldr r12, [r11], #4 @ Bring r5 from Context, and advance pointer to r6 58 | cmp r5, r12 59 | movne r0, #5 60 | bne Error 61 | ldr r12, [r11], #4 @ Bring r6 from Context, and advance pointer to r7 62 | cmp r6, r12 63 | movne r0, #6 64 | bne Error 65 | ldr r12, [r11], #4 @ Bring r7 from Context, and advance pointer to r8 66 | cmp r7, r12 67 | movne r0, #7 68 | bne Error 69 | ldr r12, [r11], #4 @ Bring r8 from Context, and advance pointer to r9 70 | cmp r8, r12 71 | movne r0, #8 72 | bne Error 73 | ldr r12, [r11], #4 @ Bring r9 from Context, and advance pointer to r10 74 | cmp r9, r12 75 | movne r0, #9 76 | bne Error 77 | ldr r12, [r11], #4 @ Bring r10 from Context, and advance pointer to r11 78 | cmp r10, r12 79 | movne r0, #10 80 | bne Error 81 | 82 | @ Check the values of registers r11 - r12 83 | mov r4, r11 84 | ldr r1, [r4], #4 @ Bring r11 from Context, and advance pointer to r12 85 | ldmia sp!, {r11-r12} @ We recover from the stack the stored values of R11 and R12 86 | cmp r11, r1 87 | movne r0, #11 88 | bne Error 89 | ldr r1, [r4], #4 @ Bring r12 from Context, and advance pointer to sp 90 | cmp r12, r1 91 | movne r0, #12 92 | bne Error 93 | 94 | @ Check the values of sp & lr, they need to be different 95 | ldr r1, [r4], #4 @ Bring SP from Context, and advance pointer to LR 96 | cmp r1, sp 97 | moveq r0, #13 98 | beq Error 99 | ldr r1, [r4], #4 @ Bring LR from Context, and advance pointer to CPSR 100 | cmp r1, lr 101 | moveq r0, #14 102 | beq Error 103 | @ Check the values of SPSR & CPSR 104 | ldr r1, [r4] @ Bring CPSR from Context 105 | @ Check the value of the CPSR is different to the one saved in Context 106 | mrs r2, cpsr 107 | cmp r1, r2 108 | moveq r0, #15 109 | beq Error 110 | @ Check the SPSR is equal to the old value of the CPSR 111 | mrs r2, spsr 112 | cmp r1, r2 113 | movne r0, #16 114 | bne Error 115 | NoError: 116 | ldr r0, =success_text 117 | swi 0x02 118 | swi 0x11 119 | 120 | @Print the error and exit the program 121 | Error: 122 | mov r1, #5 123 | mul r4, r0, r1 124 | ldr r1, =Error_Reg @ Load the string with the names of the registers 125 | add r4, r4, r1 @ Get the position of the reg name 126 | @ Print the error message 127 | ldr r0, =Error_Msg 128 | swi 0x2 @OS_Write0 129 | @ Print the name of the register that failed the check 130 | ldrb r0, [r4] 131 | swi 0x00 @OS_WriteC 132 | add r4, r4, #1 133 | ldrb r0, [r4] 134 | swi 0x00 135 | add r4, r4, #1 136 | ldrb r0, [r4] 137 | swi 0x00 138 | add r4, r4, #1 139 | ldrb r0, [r4] 140 | swi 0x00 141 | swi 0x11 142 | 143 | .end 144 | -------------------------------------------------------------------------------- /Tests/SWI/501_leaveos.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of OS_LeaveOS (0x7c) 2 | 3 | @ The program uses the SWI 0x16 to enter Supervisor mode. 4 | @ Then it saves the value of SP, LR and CPSR in the var Context (in the last three words). 5 | @ After that, it overwrites the values of register R0 through R12 with the first thirteen words of the var Context. 6 | @ Then it uses the swi 0x7c to return to user mode. 7 | @ Once you have returned to user mode check register R0-12 maintain their values, registers SP, LR and CPSR have different values that the ones stored in the var Context, and that SPSR is equal to the stored CPSR. 8 | @ If there was an error it will notify the user with a message indicating the first register in which it detected the first error. 9 | @ If there was no error it should end with no message at the end. 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | .data 18 | .align 2 19 | Context: .word 0x11111110, 0x22222221, 0xF5823992, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0, 0, 0 20 | Error_Msg: .asciz "There has been an error on the reg: " 21 | 22 | Error_Reg: .asciz "Rg00 Rg01 Rg02 Rg03 Rg04 Rg05 Rg06 Rg07 Rg08 Rg09 Rg10 Rg11 Rg12 RgSP RgLR CPSR" 23 | success_text: .asciz "Test ended without errors" 24 | 25 | 26 | .text 27 | .globl _start 28 | _start: 29 | @ Enter Supervisor mode 30 | swi 0x16 31 | 32 | @ Store in Context var current values of SP, LR, and CPSR 33 | ldr r0, =Context+52 @ Address of the 3 last words of Context 34 | stmia r0!, {sp, lr} 35 | mrs r1, cpsr 36 | str r1, [r0] 37 | @ Bring values from Context (regs 0 - 12) to user mode registers 38 | ldr r0, =Context 39 | ldm r0, {r0-r12} 40 | 41 | @ Leave Supervisor mode 42 | swi 0x7c 43 | 44 | @ Check the values of registers 0 - r10 45 | stmdb sp!, {r11-r12} @ Store the value of R11 and R12 for preservation (we need 2 free registers to check the values) 46 | ldr r11, =Context 47 | ldr r12, [r11], #4 @ Bring r0 from Context, and advance pointer to r1 48 | cmp r0, r12 49 | movne r0, #0 50 | bne Error 51 | ldr r12, [r11], #4 @ Bring r1 from Context, and advance pointer to r2 52 | cmp r1, r12 53 | movne r0, #1 54 | bne Error 55 | ldr r12, [r11], #4 @ Bring r2 from Context, and advance pointer to r3 56 | cmp r2, r12 57 | movne r0, #2 58 | bne Error 59 | ldr r12, [r11], #4 @ Bring r3 from Context, and advance pointer to r4 60 | cmp r3, r12 61 | movne r0, #3 62 | bne Error 63 | ldr r12, [r11], #4 @ Bring r4 from Context, and advance pointer to r5 64 | cmp r4, r12 65 | movne r0, #4 66 | bne Error 67 | ldr r12, [r11], #4 @ Bring r5 from Context, and advance pointer to r6 68 | cmp r5, r12 69 | movne r0, #5 70 | bne Error 71 | ldr r12, [r11], #4 @ Bring r6 from Context, and advance pointer to r7 72 | cmp r6, r12 73 | movne r0, #6 74 | bne Error 75 | ldr r12, [r11], #4 @ Bring r7 from Context, and advance pointer to r8 76 | cmp r7, r12 77 | movne r0, #7 78 | bne Error 79 | ldr r12, [r11], #4 @ Bring r8 from Context, and advance pointer to r9 80 | cmp r8, r12 81 | movne r0, #8 82 | bne Error 83 | ldr r12, [r11], #4 @ Bring r9 from Context, and advance pointer to r10 84 | cmp r9, r12 85 | movne r0, #9 86 | bne Error 87 | ldr r12, [r11], #4 @ Bring r10 from Context, and advance pointer to r11 88 | cmp r10, r12 89 | movne r0, #10 90 | bne Error 91 | 92 | @ Check the values of registers r11 - r12 93 | mov r0, r11 94 | ldr r1, [r0], #4 @ Bring r11 from Context, and advance pointer to r12 95 | ldmia sp!, {r11-r12} @ We recover from the stack the stored values of R11 and R12 96 | cmp r11, r1 97 | movne r0, #11 98 | bne Error 99 | ldr r1, [r0], #4 @ Bring r12 from Context, and advance pointer to sp 100 | cmp r12, r1 101 | movne r0, #12 102 | bne Error 103 | 104 | @ Check the values of sp & lr, they need to be different 105 | ldr r1, [r0], #4 @ Bring SP from Context, and advance pointer to LR 106 | cmp r1, sp 107 | moveq r0, #13 108 | beq Error 109 | ldr r1, [r0], #4 @ Bring LR from Context, and advance pointer to CPSR 110 | cmp r1, lr 111 | moveq r0, #14 112 | beq Error 113 | @ Check the values of SPSR & CPSR 114 | ldr r1, [r0] @ Bring CPSR from Context 115 | mrs r2, cpsr @ Check the value of the CPSR is different to the one saved in Context 116 | cmp r1, r2 117 | moveq r0, #15 118 | beq Error 119 | NoError: 120 | ldr r0, =success_text 121 | swi 0x02 122 | swi 0x11 123 | 124 | @Print the error and exit the program 125 | Error: 126 | mov r1, #5 127 | mul r4, r0, r1 128 | ldr r1, =Error_Reg @ Load the string with the names of the registers 129 | add r4, r4, r1 @ Get the position of the reg name 130 | @ Print the error message 131 | ldr r0, =Error_Msg 132 | swi 0x2 @OS_Write0 133 | @ Print the name of the register that failed the check 134 | ldrb r0, [r4] 135 | swi 0x00 @OS_WriteC 136 | add r4, r4, #1 137 | ldrb r0, [r4] 138 | swi 0x00 139 | add r4, r4, #1 140 | ldrb r0, [r4] 141 | swi 0x00 142 | add r4, r4, #1 143 | ldrb r0, [r4] 144 | swi 0x00 145 | swi 0x11 146 | 147 | .end 148 | -------------------------------------------------------------------------------- /Tests/SWI/601_convert_int.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of OS_ConvertInteger4 (0xDC) 2 | 3 | @ The program checks the results of the SWI is the expected and notifies the user if there has been an error or if it ended successfully. 4 | @ In r0 it should return the address it received in r1. 5 | @ In r1 it should return the next byte stored next to the string the SWI created. 6 | @ In r2 it should return the number of bytes written by the SWI. 7 | @ If there is an error it will notify the first register it detected an error. 8 | 9 | 10 | 11 | 12 | .data 13 | 14 | Result: .space 8 15 | success_text: .asciz "Test ended successfully.\n" 16 | error_text_r0: .asciz "Value in r0 different to expected.\n" 17 | error_text_r1: .asciz "Value in r1 different to expected.\n" 18 | error_text_r2: .asciz "Value in r2 different to expected.\n" 19 | 20 | .text 21 | .globl _start 22 | _start: 23 | mov r0, #15 24 | ldr r1, =Result 25 | mov r2, #8 26 | swi 0xDC @ OS_ConvertInteger4 27 | ldr r3, =Result 28 | cmp r0, r3 29 | bne error_r0 @ r0 should be the address passed to the SWI in r1 30 | add r3, r3, #2 31 | cmp r1, r3 32 | bne error_r1 @ r1 should be the pointer to the next byte after the saved string 33 | cmp r2, #6 34 | bne error_r2 @ r2 should be the number of bytes not used 35 | success: @ Prints a text notifying the test ended successfully 36 | ldr r0, =success_text 37 | swi 0x02 38 | swi 0x11 39 | error_r0: @ Prints a text notifying the error 40 | ldr r0, =error_text_r0 41 | swi 0x02 42 | swi 0x11 43 | error_r1: @ Prints a text notifying the error 44 | ldr r0, =error_text_r1 45 | swi 0x02 46 | swi 0x11 47 | error_r2: @ Prints a text notifying the error 48 | ldr r0, =error_text_r2 49 | swi 0x02 50 | swi 0x11 51 | 52 | .end 53 | -------------------------------------------------------------------------------- /Tests/SWI/701_hardware.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of OS_Hardware (0x7A) 2 | 3 | @ The program checks the results of the SWI is the expected and notifies the user if there has been an error or if it ended successfully. 4 | @ In r0 it should return the number associated with timer1. 5 | @ The values of r8 and r9 should be preserved after the execution of the SWI. 6 | @ If there is an error it will notify the first register it detected an error. 7 | 8 | 9 | 10 | 11 | 12 | .data 13 | success_text: .asciz "Test ended successfully.\n" 14 | error_text_r0: .asciz "Value in r0 different to expected.\n" 15 | error_text_r8: .asciz "Value in r8 different to expected.\n" 16 | error_text_r9: .asciz "Value in r9 different to expected.\n" 17 | 18 | .text 19 | .globl _start 20 | _start: 21 | mov r0, #1 @ timer1 22 | mov r8, #0 @ Call HAL routine 23 | mov r9, #13 @ HAL_TimerDevice 24 | swi 0x7a @ OS_Hardware 25 | cmp r0, #3 @ Should be the 3, the device number associated with timer1 26 | bne error_r0 27 | cmp r8, #0 @ The value in r8 should be preserved 28 | bne error_r8 29 | cmp r9, #13 @ The value in r9 should be preserved 30 | bne error_r9 31 | success: @ Prints a text notifying the test ended successfully 32 | ldr r0, =success_text 33 | swi 0x02 34 | swi 0x11 35 | error_r0: @ Prints a text notifying the error 36 | ldr r0, =error_text_r0 37 | swi 0x02 38 | swi 0x11 39 | error_r8: @ Prints a text notifying the error 40 | ldr r0, =error_text_r8 41 | swi 0x02 42 | swi 0x11 43 | error_r9: @ Prints a text notifying the error 44 | ldr r0, =error_text_r9 45 | swi 0x02 46 | swi 0x11 47 | 48 | .end 49 | -------------------------------------------------------------------------------- /Tests/SWI/801_claim_release.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of OS_ClaimDeviceVector (0x4B) and OS_ReleaseDeviceVector (0x4C) 2 | 3 | @ The program uses the system timer to check the correct functionality of the SWI calls. 4 | @ It claims a device vector for the interrupts of the timer. Then it programs the timer to generate an interrupt. 5 | @ The program idles in a loop until the interrupt is generated. Finally it releases the device vector and exits. 6 | 7 | 8 | .data 9 | Check: .word 0 10 | Device: .word 0 11 | success_text: .asciz "Interrupt detected" 12 | error_claim_text: .asciz "Register in claim not preserved" 13 | error_release_text: .asciz "Register in release not preserved" 14 | 15 | .equ STBASE, 0x20003000 16 | .equ STCS,0x00 17 | .equ STCL0,0X04 18 | .equ STC3,0X18 19 | .equ timer_int_bit, 0x08 20 | 21 | .equ WAIT_TIME, 0xD0000 @ Configuration of the timer wait time 22 | 23 | 24 | .text 25 | .global _start 26 | 27 | 28 | handler: 29 | stmdb sp!,{r4-r12,r14} 30 | mrs r10,cpsr 31 | 32 | @ Acknoledge interrupt 33 | ldr r0,=Device 34 | ldr r0, [r0,#STCS] 35 | mov r9, #timer_int_bit 36 | str r9, [r0,#STCS] 37 | 38 | @ Increase Check by 1 39 | ldr r2,=Check 40 | ldr r1,[r2] 41 | add r1,r1,#1 42 | str r1,[r2] 43 | 44 | @ Restore mode 45 | msr cpsr_c,r10 46 | ldmia sp!,{r4-r12,pc} @ Load the LR register in the PC to return 47 | 48 | 49 | 50 | _start: 51 | 52 | @ Obtain the ID of the timer in R0 53 | mov r0,#1 @ timer1 54 | mov r8,#0 55 | mov r9,#13 @HAL_TimerDevice 56 | swi 0x7a @ OS_Hardware 57 | mov r7,r0 @ Copy of the timer ID in R7 58 | 59 | @ Claim the Device vector 60 | ldr r1,=handler 61 | mov r2,#0 62 | mov r3,#0 63 | mov r4,#0 64 | swi 0x4B @ OS_ClaimDeviceVector 65 | 66 | @ Check registers r0-r4 are preserved 67 | cmp r7, r0 68 | bne error_claim 69 | ldr r5, =handler 70 | cmp r5, r1 71 | bne error_claim 72 | cmp r2, #0 73 | bne error_claim 74 | cmp r3, #0 75 | bne error_claim 76 | cmp r4, #0 77 | bne error_claim 78 | 79 | 80 | 81 | @ Maps the timer to memory 82 | mov r0, #13 83 | ldr r1, =STBASE 84 | mov r2, #0x100 85 | swi 0x68 @ OS_Memory 86 | @ Store the address of the timer 87 | ldr r0,=Device 88 | str r3,[r0] 89 | @ If there is a pending interrupt acknowledge it 90 | ldr r1, [r0,#STCS] 91 | ands r1, r1, #timer_int_bit 92 | strne r1, [r0,#STCS] 93 | 94 | 95 | @ Enables interrupts 96 | swi 0x13 @ OS_IntOn 97 | mov r8, #0 @ HAL 98 | mov r9, #1 @ HAL_IRQEnable 99 | mov r0, #0x3 @ irq of timer 100 | swi 0x7a @ OS_Hardware 101 | 102 | @ Timer counter initialization 103 | ldr r0,=Device 104 | ldr r0,[r0] 105 | swi 0x16 @EnterOS 106 | ldr r1, [r0,#STCL0] 107 | add r1, #WAIT_TIME 108 | str r1, [r0, #STC3] 109 | swi 0x7c @ OS_LeaveOS 110 | 111 | 112 | @ Wait for the interrupt 113 | ldr r0,=Check 114 | loop: 115 | @ Check if the value of the var has changed 116 | ldr r1,[r0] 117 | cmp r1,#1 118 | blt loop 119 | 120 | @ Disable interrupts 121 | mov r8,#0 122 | mov r9,#2 123 | mov r0,#0x3 124 | swi 0x7A @ OS_Hardware 125 | 126 | @ Release of the Device vector 127 | mov r0,r7 @ Recovery of the timer ID 128 | ldr r1,=handler 129 | mov r2,#0 130 | mov r3, #0 131 | mov r4, #0 132 | swi 0x4C @ OS_ReleaseDeviceVector 133 | 134 | @ Check registers r0-r4 are preserved 135 | cmp r7, r0 136 | bne error_release 137 | ldr r5, =handler 138 | cmp r5, r1 139 | bne error_release 140 | cmp r2, #0 141 | bne error_release 142 | cmp r3, #0 143 | bne error_release 144 | cmp r4, #0 145 | bne error_release 146 | 147 | @ Prints a text for confirmation 148 | ldr r0, =success_text 149 | swi 0x02 150 | 151 | mov r8, #0 152 | swi 0x11 153 | 154 | error_claim: 155 | ldr r0, =error_claim_text 156 | swi 0x02 157 | swi 0x11 158 | 159 | error_release: 160 | ldr r0, =error_release_text 161 | swi 0x02 162 | swi 0x11 163 | 164 | .end 165 | -------------------------------------------------------------------------------- /Tests/SWI/802_claim_without_release.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of OS_ClaimDeviceVector (0x4B) and OS_ReleaseDeviceVector (0x4C) 2 | 3 | @ The program uses the system timer to check the correct functionality of the SWI calls. 4 | @ It claims a device vector for the interrupts of the timer. Then it programs the timer to generate an interrupt. 5 | @ The program idles in a loop until the interrupt is generated. 6 | 7 | 8 | .data 9 | Check: .word 0 10 | Device: .word 0 11 | successful_text: .asciz "Interrupt detected" 12 | 13 | .equ STBASE, 0x20003000 14 | .equ STCS,0x00 15 | .equ STCL0,0X04 16 | .equ STC3,0X18 17 | 18 | .equ INTBASE, 0x2000b000 19 | .equ INTENIRQ1, 0x210 20 | 21 | .equ WAIT_TIME, 0x1000 @ Configuration of the timer wait time 22 | 23 | 24 | .text 25 | .global _start 26 | 27 | 28 | handler: 29 | stmdb sp!,{r4-r12,r14} 30 | mrs r10,cpsr 31 | @ Enter supervisor mode 32 | orr r0,r10,#3 33 | msr cpsr_c, r0 34 | 35 | ldr r0,=Device 36 | ldr r0,[r0] 37 | mov r9, #0x08 38 | str r9, [r0,#STCS] 39 | 40 | @ Increase Check by 1 41 | ldr r2,=Check 42 | ldr r1,[r2] 43 | add r1,r1,#1 44 | str r1,[r2] 45 | 46 | @ Restore mode 47 | msr cpsr_c,r10 48 | ldmia sp!,{r4-r12,pc} @ Load the LR register in the PC to return 49 | 50 | 51 | 52 | _start: 53 | 54 | @ Obtain the ID of the timer in R0 55 | mov r0,#1 @ timer1 56 | mov r8,#0 57 | mov r9,#13 @HAL_TimerDevice 58 | swi 0x7a @ OS_Hardware 59 | mov r7,r0 @ Copy of the timer ID in R7 60 | 61 | @ Claim the Device vector 62 | ldr r1,=handler 63 | mov r2,#0 64 | mov r3,#0 65 | mov r4,#0 66 | swi 0x4B @ OS_ClaimDeviceVector 67 | 68 | 69 | 70 | @ Maps the timer to memory 71 | mov r0, #13 72 | ldr r1, =STBASE 73 | mov r2, #0x100 74 | swi 0x68 @ OS_Memory 75 | @ Store the address of the timer 76 | ldr r0,=Device 77 | str r3,[r0] 78 | @ If there is a pending interrupt acknowledge it 79 | mov r1, #0x08 80 | ldr r1, [r0,#STCS] 81 | ands r1, r1, #0x08 82 | movne r1, #0x08 83 | strne r1, [r0,#STCS] 84 | 85 | 86 | @ Enables interrupts 87 | swi 0x13 @ OS_IntOn 88 | mov r8,#0 @ HAL 89 | mov r9,#1 @ HAL_IRQEnable 90 | mov r0, #0x3 @ irq of timer 91 | swi 0x7a @ OS_Hardware 92 | 93 | @ Timer counter initialization 94 | ldr r0,=Device 95 | ldr r0,[r0] 96 | swi 0x16 @EnterOS 97 | ldr r1, [r0,#STCL0] 98 | add r1, #WAIT_TIME 99 | str r1, [r0, #STC3] 100 | swi 0x7c @ OS_LeaveOS 101 | 102 | 103 | @ Wait for the interrupt 104 | ldr r0,=Check 105 | loop: 106 | @ Check if the value of the var has changed 107 | ldr r1,[r0] 108 | cmp r1,#1 109 | blt loop 110 | 111 | @ Disable interrupts 112 | mov r8,#0 113 | mov r9,#2 114 | mov r0,#0x3 115 | swi 0x7A @ OS_Hardware 116 | 117 | @ Prints a text for confirmation 118 | ldr r0, =successful_text 119 | swi 0x02 120 | 121 | mov r8, #0 122 | swi 0x11 123 | 124 | .end 125 | -------------------------------------------------------------------------------- /Tests/SWI/803_release_without_claim.s: -------------------------------------------------------------------------------- 1 | @ Test to check the behavior of OS_ClaimDeviceVector (0x4B) and OS_ReleaseDeviceVector (0x4C) 2 | 3 | @ The program uses the system timer to check the correct functionality of the SWI calls. 4 | @ It doesn't claim any device vector. Then it programs the timer to generate an interrupt. 5 | @ The program idles in a loop until the interrupt is generated. Finally it releases the device vector and exits. 6 | @ No interrupt should happen, and the program should stay in the infinite loop 7 | 8 | 9 | .data 10 | Check: .word 0 11 | Device: .word 0 12 | success_text: .asciz "Test NOT passed: unclaimed device has been released" 13 | 14 | .equ STBASE, 0x20003000 15 | .equ STCS,0x00 16 | 17 | .equ INTBASE, 0x2000b000 18 | .equ INTENIRQ1, 0x210 19 | 20 | .equ WAIT_TIME, 0x500000 @ Configuration of the timer wait time 21 | 22 | 23 | .text 24 | .global _start 25 | 26 | 27 | handler: 28 | stmdb sp!,{r4-r12,r14} 29 | mrs r10,cpsr 30 | 31 | @ Acknoledge interrupt 32 | ldr r0,=Device 33 | ldr r0,[r0] 34 | mov r9, #0x08 35 | str r9, [r0,#STCS] 36 | 37 | @ Increase Check by 1 38 | ldr r2,=Check 39 | ldr r1,[r2] 40 | add r1,r1,#1 41 | str r1,[r2] 42 | 43 | @ Restore mode 44 | msr cpsr_c,r10 45 | ldmia sp!,{r4-r12,pc} @ Load the LR register in the PC to return 46 | 47 | 48 | 49 | _start: 50 | 51 | @ Obtain the ID of the timer in R0 52 | mov r0,#1 @ timer1 53 | mov r8,#0 54 | mov r9,#13 @HAL_TimerDevice 55 | swi 0x7a @ OS_Hardware 56 | 57 | 58 | @ Release of the Device vector 59 | ldr r1,=handler 60 | mov r2,#0 61 | mov r3, #0 62 | mov r4, #0 63 | swi 0x4C @ OS_ReleaseDeviceVector 64 | 65 | @ Prints a text for confirmation 66 | ldr r0, =success_text 67 | swi 0x02 68 | 69 | mov r8, #0 70 | swi 0x11 71 | 72 | .end 73 | -------------------------------------------------------------------------------- /Tests/compileTests,feb: -------------------------------------------------------------------------------- 1 | | !UCDebug, ARM debugger for RISC OS. 2 | | https://github.com/fuentesp/UCDebug 3 | | Copyright (C) 2018 University of Cantabria 4 | | 5 | | !UCDebug was developed by the Computer Architecture and Technology 6 | | Group at the University of Cantabria. A comprehensive list of authors 7 | | can be found in the file AUTHORS.txt. 8 | | 9 | | You can reach the main developers at {fernando.vallejo, cristobal.camarero, 10 | | pablo.fuentes}@unican.es. 11 | | 12 | | This program is free software: you can redistribute it and/or modify 13 | | it under the terms of the GNU General Public License as published by 14 | | the Free Software Foundation, either version 3 of the License, or 15 | | (at your option) any later version. 16 | | 17 | | This program is distributed in the hope that it will be useful, 18 | | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | | GNU General Public License for more details. 21 | | 22 | | You should have received a copy of the GNU General Public License 23 | | along with this program. If not, see . 24 | 25 | set FormerFS 26 | if FormerFS="SDFS" then 27 | set aux_dir 28 | if aux_dir="" then set aux_dir "&" 29 | 30 | dir 31 | cdir o 32 | set FormerOpts 33 | set Wipe$Options ~C 34 | make 35 | wipe o 36 | set Wipe$Options 37 | if FormerFS="SDFS" then dir : else echo WARNING!!!: CSD may have changed 38 | -------------------------------------------------------------------------------- /Tests/documentation.txt: -------------------------------------------------------------------------------- 1 | These tests attempt to be a fail-safe mechanism for further development of the debugger code. Each test has to be run separately (or after another, depending on the functionality), and prints back a success message or gives an error description describing what happened. 2 | 3 | The tests are organized into 3 separate categories. However, all tests can be compiled at once through the "compile" Obey file (or alternatively, by using the 'make' command in a Task Window with the directory as CSD). Test should be run in increasing sequence number, since most build up on previous checkings, starting with SWI tests (s***) and following with Mode tests (mo***) and Reset tests (r***). Following this order lets the tester know more easily which functionality is not performing adequately. 4 | 5 | 6 | *** SWI tests *** 7 | 8 | -Test s001 9 | 10 | Tested functionality: SWI OS_ExitOS (0x11) 11 | Input: (None) 12 | Expected Output: program ends normally and the debugger shows the message "Program execution has finished" in the Console window. 13 | 14 | -Test s101 15 | 16 | Tested functionality: SWI OS_WriteC (0x00) 17 | Input: (None) 18 | Expected Output: program opens the I/O Console window and prints the following string: 1@* +;[_Ftñáçº 19 | 20 | -Test s201 21 | 22 | Tested functionality: SWI OS_Write0 (0x02) 23 | Input: (None) 24 | Expected Output: program opens the I/O Console window and prints the following string: 1@* +;[_Ftñáçº 25 | 26 | -Test s301 27 | 28 | Tested functionality: SWI OS_ReadC (0x04) 29 | Input: once the program is running, the user has to introduce the following characters: "@* +;[_Ftñáçº" 30 | Expected Output: program prints through the I/O Console window the characters inserted by the user. 31 | 32 | -Test s401 33 | 34 | Tested functionality: SWI OS_EnterOS (0x16) 35 | Input: (None) 36 | Expected Output: program prints the message "Test ended without errors" if no errors are detected; otherwise it shows "There has been an error on the reg:" followed by the name of the first register in which an error was found. 37 | 38 | -Test s501 39 | 40 | Tested functionality: SWI OS_LeaveOS (0x7c) 41 | Input: (None) 42 | Expected Output: program prints the message "Test ended without errors" if no errors are detected; otherwise it shows "There has been an error on the reg:" followed by the name of the first register in which an error was found. 43 | 44 | -Test s601 45 | 46 | Tested functionality: SWI OS_ConvertInteger4 (0xDC). This test checks the behavior of a simple non-captured SWI, to ensure the passing of arguments and results from the OS service is correctly performed. 47 | Input: (None) 48 | Expected Output: program prints the message "Test ended without errors" if no errors are detected; otherwise, it notifies the register whose returned value does not conform to the specifications. 49 | 50 | -Test s701 51 | 52 | Tested functionality: SWI OS_Hardware (0x7A) with option '0' (call HAL routine). This test checks the behavior of a non-captured SWI whose execution is known to cause errors when performed with the debugger handlers in place, therefore it verifies the correct restoration of the OS handlers. 53 | Input: (None) 54 | Expected Output: program prints the message "Test ended without errors" if no errors are detected. Otherwise, it displays the register whose value after execution does not correspond to a proper execution. If the OS handlers are not correctly restored, the execution of this test could also provoke a Data Abort within the debugger code (affecting address outside user scope). 55 | 56 | -Test s801 57 | 58 | Tested functionality: SWIs OS_ClaimDeviceVector (0x4B) & OS_ReleaseDeviceVector (0x4C) 59 | Input: (None) 60 | Expected Output: program prints the message "Interruption detected" if no errors are found. Otherwise, it will either print "Register in claim not preserved" or "Register in release not preserved" if any register used for the call to the SWIs OS_ClaimDeviceVector or OS_ReleaseDeviceVector, respectively, was not preserved after the call. The program can also get stuck in an infinite loop if no interrupts are detected; in that case, the execution needs to be forcefully halted through the 'stop' command. 61 | 62 | -Tests s802/s803 63 | 64 | Tested functionality: SWIs OS_ClaimDeviceVector (0x4B) & OS_ReleaseDeviceVector (0x4C) 65 | Input: these tests are expected to be run one after another, and then the second test (803) in a standalone fashion (e.g., after starting the debugger). 66 | Expected Output: test 802 prints the message "Interruption detected" if no errors are found, or continues executing an infinite loop otherwise. Test 803 should trigger a debugger error with the message "Device 3 has been released without claiming", either after loading and executing test 802 or working standalone. It can also print the message "Test NOT passed: unclaimed device has been released" if the debugger does not properly handle resetting the IRQ table. 67 | 68 | 69 | 70 | *** Mode tests *** 71 | 72 | - Tests mo001/mo101/mo201/mo301/mo401 73 | 74 | Tested functionality: preserving registers when entering a new processor execution mode. 75 | Input: (None) 76 | Expected Output: program prints the message "Test ended without errors" if no errors are detected. Otherwise, it displays the first register whose state does not match the expected outcome. 77 | 78 | - Tests mo002/mo102/mo202/mo302/mo402 79 | 80 | Tested functionality: preserving registers when exiting a new processor execution mode. 81 | Input: (None) 82 | Expected Output: program prints the message "Test ended without errors" if no errors are detected. Otherwise, it displays the first register whose state does not match the expected outcome. 83 | 84 | [These tests do not check the handling of entering and exiting SVC mode, since that was checked with the behavior of SWIs OS_EnterOS and OS_LeaveOS (tests s401/s501)] 85 | 86 | 87 | 88 | *** Reset tests *** 89 | 90 | - Tests r101/r102 91 | 92 | Tested functionality: reset of CPSR state when loading a new program. 93 | Input: these tests are expected to be loaded and run one after another. 94 | Expected Output: second test (r102) prints the message "Test ended without errors" if the CPSR was properly reset. In any other case, the program displays the first CPSR flag whose value differs from its default. 95 | 96 | - Tests r200/r201/r203/r204/r205/r206 97 | 98 | Tested functionality: reset of CPU execution mode when loading a new program. 99 | Input: first a test r20X is loaded and run, and then test r200 is used. 100 | Expected Output: the first test run (r201/r202/...) does not give any output. Program r200 prints the message "Test ended sucessfully" if no errors are detected. Otherwise, it will print a message warning that the CPU execution mode was not reset to the default "User" execution mode. 101 | 102 | - Tests r301/r302 103 | 104 | Tested functionality: reset of stack pointers when loading a new program. 105 | Input: these tests are expected to be loaded and run one after another. 106 | Expected Output: program prints the message "Test ended successfully" if the stack of all processor execution modes was properly reset. If not, it will print the name of the first tested execution mode whose stack pointer was not adequately reset. It can also show an error message if the auxiliary file (used to communicate between the 2 programs the correct stack pointer value at the beginning) cannot be opened. 107 | 108 | 109 | -------------------------------------------------------------------------------- /c/CodeWin: -------------------------------------------------------------------------------- 1 | /* 2 | * !UCDebug, ARM debugger for RISC OS. 3 | * https://github.com/fuentesp/UCDebug 4 | * Copyright (C) 2018 University of Cantabria 5 | * 6 | * !UCDebug was developed by the Computer Architecture and Technology 7 | * Group at the University of Cantabria. A comprehensive list of authors 8 | * can be found in the file AUTHORS.txt. 9 | * 10 | * You can reach the main developers at {fernando.vallejo, cristobal.camarero, 11 | * pablo.fuentes}@unican.es. 12 | * 13 | * This program is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | */ 26 | 27 | #include "oslib/wimp.h" 28 | #include "oslib/wimpspriteop.h" 29 | #include "oslib/debugger.h" 30 | 31 | /* Added C libraries to avoid warnings due to declaration incompatibilities */ 32 | #include 33 | #include 34 | #include 35 | 36 | #include "ibar.h" 37 | #include "CodeWin.h" 38 | #include "ConsWin.h" 39 | 40 | /*Private Vars*/ 41 | struct CodeType *CodeIcons; 42 | 43 | /* Aux Functions */ 44 | 45 | /* ColorPC receives a handle to the Code view window, the start address and the number 46 | * of instructions to print, and updates the icon from the current PC to highlight it 47 | * in a different color */ 48 | void ColorPC(wimp_w CodeWin, int StartAddr, int NumInstr) { 49 | int PC; 50 | int Line; 51 | 52 | PC = CurContext.Regs[15]; 53 | Line = (PC - StartAddr) / 4; 54 | 55 | if ((Line >= 0) && (Line < NumInstr)) { 56 | ChTextFGColour(CodeWin, CodeIcons[Line].I_Addr, PC_FG_Colour); 57 | ChTextBGColour(CodeWin, CodeIcons[Line].I_Addr, PC_BG_Colour); 58 | ChTextFGColour(CodeWin, CodeIcons[Line].I_Code, PC_FG_Colour); 59 | ChTextBGColour(CodeWin, CodeIcons[Line].I_Code, PC_BG_Colour); 60 | ChTextFGColour(CodeWin, CodeIcons[Line].I_Disem, PC_FG_Colour); 61 | ChTextBGColour(CodeWin, CodeIcons[Line].I_Disem, PC_BG_Colour); 62 | } 63 | } 64 | 65 | /* ColorBrk receives a handle to the Code view window, the start address and the number 66 | * of instructions to print, and updates the icons from those lines with a breakpoint 67 | * set to highlight them in a different color. */ 68 | void ColorBrk(wimp_w CodeWin, int StartAddr, int NumInstr) { 69 | int i, Brk; 70 | int Line; 71 | 72 | for (i = 0; i < CurNumBr; i++) { 73 | Brk = BrkPtList[i]; 74 | Line = (Brk - StartAddr) / 4; 75 | 76 | if ((Line >= 0) && (Line < NumInstr)) { 77 | ChTextFGColour(CodeWin, CodeIcons[Line].I_Addr, Brk_FG_Colour); 78 | ChTextBGColour(CodeWin, CodeIcons[Line].I_Addr, Brk_BG_Colour); 79 | ChTextFGColour(CodeWin, CodeIcons[Line].I_Code, Brk_FG_Colour); 80 | ChTextBGColour(CodeWin, CodeIcons[Line].I_Code, Brk_BG_Colour); 81 | ChTextFGColour(CodeWin, CodeIcons[Line].I_Disem, Brk_FG_Colour); 82 | ChTextBGColour(CodeWin, CodeIcons[Line].I_Disem, Brk_BG_Colour); 83 | } 84 | } 85 | } 86 | 87 | /* Public Functions */ 88 | 89 | /* Create a Code view window, showing the instructions currently loaded 90 | * in memory and their interpretation */ 91 | wimp_w CodeWinCreate(int StartAddr, int NumInstr, int PosX, int PosY) { 92 | /* Local function vars */ 93 | wimp_w CodeWin; 94 | int i, size, Addr, Code, *t_addr; 95 | char *aux; 96 | 97 | if (NumInstr < VisRows) NumInstr = VisRows; 98 | snprintf(CodeWinTitle, WinTitleSize, CodeWinName); 99 | CodeWin = open_window(CodeWinTitle, CodeWinSizeX, NumInstr * LinSizeY, PosX, PosY, 100 | CodeWinSizeX, CodeWinSizeY, 0, 0, 0x06); 101 | CodeIcons = malloc(sizeof(struct CodeType) * NumInstr); 102 | Addr = StartAddr; 103 | 104 | for (i = 0; i < NumInstr; i++) { 105 | /* Address */ 106 | snprintf(CodeIcons[i].T_Addr, PrintedWordSize + 1, "0x%08X", Addr); 107 | /* Instruction Code*/ 108 | t_addr = (int *) Addr; 109 | Code = *t_addr; 110 | snprintf(CodeIcons[i].T_Code, PrintedWordSize + 1, "0x%08X", Code); 111 | /*Instruction Disassembly */ 112 | debugger_disassemble(Code, t_addr, &aux, &size); 113 | snprintf(CodeIcons[i].T_Disem, DisasInstrSize + 1, aux); 114 | CodeIcons[i].T_Disem[DisasInstrSize] = 0; // Append null char to ensure end of string 115 | Addr = Addr + 4; 116 | 117 | CodeIcons[i].I_Addr = TextIconCreate(CodeWin, 10, 5 + LinSizeY * i, 118 | CharSizeX * 10, CharSizeY, CodeIcons[i].T_Addr, PrintedWordSize + 1, CodeIcons[i].V_Addr); 119 | ChTextBGColour(CodeWin, CodeIcons[i].I_Addr, wimp_COLOUR_LIGHT_GREY); 120 | CodeIcons[i].I_Code = TextIconCreate(CodeWin, 20 + CharSizeX * 10, 121 | 5 + LinSizeY * i, CharSizeX * 10, CharSizeY, CodeIcons[i].T_Code, PrintedWordSize + 1, CodeIcons[i].V_Code); 122 | ChTextBGColour(CodeWin, CodeIcons[i].I_Code, wimp_COLOUR_LIGHT_GREY); 123 | CodeIcons[i].I_Disem = TextIconCreate(CodeWin, 30 + CharSizeX * 20, 124 | 5 + LinSizeY * i, CharSizeX * 40, CharSizeY, CodeIcons[i].T_Disem, DisasInstrSize + 1, CodeIcons[i].V_Disem); 125 | ChTextBGColour(CodeWin, CodeIcons[i].I_Disem, wimp_COLOUR_LIGHT_GREY); 126 | } 127 | 128 | return CodeWin; 129 | } 130 | 131 | /* Update the Code view window */ 132 | void CodeWinRedraw(wimp_w CodeWin, int StartAddr, int NumInstr) { 133 | int i, size, Addr, Code, *t_addr; 134 | char *aux; 135 | 136 | if (NumInstr < VisRows) NumInstr = VisRows; 137 | Addr = StartAddr; 138 | 139 | for (i = 0; i < NumInstr; i++) { 140 | /*Address*/ 141 | snprintf(CodeIcons[i].T_Addr, PrintedWordSize + 1, "0x%08X", Addr); 142 | ChTextBGColour(CodeWin, CodeIcons[i].I_Addr, wimp_COLOUR_LIGHT_GREY); 143 | /*Instruction Code */ 144 | t_addr = (int *) Addr; 145 | Code = *t_addr; 146 | snprintf(CodeIcons[i].T_Code, PrintedWordSize + 1, "0x%08X", Code); 147 | ChTextBGColour(CodeWin, CodeIcons[i].I_Code, wimp_COLOUR_LIGHT_GREY); 148 | /* Instruction Disassembly */ 149 | debugger_disassemble(Code, t_addr, &aux, &size); 150 | snprintf(CodeIcons[i].T_Disem, DisasInstrSize + 1, aux); 151 | CodeIcons[i].T_Disem[DisasInstrSize] = 0; // Append null char to ensure end of string 152 | Addr = Addr + 4; 153 | ChTextBGColour(CodeWin, CodeIcons[i].I_Disem, wimp_COLOUR_LIGHT_GREY); 154 | } 155 | 156 | /* Highlight the PC and breakpoint instructions */ 157 | ColorPC(CodeWin, StartAddr, NumInstr); 158 | ColorBrk(CodeWin, StartAddr, NumInstr); 159 | 160 | /* Redraw window */ 161 | UpdateWindow(CodeWin); 162 | 163 | } 164 | 165 | 166 | /* Free all structures corresponding to the Code window */ 167 | void CodeWinTerminate() { 168 | free(CodeIcons); 169 | } 170 | -------------------------------------------------------------------------------- /c/ConsWin: -------------------------------------------------------------------------------- 1 | /* 2 | * !UCDebug, ARM debugger for RISC OS. 3 | * https://github.com/fuentesp/UCDebug 4 | * Copyright (C) 2018 University of Cantabria 5 | * 6 | * !UCDebug was developed by the Computer Architecture and Technology 7 | * Group at the University of Cantabria. A comprehensive list of authors 8 | * can be found in the file AUTHORS.txt. 9 | * 10 | * You can reach the main developers at {fernando.vallejo, cristobal.camarero, 11 | * pablo.fuentes}@unican.es. 12 | * 13 | * This program is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | */ 26 | 27 | #include "oslib/wimp.h" 28 | #include "oslib/wimpspriteop.h" 29 | #include 30 | /* Added C libraries to avoid warnings */ 31 | #include 32 | #include 33 | 34 | #include "ibar.h" 35 | #include "main.h" 36 | #include "ConsWin.h" 37 | #include "Interpreter.h" 38 | 39 | /*Private Types*/ 40 | struct ConsType { 41 | wimp_i I_Lines[ConsLinTot - 1]; 42 | wimp_i I_Prompt; 43 | wimp_i I_LinInp; 44 | char T_Lines[ConsLinTot - 1][ConsLinSize + 1]; 45 | char T_Prompt[PromptSize + 1]; 46 | char T_LinInp[ConsLinSize - PromptSize + 1]; 47 | char V_Lines[ConsLinTot - 1][ValStrSize + 1]; 48 | char V_Prompt[ValStrSize + 1]; 49 | char V_LinInp[ValStrSize + 1]; 50 | }; 51 | 52 | struct UsrConsType { 53 | wimp_i I_Lines[NumLinUsrCon]; 54 | char T_Lines[NumLinUsrCon][NumColUsrCon + 1]; 55 | char V_Lines[NumLinUsrCon][ValStrSize + 1]; 56 | }; 57 | 58 | /*Private Vars*/ 59 | struct ConsType Console; 60 | struct UsrConsType UsrCons; 61 | char CommandBuffer[ComBufNumEntries][ConsLinSize + 1]; 62 | char PendingCommandBackup[ConsLinSize + 1]; 63 | int P_Buffer; 64 | char CurPrompt[PromptSize + 1] = Prompt; 65 | int UsrCursor; 66 | 67 | /* ConsWinCreate opens a Console view window */ 68 | wimp_w ConsWinCreate(int PosX, int PosY) { 69 | /* Function vars */ 70 | wimp_w ConsWin; 71 | int i; 72 | 73 | /* Initialize the command buffer */ 74 | for (i = 0; i < ComBufNumEntries; i++) { 75 | snprintf(CommandBuffer[i], ConsLinSize + 1, ""); 76 | } 77 | P_Buffer = 0; 78 | 79 | snprintf(ConsWinTitle, WinTitleSize, "%s - v%s", ConsWinName, AppVersion); 80 | ConsWin = open_window(ConsWinTitle, ConsWinSizeX, ConsLinTot * LinSizeY, PosX, PosY, 81 | ConsWinSizeX, ConsWinSizeY, 0, (ConsLinTot - ConsLinVis) * LinSizeY, 0x16); 82 | 83 | for (i = 0; i < ConsLinTot - 1; i++) { 84 | snprintf(Console.T_Lines[i], ConsLinSize + 1, ""); 85 | Console.I_Lines[i] = TextIconCreate(ConsWin, 10, 5 + LinSizeY * i, 86 | CharSizeX * ConsLinSize, CharSizeY, Console.T_Lines[i], ConsLinSize + 1, Console.V_Lines[i]); 87 | } 88 | 89 | /* Define prompt icon */ 90 | snprintf(Console.T_Prompt, PromptSize + 1, CurPrompt); 91 | Console.I_Prompt = TextIconCreate(ConsWin, 10, 5 + LinSizeY * (ConsLinTot - 1), 92 | CharSizeX * PromptSize, CharSizeY, Console.T_Prompt, PromptSize + 1, Console.V_Prompt); 93 | 94 | snprintf(Console.T_LinInp, ConsLinSize - PromptSize + 1, ""); 95 | Console.I_LinInp = TextIconCreate(ConsWin, 10 + CharSizeX * PromptSize, 5 + LinSizeY * (ConsLinTot - 1), 96 | CharSizeX * (ConsLinSize - PromptSize), CharSizeY, Console.T_LinInp, ConsLinSize - PromptSize, Console.V_LinInp); 97 | wimp_set_icon_state(ConsWin, Console.I_LinInp, wimp_BUTTON_WRITABLE << wimp_ICON_BUTTON_TYPE_SHIFT, 98 | wimp_ICON_BUTTON_TYPE); 99 | wimp_set_caret_position(ConsWin, Console.I_LinInp, 94, -3200, 34, 0); /* Place prompt at the beginning */ 100 | return ConsWin; 101 | } 102 | 103 | /* ConsEnterKey is called when the Enter key has been pressed, and analyzes the input 104 | * command. */ 105 | void ConsEnterKey(wimp_w ConsWin) { 106 | int i; 107 | char line[ConsLinSize + 1]; 108 | 109 | /* First scroll the command view */ 110 | for (i = 0; i < ConsLinTot - 2; i++) { 111 | snprintf(Console.T_Lines[i], ConsLinSize + 1, "%s", Console.T_Lines[i + 1]); 112 | } 113 | 114 | /* Copy the input to the command buffer, unless line is empty or same as previous. 115 | * First, initialize the command buffer. */ 116 | if ((strcmp(Console.T_LinInp, "") != 0) 117 | && (strcmp(CommandBuffer[0], Console.T_LinInp) != 0)) { 118 | for (i = ComBufNumEntries - 1; i > 0; i--) { 119 | strcpy(CommandBuffer[i], CommandBuffer[i - 1]); 120 | } 121 | snprintf(CommandBuffer[0], ConsLinSize + 1, "%s", Console.T_LinInp); 122 | } 123 | P_Buffer = 0; 124 | 125 | /* Copy input, clear prompt line and call CLI */ 126 | snprintf(Console.T_Lines[ConsLinTot - 2], ConsLinSize + 1, "%s%s", Console.T_Prompt, Console.T_LinInp); 127 | snprintf(line, ConsLinSize + 1, "%s", Console.T_LinInp); 128 | snprintf(Console.T_LinInp, ConsLinSize + 1, ""); 129 | wimp_set_caret_position(ConsWin, Console.I_LinInp, 94, -3200, 34, 0); 130 | UpdateWindow(ConsWin); 131 | interpreter(line); 132 | 133 | /* Write a new prompt, placing caret at the beginning of the line */ 134 | snprintf(Console.T_Prompt, PromptSize + 1, CurPrompt); 135 | wimp_set_caret_position(ConsWin, Console.I_LinInp, 94, -3200, 34, 0); 136 | 137 | /* Redraw window */ 138 | ResetWindow(ConsWin, -1, -1, -1, -1, 0, ConsLinTot * LinSizeY - ConsWinSizeY, (wimp_w) 0); 139 | } 140 | 141 | /* Activate the command window to be ready to receive characters */ 142 | void ActivateCons(wimp_w ConsWin) { 143 | int lineSize; 144 | 145 | lineSize = strlen(Console.T_LinInp); 146 | wimp_set_caret_position(ConsWin, Console.I_LinInp, 94 + 18 * lineSize, -3200, 34, 147 | lineSize); 148 | } 149 | 150 | /* If the "Up" key is pressed, retrieve command from the command buffer */ 151 | void ConsUpKey(wimp_w ConsWin) { 152 | int lineSize; 153 | 154 | if (P_Buffer == 0) /* Store current command line in a backup var */ 155 | strcpy(PendingCommandBackup, Console.T_LinInp); 156 | 157 | if ((P_Buffer < ComBufNumEntries) && (strcmp(CommandBuffer[P_Buffer], "") != 0)) { 158 | /* Change command line */ 159 | strcpy(Console.T_LinInp, CommandBuffer[P_Buffer]); 160 | lineSize = strlen(Console.T_LinInp); 161 | wimp_set_caret_position(ConsWin, Console.I_LinInp, 94 + 18 * lineSize, -3200, 34, 162 | lineSize); 163 | 164 | /* Redraw window */ 165 | UpdateWindow(ConsWin); 166 | 167 | /* Update position within the buffer */ 168 | P_Buffer++; 169 | } 170 | } 171 | 172 | /* If the "Down" key is pressed, retrieve next command in the command buffer (this only 173 | * has effect if already traversing the command buffer). */ 174 | void ConsDownKey(wimp_w ConsWin) { 175 | int lineSize; 176 | 177 | if (P_Buffer > 0) { 178 | if (P_Buffer == 1) { 179 | /* If P_Buffer is 1 (last command in buffer), retrieve the pending command */ 180 | strcpy(Console.T_LinInp, PendingCommandBackup); 181 | } else { 182 | /* Change command line, only if current command has already been retrieved from 183 | * buffer. */ 184 | strcpy(Console.T_LinInp, CommandBuffer[P_Buffer - 2]); 185 | } 186 | 187 | lineSize = strlen(Console.T_LinInp); 188 | wimp_set_caret_position(ConsWin, Console.I_LinInp, 94 + 18 * lineSize, -3200, 34, 189 | lineSize); 190 | 191 | /* Redraw window */ 192 | UpdateWindow(ConsWin); 193 | 194 | /* Update position within the buffer */ 195 | P_Buffer--; 196 | } 197 | } 198 | 199 | /* If the "Escape" key is pressed, clear the current command in the command line. */ 200 | void ConsEscapeKey(wimp_w ConsWin) { 201 | P_Buffer = 0; // Reset from traversing the command buffer 202 | snprintf(PendingCommandBackup, ConsLinSize + 1, ""); // Clear pending command 203 | snprintf(Console.T_LinInp, ConsLinSize + 1, ""); // Clear current command 204 | int lineSize = strlen(Console.T_LinInp); 205 | wimp_set_caret_position(ConsWin, Console.I_LinInp, 94 + 18 * lineSize, -3200, 34, 206 | lineSize); 207 | UpdateWindow(ConsWin); // Clear the command line by forcing the redrawal of the window 208 | ResetWindow(ConsWin, -1, -1, -1, -1, 0, ConsLinTot * LinSizeY - ConsWinSizeY, (wimp_w) 0); // Redraw the window 209 | } 210 | 211 | /* Gains the input focus to the Console window (useful to be called from outside to get focus) */ 212 | void ConsSetActive(wimp_w ConsWin) { 213 | wimp_set_caret_position(ConsWin, Console.I_LinInp, 94, -3200, 34, 0); 214 | } 215 | 216 | /* ConsWrite prints in the Console window a given message (used for warnings and to 217 | * output requested info). This function does not alter the current command being input */ 218 | void ConsWrite(wimp_w ConsWin, char *text) { 219 | int i; 220 | 221 | /* First scroll the command view */ 222 | for (i = 0; i < ConsLinTot - 2; i++) { 223 | strcpy(Console.T_Lines[i], Console.T_Lines[i + 1]); 224 | } 225 | 226 | /* Copy the given text in the last line */ 227 | snprintf(Console.T_Lines[ConsLinTot - 2], ConsLinSize + 1, "%s", text); 228 | 229 | /* Redraw window */ 230 | UpdateWindow(ConsWin); 231 | 232 | } 233 | 234 | /* Function to set the command prompt to RUN mode (small workaround to print RUN when 235 | the go command is executed) */ 236 | void SetPrompt(char prompt[]) { 237 | snprintf(CurPrompt, PromptSize + 1, prompt); 238 | snprintf(Console.T_Prompt, PromptSize + 1, CurPrompt); 239 | UpdateWindow(ConsWin); 240 | } 241 | 242 | /* UsrWinCreate generates a User Console window, used to interact with the user during 243 | * the execution of the user program through the corresponding SWIs. */ 244 | wimp_w UsrWinCreate(int PosX, int PosY) { 245 | wimp_w UsrWin; 246 | wimp_icon_create icon_definition; 247 | int i; 248 | 249 | snprintf(UsrWinTitle, WinTitleSize, UsrWinName); 250 | UsrWin = open_window(UsrWinTitle, NumColUsrCon * CharSizeX, NumLinUsrCon * LinSizeY, 251 | PosX, PosY, UsrConsWinSizeX, UsrConsWinSizeY, 0, 252 | (NumLinUsrCon - 10) * LinSizeY, 0x01E); 253 | 254 | /* Initialize the window with empty lines */ 255 | for (i = 0; i < NumLinUsrCon; i++) { 256 | snprintf(UsrCons.T_Lines[i], ConsLinSize + 1, ""); 257 | UsrCons.I_Lines[i] = TextIconCreate(UsrWin, 10, 5 + LinSizeY * i, 258 | CharSizeX * NumColUsrCon, CharSizeY, UsrCons.T_Lines[i], ConsLinSize + 1, UsrCons.V_Lines[i]); 259 | } 260 | UsrCursor = 0; 261 | WindowStates[UsrWinOffset] = wss_ON_SCREEN; 262 | 263 | return UsrWin; 264 | } 265 | 266 | /* UsrScroll scrolls one line the User Console window */ 267 | void UsrScroll() { 268 | int i; 269 | for (i = 0; i < NumLinUsrCon - 1; i++) 270 | strcpy(UsrCons.T_Lines[i], UsrCons.T_Lines[i + 1]); 271 | UsrCursor = 0; /* Reset cursor to beginning of line */ 272 | } 273 | 274 | /* UsrWrite writes at the last line of the User Console. It does not print an End-of-Line 275 | * until the character 0x0A is read. Non-printable characters (below 0x20) are 276 | * represented with a dot. */ 277 | void UsrWrite(wimp_w UsrWin, char *text) { 278 | int i, len = strlen(text); 279 | char c; 280 | 281 | for (i = 0; i < len; i++) { 282 | c = text[i]; 283 | if ((c == (char) 0x0A) || (UsrCursor == NumColUsrCon)) { 284 | UsrCons.T_Lines[NumLinUsrCon - 1][UsrCursor] = (char) 0x00; 285 | UsrScroll(); 286 | } 287 | if (c != (char) 0x0A) { 288 | if (c < 0x20) c = '.'; 289 | UsrCons.T_Lines[NumLinUsrCon - 1][UsrCursor] = c; 290 | UsrCursor++; 291 | } 292 | } 293 | UsrCons.T_Lines[NumLinUsrCon - 1][UsrCursor] = (char) 0x00; 294 | 295 | /* Redraw window */ 296 | UpdateWindow(UsrWin); 297 | /* Bring I/O window to foreground */ 298 | ResetWindow(UsrWin, -1, -1, -1, -1, -1, -1, (wimp_w) -1); 299 | } 300 | -------------------------------------------------------------------------------- /c/DataWin: -------------------------------------------------------------------------------- 1 | /* 2 | * !UCDebug, ARM debugger for RISC OS. 3 | * https://github.com/fuentesp/UCDebug 4 | * Copyright (C) 2018 University of Cantabria 5 | * 6 | * !UCDebug was developed by the Computer Architecture and Technology 7 | * Group at the University of Cantabria. A comprehensive list of authors 8 | * can be found in the file AUTHORS.txt. 9 | * 10 | * You can reach the main developers at {fernando.vallejo, cristobal.camarero, 11 | * pablo.fuentes}@unican.es. 12 | * 13 | * This program is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | */ 26 | 27 | #include "oslib/wimp.h" 28 | #include "oslib/wimpspriteop.h" 29 | /* Added C libraries to avoid warnings */ 30 | #include 31 | #include 32 | #include 33 | 34 | #include "ibar.h" 35 | #include "DataWin.h" 36 | 37 | /* Private Vars */ 38 | struct DataType *DataIcons; 39 | 40 | /* DataWinCreate opens a Memory view window */ 41 | wimp_w DataWinCreate(int startAddr, int numAddrs, int displayType, int PosX, int PosY) { 42 | wimp_w DataWin; 43 | int i; 44 | 45 | if (numAddrs < VisRows) numAddrs = VisRows; 46 | snprintf(DataWinTitle, WinTitleSize, DataWinName); 47 | DataWin = open_window(DataWinTitle, DataWinSizeX, numAddrs * LinSizeY, PosX, PosY, 48 | DataWinSizeX, DataWinSizeY, 0, 0, 0x06); 49 | DataIcons = malloc(sizeof(struct DataType) * numAddrs); 50 | 51 | DataWinRedraw(DataWin, startAddr, numAddrs, displayType); 52 | 53 | /* Create the icons with the memory view (address, values, and ASCII notation) */ 54 | for (i = 0; i < numAddrs; i++) { 55 | DataIcons[i].I_Addr = TextIconCreate(DataWin, 10, 5 + LinSizeY * i, 56 | CharSizeX * (PrintedWordSize - 1), CharSizeY, DataIcons[i].T_Addr, PrintedWordSize + 1, DataIcons[i].V_Addr); 57 | ChTextBGColour(DataWin, DataIcons[i].I_Addr, wimp_COLOUR_LIGHT_GREY); 58 | DataIcons[i].I_Data = TextIconCreate(DataWin, 59 | 20 + CharSizeX * (PrintedWordSize - 1), 5 + LinSizeY * i, 60 | CharSizeX * (MemHexBlockSize - 2), CharSizeY, DataIcons[i].T_Data, MemHexBlockSize, DataIcons[i].V_Data); 61 | ChTextBGColour(DataWin, DataIcons[i].I_Data, wimp_COLOUR_LIGHT_GREY); 62 | DataIcons[i].I_ASCII = TextIconCreate(DataWin, 63 | 30 + CharSizeX * (PrintedWordSize + MemHexBlockSize - 3), 64 | 5 + LinSizeY * i, CharSizeX * (MemAsciiBlockSize - 2), CharSizeY, 65 | DataIcons[i].T_ASCII, MemAsciiBlockSize, DataIcons[i].V_ASCII); 66 | ChTextBGColour(DataWin, DataIcons[i].I_ASCII, wimp_COLOUR_LIGHT_GREY); 67 | } 68 | 69 | return DataWin; 70 | } 71 | 72 | /* DataWinRedraw updates the Memory view window */ 73 | void DataWinRedraw(wimp_w DataWin, int startAddr, int numAddrs, int displayType) { 74 | int i, j, k, t, data, addr; 75 | char Aux[MemAsciiBlockSize]; 76 | 77 | if (numAddrs < VisRows) numAddrs = VisRows; 78 | 79 | addr = startAddr; 80 | for (i = 0; i < numAddrs; i++) { 81 | /* Address */ 82 | snprintf(DataIcons[i].T_Addr, PrintedWordSize + 1, "0x%08X", addr); 83 | /* Data is displayed in two sets: in hex notation, and in ASCII format */ 84 | snprintf(DataIcons[i].T_Data, MemHexBlockSize, ""); 85 | snprintf(DataIcons[i].T_ASCII, MemAsciiBlockSize, ""); 86 | for (j = 0; j < 4; j++) { 87 | /* Pick up data and increase pointer */ 88 | data = *(int *) addr; 89 | addr += 4; 90 | switch (displayType) { 91 | case 0: /* Display in words */ 92 | snprintf(Aux, sizeof(Aux), "%08X", data); 93 | strncat(DataIcons[i].T_Data, Aux, 94 | MemHexBlockSize - 1 - strlen(DataIcons[i].T_Data)); 95 | if (j < 3) strncat(DataIcons[i].T_Data, " ", MemHexBlockSize - 1); 96 | break; 97 | case 1: /* Display in half-words */ 98 | snprintf(Aux, sizeof(Aux), "%04X %04X", (data & 0x0FFFF), 99 | ((data >> 16) & 0x0FFFF)); 100 | strncat(DataIcons[i].T_Data, Aux, 101 | MemHexBlockSize - 1 - strlen(DataIcons[i].T_Data)); 102 | if (j < 3) strncat(DataIcons[i].T_Data, " ", MemHexBlockSize - 1); 103 | break; 104 | case 2: /* Display in bytes */ 105 | snprintf(Aux, sizeof(Aux), "%02X %02X %02X %02X", data & 0x0FF, 106 | (data >> 8) & 0x0FF, (data >> 16) & 0x0FF, 107 | (data >> 24) & 0x0FF); 108 | strncat(DataIcons[i].T_Data, Aux, 109 | MemHexBlockSize - 1 - strlen(DataIcons[i].T_Data)); 110 | if (j < 3) strncat(DataIcons[i].T_Data, " ", MemHexBlockSize - 1); 111 | break; 112 | } 113 | /* ASCII representation of the memory values */ 114 | for (k = 0; k < 4; k++) { 115 | t = (data >> 8 * k) & 0x0FF; 116 | if ((t < 32) || (t > 127)) 117 | Aux[k] = '.'; 118 | else 119 | Aux[k] = (char) t; 120 | } 121 | Aux[4] = '\0'; 122 | strncat(DataIcons[i].T_ASCII, Aux, MemAsciiBlockSize - strlen(DataIcons[i].T_ASCII)); 123 | } 124 | } 125 | 126 | /* Update window */ 127 | UpdateWindow(DataWin); 128 | } 129 | 130 | void DataWinTerminate() { 131 | free(DataIcons); 132 | } 133 | -------------------------------------------------------------------------------- /c/Debug: -------------------------------------------------------------------------------- 1 | /* 2 | * !UCDebug, ARM debugger for RISC OS. 3 | * https://github.com/fuentesp/UCDebug 4 | * Copyright (C) 2018 University of Cantabria 5 | * 6 | * !UCDebug was developed by the Computer Architecture and Technology 7 | * Group at the University of Cantabria. A comprehensive list of authors 8 | * can be found in the file AUTHORS.txt. 9 | * 10 | * You can reach the main developers at {fernando.vallejo, cristobal.camarero, 11 | * pablo.fuentes}@unican.es. 12 | * 13 | * This program is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | */ 26 | 27 | #include "oslib/wimp.h" 28 | /* Added C libraries to avoid warnings */ 29 | #include 30 | #include 31 | #include 32 | 33 | #include "CodeWin.h" 34 | #include "DataWin.h" 35 | #include "RegsWin.h" 36 | #include "FPRegsWin.h" 37 | #include "ConsWin.h" 38 | #include "ibar.h" 39 | #include "main.h" 40 | 41 | /* Global variables */ 42 | int ControllerBaseAddress; 43 | char DEBUG_AREA[DebugAreaSize]; 44 | struct ContextType CurContext; 45 | int LastShownContext[18]; 46 | int BrkPtList[MaxBrPoints]; 47 | int CurNumBr = 0; 48 | int GTBrkP; 49 | int ExecType = Stop_Ex; 50 | int AddrElfFile; 51 | int AddrCodeStart; 52 | int AddrCodeCur; 53 | int AddrCodeEnd; 54 | int AddrDataStart; 55 | int AddrDataCur; 56 | int DebugAreaStart; 57 | int DebugAreaEnd; 58 | osbool mainQuitFlag = FALSE; 59 | int memDispType = 0; 60 | enum WinScreenStatus WindowStates[6] = { wss_ON_SCREEN, wss_ON_SCREEN, wss_ON_SCREEN, 61 | wss_ON_SCREEN, wss_CLOSED, wss_CLOSED }; 62 | int NumWindows = 6; 63 | osbool FPdispDoublePrec = FALSE; 64 | wimp_t AppTask; 65 | font_f AppFont; 66 | 67 | /* Titles of the windows */ 68 | char CodeWinTitle[WinTitleSize]; 69 | char DataWinTitle[WinTitleSize]; 70 | char RegsWinTitle[WinTitleSize]; 71 | char ConsWinTitle[WinTitleSize]; 72 | char UsrWinTitle[WinTitleSize]; 73 | char FPRegsWinTitle[WinTitleSize]; 74 | 75 | /* Handle to the different windows */ 76 | wimp_w CodeWin; /* Code view window */ 77 | wimp_w DataWin; /* Memory view window */ 78 | wimp_w RegsWin; /* Window to show the content of the CPU registers */ 79 | wimp_w ConsWin; /* Console window */ 80 | wimp_w UsrWin; /* User Console window */ 81 | wimp_w FPRegsWin; /* Window to show the content of the registers from the Floating Point coprocessor */ 82 | wimp_w* WinHandles[6] = { &CodeWin, &DataWin, &RegsWin, &ConsWin, &UsrWin, &FPRegsWin }; 83 | 84 | /* Declaration of local functions */ 85 | static void main_initialize(void); 86 | static void main_terminate(void); 87 | static osbool main_message_quit(wimp_message *message); 88 | 89 | /* Message strings */ 90 | #define TOO_MANY_BRKPTS_MSG "Too many breakpoints" 91 | 92 | /* Main function code */ 93 | int main(int argc, char *argv[]) { 94 | int i; 95 | 96 | main_initialize(); 97 | wimp_message_list *mlist; 98 | mlist = malloc(sizeof(int) * 3); 99 | mlist->messages[0] = message_ICONISE; 100 | mlist->messages[1] = message_ICONISE_AT; 101 | mlist->messages[2] = 0; 102 | wimp_add_messages(mlist); 103 | free(mlist); 104 | 105 | /* Fill up the debug area with random garbage data */ 106 | for (i = 0; i < DebugAreaSize; i++) { 107 | DEBUG_AREA[i] = (char) (rand() % 0x100); 108 | } 109 | 110 | /* Initialize the debugging vars */ 111 | DebugAreaStart = (int) &DEBUG_AREA; 112 | DebugAreaEnd = DebugAreaStart + DebugAreaSize; 113 | if (DebugAreaStart - (DebugAreaStart & AddrMask) > OffElfFile) 114 | AddrElfFile = (DebugAreaStart & AddrMask) + AddrMask + OffElfFile; 115 | else 116 | AddrElfFile = (DebugAreaStart & AddrMask) + OffElfFile; 117 | AddrCodeStart = AddrElfFile + (OffStartCode - OffElfFile); 118 | AddrCodeCur = AddrCodeStart; 119 | AddrCodeEnd = AddrCodeStart; 120 | AddrDataStart = AddrElfFile + (OffStartData - OffElfFile); 121 | AddrDataCur = AddrDataStart; 122 | 123 | /* Initialize the registers with their current value */ 124 | DefCurCtx(); 125 | UpdateLastShownCtx(); 126 | 127 | /* Open the basic windows from the debugger */ 128 | CodeWin = CodeWinCreate(AddrCodeCur, NumLinCode, PosXCodeWin, PosYCodeWin); 129 | DataWin = DataWinCreate(AddrDataCur, 25, 0, PosXDataWin, PosYDataWin); 130 | RegsWin = RegsWinCreate(PosXRegsWin, PosYRegsWin); 131 | ConsWin = ConsWinCreate(PosXConsWin, PosYConsWin); 132 | 133 | /* Print current available area - must be deleted for final version */ 134 | /* char aux_msg[ConsLinSize]; 135 | snprintf(aux_msg, sizeof(aux_msg), "AREA START: 0x%08X AREA END: 0x%08X", 136 | &DEBUG_AREA, &CurContext); 137 | ConsWrite(ConsWin, aux_msg);*/ 138 | 139 | /* Enter the polling function that checks CLI and acts accordingly */ 140 | while (!mainQuitFlag) { 141 | mainPoll(); 142 | } 143 | main_terminate(); 144 | return 0; 145 | } 146 | 147 | static void main_initialize(void) { 148 | /* Set the app font and store its handle for its use in icon creation */ 149 | int xsize=0xC0, ysize=0xC0, xres=0x5A, yres=0x5A, xreso, yreso; 150 | AppFont=font_find_font(TextFontName, xsize, ysize, xres, yres, &xreso, &yreso); 151 | 152 | AppTask = wimp_initialise(wimp_VERSION_RO3, AppName, NULL, NULL); 153 | ibar_initialise(); 154 | InitializeDbgKernel(); 155 | } 156 | 157 | /* ToggleBrk toggles a breakpoint at the specified address */ 158 | void ToggleBrk(int DirBrk) { 159 | int i, j; 160 | osbool brkRemoved = FALSE; 161 | 162 | /* If a breakpoint is set at the given address, then clear it */ 163 | for (i = 0; i < CurNumBr; i++) 164 | if (BrkPtList[i] == DirBrk) { 165 | for (j = i; j < CurNumBr - 1; j++) 166 | BrkPtList[j] = BrkPtList[j + 1]; 167 | CurNumBr--; 168 | brkRemoved = TRUE; 169 | } 170 | /* Otherwise, set a breakpoint at the address */ 171 | if (brkRemoved == FALSE) if (CurNumBr < MaxBrPoints) { 172 | BrkPtList[CurNumBr] = DirBrk; 173 | CurNumBr++; 174 | } else { 175 | ConsWrite(ConsWin, TOO_MANY_BRKPTS_MSG); 176 | } 177 | } 178 | 179 | /* ClrBrk clears all breakpoints */ 180 | void ClrBrk() { 181 | CurNumBr = 0; 182 | } 183 | 184 | /* PrintBrk prints at the console window the list of breakpoints currently set */ 185 | void PrintBrk() { 186 | int i; 187 | char aux[PrintedWordSize + 1]; 188 | char line[ConsLinSize + 1]; 189 | 190 | snprintf(line, sizeof(line), "%d BreakPoints", CurNumBr); 191 | ConsWrite(ConsWin, line); 192 | snprintf(line, ConsLinSize + 1, ""); 193 | for (i = 0; i < CurNumBr; i++) { 194 | snprintf(aux, sizeof(aux), "0x%08X", BrkPtList[i]); 195 | strncat(line, aux, ConsLinSize - strlen(line)); 196 | if ((((i + 1) % 4) == 0) || (i + 1) == CurNumBr) { 197 | ConsWrite(ConsWin, line); 198 | snprintf(line, ConsLinSize + 1, ""); 199 | } else { 200 | strncat(line, " ", ConsLinSize - strlen(line)); 201 | } 202 | } 203 | } 204 | 205 | /* mainPoll checks any inputs by the user and acts accordingly */ 206 | void mainPoll(void) { 207 | wimp_block block; 208 | wimp_event_no reason; 209 | int pollword, i, j; 210 | wimp_window_info *Info; 211 | char msg[ConsLinSize]; 212 | 213 | reason = wimp_poll(0, &block, &pollword); 214 | switch (reason) { 215 | case wimp_OPEN_WINDOW_REQUEST: /* reason=2 */ 216 | wimp_open_window((wimp_open *) &block); 217 | if (block.open.next == (wimp_w) - 3) { /* Iconise window */ 218 | /* Track status of iconised windows */ 219 | for (i = 0; i < NumWindows; i++) { 220 | if (block.open.w == *(WinHandles[i])) { 221 | if (WindowStates[i] != wss_CONS_WIN_ATTACHED) 222 | WindowStates[i] = wss_OFF_SCREEN; 223 | else { 224 | for (j = i + 1; j < NumWindows; j++) { 225 | if (WindowStates[j] == wss_CONS_WIN_ATTACHED) { 226 | IconiseWindow(*(WinHandles[j])); 227 | break; 228 | } 229 | } 230 | } 231 | break; 232 | } 233 | } 234 | if (block.open.w == ConsWin) { 235 | /* If the 'back' icon is clicked in the Console window, send to background 236 | all the windows that are not currently iconised. In order to iconise 237 | properly, it need to be done in cascade: each iconised window 238 | receives the event to get hidden and in its turn iconises the following. 239 | (Apparently, Wimp cannot handle more than one iconisation process 240 | at a time) */ 241 | j = -1; 242 | for (i = 0; i < NumWindows; i++) { 243 | if (WindowStates[i] == wss_ON_SCREEN) { 244 | WindowStates[i] = wss_CONS_WIN_ATTACHED; 245 | if (j == -1) j = i; // Track first window to iconise 246 | } 247 | } 248 | if (j != -1) IconiseWindow(*(WinHandles[j])); 249 | } 250 | } else if (block.open.next == (wimp_w) - 1) { //De-iconise window 251 | /* Track status of de-iconised windows */ 252 | for (i = 0; i < NumWindows; i++) { 253 | if (block.open.w == *(WinHandles[i])) { 254 | WindowStates[i] = wss_ON_SCREEN; 255 | break; 256 | } 257 | } 258 | if (block.open.w == ConsWin) { 259 | /* If the Console window is de-iconised, it brings back to 260 | foreground all the windows that were iconised with it */ 261 | ConsSetActive(ConsWin); // Gain the input focus 262 | for (i = 0; i < NumWindows; i++) { 263 | if (WindowStates[i] == wss_CONS_WIN_ATTACHED) { 264 | WindowStates[i] = wss_ON_SCREEN; 265 | ResetWindow(*(WinHandles[i]), -1, -1, -1, -1, -1, -1, (wimp_w) - 1); 266 | } 267 | } 268 | } 269 | } 270 | break; 271 | 272 | case wimp_CLOSE_WINDOW_REQUEST: /* reason=3 */ 273 | if (block.close.w == ConsWin) { 274 | mainQuitFlag = TRUE; 275 | } 276 | if (block.close.w == UsrWin && WindowStates[UsrWinOffset] == wss_ON_SCREEN) { 277 | wimp_close_window(UsrWin); 278 | WindowStates[UsrWinOffset] = wss_CLOSED; 279 | } 280 | if (block.close.w == FPRegsWin) { 281 | wimp_close_window(FPRegsWin); 282 | WindowStates[FPRegsWinOffset] = wss_CLOSED; 283 | } 284 | break; 285 | 286 | case wimp_USER_MESSAGE_RECORDED: 287 | case wimp_USER_MESSAGE_ACKNOWLEDGE: 288 | case wimp_USER_MESSAGE: 289 | if (block.message.action == message_QUIT) { 290 | mainQuitFlag = TRUE; 291 | } 292 | break; 293 | 294 | case wimp_POINTER_LEAVING_WINDOW: /* reason=4 */ 295 | break; 296 | 297 | case wimp_POINTER_ENTERING_WINDOW: /* reason=5 */ 298 | break; 299 | 300 | case wimp_MOUSE_CLICK: /* reason=6 */ 301 | if (block.pointer.w == CodeWin) { 302 | /* Click at the Code view window: with left button, scroll forward the 303 | * addresses; with right button, scroll backwards; with wheel button, 304 | * toggle breakpoint. */ 305 | if ((block.pointer.buttons == wimp_CLICK_SELECT) 306 | && validMemAddressRange(AddrCodeCur + (VisRows - 2) * 4)) 307 | AddrCodeCur = AddrCodeCur + (VisRows - 2) * 4; 308 | if ((block.pointer.buttons == wimp_CLICK_ADJUST) 309 | && validMemAddressRange(AddrCodeCur - (VisRows - 2) * 4)) 310 | AddrCodeCur = AddrCodeCur - (VisRows - 2) * 4; 311 | if (block.pointer.buttons == wimp_CLICK_MENU) { 312 | for (i = 0; i < NumLinCode; i++) 313 | if ((block.pointer.i == CodeIcons[i].I_Addr) 314 | || (block.pointer.i == CodeIcons[i].I_Code) 315 | || (block.pointer.i == CodeIcons[i].I_Disem)) 316 | ToggleBrk(AddrCodeCur + 4 * i); 317 | } 318 | CodeWinRedraw(CodeWin, AddrCodeCur, NumLinCode); 319 | } else if (block.pointer.w == DataWin) { 320 | /* Click at the Memory window: left button to advance the addresses shown, 321 | * right button to move backwards, and click button to toggle the size 322 | * of the display blocks. */ 323 | if ((block.pointer.buttons == wimp_CLICK_SELECT) 324 | && validMemAddressRange(AddrDataCur + (VisRows - 2) * 16)) 325 | AddrDataCur = AddrDataCur + (VisRows - 2) * 16; 326 | if ((block.pointer.buttons == wimp_CLICK_ADJUST) 327 | && validMemAddressRange(AddrDataCur - (VisRows - 2) * 16)) 328 | AddrDataCur = AddrDataCur - (VisRows - 2) * 16; 329 | if (block.pointer.buttons == wimp_CLICK_MENU) 330 | memDispType = (memDispType + 1) % 3; 331 | DataWinRedraw(DataWin, AddrDataCur, 25, memDispType); 332 | } else if (block.pointer.w == RegsWin) { 333 | /* Click at the Register window, it updates the window */ 334 | RegsWinRedraw(RegsWin); 335 | } else if (block.pointer.w == ConsWin) { 336 | /* Click at the Console window, activates the window to capture keyboard 337 | * inputs */ 338 | ActivateCons(ConsWin); 339 | } else if (block.pointer.w == FPRegsWin) { 340 | if (block.pointer.buttons == wimp_CLICK_MENU) { 341 | /* Wheel-button click at the FP registers window, it toggles between 342 | simple and double precision */ 343 | FPdispDoublePrec = !FPdispDoublePrec; 344 | ToggleWinDisplay(FPRegsWin); 345 | FPRegsWinRedraw(FPRegsWin); 346 | } 347 | } else if (block.pointer.w == wimp_ICON_BAR) { 348 | /* Click at the IconBar, it restores all iconised windows and displays an app menu*/ 349 | if (block.pointer.buttons == wimp_SINGLE_SELECT) { 350 | for (i = 0; i < NumWindows; i++) { 351 | if (WindowStates[i] != wss_CLOSED) { 352 | WindowStates[i] = wss_ON_SCREEN; 353 | ResetWindow(*(WinHandles[i]), -1, -1, -1, -1, -1, -1, (wimp_w) - 1); 354 | ActivateCons(ConsWin); 355 | } 356 | } 357 | } else if (block.pointer.buttons == wimp_DOUBLE_ADJUST) { 358 | ExecType = Stop_Ex; 359 | ConsWrite(ConsWin, "Stopping exec"); 360 | } else if (block.pointer.buttons == wimp_CLICK_MENU) 361 | OpenIconbarMenu(block.pointer); 362 | } 363 | break; /* fin reason=6 */ 364 | 365 | case wimp_KEY_PRESSED: /* reason=8 */ 366 | if (block.key.w == ConsWin) { 367 | if (block.key.c == wimp_KEY_RETURN) 368 | ConsEnterKey(ConsWin); 369 | else if (block.key.c == wimp_KEY_UP) 370 | ConsUpKey(ConsWin); 371 | else if (block.key.c == wimp_KEY_DOWN) 372 | ConsDownKey(ConsWin); 373 | else if (block.key.c == wimp_KEY_ESCAPE) 374 | ConsEscapeKey(ConsWin); 375 | else 376 | wimp_process_key(block.key.c); 377 | } 378 | break; 379 | 380 | case wimp_MENU_SELECTION: /* reason=9 */ 381 | handleMenuSelection(&(block.selection)); 382 | break; 383 | 384 | case wimp_SCROLL_REQUEST: /* reason=10 */ 385 | block.scroll.xscroll = block.scroll.xscroll + block.scroll.xmin * CharSizeX; 386 | block.scroll.yscroll = block.scroll.yscroll + block.scroll.ymin * LinSizeY; 387 | wimp_open_window((wimp_open *) &block); 388 | break; 389 | 390 | default: 391 | break; 392 | } 393 | } 394 | 395 | static void main_terminate(void) { 396 | FreeIconbarMenu(); 397 | wimp_close_down(0); 398 | font_lose_font(AppFont); 399 | CodeWinTerminate(); 400 | DataWinTerminate(); 401 | } 402 | 403 | /* Check if the address is in the accepted range */ 404 | bool validMemAddressRange(int addr) { 405 | if ((addr < DebugAreaEnd) && (addr > DebugAreaStart)) 406 | return TRUE; 407 | else 408 | return FALSE; 409 | } 410 | 411 | /* Check if address is aligned to word */ 412 | bool alignedAddr(int addr) { 413 | if (addr % 4 == 0) 414 | return TRUE; 415 | else 416 | return FALSE; 417 | } 418 | 419 | /* Selection at the app menu, currently under development */ 420 | void handleMenuSelection(wimp_selection *selection) { 421 | char *entry, aux[MenuEntryLen], line[ConsLinSize - 1]; 422 | int i; 423 | wimp_decode_menu(IconBarMenu, selection, aux); 424 | /* Remove trailing characters from returned string */ 425 | entry = strtok(aux, "\r."); 426 | if (strcmp(entry, "Reset view") == 0) { 427 | ResetWindow(CodeWin, CodeWinSizeX, CodeWinSizeY, PosXCodeWin, PosYCodeWin, 428 | 0, 0, (wimp_w) - 1); 429 | ResetWindow(DataWin, DataWinSizeX, DataWinSizeY, PosXDataWin, PosYDataWin, 430 | 0, 0, (wimp_w) - 1); 431 | ResetWindow(RegsWin, RegsWinSizeX, RegsWinSizeY, PosXRegsWin, PosYRegsWin, 432 | 0, 0, (wimp_w) - 1); 433 | ResetWindow(ConsWin, ConsWinSizeX, ConsWinSizeY, PosXConsWin, PosYConsWin, 434 | 0, ConsLinTot * LinSizeY - ConsWinSizeY, (wimp_w) - 1); 435 | if (WindowStates[FPRegsWinOffset] != wss_CLOSED) 436 | ResetWindow(FPRegsWin, FPRegsWinSizeX, FPRegsWinSizeY, PosXFPRegsWin, 437 | PosYFPRegsWin, 0, 0, (wimp_w) - 1); 438 | if (WindowStates[UsrWinOffset] != wss_CLOSED) 439 | ResetWindow(UsrWin, UsrConsWinSizeX, UsrConsWinSizeY, PosXUsrWin, PosYUsrWin, 440 | 0, (NumLinUsrCon - 10) * LinSizeY, (wimp_w) - 1); 441 | for (i = 0; i < NumWindows; i++) { /* Restore the status of any non-closed windows */ 442 | if (WindowStates[i] != wss_CLOSED) WindowStates[i] = wss_ON_SCREEN; 443 | } 444 | } else if (strcmp(entry, "FP Regs") == 0) { 445 | /* Submenu option */ 446 | entry = strtok(NULL, "\r."); 447 | if (entry != NULL) { 448 | /* Toggle between displays if the window is open */ 449 | if (strcmp(entry, "Single") == 0 && FPdispDoublePrec) { 450 | FPdispDoublePrec = FALSE; 451 | if(WindowStates[FPRegsWinOffset] != wss_CLOSED) 452 | ToggleWinDisplay(FPRegsWin); 453 | } else if (strcmp(entry, "Double") == 0 && !FPdispDoublePrec) { 454 | FPdispDoublePrec = TRUE; 455 | if(WindowStates[FPRegsWinOffset] != wss_CLOSED) 456 | ToggleWinDisplay(FPRegsWin); 457 | } 458 | } 459 | if (WindowStates[FPRegsWinOffset] == wss_CLOSED) 460 | FPRegsWin = FPRegsWinCreate(PosXFPRegsWin, PosYFPRegsWin); 461 | else 462 | FPRegsWinRedraw(FPRegsWin); 463 | } else if (strcmp(entry, "Quit") == 0) { 464 | mainQuitFlag = TRUE; 465 | } 466 | } 467 | -------------------------------------------------------------------------------- /c/FPRegsWin: -------------------------------------------------------------------------------- 1 | /* 2 | * !UCDebug, ARM debugger for RISC OS. 3 | * https://github.com/fuentesp/UCDebug 4 | * Copyright (C) 2018 University of Cantabria 5 | * 6 | * !UCDebug was developed by the Computer Architecture and Technology 7 | * Group at the University of Cantabria. A comprehensive list of authors 8 | * can be found in the file AUTHORS.txt. 9 | * 10 | * You can reach the main developers at {fernando.vallejo, cristobal.camarero, 11 | * pablo.fuentes}@unican.es. 12 | * 13 | * This program is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | */ 26 | 27 | #include "oslib/wimp.h" 28 | #include "oslib/wimpspriteop.h" 29 | #include 30 | /* Added C libraries to avoid warnings */ 31 | #include 32 | #include 33 | 34 | #include "ibar.h" 35 | #include "main.h" 36 | #include "FPRegsWin.h" 37 | 38 | /*Private Vars*/ 39 | struct FPRegType FPRegsIcons[34]; 40 | 41 | /* FPRegsWinCreate opens a Floating-Point Registers view window, showing the value of the VFP registers*/ 42 | wimp_w FPRegsWinCreate(int PosX, int PosY) { 43 | wimp_w FPRegsWin; 44 | int i, j; 45 | 46 | snprintf(FPRegsWinTitle, WinTitleSize, FPRegsWinName); 47 | FPRegsWin = open_window(FPRegsWinTitle, FPRegsWinSizeX, FPRegsWinSizeY, PosX, PosY, 48 | FPRegsWinSizeX, FPRegsWinSizeY, 0, 0, 0x06); 49 | 50 | if (FPdispDoublePrec) { 51 | /* Display double precision regs */ 52 | for (i = 0; i < 16; i += 1) { 53 | snprintf(FPRegsIcons[i].T_Name, FPRegNameSize + 1, "d%d", i); 54 | FPRegsIcons[i].I_Name = TextIconCreate(FPRegsWin, 7, 5 + LinSizeY * 2 * i, 55 | CharSizeX * 6, CharSizeY, FPRegsIcons[i].T_Name, FPRegNameSize + 1, FPRegsIcons[i].V_Name); 56 | ChTextBGColour(FPRegsWin, FPRegsIcons[i].I_Name, wimp_COLOUR_LIGHT_GREY); 57 | /* In double precision, even single-precision registers map to the least significant part of the 58 | value, and odd single-precision registers map to the most significant part*/ 59 | FPRegsIcons[2 * i].I_Val = TextIconCreate(FPRegsWin, 15 + CharSizeX * 6, 60 | 5 + LinSizeY * 2 * i, CharSizeX * PrintedWordSize, CharSizeY, 61 | FPRegsIcons[2 * i + 1].T_Val, PrintedWordSize + 1, FPRegsIcons[2 * i + 1].V_Val); 62 | ChTextBGColour(FPRegsWin, FPRegsIcons[2 * i].I_Val, wimp_COLOUR_LIGHT_GREY); 63 | FPRegsIcons[2 * i + 1].I_Val = TextIconCreate(FPRegsWin, 64 | 25 + CharSizeX * (PrintedWordSize + 6), 5 + LinSizeY * 2 * i, 65 | CharSizeX * PrintedWordSize, CharSizeY, FPRegsIcons[2 * i].T_Val, PrintedWordSize + 1, FPRegsIcons[2 * i].V_Val); 66 | ChTextBGColour(FPRegsWin, FPRegsIcons[2 * i + 1].I_Val, wimp_COLOUR_LIGHT_GREY); 67 | FPRegsIcons[i].I_FPval = TextIconCreate(FPRegsWin, 15 + CharSizeX * 6, 68 | 5 + LinSizeY * (2 * i + 1), CharSizeX * PrintedDoubleSize + 10, 69 | CharSizeY, FPRegsIcons[i].T_FPval, PrintedFloatSize + 1, FPRegsIcons[i].V_FPval); 70 | ChTextBGColour(FPRegsWin, FPRegsIcons[i].I_FPval, wimp_COLOUR_LIGHT_GREY); 71 | } 72 | } else { 73 | /* Display single precision regs */ 74 | for (i = 0; i < 32; i++) { 75 | snprintf(FPRegsIcons[i].T_Name, FPRegNameSize + 1, "s%d", i); 76 | /* Create the icons of registers 0 - 31 (single-value FP regs) */ 77 | FPRegsIcons[i].I_Name = TextIconCreate(FPRegsWin, 7, 5 + LinSizeY * i, 78 | CharSizeX * 6, CharSizeY, FPRegsIcons[i].T_Name, FPRegNameSize + 1, FPRegsIcons[i].V_Name); 79 | ChTextBGColour(FPRegsWin, FPRegsIcons[i].I_Name, wimp_COLOUR_LIGHT_GREY); 80 | FPRegsIcons[i].I_Val = TextIconCreate(FPRegsWin, 15 + CharSizeX * 6, 81 | 5 + LinSizeY * i, CharSizeX * PrintedWordSize, CharSizeY, 82 | FPRegsIcons[i].T_Val, PrintedWordSize + 1, FPRegsIcons[i].V_Val); 83 | ChTextBGColour(FPRegsWin, FPRegsIcons[i].I_Val, wimp_COLOUR_LIGHT_GREY); 84 | FPRegsIcons[i].I_FPval = TextIconCreate(FPRegsWin, 85 | 25 + CharSizeX * (PrintedWordSize + 6), 5 + LinSizeY * i, 86 | CharSizeX * PrintedFloatSize, CharSizeY, FPRegsIcons[i].T_FPval, PrintedFloatSize + 1, FPRegsIcons[i].V_FPval); 87 | ChTextBGColour(FPRegsWin, FPRegsIcons[i].I_FPval, wimp_COLOUR_LIGHT_GREY); 88 | } 89 | } 90 | 91 | /* Create the icons for the FCPSR and its flags */ 92 | snprintf(FPRegsIcons[32].T_Name, FPRegNameSize + 1, "FPSCR"); 93 | snprintf(FPRegsIcons[33].T_Name, FPRegNameSize + 1, "FLAGS"); 94 | for (i = 32; i < 34; i++) { 95 | FPRegsIcons[i].I_Name = TextIconCreate(FPRegsWin, 7, 20 + LinSizeY * i, 96 | CharSizeX * 6, CharSizeY, FPRegsIcons[i].T_Name, FPRegNameSize + 1, FPRegsIcons[i].V_Name); 97 | ChTextBGColour(FPRegsWin, FPRegsIcons[i].I_Name, wimp_COLOUR_LIGHT_GREY); 98 | FPRegsIcons[i].I_Val = TextIconCreate(FPRegsWin, 15 + CharSizeX * 6, 99 | 20 + LinSizeY * i, CharSizeX * 10, CharSizeY, FPRegsIcons[i].T_Val, PrintedWordSize + 1, FPRegsIcons[i].V_Val); 100 | ChTextBGColour(FPRegsWin, FPRegsIcons[i].I_Val, wimp_COLOUR_LIGHT_GREY); 101 | } 102 | 103 | FPRegsWinRedraw(FPRegsWin); 104 | WindowStates[FPRegsWinOffset] = wss_ON_SCREEN; /* Mark the FP regs window as active */ 105 | 106 | return FPRegsWin; 107 | } 108 | 109 | /* RegsWinRedraw updates the Register view window */ 110 | void FPRegsWinRedraw(wimp_w FPRegsWin) { 111 | int i; 112 | 113 | /* Register value within current context */ 114 | for (i = 0; i < 32; i++) 115 | snprintf(FPRegsIcons[i].T_Val, PrintedWordSize + 1, "0x%08X", 116 | *(long*) &CurContext.FPRegs[i]); 117 | 118 | if (FPdispDoublePrec) { /* Display values in double precision */ 119 | for (i = 0; i < 16; i++) 120 | snprintf(FPRegsIcons[i].T_FPval, PrintedDoubleSize + 1, "%*.13E", 121 | PrintedDoubleSize - 2, *((double *) &(CurContext.FPRegs[2 * i]))); 122 | } else { /* Simple precision */ 123 | for (i = 0; i < 32; i++) 124 | snprintf(FPRegsIcons[i].T_FPval, PrintedFloatSize + 1, "%*.6E", 125 | PrintedFloatSize - 2, CurContext.FPRegs[i]); 126 | } 127 | 128 | /* Display the FPSCR and the flags (from the FPSCR) */ 129 | snprintf(FPRegsIcons[32].T_Val, PrintedWordSize + 1, "0x%08X", CurContext.FPSCR); 130 | snprintf(FPRegsIcons[33].T_Val, PrintedWordSize + 1, "----"); 131 | if ((CurContext.FPSCR & 0x80000000) != 0) FPRegsIcons[33].T_Val[0] = 'N'; 132 | if ((CurContext.FPSCR & 0x40000000) != 0) FPRegsIcons[33].T_Val[1] = 'Z'; 133 | if ((CurContext.FPSCR & 0x20000000) != 0) FPRegsIcons[33].T_Val[2] = 'C'; 134 | if ((CurContext.FPSCR & 0x10000000) != 0) FPRegsIcons[33].T_Val[3] = 'V'; 135 | 136 | /* Update window */ 137 | UpdateWindow(FPRegsWin); 138 | } 139 | 140 | void ToggleWinDisplay(wimp_w FPRegsWin) { 141 | int i; 142 | if (FPdispDoublePrec) { /* Change from simple to double precision */ 143 | for (i = 0; i < 32; i++) { 144 | wimp_delete_icon(FPRegsWin, FPRegsIcons[i].I_Name); 145 | wimp_delete_icon(FPRegsWin, FPRegsIcons[i].I_Val); 146 | wimp_delete_icon(FPRegsWin, FPRegsIcons[i].I_FPval); 147 | } 148 | for (i = 0; i < 16; i += 1) { 149 | snprintf(FPRegsIcons[i].T_Name, FPRegNameSize + 1, "d%d", i); 150 | FPRegsIcons[i].I_Name = TextIconCreate(FPRegsWin, 7, 5 + LinSizeY * 2 * i, 151 | CharSizeX * 6, CharSizeY, FPRegsIcons[i].T_Name, FPRegNameSize + 1, FPRegsIcons[i].V_Name); 152 | ChTextBGColour(FPRegsWin, FPRegsIcons[i].I_Name, wimp_COLOUR_LIGHT_GREY); 153 | /* In double precision, even single-precision registers map to the least significant part of the 154 | value, and odd single-precision registers map to the most significant part*/ 155 | FPRegsIcons[2 * i].I_Val = TextIconCreate(FPRegsWin, 15 + CharSizeX * 6, 156 | 5 + LinSizeY * 2 * i, CharSizeX * PrintedWordSize, CharSizeY, 157 | FPRegsIcons[2 * i + 1].T_Val, PrintedWordSize + 1, FPRegsIcons[2 * i + 1].V_Val); 158 | ChTextBGColour(FPRegsWin, FPRegsIcons[2 * i].I_Val, wimp_COLOUR_LIGHT_GREY); 159 | FPRegsIcons[2 * i + 1].I_Val = TextIconCreate(FPRegsWin, 160 | 25 + CharSizeX * (PrintedWordSize + 6), 5 + LinSizeY * 2 * i, 161 | CharSizeX * PrintedWordSize, CharSizeY, FPRegsIcons[2 * i].T_Val, PrintedWordSize + 1, FPRegsIcons[2 * i].V_Val); 162 | ChTextBGColour(FPRegsWin, FPRegsIcons[2 * i + 1].I_Val, 163 | wimp_COLOUR_LIGHT_GREY); 164 | FPRegsIcons[i].I_FPval = TextIconCreate(FPRegsWin, 15 + CharSizeX * 6, 165 | 5 + LinSizeY * (2 * i + 1), CharSizeX * PrintedDoubleSize + 10, 166 | CharSizeY, FPRegsIcons[i].T_FPval, PrintedFloatSize + 1, FPRegsIcons[i].V_FPval); 167 | ChTextBGColour(FPRegsWin, FPRegsIcons[i].I_FPval, wimp_COLOUR_LIGHT_GREY); 168 | } 169 | } else { /* Change from double to simple precision */ 170 | for (i = 0; i < 16; i += 1) { 171 | wimp_delete_icon(FPRegsWin, FPRegsIcons[i].I_Name); 172 | wimp_delete_icon(FPRegsWin, FPRegsIcons[2 * i].I_Val); 173 | wimp_delete_icon(FPRegsWin, FPRegsIcons[2 * i + 1].I_Val); 174 | wimp_delete_icon(FPRegsWin, FPRegsIcons[i].I_FPval); 175 | } 176 | for (i = 0; i < 32; i++) { 177 | snprintf(FPRegsIcons[i].T_Name, FPRegNameSize + 1, "s%d", i); 178 | /* Create the icons of registers 0 - 31 (single-value FP regs) */ 179 | FPRegsIcons[i].I_Name = TextIconCreate(FPRegsWin, 7, 5 + LinSizeY * i, 180 | CharSizeX * 6, CharSizeY, FPRegsIcons[i].T_Name, FPRegNameSize + 1, FPRegsIcons[i].V_Name); 181 | ChTextBGColour(FPRegsWin, FPRegsIcons[i].I_Name, wimp_COLOUR_LIGHT_GREY); 182 | FPRegsIcons[i].I_Val = TextIconCreate(FPRegsWin, 15 + CharSizeX * 6, 183 | 5 + LinSizeY * i, CharSizeX * PrintedWordSize, CharSizeY, 184 | FPRegsIcons[i].T_Val, PrintedWordSize + 1, FPRegsIcons[i].V_Val); 185 | ChTextBGColour(FPRegsWin, FPRegsIcons[i].I_Val, wimp_COLOUR_LIGHT_GREY); 186 | FPRegsIcons[i].I_FPval = TextIconCreate(FPRegsWin, 187 | 25 + CharSizeX * (PrintedWordSize + 6), 5 + LinSizeY * i, 188 | CharSizeX * PrintedFloatSize, CharSizeY, FPRegsIcons[i].T_FPval, PrintedFloatSize + 1, FPRegsIcons[i].V_FPval); 189 | ChTextBGColour(FPRegsWin, FPRegsIcons[i].I_FPval, wimp_COLOUR_LIGHT_GREY); 190 | } 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /c/RegsWin: -------------------------------------------------------------------------------- 1 | /* 2 | * !UCDebug, ARM debugger for RISC OS. 3 | * https://github.com/fuentesp/UCDebug 4 | * Copyright (C) 2018 University of Cantabria 5 | * 6 | * !UCDebug was developed by the Computer Architecture and Technology 7 | * Group at the University of Cantabria. A comprehensive list of authors 8 | * can be found in the file AUTHORS.txt. 9 | * 10 | * You can reach the main developers at {fernando.vallejo, cristobal.camarero, 11 | * pablo.fuentes}@unican.es. 12 | * 13 | * This program is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | */ 26 | 27 | #include "oslib/wimp.h" 28 | #include "oslib/wimpspriteop.h" 29 | #include 30 | /* Added C libraries to avoid warnings */ 31 | #include 32 | #include 33 | 34 | #include "ibar.h" 35 | #include "main.h" 36 | #include "RegsWin.h" 37 | 38 | /*Private Vars*/ 39 | struct RegType RegsIcons[20]; 40 | 41 | /* RegsWinCreate opens a Registers view window, showing the value of the CPU registers */ 42 | wimp_w RegsWinCreate(int PosX, int PosY) { 43 | wimp_w RegsWin; 44 | int i, j; 45 | 46 | snprintf(RegsWinTitle, WinTitleSize, RegsWinName); 47 | RegsWin = open_window(RegsWinTitle, RegsWinSizeX, RegsWinSizeY, PosX, PosY, 48 | RegsWinSizeX, RegsWinSizeY, 0, 0, 0x06); 49 | 50 | snprintf(RegsIcons[0].T_Name, RegNameSize + 1, "R0"); 51 | snprintf(RegsIcons[1].T_Name, RegNameSize + 1, "R1"); 52 | snprintf(RegsIcons[2].T_Name, RegNameSize + 1, "R2"); 53 | snprintf(RegsIcons[3].T_Name, RegNameSize + 1, "R3"); 54 | snprintf(RegsIcons[4].T_Name, RegNameSize + 1, "R4"); 55 | snprintf(RegsIcons[5].T_Name, RegNameSize + 1, "R5"); 56 | snprintf(RegsIcons[6].T_Name, RegNameSize + 1, "R6"); 57 | snprintf(RegsIcons[7].T_Name, RegNameSize + 1, "R7"); 58 | snprintf(RegsIcons[8].T_Name, RegNameSize + 1, "R8"); 59 | snprintf(RegsIcons[9].T_Name, RegNameSize + 1, "R9"); 60 | snprintf(RegsIcons[10].T_Name, RegNameSize + 1, "R10"); 61 | snprintf(RegsIcons[11].T_Name, RegNameSize + 1, "R11"); 62 | snprintf(RegsIcons[12].T_Name, RegNameSize + 1, "R12"); 63 | snprintf(RegsIcons[13].T_Name, RegNameSize + 1, "R13 (SP)"); 64 | snprintf(RegsIcons[14].T_Name, RegNameSize + 1, "R14 (LR)"); 65 | snprintf(RegsIcons[15].T_Name, RegNameSize + 1, "R15 (PC)"); 66 | snprintf(RegsIcons[16].T_Name, RegNameSize + 1, "CPSR"); 67 | snprintf(RegsIcons[17].T_Name, RegNameSize + 1, "FLAGS"); 68 | snprintf(RegsIcons[18].T_Name, RegNameSize + 1, "CPU Mode"); 69 | snprintf(RegsIcons[19].T_Name, RegNameSize + 1, "SPSR"); 70 | 71 | for (i = 0; i < 16; i++) { 72 | /* Create the icons of registers 0 - 15 */ 73 | RegsIcons[i].I_Name = TextIconCreate(RegsWin, 10, 5 + LinSizeY * i, CharSizeX * 8, 74 | CharSizeY, RegsIcons[i].T_Name, RegNameSize + 1, RegsIcons[i].V_Name); 75 | ChTextBGColour(RegsWin, RegsIcons[i].I_Name, wimp_COLOUR_LIGHT_GREY); 76 | RegsIcons[i].I_Val = TextIconCreate(RegsWin, 20 + CharSizeX * 10, 77 | 5 + LinSizeY * i, CharSizeX * 10, CharSizeY, RegsIcons[i].T_Val, PrintedWordSize + 1, RegsIcons[i].V_Val); 78 | ChTextBGColour(RegsWin, RegsIcons[i].I_Val, wimp_COLOUR_LIGHT_GREY); 79 | } 80 | 81 | for (j = 0; j < 3; j++) { 82 | i = j + 16; 83 | RegsIcons[i].I_Name = TextIconCreate(RegsWin, 10, 20 + LinSizeY * i, 84 | CharSizeX * 8, CharSizeY, RegsIcons[i].T_Name, RegNameSize + 1, RegsIcons[i].V_Name); 85 | ChTextBGColour(RegsWin, RegsIcons[i].I_Name, wimp_COLOUR_LIGHT_GREY); 86 | RegsIcons[i].I_Val = TextIconCreate(RegsWin, 20 + CharSizeX * 10, 87 | 20 + LinSizeY * i, CharSizeX * 10, CharSizeY, RegsIcons[i].T_Val, PrintedWordSize + 1, RegsIcons[i].V_Val); 88 | ChTextBGColour(RegsWin, RegsIcons[i].I_Val, wimp_COLOUR_LIGHT_GREY); 89 | } 90 | 91 | i = 19; 92 | RegsIcons[i].I_Name = TextIconCreate(RegsWin, 10, 35 + LinSizeY * i, CharSizeX * 8, 93 | CharSizeY, RegsIcons[i].T_Name, RegNameSize + 1, RegsIcons[i].V_Name); 94 | ChTextBGColour(RegsWin, RegsIcons[i].I_Name, wimp_COLOUR_DARK_GREY); 95 | RegsIcons[i].I_Val = TextIconCreate(RegsWin, 20 + CharSizeX * 10, 35 + LinSizeY * i, 96 | CharSizeX * 10, CharSizeY, RegsIcons[i].T_Val, PrintedWordSize + 1, RegsIcons[i].V_Val); 97 | ChTextBGColour(RegsWin, RegsIcons[i].I_Val, wimp_COLOUR_DARK_GREY); 98 | 99 | RegsWinRedraw(RegsWin); 100 | 101 | return RegsWin; 102 | } 103 | 104 | /* RegsWinRedraw updates the Register view window */ 105 | void RegsWinRedraw(wimp_w RegsWin) { 106 | int i; 107 | 108 | /* Register value within current context */ 109 | for (i = 0; i < 16; i++) { 110 | snprintf(RegsIcons[i].T_Val, PrintedWordSize + 1, "0x%08X", CurContext.Regs[i]); 111 | if (CurContext.Regs[i] != LastShownContext[i]) 112 | ChTextFGColour(RegsWin, RegsIcons[i].I_Val, wimp_COLOUR_RED); 113 | else 114 | ChTextFGColour(RegsWin, RegsIcons[i].I_Val, wimp_COLOUR_BLACK); 115 | } 116 | /* Display the CPSR, the flags and the CPU mode (the latter two from the CPSR) */ 117 | snprintf(RegsIcons[16].T_Val, PrintedWordSize + 1, "0x%08X", CurContext.CPSR); 118 | if (CurContext.CPSR != LastShownContext[16]) 119 | ChTextFGColour(RegsWin, RegsIcons[16].I_Val, wimp_COLOUR_RED); 120 | else 121 | ChTextFGColour(RegsWin, RegsIcons[16].I_Val, wimp_COLOUR_BLACK); 122 | 123 | snprintf(RegsIcons[17].T_Val, PrintedWordSize + 1, "-----"); 124 | if ((CurContext.CPSR & 0x80000000) != 0) RegsIcons[17].T_Val[0] = 'N'; 125 | if ((CurContext.CPSR & 0x40000000) != 0) RegsIcons[17].T_Val[1] = 'Z'; 126 | if ((CurContext.CPSR & 0x20000000) != 0) RegsIcons[17].T_Val[2] = 'C'; 127 | if ((CurContext.CPSR & 0x10000000) != 0) RegsIcons[17].T_Val[3] = 'V'; 128 | if ((CurContext.CPSR & 0x08000000) != 0) RegsIcons[17].T_Val[3] = 'Q'; 129 | if ((CurContext.CPSR & 0xF8000000) != (LastShownContext[16] & 0xF8000000)) 130 | ChTextFGColour(RegsWin, RegsIcons[17].I_Val, wimp_COLOUR_RED); 131 | else 132 | ChTextFGColour(RegsWin, RegsIcons[17].I_Val, wimp_COLOUR_BLACK); 133 | 134 | switch (CurContext.CPSR & 0x01F) { 135 | case 0x010: 136 | snprintf(RegsIcons[18].T_Val, PrintedWordSize + 1, "usr"); 137 | /* Clear and hide SPSR register */ 138 | snprintf(RegsIcons[19].T_Val, PrintedWordSize + 1, ""); 139 | ChTextBGColour(RegsWin, RegsIcons[19].I_Val, wimp_COLOUR_DARK_GREY); 140 | ChTextBGColour(RegsWin, RegsIcons[19].I_Name, wimp_COLOUR_DARK_GREY); 141 | break; 142 | case 0x011: 143 | snprintf(RegsIcons[18].T_Val, PrintedWordSize + 1, "fiq"); 144 | for (i = 0; i < 7; i++) { /* Update value from sp and lr regs */ 145 | snprintf(RegsIcons[i+8].T_Val, PrintedWordSize + 1, "0x%08X", CurContext.FiqRegs[i]); 146 | if (CurContext.FiqRegs[i] != LastShownContext[i+8]) 147 | ChTextFGColour(RegsWin, RegsIcons[i+8].I_Val, wimp_COLOUR_RED); 148 | else 149 | ChTextFGColour(RegsWin, RegsIcons[i+8].I_Val, wimp_COLOUR_BLACK); 150 | } 151 | snprintf(RegsIcons[19].T_Val, PrintedWordSize + 1, "0x%08X", CurContext.FiqRegs[7]); 152 | ChTextBGColour(RegsWin, RegsIcons[19].I_Val, wimp_COLOUR_LIGHT_GREY); 153 | ChTextBGColour(RegsWin, RegsIcons[19].I_Name, wimp_COLOUR_LIGHT_GREY); 154 | if (CurContext.FiqRegs[7] != LastShownContext[17]) 155 | ChTextFGColour(RegsWin, RegsIcons[19].I_Val, wimp_COLOUR_RED); 156 | else 157 | ChTextFGColour(RegsWin, RegsIcons[19].I_Val, wimp_COLOUR_BLACK); 158 | break; 159 | case 0x012: 160 | snprintf(RegsIcons[18].T_Val, PrintedWordSize + 1, "irq"); 161 | for (i = 0; i < 2; i++) { /* Update value from sp and lr regs */ 162 | snprintf(RegsIcons[i+13].T_Val, PrintedWordSize + 1, "0x%08X", CurContext.IrqRegs[i]); 163 | if (CurContext.IrqRegs[i] != LastShownContext[i+13]) 164 | ChTextFGColour(RegsWin, RegsIcons[i+13].I_Val, wimp_COLOUR_RED); 165 | else 166 | ChTextFGColour(RegsWin, RegsIcons[i+13].I_Val, wimp_COLOUR_BLACK); 167 | } 168 | snprintf(RegsIcons[19].T_Val, PrintedWordSize + 1, "0x%08X", CurContext.IrqRegs[2]); 169 | ChTextBGColour(RegsWin, RegsIcons[19].I_Val, wimp_COLOUR_LIGHT_GREY); 170 | ChTextBGColour(RegsWin, RegsIcons[19].I_Name, wimp_COLOUR_LIGHT_GREY); 171 | if (CurContext.IrqRegs[2] != LastShownContext[17]) 172 | ChTextFGColour(RegsWin, RegsIcons[19].I_Val, wimp_COLOUR_RED); 173 | else 174 | ChTextFGColour(RegsWin, RegsIcons[19].I_Val, wimp_COLOUR_BLACK); 175 | break; 176 | case 0x013: 177 | snprintf(RegsIcons[18].T_Val, PrintedWordSize + 1, "svc"); 178 | for (i = 0; i < 2; i++) { /* Update value from sp and lr regs */ 179 | snprintf(RegsIcons[i+13].T_Val, PrintedWordSize + 1, "0x%08X", CurContext.SvcRegs[i]); 180 | if (CurContext.SvcRegs[i] != LastShownContext[i+13]) 181 | ChTextFGColour(RegsWin, RegsIcons[i+13].I_Val, wimp_COLOUR_RED); 182 | else 183 | ChTextFGColour(RegsWin, RegsIcons[i+13].I_Val, wimp_COLOUR_BLACK); 184 | } 185 | snprintf(RegsIcons[19].T_Val, PrintedWordSize + 1, "0x%08X", CurContext.SvcRegs[2]); 186 | ChTextBGColour(RegsWin, RegsIcons[19].I_Val, wimp_COLOUR_LIGHT_GREY); 187 | ChTextBGColour(RegsWin, RegsIcons[19].I_Name, wimp_COLOUR_LIGHT_GREY); 188 | if (CurContext.SvcRegs[2] != LastShownContext[17]) 189 | ChTextFGColour(RegsWin, RegsIcons[19].I_Val, wimp_COLOUR_RED); 190 | else 191 | ChTextFGColour(RegsWin, RegsIcons[19].I_Val, wimp_COLOUR_BLACK); 192 | break; 193 | case 0x017: 194 | snprintf(RegsIcons[18].T_Val, PrintedWordSize + 1, "abt"); 195 | for (i = 0; i < 2; i++) { /* Update value from sp and lr regs */ 196 | snprintf(RegsIcons[i+13].T_Val, PrintedWordSize + 1, "0x%08X", CurContext.AbtRegs[i]); 197 | if (CurContext.AbtRegs[i] != LastShownContext[i+13]) 198 | ChTextFGColour(RegsWin, RegsIcons[i+13].I_Val, wimp_COLOUR_RED); 199 | else 200 | ChTextFGColour(RegsWin, RegsIcons[i+13].I_Val, wimp_COLOUR_BLACK); 201 | } 202 | snprintf(RegsIcons[19].T_Val, PrintedWordSize + 1, "0x%08X", CurContext.AbtRegs[2]); 203 | ChTextBGColour(RegsWin, RegsIcons[19].I_Val, wimp_COLOUR_LIGHT_GREY); 204 | ChTextBGColour(RegsWin, RegsIcons[19].I_Name, wimp_COLOUR_LIGHT_GREY); 205 | if (CurContext.AbtRegs[2] != LastShownContext[17]) 206 | ChTextFGColour(RegsWin, RegsIcons[19].I_Val, wimp_COLOUR_RED); 207 | else 208 | ChTextFGColour(RegsWin, RegsIcons[19].I_Val, wimp_COLOUR_BLACK); 209 | break; 210 | case 0x01B: 211 | snprintf(RegsIcons[18].T_Val, PrintedWordSize + 1, "und"); 212 | for (i = 0; i < 2; i++) { /* Update value from sp and lr regs */ 213 | snprintf(RegsIcons[i+13].T_Val, PrintedWordSize + 1, "0x%08X", CurContext.UndRegs[i]); 214 | if (CurContext.UndRegs[i] != LastShownContext[i+13]) 215 | ChTextFGColour(RegsWin, RegsIcons[i+13].I_Val, wimp_COLOUR_RED); 216 | else 217 | ChTextFGColour(RegsWin, RegsIcons[i+13].I_Val, wimp_COLOUR_BLACK); 218 | } 219 | snprintf(RegsIcons[19].T_Val, PrintedWordSize + 1, "0x%08X", CurContext.UndRegs[2]); 220 | ChTextBGColour(RegsWin, RegsIcons[19].I_Val, wimp_COLOUR_LIGHT_GREY); 221 | ChTextBGColour(RegsWin, RegsIcons[19].I_Name, wimp_COLOUR_LIGHT_GREY); 222 | if (CurContext.UndRegs[2] != LastShownContext[17]) 223 | ChTextFGColour(RegsWin, RegsIcons[19].I_Val, wimp_COLOUR_RED); 224 | else 225 | ChTextFGColour(RegsWin, RegsIcons[19].I_Val, wimp_COLOUR_BLACK); 226 | break; 227 | case 0x01F: 228 | snprintf(RegsIcons[18].T_Val, PrintedWordSize + 1, "sys"); 229 | /* Clear and hide SPSR register */ 230 | snprintf(RegsIcons[19].T_Val, PrintedWordSize + 1, ""); 231 | ChTextBGColour(RegsWin, RegsIcons[19].I_Val, wimp_COLOUR_DARK_GREY); 232 | ChTextBGColour(RegsWin, RegsIcons[19].I_Name, wimp_COLOUR_DARK_GREY); 233 | break; 234 | default: 235 | snprintf(RegsIcons[18].T_Val, PrintedWordSize + 1, "UKN"); 236 | break; 237 | } 238 | if ((CurContext.CPSR & 0x01F) != (LastShownContext[16] & 0x01F)) 239 | ChTextFGColour(RegsWin, RegsIcons[18].I_Val, wimp_COLOUR_RED); 240 | else 241 | ChTextFGColour(RegsWin, RegsIcons[18].I_Val, wimp_COLOUR_BLACK); 242 | 243 | /* Update window */ 244 | UpdateWindow(RegsWin); 245 | } 246 | 247 | /* Update the values of the last context shown */ 248 | void UpdateLastShownCtx() { 249 | int i; 250 | for (i = 0; i < 16; i++) 251 | LastShownContext[i] = CurContext.Regs[i]; 252 | LastShownContext[16] = CurContext.CPSR; 253 | switch (CurContext.CPSR & 0x01F) { 254 | case 0x011: 255 | for (i = 0; i < 7; i++) 256 | LastShownContext[i+8] = CurContext.FiqRegs[i]; 257 | LastShownContext[17] = CurContext.FiqRegs[7]; 258 | break; 259 | case 0x012: 260 | LastShownContext[13] = CurContext.IrqRegs[0]; 261 | LastShownContext[14] = CurContext.IrqRegs[1]; 262 | LastShownContext[17] = CurContext.IrqRegs[2]; 263 | break; 264 | case 0x013: 265 | LastShownContext[13] = CurContext.SvcRegs[0]; 266 | LastShownContext[14] = CurContext.SvcRegs[1]; 267 | LastShownContext[17] = CurContext.SvcRegs[2]; 268 | break; 269 | case 0x017: 270 | LastShownContext[13] = CurContext.AbtRegs[0]; 271 | LastShownContext[14] = CurContext.AbtRegs[1]; 272 | LastShownContext[17] = CurContext.AbtRegs[2]; 273 | break; 274 | case 0x01B: 275 | LastShownContext[13] = CurContext.UndRegs[0]; 276 | LastShownContext[14] = CurContext.UndRegs[1]; 277 | LastShownContext[17] = CurContext.UndRegs[2]; 278 | break; 279 | default: 280 | LastShownContext[17] = 0x12345678; /* Weird value, to detect a change in user mode */ 281 | break; 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /compile,feb: -------------------------------------------------------------------------------- 1 | | !UCDebug, ARM debugger for RISC OS. 2 | | https://github.com/fuentesp/UCDebug 3 | | Copyright (C) 2018 University of Cantabria 4 | | 5 | | !UCDebug was developed by the Computer Architecture and Technology 6 | | Group at the University of Cantabria. A comprehensive list of authors 7 | | can be found in the file AUTHORS.txt. 8 | | 9 | | You can reach the main developers at {fernando.vallejo, cristobal.camarero, 10 | | pablo.fuentes}@unican.es. 11 | | 12 | | This program is free software: you can redistribute it and/or modify 13 | | it under the terms of the GNU General Public License as published by 14 | | the Free Software Foundation, either version 3 of the License, or 15 | | (at your option) any later version. 16 | | 17 | | This program is distributed in the hope that it will be useful, 18 | | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | | GNU General Public License for more details. 21 | | 22 | | You should have received a copy of the GNU General Public License 23 | | along with this program. If not, see . 24 | 25 | set FormerFS 26 | if FormerFS="SDFS" then 27 | set aux_dir 28 | if aux_dir="" then set aux_dir "&" 29 | 30 | dir 31 | make 32 | if FormerFS="SDFS" then dir : else echo WARNING!!!: CSD may have changed 33 | -------------------------------------------------------------------------------- /h/CodeWin: -------------------------------------------------------------------------------- 1 | /* 2 | * !UCDebug, ARM debugger for RISC OS. 3 | * https://github.com/fuentesp/UCDebug 4 | * Copyright (C) 2018 University of Cantabria 5 | * 6 | * !UCDebug was developed by the Computer Architecture and Technology 7 | * Group at the University of Cantabria. A comprehensive list of authors 8 | * can be found in the file AUTHORS.txt. 9 | * 10 | * You can reach the main developers at {fernando.vallejo, cristobal.camarero, 11 | * pablo.fuentes}@unican.es. 12 | * 13 | * This program is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | */ 26 | 27 | #include "main.h" 28 | 29 | /*Public Types*/ 30 | struct CodeType { 31 | wimp_i I_Addr; 32 | wimp_i I_Code; 33 | wimp_i I_Disem; 34 | char T_Addr[PrintedWordSize + 1]; 35 | char T_Code[PrintedWordSize + 1]; 36 | char T_Disem[DisasInstrSize + 1]; 37 | char V_Addr[ValStrSize+1]; 38 | char V_Code[ValStrSize+1]; 39 | char V_Disem[ValStrSize+1]; 40 | }; 41 | 42 | /*Public Vars*/ 43 | extern struct CodeType *CodeIcons; 44 | 45 | /* Auxiliary Functions */ 46 | void ColorPC(wimp_w CodeWin, int StartAddr, int NumInstr); 47 | void ColorBrk(wimp_w CodeWin, int StartAddr, int NumInstr); 48 | 49 | /*Public Function Protos*/ 50 | wimp_w CodeWinCreate(int StartAddr, int NumInstr, int PosX, int PosY); 51 | void CodeWinRedraw(wimp_w CodeWin, int StartAddr, int NumInstr); 52 | void CodeWinTerminate(); 53 | -------------------------------------------------------------------------------- /h/ConsWin: -------------------------------------------------------------------------------- 1 | /* 2 | * !UCDebug, ARM debugger for RISC OS. 3 | * https://github.com/fuentesp/UCDebug 4 | * Copyright (C) 2018 University of Cantabria 5 | * 6 | * !UCDebug was developed by the Computer Architecture and Technology 7 | * Group at the University of Cantabria. A comprehensive list of authors 8 | * can be found in the file AUTHORS.txt. 9 | * 10 | * You can reach the main developers at {fernando.vallejo, cristobal.camarero, 11 | * pablo.fuentes}@unican.es. 12 | * 13 | * This program is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | */ 26 | 27 | /*Public Functions*/ 28 | wimp_w ConsWinCreate(int PosX, int PosY); 29 | void ConsEnterKey(wimp_w ConsWin); 30 | void ConsUpKey(wimp_w ConsWin); 31 | void ConsDownKey(wimp_w ConsWin); 32 | void ConsEscapeKey(wimp_w ConsWin); 33 | void ConsSetActive(wimp_w ConsWin); 34 | void ConsWrite(wimp_w ConsWin, char *text); 35 | void ActivateCons(wimp_w ConsWin); 36 | wimp_w UsrWinCreate(int PosX, int PosY); 37 | void UsrWrite(wimp_w UsrWin, char *text); 38 | -------------------------------------------------------------------------------- /h/DataWin: -------------------------------------------------------------------------------- 1 | /* 2 | * !UCDebug, ARM debugger for RISC OS. 3 | * https://github.com/fuentesp/UCDebug 4 | * Copyright (C) 2018 University of Cantabria 5 | * 6 | * !UCDebug was developed by the Computer Architecture and Technology 7 | * Group at the University of Cantabria. A comprehensive list of authors 8 | * can be found in the file AUTHORS.txt. 9 | * 10 | * You can reach the main developers at {fernando.vallejo, cristobal.camarero, 11 | * pablo.fuentes}@unican.es. 12 | * 13 | * This program is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | */ 26 | 27 | #include "main.h" 28 | 29 | /*Public Types*/ 30 | struct DataType { 31 | wimp_i I_Addr; 32 | wimp_i I_Data; 33 | wimp_i I_ASCII; 34 | char T_Addr[PrintedWordSize + 1]; 35 | char T_Data[MemHexBlockSize]; 36 | char T_ASCII[MemAsciiBlockSize]; 37 | char V_Addr[ValStrSize + 1]; 38 | char V_Data[ValStrSize + 1]; 39 | char V_ASCII[ValStrSize + 1]; 40 | }; 41 | 42 | /*Public Vars*/ 43 | extern struct DataType *DataIcons; 44 | 45 | /*Public Function Protos*/ 46 | wimp_w DataWinCreate(int startAddr, int numAddrs, int displayType, int PosX, int PosY); 47 | void DataWinRedraw(wimp_w DataWin, int startAddr, int numAddrs, int displayType); 48 | void DataWinTerminate(); 49 | -------------------------------------------------------------------------------- /h/FPRegsWin: -------------------------------------------------------------------------------- 1 | /* 2 | * !UCDebug, ARM debugger for RISC OS. 3 | * https://github.com/fuentesp/UCDebug 4 | * Copyright (C) 2018 University of Cantabria 5 | * 6 | * !UCDebug was developed by the Computer Architecture and Technology 7 | * Group at the University of Cantabria. A comprehensive list of authors 8 | * can be found in the file AUTHORS.txt. 9 | * 10 | * You can reach the main developers at {fernando.vallejo, cristobal.camarero, 11 | * pablo.fuentes}@unican.es. 12 | * 13 | * This program is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | */ 26 | 27 | /* Public Types */ 28 | struct FPRegType { 29 | wimp_i I_Name; 30 | wimp_i I_Val; 31 | wimp_i I_FPval; 32 | char T_Name[FPRegNameSize + 1]; 33 | char T_Val[PrintedWordSize + 1]; 34 | char T_FPval[PrintedDoubleSize + 1]; 35 | char V_Name[ValStrSize + 1]; 36 | char V_Val[ValStrSize + 1]; 37 | char V_FPval[ValStrSize + 1]; 38 | }; 39 | 40 | /* Public Vars*/ 41 | extern struct FPRegType FPRegsIcons[34]; 42 | 43 | /* Public Functions */ 44 | wimp_w FPRegsWinCreate(int PosX, int PosY); 45 | void ToggleWinDisplay(wimp_w FPRegsWin); 46 | void FPRegsWinRedraw(wimp_w CodeWin); 47 | 48 | -------------------------------------------------------------------------------- /h/Help: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuentesp/UCDebug/78c89c71bd80b7ebdeedc49f854bc3bf8a255c96/h/Help -------------------------------------------------------------------------------- /h/Interpreter: -------------------------------------------------------------------------------- 1 | /* 2 | * !UCDebug, ARM debugger for RISC OS. 3 | * https://github.com/fuentesp/UCDebug 4 | * Copyright (C) 2018 University of Cantabria 5 | * 6 | * !UCDebug was developed by the Computer Architecture and Technology 7 | * Group at the University of Cantabria. A comprehensive list of authors 8 | * can be found in the file AUTHORS.txt. 9 | * 10 | * You can reach the main developers at {fernando.vallejo, cristobal.camarero, 11 | * pablo.fuentes}@unican.es. 12 | * 13 | * This program is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | */ 26 | 27 | void interpreter(char *linea); 28 | void help(); 29 | void printAuthors(); 30 | void loadFile(char *filename); 31 | void resetMemView(); 32 | void setMemView(int startDir); 33 | void resetCodeView(); 34 | void setCodeView(int startDir); 35 | int getAddr(char *str); 36 | unsigned int getVal(char *str); 37 | void setMem(int addr, int val, int size); 38 | void resetCodeView(); 39 | -------------------------------------------------------------------------------- /h/RegsWin: -------------------------------------------------------------------------------- 1 | /* 2 | * !UCDebug, ARM debugger for RISC OS. 3 | * https://github.com/fuentesp/UCDebug 4 | * Copyright (C) 2018 University of Cantabria 5 | * 6 | * !UCDebug was developed by the Computer Architecture and Technology 7 | * Group at the University of Cantabria. A comprehensive list of authors 8 | * can be found in the file AUTHORS.txt. 9 | * 10 | * You can reach the main developers at {fernando.vallejo, cristobal.camarero, 11 | * pablo.fuentes}@unican.es. 12 | * 13 | * This program is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | */ 26 | 27 | /* Public Types */ 28 | struct RegType { 29 | wimp_i I_Name; 30 | wimp_i I_Val; 31 | char T_Name[RegNameSize + 1]; 32 | char T_Val[PrintedWordSize + 1]; 33 | char V_Name[ValStrSize + 1]; 34 | char V_Val[ValStrSize + 1]; 35 | }; 36 | 37 | /* Public Vars*/ 38 | extern struct RegType RegsIcons[20]; 39 | 40 | /* Public Functions */ 41 | wimp_w RegsWinCreate(int PosX, int PosY); 42 | void RegsWinRedraw(wimp_w CodeWin); 43 | void UpdateLastShownCtx(); 44 | -------------------------------------------------------------------------------- /h/ibar: -------------------------------------------------------------------------------- 1 | /* 2 | * !UCDebug, ARM debugger for RISC OS. 3 | * https://github.com/fuentesp/UCDebug 4 | * Copyright (C) 2018 University of Cantabria 5 | * 6 | * !UCDebug was developed by the Computer Architecture and Technology 7 | * Group at the University of Cantabria. A comprehensive list of authors 8 | * can be found in the file AUTHORS.txt. 9 | * 10 | * You can reach the main developers at {fernando.vallejo, cristobal.camarero, 11 | * pablo.fuentes}@unican.es. 12 | * 13 | * This program is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | */ 26 | 27 | #include "main.h" 28 | 29 | /* Public Types */ 30 | struct InfoType { 31 | char Text[InfoTextSize + 1]; 32 | char Validation[InfoTextSize + 1]; 33 | }; 34 | 35 | /* Public vars */ 36 | extern struct InfoType InfoIcons[8]; 37 | extern wimp_w InfoWin; 38 | 39 | /* Public functions */ 40 | void ibar_initialise(void); 41 | wimp_w open_window(char *Title, int SizeX, int SizeY, int PosX, int PosY, int VisX, 42 | int VisY, int ScH, int ScV, int Buttons); 43 | wimp_i TextIconCreate(wimp_w WinHandle, int PosX, int PosY, int Width, int Height, 44 | char *Text, int Length, char *Validation); 45 | wimp_i IconCreate(wimp_w WinHandle, int PosX, int PosY, int Width, int Height, 46 | int flags, char *Text, int Length, char *Validation); 47 | void UpdateWindow(wimp_w WinHandle); 48 | void ResetWindow(wimp_w WinHandle, int SizeX, int SizeY, int PosX, int PosY, int ScH, 49 | int ScV, wimp_w NextW); 50 | void IconiseWindow(wimp_w WinHandle); 51 | void ChTextFGColour(wimp_w WinHandle, wimp_i IconHandle, int color); 52 | void ChTextBGColour(wimp_w WinHandle, wimp_i IconHandle, int color); 53 | void InitialiseIconbarMenu(); 54 | void FreeIconbarMenu(); 55 | void OpenIconbarMenu(wimp_pointer pt); 56 | -------------------------------------------------------------------------------- /h/main: -------------------------------------------------------------------------------- 1 | /* 2 | * !UCDebug, ARM debugger for RISC OS. 3 | * https://github.com/fuentesp/UCDebug 4 | * Copyright (C) 2018 University of Cantabria 5 | * 6 | * !UCDebug was developed by the Computer Architecture and Technology 7 | * Group at the University of Cantabria. A comprehensive list of authors 8 | * can be found in the file AUTHORS.txt. 9 | * 10 | * You can reach the main developers at {fernando.vallejo, cristobal.camarero, 11 | * pablo.fuentes}@unican.es. 12 | * 13 | * This program is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | */ 26 | 27 | /* GLOBAL CONSTANTS */ 28 | #ifndef MAIN 29 | #define MAIN 30 | 31 | #define AppName "UCDebug" 32 | #define AppPurpose "ARM Debugger for RISC OS" 33 | #define AppAuthors "ATC group | UC" 34 | #define AppVersion "1.8.11" 35 | #define AppDate " (14 - Sep - 2021)" 36 | #define SpriteName "!ucdebug" 37 | #define TextFontName "\\FCorpus.Medium" 38 | #define CharSizeX 19 39 | #define CharSizeY 35 40 | #define LinSizeY (CharSizeY+5) 41 | #define VisRows 12 42 | #define ConsLinTot 80 43 | #define ConsLinVis 8 44 | #define ConsLinSize 65 45 | #define ComBufNumEntries 15 46 | #define PrintedWordSize 11 47 | #define PrintedFloatSize 14 48 | #define PrintedDoubleSize 22 49 | #define MemHexBlockSize 63 50 | #define MemAsciiBlockSize 18 51 | #define DisasInstrSize 41 52 | #define RegNameSize 9 53 | #define FPRegNameSize 6 54 | #define InfoTextSize 40 55 | #define ValStrSize 12 56 | #define WinTitleSize 20 57 | #define NumLinCode 25 58 | #define NumLinData 25 59 | #define NumLinUsrCon 25 60 | #define NumColUsrCon 80 61 | #define MenuWidth 50 62 | #define MenuHeight 45 63 | #define MenuGap 0 64 | #define MenuEntryLen 12 65 | #define CodeWinName "Code" 66 | #define DataWinName "Data" 67 | #define RegsWinName "CPU Registers" 68 | #define ConsWinName "UCDebug" 69 | #define UsrWinName "I/O Console" 70 | #define FPRegsWinName "FP Registers" 71 | #define Prompt "Dbg>" 72 | #define PromptRUN "RUN>" 73 | #define PromptSize 4 74 | #define AddrMask 0x10000 75 | #define OffElfFile 0x8000 76 | #define OffStartCode 0x8088 77 | #define OffStartData 0x9000 78 | #define DebugAreaSize 0x20000 79 | #define StackSize 0x1E00 80 | #define MaxBrPoints 256 81 | 82 | #define PC_FG_Colour 0x7 /* BLACK */ 83 | #define PC_BG_Colour 0xA /* LIGHT_GREEN */ 84 | #define Brk_FG_Colour 0x7 /* BLACK */ 85 | #define Brk_BG_Colour 0xB /* RED */ 86 | 87 | /* ExecType Values */ 88 | #define Stop_Ex 0x0000 89 | #define Run_Go 0x0001 90 | #define Run_Tr 0x0002 91 | #define Run_Gt 0x0003 92 | #define Run_Gd 0x0004 93 | #define Run_Gf 0x0010 94 | #define Prg_End 0x0100 95 | #define SWI_WrC 0x0200 96 | #define SWI_WrL 0x0300 97 | #define SWI_EnOS 0x0400 98 | #define SWI_LeOS 0x0500 99 | #define SWI_GeC 0x0600 100 | #define Stop_Br 0x1000 101 | #define Ex_DAb 0x1100 102 | #define Ex_IIns 0x1200 103 | #define Ex_PAb 0x1300 104 | #define Ex_OoR 0x1400 105 | #define Ex_DnA 0x1500 106 | #define Ex_DnR 0x1600 107 | #define Ex_VFP 0x1700 108 | #define Ex_TMB 0x1800 109 | #define StateByteMask 0xFF00 110 | #define StateTypeMask 0xF000 111 | #define CmdByteMask 0x00FF 112 | #define SWI_Ex_Mask 0x0F00 113 | #define Skip_Inst 0x10000 114 | 115 | /* ELF file-related constants */ 116 | #define OffEntryPoint 0x18 117 | #define OffElfHeadSize 0x28 118 | #define OffPrHeadSize 0x2A 119 | #define OffPrHeadEntries 0x2C 120 | #define OffVirtAddr 0x8 121 | #define OffCodeEnd 0x58 122 | 123 | /* VISIBLE SIZE OF THE WINDOWS */ 124 | #define CodeWinSizeX (ConsLinSize*CharSizeX) 125 | #define CodeWinSizeY (VisRows*LinSizeY) 126 | #define DataWinSizeX (90*CharSizeX) 127 | #define DataWinSizeY (VisRows*LinSizeY) 128 | #define ConsWinSizeX (ConsLinSize*CharSizeX) 129 | #define ConsWinSizeY (ConsLinVis*LinSizeY) 130 | #define RegsWinSizeX (DataWinSizeX-CodeWinSizeX) 131 | #define RegsWinSizeY ((CodeWinSizeY+ConsWinSizeY)+39) 132 | #define FPRegsWinSizeX (RegsWinSizeX*1.3) 133 | #define FPRegsWinSizeY (34*LinSizeY+25) 134 | #define UsrConsWinSizeX (40*CharSizeX) 135 | #define UsrConsWinSizeY (10*LinSizeY) 136 | 137 | /* POSITION OF THE WINDOWS */ 138 | #define PosXConsWin 30 139 | #define PosYConsWin 135 140 | #define PosXCodeWin (PosXConsWin+0) 141 | #define PosYCodeWin (PosYConsWin+((ConsLinVis+1)*LinSizeY)) 142 | #define PosXDataWin (PosXConsWin+0) 143 | #define PosYDataWin (PosYConsWin+((ConsLinVis+VisRows+2)*LinSizeY)) 144 | #define PosXRegsWin (PosXConsWin+(ConsLinSize*CharSizeX)+39) 145 | #define PosYRegsWin (PosYConsWin+0) 146 | #define PosXFPRegsWin (PosXRegsWin+RegsWinSizeX) 147 | #define PosYFPRegsWin (PosYRegsWin-26) 148 | #define PosXUsrWin 750 149 | #define PosYUsrWin 1050 150 | 151 | /* PUBLIC TYPES */ 152 | struct ContextType { 153 | int Regs[16]; 154 | int CPSR; 155 | float FPRegs[32]; 156 | int FPSCR; 157 | int SvcRegs[3]; 158 | int AbtRegs[3]; 159 | int UndRegs[3]; 160 | int IrqRegs[3]; 161 | int FiqRegs[8]; 162 | }; 163 | 164 | /* Screen status of a window */ 165 | enum WinScreenStatus { 166 | wss_ON_SCREEN, // The window is currently displayed 167 | wss_OFF_SCREEN, // The window is iconised/hidden 168 | wss_CLOSED, // The window is closed 169 | wss_CONS_WIN_ATTACHED// The window has been iconised altogether with the Console Window 170 | }; 171 | 172 | /* Offsets to the Window Status structure */ 173 | #define CodeWinOffset 0 174 | #define DataWinOffset 1 175 | #define RegsWinOffset 2 176 | #define ConsWinOffset 3 177 | #define UsrWinOffset 4 178 | #define FPRegsWinOffset 5 179 | 180 | /*COMMON GLOBAL VARIABLES */ 181 | extern char DEBUG_AREA[DebugAreaSize]; 182 | extern int ControllerBaseAddress; 183 | extern osbool mainQuitFlag; 184 | extern int memDispType; 185 | extern struct ContextType CurContext; 186 | extern int LastShownContext[18]; 187 | extern int AddrElfFile; 188 | extern int AddrCodeStart; 189 | extern int AddrCodeCur; 190 | extern int AddrCodeEnd; 191 | extern int AddrDataStart; 192 | extern int AddrDataCur; 193 | extern int BrkPtList[]; 194 | extern int CurNumBr; 195 | extern int GTBrkP; 196 | extern int ExecType; 197 | extern int DebugAreaStart; 198 | extern int DebugAreaEnd; 199 | extern char CodeWinTitle[WinTitleSize]; 200 | extern char DataWinTitle[WinTitleSize]; 201 | extern char RegsWinTitle[WinTitleSize]; 202 | extern char ConsWinTitle[WinTitleSize]; 203 | extern char UsrWinTitle[WinTitleSize]; 204 | extern char FPRegsWinTitle[WinTitleSize]; 205 | extern wimp_t AppTask; 206 | extern wimp_w CodeWin; 207 | extern wimp_w DataWin; 208 | extern wimp_w RegsWin; 209 | extern wimp_w ConsWin; 210 | extern wimp_w UsrWin; 211 | extern wimp_w FPRegsWin; 212 | extern enum WinScreenStatus WindowStates[]; /* Track status of the windows */ 213 | extern int NumWindows; 214 | extern wimp_w* WinHandles[]; 215 | extern osbool FPdispDoublePrec; 216 | extern wimp_menu *IconBarMenu; 217 | extern font_f AppFont; 218 | 219 | /* COMMON GLOBAL FUNCTIONS */ 220 | void mainPoll(void); 221 | bool validMemAddressRange(int addr); 222 | bool alignedAddr(int addr); 223 | void PrintBrk(); 224 | void ToggleBrk(int brkAddr); 225 | void ClrBrk(); 226 | void EnableFPU(); 227 | void CodeExecute(); 228 | void SetPrompt(char prompt[]); 229 | void handleMenuSelection(wimp_selection *selection); 230 | 231 | #endif 232 | -------------------------------------------------------------------------------- /s/Brkpts: -------------------------------------------------------------------------------- 1 | @ !UCDebug, ARM debugger for RISC OS. 2 | @ https://github.com/fuentesp/UCDebug 3 | @ Copyright (C) 2018 University of Cantabria 4 | @ 5 | @ !UCDebug was developed by the Computer Architecture and Technology 6 | @ Group at the University of Cantabria. A comprehensive list of authors 7 | @ can be found in the file AUTHORS.txt. 8 | @ 9 | @ You can reach the main developers at {fernando.vallejo, cristobal.camarero, 10 | @ pablo.fuentes}@unican.es. 11 | @ 12 | @ This program is free software: you can redistribute it and/or modify 13 | @ it under the terms of the GNU General Public License as published by 14 | @ the Free Software Foundation, either version 3 of the License, or 15 | @ (at your option) any later version. 16 | @ 17 | @ This program is distributed in the hope that it will be useful, 18 | @ but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | @ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | @ GNU General Public License for more details. 21 | @ 22 | @ You should have received a copy of the GNU General Public License 23 | @ along with this program. If not, see . 24 | 25 | .include "s/Constants" 26 | 27 | .global setfastbreakpoints 28 | .global immediatebreakpointnumber 29 | .global immediatebreakpoints 30 | .global setimmediatebreakpoints 31 | .global clearimmediatebreakpoints 32 | .extern CurContext 33 | .extern BrkPtList 34 | .extern CurNumBr 35 | .extern CheckInstCond 36 | .extern validMemAddressRange 37 | .extern IRQFinishHandler 38 | 39 | .data 40 | 41 | .align 2 42 | immediatebreakpointnumber: .word 0 43 | immediatebreakpoints: .space 0x800 @256 pairs (address, instruction) 44 | 45 | .align 2 46 | 47 | .text 48 | 49 | 50 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 51 | @ 52 | @ Set breakpoints for go-fast mode (at every breakpoint established by the user) 53 | @ 54 | setfastbreakpoints: 55 | ldr lr, =jtp 56 | stmdb sp!, {r4-r6, lr} 57 | ldr r4, =BrkpInst 58 | ldr r5, =immediatebreakpoints 59 | ldr r6, =immediatebreakpointnumber 60 | mov r0, #0 61 | str r0, [r6] @ Reset # of breakpoints 62 | 63 | @ Now checked the breakpoints established by the user; 64 | @ check if any matches one already set 65 | ldr r0,=CurNumBr 66 | ldr r0,[r0] @ Load the number of BreakPoints 67 | cmp r0, #0 68 | beq sfb_return @ if no breakpoints, return from routine 69 | ldr r1, =BrkPtList @ pointer to BreakPoints List 70 | sfb_loop2: 71 | ldr r2, [r1], #4 @ get address of the breakpoint 72 | ldr r3, =CurContext 73 | ldr r3, [r3, #60] @ get PC 74 | cmp r2, r3 75 | beq sfb_checkloop2 @ do not place brkpt in current PC 76 | ldr r3, [r2] 77 | cmp r3, r4 @ check if a breakpoint is already in place 78 | beq sfb_checkloop2 79 | str r2, [r5], #4 @ save address 80 | str r3, [r5], #4 @ save content 81 | str r4, [r2] @ set the bkpt 82 | ldr r3, [r6] 83 | add r3, r3, #1 @ increase breakpoint counter 84 | str r3, [r6] @ store the breakpoint counter 85 | 86 | sfb_checkloop2: 87 | subs r0, r0, #1 88 | bne sfb_loop2 89 | 90 | sfb_return: 91 | mov r0,#0 @ flags, 0 for all memory 92 | @ update the whole code (from the beginning of ELF file to beginning of data 93 | @ section) 94 | ldr r1, =AddrElfFile 95 | ldr r1, [r1] 96 | ldr r2, =AddrCodeEnd 97 | ldr r2, [r2] 98 | swi OS_SynchronizeCodeAreas 99 | 100 | ldmia sp!, {r4-r6, pc} 101 | 102 | 103 | 104 | 105 | 106 | 107 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 108 | @ 109 | @ set a breakpoint in the loaded program after its pc and on potential branches 110 | @ Register use: 111 | @ -r0-r3: aux vars 112 | @ -r4: user PC 113 | @ -r5: next instruction to execute 114 | @ -r6: current context structure (bank of registers from the user) 115 | @ -r7: masked instruction (to execute and determine next PC) 116 | @ 117 | setimmediatebreakpoints: 118 | stmdb sp!, {r4-r7, lr} 119 | bl loadAuxCurContext @ update aux table to get regs from current user mode 120 | ldr r6, =AuxCurContext 121 | ldr r4, [r6, #60] @ get PC 122 | ldr r5, [r4] @ instruction to be executed 123 | 124 | @ Check if instruction will be executed; otherwise, next inst is PC+4 125 | and r0, r5, #Cond_Mask @ get condition field from the instruction 126 | cmp r0, #Alw_Exec_Inst 127 | beq sib_checkbranch @ inconditional exec, check type of inst 128 | 129 | @ conditional execution 130 | lsr r0, r0, #28 @ place condition field at the least significant bits 131 | ldr r1, [r6, #OffCpsr] @ load CPSR from CurContext 132 | bl CheckInstCond 133 | cmp r0, #0 134 | beq sib_nextinst @ the instruction will not be exec'ed, next @ is PC+4 135 | 136 | sib_checkbranch: @ check if the instruction is a B/BL 137 | and r0, r5, #BrInstMask @ mask to get instruction type 138 | cmp r0, #BrInst 139 | bne sib_checkldm 140 | bic r0, r5, #0xFF000000 @ get 24-bit immediate field 141 | tst r0, #0x00800000 @ if the most significant bit is 1, 142 | orrne r0, r0, #0xFF000000 @ the imm is negative => extend the sign 143 | add r0, r4, r0, LSL #2 @ PC + immediate * 4 144 | add r0, r0, #8 @ + 8 145 | b sib_setbrk 146 | 147 | sib_checkldm: @ check if the instruction is a LDM 148 | and r0, r5, #LdmInstMask @ mask to get instruction type 149 | cmp r0, #LdmInst @ check if the instruction is a LDM 150 | bne sib_checkdprs 151 | ands r0, r5, #MaskLdmPcField @ check if the PC is updated in the LDM 152 | beq sib_nextinst @ the PC will not be updated, next @ is PC+4 153 | ldr r0, =0x7FFF @ mask to get the number of regs loaded, including PC 154 | and r0, r5, r0 @ list of regs loaded (1 bit per reg) 155 | mov r1, #0 @ counter of number of registers 156 | sib_loop_ldm: 157 | ands r2, r0, #1 @ test least significant bit 158 | addne r1, r1, #1 @ if bit=1, increase count 159 | lsrs r0, r0, #1 @ discard that bit 160 | bne sib_loop_ldm 161 | and r0, r5, #MaskRnField @ get field 'register with the base address' 162 | ldr r0, [r6, r0, LSR #14] @ base address=mem(CurContext+reg with base @ * 4) 163 | and r2, r5, #0x01800000 @ get addressing mode field from the instruction 164 | lsr r2, r2, #23 165 | cmp r2, #1 166 | ldreq r0, [r0, r1, LSL #2] @ IA => base address + off * 4 167 | cmp r2, #2 168 | ldreq r0, [r0, #-4] @ DB => base address - 4 169 | cmp r2, #3 170 | addeq r1, #1 171 | ldreq r0, [r0, r1, LSL #2] @ IB => base address + (off * 4) + 4 172 | cmp r2, #0 173 | ldreq r0, [r0] @ DA => base address 174 | b sib_setbrk 175 | 176 | sib_checkdprs: @ check if it is a data processing register shift 177 | ldr r0, =DprsInstMask @ mask to get instruction type 178 | and r0, r5, r0 179 | cmp r0, #DprsInst 180 | bne sib_checkdpis 181 | and r0, r5, #MiscInstMask @ mask to see if it is a misc instr 182 | cmp r0, #MiscInst @ check if misc instr 183 | beq sib_nextinst 184 | and r0, r5, #MaskRdField @ check if the dest reg is PC 185 | cmp r0, #MaskRdField 186 | bne sib_nextinst @ the PC will not be updated, next @ is PC+4 187 | ldr r0, =Cond_Mask+MaskRdField+MaskRnField+MaskRsField+MaskRmField 188 | bic r7, r5, r0 @ Clear 'cond', 'Rd', 'Rn', 'Rm' and 'Rs' fields 189 | ldr r0, =Alw_Exec_Inst+MaskR0asRd+MaskR1asRn+MaskR2asRm+MaskR3asRs 190 | orr r7, r7, r0 @ set cond=AL, Rd=r0, Rn=r1, Rm=r2, Rs=r3 191 | b sib_grfi_arg3 192 | 193 | sib_checkdpis: @ check if it is a load with reg offset or 194 | @ a data processing immediate shift 195 | ldr r0, =LroInstMask @ mask to get instruction type 196 | and r0, r5, r0 197 | cmp r0, #LroInst @ check if load with reg offset 198 | ldrne r0, =DpisInstMask @ mask to get instruction type 199 | andnes r0, r5, r0 @ check if data processing immediate shift 200 | bne sib_checkdpi 201 | ldr r0, =Misc2InstMask @ mask to see if a misc instr 202 | and r0, r5, r0 203 | cmp r0, #Misc2Inst @ check if it is a misc instr 204 | beq sib_nextinst 205 | and r0, r5, #MaskRdField @ check if the dest reg is PC 206 | cmp r0, #MaskRdField 207 | bne sib_nextinst @ the PC will not be updated, next @ is PC+4 208 | ldr r0, =Cond_Mask+MaskRdField+MaskRnField+MaskRmField 209 | bic r7, r5, r0 @ mask to clear 'cond', 'Rd', 'Rn', and 'Rm' fields 210 | ldr r0, =Alw_Exec_Inst+MaskR0asRd+MaskR1asRn+MaskR2asRm 211 | orr r7, r7, r0 @ set cond=AL, Rd=r0, Rn=r1, Rm=r2 212 | b sib_grfi_arg2 213 | 214 | sib_checkdpi: @ check if instruction is a data processing immediate 215 | @ or a load with immediate offset 216 | and r0, r5, #DpiInstMask @ mask to get instruction type 217 | cmp r0, #DpiInst @ check if data processing immediate 218 | andne r0, r5, #LimInstMask 219 | cmpne r0, #LimInst @ check if load immediate offset 220 | bne sib_nextinst @ none of the instructions that affect PC, next @ is PC+4 221 | and r0, r5, #MaskRdField @ check if the dest reg is PC 222 | cmp r0, #MaskRdField 223 | bne sib_nextinst @ the PC will not be updated, next @ is PC+4 224 | ldr r0, =Cond_Mask+MaskRdField+MaskRnField 225 | bic r7, r5, r0 @ mask to clear 'cond', 'Rd', and 'Rn' fields 226 | ldr r0, =Alw_Exec_Inst+MaskR0asRd+MaskR1asRn 227 | orr r7, r7, r0 @ set cond=AL, Rd=r0, Rn=r1 228 | b sib_grfi_arg1 229 | 230 | sib_grfi_arg3: @ load in r3 the value of the Rs from the inst 231 | and r3, r5, #MaskRsField @ get Rs 232 | ldr r3, [r6, r3, LSR #6] @ r3 = mem(CurContext + Rs * 4) 233 | sib_grfi_arg2: @ load in r2 the value of the Rm from the inst 234 | and r2, r5, #MaskRmField @ get Rm 235 | ldr r2, [r6, r2, LSL #2] @ r2 = mem(CurContext + Rm * 4) 236 | sib_grfi_arg1: 237 | and r1, r5, #MaskRnField @ get Rn 238 | ldr r1, [r6, r1, LSR #14] @ r1 = mem(CurContext + Rn * 4) 239 | ldr r0, =GetResultFromInst 240 | str r7, [r0] @ store instruction to exec it 241 | mov r0, #0 @ flags, 0 for all memory 242 | swi OS_SynchronizeCodeAreas 243 | bl GetResultFromInst 244 | b sib_setbrk @ set the breakpoint at the future PC 245 | 246 | sib_nextinst: @ Consecutive execution: next inst is at PC+4 247 | add r0, r4, #4 248 | 249 | sib_setbrk: @ Set the breakpoint 250 | @stmdb sp!, {r0-r3} @ store context to keep it after function call 251 | @bl validMemAddressRange 252 | @cmp r0, #0 253 | @ldmia sp!, {r0-r3} 254 | sub sp, sp, #4 255 | str r1, [sp] 256 | ldr r1, =IRQFinishHandler 257 | cmp r0, r1 258 | ldr r1, [sp] 259 | add sp, sp, #4 260 | beq sib_end @ if address is IRQFinishHandler, do not place breakpoint 261 | ldr r1, [r0] @ instruction to be saved 262 | ldr r2, =immediatebreakpoints 263 | str r0, [r2], #4 @ save address 264 | str r1, [r2], #4 @ save content 265 | ldr r1, =BrkpInst 266 | str r1, [r0] @ set the bkpt 267 | mov r0, #1 @ breakpoint counter 268 | ldr r1, =immediatebreakpointnumber 269 | str r0, [r1] @ store the breakpoint counter 270 | 271 | mov r0,#0 @ flags, 0 for all memory 272 | swi OS_SynchronizeCodeAreas 273 | sib_end: 274 | ldmia sp!, {r4-r7, pc} 275 | 276 | 277 | GetResultFromInst: 278 | bkpt @brkpt to provoke a prefetch abort (this inst should be replaced) 279 | mov pc, lr 280 | 281 | 282 | 283 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 284 | @ 285 | @ Remove the breakpoints 286 | @ 287 | clearimmediatebreakpoints: 288 | ldr r3,=immediatebreakpoints 289 | ldr r0,[r3,#-4] @ number of breakpoints 290 | cmp r0,#0 291 | moveq pc,lr 292 | clearimmediatebreakpoints_loop: 293 | ldr r1,[r3],#4 @ address 294 | ldr r2,[r3],#4 @ content 295 | str r2,[r1] 296 | subs r0,r0,#1 297 | bgt clearimmediatebreakpoints_loop 298 | mov r0,#0 @ all memory 299 | swi OS_SynchronizeCodeAreas 300 | mov pc,lr 301 | 302 | 303 | 304 | 305 | 306 | .end 307 | -------------------------------------------------------------------------------- /s/Constants: -------------------------------------------------------------------------------- 1 | @ SWIs 2 | .equ OS_ClaimProcessorVector, 0x69 3 | .equ OS_EnterOS, 0x16 4 | .equ OS_LeaveOS, 0x7C 5 | .equ OS_Memory, 0x68 6 | .equ OS_ReadC, 0x04 7 | .equ OS_Hardware, 0x7A 8 | .equ OS_SynchronizeCodeAreas, 0x6E 9 | .equ OS_ValidateAddress, 0x3A 10 | .equ OS_EnterOSAndSave, 0x45 11 | 12 | @ Hardware-related constants 13 | .equ BCM2835_id, 0x410FB767 14 | .equ BCM2836_id, 0x410FC075 15 | .equ BCM2837_id, 0x410FD034 16 | .equ Pi1_Irq_Addr, 0x2000B000 17 | .equ Pi2_Irq_Addr, 0x3F00B000 18 | .equ Pi1_ST_Addr, 0x20003000 19 | .equ Pi2_ST_Addr, 0x3F003000 20 | 21 | @ Timer constants 22 | .equ GF_Timer_Cycles, 0x10000 23 | .equ STCS, 0x00 24 | .equ STCL0, 0x04 25 | .equ STC2, 0x14 26 | .equ timer_int_bit, 0x04 27 | .equ irq_int_bit, 0b100 28 | 29 | @ Offsets to handle CurContext structure 30 | .equ OffCpsr, 64 31 | .equ OffFPRegs, 68 32 | .equ OffFpscr, 196 33 | .equ OffSvcRegs, 200 34 | .equ OffAbtRegs, 212 35 | .equ OffUndRegs, 224 36 | .equ OffIrqRegs, 236 37 | .equ OffFiqRegs, 248 38 | 39 | @ Masks to disable interrupts and imprecise aborts 40 | .equ MaskDisIRQs, 0x180 @ Disable interrupts and imprecise aborts 41 | .equ MaskDisInt, 0x80 @ Disable interrupts 42 | 43 | 44 | @ Masks to change user mode 45 | .equ MaskSysMode, 0x1F @ Enter System mode 46 | .equ MaskSvcMode, 0x13 @ Enter Supervisor mode 47 | .equ MaskAbtMode, 0x17 @ Enter Abort mode 48 | .equ MaskUndMode, 0x1B @ Enter Undefined mode 49 | .equ MaskIrqMode, 0x12 @ Enter IRQ mode 50 | .equ MaskFiqMode, 0x11 @ Enter FIQ mode 51 | .equ MaskUsrMode, 0x10 @ Enter User mode 52 | 53 | @ Masks for CPSR fields 54 | .equ MaskCpsrFlags, 0xF0000000 55 | .equ MaskNflag, 0x80000000 56 | .equ MaskZflag, 0x40000000 57 | .equ MaskCflag, 0x20000000 58 | .equ MaskVflag, 0x10000000 59 | 60 | @ Masks and machine codes for different instructions 61 | .equ SWI_Mask, 0x0F000000 62 | .equ BrInstMask, 0x0E000000 63 | .equ BrInst, 0x0A000000 64 | .equ LdmInstMask, 0x0E100000 65 | .equ LdmInst, 0x08100000 66 | .equ DprsInstMask, 0x0E000090 67 | .equ DprsInst, 0x00000010 68 | .equ MiscInstMask, 0x0F900000 69 | .equ MiscInst, 0x01000000 70 | .equ LroInstMask, 0x0E100010 71 | .equ LroInst, 0x06100000 72 | .equ DpisInstMask, 0x0E000010 73 | .equ Misc2InstMask, 0x0F900010 74 | .equ Misc2Inst, 0x01000000 75 | .equ DpiInstMask, 0x0E000000 76 | .equ DpiInst, 0x02000000 77 | .equ LimInstMask, 0x0E100000 78 | .equ LimInst, 0x04100000 79 | .equ UmiInstMask, 0x0F900000 80 | .equ UmiInst, 0x03000000 81 | .equ MaskLdmPcField, 0x00008000 82 | .equ MaskRnField, 0x000F0000 83 | .equ MaskRdField, 0x0000F000 84 | .equ MaskRsField, 0x00000F00 85 | .equ MaskRmField, 0x0000000F 86 | .equ MaskR0asRd, 0x00000000 87 | .equ MaskR1asRn, 0x00010000 88 | .equ MaskR2asRm, 0x00000002 89 | .equ MaskR3asRs, 0x00000300 90 | 91 | .equ Cond_Mask, 0xF0000000 92 | .equ Alw_Exec_Inst, 0xE0000000 93 | .equ Code_OSExit, 0x0F000011 94 | .equ Code_OSWriteStr, 0x0F000002 95 | .equ Code_OSWriteChar, 0x0F000000 96 | .equ Code_OSGetChar, 0x0F000004 97 | .equ Code_OSEnterOS, 0x0F000016 98 | .equ Code_OSLeaveOS, 0x0F00007C 99 | .equ Code_OSClaimDeviceVector, 0x0F00004B 100 | .equ Code_OSReleaseDeviceVector, 0x0F00004C 101 | .equ Code_OSHardware, 0x0F00007A 102 | .equ Code_OSEnterOSAndSave, 0x0F000045 103 | .equ BrkpInst, 0xE1200071 104 | 105 | .equ Num_Loop, 1000 106 | 107 | /* ExecType Values */ 108 | .equ Stop_Ex, 0x0000 109 | .equ Run_Go, 0x0001 110 | .equ Run_Tr, 0x0002 111 | .equ Run_Gt, 0x0003 112 | .equ Run_Gd, 0x0004 113 | .equ Run_Gf, 0x0010 114 | .equ Prg_End, 0x0100 115 | .equ SWI_WrC, 0x0200 116 | .equ SWI_WrL, 0x0300 117 | .equ SWI_EnOS, 0x0400 118 | .equ SWI_LeOS, 0x0500 119 | .equ SWI_GeC, 0x0600 120 | .equ Stop_Br, 0x1000 121 | .equ Ex_DAb, 0x1100 122 | .equ Ex_IIns, 0x1200 123 | .equ Ex_PAb, 0x1300 124 | .equ Ex_OoR, 0x1400 125 | .equ Ex_DnA, 0x1500 126 | .equ Ex_DnR, 0x1600 127 | .equ Ex_VFP, 0x1700 128 | .equ Ex_TMB, 0x1800 129 | .equ StateByteMask, 0xFF00 130 | .equ StateTypeMask, 0xF000 131 | .equ CmdByteMask, 0x00FF 132 | .equ SWI_Ex_Mask, 0x0F00 133 | .equ Skip_Inst, 0x10000 134 | .equ SWI_NC, 0x20000 135 | 136 | .equ MaxBrPoints, 256 137 | 138 | 139 | /* Address validation constants */ 140 | .equ Partially_Phys, 0x1000 141 | .equ Completely_Phys, 0x100 142 | .equ Completly_User_RW, 0x3 143 | .equ Completly_Priv_RW, 0xC 144 | -------------------------------------------------------------------------------- /s/Misc: -------------------------------------------------------------------------------- 1 | @ !UCDebug, ARM debugger for RISC OS. 2 | @ https://github.com/fuentesp/UCDebug 3 | @ Copyright (C) 2018 University of Cantabria 4 | @ 5 | @ !UCDebug was developed by the Computer Architecture and Technology 6 | @ Group at the University of Cantabria. A comprehensive list of authors 7 | @ can be found in the file AUTHORS.txt. 8 | @ 9 | @ You can reach the main developers at {fernando.vallejo, cristobal.camarero, 10 | @ pablo.fuentes}@unican.es. 11 | @ 12 | @ This program is free software: you can redistribute it and/or modify 13 | @ it under the terms of the GNU General Public License as published by 14 | @ the Free Software Foundation, either version 3 of the License, or 15 | @ (at your option) any later version. 16 | @ 17 | @ This program is distributed in the hope that it will be useful, 18 | @ but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | @ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | @ GNU General Public License for more details. 21 | @ 22 | @ You should have received a copy of the GNU General Public License 23 | @ along with this program. If not, see . 24 | 25 | .include "s/Constants" 26 | 27 | .global EnableFPU 28 | .global DefCurCtx 29 | .global DefStackCtx 30 | .global ResetIRQtable 31 | .extern CurContext 32 | .global AuxCurContext 33 | .extern DebugAreaEnd 34 | .global loadAuxCurContext 35 | .global InitializeDbgKernel 36 | .extern ControllerBaseAddress 37 | .global SWIReadChar 38 | .extern Device 39 | 40 | .data 41 | 42 | .align 2 43 | AuxCurContext: .space 18*4 @ reserve space for 18 regs (R0-r15+CPSR+SPSR) 44 | CtxModeAddrTable: .word 0, CurContext+268, CurContext+236, CurContext+200, CurContext+52, CurContext+52, CurContext+52, CurContext+212, CurContext+52, CurContext+52, CurContext+52, CurContext+224 45 | 46 | .text 47 | 48 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 49 | @ Function used to execute the OS_ReadC SWI 50 | SWIReadChar: 51 | ldr r1, =CurContext 52 | swi OS_ReadC 53 | str r0, [r1] 54 | mov pc, lr 55 | 56 | 57 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 58 | @ Function to activate the FPU (must be executed in privileged mode) 59 | EnableFPU: 60 | mrc p15, 0, r0, c1, c0, 2 @enable FPU 61 | orr r0,r0,#0x300000 @ enable single precision 62 | orr r0,r0,#0xC00000 @ also enable double precision 63 | mcr p15, 0, r0, c1, c0, 2 @at this point, the FPU is enabled to work with single and double precision 64 | mov r0,#0x40000000 65 | VMSR FPEXC,r0 66 | mov pc, lr 67 | 68 | 69 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 70 | @ 71 | @ Set CurContext to Default values 72 | @ 73 | DefCurCtx: 74 | str lr,[sp, #-4]! 75 | str r0,[sp, #-4]! 76 | ldr r0,=CurContext 77 | stm r0,{r0-r15} 78 | ldr r1,[sp], #4 79 | str r1,[r0] @ write program r0 in its place 80 | mrs r1,CPSR 81 | str r1,[r0, #OffCpsr] @ CPSR of the user program 82 | add r2, r0, #OffFPRegs 83 | vstm r2, {s0-s31} @ write floating-point regs 84 | vmrs r3, FPSCR 85 | str r3, [r0, #OffFpscr] @ write FPSCR 86 | ands r2, r1, #0xF @ Mask to select usr mode 87 | swieq OS_EnterOS @ If in user mode, switch to SVC 88 | bic r1, r1, #0xF @ Regardless of previous mode, 89 | orr r1, r1, #0x3 @ switch to SVC mode 90 | msr CPSR, r1 91 | str lr, [r0, #OffSvcRegs+4] @ SVC lr 92 | mrs r2, SPSR 93 | str r2, [r0, #OffSvcRegs+8] @ SVC spsr 94 | bic r1, r1, #0x4 @ Switch from SVC to Abt mode 95 | msr CPSR, r1 96 | str lr, [r0, #OffAbtRegs+4] @ Abt lr 97 | mrs r2, SPSR 98 | str r2, [r0, #OffAbtRegs+8] @ Abt spsr 99 | bic r1, r1, #0xF 100 | orr r1, r1, #0xB @ Switch from Abt to Und mode 101 | msr CPSR, r1 102 | str lr, [r0, #OffUndRegs+4] @ Und lr 103 | mrs r2, SPSR 104 | str r2, [r0, #OffUndRegs+8] @ Und spsr 105 | bic r1, r1, #0x9 106 | msr CPSR, r1 @ Switch from Und to IRQ mode 107 | str lr, [r0, #OffIrqRegs+4] @ IRQ lr 108 | mrs r2, SPSR 109 | str r2, [r0, #OffIrqRegs+8] @ IRQ spsr 110 | bic r1, r1, #0xF 111 | orr r1, r1, #0x1 @ Switch to FIQ mode 112 | msr CPSR, r1 113 | add r2, r0, #OffFiqRegs 114 | stm r2, {r8-r14} @ FIQ regs 115 | mrs r2, SPSR 116 | str r2, [r0, #OffFiqRegs+7*4] @ FIQ spsr 117 | orr r1, r1, #0xF 118 | msr CPSR, r1 @ Switch to SYS mode 119 | str lr, [r0, #56] @ Usr lr 120 | 121 | ldr r1,[r0,#OffCpsr] 122 | msr CPSR, r1 @ Switch back to original mode 123 | 124 | bl DefStackCtx 125 | 126 | ldr pc,[sp], #4 127 | 128 | 129 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 130 | @ 131 | @ Set Stack to Default values for all modes; start by the end of the debugarea 132 | @ and get the nearest lower address aligned to word. From there, dedicate 133 | @ 512Bytes for each stack mode except User, that has 5KB. 134 | @ 135 | DefStackCtx: 136 | 137 | ldr r0,=CurContext 138 | ldr r3, =DebugAreaEnd 139 | ldr r3, [r3] @ To properly set stack, get address of end of debugarea 140 | bic r3, r3, #0x3 @ Ensure the address is aligned to word 141 | str r3, [r0, #OffSvcRegs] @ SVC sp 142 | sub r3, r3, #0x200 @ (stack from SVC spans 512Bytes) 143 | str r3, [r0, #OffAbtRegs] @ Abt sp 144 | sub r3, r3, #0x200 @ (stack from Abt spans 512Bytes) 145 | str r3, [r0, #OffUndRegs] @ Und sp 146 | sub r3, r3, #0x200 @ (stack from Und spans 512Bytes) 147 | 148 | str r3, [r0, #OffIrqRegs] @ IRQ sp 149 | sub r3, r3, #0x200 @ (stack from IRQ spans 512Bytes) 150 | str r3, [r0, #OffFiqRegs+5*4] @ FIQ sp 151 | sub r3, r3, #0x200 @ (stack from FIQ spans 512Bytes) 152 | str r3, [r0, #52] @ Usr sp (will later be updated, when loading program) 153 | 154 | mov pc, lr 155 | 156 | @ 157 | @ Clear IRQ table (mainly for reloading codes) 158 | @ 159 | ResetIRQtable: 160 | ldr r0, =drivercount 161 | mov r1, #0 162 | str r1, [r0] @ set counter to zero 163 | 164 | mov pc, lr 165 | 166 | @ 167 | @ Update the context from the current user mode 168 | @ 169 | loadAuxCurContext: 170 | stmdb sp!, {r0-r12,lr} 171 | ldr r0, =CurContext 172 | ldm r0, {r0-r12} @ Load values from user mode 173 | ldr r0, =AuxCurContext 174 | stm r0, {r0-r12} @ Update them in current user mode 175 | ldr r1, =CurContext 176 | ldr r2, [r1] 177 | str r2, [r0] @ Update r0 in current user mode 178 | add r2, r1, #52 179 | ldm r2, {r3-r6} @ Load sp, lr, pc & cpsr from user mode 180 | add r2, r0, #52 181 | stm r2, {r3-r6} @ Update them in current user mode 182 | ands r6, r6, #0xF @ Get current user mode 183 | beq lACC_end @ User mode 184 | cmp r6, #0xF @ System mode 185 | beq lACC_end 186 | ldr r3, =CtxModeAddrTable 187 | ldr r3, [r3, r6, LSL #2] @ Get @ of the mode to get regs from 188 | ldm r3, {r3-r5} @ Get regs 189 | stm r2, {r3-r4} @ Update sp & lr in current user mode 190 | str r5, [r0, #68] @ Update spsr in current user mode 191 | cmp r6, #0x1 @ If FIQ mode, more regs need to be loaded 192 | bne lACC_end 193 | add r2, r1, #OffFiqRegs 194 | ldm r2, {r3-r7} @ Get FIQ regs 195 | add r2, r0, #32 196 | stm r2, {r3-r7} @ Update regs r0-r12 in current user mode 197 | lACC_end: 198 | ldmia sp!, {r0-r12, pc} 199 | 200 | InitializeDbgKernel: 201 | @ Determine underlying chipset, and load one base interrupt register 202 | @ address or another, depending on which chipset is used. 203 | @ It also maps the systimer and saves the address in a global variable. 204 | swi OS_EnterOS 205 | mrc P15, 0, r0, C0, C0, 0 @ Read CPU ID from Coprocessor 15 reg 0 206 | swi OS_LeaveOS 207 | ldr r2, =BCM2835_id 208 | cmp r0, r2 209 | ldreq r1, =Pi1_Irq_Addr @ base address for ARM interrupt reg 210 | ldr r2, =BCM2836_id 211 | cmp r0, r2 212 | ldreq r1, =Pi2_Irq_Addr @ base address for ARM interrupt reg 213 | ldr r2, =BCM2837_id 214 | cmp r0, r2 215 | ldreq r1, =Pi2_Irq_Addr @ base address for ARM interrupt reg (same for Pi2 and Pi3) 216 | mov r0, #13 217 | mov r2, #0x228 @ 10 IRQ regs + 0x200 offset 218 | swi OS_Memory 219 | ldr r0, =ControllerBaseAddress 220 | str r3, [r0] @ store base address for IRQ regs 221 | 222 | @ Maps the timer to memory 223 | swi OS_EnterOS 224 | mrc P15, 0, r0, C0, C0, 0 @ Read CPU ID from Coprocessor 15 reg 0 225 | swi OS_LeaveOS 226 | ldr r2, =BCM2835_id 227 | cmp r0, r2 228 | ldreq r1, =Pi1_ST_Addr @ base address for System Timer controller 229 | ldr r2, =BCM2836_id 230 | cmp r0, r2 231 | ldreq r1, =Pi2_ST_Addr @ base address for System Timer controller 232 | ldr r2, =BCM2837_id 233 | cmp r0, r2 234 | ldreq r1, =Pi2_ST_Addr @ base address for SysTimer controller (same for Pi2 and Pi3) 235 | mov r0, #13 236 | mov r2, #0x100 237 | swi 0x68 @ OS_Memory 238 | ldr r0,=Device 239 | str r3,[r0] @ Store the address of the timer 240 | mov pc, lr 241 | 242 | 243 | .end 244 | --------------------------------------------------------------------------------