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