|
| 1 | +diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in |
| 2 | +index 6424077b835bf62cff12b671d8200d764a67890e..2174829a6caae0ab6ad1300362e3684af03c95d0 100644 |
| 3 | +--- a/erts/emulator/Makefile.in |
| 4 | ++++ b/erts/emulator/Makefile.in |
| 5 | +@@ -613,6 +613,7 @@ $(TTF_DIR)/OPCODES-GENERATED: $(OPCODE_TABLES) utils/beam_makeops |
| 6 | + -code-model @CODE_MODEL@ \ |
| 7 | + -outdir $(TTF_DIR) \ |
| 8 | + -jit $(if $(filter jit,$(FLAVOR)),yes,no) \ |
| 9 | ++ -DWASM32=$(if $(filter wasm32-unknown-emscripten,$(TARGET)),1,0) \ |
| 10 | + -DUSE_VM_PROBES=$(if $(USE_VM_PROBES),1,0) \ |
| 11 | + -emulator $(OPCODE_TABLES) && echo $? >$(TTF_DIR)/OPCODES-GENERATED |
| 12 | + GENERATE += $(TTF_DIR)/OPCODES-GENERATED |
| 13 | +diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c |
| 14 | +index 9a3dcd29cef282dce3b36e851ca1ae765bf6e565..a0e7bc0d1b1ef29440a995495f80c0d9aefc7cc7 100644 |
| 15 | +--- a/erts/emulator/beam/beam_debug.c |
| 16 | ++++ b/erts/emulator/beam/beam_debug.c |
| 17 | +@@ -647,6 +647,15 @@ print_op(fmtfn_t to, void *to_arg, int op, int size, BeamInstr* addr) |
| 18 | + *ap++ = packed & BEAM_LOOSE_MASK; |
| 19 | + packed >>= BEAM_LOOSE_SHIFT; |
| 20 | + break; |
| 21 | ++#ifdef BEAM_COMPACT_LABEL_MASK |
| 22 | ++ case '5': |
| 23 | ++ *ap++ = (BeamInstr)((Sint32)packed >> |
| 24 | ++ BEAM_COMPACT_LABEL_SHIFT); |
| 25 | ++ break; |
| 26 | ++ case '6': |
| 27 | ++ *ap++ = (packed & BEAM_TIGHTEST_MASK) << 2; |
| 28 | ++ break; |
| 29 | ++#endif |
| 30 | + #ifdef ARCH_64 |
| 31 | + case '4': /* Shift 32 steps */ |
| 32 | + *ap++ = packed & BEAM_WIDE_MASK; |
| 33 | +diff --git a/erts/emulator/beam/emu/beam_emu.c b/erts/emulator/beam/emu/beam_emu.c |
| 34 | +index a473b89fbd3bc313a7d235b9925bbd7993217207..7b1b3e7b0051fb17b13bb05d66536445d9d36eb2 100644 |
| 35 | +--- a/erts/emulator/beam/emu/beam_emu.c |
| 36 | ++++ b/erts/emulator/beam/emu/beam_emu.c |
| 37 | +@@ -162,6 +162,7 @@ void** beam_ops; |
| 38 | + |
| 39 | + #define db(N) (N) |
| 40 | + #define fb(N) ((Sint)(Sint32)(N)) |
| 41 | ++#define fcb(N) ((Sint)((Sint32)((Uint32)(N) << 10) >> 10)) |
| 42 | + #define jb(N) ((Sint)(Sint32)(N)) |
| 43 | + #define tb(N) (N) |
| 44 | + #define xb(N) (*ADD_BYTE_OFFSET(reg, N)) |
| 45 | +diff --git a/erts/emulator/beam/emu/emu_load.c b/erts/emulator/beam/emu/emu_load.c |
| 46 | +index e5eb108ed0331273823cefd93074704d507eccd6..7f11c01db95b8b5a69afeadd86f498a72e8ecb52 100644 |
| 47 | +--- a/erts/emulator/beam/emu/emu_load.c |
| 48 | ++++ b/erts/emulator/beam/emu/emu_load.c |
| 49 | +@@ -535,6 +535,17 @@ int beam_load_finish_emit(LoaderState *stp) { |
| 50 | + codev[pos] = ((Uint)rel << BEAM_WIDE_SHIFT) | |
| 51 | + (codev[pos] & BEAM_WIDE_MASK); |
| 52 | + break; |
| 53 | ++#endif |
| 54 | ++#ifdef BEAM_COMPACT_LABEL_MASK |
| 55 | ++ case 3: |
| 56 | ++ ASSERT(rel >= -(1 << 21) && rel < (1 << 21)); |
| 57 | ++ codev[pos] = |
| 58 | ++ (codev[pos] & |
| 59 | ++ ~((BeamInstr)BEAM_COMPACT_LABEL_MASK << |
| 60 | ++ BEAM_COMPACT_LABEL_SHIFT)) | |
| 61 | ++ (((BeamInstr)rel & BEAM_COMPACT_LABEL_MASK) << |
| 62 | ++ BEAM_COMPACT_LABEL_SHIFT); |
| 63 | ++ break; |
| 64 | + #endif |
| 65 | + default: |
| 66 | + ASSERT(0); |
| 67 | +@@ -1182,6 +1193,34 @@ int beam_load_emit_op(LoaderState *stp, BeamOp *tmp_op) { |
| 68 | + packed_label->packed++; |
| 69 | + } |
| 70 | + break; |
| 71 | ++#ifdef BEAM_COMPACT_LABEL_MASK |
| 72 | ++ case '5': |
| 73 | ++ { |
| 74 | ++ Uint w = code[--ci]; |
| 75 | ++ LabelPatch* lp; |
| 76 | ++ int patch; |
| 77 | ++ |
| 78 | ++ if (w != 0) { |
| 79 | ++ lp = stp->labels[w].patches; |
| 80 | ++ for (patch = stp->labels[w].num_patches - 1; |
| 81 | ++ patch >= 0; |
| 82 | ++ patch--) { |
| 83 | ++ if (lp[patch].pos == ci) { |
| 84 | ++ lp[patch].packed = 3; |
| 85 | ++ packed_label = &lp[patch]; |
| 86 | ++ break; |
| 87 | ++ } |
| 88 | ++ } |
| 89 | ++ ASSERT(packed_label); |
| 90 | ++ } |
| 91 | ++ } |
| 92 | ++ break; |
| 93 | ++ case '6': |
| 94 | ++ ci--; |
| 95 | ++ ASSERT((code[ci] & 3) == 0); |
| 96 | ++ packed = code[ci] >> 2; |
| 97 | ++ break; |
| 98 | ++#endif |
| 99 | + #ifdef ARCH_64 |
| 100 | + case '4': /* Wide shift (32 bits) */ |
| 101 | + { |
| 102 | +diff --git a/erts/emulator/beam/emu/load.h b/erts/emulator/beam/emu/load.h |
| 103 | +index 5906abaf8e7a1f33ef695f670135b66427c34280..cde51aa1bb9afcf3ee4ee5bee2f6094a7809e276 100644 |
| 104 | +--- a/erts/emulator/beam/emu/load.h |
| 105 | ++++ b/erts/emulator/beam/emu/load.h |
| 106 | +@@ -31,7 +31,7 @@ |
| 107 | + typedef struct { |
| 108 | + Uint pos; /* Position of label reference to patch. */ |
| 109 | + Uint offset; /* Offset from patch location. */ |
| 110 | +- int packed; /* 0 (not packed), 1 (lsw), 2 (msw) */ |
| 111 | ++ int packed; /* 0 (not packed), 1/2 (wide), 3 (compact) */ |
| 112 | + } LabelPatch; |
| 113 | + |
| 114 | + /* |
| 115 | +diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops |
| 116 | +index a1c45a887820d949f2a1fd0811894024cb4f5c4c..240cd13619a31738f4d08ed116cd9d82134a4e8e 100755 |
| 117 | +--- a/erts/emulator/utils/beam_makeops |
| 118 | ++++ b/erts/emulator/utils/beam_makeops |
| 119 | +@@ -37,6 +37,8 @@ use constant PACK_CMD_TIGHTEST => '1'; |
| 120 | + use constant PACK_CMD_TIGHT => '2'; |
| 121 | + use constant PACK_CMD_LOOSE => '3'; |
| 122 | + use constant PACK_CMD_WIDE => '4'; |
| 123 | ++use constant PACK_CMD_COMPACT_LABEL => '5'; |
| 124 | ++use constant PACK_CMD_COMPACT_REG => '6'; |
| 125 | + |
| 126 | + $BEAM_FORMAT_NUMBER = undef; |
| 127 | + $GC_REGEXP = undef; |
| 128 | +@@ -379,6 +381,8 @@ while (@ARGV && $ARGV[0] =~ /^-(.*)/) { |
| 129 | + if ($wordsize == 32) { |
| 130 | + $defs{'ARCH_32'} = 1; |
| 131 | + $defs{'ARCH_64'} = 0; |
| 132 | ++ @basic_pack_options = (0,PACK_JUMP) if $defs{'WASM32'}; |
| 133 | ++ @extended_pack_options = @basic_pack_options; |
| 134 | + } elsif ($wordsize == 64) { |
| 135 | + $defs{'ARCH_32'} = 0; |
| 136 | + $defs{'ARCH_64'} = 1; |
| 137 | +@@ -1032,6 +1036,11 @@ sub emulator_output { |
| 138 | + print "#define BEAM_TIGHT_MASK 0xFFC\n"; |
| 139 | + print "#define BEAM_LOOSE_SHIFT 16\n"; |
| 140 | + print "#define BEAM_TIGHT_SHIFT 10\n"; |
| 141 | ++ if ($defs{'WASM32'}) { |
| 142 | ++ print "#define BEAM_TIGHTEST_MASK 0x3FF\n"; |
| 143 | ++ print "#define BEAM_COMPACT_LABEL_MASK 0x3FFFFF\n"; |
| 144 | ++ print "#define BEAM_COMPACT_LABEL_SHIFT 10\n"; |
| 145 | ++ } |
| 146 | + } elsif ($wordsize == 64) { |
| 147 | + print "#if !defined(ARCH_64)\n"; |
| 148 | + print qq[ #error "64-bit architecture assumed, but ARCH_64 not defined"\n]; |
| 149 | +@@ -2064,6 +2073,11 @@ sub do_pack_one { |
| 150 | + my @bits_needed; # Bits needed for each argument. |
| 151 | + my $pack_in_iw = $options & PACK_IN_INSTR_WORD; |
| 152 | + |
| 153 | ++ if ($defs{'WASM32'} && ($options & PACK_JUMP) && |
| 154 | ++ !(@args >= 2 && $args[0] eq 'f' && $args[1] =~ /^[xy]$/)) { |
| 155 | ++ return (0, []); |
| 156 | ++ } |
| 157 | ++ |
| 158 | + # |
| 159 | + # Define the minimum number of bits needed for the packable argument types. |
| 160 | + # |
| 161 | +@@ -2080,6 +2094,8 @@ sub do_pack_one { |
| 162 | + $bits_needed{'f'} = 32; |
| 163 | + $bits_needed{'j'} = 32; |
| 164 | + } |
| 165 | ++ } elsif ($defs{'WASM32'} && ($options & PACK_JUMP)) { |
| 166 | ++ $bits_needed{'f'} = 22; |
| 167 | + } |
| 168 | + |
| 169 | + # |
| 170 | +@@ -2270,9 +2286,12 @@ sub do_pack_one { |
| 171 | + my $args_per_word = $args_per_word[$word]; |
| 172 | + my $pack_word_size = ($pack_in_iw && $word == 0) ? 32 : $wordsize; |
| 173 | + |
| 174 | ++ my $compact_label = $defs{'WASM32'} && ($options & PACK_JUMP) && |
| 175 | ++ $args_per_word == 2 && |
| 176 | ++ $args[$arg_num] eq 'f' && $args[$arg_num+1] =~ /^[xy]$/; |
| 177 | + my($shref,$mref,$iref,$unpack_suffix) = |
| 178 | + get_pack_parameters($name, $args_per_word, $pack_word_size, |
| 179 | +- $need_wide_mask[$word]); |
| 180 | ++ $need_wide_mask[$word], $compact_label); |
| 181 | + my @shift = @$shref; |
| 182 | + my @mask = @$mref; |
| 183 | + my @instr = @$iref; |
| 184 | +@@ -2306,7 +2325,8 @@ sub do_pack_one { |
| 185 | + |
| 186 | + $down = "$instr[$ap]$down"; |
| 187 | + my $unpack = make_unpack($packed_var, $shift[$ap], $mask[$ap]); |
| 188 | +- my $macro = "$reg$unpack_suffix"; |
| 189 | ++ my $macro = $compact_label && $reg eq 'f' ? 'fcb' : |
| 190 | ++ "$reg$unpack_suffix"; |
| 191 | + $args[$arg_num] = "packed:$reg:$this_size:$macro($unpack)"; |
| 192 | + |
| 193 | + $ap++; |
| 194 | +@@ -2335,11 +2355,16 @@ sub do_pack_one { |
| 195 | + } |
| 196 | + |
| 197 | + sub get_pack_parameters { |
| 198 | +- my($name,$args_per_word,$pack_word_size,$wide_mask) = @_; |
| 199 | ++ my($name,$args_per_word,$pack_word_size,$wide_mask,$compact_label) = @_; |
| 200 | + my(@shift,@mask,@instr); |
| 201 | + my $unpack_suffix = 'b'; |
| 202 | + |
| 203 | +- if ($wide_mask and $args_per_word > 1) { |
| 204 | ++ if ($compact_label) { |
| 205 | ++ @shift = ('BEAM_COMPACT_LABEL_SHIFT', '0'); |
| 206 | ++ @mask = ($WHOLE_WORD, 'BEAM_TIGHTEST_MASK'); |
| 207 | ++ @instr = (PACK_CMD_COMPACT_LABEL, PACK_CMD_COMPACT_REG); |
| 208 | ++ $unpack_suffix = ''; |
| 209 | ++ } elsif ($wide_mask and $args_per_word > 1) { |
| 210 | + @shift = ('0', 'BEAM_WIDE_SHIFT'); |
| 211 | + @mask = ('BEAM_WIDE_MASK', $WHOLE_WORD); |
| 212 | + @instr = (PACK_CMD_WIDE) x 2; |
0 commit comments