| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716 |
- /***************************************************************************
- * Copyright (C) 2006 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see <http://www.gnu.org/licenses/>. *
- ***************************************************************************/
- #include "protocol.h"
- .text
- .align 4
- @ Disable thumb mode
- .code 32
- @ send word to debugger
- .macro m_send_to_debugger reg
- 1:
- mrc p14, 0, r15, c14, c0, 0
- bvs 1b
- mcr p14, 0, \reg, c8, c0, 0
- .endm
- @ receive word from debugger
- .macro m_receive_from_debugger reg
- 1:
- mrc p14, 0, r15, c14, c0, 0
- bpl 1b
- mrc p14, 0, \reg, c9, c0, 0
- .endm
- @ save register on debugger, small
- .macro m_small_save_reg reg
- mov r0, \reg
- bl send_to_debugger
- .endm
- @ save status register on debugger, small
- .macro m_small_save_psr
- mrs r0, spsr
- bl send_to_debugger
- .endm
- @ wait for all outstanding coprocessor accesses to complete
- .macro m_cpwait
- mrc p15, 0, r0, c2, c0, 0
- mov r0, r0
- sub pc, pc, #4
- .endm
- .global reset_handler
- .global undef_handler
- .global swi_handler
- .global prefetch_abort_handler
- .global data_abort_handler
- .global irq_handler
- .global fiq_handler
- .section .part1 , "ax"
- reset_handler:
- @ read DCSR
- mrc p14, 0, r13, c10, c0
- @ check if global enable bit (GE) is set
- ands r13, r13, #0x80000000
- bne debug_handler
- @ set global enable bit (GE)
- mov r13, #0xc0000000
- mcr p14, 0, r13, c10, c0
- debug_handler:
- @ save r0 without modifying other registers
- m_send_to_debugger r0
- @ save lr (program PC) without branching (use macro)
- m_send_to_debugger r14
- @ save non-banked registers and spsr (program CPSR)
- m_small_save_reg r1
- m_small_save_reg r2
- m_small_save_reg r3
- m_small_save_reg r4
- m_small_save_reg r5
- m_small_save_reg r6
- m_small_save_reg r7
- m_small_save_psr
- mrs r0, spsr
- @ prepare program PSR for debug use (clear Thumb, set I/F to disable interrupts)
- bic r0, r0, #PSR_T
- orr r0, r0, #(PSR_I | PSR_F)
- @ examine mode bits
- and r1, r0, #MODE_MASK
- cmp r1, #MODE_USR
- bne not_user_mode
- @ replace USR mode with SYS
- bic r0, r0, #MODE_MASK
- orr r0, r0, #MODE_SYS
- not_user_mode:
- b save_banked_registers
- @ command loop
- @ wait for command from debugger, than execute desired function
- get_command:
- bl receive_from_debugger
- @ 0x0n - register access
- cmp r0, #0x0
- beq get_banked_registers
- cmp r0, #0x1
- beq set_banked_registers
- @ 0x1n - read memory
- cmp r0, #0x11
- beq read_byte
- cmp r0, #0x12
- beq read_half_word
- cmp r0, #0x14
- beq read_word
- @ 0x2n - write memory
- cmp r0, #0x21
- beq write_byte
- cmp r0, #0x22
- beq write_half_word
- cmp r0, #0x24
- beq write_word
- @ 0x3n - program execution
- cmp r0, #0x30
- beq resume
- cmp r0, #0x31
- beq resume_w_trace
- @ 0x4n - coprocessor access
- cmp r0, #0x40
- beq read_cp_reg
- cmp r0, #0x41
- beq write_cp_reg
- @ 0x5n - cache and mmu functions
- cmp r0, #0x50
- beq clean_d_cache
- cmp r0, #0x51
- beq invalidate_d_cache
- cmp r0, #0x52
- beq invalidate_i_cache
- cmp r0, #0x53
- beq cpwait
- @ 0x6n - misc functions
- cmp r0, #0x60
- beq clear_sa
- cmp r0, #0x61
- beq read_trace_buffer
- cmp r0, #0x62
- beq clean_trace_buffer
- @ return (back to get_command)
- b get_command
- @ ----
- @ resume program execution
- resume:
- @ restore CPSR (SPSR_dbg)
- bl receive_from_debugger
- msr spsr, r0
- @ restore registers (r7 - r0)
- bl receive_from_debugger @ r7
- mov r7, r0
- bl receive_from_debugger @ r6
- mov r6, r0
- bl receive_from_debugger @ r5
- mov r5, r0
- bl receive_from_debugger @ r4
- mov r4, r0
- bl receive_from_debugger @ r3
- mov r3, r0
- bl receive_from_debugger @ r2
- mov r2, r0
- bl receive_from_debugger @ r1
- mov r1, r0
- bl receive_from_debugger @ r0
- @ resume addresss
- m_receive_from_debugger lr
- @ branch back to application code, restoring CPSR
- subs pc, lr, #0
- @ get banked registers
- @ receive mode bits from host, then run into save_banked_registers to
- get_banked_registers:
- bl receive_from_debugger
- @ save banked registers
- @ r0[4:0]: desired mode bits
- save_banked_registers:
- @ backup CPSR
- mrs r7, cpsr
- msr cpsr_c, r0
- nop
- @ keep current mode bits in r1 for later use
- and r1, r0, #MODE_MASK
- @ backup banked registers
- m_send_to_debugger r8
- m_send_to_debugger r9
- m_send_to_debugger r10
- m_send_to_debugger r11
- m_send_to_debugger r12
- m_send_to_debugger r13
- m_send_to_debugger r14
- @ if not in SYS mode (or USR, which we replaced with SYS before)
- cmp r1, #MODE_SYS
- beq no_spsr_to_save
- @ backup SPSR
- mrs r0, spsr
- m_send_to_debugger r0
- no_spsr_to_save:
- @ restore CPSR for SDS
- msr cpsr_c, r7
- nop
- @ return
- b get_command
- @ ----
- @ set banked registers
- @ receive mode bits from host, then run into save_banked_registers to
- set_banked_registers:
- bl receive_from_debugger
- @ restore banked registers
- @ r0[4:0]: desired mode bits
- restore_banked_registers:
- @ backup CPSR
- mrs r7, cpsr
- msr cpsr_c, r0
- nop
- @ keep current mode bits in r1 for later use
- and r1, r0, #MODE_MASK
- @ set banked registers
- m_receive_from_debugger r8
- m_receive_from_debugger r9
- m_receive_from_debugger r10
- m_receive_from_debugger r11
- m_receive_from_debugger r12
- m_receive_from_debugger r13
- m_receive_from_debugger r14
- @ if not in SYS mode (or USR, which we replaced with SYS before)
- cmp r1, #MODE_SYS
- beq no_spsr_to_restore
- @ set SPSR
- m_receive_from_debugger r0
- msr spsr, r0
- no_spsr_to_restore:
- @ restore CPSR for SDS
- msr cpsr_c, r7
- nop
- @ return
- b get_command
- @ ----
- read_byte:
- @ r2: address
- bl receive_from_debugger
- mov r2, r0
- @ r1: count
- bl receive_from_debugger
- mov r1, r0
- rb_loop:
- ldrb r0, [r2], #1
- @ drain write- (and fill-) buffer to work around XScale errata
- mcr p15, 0, r8, c7, c10, 4
- bl send_to_debugger
- subs r1, r1, #1
- bne rb_loop
- @ return
- b get_command
- @ ----
- read_half_word:
- @ r2: address
- bl receive_from_debugger
- mov r2, r0
- @ r1: count
- bl receive_from_debugger
- mov r1, r0
- rh_loop:
- ldrh r0, [r2], #2
- @ drain write- (and fill-) buffer to work around XScale errata
- mcr p15, 0, r8, c7, c10, 4
- bl send_to_debugger
- subs r1, r1, #1
- bne rh_loop
- @ return
- b get_command
- @ ----
- read_word:
- @ r2: address
- bl receive_from_debugger
- mov r2, r0
- @ r1: count
- bl receive_from_debugger
- mov r1, r0
- rw_loop:
- ldr r0, [r2], #4
- @ drain write- (and fill-) buffer to work around XScale errata
- mcr p15, 0, r8, c7, c10, 4
- bl send_to_debugger
- subs r1, r1, #1
- bne rw_loop
- @ return
- b get_command
- @ ----
- write_byte:
- @ r2: address
- bl receive_from_debugger
- mov r2, r0
- @ r1: count
- bl receive_from_debugger
- mov r1, r0
- wb_loop:
- bl receive_from_debugger
- strb r0, [r2], #1
- @ drain write- (and fill-) buffer to work around XScale errata
- mcr p15, 0, r8, c7, c10, 4
- subs r1, r1, #1
- bne wb_loop
- @ return
- b get_command
- @ ----
- write_half_word:
- @ r2: address
- bl receive_from_debugger
- mov r2, r0
- @ r1: count
- bl receive_from_debugger
- mov r1, r0
- wh_loop:
- bl receive_from_debugger
- strh r0, [r2], #2
- @ drain write- (and fill-) buffer to work around XScale errata
- mcr p15, 0, r8, c7, c10, 4
- subs r1, r1, #1
- bne wh_loop
- @ return
- b get_command
- @ ----
- write_word:
- @ r2: address
- bl receive_from_debugger
- mov r2, r0
- @ r1: count
- bl receive_from_debugger
- mov r1, r0
- ww_loop:
- bl receive_from_debugger
- str r0, [r2], #4
- @ drain write- (and fill-) buffer to work around XScale errata
- mcr p15, 0, r8, c7, c10, 4
- subs r1, r1, #1
- bne ww_loop
- @ return
- b get_command
- @ ----
- clear_sa:
- @ read DCSR
- mrc p14, 0, r0, c10, c0
- @ clear SA bit
- bic r0, r0, #0x20
- @ write DCSR
- mcr p14, 0, r0, c10, c0
- @ return
- b get_command
- @ ----
- clean_d_cache:
- @ r0: cache clean area
- bl receive_from_debugger
- mov r1, #1024
- clean_loop:
- mcr p15, 0, r0, c7, c2, 5
- add r0, r0, #32
- subs r1, r1, #1
- bne clean_loop
- @ return
- b get_command
- @ ----
- invalidate_d_cache:
- mcr p15, 0, r0, c7, c6, 0
- @ return
- b get_command
- @ ----
- invalidate_i_cache:
- mcr p15, 0, r0, c7, c5, 0
- @ return
- b get_command
- @ ----
- cpwait:
- m_cpwait
- @return
- b get_command
- @ ----
- .section .part2 , "ax"
- read_cp_reg:
- @ requested cp register
- bl receive_from_debugger
- adr r1, read_cp_table
- add pc, r1, r0, lsl #3
- read_cp_table:
- mrc p15, 0, r0, c0, c0, 0 @ XSCALE_MAINID
- b read_cp_reg_reply
- mrc p15, 0, r0, c0, c0, 1 @ XSCALE_CACHETYPE
- b read_cp_reg_reply
- mrc p15, 0, r0, c1, c0, 0 @ XSCALE_CTRL
- b read_cp_reg_reply
- mrc p15, 0, r0, c1, c0, 1 @ XSCALE_AUXCTRL
- b read_cp_reg_reply
- mrc p15, 0, r0, c2, c0, 0 @ XSCALE_TTB
- b read_cp_reg_reply
- mrc p15, 0, r0, c3, c0, 0 @ XSCALE_DAC
- b read_cp_reg_reply
- mrc p15, 0, r0, c5, c0, 0 @ XSCALE_FSR
- b read_cp_reg_reply
- mrc p15, 0, r0, c6, c0, 0 @ XSCALE_FAR
- b read_cp_reg_reply
- mrc p15, 0, r0, c13, c0, 0 @ XSCALE_PID
- b read_cp_reg_reply
- mrc p15, 0, r0, c15, c0, 0 @ XSCALE_CP_ACCESS
- b read_cp_reg_reply
- mrc p15, 0, r0, c14, c8, 0 @ XSCALE_IBCR0
- b read_cp_reg_reply
- mrc p15, 0, r0, c14, c9, 0 @ XSCALE_IBCR1
- b read_cp_reg_reply
- mrc p15, 0, r0, c14, c0, 0 @ XSCALE_DBR0
- b read_cp_reg_reply
- mrc p15, 0, r0, c14, c3, 0 @ XSCALE_DBR1
- b read_cp_reg_reply
- mrc p15, 0, r0, c14, c4, 0 @ XSCALE_DBCON
- b read_cp_reg_reply
- mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG
- b read_cp_reg_reply
- mrc p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0
- b read_cp_reg_reply
- mrc p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1
- b read_cp_reg_reply
- mrc p14, 0, r0, c10, c0, 0 @ XSCALE_DCSR
- b read_cp_reg_reply
- read_cp_reg_reply:
- bl send_to_debugger
- @ return
- b get_command
- @ ----
- write_cp_reg:
- @ requested cp register
- bl receive_from_debugger
- mov r1, r0
- @ value to be written
- bl receive_from_debugger
- adr r2, write_cp_table
- add pc, r2, r1, lsl #3
- write_cp_table:
- mcr p15, 0, r0, c0, c0, 0 @ XSCALE_MAINID (0x0)
- b get_command
- mcr p15, 0, r0, c0, c0, 1 @ XSCALE_CACHETYPE (0x1)
- b get_command
- mcr p15, 0, r0, c1, c0, 0 @ XSCALE_CTRL (0x2)
- b get_command
- mcr p15, 0, r0, c1, c0, 1 @ XSCALE_AUXCTRL (0x3)
- b get_command
- mcr p15, 0, r0, c2, c0, 0 @ XSCALE_TTB (0x4)
- b get_command
- mcr p15, 0, r0, c3, c0, 0 @ XSCALE_DAC (0x5)
- b get_command
- mcr p15, 0, r0, c5, c0, 0 @ XSCALE_FSR (0x6)
- b get_command
- mcr p15, 0, r0, c6, c0, 0 @ XSCALE_FAR (0x7)
- b get_command
- mcr p15, 0, r0, c13, c0, 0 @ XSCALE_PID (0x8)
- b get_command
- mcr p15, 0, r0, c15, c0, 0 @ XSCALE_CP_ACCESS (0x9)
- b get_command
- mcr p15, 0, r0, c14, c8, 0 @ XSCALE_IBCR0 (0xa)
- b get_command
- mcr p15, 0, r0, c14, c9, 0 @ XSCALE_IBCR1 (0xb)
- b get_command
- mcr p15, 0, r0, c14, c0, 0 @ XSCALE_DBR0 (0xc)
- b get_command
- mcr p15, 0, r0, c14, c3, 0 @ XSCALE_DBR1 (0xd)
- b get_command
- mcr p15, 0, r0, c14, c4, 0 @ XSCALE_DBCON (0xe)
- b get_command
- mcr p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG (0xf)
- b get_command
- mcr p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0 (0x10)
- b get_command
- mcr p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1 (0x11)
- b get_command
- mcr p14, 0, r0, c10, c0, 0 @ XSCALE_DCSR (0x12)
- b get_command
- @ ----
- read_trace_buffer:
- @ dump 256 entries from trace buffer
- mov r1, #256
- read_tb_loop:
- mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG
- bl send_to_debugger
- subs r1, r1, #1
- bne read_tb_loop
- @ dump checkpoint register 0
- mrc p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0 (0x10)
- bl send_to_debugger
- @ dump checkpoint register 1
- mrc p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1 (0x11)
- bl send_to_debugger
- @ return
- b get_command
- @ ----
- clean_trace_buffer:
- @ clean 256 entries from trace buffer
- mov r1, #256
- clean_tb_loop:
- mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG
- subs r1, r1, #1
- bne clean_tb_loop
- @ return
- b get_command
- @ ----
- @ resume program execution with trace buffer enabled
- resume_w_trace:
- @ restore CPSR (SPSR_dbg)
- bl receive_from_debugger
- msr spsr, r0
- @ restore registers (r7 - r0)
- bl receive_from_debugger @ r7
- mov r7, r0
- bl receive_from_debugger @ r6
- mov r6, r0
- bl receive_from_debugger @ r5
- mov r5, r0
- bl receive_from_debugger @ r4
- mov r4, r0
- bl receive_from_debugger @ r3
- mov r3, r0
- bl receive_from_debugger @ r2
- mov r2, r0
- bl receive_from_debugger @ r1
- mov r1, r0
- bl receive_from_debugger @ r0
- @ resume addresss
- m_receive_from_debugger lr
- mrc p14, 0, r13, c10, c0, 0 @ XSCALE_DCSR
- orr r13, r13, #1
- mcr p14, 0, r13, c10, c0, 0 @ XSCALE_DCSR
- @ branch back to application code, restoring CPSR
- subs pc, lr, #0
- undef_handler:
- swi_handler:
- prefetch_abort_handler:
- data_abort_handler:
- irq_handler:
- fiq_handler:
- 1:
- b 1b
- send_to_debugger:
- m_send_to_debugger r0
- mov pc, lr
- receive_from_debugger:
- m_receive_from_debugger r0
- mov pc, lr
|