X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=src%2Fasm.c;h=858ff9dd59477220fdc1887cc59386ed7c935ef6;hb=56a5292888e1d46fe3033cd1d5c636051692453f;hp=2736ad1f1f08a0bbb80ae586091cd91c565c17a5;hpb=20cbfff96015938809d0e3da6cd0d83b76d27f14;p=inform.git diff --git a/src/asm.c b/src/asm.c index 2736ad1..858ff9d 100644 --- a/src/asm.c +++ b/src/asm.c @@ -1,8 +1,8 @@ /* ------------------------------------------------------------------------- */ /* "asm" : The Inform assembler */ /* */ -/* Part of Inform 6.41 */ -/* copyright (c) Graham Nelson 1993 - 2022 */ +/* Part of Inform 6.42 */ +/* copyright (c) Graham Nelson 1993 - 2024 */ /* */ /* Inform is free software: you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ @@ -92,11 +92,9 @@ static char opcode_syntax_string[128]; /* Text buffer holding the correct static int routine_symbol; /* The symbol index of the routine currently being compiled */ static memory_list current_routine_name; /* The name of the routine currently - being compiled. (This may be longer - than MAX_IDENTIFIER_LENGTH, e.g. for - an "obj.prop" property routine.) */ -static int routine_locals; /* The number of local variables used by - the routine currently being compiled */ + being compiled. (This may not be a + simple symbol, e.g. for an "obj.prop" + property routine.) */ static int32 routine_start_pc; @@ -322,7 +320,7 @@ extern int is_variable_ot(int otval) extern char *variable_name(int32 i) { if (i==0) return("sp"); - if (ioperand[1]; AMO_2 = AI->operand[2]; if ((AMO_0.type == LOCALVAR_OT) && (AMO_0.value == 0)) { - // addr is on the stack + /* addr is on the stack */ assembleg_store(temp_var3, stack_pointer); assembleg_3(aload_gc, temp_var3, one_operand, AMO_1); assembleg_3(aload_gc, temp_var3, zero_operand, AMO_2); @@ -1333,7 +1340,7 @@ static void assembleg_macro(const assembly_instruction *AI) AMO_1 = AI->operand[1]; AMO_2 = AI->operand[2]; if ((AMO_0.type == LOCALVAR_OT) && (AMO_0.value == 0)) { - // addr is on the stack + /* addr is on the stack */ assembleg_store(temp_var3, stack_pointer); assembleg_3(astore_gc, temp_var3, zero_operand, AMO_1); assembleg_3(astore_gc, temp_var3, one_operand, AMO_2); @@ -1647,9 +1654,9 @@ extern void assembleg_instruction(const assembly_instruction *AI) printf("%02x ", zcode_holding_area[start_pc]); } else { - printf("%02x", zcode_holding_area[start_pc]); if (zcode_markers[start_pc]) - printf("{%02x}", zcode_markers[start_pc]); + printf("{%s}", describe_mv_short(zcode_markers[start_pc])); + printf("%02x", zcode_holding_area[start_pc]); printf(" "); } } @@ -1722,22 +1729,22 @@ extern void define_symbol_label(int symbol) labels[label].symbol = symbol; } -extern int32 assemble_routine_header(int no_locals, - int routine_asterisked, char *name, int embedded_flag, int the_symbol) +/* The local variables must already be set up; no_locals indicates + how many exist. */ +extern int32 assemble_routine_header(int routine_asterisked, char *name, + int embedded_flag, int the_symbol) { int i, rv; int stackargs = FALSE; int name_length; execution_never_reaches_here = EXECSTATE_REACHABLE; - routine_locals = no_locals; - ensure_memory_list_available(&variables_memlist, MAX_LOCAL_VARIABLES); for (i=0; i= 1 - && strcmpcis(local_variable_names[0].text, "_vararg_count")==0) { - stackargs = TRUE; + && strcmpcis(get_local_variable_name(0), "_vararg_count")==0) { + stackargs = TRUE; } if (veneer_mode) routine_starts_line = blank_brief_location; @@ -1800,7 +1807,8 @@ extern int32 assemble_routine_header(int no_locals, if ((routine_asterisked) || (define_INFIX_switch)) { char fnt[256]; assembly_operand PV, RFA, CON, STP, SLF; int ln, ln2; - + /* TODO: fnt[256] is unsafe */ + ln = next_label++; ln2 = next_label++; @@ -2044,7 +2052,7 @@ void assemble_routine_end(int embedded_flag, debug_locations locations) debug_file_printf ("%d", zmachine_pc - routine_start_pc); write_debug_locations(locations); - for (i = 1; i <= routine_locals; ++i) + for (i = 1; i <= no_locals; ++i) { debug_file_printf(""); debug_file_printf("%s", variable_name(i)); if (glulx_mode) @@ -2070,7 +2078,7 @@ void assemble_routine_end(int embedded_flag, debug_locations locations) /* Issue warnings about any local variables not used in the routine. */ - for (i=1; i<=routine_locals; i++) + for (i=1; i<=no_locals; i++) if (!(variables[i].usage)) dbnu_warning("Local variable", variable_name(i), routine_starts_line); @@ -2216,7 +2224,7 @@ static void transfer_routine_z(void) addr = labels[j].offset - offset_of_next + 2; } if (addr<-0x2000 || addr>0x1fff) - fatalerror("Branch out of range: divide the routine up?"); + error_fmt("Branch out of range: routine \"%s\" is too large", current_routine_name.data); if (addr<0) addr+=(int32) 0x10000L; addr=addr&0x3fff; @@ -2247,7 +2255,7 @@ static void transfer_routine_z(void) addr = labels[j].offset - new_pc; } if (addr<-0x8000 || addr>0x7fff) - fatalerror("Jump out of range: divide the routine up?"); + error_fmt("Jump out of range: routine \"%s\" is too large", current_routine_name.data); if (addr<0) addr += (int32) 0x10000L; zcode_holding_area[i] = addr/256; zcode_holding_area[i+1] = addr%256; @@ -2260,6 +2268,7 @@ static void transfer_routine_z(void) default: switch(zcode_markers[i] & 0x7f) { case NULL_MV: break; + case ERROR_MV: break; case VARIABLE_MV: case OBJECT_MV: case ACTION_MV: @@ -2485,6 +2494,8 @@ static void transfer_routine_g(void) switch(zcode_markers[i] & 0x7f) { case NULL_MV: break; + case ERROR_MV: + break; case ACTION_MV: case IDENT_MV: break; @@ -3061,7 +3072,9 @@ static assembly_operand parse_operand_z(void) } static void parse_assembly_z(void) -{ int n, min, max, indirect_addressed, error_flag = FALSE; +{ int n, min, max; + int indirect_addressed, jumplabel_args; + int error_flag = FALSE; opcodez O; AI.operand_count = 0; @@ -3107,8 +3120,7 @@ static void parse_assembly_z(void) if (i>0) token_text[i-1] = ':'; if (n==-1) - { ebf_error("Expected 0OP, 1OP, 2OP, VAR, EXT, VAR_LONG or EXT_LONG", - token_text); + { ebf_curtoken_error("Expected 0OP, 1OP, 2OP, VAR, EXT, VAR_LONG or EXT_LONG"); n = EXT; } custom_opcode_z.no = n; @@ -3124,10 +3136,9 @@ static void parse_assembly_z(void) case TWO: max = 32; break; } if ((custom_opcode_z.code < min) || (custom_opcode_z.code >= max)) - { char range[32]; - sprintf(range, "%d to %d", min, max-1); - error_named("For this operand type, opcode number must be in range", - range); + { + error_fmt("For this operand type, opcode number must be in range %d to %d", + min, max-1); custom_opcode_z.code = min; } } @@ -3148,9 +3159,74 @@ T (text), I (indirect addressing), F** (set this Flags 2 bit)"); } O = custom_opcode_z; } + else if ((token_type == SEP_TT) && (token_value == ARROW_SEP || token_value == DARROW_SEP)) + { + int32 start_pc = zcode_ha_size; + int bytecount = 0; + int isword = (token_value == DARROW_SEP); + while (1) { + assembly_operand AO; + /* This isn't the start of a statement, but it's safe to + release token texts anyway. */ + release_token_texts(); + get_next_token(); + if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) break; + put_token_back(); + AO = parse_expression(ARRAY_CONTEXT); + if (AO.marker == ERROR_MV) { + break; + } + if (!isword) { + if (AO.marker != 0) + error("Entries in code byte arrays must be known constants"); + if (AO.value >= 256) + warning("Entry in code byte array not in range 0 to 255"); + } + if (execution_never_reaches_here) { + continue; + } + if (bytecount == 0 && asm_trace_level > 0) { + printf("%5d +%05lx %3s %-12s", ErrorReport.line_number, + ((long int) zmachine_pc), " ", + isword?"":""); + } + if (!isword) { + byteout((AO.value & 0xFF), 0); + bytecount++; + if (asm_trace_level > 0) { + printf(" %02x", (AO.value & 0xFF)); + } + } + else { + byteout(((AO.value >> 8) & 0xFF), AO.marker); + byteout((AO.value & 0xFF), 0); + bytecount += 2; + if (asm_trace_level > 0) { + printf(" "); + print_operand(&AO, TRUE); + } + } + } + if (bytecount > 0 && asm_trace_level > 0) { + printf("\n"); + } + if (asm_trace_level>=2) + { + int j; + for (j=0;start_pc= 256) + warning("Entry in code byte array not in range 0 to 255"); + } + if (execution_never_reaches_here) { + continue; + } + if (bytecount == 0 && asm_trace_level > 0) { + printf("%5d +%05lx %3s %-12s", ErrorReport.line_number, + ((long int) zmachine_pc), " ", + isword?"":""); + } + if (!isword) { + byteout((AO.value & 0xFF), 0); + bytecount++; + if (asm_trace_level > 0) { + printf(" %02x", (AO.value & 0xFF)); + } + } + else { + byteout(((AO.value >> 24) & 0xFF), AO.marker); + byteout(((AO.value >> 16) & 0xFF), 0); + byteout(((AO.value >> 8) & 0xFF), 0); + byteout((AO.value & 0xFF), 0); + bytecount += 4; + if (asm_trace_level > 0) { + printf(" "); + print_operand(&AO, TRUE); + } + } + } + if (bytecount > 0 && asm_trace_level > 0) { + printf("\n"); + } + if (asm_trace_level>=2) + { + int j; + for (j=0;start_pc