Sexpr* a_plus(Sexpr* b, Sexpr* rest, Sexpr* env) {
-       if(ARITH_PLUS_ARGS != u64_get_num_args(b)) {
+       if(ARITH_ADD_ARGS != u64_get_num_args(b)) {
                return cons(b, rest);
        }
        Sexpr* args = b->value.b.args;
        return cons(from_uint(m + n), rest);
 }
 
+Sexpr* a_minus(Sexpr* b, Sexpr* rest, Sexpr* env) {
+       if(ARITH_SUB_ARGS != u64_get_num_args(b)) {
+               return cons(b, rest);
+       }
+       Sexpr* args = b->value.b.args;
+       Sexpr* i = eval(clone(car(args)), env);
+       Sexpr* j = eval(clone(car(cdr(args))), env);
+       uint64_t m = unquote(i)->value.u;
+       uint64_t n = unquote(j)->value.u;
+       sexpr_free(b);
+       sexpr_free(i);
+       sexpr_free(j);
+       return cons(from_uint(n - m), rest);
+}
+
+Sexpr* a_mul(Sexpr* b, Sexpr* rest, Sexpr* env) {
+       if(ARITH_MUL_ARGS != u64_get_num_args(b)) {
+               return cons(b, rest);
+       }
+       Sexpr* args = b->value.b.args;
+       Sexpr* i = eval(clone(car(args)), env);
+       Sexpr* j = eval(clone(car(cdr(args))), env);
+       uint64_t m = unquote(i)->value.u;
+       uint64_t n = unquote(j)->value.u;
+       sexpr_free(b);
+       sexpr_free(i);
+       sexpr_free(j);
+       return cons(from_uint(m * n), rest);
+}
+
+Sexpr* a_div(Sexpr* b, Sexpr* rest, Sexpr* env) {
+       if(ARITH_DIV_ARGS != u64_get_num_args(b)) {
+               return cons(b, rest);
+       }
+       Sexpr* args = b->value.b.args;
+       Sexpr* i = eval(clone(car(args)), env);
+       Sexpr* j = eval(clone(car(cdr(args))), env);
+       uint64_t m = unquote(i)->value.u;
+       uint64_t n = unquote(j)->value.u;
+       sexpr_free(b);
+       sexpr_free(i);
+       sexpr_free(j);
+       return cons(from_uint(n / m), rest);
+}
+
+Sexpr* a_mod(Sexpr* b, Sexpr* rest, Sexpr* env) {
+       if(ARITH_MOD_ARGS != u64_get_num_args(b)) {
+               return cons(b, rest);
+       }
+       Sexpr* args = b->value.b.args;
+       Sexpr* i = eval(clone(car(args)), env);
+       Sexpr* j = eval(clone(car(cdr(args))), env);
+       uint64_t m = unquote(i)->value.u;
+       uint64_t n = unquote(j)->value.u;
+       sexpr_free(b);
+       sexpr_free(i);
+       sexpr_free(j);
+       return cons(from_uint(n % m), rest);
+}
+
+
 Sexpr* x_arith_dispatch(Sexpr* b, Sexpr* rest, Sexpr* env) {
        uint64_t code = b->value.b.opcode & 0xff;
 
        switch(code) {
-       case ARITH_PLUS:
+       case ARITH_ADD:
                return a_plus(b, rest, env);
+       case ARITH_SUB:
+               return a_minus(b, rest, env);
+       case ARITH_MUL:
+               return a_mul(b, rest, env);
+       case ARITH_DIV:
+               return a_div(b, rest, env);
+       case ARITH_MOD:
+               return a_mod(b, rest, env);
        default:
                return from_nil();
        }
 
 Sexpr* load_arith_env(Sexpr* env) {
        Sexpr* k;
+       Sexpr* v;
 
        k = from_sym("+");
-       Sexpr* a_plus = from_opcode((ARITH_PREFIX << 8) | ARITH_PLUS);
-       append_to_dict(env, k, a_plus);
-       sexpr_free(a_plus);
+       v = from_opcode((ARITH_PREFIX << 8) | ARITH_ADD);
+       append_to_dict(env, k, v);
+       sexpr_free(v);
+       sexpr_free(k);
+
+       k = from_sym("-");
+       v = from_opcode((ARITH_PREFIX << 8) | ARITH_SUB);
+       append_to_dict(env, k, v);
+       sexpr_free(v);
+       sexpr_free(k);
+
+               k = from_sym("*");
+       v = from_opcode((ARITH_PREFIX << 8) | ARITH_MUL);
+       append_to_dict(env, k, v);
+       sexpr_free(v);
+       sexpr_free(k);
+
+               k = from_sym("/");
+       v = from_opcode((ARITH_PREFIX << 8) | ARITH_DIV);
+       append_to_dict(env, k, v);
+       sexpr_free(v);
+       sexpr_free(k);
+
+               k = from_sym("%");
+       v = from_opcode((ARITH_PREFIX << 8) | ARITH_MOD);
+       append_to_dict(env, k, v);
+       sexpr_free(v);
        sexpr_free(k);
        return env;
 }