X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=src%2Fasm.c;h=2736ad1f1f08a0bbb80ae586091cd91c565c17a5;hb=ee3b3a0cb830792c0569230872a0af20eab8bb7b;hp=3c53096c05956f084497ed8d8d020459a1ff91eb;hpb=8e63120c630c94c598d4e2d6ba823dac59bce8fa;p=inform.git diff --git a/src/asm.c b/src/asm.c index 3c53096..2736ad1 100644 --- a/src/asm.c +++ b/src/asm.c @@ -1,7 +1,7 @@ /* ------------------------------------------------------------------------- */ /* "asm" : The Inform assembler */ /* */ -/* Part of Inform 6.40 */ +/* Part of Inform 6.41 */ /* copyright (c) Graham Nelson 1993 - 2022 */ /* */ /* Inform is free software: you can redistribute it and/or modify */ @@ -67,6 +67,8 @@ int uses_float_features; /* Makes use of Glulx floating-point (3.1.2) features? */ int uses_extundo_features; /* Makes use of Glulx extended undo (3.1.3) features? */ +int uses_double_features; /* Makes use of Glulx double-prec (3.1.3) + features? */ debug_location statement_debug_location; /* Location of current statement */ @@ -220,6 +222,8 @@ static memory_list sequence_points_memlist; The linked list must be in increasing PC order. We know this will be true because we call this as we run through the function, so zmachine_pc always increases. + + (It won't necessarily be in *label index* order, though.) */ static void set_label_offset(int label, int32 offset) { @@ -504,6 +508,7 @@ typedef struct opcodeg #define GOP_Acceleration 4 /* uses_acceleration_features */ #define GOP_Float 8 /* uses_float_features */ #define GOP_ExtUndo 16 /* uses_extundo_features */ +#define GOP_Double 32 /* uses_double_features */ /* Codes for the number of operands */ @@ -772,6 +777,8 @@ static opcodeg opcodes_table_g[] = { { (uchar *) "mfree", 0x179, 0, GOP_MemHeap, 1 }, { (uchar *) "accelfunc", 0x180, 0, GOP_Acceleration, 2 }, { (uchar *) "accelparam", 0x181, 0, GOP_Acceleration, 2 }, + { (uchar *) "hasundo", 0x128, St, GOP_ExtUndo, 1 }, + { (uchar *) "discardundo",0x129, 0, GOP_ExtUndo, 0 }, { (uchar *) "numtof", 0x190, St, GOP_Float, 2 }, { (uchar *) "ftonumz", 0x191, St, GOP_Float, 2 }, { (uchar *) "ftonumn", 0x192, St, GOP_Float, 2 }, @@ -801,15 +808,47 @@ static opcodeg opcodes_table_g[] = { { (uchar *) "jfge", 0x1C5, Br, GOP_Float, 3 }, { (uchar *) "jisnan", 0x1C8, Br, GOP_Float, 2 }, { (uchar *) "jisinf", 0x1C9, Br, GOP_Float, 2 }, - { (uchar *) "hasundo", 0x128, St, GOP_ExtUndo, 1 }, - { (uchar *) "discardundo",0x129, 0, GOP_ExtUndo, 0 }, + { (uchar *) "numtod", 0x200, St|St2, GOP_Double, 3 }, + { (uchar *) "dtonumz", 0x201, St, GOP_Double, 3 }, + { (uchar *) "dtonumn", 0x202, St, GOP_Double, 3 }, + { (uchar *) "ftod", 0x203, St|St2, GOP_Double, 3 }, + { (uchar *) "dtof", 0x204, St, GOP_Double, 3 }, + { (uchar *) "dceil", 0x208, St|St2, GOP_Double, 4 }, + { (uchar *) "dfloor", 0x209, St|St2, GOP_Double, 4 }, + { (uchar *) "dadd", 0x210, St|St2, GOP_Double, 6 }, + { (uchar *) "dsub", 0x211, St|St2, GOP_Double, 6 }, + { (uchar *) "dmul", 0x212, St|St2, GOP_Double, 6 }, + { (uchar *) "ddiv", 0x213, St|St2, GOP_Double, 6 }, + { (uchar *) "dmodr", 0x214, St|St2, GOP_Double, 6 }, + { (uchar *) "dmodq", 0x215, St|St2, GOP_Double, 6 }, + { (uchar *) "dsqrt", 0x218, St|St2, GOP_Double, 4 }, + { (uchar *) "dexp", 0x219, St|St2, GOP_Double, 4 }, + { (uchar *) "dlog", 0x21A, St|St2, GOP_Double, 4 }, + { (uchar *) "dpow", 0x21B, St|St2, GOP_Double, 6 }, + { (uchar *) "dsin", 0x220, St|St2, GOP_Double, 4 }, + { (uchar *) "dcos", 0x221, St|St2, GOP_Double, 4 }, + { (uchar *) "dtan", 0x222, St|St2, GOP_Double, 4 }, + { (uchar *) "dasin", 0x223, St|St2, GOP_Double, 4 }, + { (uchar *) "dacos", 0x224, St|St2, GOP_Double, 4 }, + { (uchar *) "datan", 0x225, St|St2, GOP_Double, 4 }, + { (uchar *) "datan2", 0x226, St|St2, GOP_Double, 6 }, + { (uchar *) "jdeq", 0x230, Br, GOP_Double, 7 }, + { (uchar *) "jdne", 0x231, Br, GOP_Double, 7 }, + { (uchar *) "jdlt", 0x232, Br, GOP_Double, 5 }, + { (uchar *) "jdle", 0x233, Br, GOP_Double, 5 }, + { (uchar *) "jdgt", 0x234, Br, GOP_Double, 5 }, + { (uchar *) "jdge", 0x235, Br, GOP_Double, 5 }, + { (uchar *) "jdisnan", 0x238, Br, GOP_Double, 3 }, + { (uchar *) "jdisinf", 0x239, Br, GOP_Double, 3 }, }; /* The opmacros table is used for fake opcodes. The opcode numbers are ignored; this table is only used for argument parsing. */ static opcodeg opmacros_table_g[] = { - { (uchar *) "pull", 0, St, 0, 1 }, - { (uchar *) "push", 0, 0, 0, 1 }, + { (uchar *) "pull", pull_gm, St, 0, 1 }, + { (uchar *) "push", push_gm, 0, 0, 1 }, + { (uchar *) "dload", dload_gm, St|St2, 0, 3 }, + { (uchar *) "dstore", dstore_gm, 0, 0, 3 }, }; static opcodeg custom_opcode_g; @@ -934,10 +973,6 @@ static void make_opcode_syntax_g(opcodeg opco) /* This is for Z-code only. */ static void write_operand(assembly_operand op) { int32 j; - if (module_switch && (op.marker != 0)) - { if ((op.marker != VARIABLE_MV) && (op.type == SHORT_CONSTANT_OT)) - op.type = LONG_CONSTANT_OT; - } j=op.value; switch(op.type) { case LONG_CONSTANT_OT: @@ -947,7 +982,7 @@ static void write_operand(assembly_operand op) byteout(j, 0); else byteout(j, 0x80 + op.marker); return; case VARIABLE_OT: - byteout(j, (module_switch)?(0x80 + op.marker):0); return; + byteout(j, 0); return; case CONSTANT_OT: case HALFCONSTANT_OT: case BYTECONSTANT_OT: @@ -1130,7 +1165,8 @@ extern void assemblez_instruction(const assembly_instruction *AI) /* Note that variable numbers 249 to 255 (i.e. globals 233 to 239) are used as scratch workspace, so need no mapping between - modules and story files: nor do local variables 0 to 15 */ + modules and story files: nor do local variables 0 to 15. + (Modules no longer exist but why drop a good comment.) */ if ((o1.value >= MAX_LOCAL_VARIABLES) && (o1.value < 249)) o1.marker = VARIABLE_MV; @@ -1220,8 +1256,6 @@ extern void assemblez_instruction(const assembly_instruction *AI) printf("\n"); } - if (module_switch) flush_link_data(); - return; OpcodeSyntaxError: @@ -1232,9 +1266,11 @@ extern void assemblez_instruction(const assembly_instruction *AI) static void assembleg_macro(const assembly_instruction *AI) { - /* validate macro syntax first */ int ix, no_operands_given; opcodeg opco; + assembly_operand AMO_0, AMO_1, AMO_2; + + /* validate macro syntax first */ opco = internal_number_to_opmacro_g(AI->internal_number); no_operands_given = AI->operand_count; @@ -1261,14 +1297,51 @@ static void assembleg_macro(const assembly_instruction *AI) } } - /* expand the macro */ - switch (AI->internal_number) { - case pull_gm: - assembleg_store(AI->operand[0], stack_pointer); + /* Expand the macro. + The assembleg_() functions overwrite AI, so we need to copy out + its operands before we call them. */ + + switch (opco.code) { + case pull_gm: /* @pull STORE */ + AMO_0 = AI->operand[0]; + assembleg_store(AMO_0, stack_pointer); break; - case push_gm: - assembleg_store(stack_pointer, AI->operand[0]); + case push_gm: /* @push LOAD */ + AMO_0 = AI->operand[0]; + assembleg_store(stack_pointer, AMO_0); + break; + + case dload_gm: /* @dload LOAD STORELO STOREHI */ + AMO_0 = AI->operand[0]; + 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 + 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); + } + else { + assembleg_3(aload_gc, AMO_0, one_operand, AMO_1); + assembleg_3(aload_gc, AMO_0, zero_operand, AMO_2); + } + break; + + case dstore_gm: /* @dload LOAD LOADHI LOADLO */ + AMO_0 = AI->operand[0]; + 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 + 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); + } + else { + assembleg_3(astore_gc, AMO_0, zero_operand, AMO_1); + assembleg_3(astore_gc, AMO_0, one_operand, AMO_2); + } break; default: @@ -1341,6 +1414,9 @@ extern void assembleg_instruction(const assembly_instruction *AI) if (opco.op_rules & GOP_ExtUndo) { uses_extundo_features = TRUE; } + if (opco.op_rules & GOP_Double) { + uses_double_features = TRUE; + } no_operands_given = AI->operand_count; @@ -1581,8 +1657,6 @@ extern void assembleg_instruction(const assembly_instruction *AI) printf("\n"); } - if (module_switch) flush_link_data(); - return; OpcodeSyntaxError: @@ -1596,12 +1670,16 @@ extern void assembleg_instruction(const assembly_instruction *AI) is assumed to be reachable. However, if STRIP_UNREACHABLE_LABELS and EXECSTATE_ENTIRE are both set, that's not true. The entire statement is being skipped, so we can safely - skip all labels within it. + skip all unused labels within it. + ("Unused" meaning there are no forward jumps to the label. We can't + do anything about *backward* jumps because we haven't seen them yet!) (If STRIP_UNREACHABLE_LABELS is not set, the ENTIRE flag is ignored.) */ extern void assemble_label_no(int n) { - if ((execution_never_reaches_here & EXECSTATE_ENTIRE) && STRIP_UNREACHABLE_LABELS) { + int inuse = (n >= 0 && n < labeluse_size && labeluse[n]); + + if ((!inuse) && (execution_never_reaches_here & EXECSTATE_ENTIRE) && STRIP_UNREACHABLE_LABELS) { /* We're not going to compile this label at all. Set a negative offset, which will trip an error if this label is jumped to. */ set_label_offset(n, -1); @@ -2128,7 +2206,10 @@ static void transfer_routine_z(void) offset_of_next = new_pc + long_form + 1; if (labels[j].offset < 0) { - error("Attempt to jump to an unreachable label"); + char *lname = "(anon)"; + if (labels[j].symbol >= 0 && labels[j].symbol < no_symbols) + lname = symbols[labels[j].symbol].name; + error_named("Attempt to jump to an unreachable label", lname); addr = 0; } else { @@ -2156,7 +2237,10 @@ static void transfer_routine_z(void) case LABEL_MV: j = 256*zcode_holding_area[i] + zcode_holding_area[i+1]; if (labels[j].offset < 0) { - error("Attempt to jump to an unreachable label"); + char *lname = "(anon)"; + if (labels[j].symbol >= 0 && labels[j].symbol < no_symbols) + lname = symbols[labels[j].symbol].name; + error_named("Attempt to jump to an unreachable label", lname); addr = 0; } else { @@ -2180,7 +2264,7 @@ static void transfer_routine_z(void) case OBJECT_MV: case ACTION_MV: case IDENT_MV: - if (!module_switch) break; + break; default: if ((zcode_markers[i] & 0x7f) > LARGEST_BPATCH_MV) { compiler_error("Illegal code backpatch value"); @@ -2356,7 +2440,10 @@ static void transfer_routine_g(void) offset_of_next = new_pc + form_len; if (labels[j].offset < 0) { - error("Attempt to jump to an unreachable label"); + char *lname = "(anon)"; + if (labels[j].symbol >= 0 && labels[j].symbol < no_symbols) + lname = symbols[labels[j].symbol].name; + error_named("Attempt to jump to an unreachable label", lname); addr = 0; } else { @@ -2400,7 +2487,7 @@ static void transfer_routine_g(void) break; case ACTION_MV: case IDENT_MV: - if (!module_switch) break; + break; case OBJECT_MV: case VARIABLE_MV: default: @@ -3431,6 +3518,7 @@ extern void init_asm_vars(void) uses_acceleration_features = FALSE; uses_float_features = FALSE; uses_extundo_features = FALSE; + uses_double_features = FALSE; labels = NULL; sequence_points = NULL;