Save/restore registers to host during memory operations. Cache ROM data.
[fw/altos] / lib / ccdbg-memory.c
1 /*
2  * Copyright © 2008 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include "ccdbg.h"
20
21 /*
22  * Read and write arbitrary memory through the debug port
23  */
24
25 static uint8_t  memory_init[] = {
26         3,      MOV_DPTR_data16,        0,      0,
27 #define HIGH_START      2
28 #define LOW_START       3
29         0,
30 };
31
32
33 static uint8_t write8[] = {
34         2,      MOV_A_data,     0,
35 #define DATA_BYTE       2
36         1,      MOVX_atDPTR_A,
37         1,      INC_DPTR,
38         0
39 };
40
41 static uint8_t read8[] = {
42         1,      MOVX_A_atDPTR,
43         1,      INC_DPTR,
44         0,
45 };
46
47 uint8_t
48 ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)
49 {
50         int i, nl = 0;
51         struct ccstate state;
52
53         ccdbg_state_save(dbg, &state, CC_STATE_ACC | CC_STATE_PSW | CC_STATE_DP);
54         memory_init[HIGH_START] = addr >> 8;
55         memory_init[LOW_START] = addr;
56         (void) ccdbg_execute(dbg, memory_init);
57         for (i = 0; i < nbytes; i++) {
58                 write8[DATA_BYTE] = *bytes++;
59                 ccdbg_execute(dbg, write8);
60                 if ((i & 0xf) == 0xf) {
61                         ccdbg_debug(CC_DEBUG_MEMORY, ".");
62                         ccdbg_flush(CC_DEBUG_MEMORY);
63                         nl = 1;
64                 }
65                 if ((i & 0xff) == 0xff) {
66                         ccdbg_debug(CC_DEBUG_MEMORY, "\n");
67                         nl = 0;
68                 }
69         }
70         ccdbg_state_restore(dbg, &state);
71         if (nl)
72                 ccdbg_debug(CC_DEBUG_MEMORY, "\n");
73         return 0;
74 }
75
76 uint8_t
77 ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)
78 {
79         int i, nl = 0;
80         struct ccstate state;
81
82         if (ccdbg_rom_contains(dbg, addr, nbytes)) {
83                 ccdbg_rom_replace_xmem(dbg, addr, bytes, nbytes);
84                 return 0;
85         }
86         ccdbg_state_save(dbg, &state, CC_STATE_ACC | CC_STATE_PSW | CC_STATE_DP);
87         memory_init[HIGH_START] = addr >> 8;
88         memory_init[LOW_START] = addr;
89         (void) ccdbg_execute(dbg, memory_init);
90         for (i = 0; i < nbytes; i++) {
91                 *bytes++ = ccdbg_execute(dbg, read8);
92                 if ((i & 0xf) == 0xf) {
93                         ccdbg_debug(CC_DEBUG_MEMORY, ".");
94                         ccdbg_flush(CC_DEBUG_MEMORY);
95                         nl = 1;
96                 }
97                 if ((i & 0xff) == 0xff) {
98                         ccdbg_debug(CC_DEBUG_MEMORY, "\n");
99                         nl = 0;
100                 }
101         }
102         ccdbg_state_replace_xmem(dbg, &state, addr, bytes, nbytes);
103         ccdbg_state_restore(dbg, &state);
104         if (nl)
105                 ccdbg_debug(CC_DEBUG_MEMORY, "\n");
106         return 0;
107 }
108
109 uint8_t
110 ccdbg_write_uint8(struct ccdbg *dbg, uint16_t addr, uint8_t byte)
111 {
112         return ccdbg_write_memory(dbg, addr, &byte, 1);
113 }
114
115 uint8_t
116 ccdbg_write_hex_image(struct ccdbg *dbg, struct hex_image *image, uint16_t offset)
117 {
118         ccdbg_write_memory(dbg, image->address + offset, image->data, image->length);
119         return 0;
120 }
121
122 struct hex_image *
123 ccdbg_read_hex_image(struct ccdbg *dbg, uint16_t address, uint16_t length)
124 {
125         struct hex_image *image;
126         
127         image = calloc(sizeof(struct hex_image) + length, 1);
128         image->address = address;
129         image->length = length;
130         memset(image->data, 0xff, length);
131         ccdbg_read_memory(dbg, address, image->data, length);
132         return image;
133 }
134
135 static uint8_t sfr_read[] = {
136         2,      MOV_A_direct,           0,
137 #define SFR_READ_ADDR   2
138         0,
139 };
140
141 static uint8_t sfr_write[] = {
142         3,      MOV_direct_data,        0,      0,
143 #define SFR_WRITE_ADDR  2
144 #define SFR_WRITE_DATA  3
145         0,
146 };
147
148 uint8_t
149 ccdbg_read_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes)
150 {
151         int     i;
152         struct ccstate state;
153
154         ccdbg_state_save(dbg, &state, CC_STATE_ACC);
155         for (i = 0; i < nbytes; i++) {
156                 sfr_read[SFR_READ_ADDR] = addr + i;
157                 *bytes++ = ccdbg_execute(dbg, sfr_read);
158         }
159         ccdbg_state_replace_sfr(dbg, &state, addr, bytes, nbytes);
160         ccdbg_state_restore(dbg, &state);
161         return 0;
162 }
163
164 uint8_t
165 ccdbg_write_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes)
166 {
167         int     i;
168         
169         for (i = 0; i < nbytes; i++) {
170                 sfr_write[SFR_WRITE_ADDR] = addr + i;
171                 sfr_write[SFR_WRITE_DATA] = *bytes++;
172                 ccdbg_execute(dbg, sfr_write);
173         }
174         return 0;
175 }