diff --git a/include/m6809/m6809_math.mfk b/include/m6809/m6809_math.mfk
new file mode 100644
index 00000000..5e6c4671
--- /dev/null
+++ b/include/m6809/m6809_math.mfk
@@ -0,0 +1,30 @@
+
+#if not(ARCH_6809)
+#warn m6809_math module should be used only on 6809-like targets
+#endif
+
+noinline asm word __mul_u16u16u16(word register(x) x, word register(d) d) {
+    pshs d,x
+    exg d,x
+    lda ,s
+    mul
+    tfr d,x
+    ldd 1,s
+    mul
+    abx
+    tfr x,d
+    tfr b,a
+    ldb #0
+    tfr d,x
+    puls d
+    lda 1,s
+    mul
+    leax d,x
+    tfr x,d
+    leas 2,s
+    rts
+}
+
+noinline asm word __divmod_u16u16u16u16(word register(x) x, word register(d) d) {
+
+}
\ No newline at end of file
diff --git a/include/m6809/stdlib_6809.mfk b/include/m6809/stdlib_6809.mfk
index a55a3e3c..52cf6102 100644
--- a/include/m6809/stdlib_6809.mfk
+++ b/include/m6809/stdlib_6809.mfk
@@ -4,6 +4,8 @@
 #warn stdlib_6809 module should be only used on 6809-compatible targets
 #endif
 
+import m6809/m6809_math
+
 word nmi_routine_addr   @$FFFC
 word reset_routine_addr @$FFFE
 word irq_routine_addr   @$FFF8
diff --git a/src/main/scala/millfork/compiler/m6809/M6809ExpressionCompiler.scala b/src/main/scala/millfork/compiler/m6809/M6809ExpressionCompiler.scala
index fedfc8dc..cdc2f573 100644
--- a/src/main/scala/millfork/compiler/m6809/M6809ExpressionCompiler.scala
+++ b/src/main/scala/millfork/compiler/m6809/M6809ExpressionCompiler.scala
@@ -3,7 +3,7 @@ package millfork.compiler.m6809
 import millfork.CompilationFlag
 import millfork.assembly.m6809.{DAccumulatorIndexed, Immediate, Indexed, InherentB, MLine, MLine0, MOpcode, RegisterSet, TwoRegisters}
 import millfork.compiler.{AbstractExpressionCompiler, BranchIfFalse, BranchIfTrue, BranchSpec, ComparisonType, CompilationContext, NoBranching}
-import millfork.node.{DerefExpression, Expression, FunctionCallExpression, GeneratedConstantExpression, IndexedExpression, LhsExpression, LiteralExpression, M6809Register, SumExpression, VariableExpression}
+import millfork.node.{DerefExpression, Expression, FunctionCallExpression, GeneratedConstantExpression, IndexedExpression, LhsExpression, LiteralExpression, M6809Register, SeparateBytesExpression, SumExpression, VariableExpression}
 import millfork.assembly.m6809.MOpcode._
 import millfork.env.{AssemblyOrMacroParamSignature, BuiltInBooleanType, Constant, ConstantBooleanType, ConstantPointy, ExternFunction, FatBooleanType, FlagBooleanType, FunctionInMemory, FunctionPointerType, Label, M6809RegisterVariable, MacroFunction, MathOperator, MemoryAddressConstant, MemoryVariable, NonFatalCompilationException, NormalFunction, NormalParamSignature, NumericConstant, StackVariablePointy, ThingInMemory, Type, Variable, VariableInMemory, VariablePointy}
 
@@ -139,6 +139,12 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
           case 1 => M6809Buitins.compileByteSum(ctx, e, fromScratch = true) ++ targetifyB(ctx, target, isSigned = false)
           case 2 => M6809Buitins.compileWordSum(ctx, e, fromScratch = true) ++ targetifyD(ctx, target)
         }
+      case SeparateBytesExpression(hi, lo) =>
+        val h = compile(ctx, hi, MExpressionTarget.A)
+        val l = compile(ctx, lo, MExpressionTarget.B)
+        (if (l.exists(_.changesRegister(M6809Register.A))) {
+          if (h.exists(_.changesRegister(M6809Register.B))) h ++ stashAIfNeeded(ctx, l) else l ++ h
+        } else h ++ l) ++ targetifyD(ctx, target)
       case fce@FunctionCallExpression(functionName, params) =>
         functionName match {
           case "not" =>
@@ -209,7 +215,11 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
                 ctx.log.error("Invalid call syntax", fce.position)
                 Nil
             }
-          case "*" => ???
+          case "*" =>
+            getArithmeticParamMaxSize(ctx, params) match {
+              case 1 => M6809MulDiv.compileByteMultiplication(ctx, params, updateDerefX = false) ++ targetifyB(ctx, target, isSigned = false)
+              case 2 => M6809MulDiv.compileWordMultiplication(ctx, params, updateDerefX = false) ++ targetifyD(ctx, target)
+            }
           case "*'" => ctx.log.error("Decimal multiplication not implemented yet", fce.position); Nil
           case "/" => ???
           case "%%" => ???
@@ -340,7 +350,12 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
               case _ => ???
             }
           case "-'=" => ???
-          case "*=" => ???
+          case "*=" =>
+            val (l, r, size) = assertArithmeticAssignmentLike(ctx, params)
+            size match {
+              case 1 => compileAddressToX(ctx, l) ++ M6809MulDiv.compileByteMultiplication(ctx, List(r), updateDerefX = true)
+              case 2 => compileAddressToX(ctx, l) ++ M6809MulDiv.compileWordMultiplication(ctx, List(r), updateDerefX = true)
+            }
           case "*'=" => ctx.log.error("Decimal multiplication not implemented yet", fce.position); Nil
           case "/=" => ???
           case "%%=" => ???
@@ -553,6 +568,11 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
     }
   }
 
+  def stashAIfNeeded(ctx: CompilationContext, lines: List[MLine]): List[MLine] = {
+    if (lines.exists(_.changesRegister(M6809Register.A))) MLine.pp(PSHS, M6809Register.A) :: (lines :+ MLine.pp(PULS, M6809Register.A))
+    else lines
+  }
+
   def stashBIfNeeded(ctx: CompilationContext, lines: List[MLine]): List[MLine] = {
     if (lines.exists(_.changesRegister(M6809Register.B))) MLine.pp(PSHS, M6809Register.B) :: (lines :+ MLine.pp(PULS, M6809Register.B))
     else lines
diff --git a/src/main/scala/millfork/compiler/m6809/M6809MulDiv.scala b/src/main/scala/millfork/compiler/m6809/M6809MulDiv.scala
index 5d44aa7a..c92662a1 100644
--- a/src/main/scala/millfork/compiler/m6809/M6809MulDiv.scala
+++ b/src/main/scala/millfork/compiler/m6809/M6809MulDiv.scala
@@ -1,8 +1,108 @@
 package millfork.compiler.m6809
 
+import millfork.assembly.m6809.{MLine, RegisterSet}
+import millfork.compiler.CompilationContext
+import millfork.env.{CompoundConstant, Constant, MathOperator, NumericConstant, ThingInMemory}
+import millfork.node.{Expression, IndexedExpression, LiteralExpression, M6809Register, VariableExpression}
+import millfork.assembly.m6809.MOpcode._
+import M6809Register._
+
+import scala.collection.mutable.ListBuffer
+
 /**
   * @author Karol Stasiak
   */
 object M6809MulDiv {
 
+  def compileByteMultiplication(ctx: CompilationContext, params: List[Expression], updateDerefX: Boolean): List[MLine] = {
+    var constant = Constant.One
+    val variablePart = params.flatMap { p =>
+      ctx.env.eval(p) match {
+        case Some(c) =>
+          constant = CompoundConstant(MathOperator.Times, constant, c).quickSimplify
+          None
+        case None => Some(p)
+      }
+    }
+    if (!updateDerefX && variablePart.isEmpty) {
+      return List(MLine.immediate(LDB, constant))
+    }
+    val result = ListBuffer[MLine]()
+    if (updateDerefX) {
+      result += MLine.indexedX(LDB, 0)
+    } else {
+      result ++= M6809ExpressionCompiler.compileToB(ctx, variablePart.head)
+    }
+    for (factor <- if (updateDerefX) variablePart else variablePart.tail) {
+      factor match {
+        case _: VariableExpression =>
+          result ++= M6809ExpressionCompiler.stashBIfNeeded(ctx, M6809ExpressionCompiler.compileToA(ctx, factor))
+        case _ =>
+          // TODO: optimize?
+          result += MLine.tfr(B, A)
+          result ++= M6809ExpressionCompiler.stashAIfNeeded(ctx, M6809ExpressionCompiler.compileToB(ctx, factor))
+      }
+      result += MLine.inherent(MUL)
+    }
+    constant.loByte.quickSimplify match {
+      case NumericConstant(0, _) => result += MLine.immediate(LDB, 0)
+      case NumericConstant(1, _) => ()
+      case NumericConstant(2, _) => result += MLine.inherentB(ASL)
+      case NumericConstant(4, _) => result ++= List(MLine.inherentB(ASL), MLine.inherentB(ASL))
+      case NumericConstant(8, _) => result ++= List(MLine.inherentB(ASL), MLine.inherentB(ASL), MLine.inherentB(ASL))
+      case NumericConstant(16, _) => result ++= List(MLine.inherentB(ASL), MLine.inherentB(ASL), MLine.inherentB(ASL), MLine.inherentB(ASL))
+      case NumericConstant(32, _) => result ++= List(MLine.inherentB(ASL), MLine.inherentB(ASL), MLine.inherentB(ASL), MLine.inherentB(ASL), MLine.inherentB(ASL))
+      case NumericConstant(-1 | 255, _) => result += MLine.inherentB(NEG)
+      case NumericConstant(-2 | 254, _) => result ++= List(MLine.inherentB(ASL), MLine.inherentB(NEG))
+      case _ => result ++= List(MLine.immediate(LDA, constant), MLine.inherent(MUL))
+    }
+    if (updateDerefX) {
+      result += MLine.indexedX(STB, 0)
+    }
+    result.toList
+  }
+
+  def compileWordMultiplication(ctx: CompilationContext, params: List[Expression], updateDerefX: Boolean): List[MLine] = {
+    var constant = Constant.One
+    val variablePart = params.flatMap { p =>
+      ctx.env.eval(p) match {
+        case Some(c) =>
+          constant = CompoundConstant(MathOperator.Times, constant, c).quickSimplify
+          None
+        case None => Some(p)
+      }
+    }
+    if (!updateDerefX && variablePart.isEmpty) {
+      return List(MLine.immediate(LDD, constant))
+    }
+    val result = ListBuffer[MLine]()
+    if (updateDerefX) {
+      result += MLine.indexedX(LDD, 0)
+      result += MLine(PSHS, RegisterSet(Set(X)), Constant.Zero)
+    } else {
+      result ++= M6809ExpressionCompiler.compileToD(ctx, variablePart.head)
+    }
+    for (factor <- if (updateDerefX) variablePart else variablePart.tail) {
+      factor match {
+        case _: VariableExpression =>
+          result ++= M6809ExpressionCompiler.stashDIfNeeded(ctx, M6809ExpressionCompiler.compileToX(ctx, factor))
+        case _ =>
+          // TODO: optimize?
+          result += MLine.tfr(D, X)
+          result ++= M6809ExpressionCompiler.stashXIfNeeded(ctx, M6809ExpressionCompiler.compileToD(ctx, factor))
+      }
+      result += MLine.absolute(JSR, ctx.env.get[ThingInMemory]("__mul_u16u16u16"))
+    }
+    constant.loByte.quickSimplify match {
+      case NumericConstant(0, _) => result += MLine.immediate(LDD, 0)
+      case NumericConstant(1, _) => ()
+      case NumericConstant(2, _) => result ++= List(MLine.inherentB(ASL), MLine.inherentA(ROL))
+      case _ => result ++= List(MLine.immediate(LDX, constant), MLine.absolute(JSR, ctx.env.get[ThingInMemory]("__mul_u16u16u16")))
+    }
+    if (updateDerefX) {
+      result += MLine(PULS, RegisterSet(Set(X)), Constant.Zero)
+      result += MLine.indexedX(STD, 0)
+    }
+    result.toList
+  }
 }
diff --git a/src/test/scala/millfork/test/emu/EmuM6809Run.scala b/src/test/scala/millfork/test/emu/EmuM6809Run.scala
index 7a19934d..dd184821 100644
--- a/src/test/scala/millfork/test/emu/EmuM6809Run.scala
+++ b/src/test/scala/millfork/test/emu/EmuM6809Run.scala
@@ -36,7 +36,7 @@ object EmuM6809Run {
     val PreprocessingResult(preprocessedSource, features, _) = Preprocessor.preprocessForTest(options, source)
     TestErrorReporting.log.debug(s"Features: $features")
     TestErrorReporting.log.info(s"Parsing $filename")
-    val parser = Z80Parser(filename, preprocessedSource, "", options, features, useIntelSyntax = false)
+    val parser = M6809Parser(filename, preprocessedSource, "", options, features)
     parser.toAst match {
       case Success(x, _) => Some(x)
       case f: Failure[_, _] =>
@@ -53,7 +53,7 @@ object EmuM6809Run {
   private def get(cpu: millfork.Cpu.Value, path: String): Program =
     synchronized { cache.getOrElseUpdate(cpu->path, preload(cpu, path)).getOrElse(throw new IllegalStateException()) }
 
-  def cachedMath(cpu: millfork.Cpu.Value): Program = get(cpu, "include/m6809_math.mfk")
+  def cachedMath(cpu: millfork.Cpu.Value): Program = get(cpu, "include/m6809/m6809_math.mfk")
   def cachedStdio(cpu: millfork.Cpu.Value): Program = get(cpu, "src/test/resources/include/dummy_stdio.mfk")
 }
 
@@ -113,9 +113,8 @@ class EmuM6809Run(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimizat
         val withLibraries = {
           var tmp = unoptimized
           if(source.contains("import stdio"))
-            tmp += EmuRun.cachedStdio
-          if(!options.flag(CompilationFlag.DecimalMode) && (source.contains("+'") || source.contains("-'") || source.contains("<<'") || source.contains("*'")))
-            tmp += EmuRun.cachedBcd
+            tmp += EmuM6809Run.cachedStdio(cpu)
+          tmp += EmuM6809Run.cachedMath(cpu)
           tmp
         }
         val program = nodeOptimizations.foldLeft(withLibraries.applyImportantAliases)((p, opt) => p.applyNodeOptimization(opt, options))