1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-12-27 09:31:18 +00:00

Added initial support for special BYTE0() and BYTE1() unary operators giving access to specific bytes. #221

This commit is contained in:
jespergravgaard 2021-04-05 00:27:47 +02:00
parent d8cd73115a
commit 1d4e754f0e
68 changed files with 280 additions and 19563 deletions

View File

@ -7,9 +7,18 @@
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value>
<package name="java.util" withSubpackages="false" static="false" />
<package name="kotlinx.android.synthetic" withSubpackages="true" static="false" />
<package name="io.ktor" withSubpackages="true" static="false" />
<package name="java.util" alias="false" withSubpackages="false" />
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
<package name="io.ktor" alias="false" withSubpackages="true" />
</value>
</option>
<option name="PACKAGES_IMPORT_LAYOUT">
<value>
<package name="" alias="false" withSubpackages="true" />
<package name="java" alias="false" withSubpackages="true" />
<package name="javax" alias="false" withSubpackages="true" />
<package name="kotlin" alias="false" withSubpackages="true" />
<package name="" alias="true" withSubpackages="true" />
</value>
</option>
</JetCodeStyleSettings>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
lda {m1}

View File

@ -0,0 +1 @@
txa

View File

@ -0,0 +1 @@
tya

View File

@ -0,0 +1 @@
txa

View File

@ -0,0 +1 @@
tya

View File

@ -0,0 +1 @@
lda {m1}

View File

@ -0,0 +1 @@
lda {m1}

View File

@ -0,0 +1 @@
lda {m1}

View File

@ -0,0 +1 @@
lda {m1}

View File

@ -0,0 +1 @@
lda {m1}+1

View File

@ -0,0 +1 @@
lda #0

View File

@ -0,0 +1 @@
lda #0

View File

@ -0,0 +1 @@
lda #0

View File

@ -0,0 +1 @@
lda #0

View File

@ -0,0 +1 @@
lda #0

View File

@ -0,0 +1 @@
lda #0

View File

@ -0,0 +1 @@
lda #0

View File

@ -0,0 +1 @@
lda #0

View File

@ -0,0 +1 @@
lda {m1}+1

View File

@ -0,0 +1 @@
lda {m1}+1

View File

@ -0,0 +1 @@
lda {m1}+1

View File

@ -0,0 +1 @@
lda {m1}+1

View File

@ -0,0 +1 @@
ldx {m1}

View File

@ -0,0 +1 @@
tax

View File

@ -0,0 +1 @@
tax

View File

@ -0,0 +1 @@
ldx {m1}

View File

@ -0,0 +1 @@
ldx {m1}

View File

@ -0,0 +1 @@
ldx {m1}

View File

@ -0,0 +1 @@
ldx {m1}

View File

@ -0,0 +1 @@
ldx {m1}+1

View File

@ -0,0 +1 @@
ldx #0

View File

@ -0,0 +1 @@
ldx #0

View File

@ -0,0 +1 @@
ldx #0

View File

@ -0,0 +1 @@
ldx #0

View File

@ -0,0 +1 @@
ldx {m1}+1

View File

@ -0,0 +1 @@
ldx {m1}+1

View File

@ -0,0 +1 @@
ldx {m1}+1

View File

@ -0,0 +1 @@
ldx {m1}+1

View File

@ -0,0 +1 @@
ldy {m1}

View File

@ -0,0 +1 @@
tay

View File

@ -0,0 +1 @@
tay

View File

@ -0,0 +1 @@
ldy {m1}

View File

@ -0,0 +1 @@
ldy {m1}

View File

@ -0,0 +1 @@
ldy {m1}

View File

@ -0,0 +1 @@
ldy {m1}

View File

@ -0,0 +1 @@
ldy {m1}+1

View File

@ -0,0 +1 @@
ldy #0

View File

@ -0,0 +1 @@
ldy #0

View File

@ -0,0 +1 @@
ldy #0

View File

@ -0,0 +1 @@
ldy #0

View File

@ -0,0 +1 @@
ldy {m1}+1

View File

@ -0,0 +1 @@
ldy {m1}+1

View File

@ -0,0 +1 @@
ldy {m1}+1

View File

@ -0,0 +1 @@
ldy {m1}+1

View File

@ -231,6 +231,7 @@ public class Compiler {
getLog().append(program.getGraph().toString(program));
}
new Pass1ResolveForwardReferences(program).execute();
new Pass1ByteXIntrinsicRewrite(program).execute();
new Pass1AssertProcedureDefined(program).execute();
new Pass1AssertVariableDefined(program).execute();
new PassNAssertStructMembers(program).execute();

View File

@ -212,6 +212,10 @@ public class AsmFormat {
} else {
throw new CompileError("Operator _hi_ cannot handle " + operand.toString(program));
}
} else if(Operators.BYTE0.equals(operator)) {
return operator.getOperator() + "(" + getAsmConstant(program, operand, operator.getPrecedence(), codeScope) + ")";
} else if(Operators.BYTE1.equals(operator)) {
return operator.getOperator() + "(" + getAsmConstant(program, operand, operator.getPrecedence(), codeScope) + ")";
} else if(Operators.INCREMENT.equals(operator)) {
return getAsmConstant(program, new ConstantBinary(operand, Operators.PLUS, new ConstantInteger((long) 1)), outerPrecedence, codeScope);
} else if(Operators.DECREMENT.equals(operator)) {

View File

@ -0,0 +1,37 @@
package dk.camelot64.kickc.model.operators;
import dk.camelot64.kickc.model.ConstantNotLiteral;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.ConstantInteger;
import dk.camelot64.kickc.model.values.ConstantLiteral;
import dk.camelot64.kickc.model.values.ConstantPointer;
import dk.camelot64.kickc.model.values.ConstantString;
/** Unary get byte 0 operator byte0(x) */
public class OperatorGetByte0 extends OperatorUnary {
public OperatorGetByte0(int precedence) {
super("<", "_byte0_", precedence);
}
@Override
public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) {
if(operand instanceof ConstantInteger) {
ConstantInteger operandInt = (ConstantInteger) operand;
return new ConstantInteger(operandInt.getInteger() & 0xff, SymbolType.BYTE);
} else if(operand instanceof ConstantPointer) {
return new ConstantInteger(((ConstantPointer) operand).getLocation() & 0xff, SymbolType.BYTE);
} else if(operand instanceof ConstantString) {
throw ConstantNotLiteral.getException();
}
throw ConstantNotLiteral.getException();
}
@Override
public SymbolType inferType(SymbolType operandType) {
return SymbolType.BYTE;
}
}

View File

@ -0,0 +1,37 @@
package dk.camelot64.kickc.model.operators;
import dk.camelot64.kickc.model.ConstantNotLiteral;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.ConstantInteger;
import dk.camelot64.kickc.model.values.ConstantLiteral;
import dk.camelot64.kickc.model.values.ConstantPointer;
import dk.camelot64.kickc.model.values.ConstantString;
/** Unary get byte 1 operator byte1(x) */
public class OperatorGetByte1 extends OperatorUnary {
public OperatorGetByte1(int precedence) {
super(">", "_byte1_", precedence);
}
@Override
public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) {
if(operand instanceof ConstantInteger) {
ConstantInteger operandInt = (ConstantInteger) operand;
return new ConstantInteger((operandInt.getInteger()>>8)&0xff, SymbolType.BYTE);
} else if(operand instanceof ConstantPointer) {
return new ConstantInteger((((ConstantPointer) operand).getLocation()>>8) & 0xff, SymbolType.BYTE);
} else if(operand instanceof ConstantString) {
throw ConstantNotLiteral.getException();
}
throw ConstantNotLiteral.getException();
}
@Override
public SymbolType inferType(SymbolType operandType) {
return SymbolType.BYTE;
}
}

View File

@ -40,6 +40,10 @@ public class Operators {
public static final OperatorBinary SHIFT_RIGHT = new OperatorShiftRight(5);
public static final OperatorUnary LOWBYTE = new OperatorGetLow(14);
public static final OperatorUnary HIBYTE = new OperatorGetHigh(14);
public static final OperatorUnary BYTE0 = new OperatorGetByte0(14);
public static final OperatorUnary BYTE1 = new OperatorGetByte1(14);
//public static final OperatorUnary BYTE2 = new OperatorGetByte2(14);
//public static final OperatorUnary BYTE3 = new OperatorGetByte3(14);
public static final OperatorBinary LT = new OperatorLessThan(7);
public static final OperatorBinary LE = new OperatorLessThanEqual(7);
public static final OperatorBinary GT = new OperatorGreaterThan(7);
@ -132,6 +136,14 @@ public class Operators {
return LOWBYTE;
case ">":
return HIBYTE;
case "b0":
return BYTE0;
//case "b1":
// return BYTE1;
//case "b2":
// return BYTE2;
//case "b3":
// return BYTE3;
case "&":
return ADDRESS_OF;
default:

View File

@ -5,6 +5,7 @@ import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeProcedure;
import dk.camelot64.kickc.model.values.ProcedureRef;
import dk.camelot64.kickc.passes.Pass1ByteXIntrinsicRewrite;
import dk.camelot64.kickc.passes.Pass1PrintfIntrinsicRewrite;
import java.util.*;
@ -36,7 +37,7 @@ public class Procedure extends Scope {
private boolean isConstructor;
/** The names of all legal intrinsic procedures. */
final public static List<String> INTRINSIC_PROCEDURES = Collections.singletonList(Pass1PrintfIntrinsicRewrite.INTRINSIC_PRINTF_NAME);
final public static List<String> INTRINSIC_PROCEDURES = Arrays.asList(Pass1PrintfIntrinsicRewrite.INTRINSIC_PRINTF_NAME, Pass1ByteXIntrinsicRewrite.INTRINSIC_BYTE0_NAME, Pass1ByteXIntrinsicRewrite.INTRINSIC_BYTE1_NAME );
/** The method for passing parameters and return value to the procedure. */
public enum CallingConvention {

View File

@ -0,0 +1,64 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.OperatorUnary;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.statements.StatementCall;
import dk.camelot64.kickc.model.values.RValue;
import java.util.List;
import java.util.ListIterator;
/**
* Rewrite BYTE0() / BYTE1() / BYTE2() / BYTE3() calls to special unary operators.
*/
public class Pass1ByteXIntrinsicRewrite extends Pass2SsaOptimization {
/** The byte0 procedure name. */
public static final String INTRINSIC_BYTE0_NAME = "BYTE0";
/** The byte1 procedure name. */
public static final String INTRINSIC_BYTE1_NAME = "BYTE1";
public Pass1ByteXIntrinsicRewrite(Program program) {
super(program);
}
@Override
public boolean step() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
final ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();
if(statement instanceof StatementCall) {
StatementCall call = (StatementCall) statement;
final List<RValue> parameters = call.getParameters();
if(INTRINSIC_BYTE0_NAME.equals(call.getProcedureName())) {
generateUnaryOperator(stmtIt, call, parameters, Operators.BYTE0);
} else if(INTRINSIC_BYTE1_NAME.equals(call.getProcedureName())) {
generateUnaryOperator(stmtIt, call, parameters, Operators.BYTE1);
}
}
}
}
return false;
}
/**
* Generate an unary operator expression for the BYTEX()
*/
private void generateUnaryOperator(ListIterator<Statement> stmtIt, StatementCall call, List<RValue> parameters, OperatorUnary operator) {
if(parameters.size()!=1) {
throw new CompileError("Wrong number of parameters in call " + call.toString(getProgram(), false) + " expected " + 1, call);
}
// Remove the call
stmtIt.remove();
// Add the unary byte0 operator
stmtIt.add(new StatementAssignment(call.getlValue(), operator, parameters.get(0), call.isInitialAssignment(), call.getSource(), call.getComments()));
}
}

View File

@ -44,6 +44,17 @@ public class TestPrograms {
public TestPrograms() {
}
@Test
public void testOperatorByte1() throws IOException, URISyntaxException {
compileAndCompare("operator-byte1.c", log());
}
@Test
public void testOperatorByte0() throws IOException, URISyntaxException {
compileAndCompare("operator-byte0.c", log());
}
@Test
public void testStdlibStringMemChr1() throws IOException, URISyntaxException {
compileAndCompare("stdlib-string-memchr-1.c");

View File

@ -0,0 +1,23 @@
// Test operator BYTE0()
void main() {
volatile unsigned char bu = 7;
volatile signed char bs = 7;
volatile unsigned int wu = 20000;
volatile signed int ws = -177;
volatile unsigned long du = 2000000;
volatile signed long ds = -3777777;
char * volatile ptr = 0x0000;
char * const SCREEN = 0x0400;
char i = 0;
SCREEN[i++] = BYTE0(17);
SCREEN[i++] = BYTE0(377);
SCREEN[i++] = BYTE0(bu);
SCREEN[i++] = BYTE0(bs);
SCREEN[i++] = BYTE0(wu);
SCREEN[i++] = BYTE0(ws);
SCREEN[i++] = BYTE0(du);
SCREEN[i++] = BYTE0(ds);
SCREEN[i++] = BYTE0(ptr);
}

View File

@ -0,0 +1,23 @@
// Test operator BYTE0()
void main() {
volatile unsigned char bu = 7;
volatile signed char bs = 7;
volatile unsigned int wu = 20000;
volatile signed int ws = -177;
volatile unsigned long du = 2000000;
volatile signed long ds = -3777777;
char * volatile ptr = 0x0000;
char * const SCREEN = 0x0400;
char i = 0;
SCREEN[i++] = BYTE1(17);
SCREEN[i++] = BYTE1(377);
SCREEN[i++] = BYTE1(bu);
SCREEN[i++] = BYTE1(bs);
SCREEN[i++] = BYTE1(wu);
SCREEN[i++] = BYTE1(ws);
SCREEN[i++] = BYTE1(du);
SCREEN[i++] = BYTE1(ds);
SCREEN[i++] = BYTE1(ptr);
}