mirror of
https://github.com/KarolS/millfork.git
synced 2024-10-04 12:55:29 +00:00
Extract asDecimal. Improve constants.
This commit is contained in:
parent
0a01dd30e1
commit
779cc6ab5c
36
src/main/scala/millfork/DecimalUtils.scala
Normal file
36
src/main/scala/millfork/DecimalUtils.scala
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package millfork
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karol Stasiak
|
||||||
|
*/
|
||||||
|
object DecimalUtils {
|
||||||
|
|
||||||
|
private def parseNormalToDecimalValue(a: Long): Long = {
|
||||||
|
if (a < 0) -parseNormalToDecimalValue(-a)
|
||||||
|
var x = a
|
||||||
|
var result = 0L
|
||||||
|
var multiplier = 1L
|
||||||
|
while (x > 0) {
|
||||||
|
result += multiplier * (x % 16L)
|
||||||
|
x /= 16L
|
||||||
|
multiplier *= 10L
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
private def storeDecimalValueInNormalRespresentation(a: Long): Long = {
|
||||||
|
if (a < 0) -storeDecimalValueInNormalRespresentation(-a)
|
||||||
|
var x = a
|
||||||
|
var result = 0L
|
||||||
|
var multiplier = 1L
|
||||||
|
while (x > 0) {
|
||||||
|
result += multiplier * (x % 10L)
|
||||||
|
x /= 10L
|
||||||
|
multiplier *= 16L
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
def asDecimal(a: Long, b: Long, f: (Long, Long) => Long): Long =
|
||||||
|
storeDecimalValueInNormalRespresentation(f(parseNormalToDecimalValue(a), parseNormalToDecimalValue(b)))
|
||||||
|
}
|
109
src/main/scala/millfork/env/Constant.scala
vendored
109
src/main/scala/millfork/env/Constant.scala
vendored
@ -1,7 +1,6 @@
|
|||||||
package millfork.env
|
package millfork.env
|
||||||
|
|
||||||
import millfork.error.{ConsoleLogger, Logger}
|
import millfork.DecimalUtils._
|
||||||
import millfork.node.Position
|
|
||||||
|
|
||||||
object Constant {
|
object Constant {
|
||||||
val Zero: Constant = NumericConstant(0, 1)
|
val Zero: Constant = NumericConstant(0, 1)
|
||||||
@ -23,6 +22,10 @@ sealed trait Constant {
|
|||||||
def isProvablyZero: Boolean = false
|
def isProvablyZero: Boolean = false
|
||||||
def isProvably(value: Int): Boolean = false
|
def isProvably(value: Int): Boolean = false
|
||||||
def isProvablyNonnegative: Boolean = false
|
def isProvablyNonnegative: Boolean = false
|
||||||
|
def isProvablyGreaterOrEqualThan(other: Constant): Boolean = other match {
|
||||||
|
case NumericConstant(0, _) => true
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
|
||||||
def asl(i: Constant): Constant = i match {
|
def asl(i: Constant): Constant = i match {
|
||||||
case NumericConstant(sa, _) => asl(sa.toInt)
|
case NumericConstant(sa, _) => asl(sa.toInt)
|
||||||
@ -93,6 +96,7 @@ sealed trait Constant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case class AssertByte(c: Constant) extends Constant {
|
case class AssertByte(c: Constant) extends Constant {
|
||||||
|
override def isProvablyGreaterOrEqualThan(other: Constant): Boolean = c.isProvablyGreaterOrEqualThan(other)
|
||||||
override def isProvablyZero: Boolean = c.isProvablyZero
|
override def isProvablyZero: Boolean = c.isProvablyZero
|
||||||
override def isProvably(i: Int): Boolean = c.isProvably(i)
|
override def isProvably(i: Int): Boolean = c.isProvably(i)
|
||||||
override def isProvablyNonnegative: Boolean = c.isProvablyNonnegative
|
override def isProvablyNonnegative: Boolean = c.isProvablyNonnegative
|
||||||
@ -121,6 +125,10 @@ case class NumericConstant(value: Long, requiredSize: Int) extends Constant {
|
|||||||
throw new IllegalArgumentException(s"The constant $value is too big")
|
throw new IllegalArgumentException(s"The constant $value is too big")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
override def isProvablyGreaterOrEqualThan(other: Constant): Boolean = value >= 0 && (other match {
|
||||||
|
case NumericConstant(o, _) if o >= 0 => value >=o
|
||||||
|
case _ => false
|
||||||
|
})
|
||||||
override def isProvablyZero: Boolean = value == 0
|
override def isProvablyZero: Boolean = value == 0
|
||||||
override def isProvably(i: Int): Boolean = value == i
|
override def isProvably(i: Int): Boolean = value == i
|
||||||
override def isProvablyNonnegative: Boolean = value >= 0
|
override def isProvablyNonnegative: Boolean = value >= 0
|
||||||
@ -172,6 +180,11 @@ case class NumericConstant(value: Long, requiredSize: Int) extends Constant {
|
|||||||
case class MemoryAddressConstant(var thing: ThingInMemory) extends Constant {
|
case class MemoryAddressConstant(var thing: ThingInMemory) extends Constant {
|
||||||
|
|
||||||
override def isProvablyNonnegative: Boolean = true
|
override def isProvablyNonnegative: Boolean = true
|
||||||
|
override def isProvablyGreaterOrEqualThan(other: Constant): Boolean = other match {
|
||||||
|
case NumericConstant(0, _) => true
|
||||||
|
case MemoryAddressConstant(otherThing) => thing == otherThing
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
|
||||||
override def requiredSize = 2
|
override def requiredSize = 2
|
||||||
|
|
||||||
@ -239,6 +252,7 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co
|
|||||||
val l = lhs.quickSimplify
|
val l = lhs.quickSimplify
|
||||||
val r = rhs.quickSimplify
|
val r = rhs.quickSimplify
|
||||||
(l, r) match {
|
(l, r) match {
|
||||||
|
case (MemoryAddressConstant(lt), MemoryAddressConstant(rt)) if operator == MathOperator.Minus && lt == rt => Constant.Zero
|
||||||
case (CompoundConstant(MathOperator.Plus, a, ll@NumericConstant(lv, _)), rr@NumericConstant(rv, _)) if operator == MathOperator.Plus =>
|
case (CompoundConstant(MathOperator.Plus, a, ll@NumericConstant(lv, _)), rr@NumericConstant(rv, _)) if operator == MathOperator.Plus =>
|
||||||
CompoundConstant(MathOperator.Plus, a, ll + rr).quickSimplify
|
CompoundConstant(MathOperator.Plus, a, ll + rr).quickSimplify
|
||||||
case (CompoundConstant(MathOperator.Minus, a, ll@NumericConstant(lv, _)), rr@NumericConstant(rv, _)) if operator == MathOperator.Minus =>
|
case (CompoundConstant(MathOperator.Minus, a, ll@NumericConstant(lv, _)), rr@NumericConstant(rv, _)) if operator == MathOperator.Minus =>
|
||||||
@ -263,37 +277,6 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co
|
|||||||
|
|
||||||
case (_, CompoundConstant(MathOperator.DecimalMinus, a, b)) if operator == MathOperator.DecimalPlus =>
|
case (_, CompoundConstant(MathOperator.DecimalMinus, a, b)) if operator == MathOperator.DecimalPlus =>
|
||||||
CompoundConstant(MathOperator.DecimalMinus, CompoundConstant(MathOperator.DecimalPlus, l, a), b).quickSimplify
|
CompoundConstant(MathOperator.DecimalMinus, CompoundConstant(MathOperator.DecimalPlus, l, a), b).quickSimplify
|
||||||
case (NumericConstant(lv, ls), NumericConstant(rv, rs)) =>
|
|
||||||
var size = ls max rs
|
|
||||||
val value = operator match {
|
|
||||||
case MathOperator.Plus => lv + rv
|
|
||||||
case MathOperator.Minus => lv - rv
|
|
||||||
case MathOperator.Times => lv * rv
|
|
||||||
case MathOperator.Shl => lv << rv
|
|
||||||
case MathOperator.Shr => lv >> rv
|
|
||||||
case MathOperator.Shl9 => (lv << rv) & 0x1ff
|
|
||||||
case MathOperator.Plus9 => (lv + rv) & 0x1ff
|
|
||||||
case MathOperator.Shr9 => (lv & 0x1ff) >> rv
|
|
||||||
case MathOperator.Exor => lv ^ rv
|
|
||||||
case MathOperator.Or => lv | rv
|
|
||||||
case MathOperator.And => lv & rv
|
|
||||||
case MathOperator.DecimalPlus if ls == 1 && rs == 1 =>
|
|
||||||
asDecimal(lv & 0xff, rv & 0xff, _ + _) & 0xff
|
|
||||||
case MathOperator.DecimalMinus if ls == 1 && rs == 1 && lv.&(0xff) >= rv.&(0xff) =>
|
|
||||||
asDecimal(lv & 0xff, rv & 0xff, _ - _) & 0xff
|
|
||||||
case _ => return this
|
|
||||||
}
|
|
||||||
operator match {
|
|
||||||
case MathOperator.Plus9 | MathOperator.DecimalPlus9 =>
|
|
||||||
size = 2
|
|
||||||
case MathOperator.Times | MathOperator.Shl =>
|
|
||||||
val mask = (1 << (size * 8)) - 1
|
|
||||||
if (value != (value & mask)) {
|
|
||||||
size = ls + rs
|
|
||||||
}
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
NumericConstant(value, size)
|
|
||||||
case (NumericConstant(0, 1), c) =>
|
case (NumericConstant(0, 1), c) =>
|
||||||
operator match {
|
operator match {
|
||||||
case MathOperator.Plus => c
|
case MathOperator.Plus => c
|
||||||
@ -329,39 +312,41 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co
|
|||||||
case MathOperator.And => Constant.Zero
|
case MathOperator.And => Constant.Zero
|
||||||
case _ => CompoundConstant(operator, l, r)
|
case _ => CompoundConstant(operator, l, r)
|
||||||
}
|
}
|
||||||
|
case (NumericConstant(lv, ls), NumericConstant(rv, rs)) =>
|
||||||
|
var size = ls max rs
|
||||||
|
val value = operator match {
|
||||||
|
case MathOperator.Plus => lv + rv
|
||||||
|
case MathOperator.Minus => lv - rv
|
||||||
|
case MathOperator.Times => lv * rv
|
||||||
|
case MathOperator.Shl => lv << rv
|
||||||
|
case MathOperator.Shr => lv >> rv
|
||||||
|
case MathOperator.Shl9 => (lv << rv) & 0x1ff
|
||||||
|
case MathOperator.Plus9 => (lv + rv) & 0x1ff
|
||||||
|
case MathOperator.Shr9 => (lv & 0x1ff) >> rv
|
||||||
|
case MathOperator.Exor => lv ^ rv
|
||||||
|
case MathOperator.Or => lv | rv
|
||||||
|
case MathOperator.And => lv & rv
|
||||||
|
case MathOperator.DecimalPlus if ls == 1 && rs == 1 =>
|
||||||
|
asDecimal(lv & 0xff, rv & 0xff, _ + _) & 0xff
|
||||||
|
case MathOperator.DecimalMinus if ls == 1 && rs == 1 && lv.&(0xff) >= rv.&(0xff) =>
|
||||||
|
asDecimal(lv & 0xff, rv & 0xff, _ - _) & 0xff
|
||||||
|
case _ => return this
|
||||||
|
}
|
||||||
|
operator match {
|
||||||
|
case MathOperator.Plus9 | MathOperator.DecimalPlus9 =>
|
||||||
|
size = 2
|
||||||
|
case MathOperator.Times | MathOperator.Shl =>
|
||||||
|
val mask = (1 << (size * 8)) - 1
|
||||||
|
if (value != (value & mask)) {
|
||||||
|
size = ls + rs
|
||||||
|
}
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
|
NumericConstant(value, size)
|
||||||
case _ => CompoundConstant(operator, l, r)
|
case _ => CompoundConstant(operator, l, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def parseNormalToDecimalValue(a: Long): Long = {
|
|
||||||
if (a < 0) -parseNormalToDecimalValue(-a)
|
|
||||||
var x = a
|
|
||||||
var result = 0L
|
|
||||||
var multiplier = 1L
|
|
||||||
while (x > 0) {
|
|
||||||
result += multiplier * (x % 16L)
|
|
||||||
x /= 16L
|
|
||||||
multiplier *= 10L
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
private def storeDecimalValueInNormalRespresentation(a: Long): Long = {
|
|
||||||
if (a < 0) -storeDecimalValueInNormalRespresentation(-a)
|
|
||||||
var x = a
|
|
||||||
var result = 0L
|
|
||||||
var multiplier = 1L
|
|
||||||
while (x > 0) {
|
|
||||||
result += multiplier * (x % 10L)
|
|
||||||
x /= 10L
|
|
||||||
multiplier *= 16L
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
private def asDecimal(a: Long, b: Long, f: (Long, Long) => Long): Long =
|
|
||||||
storeDecimalValueInNormalRespresentation(f(parseNormalToDecimalValue(a), parseNormalToDecimalValue(b)))
|
|
||||||
|
|
||||||
|
|
||||||
import MathOperator._
|
import MathOperator._
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import millfork._
|
|||||||
import millfork.assembly.z80.ZLine
|
import millfork.assembly.z80.ZLine
|
||||||
|
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
import scala.math.Integral.Implicits.infixIntegralOps
|
import DecimalUtils._
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Karol Stasiak
|
* @author Karol Stasiak
|
||||||
@ -104,6 +104,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
|
|||||||
case Some(cc) =>
|
case Some(cc) =>
|
||||||
deepConstResolve(cc)
|
deepConstResolve(cc)
|
||||||
case None =>
|
case None =>
|
||||||
|
log.fatal("Failed to resolve constant: " + th.name)
|
||||||
println(th)
|
println(th)
|
||||||
???
|
???
|
||||||
}
|
}
|
||||||
@ -150,35 +151,6 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def parseNormalToDecimalValue(a: Long): Long = {
|
|
||||||
if (a < 0) -parseNormalToDecimalValue(-a)
|
|
||||||
var x = a
|
|
||||||
var result = 0L
|
|
||||||
var multiplier = 1L
|
|
||||||
while (x > 0) {
|
|
||||||
result += multiplier * (x % 16L)
|
|
||||||
x /= 16L
|
|
||||||
multiplier *= 10L
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
private def storeDecimalValueInNormalRespresentation(a: Long): Long = {
|
|
||||||
if (a < 0) -storeDecimalValueInNormalRespresentation(-a)
|
|
||||||
var x = a
|
|
||||||
var result = 0L
|
|
||||||
var multiplier = 1L
|
|
||||||
while (x > 0) {
|
|
||||||
result += multiplier * (x % 10L)
|
|
||||||
x /= 10L
|
|
||||||
multiplier *= 16L
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
private def asDecimal(a: Long, b: Long, f: (Long, Long) => Long): Long =
|
|
||||||
storeDecimalValueInNormalRespresentation(f(parseNormalToDecimalValue(a), parseNormalToDecimalValue(b)))
|
|
||||||
|
|
||||||
def bytePseudoopcode: String
|
def bytePseudoopcode: String
|
||||||
|
|
||||||
def assemble(callGraph: CallGraph, optimizations: Seq[AssemblyOptimization[T]], options: CompilationOptions): AssemblerOutput = {
|
def assemble(callGraph: CallGraph, optimizations: Seq[AssemblyOptimization[T]], options: CompilationOptions): AssemblerOutput = {
|
||||||
|
Loading…
Reference in New Issue
Block a user