From b9dd4b657dc1d5d89eee64354e77cb9582e6ede6 Mon Sep 17 00:00:00 2001
From: Graham Nelson
+
-int CodeGen::CL::node_is_ref_to(inter_tree *I, inter_tree_node *P, inter_ti seek_bip) {
+int CodeGen::CL::node_is_ref_to(inter_tree *I, inter_tree_node *P, inter_ti seek_bip) {
int reffed = FALSE;
while (P->W.data[ID_IFLD] == REFERENCE_IST) {
P = InterTree::first_child(P);
diff --git a/docs/final-module/2-cg.html b/docs/final-module/2-cg.html
index 105296cbd..32b7b2f9d 100644
--- a/docs/final-module/2-cg.html
+++ b/docs/final-module/2-cg.html
@@ -201,7 +201,7 @@ always be done in a way which is then undone, restoring the previous state:
-generated_segment *CodeGen::select(code_generation *gen, int i) { +generated_segment *CodeGen::select(code_generation *gen, int i) { generated_segment *saved = gen->current_segment; if ((i < 0) || (i >= MAX_CG_SEGMENTS)) internal_error("out of range"); if (gen->temporarily_diverted) internal_error("poorly timed selection"); @@ -209,7 +209,7 @@ always be done in a way which is then undone, restoring the previous state: return saved; } -void CodeGen::deselect(code_generation *gen, generated_segment *saved) { +void CodeGen::deselect(code_generation *gen, generated_segment *saved) { if (gen->temporarily_diverted) internal_error("poorly timed deselection"); gen->current_segment = saved; } @@ -238,7 +238,7 @@ we also have to direct it to a given text.-text_stream *CodeGen::current(code_generation *gen) { +text_stream *CodeGen::current(code_generation *gen) { if (gen->temporarily_diverted) return gen->segments[temporary_I7CGS]->generated_code; if (gen->current_segment == NULL) return NULL; diff --git a/docs/final-module/2-ft.html b/docs/final-module/2-ft.html index 3c2cdbe8c..410cb15b5 100644 --- a/docs/final-module/2-ft.html +++ b/docs/final-module/2-ft.html @@ -401,6 +401,7 @@ function togglePopup(material_id) {+enum BEGIN_ARRAY_MTID enum ARRAY_ENTRY_MTID +enum ARRAY_ENTRIES_MTID enum END_ARRAY_MTID define WORD_ARRAY_FORMAT 1 define BYTE_ARRAY_FORMAT 2 @@ -410,6 +411,7 @@ function togglePopup(material_id) {VOID_METHOD_TYPE(BEGIN_ARRAY_MTID, code_generation_target *cgt, code_generation *gen, text_stream *const_name, int format) VOID_METHOD_TYPE(ARRAY_ENTRY_MTID, code_generation_target *cgt, code_generation *gen, text_stream *entry, int format) +VOID_METHOD_TYPE(ARRAY_ENTRIES_MTID, code_generation_target *cgt, code_generation *gen, int how_many, int plus_ips, int format) VOID_METHOD_TYPE(END_ARRAY_MTID, code_generation_target *cgt, code_generation *gen, int format) void CodeGen::Targets::begin_array(code_generation *gen, text_stream *const_name, int format) { VOID_METHOD_CALL(gen->target, BEGIN_ARRAY_MTID, gen, const_name, format); @@ -417,13 +419,16 @@ function togglePopup(material_id) { void CodeGen::Targets::array_entry(code_generation *gen, text_stream *entry, int format) { VOID_METHOD_CALL(gen->target, ARRAY_ENTRY_MTID, gen, entry, format); } -void CodeGen::Targets::mangled_array_entry(code_generation *gen, text_stream *entry, int format) { +void CodeGen::Targets::array_entries(code_generation *gen, int how_many, int plus_ips, int format) { + VOID_METHOD_CALL(gen->target, ARRAY_ENTRIES_MTID, gen, how_many, plus_ips, format); +} +void CodeGen::Targets::mangled_array_entry(code_generation *gen, text_stream *entry, int format) { TEMPORARY_TEXT(mangled) CodeGen::Targets::mangle(gen, mangled, entry); VOID_METHOD_CALL(gen->target, ARRAY_ENTRY_MTID, gen, mangled, format); DISCARD_TEXT(mangled) } -void CodeGen::Targets::end_array(code_generation *gen, int format) { +void CodeGen::Targets::end_array(code_generation *gen, int format) { VOID_METHOD_CALL(gen->target, END_ARRAY_MTID, gen, format); }@@ -433,7 +438,7 @@ function togglePopup(material_id) {VOID_METHOD_TYPE(NEW_FAKE_ACTION_MTID, code_generation_target *cgt, code_generation *gen, text_stream *name) -void CodeGen::Targets::new_fake_action(code_generation *gen, text_stream *name) { +void CodeGen::Targets::new_fake_action(code_generation *gen, text_stream *name) { VOID_METHOD_CALL(gen->target, NEW_FAKE_ACTION_MTID, gen, name); }diff --git a/docs/final-module/4-fi6.html b/docs/final-module/4-fi6.html index ddef46cd2..8161d2255 100644 --- a/docs/final-module/4-fi6.html +++ b/docs/final-module/4-fi6.html @@ -177,10 +177,11 @@ function togglePopup(material_id) { METHOD_ADD(cgt, END_OPCODE_MTID, CodeGen::I6::end_opcode); METHOD_ADD(cgt, BEGIN_ARRAY_MTID, CodeGen::I6::begin_array); METHOD_ADD(cgt, ARRAY_ENTRY_MTID, CodeGen::I6::array_entry); - METHOD_ADD(cgt, END_ARRAY_MTID, CodeGen::I6::end_array); + METHOD_ADD(cgt, ARRAY_ENTRIES_MTID, CodeGen::I6::array_entries); + METHOD_ADD(cgt, END_ARRAY_MTID, CodeGen::I6::end_array); METHOD_ADD(cgt, OFFER_PRAGMA_MTID, CodeGen::I6::offer_pragma) METHOD_ADD(cgt, END_GENERATION_MTID, CodeGen::I6::end_generation); - METHOD_ADD(cgt, NEW_FAKE_ACTION_MTID, CodeGen::I6::new_fake_action); + METHOD_ADD(cgt, NEW_FAKE_ACTION_MTID, CodeGen::I6::new_fake_action); inform6_target = cgt; } @@ -943,13 +944,25 @@ trick called "stubbing", these being "stub definitions".) text_stream *OUT = CodeGen::current(gen); WRITE(" (%S)", entry); } +§9. Alternatively, we can just specify how many entries there will be: they will +then be initialised to 0. +
-void CodeGen::I6::end_array(code_generation_target *cgt, code_generation *gen, int format) { ++void CodeGen::I6::array_entries(code_generation_target *cgt, code_generation *gen, + int how_many, int plus_ips, int format) { + text_stream *OUT = CodeGen::current(gen); + if (plus_ips) WRITE(" (%d + INDIV_PROP_START)", how_many, plus_ips); + else WRITE(" (%d)", how_many); +} + +void CodeGen::I6::end_array(code_generation_target *cgt, code_generation *gen, int format) { text_stream *OUT = CodeGen::current(gen); WRITE(";\n"); } -void CodeGen::I6::new_fake_action(code_generation_target *cgt, code_generation *gen, text_stream *name) { +void CodeGen::I6::new_fake_action(code_generation_target *cgt, code_generation *gen, text_stream *name) { text_stream *OUT = CodeGen::current(gen); WRITE("Fake_Action %S;\n", name); } diff --git a/docs/final-module/5-car.html b/docs/final-module/5-car.html index 57b8ebffc..45101a91d 100644 --- a/docs/final-module/5-car.html +++ b/docs/final-module/5-car.html @@ -85,9 +85,19 @@ easy. case PLUS_BIP: WRITE("("); INV_A1; WRITE(" + "); INV_A2; WRITE(")"); break; case MINUS_BIP: WRITE("("); INV_A1; WRITE(" - "); INV_A2; WRITE(")"); break; case UNARYMINUS_BIP: WRITE("(-("); INV_A1; WRITE("))"); break; - case TIMES_BIP: WRITE("("); INV_A1; WRITE("*"); INV_A2; WRITE(")"); break; - case DIVIDE_BIP: WRITE("("); INV_A1; WRITE("/"); INV_A2; WRITE(")"); break; - case MODULO_BIP: WRITE("("); INV_A1; WRITE("%%"); INV_A2; WRITE(")"); break; + case TIMES_BIP: WRITE("("); INV_A1; WRITE(" * "); INV_A2; WRITE(")"); break; + case DIVIDE_BIP: if (CFunctionModel::inside_function(gen)) { + WRITE("glulx_div_r("); INV_A1; WRITE(", "); INV_A2; WRITE(")"); + } else { + WRITE("("); INV_A1; WRITE(" / "); INV_A2; WRITE(")"); break; + } + break; + case MODULO_BIP: if (CFunctionModel::inside_function(gen)) { + WRITE("glulx_mod_r("); INV_A1; WRITE(", "); INV_A2; WRITE(")"); + } else { + WRITE("("); INV_A1; WRITE(" %% "); INV_A2; WRITE(")"); + } + break; case BITWISEAND_BIP: WRITE("(("); INV_A1; WRITE(")&("); INV_A2; WRITE("))"); break; case BITWISEOR_BIP: WRITE("(("); INV_A1; WRITE(")|("); INV_A2; WRITE("))"); break; case BITWISENOT_BIP: WRITE("(~("); INV_A1; WRITE("))"); break; @@ -131,105 +141,277 @@ storing float@@ -201,10 +233,6 @@ function togglePopup(material_id) { printf("Unimplemented: glulx_copy.\n"); } -void glulx_div(i7val x, i7val y, i7val z) { - printf("Unimplemented: glulx_div.\n"); -} - void glulx_gestalt(i7val x, i7val y, i7val *z) { *z = 1; } @@ -238,7 +266,7 @@ function togglePopup(material_id) { } int glulx_jeq(i7val x, i7val y) { - printf("Unimplemented: glulx_jeq.\n"); + if (x == y) return 1; return 0; } @@ -248,12 +276,12 @@ function togglePopup(material_id) { } int glulx_jnz(i7val x) { - printf("Unimplemented: glulx_jnz.\n"); + if (x != 0) return 1; return 0; } int glulx_jz(i7val x) { - printf("Unimplemented: glulx_jz.\n"); + if (x == 0) return 1; return 0; } @@ -269,17 +297,6 @@ function togglePopup(material_id) { printf("Unimplemented: glulx_mfree.\n"); } -void glulx_mod(i7val x, i7val y, i7val z) { - printf("Unimplemented: glulx_mod.\n"); -} - -void glulx_neg(i7val x, i7val y) { - printf("Unimplemented: glulx_neg.\n"); -} - -void glulx_numtof(i7val x, i7val y) { - printf("Unimplemented: glulx_numtof.\n"); -} void glulx_quit(void) { printf("Unimplemented: glulx_quit.\n"); @@ -293,12 +310,14 @@ function togglePopup(material_id) { // Deliberately ignored: we are using stdout, not glk } +void i7_print_char(i7val x); void glulx_streamchar(i7val x) { - printf("%c", (int) x); + i7_print_char(x); } +void i7_print_decimal(i7val x); void glulx_streamnum(i7val x) { - printf("Unimplemented: glulx_streamnum.\n"); + i7_print_decimal(x); } void glulx_streamstr(i7val x) { @@ -306,11 +325,7 @@ function togglePopup(material_id) { } void glulx_streamunichar(i7val x) { - printf("%c", (int) x); -} - -void glulx_sub(i7val x, i7val y, i7val z) { - printf("Unimplemented: glulx_sub.\n"); + i7_print_char(x); } void glulx_ushiftr(i7val x, i7val y, i7val z) { diff --git a/docs/final-module/5-cfm.html b/docs/final-module/5-cfm.html index 66822e940..9d7c65537 100644 --- a/docs/final-module/5-cfm.html +++ b/docs/final-module/5-cfm.html @@ -92,12 +92,14 @@ function togglePopup(material_id) { struct text_stream *prototype; int argument_count; struct final_c_function *current_fcf; + int compiling_function; } C_generation_function_model_data; void CFunctionModel::initialise_data(code_generation *gen) { C_GEN_DATA(fndata.prototype) = Str::new(); C_GEN_DATA(fndata.argument_count) = 0; C_GEN_DATA(fndata.current_fcf) = NULL; + C_GEN_DATA(fndata.compiling_function) = FALSE; } void CFunctionModel::begin(code_generation *gen) { @@ -137,6 +139,43 @@ function togglePopup(material_id) { WRITE("#endif\n"); WRITE("#endif\n"); CodeGen::deselect(gen, saved); + + saved = CodeGen::select(gen, c_fundamental_types_I7CGS); + OUT = CodeGen::current(gen); + WRITE("i7val i7_gen_call(i7val fn_ref, i7val *args, int argc, int call_message);\n"); + CodeGen::deselect(gen, saved); + + saved = CodeGen::select(gen, c_stubs_at_eof_I7CGS); + OUT = CodeGen::current(gen); + WRITE("i7val i7_gen_call(i7val fn_ref, i7val *args, int argc, int call_message) {\n"); INDENT; + WRITE("switch (fn_ref) {\n"); INDENT; + final_c_function *fcf; + LOOP_OVER(fcf, final_c_function) { + WRITE("case "); + CNamespace::mangle(NULL, OUT, fcf->identifier_as_constant); + WRITE(": return fn_"); + CNamespace::mangle(NULL, OUT, fcf->identifier_as_constant); + WRITE("("); + if (fcf->uses_vararg_model) { + WRITE("2, argc, (i7varargs) { "); + for (int i=0; i<10; i++) { + if (i > 0) WRITE(", "); + WRITE("args[%d]", i); + } + WRITE(" }"); + for (int i=0; i<fcf->max_arity - 1; i++) + WRITE(", 0"); + } else { + WRITE("argc"); + for (int i=0; i<fcf->max_arity; i++) + WRITE(", args[%d]", i); + } + WRITE(");\n"); + } + OUTDENT; WRITE("}\n"); + WRITE("printf(\"function not found\\n\");\n"); + OUTDENT; WRITE("}\n"); + CodeGen::deselect(gen, saved); } typedef struct final_c_function { @@ -165,6 +204,7 @@ function togglePopup(material_id) { void CFunctionModel::make_veneer_fcf(code_generation *gen, text_stream *unmangled_name) { final_c_function *fcf = CFunctionModel::new_fcf(unmangled_name); + fcf->max_arity = 1; CFunctionModel::declare_fcf(gen, fcf); } @@ -196,6 +236,7 @@ function togglePopup(material_id) { WRITE("printf(\"called %S\\n\");\n", C_GEN_DATA(fndata.current_fcf)->identifier_as_constant); } } + C_GEN_DATA(fndata.compiling_function) = TRUE; } void CFunctionModel::place_label(code_generation_target *cgt, code_generation *gen, text_stream *label_name) { @@ -222,9 +263,15 @@ function togglePopup(material_id) { text_stream *OUT = CodeGen::current(gen); WRITE("return 1;\n"); WRITE("\n}\n"); + C_GEN_DATA(fndata.compiling_function) = FALSE; } } +int CFunctionModel::inside_function(code_generation *gen) { + if (C_GEN_DATA(fndata.compiling_function)) return TRUE; + return FALSE; +} + void CFunctionModel::begin_function_call(code_generation_target *cgt, code_generation *gen, inter_symbol *fn, int argc) { inter_tree_node *D = fn->definition; if ((D) && (D->W.data[ID_IFLD] == CONSTANT_IST) && (D->W.data[FORMAT_CONST_IFLD] == CONSTANT_DIRECT)) { @@ -323,11 +370,6 @@ function togglePopup(material_id) { i7val i7_mgl_self = 0; -i7val i7_gen_call(i7val fn_ref, i7val *args, int argc, int call_message) { - printf("Unimplemented: i7_gen_call.\n"); - return 0; -} - i7val i7_call_0(i7val fn_ref) { i7val args[10]; for (int i=0; i<10; i++) args[i] = 0; return i7_gen_call(fn_ref, args, 0, 0); diff --git a/docs/final-module/5-cgv.html b/docs/final-module/5-cgv.html index 5d0418216..f131e0302 100644 --- a/docs/final-module/5-cgv.html +++ b/docs/final-module/5-cgv.html @@ -139,7 +139,7 @@ function togglePopup(material_id) { CMemoryModel::array_entry(cgt, gen, I"0", WORD_ARRAY_FORMAT); CMemoryModel::array_entry(cgt, gen, I"0", WORD_ARRAY_FORMAT); } - CMemoryModel::end_array(cgt, gen, WORD_ARRAY_FORMAT); + CMemoryModel::end_array(cgt, gen, WORD_ARRAY_FORMAT); } } return k; diff --git a/docs/final-module/5-cim.html b/docs/final-module/5-cim.html index 4b40e3c04..05310ab2f 100644 --- a/docs/final-module/5-cim.html +++ b/docs/final-module/5-cim.html @@ -110,7 +110,7 @@ function togglePopup(material_id) { case PRINTNAME_BIP: WRITE("i7_print_name("); INV_A1; WRITE(")"); break; case PRINTOBJ_BIP: WRITE("i7_print_object("); INV_A1; WRITE(")"); break; case PRINTPROPERTY_BIP: WRITE("i7_print_property("); INV_A1; WRITE(")"); break; - case PRINTNUMBER_BIP: WRITE("printf(\"%%d\", (int) "); INV_A1; WRITE(")"); break; + case PRINTNUMBER_BIP: WRITE("i7_print_decimal("); INV_A1; WRITE(")"); break; case PRINTNLNUMBER_BIP: WRITE("i7_print_number("); INV_A1; WRITE(")"); break; case PRINTDEF_BIP: WRITE("i7_print_def_art("); INV_A1; WRITE(")"); break; case PRINTCDEF_BIP: WRITE("i7_print_cdef_art("); INV_A1; WRITE(")"); break; @@ -138,6 +138,10 @@ function togglePopup(material_id) { void i7_font(int what) { } +void i7_print_decimal(i7val x) { + printf("%d", (int) x); +} + void i7_print_char(i7val x) { printf("%c", (int) x); } diff --git a/docs/final-module/5-cmm.html b/docs/final-module/5-cmm.html index 6b2937b1c..a1d2ef951 100644 --- a/docs/final-module/5-cmm.html +++ b/docs/final-module/5-cmm.html @@ -74,7 +74,7 @@ function togglePopup(material_id) {-void glulx_exp(i7val x, i7val y) { - printf("Unimplemented: glulx_exp.\n"); +void glulx_add(i7val x, i7val y, i7val *z) { + if (z) *z = x + y; } -void glulx_fadd(i7val x, i7val y, i7val z) { - printf("Unimplemented: glulx_fadd.\n"); +void glulx_sub(i7val x, i7val y, i7val *z) { + if (z) *z = x - y; } -void glulx_fdiv(i7val x, i7val y, i7val z) { - printf("Unimplemented: glulx_fdiv.\n"); +void glulx_neg(i7val x, i7val *y) { + if (y) *y = -x; } -void glulx_floor(i7val x, i7val y) { - printf("Unimplemented: glulx_floor.\n"); +void glulx_mul(i7val x, i7val y, i7val *z) { + if (z) *z = x * y; } -void glulx_fmod(i7val x, i7val y, i7val z, i7val w) { - printf("Unimplemented: glulx_fmod.\n"); +void glulx_div(i7val x, i7val y, i7val *z) { + if (y == 0) { printf("Division of %d by 0\n", x); if (z) *z = 1; return; } + int result, ax, ay; + /* Since C doesn't guarantee the results of division of negative + numbers, we carefully convert everything to positive values + first. They have to be unsigned values, too, otherwise the + 0x80000000 case goes wonky. */ + if (x < 0) { + ax = (-x); + if (y < 0) { + ay = (-y); + result = ax / ay; + } else { + ay = y; + result = -(ax / ay); + } + } else { + ax = x; + if (y < 0) { + ay = (-y); + result = -(ax / ay); + } else { + ay = y; + result = ax / ay; + } + } + if (z) *z = result; } -void glulx_fmul(i7val x, i7val y, i7val z) { - printf("Unimplemented: glulx_fmul.\n"); +i7val glulx_div_r(i7val x, i7val y) { + i7val z; + glulx_div(x, y, &z); + return z; } -void glulx_fsub(i7val x, i7val y, i7val z) { - printf("Unimplemented: glulx_fsub.\n"); +void glulx_mod(i7val x, i7val y, i7val *z) { + if (y == 0) { printf("Division of %d by 0\n", x); if (z) *z = 0; return; } + int result, ax, ay; + if (y < 0) { + ay = -y; + } else { + ay = y; + } + if (x < 0) { + ax = (-x); + result = -(ax % ay); + } else { + ax = x; + result = ax % ay; + } + if (z) *z = result; } -void glulx_ftonumn(i7val x, i7val y) { - printf("Unimplemented: glulx_ftonumn.\n"); +i7val glulx_mod_r(i7val x, i7val y) { + i7val z; + glulx_mod(x, y, &z); + return z; } -void glulx_ftonumz(i7val x, i7val y) { - printf("Unimplemented: glulx_ftonumz.\n"); +typedef float gfloat32; + +i7val encode_float(gfloat32 val) { + i7val res; + *(gfloat32 *)(&res) = val; + return res; +} + +gfloat32 decode_float(i7val val) { + gfloat32 res; + *(i7val *)(&res) = val; + return res; +} + +void glulx_exp(i7val x, i7val *y) { + *y = encode_float(expf(decode_float(x))); +} + +void glulx_fadd(i7val x, i7val y, i7val *z) { + *z = encode_float(decode_float(x) + decode_float(y)); +} + +void glulx_fdiv(i7val x, i7val y, i7val *z) { + *z = encode_float(decode_float(x) / decode_float(y)); +} + +void glulx_floor(i7val x, i7val *y) { + *y = encode_float(floorf(decode_float(x))); +} + +void glulx_fmod(i7val x, i7val y, i7val *z, i7val *w) { + float fx = decode_float(x); + float fy = decode_float(y); + float fquot = fmodf(fx, fy); + i7val quot = encode_float(fquot); + i7val rem = encode_float((fx-fquot) / fy); + if (rem == 0x0 || rem == 0x80000000) { + /* When the quotient is zero, the sign has been lost in the + shuffle. We'll set that by hand, based on the original + arguments. */ + rem = (x ^ y) & 0x80000000; + } + if (z) *z = quot; + if (w) *w = rem; +} + +void glulx_fmul(i7val x, i7val y, i7val *z) { + *z = encode_float(decode_float(x) * decode_float(y)); +} + +void glulx_fsub(i7val x, i7val y, i7val *z) { + *z = encode_float(decode_float(x) - decode_float(y)); +} + +void glulx_ftonumn(i7val x, i7val *y) { + float fx = decode_float(x); + i7val result; + if (!signbit(fx)) { + if (isnan(fx) || isinf(fx) || (fx > 2147483647.0)) + result = 0x7FFFFFFF; + else + result = (i7val) (roundf(fx)); + } + else { + if (isnan(fx) || isinf(fx) || (fx < -2147483647.0)) + result = 0x80000000; + else + result = (i7val) (roundf(fx)); + } + *y = result; +} + +void glulx_ftonumz(i7val x, i7val *y) { + float fx = decode_float(x); + i7val result; + if (!signbit(fx)) { + if (isnan(fx) || isinf(fx) || (fx > 2147483647.0)) + result = 0x7FFFFFFF; + else + result = (i7val) (truncf(fx)); + } + else { + if (isnan(fx) || isinf(fx) || (fx < -2147483647.0)) + result = 0x80000000; + else + result = (i7val) (truncf(fx)); + } + *y = result; +} + +void glulx_numtof(i7val x, i7val *y) { + *y = encode_float((float) x); } int glulx_jfeq(i7val x, i7val y, i7val z) { - printf("Unimplemented: glulx_jfeq.\n"); + int result; + if ((z & 0x7F800000) == 0x7F800000 && (z & 0x007FFFFF) != 0) { + /* The delta is NaN, which can never match. */ + result = 0; + } else if ((x == 0x7F800000 || x == 0xFF800000) + && (y == 0x7F800000 || y == 0xFF800000)) { + /* Both are infinite. Opposite infinities are never equal, + even if the difference is infinite, so this is easy. */ + result = (x == y); + } else { + float fx = decode_float(y) - decode_float(x); + float fy = fabs(decode_float(z)); + result = (fx <= fy && fx >= -fy); + } + if (!result) return 1; return 0; } +int glulx_jfne(i7val x, i7val y, i7val z) { + int result; + if ((z & 0x7F800000) == 0x7F800000 && (z & 0x007FFFFF) != 0) { + /* The delta is NaN, which can never match. */ + result = 0; + } else if ((x == 0x7F800000 || x == 0xFF800000) + && (y == 0x7F800000 || y == 0xFF800000)) { + /* Both are infinite. Opposite infinities are never equal, + even if the difference is infinite, so this is easy. */ + result = (x == y); + } else { + float fx = decode_float(y) - decode_float(x); + float fy = fabs(decode_float(z)); + result = (fx <= fy && fx >= -fy); + } + if (!result) return 1; +} + int glulx_jfge(i7val x, i7val y) { - printf("Unimplemented: glulx_jfge.\n"); + if (isgreaterequal(decode_float(x), decode_float(y))) return 1; return 0; } int glulx_jflt(i7val x, i7val y) { - printf("Unimplemented: glulx_jflt.\n"); + if (isless(decode_float(x), decode_float(y))) return 1; return 0; } int glulx_jisinf(i7val x) { - printf("Unimplemented: glulx_jisinf.\n"); + if (isinf(decode_float(x))) return 1; return 0; } int glulx_jisnan(i7val x) { - printf("Unimplemented: glulx_jisnan.\n"); + if (isnan(decode_float(x))) return 1; return 0; } -void glulx_log(i7val x, i7val y) { - printf("Unimplemented: glulx_log.\n"); +void glulx_log(i7val x, i7val *y) { + *y = encode_float(logf(decode_float(x))); } void glulx_acos(i7val x, i7val *y) { - printf("Unimplemented: glulx_acos\n"); + *y = encode_float(acosf(decode_float(x))); } void glulx_asin(i7val x, i7val *y) { - printf("Unimplemented: glulx_asin\n"); + *y = encode_float(asinf(decode_float(x))); } void glulx_atan(i7val x, i7val *y) { - printf("Unimplemented: glulx_atan\n"); + *y = encode_float(atanf(decode_float(x))); } void glulx_ceil(i7val x, i7val *y) { - printf("Unimplemented: glulx_ceil\n"); + *y = encode_float(ceilf(decode_float(x))); } void glulx_cos(i7val x, i7val *y) { - printf("Unimplemented: glulx_cos\n"); + *y = encode_float(cosf(decode_float(x))); } void glulx_pow(i7val x, i7val y, i7val *z) { - printf("Unimplemented: glulx_pow\n"); + if (decode_float(x) == 1.0f) + *z = encode_float(1.0f); + else if ((decode_float(y) == 0.0f) || (decode_float(y) == -0.0f)) + *z = encode_float(1.0f); + else if ((decode_float(x) == -1.0f) && isinf(decode_float(y))) + *z = encode_float(1.0f); + else + *z = encode_float(powf(decode_float(x), decode_float(y))); } void glulx_sin(i7val x, i7val *y) { - printf("Unimplemented: glulx_sin\n"); + *y = encode_float(sinf(decode_float(x))); } void glulx_sqrt(i7val x, i7val *y) { - printf("Unimplemented: glulx_sqrt\n"); + *y = encode_float(sqrtf(decode_float(x))); } void glulx_tan(i7val x, i7val *y) { - printf("Unimplemented: glulx_tan\n"); + *y = encode_float(tanf(decode_float(x))); }diff --git a/docs/final-module/5-cas.html b/docs/final-module/5-cas.html index cfa6adde0..e6b8cca3f 100644 --- a/docs/final-module/5-cas.html +++ b/docs/final-module/5-cas.html @@ -87,14 +87,17 @@ function togglePopup(material_id) { int operand_count; int operand_branches; struct inter_tree_node *operand_label; - int pointer_on_operand; + int pointer_on_operand[16]; + int pushed_result; } C_generation_assembly_data; void CAssembly::initialise_data(code_generation *gen) { C_GEN_DATA(asmdata.operand_count) = 0; C_GEN_DATA(asmdata.operand_branches) = FALSE; C_GEN_DATA(asmdata.operand_label) = NULL; - C_GEN_DATA(asmdata.pointer_on_operand) = -1; + for (int i=0; i<16; i++) + C_GEN_DATA(asmdata.pointer_on_operand[i]) = FALSE; + C_GEN_DATA(asmdata.pushed_result) = FALSE; } void CAssembly::begin(code_generation *gen) { @@ -109,14 +112,18 @@ function togglePopup(material_id) {
- This is part of the extract file inform7_clib.h.
i7val i7_mgl_sp = 0; +#define I7_ASM_STACK_CAPACITY 128 +i7val i7_asm_stack[I7_ASM_STACK_CAPACITY]; +int i7_asm_stack_pointer = 0; i7val i7_pull(void) { - printf("Unimplemented: i7_pull.\n"); - return (i7val) 0; + if (i7_asm_stack_pointer <= 0) { printf("Stack underflow\n"); return (i7val) 0; } + return i7_asm_stack[--i7_asm_stack_pointer]; } void i7_push(i7val x) { - printf("Unimplemented: i7_push.\n"); + if (i7_asm_stack_pointer >= I7_ASM_STACK_CAPACITY) { printf("Stack overflow\n"); return; } + i7_asm_stack[i7_asm_stack_pointer++] = x; }@@ -126,6 +133,7 @@ function togglePopup(material_id) { void CAssembly::begin_opcode(code_generation_target *cgt, code_generation *gen, text_stream *opcode) { text_stream *OUT = CodeGen::current(gen); C_GEN_DATA(asmdata.operand_branches) = FALSE; + C_GEN_DATA(asmdata.pushed_result) = FALSE; C_GEN_DATA(asmdata.operand_label) = NULL; if (Str::get_at(opcode, 1) == 'j') { C_GEN_DATA(asmdata.operand_branches) = TRUE; } if (Str::eq(opcode, I"@return")) WRITE("return "); @@ -134,23 +142,44 @@ function togglePopup(material_id) { CNamespace::mangle_opcode(cgt, OUT, opcode); } WRITE("("); C_GEN_DATA(asmdata.operand_count) = 0; - C_GEN_DATA(asmdata.pointer_on_operand) = -1; - if (Str::eq(opcode, I"@acos")) C_GEN_DATA(asmdata.pointer_on_operand) = 2; - if (Str::eq(opcode, I"@aload")) C_GEN_DATA(asmdata.pointer_on_operand) = 3; - if (Str::eq(opcode, I"@aloadb")) C_GEN_DATA(asmdata.pointer_on_operand) = 3; - if (Str::eq(opcode, I"@aloads")) C_GEN_DATA(asmdata.pointer_on_operand) = 3; - if (Str::eq(opcode, I"@asin")) C_GEN_DATA(asmdata.pointer_on_operand) = 2; - if (Str::eq(opcode, I"@atan")) C_GEN_DATA(asmdata.pointer_on_operand) = 2; - if (Str::eq(opcode, I"@binarysearch")) C_GEN_DATA(asmdata.pointer_on_operand) = 8; - if (Str::eq(opcode, I"@ceil")) C_GEN_DATA(asmdata.pointer_on_operand) = 2; - if (Str::eq(opcode, I"@cos")) C_GEN_DATA(asmdata.pointer_on_operand) = 2; - if (Str::eq(opcode, I"@gestalt")) C_GEN_DATA(asmdata.pointer_on_operand) = 3; - if (Str::eq(opcode, I"@glk")) C_GEN_DATA(asmdata.pointer_on_operand) = 3; - if (Str::eq(opcode, I"@pow")) C_GEN_DATA(asmdata.pointer_on_operand) = 3; - if (Str::eq(opcode, I"@shiftl")) C_GEN_DATA(asmdata.pointer_on_operand) = 3; - if (Str::eq(opcode, I"@sin")) C_GEN_DATA(asmdata.pointer_on_operand) = 2; - if (Str::eq(opcode, I"@sqrt")) C_GEN_DATA(asmdata.pointer_on_operand) = 2; - if (Str::eq(opcode, I"@tan")) C_GEN_DATA(asmdata.pointer_on_operand) = 2; + for (int i=0; i<16; i++) + C_GEN_DATA(asmdata.pointer_on_operand[i]) = FALSE; + if (Str::eq(opcode, I"@acos")) C_GEN_DATA(asmdata.pointer_on_operand[2]) = TRUE; + if (Str::eq(opcode, I"@add")) C_GEN_DATA(asmdata.pointer_on_operand[3]) = TRUE; + if (Str::eq(opcode, I"@aload")) C_GEN_DATA(asmdata.pointer_on_operand[3]) = TRUE; + if (Str::eq(opcode, I"@aloadb")) C_GEN_DATA(asmdata.pointer_on_operand[3]) = TRUE; + if (Str::eq(opcode, I"@aloads")) C_GEN_DATA(asmdata.pointer_on_operand[3]) = TRUE; + if (Str::eq(opcode, I"@asin")) C_GEN_DATA(asmdata.pointer_on_operand[2]) = TRUE; + if (Str::eq(opcode, I"@atan")) C_GEN_DATA(asmdata.pointer_on_operand[2]) = TRUE; + if (Str::eq(opcode, I"@binarysearch")) C_GEN_DATA(asmdata.pointer_on_operand[8]) = TRUE; + if (Str::eq(opcode, I"@ceil")) C_GEN_DATA(asmdata.pointer_on_operand[2]) = TRUE; + if (Str::eq(opcode, I"@cos")) C_GEN_DATA(asmdata.pointer_on_operand[2]) = TRUE; + if (Str::eq(opcode, I"@div")) C_GEN_DATA(asmdata.pointer_on_operand[3]) = TRUE; + if (Str::eq(opcode, I"@exp")) C_GEN_DATA(asmdata.pointer_on_operand[2]) = TRUE; + if (Str::eq(opcode, I"@fadd")) C_GEN_DATA(asmdata.pointer_on_operand[3]) = TRUE; + if (Str::eq(opcode, I"@fdiv")) C_GEN_DATA(asmdata.pointer_on_operand[3]) = TRUE; + if (Str::eq(opcode, I"@floor")) C_GEN_DATA(asmdata.pointer_on_operand[2]) = TRUE; + if (Str::eq(opcode, I"@fmod")) { + C_GEN_DATA(asmdata.pointer_on_operand[3]) = TRUE; + C_GEN_DATA(asmdata.pointer_on_operand[4]) = TRUE; + } + if (Str::eq(opcode, I"@fmul")) C_GEN_DATA(asmdata.pointer_on_operand[3]) = TRUE; + if (Str::eq(opcode, I"@fsub")) C_GEN_DATA(asmdata.pointer_on_operand[3]) = TRUE; + if (Str::eq(opcode, I"@ftonumn")) C_GEN_DATA(asmdata.pointer_on_operand[2]) = TRUE; + if (Str::eq(opcode, I"@ftonumz")) C_GEN_DATA(asmdata.pointer_on_operand[2]) = TRUE; + if (Str::eq(opcode, I"@gestalt")) C_GEN_DATA(asmdata.pointer_on_operand[3]) = TRUE; + if (Str::eq(opcode, I"@glk")) C_GEN_DATA(asmdata.pointer_on_operand[3]) = TRUE; + if (Str::eq(opcode, I"@log")) C_GEN_DATA(asmdata.pointer_on_operand[2]) = TRUE; + if (Str::eq(opcode, I"@mod")) C_GEN_DATA(asmdata.pointer_on_operand[3]) = TRUE; + if (Str::eq(opcode, I"@mul")) C_GEN_DATA(asmdata.pointer_on_operand[3]) = TRUE; + if (Str::eq(opcode, I"@neg")) C_GEN_DATA(asmdata.pointer_on_operand[2]) = TRUE; + if (Str::eq(opcode, I"@numtof")) C_GEN_DATA(asmdata.pointer_on_operand[2]) = TRUE; + if (Str::eq(opcode, I"@pow")) C_GEN_DATA(asmdata.pointer_on_operand[3]) = TRUE; + if (Str::eq(opcode, I"@shiftl")) C_GEN_DATA(asmdata.pointer_on_operand[3]) = TRUE; + if (Str::eq(opcode, I"@sin")) C_GEN_DATA(asmdata.pointer_on_operand[2]) = TRUE; + if (Str::eq(opcode, I"@sqrt")) C_GEN_DATA(asmdata.pointer_on_operand[2]) = TRUE; + if (Str::eq(opcode, I"@sub")) C_GEN_DATA(asmdata.pointer_on_operand[3]) = TRUE; + if (Str::eq(opcode, I"@tan")) C_GEN_DATA(asmdata.pointer_on_operand[2]) = TRUE; } void CAssembly::supply_operand(code_generation_target *cgt, code_generation *gen, inter_tree_node *F, int is_label) { text_stream *OUT = CodeGen::current(gen); @@ -158,17 +187,19 @@ function togglePopup(material_id) { C_GEN_DATA(asmdata.operand_label) = F; } else { if (C_GEN_DATA(asmdata.operand_count)++ > 0) WRITE(", "); - if (C_GEN_DATA(asmdata.operand_count) == C_GEN_DATA(asmdata.pointer_on_operand)) { - TEMPORARY_TEXT(write_to) - CodeGen::select_temporary(gen, write_to); - CodeGen::FC::frame(gen, F); - CodeGen::deselect_temporary(gen); - if (Str::eq(write_to, I"0")) WRITE("NULL"); + TEMPORARY_TEXT(write_to) + CodeGen::select_temporary(gen, write_to); + CodeGen::FC::frame(gen, F); + CodeGen::deselect_temporary(gen); + if (C_GEN_DATA(asmdata.pointer_on_operand[C_GEN_DATA(asmdata.operand_count)])) { + if (Str::eq(write_to, I"i7_mgl_sp")) { WRITE("&%S", write_to); C_GEN_DATA(asmdata.pushed_result) = TRUE; } + else if (Str::eq(write_to, I"0")) WRITE("NULL"); else WRITE("&%S", write_to); - DISCARD_TEXT(write_to) } else { - CodeGen::FC::frame(gen, F); + if (Str::eq(write_to, I"i7_mgl_sp")) { WRITE("i7_pull()"); } + else WRITE("%S", write_to); } + DISCARD_TEXT(write_to) } } void CAssembly::end_opcode(code_generation_target *cgt, code_generation *gen) { @@ -180,6 +211,7 @@ function togglePopup(material_id) { if (C_GEN_DATA(asmdata.operand_label) == NULL) internal_error("no branch label"); CodeGen::FC::frame(gen, C_GEN_DATA(asmdata.operand_label)); } + if (C_GEN_DATA(asmdata.pushed_result)) WRITE("; i7_push(i7_mgl_sp)"); }
- This is part of the extract file inform7_clib.h.
How arrays of all kinds are stored in C.
--void CMemoryModel::array_entry(code_generation_target *cgt, code_generation *gen, +void CMemoryModel::array_entry(code_generation_target *cgt, code_generation *gen, text_stream *entry, int format) { generated_segment *saved = CodeGen::select(gen, c_mem_I7CGS); text_stream *OUT = CodeGen::current(gen); @@ -298,7 +299,7 @@ predefine when the array ends.- WRITE(" (i7byte) %S,\n", entry); + WRITE(" (i7byte) %S, /* %d */\n", entry, C_GEN_DATA(memdata.himem)); C_GEN_DATA(memdata.himem) += 1;
- WRITE(" I7BYTE_0(%S), I7BYTE_1(%S), I7BYTE_2(%S), I7BYTE_3(%S),\n", - entry, entry, entry, entry); + WRITE(" I7BYTE_0(%S), I7BYTE_1(%S), I7BYTE_2(%S), I7BYTE_3(%S), /* %d */\n", + entry, entry, entry, entry, C_GEN_DATA(memdata.himem)); C_GEN_DATA(memdata.himem) += 4;
§9. When all the entries have been placed, the following is called. It does nothing +
§9. Alternatively, we can just specify how many entries there will be: they will +then be initialised to 0. +
+ ++void CMemoryModel::array_entries(code_generation_target *cgt, code_generation *gen, + int how_many, int plus_ips, int format) { + if (plus_ips) how_many += 64; + for (int i=0; i<how_many; i++) CMemoryModel::array_entry(cgt, gen, I"0", format); +} ++
§10. When all the entries have been placed, the following is called. It does nothing except to predeclare the extent constant, if one was used.
-void CMemoryModel::end_array(code_generation_target *cgt, code_generation *gen, int format) { +void CMemoryModel::end_array(code_generation_target *cgt, code_generation *gen, int format) { if ((format == TABLE_ARRAY_FORMAT) || (format == BUFFER_ARRAY_FORMAT)) { generated_segment *saved = CodeGen::select(gen, c_predeclarations_I7CGS); text_stream *OUT = CodeGen::current(gen); @@ -332,7 +344,7 @@ except to predeclare the extent constant, if one was used. } }-
§10. Primitives for byte and word lookup. The signatures here are: +
§11. Primitives for byte and word lookup. The signatures here are:
@@ -340,44 +352,44 @@ except to predeclare the extent constant, if one was used.
primitive !lookupbyte val val -> val
-int CMemoryModel::handle_store_by_ref(code_generation *gen, inter_tree_node *ref) { +int CMemoryModel::handle_store_by_ref(code_generation *gen, inter_tree_node *ref) { if (CodeGen::CL::node_is_ref_to(gen->from, ref, LOOKUP_BIP)) return TRUE; return FALSE; } -int CMemoryModel::compile_primitive(code_generation *gen, inter_ti bip, inter_tree_node *P) { +int CMemoryModel::compile_primitive(code_generation *gen, inter_ti bip, inter_tree_node *P) { text_stream *OUT = CodeGen::current(gen); switch (bip) { - case LOOKUP_BIP: if (CReferences::am_I_a_ref(gen)) Word value as reference10.2 - else Word value as value10.1; + case LOOKUP_BIP: if (CReferences::am_I_a_ref(gen)) Word value as reference11.2 + else Word value as value11.1; break; - case LOOKUPBYTE_BIP: Byte value as value10.3; break; + case LOOKUPBYTE_BIP: Byte value as value11.3; break; default: return NOT_APPLICABLE; } return FALSE; }-
§10.1. Word value as value10.1 = +
§11.1. Word value as value11.1 =
WRITE("i7_read_word(i7mem, "); INV_A1; WRITE(", "); INV_A2; WRITE(")");-
§10.2. Word value as reference10.2 = +
§11.2. Word value as reference11.2 =
WRITE("i7_write_word(i7mem, "); INV_A1; WRITE(", "); INV_A2; WRITE(", ");-
§10.3. Byte value as value10.3 = +
§11.3. Byte value as value11.3 =
WRITE("i7mem["); INV_A1; WRITE(" + "); INV_A2; WRITE("]");-
-int CReferences::am_I_a_ref(code_generation *gen) { +int CReferences::am_I_a_ref(code_generation *gen) { int answer = C_GEN_DATA(memdata.next_node_is_a_ref); C_GEN_DATA(memdata.next_node_is_a_ref) = FALSE; return answer; @@ -185,7 +185,7 @@ That's what is done by the "A1 as ref" mode set up above.inter_tree_node *ref = InterTree::first_child(P); - if ((CMemoryModel::handle_store_by_ref(gen, ref)) || + if ((CMemoryModel::handle_store_by_ref(gen, ref)) || (CObjectModel::handle_store_by_ref(gen, ref))) { Handle the ref using the incomplete-function mode4.1.1; } else { diff --git a/docs/final-module/5-fnc.html b/docs/final-module/5-fnc.html index bdbf2df14..4d3f4ba3d 100644 --- a/docs/final-module/5-fnc.html +++ b/docs/final-module/5-fnc.html @@ -123,6 +123,7 @@ first of those: #include <stdlib.h> #include <stdio.h> +#include <math.h>