1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-02-10 10:31:27 +00:00

Added utoa16(). Fixed early constant identification not taking procedure parameters into account.

This commit is contained in:
jespergravgaard 2019-05-20 23:41:58 +02:00
parent 2b26c813d9
commit bc699a9e27
3 changed files with 187 additions and 116 deletions

View File

@ -6,12 +6,15 @@ import dk.camelot64.kickc.model.operators.OperatorCastPtr;
import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.statements.StatementLValue; import dk.camelot64.kickc.model.statements.StatementLValue;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.values.ConstantValue; import dk.camelot64.kickc.model.values.ConstantValue;
import dk.camelot64.kickc.model.values.VariableRef; import dk.camelot64.kickc.model.values.VariableRef;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List;
/** Identify any variable that are clearly constant. */ /** Identify any variable that are clearly constant. */
public class Pass1EarlyConstantIdentification extends Pass1Base { public class Pass1EarlyConstantIdentification extends Pass1Base {
@ -26,18 +29,20 @@ public class Pass1EarlyConstantIdentification extends Pass1Base {
for(Variable variable : getProgram().getScope().getAllVariables(true)) { for(Variable variable : getProgram().getScope().getAllVariables(true)) {
VariableRef variableRef = variable.getRef(); VariableRef variableRef = variable.getRef();
if(!variable.isDeclaredConstant() && !variable.isDeclaredVolatile() && !variableRef.isIntermediate()) { if(!variable.isDeclaredConstant() && !variable.isDeclaredVolatile() && !variableRef.isIntermediate()) {
Collection<StatementLValue> assignments = getAssignments(variable); if(!isParameter(variableRef)) {
if(assignments.size() == 1) { Collection<StatementLValue> assignments = getAssignments(variable);
if(!Pass2ConstantIdentification.isAddressOfUsed(variableRef, getProgram())) { if(assignments.size() == 1) {
StatementLValue assignment = assignments.iterator().next(); if(!Pass2ConstantIdentification.isAddressOfUsed(variableRef, getProgram())) {
if(assignment instanceof StatementAssignment) { StatementLValue assignment = assignments.iterator().next();
StatementAssignment assign = (StatementAssignment) assignment; if(assignment instanceof StatementAssignment) {
if(assign.getrValue1() == null && assign.getOperator() == null && assign.getrValue2() instanceof ConstantValue) { StatementAssignment assign = (StatementAssignment) assignment;
getLog().append("Identified constant variable " + variable.toString(getProgram())); if(assign.getrValue1() == null && assign.getOperator() == null && assign.getrValue2() instanceof ConstantValue) {
earlyConstants.add(variableRef); getLog().append("Identified constant variable " + variable.toString(getProgram()));
} else if(assign.getrValue1() == null && assign.getOperator() instanceof OperatorCastPtr && assign.getrValue2() instanceof ConstantValue) { earlyConstants.add(variableRef);
getLog().append("Identified constant variable " + variable.toString(getProgram())); } else if(assign.getrValue1() == null && assign.getOperator() instanceof OperatorCastPtr && assign.getrValue2() instanceof ConstantValue) {
earlyConstants.add(variableRef); getLog().append("Identified constant variable " + variable.toString(getProgram()));
earlyConstants.add(variableRef);
}
} }
} }
} }
@ -48,6 +53,23 @@ public class Pass1EarlyConstantIdentification extends Pass1Base {
return false; return false;
} }
/**
* Examines whether a variale is a procedure parameter
* @param variableRef The variable
* @return true if the variable is a procedure parameter
*/
public boolean isParameter(VariableRef variableRef) {
Variable var = getScope().getVariable(variableRef);
Scope varScope = var.getScope();
if(varScope instanceof Procedure) {
List<Variable> parameters = ((Procedure) varScope).getParameters();
if(parameters.contains(var))
return true;
}
return false;
}
/** /**
* Find all assignments of a variable. * Find all assignments of a variable.
* *

View File

@ -14,15 +14,15 @@ void main() {
unsigned char *screen = 0x0400; unsigned char *screen = 0x0400;
*bordercol = 1; *bordercol = 1;
unsigned char time_start = *raster; unsigned char time_start = *raster;
utoa10b(00000, screen); (*bordercol)++; screen += 40; utoa16w(00000, screen); (*bordercol)++; screen += 40;
utoa10b(01234, screen); (*bordercol)++; screen += 40; utoa16w(01234, screen); (*bordercol)++; screen += 40;
utoa10b(05678, screen); (*bordercol)++; screen += 40; utoa16w(05678, screen); (*bordercol)++; screen += 40;
utoa10b(09999, screen); (*bordercol)++; screen += 40; utoa16w(09999, screen); (*bordercol)++; screen += 40;
utoa10b(58888, screen); utoa16w(58888, screen);
unsigned char time_end = *raster; unsigned char time_end = *raster;
*bordercol = 0; *bordercol = 0;
unsigned char time = time_end - time_start; unsigned char time = time_end - time_start;
utoa10b((unsigned int)time, screen+80); utoa10w((unsigned int)time, screen+80);
byte[] msg = "raster lines"; byte[] msg = "raster lines";
for( byte i=0; msg[i]!=0; i++ ) (screen+80+3)[i] = msg[i]; for( byte i=0; msg[i]!=0; i++ ) (screen+80+3)[i] = msg[i];
//for( byte* m="lines", s=screen+80+6 ;*m!=0;m++,s++) *s = *m; //for( byte* m="lines", s=screen+80+6 ;*m!=0;m++,s++) *s = *m;
@ -40,58 +40,20 @@ const unsigned char RADIX_OCTAL = 8;
const unsigned char RADIX_DECIMAL = 10; const unsigned char RADIX_DECIMAL = 10;
const unsigned char RADIX_HEX = 16; const unsigned char RADIX_HEX = 16;
// simple 'utoa' without using multiply or divide // Digits used for utoa()
unsigned int utoa_digit(unsigned char *dst, unsigned int value, unsigned int sub){
unsigned char digit = 0;
unsigned int sub3 = sub*2+sub;
while (value >= sub3){ digit += 3; value -= sub3; }
while (value >= sub){ ++digit; value -= sub; }
*dst = DIGITS[digit];
return value;
}
void utoa(unsigned int value, unsigned char *dst){
unsigned char bStarted = 0;
if (bStarted == 1 || value >= 10000){ value = utoa_digit(dst++, value, 10000); bStarted = 1; }
if (bStarted == 1 || value >= 1000){ value = utoa_digit(dst++, value, 1000); bStarted = 1; }
if (bStarted == 1 || value >= 100){ value = utoa_digit(dst++, value, 100); bStarted = 1; }
if (bStarted == 1 || value >= 10){ value = utoa_digit(dst++, value, 10); bStarted = 1; }
*dst++ = '0' + (unsigned char) value;
//*dst = 0;
}
unsigned char[] DIGITS = "0123456789abcdef"; unsigned char[] DIGITS = "0123456789abcdef";
unsigned int[] SUB3 = { 30000, 3000, 300, 30 };
unsigned int[] SUB1 = { 10000, 1000, 100, 10 };
// Simple decimal utoa() without using multiply or divide // Subtraction values used for decimal utoa()
void utoa10(unsigned int value, unsigned char* dst) { unsigned int[] UTOA10_SUB = { 30000, 10000, 3000, 1000, 300, 100, 30, 10 };
unsigned char bStarted = 0; // Digit addition values used for decimal utoa()
for( unsigned char i: 0..3) { unsigned char[] UTOA10_VAL = { 3, 1, 3, 1, 3, 1, 3, 1 };
unsigned char digit = 0;
unsigned int sub1 = SUB1[i];
if(value>=sub1) {
unsigned int sub3 = SUB3[i];
while(value>=sub3) { digit += 3; value -= sub3; bStarted = 1; }
while(value>=sub1) { digit += 1; value -= sub1; bStarted = 1; }
}
if(bStarted!=0) {
*dst++ = DIGITS[digit];
}
}
*dst++ = DIGITS[(unsigned char) value];
//*dst = 0;
}
unsigned int[] SUB = { 30000, 10000, 3000, 1000, 300, 100, 30, 10 };
unsigned char[] VAL = { 3, 1, 3, 1, 3, 1, 3, 1 };
// Decimal utoa() without using multiply or divide // Decimal utoa() without using multiply or divide
void utoa10b(unsigned int value, unsigned char* dst) { void utoa10w(unsigned int value, unsigned char* dst) {
unsigned char bStarted = 0; unsigned char bStarted = 0;
unsigned char digit = 0; unsigned char digit = 0;
for( unsigned char i: 0..7) { for( unsigned char i: 0..7) {
while(value>=SUB[i]) { digit += VAL[i]; value -= SUB[i]; bStarted = 1; } while(value>=UTOA10_SUB[i]) { digit += UTOA10_VAL[i]; value -= UTOA10_SUB[i]; bStarted = 1; }
if((i&1)!=0) { if((i&1)!=0) {
if(bStarted!=0) { if(bStarted!=0) {
*dst++ = DIGITS[digit]; *dst++ = DIGITS[digit];
@ -101,4 +63,29 @@ void utoa10b(unsigned int value, unsigned char* dst) {
} }
*dst++ = DIGITS[(unsigned char) value]; *dst++ = DIGITS[(unsigned char) value];
*dst = 0; *dst = 0;
} }
// Holds the destination address for the hexadecimal utoa()
unsigned char* utoa16_dst;
// Holds whether the hexadecimal utoa() has started outputting digits
unsigned char utoa16_started;
// Hexadecimal utoa() for an unsigned int (16bits)
void utoa16w(unsigned int value, unsigned char* dst) {
utoa16_dst = dst;
utoa16_started = 0;
utoa16n((>value)>>4);
utoa16n((>value)&0x0f);
utoa16n((<value)>>4);
utoa16_started = 1;
utoa16n((<value)&0x0f);
*utoa16_dst = 0;
}
// Hexadecimal utoa() for a single nybble
void utoa16n(unsigned char nybble) {
if(nybble!=0) utoa16_started=1;
if(utoa16_started!=0) {
*utoa16_dst++ = DIGITS[nybble];
}
}

View File

@ -5,9 +5,11 @@
.label control = $d011 .label control = $d011
.label raster = $d012 .label raster = $d012
.label bordercol = $d020 .label bordercol = $d020
.label utoa16_dst = 2
.label utoa16_started = 4
main: { main: {
.label _1 = 4 .label _1 = 4
.label time_start = 8 .label time_start = 5
sei sei
jsr cls jsr cls
b1: b1:
@ -23,68 +25,64 @@ main: {
sta bordercol sta bordercol
lda raster lda raster
sta time_start sta time_start
lda #<$400
sta utoa10b.dst
lda #>$400
sta utoa10b.dst+1
lda #0 lda #0
sta utoa10b.value sta utoa16w.value
sta utoa10b.value+1 sta utoa16w.value+1
jsr utoa10b lda #<$400
sta utoa16w.dst
lda #>$400
sta utoa16w.dst+1
jsr utoa16w
inc bordercol inc bordercol
lda #<$400+$28
sta utoa10b.dst
lda #>$400+$28
sta utoa10b.dst+1
lda #<$4d2 lda #<$4d2
sta utoa10b.value sta utoa16w.value
lda #>$4d2 lda #>$4d2
sta utoa10b.value+1 sta utoa16w.value+1
jsr utoa10b lda #<$400+$28
sta utoa16w.dst
lda #>$400+$28
sta utoa16w.dst+1
jsr utoa16w
inc bordercol inc bordercol
lda #<$400+$28+$28
sta utoa10b.dst
lda #>$400+$28+$28
sta utoa10b.dst+1
lda #<$162e lda #<$162e
sta utoa10b.value sta utoa16w.value
lda #>$162e lda #>$162e
sta utoa10b.value+1 sta utoa16w.value+1
jsr utoa10b lda #<$400+$28+$28
sta utoa16w.dst
lda #>$400+$28+$28
sta utoa16w.dst+1
jsr utoa16w
inc bordercol inc bordercol
lda #<$400+$28+$28+$28
sta utoa10b.dst
lda #>$400+$28+$28+$28
sta utoa10b.dst+1
lda #<$270f lda #<$270f
sta utoa10b.value sta utoa16w.value
lda #>$270f lda #>$270f
sta utoa10b.value+1 sta utoa16w.value+1
jsr utoa10b lda #<$400+$28+$28+$28
sta utoa16w.dst
lda #>$400+$28+$28+$28
sta utoa16w.dst+1
jsr utoa16w
inc bordercol inc bordercol
lda #<$400+$28+$28+$28+$28
sta utoa10b.dst
lda #>$400+$28+$28+$28+$28
sta utoa10b.dst+1
lda #<$e608 lda #<$e608
sta utoa10b.value sta utoa16w.value
lda #>$e608 lda #>$e608
sta utoa10b.value+1 sta utoa16w.value+1
jsr utoa10b lda #<$400+$28+$28+$28+$28
sta utoa16w.dst
lda #>$400+$28+$28+$28+$28
sta utoa16w.dst+1
jsr utoa16w
ldx raster ldx raster
lda #0 lda #0
sta bordercol sta bordercol
txa txa
sec sec
sbc time_start sbc time_start
sta utoa10b.value sta utoa10w.value
lda #0 lda #0
sta utoa10b.value+1 sta utoa10w.value+1
lda #<$400+$28+$28+$28+$28+$50 jsr utoa10w
sta utoa10b.dst
lda #>$400+$28+$28+$28+$28+$50
sta utoa10b.dst+1
jsr utoa10b
ldx #0 ldx #0
b3: b3:
lda msg,x lda msg,x
@ -97,12 +95,16 @@ main: {
msg: .text "raster lines@" msg: .text "raster lines@"
} }
// Decimal utoa() without using multiply or divide // Decimal utoa() without using multiply or divide
// utoa10b(word zeropage(2) value, byte* zeropage(6) dst) // utoa10w(word zeropage(2) value, byte* zeropage(6) dst)
utoa10b: { utoa10w: {
.label value = 2 .label value = 2
.label digit = 4 .label digit = 4
.label dst = 6 .label dst = 6
.label bStarted = 5 .label bStarted = 5
lda #<$400+$28+$28+$28+$28+$50
sta dst
lda #>$400+$28+$28+$28+$28+$50
sta dst+1
lda #0 lda #0
sta bStarted sta bStarted
sta digit sta digit
@ -111,10 +113,10 @@ utoa10b: {
txa txa
asl asl
tay tay
lda SUB+1,y lda UTOA10_SUB+1,y
cmp value+1 cmp value+1
bne !+ bne !+
lda SUB,y lda UTOA10_SUB,y
cmp value cmp value
beq b2 beq b2
!: !:
@ -155,7 +157,7 @@ utoa10b: {
sta (dst),y sta (dst),y
rts rts
b2: b2:
lda VAL,x lda UTOA10_VAL,x
clc clc
adc digit adc digit
sta digit sta digit
@ -164,15 +166,72 @@ utoa10b: {
tay tay
sec sec
lda value lda value
sbc SUB,y sbc UTOA10_SUB,y
sta value sta value
lda value+1 lda value+1
sbc SUB+1,y sbc UTOA10_SUB+1,y
sta value+1 sta value+1
lda #1 lda #1
sta bStarted sta bStarted
jmp b1 jmp b1
} }
// Hexadecimal utoa() for an unsigned int (16bits)
// utoa16w(word zeropage(6) value, byte* zeropage(2) dst)
utoa16w: {
.label dst = 2
.label value = 6
lda value+1
lsr
lsr
lsr
lsr
tax
lda #0
sta utoa16_started
jsr utoa16n
lda value+1
ldx #$f
axs #0
jsr utoa16n
lda value
lsr
lsr
lsr
lsr
tax
jsr utoa16n
lda value
ldx #$f
axs #0
lda #1
sta utoa16_started
jsr utoa16n
lda #0
tay
sta (utoa16_dst),y
rts
}
// Hexadecimal utoa() for a single nybble
// utoa16n(byte register(X) nybble)
utoa16n: {
cpx #0
beq b1
lda #1
sta utoa16_started
b1:
lda utoa16_started
cmp #0
beq breturn
lda DIGITS,x
ldy #0
sta (utoa16_dst),y
inc utoa16_dst
bne !+
inc utoa16_dst+1
!:
breturn:
rts
}
cls: { cls: {
.label screen = $400 .label screen = $400
.label sc = 2 .label sc = 2
@ -196,6 +255,9 @@ cls: {
bne b1 bne b1
rts rts
} }
// Digits used for utoa()
DIGITS: .text "0123456789abcdef@" DIGITS: .text "0123456789abcdef@"
SUB: .word $7530, $2710, $bb8, $3e8, $12c, $64, $1e, $a // Subtraction values used for decimal utoa()
VAL: .byte 3, 1, 3, 1, 3, 1, 3, 1 UTOA10_SUB: .word $7530, $2710, $bb8, $3e8, $12c, $64, $1e, $a
// Digit addition values used for decimal utoa()
UTOA10_VAL: .byte 3, 1, 3, 1, 3, 1, 3, 1