# HG changeset patch # User Petter T. # Date 1696802950 -7200 # Node ID 7da49c0da993711f77e2f71b3608063baa6c481f # Parent 1156548e62111d7a5ded50ea224b9260e42f7b1c Support big endian systems in VM Recreate unsigned short, unsigned int from unsigned char pointer in a endian aware way. * configure.ac: Pull in WORDS_BIGENDIAN via call to AC_C_BIGENDIAN() * libinterp/parse-tree/pt-bytecode-vm.cc: #ifdef guards using WORDS_BIGENDIAN diff -r 1156548e6211 -r 7da49c0da993 configure.ac --- a/configure.ac Sun Oct 08 22:25:06 2023 +0200 +++ b/configure.ac Mon Oct 09 00:09:10 2023 +0200 @@ -1410,6 +1410,8 @@ ### Configure compilation of *experimental* Virtual Machine evaluator. +AC_C_BIGENDIAN() + ENABLE_VM_EVALUATOR=yes AC_ARG_ENABLE([vm-evaluator], [AS_HELP_STRING([--disable-vm-evaluator], diff -r 1156548e6211 -r 7da49c0da993 libinterp/parse-tree/pt-bytecode-vm.cc --- a/libinterp/parse-tree/pt-bytecode-vm.cc Sun Oct 08 22:25:06 2023 +0200 +++ b/libinterp/parse-tree/pt-bytecode-vm.cc Mon Oct 09 00:09:10 2023 +0200 @@ -52,6 +52,20 @@ //#pragma GCC optimize("O0") +// Returns the uint16 value stored at 'p' taking endianess into account +#ifdef WORDS_BIGENDIAN +#define USHORT_FROM_UCHAR_PTR(p) (((p)[0] << 8) + (p)[1]) +#else +#define USHORT_FROM_UCHAR_PTR(p) ((p)[0] + ((p)[1] << 8)) +#endif + +// Returns the uint16 value from two unsigned chars taking endianess into account +#ifdef WORDS_BIGENDIAN +#define USHORT_FROM_UCHARS(c1,c2) ((c1 << 8) | (c2)) +#else +#define USHORT_FROM_UCHARS(c1,c2) ((c1) | (c2 << 8)) +#endif + static bool ov_need_stepwise_subsrefs (octave_value &ov); static void copy_many_args_to_caller (octave::stack_element *sp, octave::stack_element *caller_stack_end, int n_args_to_move, int n_args_caller_expects); @@ -72,10 +86,17 @@ chars_to_uint (unsigned char *p) { unsigned u = 0; +#ifdef WORDS_BIGENDIAN + u |= *p++ << 24; + u |= *p++ << 16; + u |= *p++ << 8; + u |= *p; +#else u |= *p++; u |= *p++ << 8; u |= *p++ << 16; u |= *p << 24; +#endif return u; } @@ -134,13 +155,13 @@ s += std::string {" '"} + static_cast (*p) + "'";} #define PSHORT() \ - {p++; \ - CHECK_END (); \ - unsigned char b0 = *p; \ - p++; \ - CHECK_END (); \ - unsigned char b1 = *p; \ - unsigned u = b0 | (b1 << 8); \ + {p++; \ + CHECK_END (); \ + unsigned char b0 = *p; \ + p++; \ + CHECK_END (); \ + unsigned char b1 = *p; \ + unsigned u = USHORT_FROM_UCHARS (b0, b1); \ s += " " + std::to_string (u);} #define PSSLOT() \ @@ -165,7 +186,7 @@ p++; \ CHECK_END (); \ unsigned char b1 = *p; \ - unsigned u = b0 | (b1 << 8); \ + unsigned u = USHORT_FROM_UCHARS (b0, b1); \ s += " " + std::to_string (u); \ v_ids.push_back (std::string {u < names.size() ? \ names[u].c_str() : \ @@ -174,6 +195,22 @@ #define CHECK_END() \ do {if (p >= v_code.data () + v_code.size ()) { error ("Invalid bytecode\n");}} while((0)) +#ifdef WORDS_BIGENDIAN +#define PINT() \ + do {\ + unsigned u = 0;\ + p++;\ + CHECK_END ();\ + u |= *p++ << 24;\ + CHECK_END ();\ + u |= *p++ << 16;\ + CHECK_END ();\ + u |= *p++ << 8;\ + CHECK_END ();\ + u |= *p;\ + s += " " + std::to_string (u);\ + } while (0); +#else #define PINT() \ do {\ unsigned u = 0;\ @@ -188,6 +225,7 @@ u |= *p << 24;\ s += " " + std::to_string (u);\ } while (0); +#endif while (p < code + n) { @@ -532,11 +570,17 @@ { unsigned int ans; ip -= 4; +#ifdef WORDS_BIGENDIAN + ans = *ip++ << 24; + ans |= *ip++ << 16; + ans |= *ip++ << 8; + ans |= *ip++; +#else ans = *ip++; ans |= *ip++ << 8; ans |= *ip++ << 16; ans |= *ip++ << 24; - +#endif return ans; } @@ -544,9 +588,13 @@ { unsigned int ans; ip -= 2; +#ifdef WORDS_BIGENDIAN + ans = *ip++ << 8; + ans |= *ip++; +#else ans = *ip++; ans |= *ip++ << 8; - +#endif return ans; } @@ -913,7 +961,7 @@ { #define N_RETURNS() static_cast(code[0]) #define N_ARGS() static_cast(code[1]) -#define N_LOCALS() (code[2] | (code [3] << 8)) +#define N_LOCALS() USHORT_FROM_UCHAR_PTR (code + 2) int n_returns = static_cast (*ip++); // n_args is negative for varargin calls @@ -1378,7 +1426,7 @@ unsigned char b0 = arg0; unsigned char b1 = *ip++; - int target = b0 | (b1 << 8); + int target = USHORT_FROM_UCHARS (b0, b1); octave_bool &ovb_bool = REP (octave_bool, ov_1); @@ -1406,7 +1454,7 @@ unsigned char b0 = arg0; unsigned char b1 = *ip++; - int target = b0 | (b1 << 8); + int target = USHORT_FROM_UCHARS (b0, b1); bool is_true; if (ov_1.is_defined ()) @@ -1438,7 +1486,7 @@ unsigned char b0 = arg0; unsigned char b1 = *ip++; - int target = b0 | (b1 << 8); + int target = USHORT_FROM_UCHARS (b0, b1); ip = code + target; } DISPATCH (); @@ -1456,7 +1504,7 @@ unsigned char b0 = arg0; unsigned char b1 = *ip++; - int target = b0 | (b1 << 8); + int target = USHORT_FROM_UCHARS (b0, b1); octave_bool &ovb_bool = REP (octave_bool, ov_1); @@ -1484,7 +1532,7 @@ unsigned char b0 = arg0; unsigned char b1 = *ip++; - int target = b0 | (b1 << 8); + int target = USHORT_FROM_UCHARS (b0, b1); bool is_true; if (ov_1.is_defined ()) //10 @@ -1550,7 +1598,7 @@ if (ovb->is_defined () && ovb->cache_is_valid ()) { PUSH_OV (ovb->get_cached_value ()); - int target = b0 | (b1 << 8); + int target = USHORT_FROM_UCHARS (b0, b1); ip = code + target; } else @@ -2734,8 +2782,8 @@ // The next opcode is in arg0, and is either WIDE or FOR_COND if (arg0 == static_cast (INSTR::WIDE)) { - // Byte layout: ip[-2]:FOR_SETUP, ip[-1]:WIDE, ip[0]:FOR_COND, ip[1]:slot_lsb, ip[2]:slot_msb - slot = ip[1] + (ip[2] << 8); + // Byte layout: ip[-2]:FOR_SETUP, ip[-1]:WIDE, ip[0]:FOR_COND, ip[1:2]:wide slot + slot = USHORT_FROM_UCHAR_PTR (ip + 1); } else { @@ -2780,7 +2828,7 @@ unsigned char b0 = *ip++; unsigned char b1 = *ip++; - int after = b0 | (b1 << 8); + int after = USHORT_FROM_UCHARS (b0, b1); // goto after block ip = code + after; @@ -3593,7 +3641,7 @@ unsigned char b0 = arg0; unsigned char b1 = *ip++; - int target = b0 | (b1 << 8); + int target = USHORT_FROM_UCHARS (b0, b1); if (ov_rhs.is_undefined ()) { @@ -3635,7 +3683,7 @@ unsigned char b0 = arg0; unsigned char b1 = *ip++; - int after = b0 | (b1 << 8); + int after = USHORT_FROM_UCHARS (b0, b1); // goto after block ip = code + after; @@ -4300,7 +4348,7 @@ n_returns_callee = -n_returns_callee; } int n_args_callee = -static_cast (ip[-3]); // Note: Minus - int n_locals_callee = ip[-2] | (ip[-1] << 8); + int n_locals_callee = USHORT_FROM_UCHAR_PTR (ip - 2); int nargout = sp[-1].i; @@ -4755,7 +4803,7 @@ { unsigned char b0 = *ip++; unsigned char b1 = *ip++; - after = b0 | (b1 << 8); + after = USHORT_FROM_UCHARS (b0, b1); if (!global_is_new_in_callstack || slot_already_live) ip = code + after; @@ -4809,7 +4857,7 @@ unsigned char b0 = arg0; unsigned char b1 = *ip++; - int target = b0 | (b1 << 8); + int target = USHORT_FROM_UCHARS (b0, b1); if (ov_1.is_defined () && !ov_1.is_magic_colon ()) ip = code + target; @@ -4824,7 +4872,7 @@ unsigned char b0 = arg0; unsigned char b1 = *ip++; - int target = b0 | (b1 << 8); + int target = USHORT_FROM_UCHARS (b0, b1); bool do_it; if (ov_label.is_undefined ()) @@ -6195,7 +6243,7 @@ int opcode = arg0; // The opcode to execute next is in arg0, i.e. ip[-1] // The next opcode needs its arg0, which is a unsigned short instead of the usual byte // that DISPATCH() writes to arg0. - arg0 = (ip[1] << 8) | ip[0]; + arg0 = USHORT_FROM_UCHAR_PTR (ip); ip += 2; // Forward ip so it points to after the widened argument goto *instr [opcode]; }