1 %{
2 /* -*- C -*-
3 *
4 * mon_parse.y - Parser for the VICE built-in monitor.
5 *
6 * Written by
7 * Daniel Sladic <sladic@eecg.toronto.edu>
8 * Andreas Boose <viceteam@t-online.de>
9 * Thomas Giesel <skoe@directbox.com>
10 *
11 * This file is part of VICE, the Versatile Commodore Emulator.
12 * See README for copyright notice.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 * 02111-1307 USA.
28 *
29 */
30
31 #include "vice.h"
32
33 #if !defined(MACOS_COMPILE) && !(defined(__OS2__) && defined(IDE_COMPILE))
34 #ifdef __GNUC__
35 #undef alloca
36 #ifndef ANDROID_COMPILE
37 #define alloca(n) __builtin_alloca (n)
38 #endif
39 #else
40 #ifdef HAVE_ALLOCA_H
41 #include <alloca.h>
42 #else /* Not HAVE_ALLOCA_H. */
43 #if !defined(_AIX) && !defined(WINCE)
44 #ifndef _MSC_VER
45 extern char *alloca();
46 #else
47 #define alloca(n) _alloca(n)
48 #endif /* MSVC */
49 #endif /* Not AIX and not WINCE. */
50 #endif /* HAVE_ALLOCA_H. */
51 #endif /* GCC. */
52 #endif /* MACOS OS2 */
53
54 /* SunOS 4.x specific stuff */
55 #if defined(sun) || defined(__sun)
56 # if !defined(__SVR4) && !defined(__svr4__)
57 # ifdef __sparc__
58 # define YYFREE
59 # endif
60 # endif
61 #endif
62
63 #include <assert.h>
64 #include <stdio.h>
65 #include <string.h>
66 #include <stdlib.h>
67
68 #include "asm.h"
69 #include "console.h"
70 #include "lib.h"
71 #include "machine.h"
72 #include "mon_breakpoint.h"
73 #include "mon_command.h"
74 #include "mon_disassemble.h"
75 #include "mon_drive.h"
76 #include "mon_file.h"
77 #include "mon_memmap.h"
78 #include "mon_memory.h"
79 #include "mon_register.h"
80 #include "mon_util.h"
81 #include "montypes.h"
82 #include "resources.h"
83 #include "types.h"
84 #include "uimon.h"
85
86 #ifdef AMIGA_MORPHOS
87 #undef REG_PC
88 #endif
89
90 #define join_ints(x,y) (LO16_TO_HI16(x)|y)
91 #define separate_int1(x) (HI16_TO_LO16(x))
92 #define separate_int2(x) (LO16(x))
93
94 static int yyerror(char *s);
95 static int temp;
96 static int resolve_datatype(unsigned guess_type, const char *num);
97 static int resolve_range(enum t_memspace memspace, MON_ADDR range[2],
98 const char *num);
99
100 #ifdef __IBMC__
101 static void __yy_memcpy (char *to, char *from, int count);
102 #endif
103
104 /* Defined in the lexer */
105 extern int new_cmd, opt_asm;
106 extern void free_buffer(void);
107 extern void make_buffer(char *str);
108 extern int yylex(void);
109 extern int cur_len, last_len;
110
111 #define ERR_ILLEGAL_INPUT 1 /* Generic error as returned by yacc. */
112 #define ERR_RANGE_BAD_START 2
113 #define ERR_RANGE_BAD_END 3
114 #define ERR_BAD_CMD 4
115 #define ERR_EXPECT_CHECKNUM 5
116 #define ERR_EXPECT_END_CMD 6
117 #define ERR_MISSING_CLOSE_PAREN 7
118 #define ERR_INCOMPLETE_COMPARE_OP 8
119 #define ERR_EXPECT_FILENAME 9
120 #define ERR_ADDR_TOO_BIG 10
121 #define ERR_IMM_TOO_BIG 11
122 #define ERR_EXPECT_STRING 12
123 #define ERR_UNDEFINED_LABEL 13
124 #define ERR_EXPECT_DEVICE_NUM 14
125 #define ERR_EXPECT_ADDRESS 15
126 #define ERR_INVALID_REGISTER 16
127
128 #define BAD_ADDR (new_addr(e_invalid_space, 0))
129 #define CHECK_ADDR(x) ((x) == addr_mask(x))
130
131 #define YYDEBUG 1
132
133 %}
134
135 %union {
136 MON_ADDR a;
137 MON_ADDR range[2];
138 int i;
139 REG_ID reg;
140 CONDITIONAL cond_op;
141 cond_node_t *cond_node;
142 RADIXTYPE rt;
143 ACTION action;
144 char *str;
145 asm_mode_addr_info_t mode;
146 }
147
148 %token<i> H_NUMBER D_NUMBER O_NUMBER B_NUMBER CONVERT_OP B_DATA
149 %token<str> H_RANGE_GUESS D_NUMBER_GUESS O_NUMBER_GUESS B_NUMBER_GUESS
150 %token<i> BAD_CMD MEM_OP IF MEM_COMP MEM_DISK8 MEM_DISK9 MEM_DISK10 MEM_DISK11 EQUALS
151 %token TRAIL CMD_SEP LABEL_ASGN_COMMENT
152 %token CMD_SIDEFX CMD_RETURN CMD_BLOCK_READ CMD_BLOCK_WRITE CMD_UP CMD_DOWN
153 %token CMD_LOAD CMD_SAVE CMD_VERIFY CMD_IGNORE CMD_HUNT CMD_FILL CMD_MOVE
154 %token CMD_GOTO CMD_REGISTERS CMD_READSPACE CMD_WRITESPACE CMD_RADIX
155 %token CMD_MEM_DISPLAY CMD_BREAK CMD_TRACE CMD_IO CMD_BRMON CMD_COMPARE
156 %token CMD_DUMP CMD_UNDUMP CMD_EXIT CMD_DELETE CMD_CONDITION CMD_COMMAND
157 %token CMD_ASSEMBLE CMD_DISASSEMBLE CMD_NEXT CMD_STEP CMD_PRINT CMD_DEVICE
158 %token CMD_HELP CMD_WATCH CMD_DISK CMD_QUIT CMD_CHDIR CMD_BANK
159 %token CMD_LOAD_LABELS CMD_SAVE_LABELS CMD_ADD_LABEL CMD_DEL_LABEL CMD_SHOW_LABELS CMD_CLEAR_LABELS
160 %token CMD_RECORD CMD_MON_STOP CMD_PLAYBACK CMD_CHAR_DISPLAY CMD_SPRITE_DISPLAY
161 %token CMD_TEXT_DISPLAY CMD_SCREENCODE_DISPLAY CMD_ENTER_DATA CMD_ENTER_BIN_DATA CMD_KEYBUF
162 %token CMD_BLOAD CMD_BSAVE CMD_SCREEN CMD_UNTIL CMD_CPU CMD_YYDEBUG
163 %token CMD_BACKTRACE CMD_SCREENSHOT CMD_PWD CMD_DIR
164 %token CMD_RESOURCE_GET CMD_RESOURCE_SET CMD_LOAD_RESOURCES CMD_SAVE_RESOURCES
165 %token CMD_ATTACH CMD_DETACH CMD_MON_RESET CMD_TAPECTRL CMD_CARTFREEZE
166 %token CMD_CPUHISTORY CMD_MEMMAPZAP CMD_MEMMAPSHOW CMD_MEMMAPSAVE
167 %token CMD_COMMENT CMD_LIST CMD_STOPWATCH RESET
168 %token CMD_EXPORT CMD_AUTOSTART CMD_AUTOLOAD CMD_MAINCPU_TRACE
169 %token<str> CMD_LABEL_ASGN
170 %token<i> L_PAREN R_PAREN ARG_IMMEDIATE REG_A REG_X REG_Y COMMA INST_SEP
171 %token<i> L_BRACKET R_BRACKET LESS_THAN REG_U REG_S REG_PC REG_PCR
172 %token<i> REG_B REG_C REG_D REG_E REG_H REG_L
173 %token<i> REG_AF REG_BC REG_DE REG_HL REG_IX REG_IY REG_SP
174 %token<i> REG_IXH REG_IXL REG_IYH REG_IYL
175 %token<i> PLUS MINUS
176 %token<str> STRING FILENAME R_O_L OPCODE LABEL BANKNAME CPUTYPE
177 %token<reg> MON_REGISTER
178 %left<cond_op> COMPARE_OP
179 %token<rt> RADIX_TYPE INPUT_SPEC
180 %token<action> CMD_CHECKPT_ON CMD_CHECKPT_OFF TOGGLE
181 %type<range> address_range address_opt_range
182 %type<a> address opt_address
183 %type<cond_node> opt_if_cond_expr cond_expr compare_operand
184 %type<i> number expression d_number guess_default device_num
185 %type<i> memspace memloc memaddr checkpt_num mem_op opt_mem_op
186 %type<i> top_level value
187 %type<i> assembly_instruction register
188 %type<str> rest_of_line opt_rest_of_line data_list data_element filename
189 %token<i> MASK
190 %type<str> hunt_list hunt_element
191 %type<mode> asm_operand_mode
192 %type<i> index_reg index_ureg
193
194 %left '+' '-'
195 %left '*' '/'
196
197 %%
198
199 top_level: command_list { $$ = 0; }
200 | assembly_instruction TRAIL { $$ = 0; }
201 | TRAIL { new_cmd = 1; asm_mode = 0; $$ = 0; }
202 ;
203
204 command_list: command
205 | command_list command
206 ;
207
208 end_cmd: CMD_SEP
209 | TRAIL
210 | error { return ERR_EXPECT_END_CMD; }
211 ;
212
213 command: machine_state_rules
214 | symbol_table_rules
215 | memory_rules
216 | asm_rules
217 | checkpoint_rules
218 | checkpoint_control_rules
219 | monitor_state_rules
220 | monitor_misc_rules
221 | disk_rules
222 | cmd_file_rules
223 | data_entry_rules
224 | monitor_debug_rules
225 | BAD_CMD { return ERR_BAD_CMD; }
226 ;
227
228 machine_state_rules: CMD_BANK end_cmd
229 { mon_bank(e_default_space, NULL); }
230 | CMD_BANK memspace end_cmd
231 { mon_bank($2, NULL); }
232 | CMD_BANK BANKNAME end_cmd
233 { mon_bank(e_default_space, $2); }
234 | CMD_BANK memspace opt_sep BANKNAME end_cmd
235 { mon_bank($2, $4); }
236 | CMD_GOTO address end_cmd
237 { mon_jump($2); }
238 | CMD_GOTO end_cmd
239 { mon_go(); }
240 | CMD_IO end_cmd
241 { mon_display_io_regs(0); }
242 | CMD_IO address end_cmd
243 { mon_display_io_regs($2); }
244 | CMD_CPU end_cmd
245 { monitor_cpu_type_set(""); }
246 | CMD_CPU CPUTYPE end_cmd
247 { monitor_cpu_type_set($2); }
248 | CMD_CPUHISTORY end_cmd
249 { mon_cpuhistory(-1); }
250 | CMD_CPUHISTORY opt_sep expression end_cmd
251 { mon_cpuhistory($3); }
252 | CMD_RETURN end_cmd
253 { mon_instruction_return(); }
254 | CMD_DUMP filename end_cmd
255 { machine_write_snapshot($2,0,0,0); /* FIXME */ }
256 | CMD_UNDUMP filename end_cmd
257 { machine_read_snapshot($2, 0); }
258 | CMD_STEP end_cmd
259 { mon_instructions_step(-1); }
260 | CMD_STEP opt_sep expression end_cmd
261 { mon_instructions_step($3); }
262 | CMD_NEXT end_cmd
263 { mon_instructions_next(-1); }
264 | CMD_NEXT opt_sep expression end_cmd
265 { mon_instructions_next($3); }
266 | CMD_UP end_cmd
267 { mon_stack_up(-1); }
268 | CMD_UP opt_sep expression end_cmd
269 { mon_stack_up($3); }
270 | CMD_DOWN end_cmd
271 { mon_stack_down(-1); }
272 | CMD_DOWN opt_sep expression end_cmd
273 { mon_stack_down($3); }
274 | CMD_SCREEN end_cmd
275 { mon_display_screen(); }
276 | register_mod
277 ;
278
279 register_mod: CMD_REGISTERS end_cmd
280 { (monitor_cpu_for_memspace[default_memspace]->mon_register_print)(default_memspace); }
281 | CMD_REGISTERS memspace end_cmd
282 { (monitor_cpu_for_memspace[$2]->mon_register_print)($2); }
283 | CMD_REGISTERS reg_list end_cmd
284 ;
285
286 symbol_table_rules: CMD_LOAD_LABELS memspace opt_sep filename end_cmd
287 {
288 /* What about the memspace? */
289 mon_playback_init($4);
290 }
291 | CMD_LOAD_LABELS filename end_cmd
292 {
293 /* What about the memspace? */
294 mon_playback_init($2);
295 }
296 | CMD_SAVE_LABELS memspace opt_sep filename end_cmd
297 { mon_save_symbols($2, $4); }
298 | CMD_SAVE_LABELS filename end_cmd
299 { mon_save_symbols(e_default_space, $2); }
300 | CMD_ADD_LABEL address opt_sep LABEL end_cmd
301 { mon_add_name_to_symbol_table($2, $4); }
302 | CMD_DEL_LABEL LABEL end_cmd
303 { mon_remove_name_from_symbol_table(e_default_space, $2); }
304 | CMD_DEL_LABEL memspace opt_sep LABEL end_cmd
305 { mon_remove_name_from_symbol_table($2, $4); }
306 | CMD_SHOW_LABELS memspace end_cmd
307 { mon_print_symbol_table($2); }
308 | CMD_SHOW_LABELS end_cmd
309 { mon_print_symbol_table(e_default_space); }
310 | CMD_CLEAR_LABELS memspace end_cmd
311 { mon_clear_symbol_table($2); }
312 | CMD_CLEAR_LABELS end_cmd
313 { mon_clear_symbol_table(e_default_space); }
314 | CMD_LABEL_ASGN EQUALS address end_cmd
315 {
316 mon_add_name_to_symbol_table($3, mon_prepend_dot_to_name($1));
317 }
318 | CMD_LABEL_ASGN EQUALS address LABEL_ASGN_COMMENT end_cmd
319 {
320 mon_add_name_to_symbol_table($3, mon_prepend_dot_to_name($1));
321 }
322 ;
323
324 asm_rules: CMD_ASSEMBLE address
325 { mon_start_assemble_mode($2, NULL); } post_assemble end_cmd
326 { }
327 | CMD_ASSEMBLE address end_cmd
328 { mon_start_assemble_mode($2, NULL); }
329 | CMD_DISASSEMBLE address_opt_range end_cmd
330 { mon_disassemble_lines($2[0], $2[1]); }
331 | CMD_DISASSEMBLE end_cmd
332 { mon_disassemble_lines(BAD_ADDR, BAD_ADDR); }
333 ;
334
335 memory_rules: CMD_MOVE address_range opt_sep address end_cmd
336 { mon_memory_move($2[0], $2[1], $4); }
337 | CMD_COMPARE address_range opt_sep address end_cmd
338 { mon_memory_compare($2[0], $2[1], $4); }
339 | CMD_FILL address_range opt_sep data_list end_cmd
340 { mon_memory_fill($2[0], $2[1],(unsigned char *)$4); }
341 | CMD_HUNT address_range opt_sep hunt_list end_cmd
342 { mon_memory_hunt($2[0], $2[1],(unsigned char *)$4); }
343 | CMD_MEM_DISPLAY RADIX_TYPE opt_sep address_opt_range end_cmd
344 { mon_memory_display($2, $4[0], $4[1], DF_PETSCII); }
345 | CMD_MEM_DISPLAY address_opt_range end_cmd
346 { mon_memory_display(default_radix, $2[0], $2[1], DF_PETSCII); }
347 | CMD_MEM_DISPLAY end_cmd
348 { mon_memory_display(default_radix, BAD_ADDR, BAD_ADDR, DF_PETSCII); }
349 | CMD_CHAR_DISPLAY address_opt_range end_cmd
350 { mon_memory_display_data($2[0], $2[1], 8, 8); }
351 | CMD_CHAR_DISPLAY end_cmd
352 { mon_memory_display_data(BAD_ADDR, BAD_ADDR, 8, 8); }
353 | CMD_SPRITE_DISPLAY address_opt_range end_cmd
354 { mon_memory_display_data($2[0], $2[1], 24, 21); }
355 | CMD_SPRITE_DISPLAY end_cmd
356 { mon_memory_display_data(BAD_ADDR, BAD_ADDR, 24, 21); }
357 | CMD_TEXT_DISPLAY address_opt_range end_cmd
358 { mon_memory_display(0, $2[0], $2[1], DF_PETSCII); }
359 | CMD_TEXT_DISPLAY end_cmd
360 { mon_memory_display(0, BAD_ADDR, BAD_ADDR, DF_PETSCII); }
361 | CMD_SCREENCODE_DISPLAY address_opt_range end_cmd
362 { mon_memory_display(0, $2[0], $2[1], DF_SCREEN_CODE); }
363 | CMD_SCREENCODE_DISPLAY end_cmd
364 { mon_memory_display(0, BAD_ADDR, BAD_ADDR, DF_SCREEN_CODE); }
365 | CMD_MEMMAPZAP end_cmd
366 { mon_memmap_zap(); }
367 | CMD_MEMMAPSHOW end_cmd
368 { mon_memmap_show(-1,BAD_ADDR,BAD_ADDR); }
369 | CMD_MEMMAPSHOW opt_sep expression end_cmd
370 { mon_memmap_show($3,BAD_ADDR,BAD_ADDR); }
371 | CMD_MEMMAPSHOW opt_sep expression address_opt_range end_cmd
372 { mon_memmap_show($3,$4[0],$4[1]); }
373 | CMD_MEMMAPSAVE filename opt_sep expression end_cmd
374 { mon_memmap_save($2,$4); }
375 ;
376
377 checkpoint_rules: CMD_BREAK opt_mem_op address_opt_range opt_if_cond_expr end_cmd
378 {
379 if ($2) {
380 temp = mon_breakpoint_add_checkpoint($3[0], $3[1], TRUE, $2, FALSE);
381 } else {
382 temp = mon_breakpoint_add_checkpoint($3[0], $3[1], TRUE, e_exec, FALSE);
383 }
384 mon_breakpoint_set_checkpoint_condition(temp, $4);
385 }
386 | CMD_BREAK end_cmd
387 { mon_breakpoint_print_checkpoints(); }
388
389 | CMD_UNTIL address_opt_range end_cmd
390 {
391 mon_breakpoint_add_checkpoint($2[0], $2[1], TRUE, e_exec, TRUE);
392 }
393 | CMD_UNTIL end_cmd
394 { mon_breakpoint_print_checkpoints(); }
395
396 | CMD_WATCH opt_mem_op address_opt_range opt_if_cond_expr end_cmd
397 {
398 if ($2) {
399 temp = mon_breakpoint_add_checkpoint($3[0], $3[1], TRUE, $2, FALSE);
400 } else {
401 temp = mon_breakpoint_add_checkpoint($3[0], $3[1], TRUE, e_load | e_store, FALSE);
402 }
403 mon_breakpoint_set_checkpoint_condition(temp, $4);
404 }
405 | CMD_WATCH end_cmd
406 { mon_breakpoint_print_checkpoints(); }
407
408 | CMD_TRACE opt_mem_op address_opt_range opt_if_cond_expr end_cmd
409 {
410 if ($2) {
411 temp = mon_breakpoint_add_checkpoint($3[0], $3[1], FALSE, $2, FALSE);
412 } else {
413 temp = mon_breakpoint_add_checkpoint($3[0], $3[1], FALSE, e_load | e_store, FALSE);
414 }
415 mon_breakpoint_set_checkpoint_condition(temp, $4);
416 }
417 | CMD_TRACE end_cmd
418 { mon_breakpoint_print_checkpoints(); }
419 ;
420
421
422 checkpoint_control_rules: CMD_CHECKPT_ON checkpt_num end_cmd
423 { mon_breakpoint_switch_checkpoint(e_ON, $2); }
424 | CMD_CHECKPT_ON end_cmd
425 { mon_breakpoint_switch_checkpoint(e_ON, -1); }
426 | CMD_CHECKPT_OFF checkpt_num end_cmd
427 { mon_breakpoint_switch_checkpoint(e_OFF, $2); }
428 | CMD_CHECKPT_OFF end_cmd
429 { mon_breakpoint_switch_checkpoint(e_OFF, -1); }
430 | CMD_IGNORE checkpt_num end_cmd
431 { mon_breakpoint_set_ignore_count($2, -1); }
432 | CMD_IGNORE checkpt_num opt_sep expression end_cmd
433 { mon_breakpoint_set_ignore_count($2, $4); }
434 | CMD_DELETE checkpt_num end_cmd
435 { mon_breakpoint_delete_checkpoint($2); }
436 | CMD_DELETE end_cmd
437 { mon_breakpoint_delete_checkpoint(-1); }
438 | CMD_CONDITION checkpt_num IF cond_expr end_cmd
439 { mon_breakpoint_set_checkpoint_condition($2, $4); }
440 | CMD_COMMAND checkpt_num opt_sep STRING end_cmd
441 { mon_breakpoint_set_checkpoint_command($2, $4); }
442 | CMD_COMMAND checkpt_num error end_cmd
443 { return ERR_EXPECT_STRING; }
444 ;
445
446 monitor_state_rules: CMD_SIDEFX TOGGLE end_cmd
447 { sidefx = (($2 == e_TOGGLE) ? (sidefx ^ 1) : $2); }
448 | CMD_SIDEFX end_cmd
449 {
450 mon_out("I/O side effects are %s\n",
451 sidefx ? "enabled" : "disabled");
452 }
453 | CMD_RADIX RADIX_TYPE end_cmd
454 { default_radix = $2; }
455 | CMD_RADIX end_cmd
456 {
457 const char *p;
458
459 if (default_radix == e_hexadecimal)
460 p = "Hexadecimal";
461 else if (default_radix == e_decimal)
462 p = "Decimal";
463 else if (default_radix == e_octal)
464 p = "Octal";
465 else if (default_radix == e_binary)
466 p = "Binary";
467 else
468 p = "Unknown";
469
470 mon_out("Default radix is %s\n", p);
471 }
472
473 | CMD_DEVICE memspace end_cmd
474 { monitor_change_device($2); }
475 | CMD_EXPORT end_cmd
476 { mon_export(); }
477 | CMD_QUIT end_cmd
478 { mon_quit(); YYACCEPT; }
479 | CMD_EXIT end_cmd
480 { mon_exit(); YYACCEPT; }
481 | CMD_MAINCPU_TRACE TOGGLE end_cmd
482 { mon_maincpu_toggle_trace($2); }
483 ;
484
485 monitor_misc_rules: CMD_DISK rest_of_line end_cmd
486 { mon_drive_execute_disk_cmd($2); }
487 | CMD_PRINT expression end_cmd
488 { mon_out("\t%d\n",$2); }
489 | CMD_HELP end_cmd
490 { mon_command_print_help(NULL); }
491 | CMD_HELP rest_of_line end_cmd
492 { mon_command_print_help($2); }
493 | CONVERT_OP expression end_cmd
494 { mon_print_convert($2); }
495 | CMD_CHDIR rest_of_line end_cmd
496 { mon_change_dir($2); }
497 | CMD_KEYBUF rest_of_line end_cmd /* STRING */
498 { mon_keyboard_feed($2); }
499 | CMD_BACKTRACE end_cmd
500 { mon_backtrace(); }
501 | CMD_DIR opt_rest_of_line end_cmd
502 { mon_show_dir($2); }
503 | CMD_PWD end_cmd
504 { mon_show_pwd(); }
505 | CMD_SCREENSHOT filename end_cmd
506 { mon_screenshot_save($2,-1); }
507 | CMD_SCREENSHOT filename opt_sep expression end_cmd
508 { mon_screenshot_save($2,$4); }
509 | CMD_RESOURCE_GET STRING end_cmd
510 { mon_resource_get($2); }
511 | CMD_RESOURCE_SET STRING STRING end_cmd
512 { mon_resource_set($2,$3); }
513 | CMD_LOAD_RESOURCES filename end_cmd
514 { resources_load($2); }
515 | CMD_SAVE_RESOURCES filename end_cmd
516 { resources_save($2); }
517 | CMD_MON_RESET end_cmd
518 { mon_reset_machine(-1); }
519 | CMD_MON_RESET opt_sep expression end_cmd
520 { mon_reset_machine($3); }
521 | CMD_TAPECTRL opt_sep expression end_cmd
522 { mon_tape_ctrl($3); }
523 | CMD_CARTFREEZE end_cmd
524 { mon_cart_freeze(); }
525 | CMD_COMMENT opt_rest_of_line end_cmd
526 { }
527 | CMD_STOPWATCH RESET end_cmd
528 { mon_stopwatch_reset(); }
529 | CMD_STOPWATCH end_cmd
530 { mon_stopwatch_show("Stopwatch: ", "\n"); }
531 ;
532
533 disk_rules: CMD_LOAD filename device_num opt_address end_cmd
534 { mon_file_load($2, $3, $4, FALSE); }
535 | CMD_BLOAD filename device_num opt_address end_cmd
536 { mon_file_load($2, $3, $4, TRUE); }
537 | CMD_SAVE filename device_num address_range end_cmd
538 { mon_file_save($2, $3, $4[0], $4[1], FALSE); }
539 | CMD_SAVE filename error
540 { return ERR_EXPECT_DEVICE_NUM; }
541 | CMD_SAVE filename device_num error
542 { return ERR_EXPECT_ADDRESS; }
543 | CMD_BSAVE filename device_num address_range end_cmd
544 { mon_file_save($2, $3, $4[0], $4[1], TRUE); }
545 | CMD_BSAVE filename device_num error
546 { return ERR_EXPECT_ADDRESS; }
547 | CMD_VERIFY filename device_num address end_cmd
548 { mon_file_verify($2,$3,$4); }
549 | CMD_VERIFY filename device_num error
550 { return ERR_EXPECT_ADDRESS; }
551 | CMD_BLOCK_READ expression expression opt_address end_cmd
552 { mon_drive_block_cmd(0,$2,$3,$4); }
553 | CMD_BLOCK_WRITE expression expression address end_cmd
554 { mon_drive_block_cmd(1,$2,$3,$4); }
555 | CMD_LIST end_cmd
556 { mon_drive_list(-1); }
557 | CMD_LIST device_num end_cmd
558 { mon_drive_list($2); }
559 | CMD_ATTACH filename expression end_cmd
560 { mon_attach($2,$3); }
561 | CMD_DETACH expression end_cmd
562 { mon_detach($2); }
563 | CMD_AUTOSTART filename end_cmd
564 { mon_autostart($2,0,1); }
565 | CMD_AUTOSTART filename opt_sep number end_cmd
566 { mon_autostart($2,$4,1); }
567 | CMD_AUTOLOAD filename end_cmd
568 { mon_autostart($2,0,0); }
569 | CMD_AUTOLOAD filename opt_sep number end_cmd
570 { mon_autostart($2,$4,0); }
571 ;
572
573 cmd_file_rules: CMD_RECORD filename end_cmd
574 { mon_record_commands($2); }
575 | CMD_MON_STOP end_cmd
576 { mon_end_recording(); }
577 | CMD_PLAYBACK filename end_cmd
578 { mon_playback_init($2); }
579 ;
580
581 data_entry_rules: CMD_ENTER_DATA address data_list end_cmd
582 { mon_memory_fill($2, BAD_ADDR, (unsigned char *)$3); }
583 | CMD_ENTER_BIN_DATA end_cmd
584 { printf("Not yet.\n"); }
585 ;
586
587 monitor_debug_rules: CMD_YYDEBUG end_cmd
588 { yydebug = 1; }
589 ;
590
591 rest_of_line: R_O_L { $$ = $1; }
592 ;
593
594 opt_rest_of_line: R_O_L { $$ = $1; }
595 | { $$ = NULL; }
596 ;
597
598 filename: FILENAME
599 | error { return ERR_EXPECT_FILENAME; }
600 ;
601
602 device_num: expression
603 | error { return ERR_EXPECT_DEVICE_NUM; }
604 ;
605
606 mem_op: mem_op MEM_OP { $$ = $1 | $2; }
607 | MEM_OP { $$ = $1; }
608 ;
609
610 opt_mem_op: mem_op { $$ = $1; }
611 | { $$ = 0; }
612 ;
613
614 register: MON_REGISTER {
615 if (!mon_register_valid(default_memspace, $1)) {
616 return ERR_INVALID_REGISTER;
617 }
618 $$ = new_reg(default_memspace, $1);
619 }
620 | memspace MON_REGISTER {
621 if (!mon_register_valid($1, $2)) {
622 return ERR_INVALID_REGISTER;
623 }
624 $$ = new_reg($1, $2);
625 }
626 ;
627
628 reg_list: reg_list COMMA reg_asgn
629 | reg_asgn
630 ;
631
632 reg_asgn: register EQUALS number
633 { (monitor_cpu_for_memspace[reg_memspace($1)]->mon_register_set_val)(reg_memspace($1), reg_regid($1), (uint16_t) $3); }
634 ;
635
636 checkpt_num: d_number { $$ = $1; }
637 | error { return ERR_EXPECT_CHECKNUM; }
638 ;
639
640 address_opt_range: address_range
641 | address { $$[0] = $1; $$[1] = BAD_ADDR; }
642 ;
643
644 address_range: address opt_sep address { $$[0] = $1; $$[1] = $3; }
645 | H_RANGE_GUESS
646 { if (resolve_range(e_default_space, $$, $1)) return ERR_ADDR_TOO_BIG; }
647 | memspace opt_sep H_RANGE_GUESS
648 { if (resolve_range($1, $$, $3)) return ERR_ADDR_TOO_BIG; }
649 ;
650
651 opt_address: opt_sep address { $$ = $2; }
652 | { $$ = BAD_ADDR; }
653 ;
654
655 address: memloc
656 {
657 $$ = new_addr(e_default_space,$1);
658 if (opt_asm) new_cmd = asm_mode = 1;
659 }
660 | memspace opt_sep memloc
661 {
662 $$ = new_addr($1, $3);
663 if (opt_asm) new_cmd = asm_mode = 1;
664 }
665 | LABEL
666 {
667 temp = mon_symbol_table_lookup_addr(e_default_space, $1);
668 if (temp >= 0)
669 $$ = new_addr(e_default_space, temp);
670 else
671 return ERR_UNDEFINED_LABEL;
672 }
673 ;
674
675 opt_sep: COMMA
676 |
677 ;
678
679 memspace: MEM_COMP { $$ = e_comp_space; }
680 | MEM_DISK8 { $$ = e_disk8_space; }
681 | MEM_DISK9 { $$ = e_disk9_space; }
682 | MEM_DISK10 { $$ = e_disk10_space; }
683 | MEM_DISK11 { $$ = e_disk11_space; }
684 ;
685
686 memloc: memaddr { $$ = $1; if (!CHECK_ADDR($1)) return ERR_ADDR_TOO_BIG; };
687
688 memaddr: number { $$ = $1; };
689
690 expression: expression '+' expression { $$ = $1 + $3; }
691 | expression '-' expression { $$ = $1 - $3; }
692 | expression '*' expression { $$ = $1 * $3; }
693 | expression '/' expression { $$ = ($3) ? ($1 / $3) : 1; }
694 | '(' expression ')' { $$ = $2; }
695 | '(' expression error { return ERR_MISSING_CLOSE_PAREN; }
696 | value { $$ = $1; }
697 ;
698
699 opt_if_cond_expr: IF cond_expr { $$ = $2; }
700 | { $$ = 0; }
701
702 cond_expr: cond_expr COMPARE_OP cond_expr
703 {
704 $$ = new_cond; $$->is_parenthized = FALSE;
705 $$->child1 = $1; $$->child2 = $3; $$->operation = $2;
706 }
707 | cond_expr COMPARE_OP error
708 { return ERR_INCOMPLETE_COMPARE_OP; }
709 | L_PAREN cond_expr R_PAREN
710 { $$ = $2; $$->is_parenthized = TRUE; }
711 | L_PAREN cond_expr error
712 { return ERR_MISSING_CLOSE_PAREN; }
713 | compare_operand
714 { $$ = $1; }
715 ;
716
717 compare_operand: register { $$ = new_cond;
718 $$->operation = e_INV;
719 $$->is_parenthized = FALSE;
720 $$->reg_num = $1; $$->is_reg = TRUE; $$->banknum=-1;
721 $$->child1 = NULL; $$->child2 = NULL;
722 }
723 | number { $$ = new_cond;
724 $$->operation = e_INV;
725 $$->is_parenthized = FALSE;
726 $$->value = $1; $$->is_reg = FALSE; $$->banknum=-1;
727 $$->child1 = NULL; $$->child2 = NULL;
728 }
729 | '@' BANKNAME ':' address {$$=new_cond;
730 $$->operation=e_INV;
731 $$->is_parenthized = FALSE;
732 $$->banknum=mon_banknum_from_bank(e_default_space,$2); $$->value = $4; $$->is_reg = FALSE;
733 $$->child1 = NULL; $$->child2 = NULL;
734 }
735 ;
736
737 data_list: data_list opt_sep data_element
738 | data_element
739 ;
740
741 data_element: number { mon_add_number_to_buffer($1); }
742 | STRING { mon_add_string_to_buffer($1); }
743 ;
744
745 hunt_list: hunt_list hunt_element
746 | hunt_element
747 ;
748
749 hunt_element: number { mon_add_number_to_buffer($1); }
750 | MASK { mon_add_number_masked_to_buffer($1, 0x00); }
751 | STRING { mon_add_string_to_buffer($1); }
752 ;
753
754 value: number { $$ = $1; }
755 | register { $$ = (monitor_cpu_for_memspace[reg_memspace($1)]->mon_register_get_val)(reg_memspace($1), reg_regid($1)); }
756 ;
757
758 d_number: D_NUMBER { $$ = $1; }
759 | B_NUMBER_GUESS { $$ = strtol($1, NULL, 10); }
760 | O_NUMBER_GUESS { $$ = strtol($1, NULL, 10); }
761 | D_NUMBER_GUESS { $$ = strtol($1, NULL, 10); }
762 ;
763
764 guess_default: B_NUMBER_GUESS { $$ = resolve_datatype(B_NUMBER,$1); }
765 | O_NUMBER_GUESS { $$ = resolve_datatype(O_NUMBER,$1); }
766 | D_NUMBER_GUESS { $$ = resolve_datatype(D_NUMBER,$1); }
767 ;
768
769 number: H_NUMBER { $$ = $1; }
770 | D_NUMBER { $$ = $1; }
771 | O_NUMBER { $$ = $1; }
772 | B_NUMBER { $$ = $1; }
773 | guess_default { $$ = $1; }
774 ;
775
776 assembly_instr_list: assembly_instr_list INST_SEP assembly_instruction
777 | assembly_instruction INST_SEP assembly_instruction
778 | assembly_instruction INST_SEP
779 ;
780
781 assembly_instruction: OPCODE asm_operand_mode { $$ = 0;
782 if ($1) {
783 (monitor_cpu_for_memspace[default_memspace]->mon_assemble_instr)($1, $2);
784 } else {
785 new_cmd = 1;
786 asm_mode = 0;
787 }
788 opt_asm = 0;
789 };
790
791 post_assemble: assembly_instruction
792 | assembly_instr_list { asm_mode = 0; }
793 ;
794
795 asm_operand_mode: ARG_IMMEDIATE number { if ($2 > 0xff) {
796 $$.addr_mode = ASM_ADDR_MODE_IMMEDIATE_16;
797 $$.param = $2;
798 } else {
799 $$.addr_mode = ASM_ADDR_MODE_IMMEDIATE;
800 $$.param = $2;
801 } }
802 | number { if ($1 >= 0x10000) {
803 $$.addr_mode = ASM_ADDR_MODE_ABSOLUTE_LONG;
804 $$.param = $1;
805 } else if ($1 < 0x100) {
806 $$.addr_mode = ASM_ADDR_MODE_ZERO_PAGE;
807 $$.param = $1;
808 } else {
809 $$.addr_mode = ASM_ADDR_MODE_ABSOLUTE;
810 $$.param = $1;
811 }
812 }
813 | number COMMA REG_X { if ($1 >= 0x10000) {
814 $$.addr_mode = ASM_ADDR_MODE_ABSOLUTE_LONG_X;
815 $$.param = $1;
816 } else if ($1 < 0x100) {
817 $$.addr_mode = ASM_ADDR_MODE_ZERO_PAGE_X;
818 $$.param = $1;
819 } else {
820 $$.addr_mode = ASM_ADDR_MODE_ABSOLUTE_X;
821 $$.param = $1;
822 }
823 }
824 | number COMMA REG_Y { if ($1 < 0x100) {
825 $$.addr_mode = ASM_ADDR_MODE_ZERO_PAGE_Y;
826 $$.param = $1;
827 } else {
828 $$.addr_mode = ASM_ADDR_MODE_ABSOLUTE_Y;
829 $$.param = $1;
830 }
831 }
832 | number COMMA REG_S { if ($1 < 0x100) {
833 $$.addr_mode = ASM_ADDR_MODE_STACK_RELATIVE;
834 $$.param = $1;
835 } else { /* 6809 */
836 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
837 if ($1 >= -16 && $1 < 16) {
838 $$.addr_submode = $3 | ($1 & 0x1F);
839 } else if ($1 >= -128 && $1 < 128) {
840 $$.addr_submode = 0x80 | $3 | ASM_ADDR_MODE_INDEXED_OFF8;
841 $$.param = $1;
842 } else if ($1 >= -32768 && $1 < 32768) {
843 $$.addr_submode = 0x80 | $3 | ASM_ADDR_MODE_INDEXED_OFF16;
844 $$.param = $1;
845 } else {
846 $$.addr_mode = ASM_ADDR_MODE_ILLEGAL;
847 mon_out("offset too large even for 16 bits (signed)\n");
848 }
849 }
850 }
851 | number COMMA number { if ($1 < 0x100) {
852 $$.addr_mode = ASM_ADDR_MODE_DOUBLE;
853 $$.param = $3;
854 $$.addr_submode = $1;
855 }
856 }
857 | L_PAREN number R_PAREN { if ($2 < 0x100) {
858 $$.addr_mode = ASM_ADDR_MODE_INDIRECT;
859 $$.param = $2;
860 } else {
861 $$.addr_mode = ASM_ADDR_MODE_ABS_INDIRECT;
862 $$.param = $2;
863 }
864 }
865 | L_PAREN number COMMA REG_X R_PAREN { if ($2 < 0x100) {
866 $$.addr_mode = ASM_ADDR_MODE_INDIRECT_X;
867 $$.param = $2;
868 } else {
869 $$.addr_mode = ASM_ADDR_MODE_ABS_INDIRECT_X;
870 $$.param = $2;
871 }
872 }
873 | L_PAREN number COMMA REG_S R_PAREN COMMA REG_Y
874 { $$.addr_mode = ASM_ADDR_MODE_STACK_RELATIVE_Y; $$.param = $2; }
875 | L_PAREN number R_PAREN COMMA REG_Y
876 { $$.addr_mode = ASM_ADDR_MODE_INDIRECT_Y; $$.param = $2; }
877 | L_PAREN REG_BC R_PAREN { $$.addr_mode = ASM_ADDR_MODE_REG_IND_BC; }
878 | L_PAREN REG_DE R_PAREN { $$.addr_mode = ASM_ADDR_MODE_REG_IND_DE; }
879 | L_PAREN REG_HL R_PAREN { $$.addr_mode = ASM_ADDR_MODE_REG_IND_HL; }
880 | L_PAREN REG_IX R_PAREN { $$.addr_mode = ASM_ADDR_MODE_REG_IND_IX; }
881 | L_PAREN REG_IY R_PAREN { $$.addr_mode = ASM_ADDR_MODE_REG_IND_IY; }
882 | L_PAREN REG_SP R_PAREN { $$.addr_mode = ASM_ADDR_MODE_REG_IND_SP; }
883 | L_PAREN number R_PAREN COMMA REG_A
884 { $$.addr_mode = ASM_ADDR_MODE_ABSOLUTE_A; $$.param = $2; }
885 | L_PAREN number R_PAREN COMMA REG_HL
886 { $$.addr_mode = ASM_ADDR_MODE_ABSOLUTE_HL; $$.param = $2; }
887 | L_PAREN number R_PAREN COMMA REG_IX
888 { $$.addr_mode = ASM_ADDR_MODE_ABSOLUTE_IX; $$.param = $2; }
889 | L_PAREN number R_PAREN COMMA REG_IY
890 { $$.addr_mode = ASM_ADDR_MODE_ABSOLUTE_IY; $$.param = $2; }
891 | { $$.addr_mode = ASM_ADDR_MODE_IMPLIED; }
892 | REG_A { $$.addr_mode = ASM_ADDR_MODE_ACCUMULATOR; }
893 | REG_B { $$.addr_mode = ASM_ADDR_MODE_REG_B; }
894 | REG_C { $$.addr_mode = ASM_ADDR_MODE_REG_C; }
895 | REG_D { $$.addr_mode = ASM_ADDR_MODE_REG_D; }
896 | REG_E { $$.addr_mode = ASM_ADDR_MODE_REG_E; }
897 | REG_H { $$.addr_mode = ASM_ADDR_MODE_REG_H; }
898 | REG_IXH { $$.addr_mode = ASM_ADDR_MODE_REG_IXH; }
899 | REG_IYH { $$.addr_mode = ASM_ADDR_MODE_REG_IYH; }
900 | REG_L { $$.addr_mode = ASM_ADDR_MODE_REG_L; }
901 | REG_IXL { $$.addr_mode = ASM_ADDR_MODE_REG_IXL; }
902 | REG_IYL { $$.addr_mode = ASM_ADDR_MODE_REG_IYL; }
903 | REG_AF { $$.addr_mode = ASM_ADDR_MODE_REG_AF; }
904 | REG_BC { $$.addr_mode = ASM_ADDR_MODE_REG_BC; }
905 | REG_DE { $$.addr_mode = ASM_ADDR_MODE_REG_DE; }
906 | REG_HL { $$.addr_mode = ASM_ADDR_MODE_REG_HL; }
907 | REG_IX { $$.addr_mode = ASM_ADDR_MODE_REG_IX; }
908 | REG_IY { $$.addr_mode = ASM_ADDR_MODE_REG_IY; }
909 | REG_SP { $$.addr_mode = ASM_ADDR_MODE_REG_SP; }
910 /* 6809 modes */
911 | LESS_THAN number { $$.addr_mode = ASM_ADDR_MODE_DIRECT; $$.param = $2; }
912 | number COMMA index_ureg { /* Clash with addr,x addr,y addr,s modes! */
913 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
914 if ($1 >= -16 && $1 < 16) {
915 $$.addr_submode = (3 << 5) | ($1 & 0x1F);
916 } else if ($1 >= -128 && $1 < 128) {
917 $$.addr_submode = 0x80 | (3 << 5) | ASM_ADDR_MODE_INDEXED_OFF8;
918 $$.param = $1;
919 } else if ($1 >= -32768 && $1 < 32768) {
920 $$.addr_submode = 0x80 | (3 << 5) | ASM_ADDR_MODE_INDEXED_OFF16;
921 $$.param = $1;
922 } else {
923 $$.addr_mode = ASM_ADDR_MODE_ILLEGAL;
924 mon_out("offset too large even for 16 bits (signed)\n");
925 }
926 }
927 | COMMA index_reg PLUS {
928 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
929 $$.addr_submode = 0x80 | $2 | ASM_ADDR_MODE_INDEXED_INC1;
930 }
931 | COMMA index_reg PLUS PLUS {
932 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
933 $$.addr_submode = 0x80 | $2 | ASM_ADDR_MODE_INDEXED_INC2;
934 }
935 | COMMA MINUS index_reg {
936 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
937 $$.addr_submode = 0x80 | $3 | ASM_ADDR_MODE_INDEXED_DEC1;
938 }
939 | COMMA MINUS MINUS index_reg {
940 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
941 $$.addr_submode = 0x80 | $4 | ASM_ADDR_MODE_INDEXED_DEC2;
942 }
943 | COMMA index_reg {
944 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
945 $$.addr_submode = 0x80 | $2 | ASM_ADDR_MODE_INDEXED_OFF0;
946 }
947 | REG_B COMMA index_reg {
948 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
949 $$.addr_submode = 0x80 | $2 | ASM_ADDR_MODE_INDEXED_OFFB;
950 }
951 | REG_A COMMA index_reg {
952 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
953 $$.addr_submode = 0x80 | $2 | ASM_ADDR_MODE_INDEXED_OFFA;
954 }
955 | REG_D COMMA index_reg {
956 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
957 $$.addr_submode = 0x80 | $2 | ASM_ADDR_MODE_INDEXED_OFFD;
958 }
959 | number COMMA REG_PC {
960 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
961 $$.param = $1;
962 if ($1 >= -128 && $1 < 128) {
963 $$.addr_submode = ASM_ADDR_MODE_INDEXED_OFFPC8;
964 } else if ($1 >= -32768 && $1 < 32768) {
965 $$.addr_submode = ASM_ADDR_MODE_INDEXED_OFFPC16;
966 } else {
967 $$.addr_mode = ASM_ADDR_MODE_ILLEGAL;
968 mon_out("offset too large even for 16 bits (signed)\n");
969 }
970 }
971 | L_BRACKET number COMMA index_reg R_BRACKET {
972 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
973 if ($2 >= -16 && $2 < 16) {
974 $$.addr_submode = $2 & 0x1F;
975 } else if ($1 >= -128 && $1 < 128) {
976 $$.addr_submode = ASM_ADDR_MODE_INDEXED_OFF8;
977 $$.param = $2;
978 } else if ($2 >= -32768 && $2 < 32768) {
979 $$.addr_submode = ASM_ADDR_MODE_INDEXED_OFF16;
980 $$.param = $2;
981 } else {
982 $$.addr_mode = ASM_ADDR_MODE_ILLEGAL;
983 mon_out("offset too large even for 16 bits (signed)\n");
984 }
985 }
986 | L_BRACKET COMMA index_reg PLUS R_BRACKET {
987 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
988 $$.addr_submode = 0x80 | $3 | ASM_ADDR_MODE_INDEXED_INC1;
989 }
990 | L_BRACKET COMMA index_reg PLUS PLUS R_BRACKET {
991 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
992 $$.addr_submode = 0x80 | $3 | ASM_ADDR_MODE_INDEXED_INC2;
993 }
994 | L_BRACKET COMMA MINUS index_reg R_BRACKET {
995 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
996 $$.addr_submode = 0x80 | $4 | ASM_ADDR_MODE_INDEXED_DEC1;
997 }
998 | L_BRACKET COMMA MINUS MINUS index_reg R_BRACKET {
999 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
1000 $$.addr_submode = 0x80 | $5 | ASM_ADDR_MODE_INDEXED_DEC2;
1001 }
1002 | L_BRACKET COMMA index_reg R_BRACKET {
1003 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
1004 $$.addr_submode = 0x80 | $3 | ASM_ADDR_MODE_INDEXED_OFF0;
1005 }
1006 | L_BRACKET REG_B COMMA index_reg R_BRACKET {
1007 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
1008 $$.addr_submode = 0x80 | $3 | ASM_ADDR_MODE_INDEXED_OFFB;
1009 }
1010 | L_BRACKET REG_A COMMA index_reg R_BRACKET {
1011 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
1012 $$.addr_submode = 0x80 | $3 | ASM_ADDR_MODE_INDEXED_OFFA;
1013 }
1014 | L_BRACKET REG_D COMMA index_reg R_BRACKET {
1015 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
1016 $$.addr_submode = 0x80 | $3 | ASM_ADDR_MODE_INDEXED_OFFD;
1017 }
1018 | L_BRACKET number COMMA REG_PC R_BRACKET {
1019 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
1020 $$.param = $2;
1021 if ($2 >= -128 && $2 < 128) {
1022 $$.addr_submode = ASM_ADDR_MODE_INDEXED_OFFPC8_IND;
1023 } else if ($2 >= -32768 && $2 < 32768) {
1024 $$.addr_submode = ASM_ADDR_MODE_INDEXED_OFFPC16_IND;
1025 } else {
1026 $$.addr_mode = ASM_ADDR_MODE_ILLEGAL;
1027 mon_out("offset too large even for 16 bits (signed)\n");
1028 }
1029 }
1030 | L_BRACKET number R_BRACKET {
1031 $$.addr_mode = ASM_ADDR_MODE_INDEXED;
1032 $$.addr_submode = 0x80 | ASM_ADDR_MODE_EXTENDED_INDIRECT;
1033 $$.param = $2;
1034 }
1035 | L_BRACKET number R_BRACKET COMMA REG_Y {
1036 $$.addr_mode = ASM_ADDR_MODE_INDIRECT_LONG_Y;
1037 $$.param = $2;
1038 }
1039 /* TODO: register lists for PSHx PULx, and register pairs for TFR and EXG */
1040 ;
1041
1042 index_reg:
1043 REG_X { $$ = (0 << 5); printf("reg_x\n"); }
1044 | REG_Y { $$ = (1 << 5); printf("reg_y\n"); }
1045 | index_ureg { $$ = $1; }
1046 | REG_S { $$ = (3 << 5); printf("reg_s\n"); }
1047 ;
1048
1049 index_ureg:
1050 REG_U { $$ = (2 << 5); printf("reg_u\n"); }
1051 ;
1052
1053
1054 %%
1055
1056 void parse_and_execute_line(char *input)
1057 {
1058 char *temp_buf;
1059 int i, rc;
1060
1061 temp_buf = lib_malloc(strlen(input) + 3);
1062 strcpy(temp_buf,input);
1063 i = (int)strlen(input);
1064 temp_buf[i++] = '\n';
1065 temp_buf[i++] = '\0';
1066 temp_buf[i++] = '\0';
1067
1068 make_buffer(temp_buf);
1069 mon_clear_buffer();
1070 if ( (rc =yyparse()) != 0) {
1071 mon_out("ERROR -- ");
1072 switch(rc) {
1073 case ERR_BAD_CMD:
1074 mon_out("Bad command:\n");
1075 break;
1076 case ERR_RANGE_BAD_START:
1077 mon_out("Bad first address in range:\n");
1078 break;
1079 case ERR_RANGE_BAD_END:
1080 mon_out("Bad second address in range:\n");
1081 break;
1082 case ERR_EXPECT_CHECKNUM:
1083 mon_out("Checkpoint number expected:\n");
1084 break;
1085 case ERR_EXPECT_END_CMD:
1086 mon_out("Unexpected token:\n");
1087 break;
1088 case ERR_MISSING_CLOSE_PAREN:
1089 mon_out("')' expected:\n");
1090 break;
1091 case ERR_INCOMPLETE_COMPARE_OP:
1092 mon_out("Compare operation missing an operand:\n");
1093 break;
1094 case ERR_EXPECT_FILENAME:
1095 mon_out("Expecting a filename:\n");
1096 break;
1097 case ERR_ADDR_TOO_BIG:
1098 mon_out("Address too large:\n");
1099 break;
1100 case ERR_IMM_TOO_BIG:
1101 mon_out("Immediate argument too large:\n");
1102 break;
1103 case ERR_EXPECT_STRING:
1104 mon_out("Expecting a string.\n");
1105 break;
1106 case ERR_UNDEFINED_LABEL:
1107 mon_out("Found an undefined label.\n");
1108 break;
1109 case ERR_EXPECT_DEVICE_NUM:
1110 mon_out("Expecting a device number.\n");
1111 break;
1112 case ERR_EXPECT_ADDRESS:
1113 mon_out("Expecting an address.\n");
1114 break;
1115 case ERR_INVALID_REGISTER:
1116 mon_out("Invalid register.\n");
1117 break;
1118 case ERR_ILLEGAL_INPUT:
1119 default:
1120 mon_out("Wrong syntax:\n");
1121 }
1122 mon_out(" %s\n", input);
1123 for (i = 0; i < last_len; i++)
1124 mon_out(" ");
1125 mon_out(" ^\n");
1126 asm_mode = 0;
1127 new_cmd = 1;
1128 }
1129 lib_free(temp_buf);
1130 free_buffer();
1131 }
1132
yyerror(char * s)1133 static int yyerror(char *s)
1134 {
1135 fprintf(stderr, "ERR:%s\n", s);
1136 return 0;
1137 }
1138
resolve_datatype(unsigned guess_type,const char * num)1139 static int resolve_datatype(unsigned guess_type, const char *num)
1140 {
1141 /* FIXME: Handle cases when default type is non-numerical */
1142 if (default_radix == e_hexadecimal) {
1143 return strtol(num, NULL, 16);
1144 }
1145
1146 if ((guess_type == D_NUMBER) || (default_radix == e_decimal)) {
1147 return strtol(num, NULL, 10);
1148 }
1149
1150 if ((guess_type == O_NUMBER) || (default_radix == e_octal)) {
1151 return strtol(num, NULL, 8);
1152 }
1153
1154 return strtol(num, NULL, 2);
1155 }
1156
1157 /*
1158 * Resolve a character sequence containing 8 hex digits like "08001000".
1159 * This could be a lazy version of "0800 1000". If the default radix is not
1160 * hexadecimal, we handle it like a ordinary number, in the latter case there
1161 * is only one number in the range.
1162 */
resolve_range(enum t_memspace memspace,MON_ADDR range[2],const char * num)1163 static int resolve_range(enum t_memspace memspace, MON_ADDR range[2],
1164 const char *num)
1165 {
1166 char start[5];
1167 char end[5];
1168 long sa;
1169
1170 range[1] = BAD_ADDR;
1171
1172 switch (default_radix)
1173 {
1174 case e_hexadecimal:
1175 /* checked twice, but as the code must have exactly 8 digits: */
1176 if (strlen(num) == 8) {
1177 memcpy(start, num, 4);
1178 start[4] = '\0';
1179 memcpy(end, num + 4, 4);
1180 end[4] = '\0';
1181 sa = strtol(start, NULL, 16);
1182 range[1] = new_addr(memspace, strtol(end, NULL, 16));
1183 }
1184 else
1185 sa = strtol(num, NULL, 16);
1186 break;
1187
1188 case e_decimal:
1189 sa = strtol(num, NULL, 10);
1190 break;
1191
1192 case e_octal:
1193 sa = strtol(num, NULL, 8);
1194 break;
1195
1196 default:
1197 sa = strtol(num, NULL, 2);
1198 }
1199
1200 if (!CHECK_ADDR(sa))
1201 return ERR_ADDR_TOO_BIG;
1202
1203 range[0] = new_addr(memspace, sa);
1204 return 0;
1205 }
1206