X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;ds=sidebyside;f=asm.c;fp=asm.c;h=0000000000000000000000000000000000000000;hb=81ffe9a7de1db0b3a318a053b38882d1b7ab304c;hp=a5444fd589d92f71d0838a53bfb0493b17d3d66a;hpb=d1090135a32de7b38b48c55d4e21f95da4c405bc;p=inform.git diff --git a/asm.c b/asm.c deleted file mode 100644 index a5444fd..0000000 --- a/asm.c +++ /dev/null @@ -1,3188 +0,0 @@ -/* ------------------------------------------------------------------------- */ -/* "asm" : The Inform assembler */ -/* */ -/* Copyright (c) Graham Nelson 1993 - 2018 */ -/* */ -/* This file is part of Inform. */ -/* */ -/* Inform is free software: you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation, either version 3 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* Inform is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with Inform. If not, see https://gnu.org/licenses/ */ -/* */ -/* ------------------------------------------------------------------------- */ - -#include "header.h" - -uchar *zcode_holding_area; /* Area holding code yet to be transferred - to either zcode_area or temp file no 1 */ -uchar *zcode_markers; /* Bytes holding marker values for this - code */ -static int zcode_ha_size; /* Number of bytes in holding area */ - -memory_block zcode_area; /* Block to hold assembled code (if - temporary files are not being used) */ - -int32 zmachine_pc; /* PC position of assembly (byte offset - from start of Z-code area) */ - -int32 no_instructions; /* Number of instructions assembled */ -int execution_never_reaches_here, /* TRUE if the current PC value in the - code area cannot be reached: e.g. if - the previous instruction was a "quit" - opcode and no label is set to here */ - next_label, /* Used to count the labels created all - over Inform in current routine, from 0 */ - next_sequence_point; /* Likewise, for sequence points */ -int no_sequence_points; /* Kept for statistics purposes only */ - -static int label_moved_error_already_given; - /* When one label has moved, all subsequent - ones probably have too, and this flag - suppresses the runaway chain of error - messages which would otherwise result */ - -int sequence_point_follows; /* Will the next instruction assembled */ - /* be at a sequence point in the routine? */ - -int uses_unicode_features; /* Makes use of Glulx Unicode (3.0) - features? */ -int uses_memheap_features; /* Makes use of Glulx mem/heap (3.1) - features? */ -int uses_acceleration_features; /* Makes use of Glulx acceleration (3.1.1) - features? */ -int uses_float_features; /* Makes use of Glulx floating-point (3.1.2) - features? */ - -debug_location statement_debug_location; - /* Location of current statement */ - - -int32 *variable_tokens; /* The allocated size is - (MAX_LOCAL_VARIABLES + - MAX_GLOBAL_VARIABLES). The entries - MAX_LOCAL_VARIABLES and up give the - symbol table index for the names of - the global variables */ -int *variable_usage; /* TRUE if referred to, FALSE otherwise */ - -assembly_instruction AI; /* A structure used to hold the full - specification of a single Z-code - instruction: effectively this is the - input to the routine - assemble_instruction() */ - -static char opcode_syntax_string[128]; /* Text buffer holding the correct - syntax for an opcode: used to produce - helpful assembler error messages */ - -static int routine_symbol; /* The symbol index of the routine currently - being compiled */ -static char *routine_name; /* The name of the routine currently being - compiled */ -static int routine_locals; /* The number of local variables used by - the routine currently being compiled */ - -static int32 routine_start_pc; - -int32 *named_routine_symbols; - -static void transfer_routine_z(void); -static void transfer_routine_g(void); - -/* ------------------------------------------------------------------------- */ -/* Label data */ -/* ------------------------------------------------------------------------- */ - -static int first_label, last_label; -static int32 *label_offsets; /* Double-linked list of label offsets */ -static int *label_next, /* (i.e. zmachine_pc values) in PC order */ - *label_prev; -static int32 *label_symbols; /* Symbol numbers if defined in source */ - -static int *sequence_point_labels; - /* Label numbers for each */ -static debug_location *sequence_point_locations; - /* Source code references for each */ - /* (used for making debugging file) */ - -static void set_label_offset(int label, int32 offset) -{ - if (label >= MAX_LABELS) memoryerror("MAX_LABELS", MAX_LABELS); - - label_offsets[label] = offset; - if (last_label == -1) - { label_prev[label] = -1; - first_label = label; - } - else - { label_prev[label] = last_label; - label_next[last_label] = label; - } - last_label = label; - label_next[label] = -1; - label_symbols[label] = -1; -} - -/* ------------------------------------------------------------------------- */ -/* Useful tool for building operands */ -/* ------------------------------------------------------------------------- */ - -extern void set_constant_ot(assembly_operand *AO) -{ - if (!glulx_mode) { - if (AO->value >= 0 && AO->value <= 255) - AO->type = SHORT_CONSTANT_OT; - else - AO->type = LONG_CONSTANT_OT; - } - else { - if (AO->value == 0) - AO->type = ZEROCONSTANT_OT; - else if (AO->value >= -0x80 && AO->value < 0x80) - AO->type = BYTECONSTANT_OT; - else if (AO->value >= -0x8000 && AO->value < 0x8000) - AO->type = HALFCONSTANT_OT; - else - AO->type = CONSTANT_OT; - } -} - -extern int is_constant_ot(int otval) -{ - if (!glulx_mode) { - return ((otval == LONG_CONSTANT_OT) - || (otval == SHORT_CONSTANT_OT)); - } - else { - return ((otval == CONSTANT_OT) - || (otval == HALFCONSTANT_OT) - || (otval == BYTECONSTANT_OT) - || (otval == ZEROCONSTANT_OT)); - } -} - -extern int is_variable_ot(int otval) -{ - if (!glulx_mode) { - return (otval == VARIABLE_OT); - } - else { - return ((otval == LOCALVAR_OT) - || (otval == GLOBALVAR_OT)); - } -} - -/* ------------------------------------------------------------------------- */ -/* Used in printing assembly traces */ -/* ------------------------------------------------------------------------- */ - -extern char *variable_name(int32 i) -{ - if (i==0) return("sp"); - if (i= 256 && i < 286) - { if (i - 256 < NUMBER_SYSTEM_FUNCTIONS) return system_functions.keywords[i - 256]; - return ""; - } - } - else { - switch (i - MAX_LOCAL_VARIABLES) { - case 0: return "temp_global"; - case 1: return "temp__global2"; - case 2: return "temp__global3"; - case 3: return "temp__global4"; - case 4: return "self"; - case 5: return "sender"; - case 6: return "sw__var"; - case 7: return "sys__glob0"; - case 8: return "sys__glob1"; - case 9: return "sys__glob2"; - case 10: return "sys_statusline_flag"; - } - } - - return ((char *) symbs[variable_tokens[i]]); -} - -static void print_operand_z(assembly_operand o) -{ switch(o.type) - { case EXPRESSION_OT: printf("expr_"); break; - case LONG_CONSTANT_OT: printf("long_"); break; - case SHORT_CONSTANT_OT: printf("short_"); break; - case VARIABLE_OT: - if (o.value==0) { printf("sp"); return; } - printf("%s", variable_name(o.value)); return; - case OMITTED_OT: printf(""); return; - } - printf("%d", o.value); -} - -static void print_operand_g(assembly_operand o) -{ - switch (o.type) { - case EXPRESSION_OT: printf("expr_"); break; - case CONSTANT_OT: printf("long_"); break; - case HALFCONSTANT_OT: printf("short_"); break; - case BYTECONSTANT_OT: printf("byte_"); break; - case ZEROCONSTANT_OT: printf("zero_"); return; - case DEREFERENCE_OT: printf("*"); break; - case GLOBALVAR_OT: - printf("%s (global_%d)", variable_name(o.value), o.value); - return; - case LOCALVAR_OT: - if (o.value == 0) - printf("stackptr"); - else - printf("%s (local_%d)", variable_name(o.value), o.value-1); - return; - case SYSFUN_OT: - if (o.value >= 0 && o.value < NUMBER_SYSTEM_FUNCTIONS) - printf("%s", system_functions.keywords[o.value]); - else - printf(""); - return; - case OMITTED_OT: printf(""); return; - default: printf("???_"); break; - } - printf("%d", o.value); -} - -extern void print_operand(assembly_operand o) -{ - if (!glulx_mode) - print_operand_z(o); - else - print_operand_g(o); -} - -/* ------------------------------------------------------------------------- */ -/* Writing bytes to the code area */ -/* ------------------------------------------------------------------------- */ - -static void byteout(int32 i, int mv) -{ if (zcode_ha_size >= MAX_ZCODE_SIZE) - memoryerror("MAX_ZCODE_SIZE",MAX_ZCODE_SIZE); - zcode_markers[zcode_ha_size] = (uchar) mv; - zcode_holding_area[zcode_ha_size++] = (uchar) i; - zmachine_pc++; -} - -/* ------------------------------------------------------------------------- */ -/* A database of the 115 canonical Infocom opcodes in Versions 3 to 6 */ -/* And of the however-many-there-are Glulx opcode */ -/* ------------------------------------------------------------------------- */ - -typedef struct opcodez -{ uchar *name; /* Lower case standard name */ - int version1; /* Valid from this version number... */ - int version2; /* ...until this one (or forever if this is 0) */ - int extension; /* In later versions, see this line in extension table: - if -1, the opcode is illegal in later versions */ - int code; /* Opcode number within its operand-number block */ - int flags; /* Flags (see below) */ - int op_rules; /* Any unusual operand rule applying (see below) */ - int flags2_set; /* If not zero, set this bit in Flags 2 in the header - of any game using the opcode */ - int no; /* Number of operands (see below) */ -} opcodez; - -typedef struct opcodeg -{ uchar *name; /* Lower case standard name */ - int32 code; /* Opcode number */ - int flags; /* Flags (see below) */ - int op_rules; /* Any unusual operand rule applying (see below) */ - int no; /* Number of operands */ -} opcodeg; - - /* Flags which can be set */ - -#define St 1 /* Store */ -#define Br 2 /* Branch */ -#define Rf 4 /* "Return flag": execution never continues after this - opcode (e.g., is a return or unconditional jump) */ -#define St2 8 /* Store2 (second-to-last operand is store (Glulx)) */ - - /* Codes for any unusual operand assembly rules */ - - /* Z-code: */ - -#define VARIAB 1 /* First operand expected to be a variable name and - assembled to a short constant: the variable number */ -#define TEXT 2 /* One text operand, to be Z-encoded into the program */ -#define LABEL 3 /* One operand, a label, given as long constant offset */ -#define CALL 4 /* First operand is name of a routine, to be assembled - as long constant (the routine's packed address): - as if the name were prefixed by #r$ */ - - /* Glulx: (bit flags for Glulx VM features) */ - -#define GOP_Unicode 1 /* uses_unicode_features */ -#define GOP_MemHeap 2 /* uses_memheap_features */ -#define GOP_Acceleration 4 /* uses_acceleration_features */ -#define GOP_Float 8 /* uses_float_features */ - - /* Codes for the number of operands */ - -#define TWO 1 /* 2 (with certain types of operand, compiled as VAR) */ -#define VAR 2 /* 0 to 4 */ -#define VAR_LONG 3 /* 0 to 8 */ -#define ONE 4 /* 1 */ -#define ZERO 5 /* 0 */ -#define EXT 6 /* Extended opcode set VAR: 0 to 4 */ -#define EXT_LONG 7 /* Extended: 0 to 8 (not used by the canonical opcodes) */ - -static opcodez opcodes_table_z[] = -{ - /* Opcodes introduced in Version 3 */ - -/* 0 */ { (uchar *) "je", 3, 0, -1, 0x01, Br, 0, 0, TWO }, -/* 1 */ { (uchar *) "jl", 3, 0, -1, 0x02, Br, 0, 0, TWO }, -/* 2 */ { (uchar *) "jg", 3, 0, -1, 0x03, Br, 0, 0, TWO }, -/* 3 */ { (uchar *) "dec_chk", 3, 0, -1, 0x04, Br, VARIAB, 0, TWO }, -/* 4 */ { (uchar *) "inc_chk", 3, 0, -1, 0x05, Br, VARIAB, 0, TWO }, -/* 5 */ { (uchar *) "jin", 3, 0, -1, 0x06, Br, 0, 0, TWO }, -/* 6 */ { (uchar *) "test", 3, 0, -1, 0x07, Br, 0, 0, TWO }, -/* 7 */ { (uchar *) "or", 3, 0, -1, 0x08, St, 0, 0, TWO }, -/* 8 */ { (uchar *) "and", 3, 0, -1, 0x09, St, 0, 0, TWO }, -/* 9 */ { (uchar *) "test_attr", 3, 0, -1, 0x0A, Br, 0, 0, TWO }, -/* 10 */ {(uchar *) "set_attr", 3, 0, -1, 0x0B, 0, 0, 0, TWO }, -/* 11 */ {(uchar *) "clear_attr", 3, 0, -1, 0x0C, 0, 0, 0, TWO }, -/* 12 */ {(uchar *) "store", 3, 0, -1, 0x0D, 0, VARIAB, 0, TWO }, -/* 13 */ {(uchar *) "insert_obj", 3, 0, -1, 0x0E, 0, 0, 0, TWO }, -/* 14 */ {(uchar *) "loadw", 3, 0, -1, 0x0F, St, 0, 0, TWO }, -/* 15 */ {(uchar *) "loadb", 3, 0, -1, 0x10, St, 0, 0, TWO }, -/* 16 */ {(uchar *) "get_prop", 3, 0, -1, 0x11, St, 0, 0, TWO }, -/* 17 */ {(uchar *) "get_prop_addr", 3, 0, -1, 0x12, St, 0, 0, TWO }, -/* 18 */ {(uchar *) "get_next_prop", 3, 0, -1, 0x13, St, 0, 0, TWO }, -/* 19 */ {(uchar *) "add", 3, 0, -1, 0x14, St, 0, 0, TWO }, -/* 20 */ {(uchar *) "sub", 3, 0, -1, 0x15, St, 0, 0, TWO }, -/* 21 */ {(uchar *) "mul", 3, 0, -1, 0x16, St, 0, 0, TWO }, -/* 22 */ {(uchar *) "div", 3, 0, -1, 0x17, St, 0, 0, TWO }, -/* 23 */ {(uchar *) "mod", 3, 0, -1, 0x18, St, 0, 0, TWO }, -/* 24 */ {(uchar *) "call", 3, 0, -1, 0x20, St, CALL, 0, VAR }, -/* 25 */ {(uchar *) "storew", 3, 0, -1, 0x21, 0, 0, 0, VAR }, -/* 26 */ {(uchar *) "storeb", 3, 0, -1, 0x22, 0, 0, 0, VAR }, -/* 27 */ {(uchar *) "put_prop", 3, 0, -1, 0x23, 0, 0, 0, VAR }, - /* This is the version of "read" called "sread" internally: */ -/* 28 */ {(uchar *) "read", 3, 0, -1, 0x24, 0, 0, 0, VAR }, -/* 29 */ {(uchar *) "print_char", 3, 0, -1, 0x25, 0, 0, 0, VAR }, -/* 30 */ {(uchar *) "print_num", 3, 0, -1, 0x26, 0, 0, 0, VAR }, -/* 31 */ {(uchar *) "random", 3, 0, -1, 0x27, St, 0, 0, VAR }, -/* 32 */ {(uchar *) "push", 3, 0, -1, 0x28, 0, 0, 0, VAR }, -/* 33 */ {(uchar *) "pull", 3, 5, 6, 0x29, 0, VARIAB, 0, VAR }, -/* 34 */ {(uchar *) "split_window", 3, 0, -1, 0x2A, 0, 0, 0, VAR }, -/* 35 */ {(uchar *) "set_window", 3, 0, -1, 0x2B, 0, 0, 0, VAR }, -/* 36 */ {(uchar *) "output_stream", 3, 0, -1, 0x33, 0, 0, 0, VAR }, -/* 37 */ {(uchar *) "input_stream", 3, 0, -1, 0x34, 0, 0, 0, VAR }, -/* 38 */ {(uchar *) "sound_effect", 3, 0, -1, 0x35, 0, 0, 7, VAR }, -/* 39 */ {(uchar *) "jz", 3, 0, -1, 0x00, Br, 0, 0, ONE }, -/* 40 */ {(uchar *) "get_sibling", 3, 0, -1, 0x01, St+Br, 0, 0, ONE }, -/* 41 */ {(uchar *) "get_child", 3, 0, -1, 0x02, St+Br, 0, 0, ONE }, -/* 42 */ {(uchar *) "get_parent", 3, 0, -1, 0x03, St, 0, 0, ONE }, -/* 43 */ {(uchar *) "get_prop_len", 3, 0, -1, 0x04, St, 0, 0, ONE }, -/* 44 */ {(uchar *) "inc", 3, 0, -1, 0x05, 0, VARIAB, 0, ONE }, -/* 45 */ {(uchar *) "dec", 3, 0, -1, 0x06, 0, VARIAB, 0, ONE }, -/* 46 */ {(uchar *) "print_addr", 3, 0, -1, 0x07, 0, 0, 0, ONE }, -/* 47 */ {(uchar *) "remove_obj", 3, 0, -1, 0x09, 0, 0, 0, ONE }, -/* 48 */ {(uchar *) "print_obj", 3, 0, -1, 0x0A, 0, 0, 0, ONE }, -/* 49 */ {(uchar *) "ret", 3, 0, -1, 0x0B, Rf, 0, 0, ONE }, -/* 50 */ {(uchar *) "jump", 3, 0, -1, 0x0C, Rf, LABEL, 0, ONE }, -/* 51 */ {(uchar *) "print_paddr", 3, 0, -1, 0x0D, 0, 0, 0, ONE }, -/* 52 */ {(uchar *) "load", 3, 0, -1, 0x0E, St, VARIAB, 0, ONE }, -/* 53 */ {(uchar *) "not", 3, 3, 0, 0x0F, St, 0, 0, ONE }, -/* 54 */ {(uchar *) "rtrue", 3, 0, -1, 0x00, Rf, 0, 0,ZERO }, -/* 55 */ {(uchar *) "rfalse", 3, 0, -1, 0x01, Rf, 0, 0,ZERO }, -/* 56 */ {(uchar *) "print", 3, 0, -1, 0x02, 0, TEXT, 0,ZERO }, -/* 57 */ {(uchar *) "print_ret", 3, 0, -1, 0x03, Rf, TEXT, 0,ZERO }, -/* 58 */ {(uchar *) "nop", 3, 0, -1, 0x04, 0, 0, 0,ZERO }, -/* 59 */ {(uchar *) "save", 3, 3, 1, 0x05, Br, 0, 0,ZERO }, -/* 60 */ {(uchar *) "restore", 3, 3, 2, 0x06, Br, 0, 0,ZERO }, -/* 61 */ {(uchar *) "restart", 3, 0, -1, 0x07, 0, 0, 0,ZERO }, -/* 62 */ {(uchar *) "ret_popped", 3, 0, -1, 0x08, Rf, 0, 0,ZERO }, -/* 63 */ {(uchar *) "pop", 3, 4, -1, 0x09, 0, 0, 0,ZERO }, -/* 64 */ {(uchar *) "quit", 3, 0, -1, 0x0A, Rf, 0, 0,ZERO }, -/* 65 */ {(uchar *) "new_line", 3, 0, -1, 0x0B, 0, 0, 0,ZERO }, -/* 66 */ {(uchar *) "show_status", 3, 3, -1, 0x0C, 0, 0, 0,ZERO }, -/* 67 */ {(uchar *) "verify", 3, 0, -1, 0x0D, Br, 0, 0,ZERO }, - - /* Opcodes introduced in Version 4 */ - -/* 68 */ {(uchar *) "call_2s", 4, 0, -1, 0x19, St, CALL, 0, TWO }, -/* 69 */ {(uchar *) "call_vs", 4, 0, -1, 0x20, St, CALL, 0, VAR }, - /* This is the version of "read" called "aread" internally: */ -/* 70 */ {(uchar *) "read", 4, 0, -1, 0x24, St, 0, 0, VAR }, -/* 71 */ {(uchar *) "call_vs2", 4, 0, -1, 0x2C, St, CALL, 0, - VAR_LONG }, -/* 72 */ {(uchar *) "erase_window", 4, 0, -1, 0x2D, 0, 0, 0, VAR }, -/* 73 */ {(uchar *) "erase_line", 4, 0, -1, 0x2E, 0, 0, 0, VAR }, -/* 74 */ {(uchar *) "set_cursor", 4, 0, -1, 0x2F, 0, 0, 0, VAR }, -/* 75 */ {(uchar *) "get_cursor", 4, 0, -1, 0x30, 0, 0, 0, VAR }, -/* 76 */ {(uchar *) "set_text_style", 4, 0, -1, 0x31, 0, 0, 0, VAR }, -/* 77 */ {(uchar *) "buffer_mode", 4, 0, -1, 0x32, 0, 0, 0, VAR }, -/* 78 */ {(uchar *) "read_char", 4, 0, -1, 0x36, St, 0, 0, VAR }, -/* 79 */ {(uchar *) "scan_table", 4, 0, -1, 0x37, St+Br, 0, 0, VAR }, -/* 80 */ {(uchar *) "call_1s", 4, 0, -1, 0x08, St, CALL, 0, ONE }, - - /* Opcodes introduced in Version 5 */ - -/* 81 */ {(uchar *) "call_2n", 5, 0, -1, 0x1a, 0, CALL, 0, TWO }, -/* 82 */ {(uchar *) "set_colour", 5, 0, -1, 0x1b, 0, 0, 6, TWO }, -/* 83 */ {(uchar *) "throw", 5, 0, -1, 0x1c, 0, 0, 0, TWO }, -/* 84 */ {(uchar *) "call_vn", 5, 0, -1, 0x39, 0, CALL, 0, VAR }, -/* 85 */ {(uchar *) "call_vn2", 5, 0, -1, 0x3a, 0, CALL, 0, - VAR_LONG }, -/* 86 */ {(uchar *) "tokenise", 5, 0, -1, 0x3b, 0, 0, 0, VAR }, -/* 87 */ {(uchar *) "encode_text", 5, 0, -1, 0x3c, 0, 0, 0, VAR }, -/* 88 */ {(uchar *) "copy_table", 5, 0, -1, 0x3d, 0, 0, 0, VAR }, -/* 89 */ {(uchar *) "print_table", 5, 0, -1, 0x3e, 0, 0, 0, VAR }, -/* 90 */ {(uchar *) "check_arg_count", 5, 0, -1, 0x3f, Br, 0, 0, VAR }, -/* 91 */ {(uchar *) "call_1n", 5, 0, -1, 0x0F, 0, CALL, 0, ONE }, -/* 92 */ {(uchar *) "catch", 5, 0, -1, 0x09, St, 0, 0, ZERO }, -/* 93 */ {(uchar *) "piracy", 5, 0, -1, 0x0F, Br, 0, 0, ZERO }, -/* 94 */ {(uchar *) "log_shift", 5, 0, -1, 0x02, St, 0, 0, EXT }, -/* 95 */ {(uchar *) "art_shift", 5, 0, -1, 0x03, St, 0, 0, EXT }, -/* 96 */ {(uchar *) "set_font", 5, 0, -1, 0x04, St, 0, 0, EXT }, -/* 97 */ {(uchar *) "save_undo", 5, 0, -1, 0x09, St, 0, 4, EXT }, -/* 98 */ {(uchar *) "restore_undo", 5, 0, -1, 0x0A, St, 0, 4, EXT }, - - /* Opcodes introduced in Version 6 */ - -/* 99 */ { (uchar *) "draw_picture", 6, 6, -1, 0x05, 0, 0, 3, EXT }, -/* 100 */ { (uchar *) "picture_data", 6, 6, -1, 0x06, Br, 0, 3, EXT }, -/* 101 */ { (uchar *) "erase_picture", 6, 6, -1, 0x07, 0, 0, 3, EXT }, -/* 102 */ { (uchar *) "set_margins", 6, 6, -1, 0x08, 0, 0, 0, EXT }, -/* 103 */ { (uchar *) "move_window", 6, 6, -1, 0x10, 0, 0, 0, EXT }, -/* 104 */ { (uchar *) "window_size", 6, 6, -1, 0x11, 0, 0, 0, EXT }, -/* 105 */ { (uchar *) "window_style", 6, 6, -1, 0x12, 0, 0, 0, EXT }, -/* 106 */ { (uchar *) "get_wind_prop", 6, 6, -1, 0x13, St, 0, 0, EXT }, -/* 107 */ { (uchar *) "scroll_window", 6, 6, -1, 0x14, 0, 0, 0, EXT }, -/* 108 */ { (uchar *) "pop_stack", 6, 6, -1, 0x15, 0, 0, 0, EXT }, -/* 109 */ { (uchar *) "read_mouse", 6, 6, -1, 0x16, 0, 0, 5, EXT }, -/* 110 */ { (uchar *) "mouse_window", 6, 6, -1, 0x17, 0, 0, 5, EXT }, -/* 111 */ { (uchar *) "push_stack", 6, 6, -1, 0x18, Br, 0, 0, EXT }, -/* 112 */ { (uchar *) "put_wind_prop", 6, 6, -1, 0x19, 0, 0, 0, EXT }, -/* 113 */ { (uchar *) "print_form", 6, 6, -1, 0x1a, 0, 0, 0, EXT }, -/* 114 */ { (uchar *) "make_menu", 6, 6, -1, 0x1b, Br, 0, 8, EXT }, -/* 115 */ { (uchar *) "picture_table", 6, 6, -1, 0x1c, 0, 0, 3, EXT }, - - /* Opcodes introduced in Z-Machine Specification Standard 1.0 */ - -/* 116 */ { (uchar *) "print_unicode", 5, 0, -1, 0x0b, 0, 0, 0, EXT }, -/* 117 */ { (uchar *) "check_unicode", 5, 0, -1, 0x0c, St, 0, 0, EXT } -}; - - /* Subsequent forms for opcodes whose meaning changes with version */ - -static opcodez extension_table_z[] = -{ -/* 0 */ { (uchar *) "not", 4, 4, 3, 0x0F, St, 0, 0, ONE }, -/* 1 */ { (uchar *) "save", 4, 4, 4, 0x05, St, 0, 0,ZERO }, -/* 2 */ { (uchar *) "restore", 4, 4, 5, 0x06, St, 0, 0,ZERO }, -/* 3 */ { (uchar *) "not", 5, 0, -1, 0x38, St, 0, 0, VAR }, -/* 4 */ { (uchar *) "save", 5, 0, -1, 0x00, St, 0, 0, EXT }, -/* 5 */ { (uchar *) "restore", 5, 0, -1, 0x01, St, 0, 0, EXT }, -/* 6 */ { (uchar *) "pull", 6, 6, -1, 0x29, St, 0, 0, VAR } -}; - -static opcodez invalid_opcode_z = - { (uchar *) "invalid", 0, 0, -1, 0xff, 0, 0, 0, ZERO}; - -static opcodez custom_opcode_z; - -/* Note that this table assumes that all opcodes have at most two - branch-label or store operands, and that if they exist, they are the - last operands. Glulx does not actually guarantee this. But it is - true for all opcodes in the current Glulx spec, so we will assume - it for now. - - Also note that Inform can only compile branches to constant offsets, - even though the Glulx machine can handle stack or memory-loaded - operands in a branch instruction. -*/ - -static opcodeg opcodes_table_g[] = { - { (uchar *) "nop", 0x00, 0, 0, 0 }, - { (uchar *) "add", 0x10, St, 0, 3 }, - { (uchar *) "sub", 0x11, St, 0, 3 }, - { (uchar *) "mul", 0x12, St, 0, 3 }, - { (uchar *) "div", 0x13, St, 0, 3 }, - { (uchar *) "mod", 0x14, St, 0, 3 }, - { (uchar *) "neg", 0x15, St, 0, 2 }, - { (uchar *) "bitand", 0x18, St, 0, 3 }, - { (uchar *) "bitor", 0x19, St, 0, 3 }, - { (uchar *) "bitxor", 0x1A, St, 0, 3 }, - { (uchar *) "bitnot", 0x1B, St, 0, 2 }, - { (uchar *) "shiftl", 0x1C, St, 0, 3 }, - { (uchar *) "sshiftr", 0x1D, St, 0, 3 }, - { (uchar *) "ushiftr", 0x1E, St, 0, 3 }, - { (uchar *) "jump", 0x20, Br|Rf, 0, 1 }, - { (uchar *) "jz", 0x22, Br, 0, 2 }, - { (uchar *) "jnz", 0x23, Br, 0, 2 }, - { (uchar *) "jeq", 0x24, Br, 0, 3 }, - { (uchar *) "jne", 0x25, Br, 0, 3 }, - { (uchar *) "jlt", 0x26, Br, 0, 3 }, - { (uchar *) "jge", 0x27, Br, 0, 3 }, - { (uchar *) "jgt", 0x28, Br, 0, 3 }, - { (uchar *) "jle", 0x29, Br, 0, 3 }, - { (uchar *) "jltu", 0x2A, Br, 0, 3 }, - { (uchar *) "jgeu", 0x2B, Br, 0, 3 }, - { (uchar *) "jgtu", 0x2C, Br, 0, 3 }, - { (uchar *) "jleu", 0x2D, Br, 0, 3 }, - { (uchar *) "call", 0x30, St, 0, 3 }, - { (uchar *) "return", 0x31, Rf, 0, 1 }, - { (uchar *) "catch", 0x32, Br|St, 0, 2 }, - { (uchar *) "throw", 0x33, Rf, 0, 2 }, - { (uchar *) "tailcall", 0x34, Rf, 0, 2 }, - { (uchar *) "copy", 0x40, St, 0, 2 }, - { (uchar *) "copys", 0x41, St, 0, 2 }, - { (uchar *) "copyb", 0x42, St, 0, 2 }, - { (uchar *) "sexs", 0x44, St, 0, 2 }, - { (uchar *) "sexb", 0x45, St, 0, 2 }, - { (uchar *) "aload", 0x48, St, 0, 3 }, - { (uchar *) "aloads", 0x49, St, 0, 3 }, - { (uchar *) "aloadb", 0x4A, St, 0, 3 }, - { (uchar *) "aloadbit", 0x4B, St, 0, 3 }, - { (uchar *) "astore", 0x4C, 0, 0, 3 }, - { (uchar *) "astores", 0x4D, 0, 0, 3 }, - { (uchar *) "astoreb", 0x4E, 0, 0, 3 }, - { (uchar *) "astorebit", 0x4F, 0, 0, 3 }, - { (uchar *) "stkcount", 0x50, St, 0, 1 }, - { (uchar *) "stkpeek", 0x51, St, 0, 2 }, - { (uchar *) "stkswap", 0x52, 0, 0, 0 }, - { (uchar *) "stkroll", 0x53, 0, 0, 2 }, - { (uchar *) "stkcopy", 0x54, 0, 0, 1 }, - { (uchar *) "streamchar", 0x70, 0, 0, 1 }, - { (uchar *) "streamnum", 0x71, 0, 0, 1 }, - { (uchar *) "streamstr", 0x72, 0, 0, 1 }, - { (uchar *) "gestalt", 0x0100, St, 0, 3 }, - { (uchar *) "debugtrap", 0x0101, 0, 0, 1 }, - { (uchar *) "getmemsize", 0x0102, St, 0, 1 }, - { (uchar *) "setmemsize", 0x0103, St, 0, 2 }, - { (uchar *) "jumpabs", 0x0104, Rf, 0, 1 }, - { (uchar *) "random", 0x0110, St, 0, 2 }, - { (uchar *) "setrandom", 0x0111, 0, 0, 1 }, - { (uchar *) "quit", 0x0120, Rf, 0, 0 }, - { (uchar *) "verify", 0x0121, St, 0, 1 }, - { (uchar *) "restart", 0x0122, 0, 0, 0 }, - { (uchar *) "save", 0x0123, St, 0, 2 }, - { (uchar *) "restore", 0x0124, St, 0, 2 }, - { (uchar *) "saveundo", 0x0125, St, 0, 1 }, - { (uchar *) "restoreundo", 0x0126, St, 0, 1 }, - { (uchar *) "protect", 0x0127, 0, 0, 2 }, - { (uchar *) "glk", 0x0130, St, 0, 3 }, - { (uchar *) "getstringtbl", 0x0140, St, 0, 1 }, - { (uchar *) "setstringtbl", 0x0141, 0, 0, 1 }, - { (uchar *) "getiosys", 0x0148, St|St2, 0, 2 }, - { (uchar *) "setiosys", 0x0149, 0, 0, 2 }, - { (uchar *) "linearsearch", 0x0150, St, 0, 8 }, - { (uchar *) "binarysearch", 0x0151, St, 0, 8 }, - { (uchar *) "linkedsearch", 0x0152, St, 0, 7 }, - { (uchar *) "callf", 0x0160, St, 0, 2 }, - { (uchar *) "callfi", 0x0161, St, 0, 3 }, - { (uchar *) "callfii", 0x0162, St, 0, 4 }, - { (uchar *) "callfiii", 0x0163, St, 0, 5 }, - { (uchar *) "streamunichar", 0x73, 0, GOP_Unicode, 1 }, - { (uchar *) "mzero", 0x170, 0, GOP_MemHeap, 2 }, - { (uchar *) "mcopy", 0x171, 0, GOP_MemHeap, 3 }, - { (uchar *) "malloc", 0x178, St, GOP_MemHeap, 2 }, - { (uchar *) "mfree", 0x179, 0, GOP_MemHeap, 1 }, - { (uchar *) "accelfunc", 0x180, 0, GOP_Acceleration, 2 }, - { (uchar *) "accelparam", 0x181, 0, GOP_Acceleration, 2 }, - { (uchar *) "numtof", 0x190, St, GOP_Float, 2 }, - { (uchar *) "ftonumz", 0x191, St, GOP_Float, 2 }, - { (uchar *) "ftonumn", 0x192, St, GOP_Float, 2 }, - { (uchar *) "ceil", 0x198, St, GOP_Float, 2 }, - { (uchar *) "floor", 0x199, St, GOP_Float, 2 }, - { (uchar *) "fadd", 0x1A0, St, GOP_Float, 3 }, - { (uchar *) "fsub", 0x1A1, St, GOP_Float, 3 }, - { (uchar *) "fmul", 0x1A2, St, GOP_Float, 3 }, - { (uchar *) "fdiv", 0x1A3, St, GOP_Float, 3 }, - { (uchar *) "fmod", 0x1A4, St|St2, GOP_Float, 4 }, - { (uchar *) "sqrt", 0x1A8, St, GOP_Float, 2 }, - { (uchar *) "exp", 0x1A9, St, GOP_Float, 2 }, - { (uchar *) "log", 0x1AA, St, GOP_Float, 2 }, - { (uchar *) "pow", 0x1AB, St, GOP_Float, 3 }, - { (uchar *) "sin", 0x1B0, St, GOP_Float, 2 }, - { (uchar *) "cos", 0x1B1, St, GOP_Float, 2 }, - { (uchar *) "tan", 0x1B2, St, GOP_Float, 2 }, - { (uchar *) "asin", 0x1B3, St, GOP_Float, 2 }, - { (uchar *) "acos", 0x1B4, St, GOP_Float, 2 }, - { (uchar *) "atan", 0x1B5, St, GOP_Float, 2 }, - { (uchar *) "atan2", 0x1B6, St, GOP_Float, 3 }, - { (uchar *) "jfeq", 0x1C0, Br, GOP_Float, 4 }, - { (uchar *) "jfne", 0x1C1, Br, GOP_Float, 4 }, - { (uchar *) "jflt", 0x1C2, Br, GOP_Float, 3 }, - { (uchar *) "jfle", 0x1C3, Br, GOP_Float, 3 }, - { (uchar *) "jfgt", 0x1C4, Br, GOP_Float, 3 }, - { (uchar *) "jfge", 0x1C5, Br, GOP_Float, 3 }, - { (uchar *) "jisnan", 0x1C8, Br, GOP_Float, 2 }, - { (uchar *) "jisinf", 0x1C9, Br, GOP_Float, 2 }, -}; - -/* 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 }, -}; - -static opcodeg custom_opcode_g; - -static opcodez internal_number_to_opcode_z(int32 i) -{ opcodez x; - ASSERT_ZCODE(); - if (i == -1) return custom_opcode_z; - x = opcodes_table_z[i]; - if (instruction_set_number < x.version1) return invalid_opcode_z; - if (x.version2 == 0) return x; - if (instruction_set_number <= x.version2) return x; - i = x.extension; - if (i < 0) return invalid_opcode_z; - x = extension_table_z[i]; - if (instruction_set_number < x.version1) return invalid_opcode_z; - if (x.version2 == 0) return x; - if (instruction_set_number <= x.version2) return x; - return extension_table_z[x.extension]; -} - -static void make_opcode_syntax_z(opcodez opco) -{ char *p = "", *q = opcode_syntax_string; - sprintf(q, "%s", opco.name); - switch(opco.no) - { case ONE: p=" "; break; - case TWO: p=" "; break; - case EXT: - case VAR: p=" <0 to 4 operands>"; break; - case VAR_LONG: p=" <0 to 8 operands>"; break; - } - switch(opco.op_rules) - { case TEXT: sprintf(q+strlen(q), " "); return; - case LABEL: sprintf(q+strlen(q), "