Correctly comment which bit the beep program uses
[fw/altos] / lib / ccdbg-state.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 static uint8_t save_acc[] = {
22         1,      NOP,
23         0
24 };
25
26 static uint8_t save_sfr[] = {
27         2,      MOV_A_direct,   0,
28 #define SAVE_SFR_ADDR   2
29         0,
30 };
31
32 struct sfr_state {
33         uint8_t         address;
34         uint16_t        mask;
35         char            *name;
36 };
37
38 static struct sfr_state sfrs[CC_STATE_NSFR] = {
39         { SFR_DPL0,     CC_STATE_DP,    "dpl0" },
40         { SFR_DPH0,     CC_STATE_DP,    "dph0" },
41         { SFR_DPL1,     CC_STATE_DP,    "dpl1" },
42         { SFR_DPH1,     CC_STATE_DP,    "dph1" },
43         { PSW(0),       CC_STATE_PSW,   "psw"  },
44 };
45
46 uint8_t
47 ccdbg_state_save(struct ccdbg *dbg, struct ccstate *state, unsigned int mask)
48 {
49         int     i;
50
51         mask |= CC_STATE_ACC;
52         if (mask & CC_STATE_ACC)
53                 state->acc = ccdbg_execute(dbg, save_acc);
54         for (i = 0; i < CC_STATE_NSFR; i++) {
55                 if (sfrs[i].mask & mask) {
56                         save_sfr[SAVE_SFR_ADDR] = sfrs[i].address;
57                         state->sfr[i] = ccdbg_execute(dbg, save_sfr);
58                 }
59         }
60         state->mask = mask;
61         return 0;
62 }
63
64 static uint8_t restore_sfr[] = {
65         3,      MOV_direct_data,        0,      0,
66 #define RESTORE_SFR_ADDR        2
67 #define RESTORE_SFR_DATA        3
68         0
69 };
70
71 static uint8_t restore_acc[] = {
72         2,      MOV_A_data,     0,
73 #define RESTORE_ACC_DATA        2
74         0
75 };
76
77 uint8_t
78 ccdbg_state_restore(struct ccdbg *dbg, struct ccstate *state)
79 {
80         int i;
81         for (i = CC_STATE_NSFR - 1; i >= 0; i--) {
82                 if (sfrs[i].mask & state->mask) {
83                         restore_sfr[RESTORE_SFR_ADDR] = sfrs[i].address;
84                         restore_sfr[RESTORE_SFR_DATA] = state->sfr[i];
85                         ccdbg_execute(dbg, restore_sfr);
86                 }
87         }
88         if (state->mask & CC_STATE_ACC) {
89                 restore_acc[RESTORE_ACC_DATA] = state->acc;
90                 ccdbg_execute(dbg, restore_acc);
91         }
92         state->mask = 0;
93         return 0;
94 }
95
96 static void
97 ccdbg_state_replace(uint16_t sfr_addr, uint8_t sfr, char *name,
98                     uint16_t addr, uint8_t *bytes, int nbytes)
99 {
100         sfr_addr += 0xdf00;
101
102         if (addr <= sfr_addr && sfr_addr < addr + nbytes) {
103                 fprintf(stderr, "replacing %s at 0x%04x - read 0x%02x saved 0x%02x\n",
104                         name, sfr_addr, bytes[sfr_addr - addr], sfr);
105                 bytes[sfr_addr - addr] = sfr;
106         }
107 }
108
109 void
110 ccdbg_state_replace_xmem(struct ccdbg *dbg, struct ccstate *state,
111                          uint16_t addr, uint8_t *bytes, int nbytes)
112 {
113         int i;
114         if (state->mask & CC_STATE_ACC)
115                 ccdbg_state_replace(ACC(0), state->acc, "acc",
116                                     addr, bytes, nbytes);
117         for (i = 0; i < CC_STATE_NSFR; i++)
118                 if (state->mask & sfrs[i].mask)
119                         ccdbg_state_replace(sfrs[i].address, state->sfr[i],
120                                             sfrs[i].name, addr, bytes, nbytes);
121 }
122
123 void
124 ccdbg_state_replace_sfr(struct ccdbg *dbg, struct ccstate *state,
125                         uint8_t addr, uint8_t *bytes, int nbytes)
126 {
127         ccdbg_state_replace_xmem(dbg, state, (uint16_t) addr + 0xdf00, bytes, nbytes);
128 }