aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/beam_load.c
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2015-06-16 06:39:25 +0200
committerBjörn Gustavsson <[email protected]>2015-07-03 14:34:49 +0200
commitf0923b143ecfdacfe4873fc1e96c8ec69726a4d9 (patch)
tree41f683ecd61f2aca87bb0944c622d3b9c48b732b /erts/emulator/beam/beam_load.c
parente1019cbba7a66788a068b6df1a1caf2d643ef65b (diff)
downloadotp-f0923b143ecfdacfe4873fc1e96c8ec69726a4d9.tar.gz
otp-f0923b143ecfdacfe4873fc1e96c8ec69726a4d9.tar.bz2
otp-f0923b143ecfdacfe4873fc1e96c8ec69726a4d9.zip
Allow X and Y registers to be overloaded with any literal
Consider the try_case_end instruction: try_case_end s The 's' operand type means that the operand can either be a literal of one of the types atom, integer, or empty list, or a register. That worked well before R12. In R12 additional types of literals where introduced. Because of way the overloading was done, an 's' operand cannot handle the new types of literals. Therefore, code such as the following is necessary in ops.tab to avoid giving an 's' operand a literal: try_case_end Literal=q => move Literal x | try_case_end x While this work, it is error-prone in that it is easy to forget to add that kind of rule. It would also be complicated in case we wanted to introduce a new kind of addition operator such as: i_plus jssd Since there are two 's' operands, two scratch registers and two 'move' instructions would be needed. Therefore, we'll need to find a smarter way to find tag register operands. We will overload the pid and port tags for X and Y register, respectively. That works because pids and port are immediate values (fit in one word), and there are no literals for pids and ports.
Diffstat (limited to 'erts/emulator/beam/beam_load.c')
-rw-r--r--erts/emulator/beam/beam_load.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 495e92d600..3cd80c4ec2 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -2167,13 +2167,13 @@ load_code(LoaderState* stp)
case 's': /* Any source (tagged constant or register) */
switch (tag) {
case TAG_r:
- code[ci++] = make_xreg(0);
+ code[ci++] = make_loader_x_reg(0);
break;
case TAG_x:
- code[ci++] = make_xreg(tmp_op->a[arg].val);
+ code[ci++] = make_loader_x_reg(tmp_op->a[arg].val);
break;
case TAG_y:
- code[ci++] = make_yreg(tmp_op->a[arg].val);
+ code[ci++] = make_loader_y_reg(tmp_op->a[arg].val);
break;
case TAG_i:
code[ci++] = (BeamInstr) make_small((Uint)tmp_op->a[arg].val);
@@ -2184,6 +2184,10 @@ load_code(LoaderState* stp)
case TAG_n:
code[ci++] = NIL;
break;
+ case TAG_q:
+ new_literal_patch(stp, ci);
+ code[ci++] = tmp_op->a[arg].val;
+ break;
default:
LoadError1(stp, "bad tag %d for general source",
tmp_op->a[arg].type);
@@ -2193,13 +2197,13 @@ load_code(LoaderState* stp)
case 'd': /* Destination (x(0), x(N), y(N) */
switch (tag) {
case TAG_r:
- code[ci++] = make_xreg(0);
+ code[ci++] = make_loader_x_reg(0);
break;
case TAG_x:
- code[ci++] = make_xreg(tmp_op->a[arg].val);
+ code[ci++] = make_loader_x_reg(tmp_op->a[arg].val);
break;
case TAG_y:
- code[ci++] = make_yreg(tmp_op->a[arg].val);
+ code[ci++] = make_loader_y_reg(tmp_op->a[arg].val);
break;
default:
LoadError1(stp, "bad tag %d for destination",
@@ -2359,13 +2363,11 @@ load_code(LoaderState* stp)
case TAG_r:
case TAG_x:
CodeNeed(1);
- code[ci++] = (tmp_op->a[arg].val << _TAG_IMMED1_SIZE) |
- (X_REG_DEF << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_HEADER;
+ code[ci++] = make_loader_x_reg(tmp_op->a[arg].val);
break;
case TAG_y:
CodeNeed(1);
- code[ci++] = (tmp_op->a[arg].val << _TAG_IMMED1_SIZE) |
- (Y_REG_DEF << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_HEADER;
+ code[ci++] = make_loader_y_reg(tmp_op->a[arg].val);
break;
case TAG_n:
CodeNeed(1);