Optimized equality and non equality tests with zero in comparison.go
This commit is contained in:
parent
af315647bd
commit
2dc591f40d
1 changed files with 76 additions and 72 deletions
|
|
@ -180,6 +180,21 @@ func (cg *comparisonGenerator) tempLabel() string {
|
|||
return label
|
||||
}
|
||||
|
||||
// isZeroLiteral checks if operand is literal 0
|
||||
func (cg *comparisonGenerator) isZeroLiteral(op *operandInfo) bool {
|
||||
return !op.isVar && op.value == 0
|
||||
}
|
||||
|
||||
// genLoadAndTest generates load with optional compare for zero optimization
|
||||
func (cg *comparisonGenerator) genLoadAndTest(loadOp *operandInfo, cmpOp *operandInfo, offset int) []string {
|
||||
code := []string{cg.loadOperand(loadOp, offset)}
|
||||
// Skip CMP when comparing with zero - Z flag already set by LDA
|
||||
if !cg.isZeroLiteral(cmpOp) {
|
||||
code = append(code, cg.cmpOperand(cmpOp, offset))
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
// extractByteWord separates byte and word operands
|
||||
func (cg *comparisonGenerator) extractByteWord() (byte, word *operandInfo) {
|
||||
if cg.kind1 == compiler.KindByte {
|
||||
|
|
@ -205,76 +220,69 @@ func (cg *comparisonGenerator) genEqual() ([]string, error) {
|
|||
}
|
||||
|
||||
func (cg *comparisonGenerator) genByteEqual() ([]string, error) {
|
||||
code := cg.genLoadAndTest(cg.param1, cg.param2, 0)
|
||||
|
||||
if !cg.useLongJump {
|
||||
return []string{
|
||||
cg.loadOperand(cg.param1, 0),
|
||||
cg.cmpOperand(cg.param2, 0),
|
||||
fmt.Sprintf("\tbne %s", cg.skipLabel),
|
||||
}, nil
|
||||
code = append(code, fmt.Sprintf("\tbne %s", cg.skipLabel))
|
||||
return code, nil
|
||||
}
|
||||
|
||||
success := cg.tempLabel()
|
||||
return []string{
|
||||
cg.loadOperand(cg.param1, 0),
|
||||
cg.cmpOperand(cg.param2, 0),
|
||||
code = append(code,
|
||||
fmt.Sprintf("\tbeq %s", success),
|
||||
fmt.Sprintf("\tjmp %s", cg.skipLabel),
|
||||
success,
|
||||
}, nil
|
||||
)
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func (cg *comparisonGenerator) genWordEqual() ([]string, error) {
|
||||
code := cg.genLoadAndTest(cg.param1, cg.param2, 0)
|
||||
|
||||
if !cg.useLongJump {
|
||||
return []string{
|
||||
cg.loadOperand(cg.param1, 0),
|
||||
cg.cmpOperand(cg.param2, 0),
|
||||
fmt.Sprintf("\tbne %s", cg.skipLabel),
|
||||
cg.loadOperand(cg.param1, 1),
|
||||
cg.cmpOperand(cg.param2, 1),
|
||||
fmt.Sprintf("\tbne %s", cg.skipLabel),
|
||||
}, nil
|
||||
code = append(code, fmt.Sprintf("\tbne %s", cg.skipLabel))
|
||||
code = append(code, cg.genLoadAndTest(cg.param1, cg.param2, 1)...)
|
||||
code = append(code, fmt.Sprintf("\tbne %s", cg.skipLabel))
|
||||
return code, nil
|
||||
}
|
||||
|
||||
success := cg.tempLabel()
|
||||
fail := cg.tempLabel()
|
||||
return []string{
|
||||
cg.loadOperand(cg.param1, 0),
|
||||
cg.cmpOperand(cg.param2, 0),
|
||||
fmt.Sprintf("\tbne %s", fail),
|
||||
cg.loadOperand(cg.param1, 1),
|
||||
cg.cmpOperand(cg.param2, 1),
|
||||
code = append(code, fmt.Sprintf("\tbne %s", fail))
|
||||
code = append(code, cg.genLoadAndTest(cg.param1, cg.param2, 1)...)
|
||||
code = append(code,
|
||||
fmt.Sprintf("\tbeq %s", success),
|
||||
fail,
|
||||
fmt.Sprintf("\tjmp %s", cg.skipLabel),
|
||||
success,
|
||||
}, nil
|
||||
)
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func (cg *comparisonGenerator) genMixedEqual() ([]string, error) {
|
||||
byteOp, wordOp := cg.extractByteWord()
|
||||
|
||||
// Check if word high byte != 0 (means can't be equal)
|
||||
code := []string{cg.loadOperand(wordOp, 1)}
|
||||
code = append(code, fmt.Sprintf("\tbne %s", cg.skipLabel))
|
||||
|
||||
// High byte is 0, compare low bytes
|
||||
code = append(code, cg.genLoadAndTest(wordOp, byteOp, 0)...)
|
||||
|
||||
if !cg.useLongJump {
|
||||
return []string{
|
||||
cg.loadOperand(wordOp, 1),
|
||||
fmt.Sprintf("\tbne %s", cg.skipLabel),
|
||||
cg.loadOperand(byteOp, 0),
|
||||
cg.cmpOperand(wordOp, 0),
|
||||
fmt.Sprintf("\tbne %s", cg.skipLabel),
|
||||
}, nil
|
||||
code = append(code, fmt.Sprintf("\tbne %s", cg.skipLabel))
|
||||
return code, nil
|
||||
}
|
||||
|
||||
success := cg.tempLabel()
|
||||
fail := cg.tempLabel()
|
||||
return []string{
|
||||
cg.loadOperand(wordOp, 1),
|
||||
fmt.Sprintf("\tbne %s", fail),
|
||||
cg.loadOperand(byteOp, 0),
|
||||
cg.cmpOperand(wordOp, 0),
|
||||
code = append(code,
|
||||
fmt.Sprintf("\tbeq %s", success),
|
||||
fail,
|
||||
fmt.Sprintf("\tjmp %s", cg.skipLabel),
|
||||
success,
|
||||
}, nil
|
||||
)
|
||||
return code, nil
|
||||
}
|
||||
|
||||
// != operator
|
||||
|
|
@ -291,76 +299,72 @@ func (cg *comparisonGenerator) genNotEqual() ([]string, error) {
|
|||
}
|
||||
|
||||
func (cg *comparisonGenerator) genByteNotEqual() ([]string, error) {
|
||||
code := cg.genLoadAndTest(cg.param1, cg.param2, 0)
|
||||
|
||||
if !cg.useLongJump {
|
||||
return []string{
|
||||
cg.loadOperand(cg.param1, 0),
|
||||
cg.cmpOperand(cg.param2, 0),
|
||||
fmt.Sprintf("\tbeq %s", cg.skipLabel),
|
||||
}, nil
|
||||
code = append(code, fmt.Sprintf("\tbeq %s", cg.skipLabel))
|
||||
return code, nil
|
||||
}
|
||||
|
||||
success := cg.tempLabel()
|
||||
return []string{
|
||||
cg.loadOperand(cg.param1, 0),
|
||||
cg.cmpOperand(cg.param2, 0),
|
||||
code = append(code,
|
||||
fmt.Sprintf("\tbne %s", success),
|
||||
fmt.Sprintf("\tjmp %s", cg.skipLabel),
|
||||
success,
|
||||
}, nil
|
||||
)
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func (cg *comparisonGenerator) genWordNotEqual() ([]string, error) {
|
||||
success := cg.tempLabel()
|
||||
code := cg.genLoadAndTest(cg.param1, cg.param2, 0)
|
||||
|
||||
if !cg.useLongJump {
|
||||
return []string{
|
||||
cg.loadOperand(cg.param1, 0),
|
||||
cg.cmpOperand(cg.param2, 0),
|
||||
fmt.Sprintf("\tbne %s", success),
|
||||
cg.loadOperand(cg.param1, 1),
|
||||
cg.cmpOperand(cg.param2, 1),
|
||||
code = append(code, fmt.Sprintf("\tbne %s", success))
|
||||
code = append(code, cg.genLoadAndTest(cg.param1, cg.param2, 1)...)
|
||||
code = append(code,
|
||||
fmt.Sprintf("\tbne %s", success),
|
||||
fmt.Sprintf("\tjmp %s", cg.skipLabel),
|
||||
success,
|
||||
}, nil
|
||||
)
|
||||
return code, nil
|
||||
}
|
||||
|
||||
return []string{
|
||||
cg.loadOperand(cg.param1, 0),
|
||||
cg.cmpOperand(cg.param2, 0),
|
||||
fmt.Sprintf("\tbne %s", success),
|
||||
cg.loadOperand(cg.param1, 1),
|
||||
cg.cmpOperand(cg.param2, 1),
|
||||
code = append(code, fmt.Sprintf("\tbne %s", success))
|
||||
code = append(code, cg.genLoadAndTest(cg.param1, cg.param2, 1)...)
|
||||
code = append(code,
|
||||
fmt.Sprintf("\tbne %s", success),
|
||||
fmt.Sprintf("\tjmp %s", cg.skipLabel),
|
||||
success,
|
||||
}, nil
|
||||
)
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func (cg *comparisonGenerator) genMixedNotEqual() ([]string, error) {
|
||||
byteOp, wordOp := cg.extractByteWord()
|
||||
success := cg.tempLabel()
|
||||
|
||||
// Check if word high byte != 0 (means values definitely not equal)
|
||||
code := []string{cg.loadOperand(wordOp, 1)}
|
||||
code = append(code, fmt.Sprintf("\tbne %s", success))
|
||||
|
||||
// High byte is 0, compare low bytes
|
||||
code = append(code, cg.genLoadAndTest(wordOp, byteOp, 0)...)
|
||||
|
||||
if !cg.useLongJump {
|
||||
return []string{
|
||||
cg.loadOperand(wordOp, 1),
|
||||
fmt.Sprintf("\tbne %s", success),
|
||||
cg.loadOperand(byteOp, 0),
|
||||
cg.cmpOperand(wordOp, 0),
|
||||
code = append(code,
|
||||
fmt.Sprintf("\tbeq %s", cg.skipLabel),
|
||||
success,
|
||||
}, nil
|
||||
)
|
||||
return code, nil
|
||||
}
|
||||
|
||||
return []string{
|
||||
cg.loadOperand(wordOp, 1),
|
||||
fmt.Sprintf("\tbne %s", success),
|
||||
cg.loadOperand(byteOp, 0),
|
||||
cg.cmpOperand(wordOp, 0),
|
||||
code = append(code,
|
||||
fmt.Sprintf("\tbne %s", success),
|
||||
fmt.Sprintf("\tjmp %s", cg.skipLabel),
|
||||
success,
|
||||
}, nil
|
||||
)
|
||||
return code, nil
|
||||
}
|
||||
|
||||
// > operator (unsigned)
|
||||
|
|
|
|||
Loading…
Reference in a new issue