This commit implements addc and subb operations using Wasm instructions. A
carry flag is introduced as the 16th variable in the module following other
15 variables that represent TCG variables.

Signed-off-by: Kohei Tokunaga <ktokunaga.m...@gmail.com>
---
 tcg/wasm32/tcg-target.c.inc | 151 ++++++++++++++++++++++++++++++++++++
 1 file changed, 151 insertions(+)

diff --git a/tcg/wasm32/tcg-target.c.inc b/tcg/wasm32/tcg-target.c.inc
index 75e47f8c8c..167850ea7c 100644
--- a/tcg/wasm32/tcg-target.c.inc
+++ b/tcg/wasm32/tcg-target.c.inc
@@ -118,6 +118,11 @@ static const uint8_t 
tcg_target_reg_index[TCG_TARGET_NB_REGS] = {
     15, /* TCG_REG_R15 */
 };
 
+/*
+ * Global variable to store the carry flag
+ */
+#define CARRY_IDX 16
+
 /* Temporary local variables */
 #define TMP32_LOCAL_0_IDX 1
 #define TMP32_LOCAL_1_IDX 2
@@ -324,10 +329,23 @@ static void tcg_wasm_out_op_i32_eqz(TCGContext *s)
 {
     tcg_wasm_out8(s, 0x45);
 }
+static void tcg_wasm_out_op_i64_lt_u(TCGContext *s)
+{
+    tcg_wasm_out8(s, 0x54);
+}
+static void tcg_wasm_out_op_i64_le_u(TCGContext *s)
+{
+    tcg_wasm_out8(s, 0x58);
+}
 static void tcg_wasm_out_op_i64_eqz(TCGContext *s)
 {
     tcg_wasm_out8(s, 0x50);
 }
+static void tcg_wasm_out_op_if_noret(TCGContext *s)
+{
+    tcg_wasm_out8(s, 0x04);
+    tcg_wasm_out8(s, 0x40);
+}
 
 static void tcg_wasm_out_op_if_ret_i64(TCGContext *s)
 {
@@ -1789,10 +1807,28 @@ static TCGConstraintSetIndex cset_addsubcarry(TCGType 
type, unsigned flags)
     return type == TCG_TYPE_REG ? C_O1_I2(r, r, r) : C_NotImplemented;
 }
 
+static void tcg_wasm_out_addco(TCGContext *s, TCGReg a0, TCGReg a1, TCGReg a2)
+{
+    tcg_wasm_out_op_global_get_r(s, a1);
+    tcg_wasm_out_op_global_get_r(s, a2);
+    tcg_wasm_out_op_i64_add(s);
+    tcg_wasm_out_op_global_set_r(s, a0);
+    tcg_wasm_out_op_global_get_r(s, a0);
+    if (a0 == a1) {
+        tcg_wasm_out_op_global_get_r(s, a2);
+    } else {
+        tcg_wasm_out_op_global_get_r(s, a1);
+    }
+    tcg_wasm_out_op_i64_lt_u(s);
+    tcg_wasm_out_op_i64_extend_i32_s(s);
+    tcg_wasm_out_op_global_set(s, CARRY_IDX);
+}
+
 static void tgen_addco(TCGContext *s, TCGType type,
                        TCGReg a0, TCGReg a1, TCGReg a2)
 {
     tcg_out_op_rrr(s, INDEX_op_addco, a0, a1, a2);
+    tcg_wasm_out_addco(s, a0, a1, a2);
 }
 
 static const TCGOutOpBinary outop_addco = {
@@ -1801,10 +1837,21 @@ static const TCGOutOpBinary outop_addco = {
     .out_rrr = tgen_addco,
 };
 
+static void tcg_wasm_out_addci(TCGContext *s, TCGReg a0, TCGReg a1, TCGReg a2)
+{
+    tcg_wasm_out_op_global_get_r(s, a1);
+    tcg_wasm_out_op_global_get_r(s, a2);
+    tcg_wasm_out_op_i64_add(s);
+    tcg_wasm_out_op_global_get(s, CARRY_IDX);
+    tcg_wasm_out_op_i64_add(s);
+    tcg_wasm_out_op_global_set_r(s, a0);
+}
+
 static void tgen_addci(TCGContext *s, TCGType type,
                        TCGReg a0, TCGReg a1, TCGReg a2)
 {
     tcg_out_op_rrr(s, INDEX_op_addci, a0, a1, a2);
+    tcg_wasm_out_addci(s, a0, a1, a2);
 }
 
 static const TCGOutOpAddSubCarry outop_addci = {
@@ -1813,10 +1860,51 @@ static const TCGOutOpAddSubCarry outop_addci = {
     .out_rrr = tgen_addci,
 };
 
+static void tcg_wasm_out_addcio(TCGContext *s, TCGReg a0, TCGReg a1, TCGReg a2)
+{
+    tcg_wasm_out_op_global_get(s, CARRY_IDX);
+    tcg_wasm_out_op_if_noret(s);
+
+    tcg_wasm_out_op_global_get_r(s, a1);
+    tcg_wasm_out_op_global_get_r(s, a2);
+    tcg_wasm_out_op_i64_add(s);
+    tcg_wasm_out_op_i64_const(s, 1);
+    tcg_wasm_out_op_i64_add(s);
+    tcg_wasm_out_op_global_set_r(s, a0);
+    tcg_wasm_out_op_global_get_r(s, a0);
+    if (a0 == a1) {
+        tcg_wasm_out_op_global_get_r(s, a2);
+    } else {
+        tcg_wasm_out_op_global_get_r(s, a1);
+    }
+    tcg_wasm_out_op_i64_le_u(s);
+    tcg_wasm_out_op_i64_extend_i32_s(s);
+    tcg_wasm_out_op_global_set(s, CARRY_IDX);
+
+    tcg_wasm_out_op_else(s);
+
+    tcg_wasm_out_op_global_get_r(s, a1);
+    tcg_wasm_out_op_global_get_r(s, a2);
+    tcg_wasm_out_op_i64_add(s);
+    tcg_wasm_out_op_global_set_r(s, a0);
+    tcg_wasm_out_op_global_get_r(s, a0);
+    if (a0 == a1) {
+        tcg_wasm_out_op_global_get_r(s, a2);
+    } else {
+        tcg_wasm_out_op_global_get_r(s, a1);
+    }
+    tcg_wasm_out_op_i64_lt_u(s);
+    tcg_wasm_out_op_i64_extend_i32_s(s);
+    tcg_wasm_out_op_global_set(s, CARRY_IDX);
+
+    tcg_wasm_out_op_end(s);
+}
+
 static void tgen_addcio(TCGContext *s, TCGType type,
                         TCGReg a0, TCGReg a1, TCGReg a2)
 {
     tcg_out_op_rrr(s, INDEX_op_addcio, a0, a1, a2);
+    tcg_wasm_out_addcio(s, a0, a1, a2);
 }
 
 static const TCGOutOpBinary outop_addcio = {
@@ -1828,6 +1916,8 @@ static const TCGOutOpBinary outop_addcio = {
 static void tcg_out_set_carry(TCGContext *s)
 {
     tcg_out_op_v(s, INDEX_op_tci_setcarry);
+    tcg_wasm_out_op_i64_const(s, 1);
+    tcg_wasm_out_op_global_set(s, CARRY_IDX);
 }
 
 static void tgen_and(TCGContext *s, TCGType type,
@@ -2182,10 +2272,25 @@ static const TCGOutOpSubtract outop_sub = {
     .out_rrr = tgen_sub,
 };
 
+static void tcg_wasm_out_subbo(TCGContext *s, TCGReg a0, TCGReg a1, TCGReg a2)
+{
+    tcg_wasm_out_op_global_get_r(s, a1);
+    tcg_wasm_out_op_global_get_r(s, a2);
+    tcg_wasm_out_op_i64_lt_u(s);
+    tcg_wasm_out_op_i64_extend_i32_s(s);
+    tcg_wasm_out_op_global_set(s, CARRY_IDX);
+
+    tcg_wasm_out_op_global_get_r(s, a1);
+    tcg_wasm_out_op_global_get_r(s, a2);
+    tcg_wasm_out_op_i64_sub(s);
+    tcg_wasm_out_op_global_set_r(s, a0);
+}
+
 static void tgen_subbo(TCGContext *s, TCGType type,
                        TCGReg a0, TCGReg a1, TCGReg a2)
 {
     tcg_out_op_rrr(s, INDEX_op_subbo, a0, a1, a2);
+    tcg_wasm_out_subbo(s, a0, a1, a2);
 }
 
 static const TCGOutOpAddSubCarry outop_subbo = {
@@ -2194,10 +2299,21 @@ static const TCGOutOpAddSubCarry outop_subbo = {
     .out_rrr = tgen_subbo,
 };
 
+static void tcg_wasm_out_subbi(TCGContext *s, TCGReg a0, TCGReg a1, TCGReg a2)
+{
+    tcg_wasm_out_op_global_get_r(s, a1);
+    tcg_wasm_out_op_global_get_r(s, a2);
+    tcg_wasm_out_op_i64_sub(s);
+    tcg_wasm_out_op_global_get(s, CARRY_IDX);
+    tcg_wasm_out_op_i64_sub(s);
+    tcg_wasm_out_op_global_set_r(s, a0);
+}
+
 static void tgen_subbi(TCGContext *s, TCGType type,
                        TCGReg a0, TCGReg a1, TCGReg a2)
 {
     tcg_out_op_rrr(s, INDEX_op_subbi, a0, a1, a2);
+    tcg_wasm_out_subbi(s, a0, a1, a2);
 }
 
 static const TCGOutOpAddSubCarry outop_subbi = {
@@ -2206,10 +2322,43 @@ static const TCGOutOpAddSubCarry outop_subbi = {
     .out_rrr = tgen_subbi,
 };
 
+static void tcg_wasm_out_subbio(TCGContext *s, TCGReg a0, TCGReg a1, TCGReg a2)
+{
+    tcg_wasm_out_op_global_get(s, CARRY_IDX);
+    tcg_wasm_out_op_if_noret(s);
+
+    tcg_wasm_out_op_global_get_r(s, a1);
+    tcg_wasm_out_op_global_get_r(s, a2);
+    tcg_wasm_out_op_i64_le_u(s);
+    tcg_wasm_out_op_i64_extend_i32_s(s);
+    tcg_wasm_out_op_global_set(s, CARRY_IDX);
+    tcg_wasm_out_op_global_get_r(s, a1);
+    tcg_wasm_out_op_global_get_r(s, a2);
+    tcg_wasm_out_op_i64_sub(s);
+    tcg_wasm_out_op_i64_const(s, 1);
+    tcg_wasm_out_op_i64_sub(s);
+    tcg_wasm_out_op_global_set_r(s, a0);
+
+    tcg_wasm_out_op_else(s);
+
+    tcg_wasm_out_op_global_get_r(s, a1);
+    tcg_wasm_out_op_global_get_r(s, a2);
+    tcg_wasm_out_op_i64_lt_u(s);
+    tcg_wasm_out_op_i64_extend_i32_s(s);
+    tcg_wasm_out_op_global_set(s, CARRY_IDX);
+    tcg_wasm_out_op_global_get_r(s, a1);
+    tcg_wasm_out_op_global_get_r(s, a2);
+    tcg_wasm_out_op_i64_sub(s);
+    tcg_wasm_out_op_global_set_r(s, a0);
+
+    tcg_wasm_out_op_end(s);
+}
+
 static void tgen_subbio(TCGContext *s, TCGType type,
                         TCGReg a0, TCGReg a1, TCGReg a2)
 {
     tcg_out_op_rrr(s, INDEX_op_subbio, a0, a1, a2);
+    tcg_wasm_out_subbio(s, a0, a1, a2);
 }
 
 static const TCGOutOpAddSubCarry outop_subbio = {
@@ -2221,6 +2370,8 @@ static const TCGOutOpAddSubCarry outop_subbio = {
 static void tcg_out_set_borrow(TCGContext *s)
 {
     tcg_out_op_v(s, INDEX_op_tci_setcarry);  /* borrow == carry */
+    tcg_wasm_out_op_i64_const(s, 1);
+    tcg_wasm_out_op_global_set(s, CARRY_IDX);
 }
 
 static void tgen_xor(TCGContext *s, TCGType type,
-- 
2.43.0


Reply via email to