comparison debug.c @ 2393:5f4917b9ecfa

Add debugger save command
author Michael Pavone <pavone@retrodev.com>
date Tue, 05 Dec 2023 21:29:21 -0800
parents 9f178feb3cb0
children 340299a76db7
comparison
equal deleted inserted replaced
2392:a71176b9903d 2393:5f4917b9ecfa
3000 tern_foreach(root->symbols, print_symbol, &max_len); 3000 tern_foreach(root->symbols, print_symbol, &max_len);
3001 } 3001 }
3002 return 1; 3002 return 1;
3003 } 3003 }
3004 3004
3005 static uint8_t cmd_save(debug_root *root, parsed_command *cmd)
3006 {
3007 char size = cmd->format ? cmd->format[0] : 'b';
3008 if (size != 'b' && size != 'w' && size != 'l') {
3009 fprintf(stderr, "Invalid size %s\n", cmd->format);
3010 return 1;
3011 }
3012 FILE *f = fopen(cmd->args[0].raw, "wb");
3013 if (!f) {
3014 fprintf(stderr, "Failed to open %s for writing\n", cmd->args[0].raw);
3015 return 1;
3016 }
3017 uint32_t start = 0;
3018 debug_val val;
3019 debug_array * arr = NULL;
3020 if (cmd->args[1].parsed->type == EXPR_MEM) {
3021
3022 if (!eval_expr(root, cmd->args[1].parsed->left, &val)) {
3023 fprintf(stderr, "Failed to eval start index\n");
3024 goto cleanup;
3025 }
3026 if (!debug_cast_int(val, &start)) {
3027 fprintf(stderr, "Start index must evaluate to integer\n");
3028 goto cleanup;
3029 }
3030 if (cmd->args[1].parsed->right) {
3031 if (!eval_expr(root, cmd->args[1].parsed->right, &val)) {
3032 fprintf(stderr, "Failed to eval array name in argument %s\n", cmd->args[1].raw);
3033 goto cleanup;
3034 }
3035 arr = get_array(val);
3036 if (!arr) {
3037 fprintf(stderr, "Name in argument %s did not evaluate to an array\n", cmd->args[1].raw);
3038 goto cleanup;
3039 }
3040 }
3041 } else {
3042 if (!eval_expr(root, cmd->args[1].parsed, &val)) {
3043 fprintf(stderr, "Failed to eval %s\n", cmd->args[1].raw);
3044 goto cleanup;
3045 }
3046 arr = get_array(val);
3047 if (!arr) {
3048 fprintf(stderr, "Argument %s did not evaluate to an array\n", cmd->args[1].raw);
3049 goto cleanup;
3050 }
3051 }
3052 uint32_t count = 0;
3053 if (cmd->num_args > 2) {
3054 if (!eval_expr(root, cmd->args[2].parsed, &val)) {
3055 fprintf(stderr, "Failed to eval %s\n", cmd->args[2].raw);
3056 goto cleanup;
3057 }
3058 if (!debug_cast_int(val, &count)) {
3059 fprintf(stderr, "Count must evaluate to integer\n");
3060 goto cleanup;
3061 }
3062 } else if (arr) {
3063 count = arr->size < start ? 0 : arr->size - start;
3064 } else {
3065 count = root->chunk_end(root, start) - start;
3066 if (size == 'l') {
3067 count /= 4;
3068 } else if (size == 'w') {
3069 count /= 2;
3070 }
3071 }
3072 union {
3073 uint8_t b[1024];
3074 uint16_t w[512];
3075 uint32_t l[256];
3076 } buffer;
3077 uint32_t cur = start;
3078 if (size == 'l') {
3079 while (count)
3080 {
3081 uint32_t n = count < 256 ? count : 256;
3082 count -= n;
3083 for (uint32_t i = 0; i < n ; i++)
3084 {
3085 if (arr) {
3086 val = arr->get(arr, cur++);
3087 if (!debug_cast_int(val, buffer.l + i)) {
3088 n = i;
3089 count = 0;
3090 }
3091 } else {
3092 buffer.l[i] = cur;
3093 cur += 4;
3094 if (!root->read_mem(root, buffer.l + i, 'l')) {
3095 n = i;
3096 count = 0;
3097 }
3098 }
3099 }
3100 fwrite(buffer.l, sizeof(uint32_t), n, f);
3101 }
3102 } else if (size == 'w') {
3103 while (count)
3104 {
3105 uint32_t n = count < 512 ? count : 512;
3106 count -= n;
3107 uint32_t tmp;
3108 for (uint32_t i = 0; i < n ; i++)
3109 {
3110 if (arr) {
3111 val = arr->get(arr, cur++);
3112 if (!debug_cast_int(val, &tmp)) {
3113 n = i;
3114 count = 0;
3115 }
3116 } else {
3117 tmp = cur;
3118 cur += 2;
3119 if (!root->read_mem(root, &tmp, 'w')) {
3120 n = i;
3121 count = 0;
3122 }
3123 }
3124 buffer.w[i] = tmp;
3125 }
3126 fwrite(buffer.w, sizeof(uint16_t), n, f);
3127 }
3128 } else {
3129 while (count)
3130 {
3131 uint32_t n = count < 1024 ? count : 1024;
3132 count -= n;
3133 uint32_t tmp;
3134 for (uint32_t i = 0; i < n ; i++)
3135 {
3136 if (arr) {
3137 val = arr->get(arr, cur++);
3138 if (!debug_cast_int(val, &tmp)) {
3139 n = i;
3140 count = 0;
3141 }
3142 } else {
3143 tmp = cur++;
3144 if (!root->read_mem(root, &tmp, 'b')) {
3145 n = i;
3146 count = 0;
3147 }
3148 }
3149 buffer.b[i] = tmp;
3150 }
3151 fwrite(buffer.b, sizeof(uint8_t), n, f);
3152 }
3153 }
3154 cleanup:
3155 fclose(f);
3156 return 1;
3157 }
3158
3005 static uint8_t cmd_delete_m68k(debug_root *root, parsed_command *cmd) 3159 static uint8_t cmd_delete_m68k(debug_root *root, parsed_command *cmd)
3006 { 3160 {
3007 uint32_t index; 3161 uint32_t index;
3008 if (!debug_cast_int(cmd->args[0].value, &index)) { 3162 if (!debug_cast_int(cmd->args[0].value, &index)) {
3009 fprintf(stderr, "Argument to delete must be an integer\n"); 3163 fprintf(stderr, "Argument to delete must be an integer\n");
3642 .desc = "Loads a list of symbols from the file indicated by FILENAME or lists currently loaded symbols if FILENAME is omitted", 3796 .desc = "Loads a list of symbols from the file indicated by FILENAME or lists currently loaded symbols if FILENAME is omitted",
3643 .impl = cmd_symbols, 3797 .impl = cmd_symbols,
3644 .min_args = 0, 3798 .min_args = 0,
3645 .max_args = 1, 3799 .max_args = 1,
3646 .raw_args = 1 3800 .raw_args = 1
3801 },
3802 {
3803 .names = (const char *[]){
3804 "save", NULL
3805 },
3806 .usage = "save[/SIZE] FILENAME ARRAY [COUNT]",
3807 .desc = "Saves COUNT elements of size SIZE from the array or memory region specified by ARRAY to a file",
3808 .impl = cmd_save,
3809 .min_args = 2,
3810 .max_args = 3,
3811 .skip_eval = 1
3647 } 3812 }
3648 }; 3813 };
3649 #define NUM_COMMON (sizeof(common_commands)/sizeof(*common_commands)) 3814 #define NUM_COMMON (sizeof(common_commands)/sizeof(*common_commands))
3650 3815
3651 command_def m68k_commands[] = { 3816 command_def m68k_commands[] = {
4221 { 4386 {
4222 vdp_context *vdp = var->ptr; 4387 vdp_context *vdp = var->ptr;
4223 return debug_int(vdp->frame); 4388 return debug_int(vdp->frame);
4224 } 4389 }
4225 4390
4391 static uint32_t m68k_chunk_end(debug_root *root, uint32_t start_address)
4392 {
4393 m68k_context *m68k = root->cpu_context;
4394 memmap_chunk const *chunk = find_map_chunk(start_address, &m68k->options->gen, 0, NULL);
4395 if (!chunk) {
4396 return start_address;
4397 }
4398 if (chunk->mask == m68k->options->gen.address_mask) {
4399 return chunk->end;
4400 }
4401 return (start_address & ~chunk->mask) + chunk->mask + 1;
4402 }
4403
4226 debug_root *find_m68k_root(m68k_context *context) 4404 debug_root *find_m68k_root(m68k_context *context)
4227 { 4405 {
4228 debug_root *root = find_root(context); 4406 debug_root *root = find_root(context);
4229 if (root && !root->commands) { 4407 if (root && !root->commands) {
4230 add_commands(root, common_commands, NUM_COMMON); 4408 add_commands(root, common_commands, NUM_COMMON);
4231 add_commands(root, m68k_commands, NUM_68K); 4409 add_commands(root, m68k_commands, NUM_68K);
4232 root->read_mem = read_m68k; 4410 root->read_mem = read_m68k;
4233 root->write_mem = write_m68k; 4411 root->write_mem = write_m68k;
4412 root->chunk_end = m68k_chunk_end;
4234 root->disasm = create_68000_disasm(); 4413 root->disasm = create_68000_disasm();
4235 m68k_names(root); 4414 m68k_names(root);
4236 debug_var *var; 4415 debug_var *var;
4237 switch (current_system->type) 4416 switch (current_system->type)
4238 { 4417 {
4609 var->get = z80_pc_get; 4788 var->get = z80_pc_get;
4610 root->variables = tern_insert_ptr(root->variables, "pc", var); 4789 root->variables = tern_insert_ptr(root->variables, "pc", var);
4611 root->variables = tern_insert_ptr(root->variables, "PC", var); 4790 root->variables = tern_insert_ptr(root->variables, "PC", var);
4612 } 4791 }
4613 4792
4793 static uint32_t z80_chunk_end(debug_root *root, uint32_t start_address)
4794 {
4795 z80_context *z80 = root->cpu_context;
4796 memmap_chunk const *chunk = find_map_chunk(start_address, &z80->options->gen, 0, NULL);
4797 if (!chunk) {
4798 return start_address;
4799 }
4800 if (chunk->mask == z80->options->gen.address_mask) {
4801 return chunk->end;
4802 }
4803 return (start_address & ~chunk->mask) + chunk->mask + 1;
4804 }
4805
4614 debug_root *find_z80_root(z80_context *context) 4806 debug_root *find_z80_root(z80_context *context)
4615 { 4807 {
4616 debug_root *root = find_root(context); 4808 debug_root *root = find_root(context);
4617 if (root && !root->commands) { 4809 if (root && !root->commands) {
4618 add_commands(root, common_commands, NUM_COMMON); 4810 add_commands(root, common_commands, NUM_COMMON);
4645 //root->resolve = resolve_z80; 4837 //root->resolve = resolve_z80;
4646 } 4838 }
4647 root->read_mem = read_z80; 4839 root->read_mem = read_z80;
4648 root->write_mem = write_z80; 4840 root->write_mem = write_z80;
4649 root->disasm = create_z80_disasm(); 4841 root->disasm = create_z80_disasm();
4842 root->chunk_end = z80_chunk_end;
4650 } 4843 }
4651 return root; 4844 return root;
4652 } 4845 }
4653 4846
4654 z80_context * zdebugger(z80_context * context, uint16_t address) 4847 z80_context * zdebugger(z80_context * context, uint16_t address)