# Arithmetic

***

### ADD <a href="#add" id="add"></a>

Original [EVM](https://www.evm.codes/#01?fork=shanghai) instruction.

#### LLVM IR <a href="#llvm-ir" id="llvm-ir"></a>

```llvm
%addition_result = add i256 %value1, %value2
```

[The LLVM IR generator code](https://github.com/matter-labs/era-compiler-llvm-context/blob/main/src/eravm/evm/arithmetic.rs#L15) is common for Yul and EVMLA representations.

[LLVM IR instruction documentation](https://releases.llvm.org/15.0.0/docs/LangRef.html#add-instruction)

#### EraVM Assembly <a href="#eravm-assembly" id="eravm-assembly"></a>

```llvm
add     r1, r2, r1
```

For more detail, see the [EraVM specification reference](https://matter-labs.github.io/eravm-spec/spec.html#AddDefinition)

### MUL <a href="#mul" id="mul"></a>

Original [EVM](https://www.evm.codes/#02?fork=shanghai) instruction.

#### [Differences from EVM](https://docs.zksync.io/zk-stack/components/compiler/specification/instructions/evm/arithmetic#differences-from-evm) <a href="#differences-from-evm" id="differences-from-evm"></a>

1. The carry is written to the 2nd output register

#### LLVM IR <a href="#llvm-ir-1" id="llvm-ir-1"></a>

```llvm
%multiplication_result = mul i256 %value1, %value2
```

EraVM can output the carry of the multiplication operation. In this case, the result is a tuple of two values: the multiplication result and the carry. The carry is written to the 2nd output register. The snippet below returns the carry value.

```llvm
%value1_extended = zext i256 %value1 to i512
%value2_extended = zext i256 %value2 to i512
%result_extended = mul nuw i512 %value1_extended, %value2_extended
%result_shifted = lshr i512 %result_extended, 256
%result = trunc i512 %result_shifted to i256
```

[The LLVM IR generator code](https://github.com/matter-labs/era-compiler-llvm-context/blob/main/src/eravm/evm/arithmetic.rs#L53) is common for Yul and EVMLA representations.

[LLVM IR instruction documentation](https://releases.llvm.org/15.0.0/docs/LangRef.html#mul-instruction)

#### EraVM Assembly <a href="#eravm-assembly-1" id="eravm-assembly-1"></a>

```llvm
mul     r1, r2, r1, r2
```

For more detail, see the [EraVM specification reference](https://matter-labs.github.io/eravm-spec/spec.html#MulDefinition)

### SUB <a href="#sub" id="sub"></a>

Original [EVM](https://www.evm.codes/#03?fork=shanghai) instruction.

#### LLVM IR <a href="#llvm-ir-2" id="llvm-ir-2"></a>

```llvm
%subtraction_result = sub i256 %value1, %value2
```

[The LLVM IR generator code](https://github.com/matter-labs/era-compiler-llvm-context/blob/main/src/eravm/evm/arithmetic.rs#L34) is common for Yul and EVMLA representations.

[LLVM IR instruction documentation](https://releases.llvm.org/15.0.0/docs/LangRef.html#sub-instruction)

#### EraVM Assembly <a href="#eravm-assembly-2" id="eravm-assembly-2"></a>

```llvm
sub     r1, r2, r1
```

For more detail, see the [EraVM specification reference](https://matter-labs.github.io/eravm-spec/spec.html#SubDefinition)

### DIV <a href="#div" id="div"></a>

Original [EVM](https://www.evm.codes/#04?fork=shanghai) instruction.

#### [Differences from EVM](https://docs.zksync.io/zk-stack/components/compiler/specification/instructions/evm/arithmetic#differences-from-evm-1) <a href="#differences-from-evm-1" id="differences-from-evm-1"></a>

1. The remainder is written to the 2nd output register

#### LLVM IR <a href="#llvm-ir-3" id="llvm-ir-3"></a>

```llvm
define i256 @__div(i256 %arg1, i256 %arg2) #0 {
entry:
  %is_divider_zero = icmp eq i256 %arg2, 0
  br i1 %is_divider_zero, label %return, label %division

division:
  %div_res = udiv i256 %arg1, %arg2
  br label %return

return:
  %res = phi i256 [ 0, %entry ], [ %div_res, %division ]
  ret i256 %res
}
```

[The LLVM IR generator code](https://github.com/matter-labs/era-compiler-llvm-context/blob/main/src/eravm/evm/arithmetic.rs#L73) is common for Yul and EVMLA representations.

[LLVM IR instruction documentation](https://releases.llvm.org/15.0.0/docs/LangRef.html#udiv-instruction)

For more detail, see the [EraVM specification reference](https://matter-labs.github.io/eravm-spec/spec.html#DivDefinition)

### SDIV <a href="#sdiv" id="sdiv"></a>

Original [EVM](https://www.evm.codes/#05?fork=shanghai) instruction.

#### LLVM IR <a href="#llvm-ir-4" id="llvm-ir-4"></a>

```llvm
define i256 @__sdiv(i256 %arg1, i256 %arg2) #0 {
entry:
  %is_divider_zero = icmp eq i256 %arg2, 0
  br i1 %is_divider_zero, label %return, label %division_overflow

division_overflow:
  %is_divided_int_min = icmp eq i256 %arg1, -57896044618658097711785492504343953926634992332820282019728792003956564819968
  %is_minus_one = icmp eq i256 %arg2, -1
  %is_overflow = and i1 %is_divided_int_min, %is_minus_one
  br i1 %is_overflow, label %return, label %division

division:
  %div_res = sdiv i256 %arg1, %arg2
  br label %return

return:
  %res = phi i256 [ 0, %entry ], [ %arg1, %division_overflow ], [ %div_res, %division ]
  ret i256 %res
}
```

[The LLVM IR generator code](https://github.com/matter-labs/era-compiler-llvm-context/blob/main/src/eravm/evm/arithmetic.rs#L162) is common for Yul and EVMLA representations.

[LLVM IR instruction documentation](https://releases.llvm.org/15.0.0/docs/LangRef.html#sdiv-instruction)

EraVM does not have a similar instruction.

### MOD <a href="#mod" id="mod"></a>

Original [EVM](https://www.evm.codes/#06?fork=shanghai) instruction.

#### [Differences from EVM](https://docs.zksync.io/zk-stack/components/compiler/specification/instructions/evm/arithmetic#differences-from-evm-2) <a href="#differences-from-evm-2" id="differences-from-evm-2"></a>

1. The remainder is written to the 2nd output register

#### LLVM IR <a href="#llvm-ir-5" id="llvm-ir-5"></a>

```llvm
define i256 @__mod(i256 %arg1, i256 %arg2) #0 {
entry:
  %is_divider_zero = icmp eq i256 %arg2, 0
  br i1 %is_divider_zero, label %return, label %remainder

remainder:
  %rem_res = urem i256 %arg1, %arg2
  br label %return

return:
  %res = phi i256 [ 0, %entry ], [ %rem_res, %remainder ]
  ret i256 %res
}
```

[The LLVM IR generator code](https://github.com/matter-labs/era-compiler-llvm-context/blob/main/src/eravm/evm/arithmetic.rs#L117) is common for Yul and EVMLA representations.

[LLVM IR instruction documentation](https://releases.llvm.org/15.0.0/docs/LangRef.html#urem-instruction)

For more detail, see the [EraVM specification reference](https://matter-labs.github.io/eravm-spec/spec.html#DivDefinition)

### SMOD <a href="#smod" id="smod"></a>

Original [EVM](https://www.evm.codes/#07?fork=shanghai) instruction.

#### LLVM IR <a href="#llvm-ir-6" id="llvm-ir-6"></a>

```llvm
define i256 @__smod(i256 %arg1, i256 %arg2) #0 {
entry:
  %is_divider_zero = icmp eq i256 %arg2, 0
  br i1 %is_divider_zero, label %return, label %division_overflow

division_overflow:
  %is_divided_int_min = icmp eq i256 %arg1, -57896044618658097711785492504343953926634992332820282019728792003956564819968
  %is_minus_one = icmp eq i256 %arg2, -1
  %is_overflow = and i1 %is_divided_int_min, %is_minus_one
  br i1 %is_overflow, label %return, label %remainder

remainder:
  %rem_res = srem i256 %arg1, %arg2
  br label %return

return:
  %res = phi i256 [ 0, %entry ], [ 0, %division_overflow ], [ %rem_res, %remainder ]
  ret i256 %res
}
```

[The LLVM IR generator code](https://github.com/matter-labs/era-compiler-llvm-context/blob/main/src/eravm/evm/arithmetic.rs#L236) is common for Yul and EVMLA representations.

[LLVM IR instruction documentation](https://releases.llvm.org/15.0.0/docs/LangRef.html#srem-instruction)

EraVM does not have a similar instruction.

### ADDMOD <a href="#addmod" id="addmod"></a>

Original [EVM](https://www.evm.codes/#08?fork=shanghai) instruction.

#### LLVM IR <a href="#llvm-ir-7" id="llvm-ir-7"></a>

```llvm
define i256 @__addmod(i256 %arg1, i256 %arg2, i256 %modulo) #0 {
entry:
  %is_zero = icmp eq i256 %modulo, 0
  br i1 %is_zero, label %return, label %addmod

addmod:
  %arg1m = urem i256 %arg1, %modulo
  %arg2m = urem i256 %arg2, %modulo
  %res = call {i256, i1} @llvm.uadd.with.overflow.i256(i256 %arg1m, i256 %arg2m)
  %sum = extractvalue {i256, i1} %res, 0
  %obit = extractvalue {i256, i1} %res, 1
  %sum.mod = urem i256 %sum, %modulo
  br i1 %obit, label %overflow, label %return

overflow:
  %mod.inv = xor i256 %modulo, -1
  %sum1 = add i256 %sum, %mod.inv
  %sum.ovf = add i256 %sum1, 1
  br label %return

return:
  %value = phi i256 [0, %entry], [%sum.mod, %addmod], [%sum.ovf, %overflow]
  ret i256 %value
}
```

[The LLVM IR generator code](https://github.com/matter-labs/era-compiler-llvm-context/blob/main/src/eravm/evm/math.rs#L16) is common for Yul and EVMLA representations.

EraVM does not have a similar instruction.

### MULMOD <a href="#mulmod" id="mulmod"></a>

Original [EVM](https://www.evm.codes/#09?fork=shanghai) instruction.

#### LLVM IR <a href="#llvm-ir-8" id="llvm-ir-8"></a>

```llvm
define i256 @__mulmod(i256 %arg1, i256 %arg2, i256 %modulo) #0 {
entry:
  %cccond = icmp eq i256 %modulo, 0
  br i1 %cccond, label %ccret, label %entrycont

ccret:
  ret i256 0

entrycont:
  %arg1m = urem i256 %arg1, %modulo
  %arg2m = urem i256 %arg2, %modulo
  %less_then_2_128 = icmp ult i256 %modulo, 340282366920938463463374607431768211456
  br i1 %less_then_2_128, label %fast, label %slow

fast:
  %prod = mul i256 %arg1m, %arg2m
  %prodm = urem i256 %prod, %modulo
  ret i256 %prodm

slow:
  %arg1e = zext i256 %arg1m to i512
  %arg2e = zext i256 %arg2m to i512
  %prode = mul i512 %arg1e, %arg2e
  %prodl = trunc i512 %prode to i256
  %prodeh = lshr i512 %prode, 256
  %prodh = trunc i512 %prodeh to i256
  %res = call i256 @__ulongrem(i256 %prodl, i256 %prodh, i256 %modulo)
  ret i256 %res
}
```

[The LLVM IR generator code](https://github.com/matter-labs/era-compiler-llvm-context/blob/main/src/eravm/evm/math.rs#L43) is common for Yul and EVMLA representations.

EraVM does not have a similar instruction.

### EXP <a href="#exp" id="exp"></a>

Original [EVM](https://www.evm.codes/#0a?fork=shanghai) instruction.

#### LLVM IR <a href="#llvm-ir-9" id="llvm-ir-9"></a>

```llvm
define i256 @__exp(i256 %value, i256 %exp) "noinline-oz" #0 {
entry:
  %exp_is_non_zero = icmp eq i256 %exp, 0
  br i1 %exp_is_non_zero, label %return, label %exponent_loop_body

return:
  %exp_res = phi i256 [ 1, %entry ], [ %exp_res.1, %exponent_loop_body ]
  ret i256 %exp_res

exponent_loop_body:
  %exp_res.2 = phi i256 [ %exp_res.1, %exponent_loop_body ], [ 1, %entry ]
  %exp_val = phi i256 [ %exp_val_halved, %exponent_loop_body ], [ %exp, %entry ]
  %val_squared.1 = phi i256 [ %val_squared, %exponent_loop_body ], [ %value, %entry ]
  %odd_test = and i256 %exp_val, 1
  %is_exp_odd = icmp eq i256 %odd_test, 0
  %exp_res.1.interm = select i1 %is_exp_odd, i256 1, i256 %val_squared.1
  %exp_res.1 = mul i256 %exp_res.1.interm, %exp_res.2
  %val_squared = mul i256 %val_squared.1, %val_squared.1
  %exp_val_halved = lshr i256 %exp_val, 1
  %exp_val_is_less_2 = icmp ult i256 %exp_val, 2
  br i1 %exp_val_is_less_2, label %return, label %exponent_loop_body
}
```

[The LLVM IR generator code](https://github.com/matter-labs/era-compiler-llvm-context/blob/main/src/eravm/evm/math.rs#L70) is common for Yul and EVMLA representations.

EraVM does not have a similar instruction.

### SIGNEXTEND <a href="#signextend" id="signextend"></a>

Original [EVM](https://www.evm.codes/#0b?fork=shanghai) instruction.

#### [LLVM IR](https://docs.zksync.io/zk-stack/components/compiler/specification/instructions/evm/arithmetic#llvm-ir-10) <a href="#llvm-ir-10" id="llvm-ir-10"></a>

```llvm
define i256 @__signextend(i256 %numbyte, i256 %value) #0 {
entry:
  %is_overflow = icmp uge i256 %numbyte, 31
  br i1 %is_overflow, label %return, label %signextend

signextend:
  %numbit_byte = mul nuw nsw i256 %numbyte, 8
  %numbit = add nsw nuw i256 %numbit_byte, 7
  %numbit_inv = sub i256 256, %numbit
  %signmask = shl i256 1, %numbit
  %valmask = lshr i256 -1, %numbit_inv
  %ext1 = shl i256 -1, %numbit
  %signv = and i256 %signmask, %value
  %sign = icmp ne i256 %signv, 0
  %valclean = and i256 %value, %valmask
  %sext = select i1 %sign, i256 %ext1, i256 0
  %result = or i256 %sext, %valclean
  br label %return

return:
  %signext_res = phi i256 [%value, %entry], [%result, %signextend]
  ret i256 %signext_res
}
```

[The LLVM IR generator code](https://github.com/matter-labs/era-compiler-llvm-context/blob/main/src/eravm/evm/math.rs#L93) is common for Yul and EVMLA representations.

EraVM does not have a similar instruction.

<br>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://validium.gitbook.io/docs/components/compiler/specification/instructions/evm/arithmetic.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
