Blame view

debug.c 8.5 KB
1
2
3
4
5
6
7
//
// Created by imanol on 12/26/16.
//

#include <malloc.h>
#include <string.h>
#include "debug.h"
8
#include <signal.h>
9
10
uint32_t cycle_count = 0;
11
12
13
14
uint8_t breakpoint = 1;
uint16_t breakpoints[0xFF];
uint16_t nbpoints = 0;
char lastchoice = 0;
15
uint8_t terminate = 0;
Imanol-Mikel Barba Sabariego authored
16
uint8_t break_on_next = 0;
17
18
19
20
21

void to_debugger(int signal)
{
    if(signal == SIGINT)
    {
22
        fprintf(stderr,"CTRL+C hit. Falling to debugger (Press enter if in the middle of input)\n");
23
24
25
26
27
        breakpoint = 1;
        return;
    }
    core_dump();
}
28
29
void load_state(char *filename)
30
{
31
32
33
34
    FILE *state = fopen(filename,"r");
    uint16_t regsdump[NUM_REGISTERS+1];
    uint16_t memdump[MEMSIZE];
    uint16_t *stackdump;
35
36
    uint32_t stacksize;
    long stackpos;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

    fread(regsdump,sizeof(uint16_t),NUM_REGISTERS+1,state);
    fread(memdump,sizeof(uint16_t),MEMSIZE,state);
    stackpos = ftell(state);
    fseek(state,0,SEEK_END);
    stacksize = (ftell(state) - stackpos)/sizeof(uint16_t);
    stackdump = calloc(stacksize,sizeof(uint16_t));
    fseek(state,stackpos,SEEK_SET);
    fread(stackdump,sizeof(uint16_t),stacksize,state);
    fclose(state);

    load_regs(regsdump);
    load_memory(memdump);
    stack_load(stackdump,stacksize);

    free(stackdump);
53
54
}
55
void save_state(char *filename)
56
{
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
    FILE *state = fopen(filename,"w");
    uint16_t regsdump[NUM_REGISTERS+1];
    uint16_t memdump[MEMSIZE];
    uint16_t *stackdump;
    uint32_t stacksize;

    dump_regs(regsdump);
    dump_memory(memdump);
    stacksize = stack_dump(&stackdump);

    fwrite(regsdump,sizeof(uint16_t),NUM_REGISTERS+1,state);
    fwrite(memdump,sizeof(uint16_t),MEMSIZE,state);
    fwrite(stackdump,sizeof(uint16_t),stacksize,state);
    fclose(state);
    free(stackdump);
72
73
74
75
76
}

void query()
{
    uint8_t end = 0;
77
78
    uint16_t bpoint;
    uint16_t mempos;
79
80
    char input[100] = {0};
    char filename[32];
81
82
    uint8_t reg;
    uint16_t value;
83
84
85
    while(!end)
    {
        printf("\n> ");
86
87
88
        char command = 0;
        fgets(input,100,stdin);
        command = input[0];
89
        //FIXME: Input is not validated in any way. Crashes *will* occur on misuse. Have fun!
90
91
92
93
94
95
96
97
98
99
100
        if (command != '\n')
        {
            lastchoice = command;
        }
        else
        {
            command = lastchoice;
        }
        switch (command)
        {
            case 'b':
101
102
                sscanf(input,"b %hx\n",&bpoint);
                fprintf(stderr,"Set breakpoint %hu to %hx",nbpoints,bpoint);
103
                breakpoints[nbpoints] = bpoint;
104
                nbpoints = (uint16_t)(nbpoints + 1 % 0xFF);
105
106
                break;
            case 'd':
107
108
                sscanf(input,"d %hu\n",&bpoint);
                fprintf(stderr,"Deleted breakpoint %hu",bpoint);
109
                breakpoints[bpoint] = 0;
110
111
112
113
114
115
                break;
            case 'c':
                breakpoint = 0;
                end = 1;
                break;
            case 'n':
Imanol-Mikel Barba Sabariego authored
116
                break_on_next = 1;
117
118
119
120
121
122
                end = 1;
                break;
            case 'r':
                print_regs();
                break;
            case 'm':
123
                sscanf(input,"m %hX\n",&mempos);
124
                fprintf(stderr,"%02X: %02x\n",mempos,mem[mempos]);
125
                break;
Imanol-Mikel Barba Sabariego authored
126
127
            case 't':
                sscanf(input,"t %s\n",filename);
128
129
130
                save_state(filename);
                fprintf(stderr,"Saved state as %s",filename);
                break;
Imanol-Mikel Barba Sabariego authored
131
132
133
            case 's':
                end = 1;
                break;
134
135
136
137
138
139
            case 'l':
                sscanf(input,"l %s\n",filename);
                load_state(filename);
                fprintf(stderr,"Loaded state as %s",filename);
                break;
            case 'w':
140
141
                sscanf(input,"w r%hhu %hu\n",&reg,&value);
                fprintf(stderr,"Setting r%hhu = %02X",reg,value);
142
143
                regs[reg] = value;
                break;
144
145
146
147
            case 'q':
                terminate = 1;
                end = 1;
                break;
Imanol-Mikel Barba Sabariego authored
148
149
150
            case 'h':
                //print_debug_commands();
                break;
151
152
153
154
155
156
            default:
                break;
        }
    }
}
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
uint8_t in_breakpoint(uint16_t pc)
{
    uint8_t i;
    for(i = 0; i < nbpoints; i++)
    {
        if(breakpoints[i] == pc)
        {
            return 1;
        }
    }
    return 0;
}

uint16_t fetch_debug()
{
    uint16_t value = mem[pc++];
    return value;
}
176
void translate_args(uint16_t a1, uint16_t a2, uint16_t a3, char *arg1, char *arg2, char *arg3)
177
{
178
179
180
181
182
183
    if(a1 > MAX_INT)
    {
        sprintf(arg1,"r%d",a1-(MAX_INT+1));
    }
    else
    {
184
        sprintf(arg1,"%02X",a1);
185
186
187
188
189
190
191
192
    }

    if(a2 > MAX_INT)
    {
        sprintf(arg2,"r%d",a2-(MAX_INT+1));
    }
    else
    {
193
        sprintf(arg2,"%02X",a2);
194
195
196
197
198
199
200
201
    }

    if(a3 > MAX_INT)
    {
        sprintf(arg3,"r%d",a3-(MAX_INT+1));
    }
    else
    {
202
        sprintf(arg3,"%02X",a3);
203
204
205
206
207
208
209
210
211
212
    }

}

void print_instruction(uint16_t opcode, uint16_t a1, uint16_t a2, uint16_t a3)
{
    char arg1[10];
    char arg2[10];
    char arg3[10];
    translate_args(a1,a2,a3,arg1,arg2,arg3);
213
214
215
    switch(opcode)
    {
        case HALT:
216
            fprintf(stderr, "HALT\n");
217
218
            break;
        case MOV:
219
            fprintf(stderr, "MOV %s %s\n", arg1, arg2);
220
221
            break;
        case PUSH:
222
            fprintf(stderr, "PUSH %s\n", arg1);
223
224
            break;
        case POP:
225
            fprintf(stderr, "POP %s\n", arg1);
226
227
            break;
        case TEQ:
228
            fprintf(stderr, "TEQ %s %s %s\n", arg1, arg2, arg3);
229
230
            break;
        case TGT:
231
            fprintf(stderr, "TGT %s %s %s\n", arg1, arg2, arg3);
232
233
            break;
        case JMP:
234
            fprintf(stderr, "JMP %s\n", arg1);
235
236
            break;
        case JNZ:
237
            fprintf(stderr, "JNZ %s %s\n", arg1, arg2);
238
239
            break;
        case JZ:
240
            fprintf(stderr, "JZ %s %s\n", arg1, arg2);
241
242
            break;
        case ADD:
243
            fprintf(stderr, "ADD %s %s %s\n", arg1, arg2, arg3);
244
245
            break;
        case MUL:
246
            fprintf(stderr, "MUL %s %s %s\n", arg1, arg2, arg3);
247
248
            break;
        case MOD:
249
            fprintf(stderr, "MOD %s %s %s\n", arg1, arg2, arg3);
250
251
            break;
        case AND:
252
            fprintf(stderr, "AND %s %s %s\n", arg1, arg2, arg3);
253
254
            break;
        case OR:
255
            fprintf(stderr, "OR %s %s %s\n", arg1, arg2, arg3);
256
257
            break;
        case NOT:
258
            fprintf(stderr, "NOT %s %s\n", arg1, arg2);
259
260
            break;
        case LOAD:
261
            fprintf(stderr, "LOAD %s %s\n", arg1, arg2);
262
263
            break;
        case STOR:
264
            fprintf(stderr, "STOR %s %s\n", arg1, arg2);
265
266
            break;
        case CALL:
267
            fprintf(stderr, "CALL %s\n", arg1);
268
269
            break;
        case RET:
270
            fprintf(stderr, "RET\n");
271
272
            break;
        case OUT:
273
274
275
276
277
278
279
280
            if (a1 <= MAX_INT)
            {
                fprintf(stderr, "OUT '%c'\n",a1);
            }
            else
            {
                fprintf(stderr, "OUT %s\n", arg1);
            }
281
282
            break;
        case IN:
283
            fprintf(stderr,"IN %s\n",arg1);
284
285
            break;
        case NOP:
Imanol-Mikel Barba Sabariego authored
286
            fprintf(stderr,"NOP\n");
287
288
            break;
        default:
289
            fprintf(stderr,"UNK %02X\n", opcode);
290
291
292
293
294
            break;
    }
}
295
296
void debug_program()
{
297
    signal(SIGINT, to_debugger);
298
299
300
301
302
303
    memset(breakpoints,0x00,0xFF);
    uint16_t arg1;
    uint16_t arg2;
    uint16_t arg3;
    for(;;)
    {
304
        cycle_count++;
305
306
307
        if(in_breakpoint(pc))
        {
            breakpoint = 1;
308
            fprintf(stderr,"Breakpoint hit @ pc=%X\n",pc);
309
        }
310
        if(breakpoint)
311
        {
Imanol-Mikel Barba Sabariego authored
312
            break_on_next = 0;
313
            fprintf(stderr, "cycle: %d\n", cycle_count);
314
            fprintf(stderr, "%02X: ", pc);
315
            print_instruction(mem[pc], mem[pc+1], mem[pc+2], mem[pc+3]);
316
317
318
319
            if(stdin_length())
            {
                read_input();
            }
320
            query();
321
322
323
324
            if(terminate)
            {
                return;
            }
325
326
        }
        uint16_t opcode = fetch_debug();
Imanol-Mikel Barba Sabariego authored
327
328
329
330
331
332
333
334
335
336
337
338
339
        if(opcode == CALL && break_on_next != 0)
        {
            breakpoint = 0;
            break_on_next++;
        }
        else if(opcode == RET && break_on_next != 0)
        {
            if(--break_on_next == 1)
            {
                breakpoint = 1;
                break_on_next = 0;
            }
        }
340
341
        decode_instruction(opcode, &arg1, &arg2, &arg3);
        if (execute_instruction(opcode, arg1, arg2, arg3))
342
        {
343
            return;
344
345
346
        }
    }
}