summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2021-07-21 07:52:39 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2021-07-21 07:52:39 +0900
commit275fe8c94b7f19260c58104e6cf5b7fe1f17cece (patch)
treea089d46b8aab2a828186b2f5a5d27c3f5b963afe
parent5066e2370d613355c813fd48be5ab0f76b7d341c (diff)
downloadmruby-275fe8c94b7f19260c58104e6cf5b7fe1f17cece.tar.gz
mruby-275fe8c94b7f19260c58104e6cf5b7fe1f17cece.zip
codegen.c: a new function `get_int_operand`.
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c61
1 files changed, 39 insertions, 22 deletions
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index 3c9d12f9f..80673d918 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -562,6 +562,33 @@ gen_return(codegen_scope *s, uint8_t op, uint16_t src)
}
}
+static mrb_bool
+get_int_operand(struct mrb_insn_data *data, int32_t *n)
+{
+ switch (data->insn) {
+ case OP_LOADI__1:
+ *n = -1;
+ return TRUE;
+
+ case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3:
+ case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7:
+ *n = data->insn - OP_LOADI_0;
+ return TRUE;
+
+ case OP_LOADI:
+ case OP_LOADI16:
+ *n = data->b;
+ return TRUE;
+
+ case OP_LOADI32:
+ *n = (int32_t)((uint32_t)data->b<<16)+data->c;
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
static void
gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst)
{
@@ -572,31 +599,21 @@ gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst)
}
else {
struct mrb_insn_data data = mrb_last_insn(s);
+ int32_t n;
- switch (data.insn) {
- case OP_LOADI__1:
- if (op == OP_ADD) op = OP_SUB;
- else op = OP_ADD;
- data.b = 1;
- goto replace;
- case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3:
- case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7:
- data.b = data.insn - OP_LOADI_0;
- /* fall through */
- case OP_LOADI:
- case OP_LOADI16:
- replace:
- s->pc = s->lastpc;
- if (op == OP_ADD) {
- genop_2(s, OP_ADDI, dst, data.b);
- }
- else {
- genop_2(s, OP_SUBI, dst, data.b);
- }
- break;
- default:
+ if (!get_int_operand(&data, &n)) {
+ /* not integer immediate */
goto normal;
}
+ /* OP_ADDI/OP_SUBI takes upto 16bits */
+ if (n > INT16_MAX) goto normal;
+ s->pc = s->lastpc;
+ if (op == OP_ADD) {
+ genop_2(s, OP_ADDI, dst, (uint16_t)n);
+ }
+ else {
+ genop_2(s, OP_SUBI, dst, (uint16_t)n);
+ }
}
}