optimize strlen()

This commit is contained in:
Irmen de Jong 2020-08-25 17:22:51 +02:00
parent 4a4f8ff5db
commit d19b17cbfe
5 changed files with 53 additions and 39 deletions

View File

@ -1224,19 +1224,6 @@ _gtequ dey
_result_minw .word 0
.pend
func_strlen .proc
; -- push length of 0-terminated string on stack
jsr peek_address
ldy #0
- lda (c64.SCRATCH_ZPWORD1),y
beq +
iny
bne -
+ tya
sta c64.ESTACK_LO+1,x
rts
.pend
func_rnd .proc
; -- put a random ubyte on the estack
jsr math.randbyte
@ -1325,6 +1312,19 @@ func_memsetw .proc
rts
.pend
strlen .proc
; -- put length of 0-terminated string in A/Y into A
sta c64.SCRATCH_ZPWORD1
sty c64.SCRATCH_ZPWORD1+1
ldy #0
- lda (c64.SCRATCH_ZPWORD1),y
beq +
iny
bne -
+ tya
rts
.pend
memcopy16_up .proc
; -- copy memory UP from (SCRATCH_ZPWORD1) to (SCRATCH_ZPWORD2) of length X/Y (16-bit, X=lo, Y=hi)

View File

@ -11,6 +11,10 @@ import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_HI_HEX
import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_HI_PLUS1_HEX
import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_LO_HEX
import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_LO_PLUS1_HEX
import prog8.compiler.target.c64.codegen.assignment.AsmAssignSource
import prog8.compiler.target.c64.codegen.assignment.AsmAssignTarget
import prog8.compiler.target.c64.codegen.assignment.AsmAssignment
import prog8.compiler.target.c64.codegen.assignment.TargetStorageKind
import prog8.compiler.toHex
import prog8.functions.FSignature
@ -388,8 +392,13 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
}
private fun funcStrlen(fcall: IFunctionCall) {
outputPushAddressOfIdentifier(fcall.args[0])
asmgen.out(" jsr prog8_lib.func_strlen")
val name = asmgen.asmIdentifierName(fcall.args[0] as IdentifierReference)
asmgen.out("""
lda #<$name
ldy #>$name
jsr prog8_lib.strlen
sta $ESTACK_LO_HEX,x
dex""")
}
private fun funcSwap(fcall: IFunctionCall) {
@ -500,17 +509,6 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
""")
}
private fun outputPushAddressOfIdentifier(arg: Expression) {
val identifierName = asmgen.asmIdentifierName(arg as IdentifierReference)
asmgen.out("""
lda #<$identifierName
sta $ESTACK_LO_HEX,x
lda #>$identifierName
sta $ESTACK_HI_HEX,x
dex
""")
}
private fun translateFunctionArguments(args: MutableList<Expression>, signature: FSignature) {
args.forEach {
asmgen.translateExpression(it)

View File

@ -318,7 +318,15 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
else -> throw AssemblyError("can't load address in a single 8-bit register")
}
}
TargetStorageKind.STACK -> TODO()
TargetStorageKind.STACK -> {
val srcname = asmgen.asmIdentifierName(name)
asmgen.out("""
lda #<$srcname
sta $ESTACK_LO_HEX,x
lda #>$srcname
sta $ESTACK_HI_HEX,x
dex""")
}
}
}
@ -875,11 +883,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
asmgen.out("""
inx
ldy $ESTACK_LO_HEX,x
sty ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W2}
ldy $ESTACK_HI_HEX,x
sty ${C64Zeropage.SCRATCH_W1+1}
sty ${C64Zeropage.SCRATCH_W2+1}
ldy #0
sta (${C64Zeropage.SCRATCH_W1}),y""")
sta (${C64Zeropage.SCRATCH_W2}),y""")
}
}
}

View File

@ -280,11 +280,18 @@ private fun builtinSizeof(args: List<Expression>, position: Position, program: P
private fun builtinStrlen(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
if (args.size != 1)
throw SyntaxError("strlen requires one argument", position)
val argument = args[0].constValue(program) ?: throw NotConstArgumentException()
if(argument.type != DataType.STR)
throw SyntaxError("strlen must have string argument", position)
throw NotConstArgumentException() // this function is not considering the string argument a constant
val argument=args[0]
if(argument is StringLiteralValue)
return NumericLiteralValue.optimalInteger(argument.value.length, argument.position)
val vardecl = (argument as IdentifierReference).targetVarDecl(program.namespace)
if(vardecl!=null) {
if(vardecl.datatype!=DataType.STR)
throw SyntaxError("strlen must have string argument", position)
if(vardecl.autogeneratedDontRemove) {
return NumericLiteralValue.optimalInteger((vardecl.value as StringLiteralValue).value.length, argument.position)
}
}
throw NotConstArgumentException()
}
private fun builtinLen(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {

View File

@ -5,11 +5,12 @@ main {
sub start() {
subje(12345)
}
str tekst = "the quick brown fox"
sub subje(uword xx) {
@($c000) = lsb(xx)
c64scr.print_uw(strlen("aapje"))
c64.CHROUT('\n')
c64scr.print_uw(strlen(tekst))
c64.CHROUT('\n')
}
}