This commit is contained in:
Irmen de Jong 2019-01-19 16:00:30 +01:00
parent 75b38d7b84
commit 25e44a54fb
12 changed files with 267 additions and 216 deletions

31
build_the_compiler.sh Executable file
View File

@ -0,0 +1,31 @@
#!/usr/bin/env bash
echo "Compiling the parser..."
java -jar ./parser/antlr/lib/antlr-4.7.2-complete.jar -o ./parser/src/prog8/parser -Xexact-output-dir -no-listener -no-visitor -package prog8.parser ./parser/antlr/prog8.g4
PARSER_CLASSES=./out/production/parser
COMPILER_JAR=prog8compiler.jar
ANTLR_RUNTIME=./parser/antlr/lib/antlr-runtime-4.7.2.jar
mkdir -p ${PARSER_CLASSES}
javac -d ${PARSER_CLASSES} -cp ${ANTLR_RUNTIME} ./parser/src/prog8/parser/prog8Lexer.java ./parser/src/prog8/parser/prog8Parser.java
echo "Compiling the compiler itself..."
kotlinc -verbose -include-runtime -d ${COMPILER_JAR} -cp ${ANTLR_RUNTIME}:${PARSER_CLASSES} ./compiler/src/prog8
echo "Finalizing the compiler jar file..."
# add the antlr parser classes
jar ufe ${COMPILER_JAR} prog8.CompilerMainKt -C ${PARSER_CLASSES} prog8
# add the resources
jar uf ${COMPILER_JAR} -C ./compiler/res .
# add the antlr runtime classes
rm -rf antlr_runtime_extraction
mkdir antlr_runtime_extraction
(cd antlr_runtime_extraction; jar xf ../${ANTLR_RUNTIME})
jar uf ${COMPILER_JAR} -C antlr_runtime_extraction org
rm -rf antlr_runtime_extraction
echo "Done!"

View File

@ -1,13 +0,0 @@
#!/usr/bin/env bash
java -jar ../antlr/lib/antlr-4.7.2-complete.jar -o ./prog8/parser -Xexact-output-dir -no-listener -no-visitor -package prog8.parser ../antlr/prog8.g4
find prog8 -name \*.java > javasources.txt
mkdir -p compiled_java
javac -verbose -d compiled_java -cp ../antlr/lib/antlr-runtime-4.7.2.jar @javasources.txt
rm javasources.txt
KOTLINC="bash ${HOME}/.IntelliJIdea2018.3/config/plugins/Kotlin/kotlinc/bin/kotlinc"
${KOTLINC} -verbose -include-runtime -d prog8_kotlin.jar -cp ../antlr/lib/antlr-runtime-4.7.2.jar:compiled_java prog8
jar uf prog8_kotlin.jar -C compiled_java prog8

View File

@ -8,6 +8,7 @@ import prog8.optimizing.optimizeStatements
import prog8.optimizing.simplifyExpressions
import prog8.parser.ParsingFailedError
import prog8.parser.importModule
import prog8.stackvm.StackVm
import java.io.File
import java.io.PrintStream
import java.lang.Exception
@ -17,6 +18,15 @@ import kotlin.system.measureTimeMillis
fun main(args: Array<String>) {
// check if the user wants to launch the VM instead
if("--vm" in args) {
val newArgs = args.toMutableList()
newArgs.remove("--vm")
return stackVmMain(newArgs.toTypedArray())
}
println("\nProg8 compiler by Irmen de Jong (irmen@razorvine.net)")
// @todo software license string
// println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n")
@ -169,7 +179,7 @@ private fun compileMain(args: Array<String>) {
if(startEmu) {
println("\nStarting C64 emulator...")
val cmdline = listOf("x64", "-silent", "-moncommands", "$programname.vice-mon-list",
val cmdline = listOf("x64sc", "-silent", "-moncommands", "$programname.vice-mon-list",
"-autostartprgmode", "1", "-autostart-warp", "-autostart", programname+".prg")
val process = ProcessBuilder(cmdline).inheritIO().start()
process.waitFor()
@ -180,6 +190,7 @@ private fun usage() {
System.err.println("Missing argument(s):")
System.err.println(" [--emu] auto-start the C64 emulator after successful compilation")
System.err.println(" [--asmtrace] print trace output of the AsmGen for debugging purposes")
System.err.println(" [--vm] launch the prog8 virtual machine instead of the compiler")
System.err.println(" modulefile main module file to compile")
exitProcess(1)
}

View File

@ -6,6 +6,10 @@ import javax.swing.Timer
import kotlin.system.exitProcess
fun main(args: Array<String>) {
stackVmMain(args)
}
fun stackVmMain(args: Array<String>) {
println("\nProg8 StackVM by Irmen de Jong (irmen@razorvine.net)")
// @todo decide on software license
// println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n")

View File

@ -398,7 +398,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
if(continueStmtLabelStack.empty())
throw CompilerException("continue outside of loop statement block")
val label = continueStmtLabelStack.peek()
prog.instr(Opcode.JUMP, null, label)
prog.instr(Opcode.JUMP, callLabel = label)
}
private fun translate(stmt: Break) {
@ -406,7 +406,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
if(breakStmtLabelStack.empty())
throw CompilerException("break outside of loop statement block")
val label = breakStmtLabelStack.peek()
prog.instr(Opcode.JUMP, null, label)
prog.instr(Opcode.JUMP, callLabel = label)
}
private fun translate(branch: BranchStatement) {
@ -930,7 +930,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
}
private fun StatementTranslator.translateSwap(args: List<IExpression>) {
private fun translateSwap(args: List<IExpression>) {
// swap(x,y) is treated differently, it's not a normal function call
if (args.size != 2)
throw AstException("swap requires 2 arguments")
@ -940,65 +940,49 @@ private class StatementTranslator(private val prog: IntermediateProgram,
throw AstException("swap requires 2 args of identical type")
if (args[0].constValue(namespace, heap) != null || args[1].constValue(namespace, heap) != null)
throw AstException("swap requires 2 variables, not constant value(s)")
if (dt1 !in NumericDatatypes)
throw AstException("swap requires args of numerical type")
if(same(args[0], args[1]))
throw AstException("swap should have 2 different args")
if(dt1 !in NumericDatatypes)
throw AstException("swap requires args of numerical type")
// @todo implement these errors as nice AstChecker expression errors.
// @todo implement the above errors as nice AstChecker expression errors.
// @todo implement this more efficiently with using the xor trick instead of the stack!
// Swap(X,Y) :=
// eor trick: Swap(X,Y) :=
// X ^= Y
// Y ^= X
// X ^= Y
// for floats, this doesn't work, use a temp variable instead.
// this trick is used when we're dealing with: (u)byte or (u)word variables, ... @todo
// pop first then second arg
translate(args[0])
translate(args[1])
// pop stack in reverse order
when {
args[0] is IdentifierReference -> {
val target = AssignTarget(null, args[0] as IdentifierReference, null, null, args[0].position)
popValueIntoTarget(target, dt1)
}
args[0] is RegisterExpr -> {
val target = AssignTarget((args[0] as RegisterExpr).register, null, null, null, args[0].position)
popValueIntoTarget(target, dt1)
}
args[0] is ArrayIndexedExpression -> {
val target = AssignTarget(null, null, args[0] as ArrayIndexedExpression, null, args[0].position)
popValueIntoTarget(target, dt1)
}
args[0] is DirectMemoryRead -> {
val target = AssignTarget(null, null, null, DirectMemoryWrite((args[0] as DirectMemoryRead).addressExpression, args[0].position), args[0].position)
popValueIntoTarget(target, dt1)
}
else -> TODO("unpop type ${args[0]}")
}
when {
args[1] is IdentifierReference -> {
val target = AssignTarget(null, args[1] as IdentifierReference, null, null, args[1].position)
popValueIntoTarget(target, dt2)
}
args[1] is RegisterExpr -> {
val target = AssignTarget((args[1] as RegisterExpr).register, null, null, null, args[1].position)
popValueIntoTarget(target, dt2)
}
args[1] is ArrayIndexedExpression -> {
val target = AssignTarget(null, null, args[1] as ArrayIndexedExpression, null, args[1].position)
popValueIntoTarget(target, dt2)
}
args[1] is DirectMemoryRead -> {
val target = AssignTarget(null, null, null, DirectMemoryWrite((args[1] as DirectMemoryRead).addressExpression, args[1].position), args[1].position)
popValueIntoTarget(target, dt2)
}
else -> TODO("unpop type ${args[1]}")
if(useEorTrickForSwap(dt1, args[0], args[1])) {
val xEorY = BinaryExpression(args[0], "^", args[1], args[0].position)
val yEorX = BinaryExpression(args[1], "^", args[0], args[1].position)
val xIsXeorY = Assignment(listOf(AssignTarget.fromExpr(args[0])), null, xEorY, args[0].position)
val yIsYeorX = Assignment(listOf(AssignTarget.fromExpr(args[1])), null, yEorX, args[1].position)
xIsXeorY.linkParents(args[0].parent)
yIsYeorX.linkParents(args[0].parent)
translate(xIsXeorY)
translate(yIsYeorX)
translate(xIsXeorY)
} else {
translate(args[0])
translate(args[1])
// pop in reverse order
popValueIntoTarget(AssignTarget.fromExpr(args[0]), dt1)
popValueIntoTarget(AssignTarget.fromExpr(args[1]), dt2)
}
return
}
private fun useEorTrickForSwap(dt: DataType, expr1: IExpression, expr2: IExpression): Boolean {
if(dt in IntegerDatatypes) {
if (expr1 is IdentifierReference && expr2 is IdentifierReference)
return true
if(expr1 is ArrayIndexedExpression && expr2 is ArrayIndexedExpression) {
return expr1.arrayspec.x is LiteralValue && expr2.arrayspec.x is LiteralValue
}
}
return false
}
private fun translateSubroutineCall(subroutine: Subroutine, arguments: List<IExpression>, callPosition: Position) {
// evaluate the arguments and assign them into the subroutine's argument variables.
var restoreX = Register.X in subroutine.asmClobbers
@ -1441,7 +1425,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
}
prog.line(stmt.position)
prog.instr(branchOpcode ?: Opcode.JUMP, jumpAddress, jumpLabel)
prog.instr(branchOpcode ?: Opcode.JUMP, jumpAddress, callLabel = jumpLabel)
}
private fun translate(stmt: PostIncrDecr) {
@ -1544,28 +1528,8 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
}
if(stmt.aug_op!=null) {
// augmented assignment
when {
assignTarget.identifier != null -> {
val target = assignTarget.identifier.targetStatement(namespace)!!
when(target) {
is VarDecl -> {
val opcode = opcodePushvar(assignTarget.determineDatatype(namespace, heap, stmt)!!)
prog.instr(opcode, callLabel = target.scopedname)
}
else -> throw CompilerException("invalid assignment target type ${target::class}")
}
}
assignTarget.register != null -> prog.instr(Opcode.PUSH_VAR_BYTE, callLabel = assignTarget.register.toString())
assignTarget.arrayindexed != null -> translate(assignTarget.arrayindexed, false)
assignTarget.memoryAddress != null -> {
TODO("translate aug assign on memory address $stmt")
}
}
translateAugAssignOperator(stmt.aug_op, stmt.value.resultingDatatype(namespace, heap))
}
if(stmt.aug_op!=null)
throw CompilerException("augmented assignment should have been converted to regular assignment already")
if(stmt.value is FunctionCall) {
val sub = (stmt.value as FunctionCall).target.targetStatement(namespace)
@ -1708,82 +1672,6 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
}
private fun translateAugAssignOperator(aug_op: String, valueDt: DataType?) { // @todo: not used in practice? (all augassigns are converted to normal assigns)
if(valueDt==null)
throw CompilerException("value datatype not known")
val validDt = setOf(DataType.UBYTE, DataType.UWORD, DataType.FLOAT)
if(valueDt !in validDt)
throw CompilerException("invalid datatype(s) for operand(s)")
val opcode = when(aug_op) {
// @todo ... need more datatypes here?
"+=" -> {
when (valueDt) {
DataType.UBYTE -> Opcode.ADD_UB
DataType.UWORD -> Opcode.ADD_UW
DataType.FLOAT -> Opcode.ADD_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
"-=" -> {
when (valueDt) {
DataType.UBYTE -> Opcode.SUB_UB
DataType.UWORD -> Opcode.SUB_UW
DataType.FLOAT -> Opcode.SUB_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
"/=" -> {
when (valueDt) {
DataType.UBYTE -> Opcode.IDIV_UB
DataType.BYTE -> Opcode.IDIV_B
DataType.UWORD -> Opcode.IDIV_UW
DataType.WORD -> Opcode.IDIV_W
DataType.FLOAT -> Opcode.DIV_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
"*=" -> {
when (valueDt) {
DataType.UBYTE -> Opcode.MUL_UB
DataType.UWORD -> Opcode.MUL_UW
DataType.FLOAT -> Opcode.MUL_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
"**=" -> {
when (valueDt) {
DataType.UBYTE -> Opcode.POW_UB
DataType.UWORD -> Opcode.POW_UW
DataType.FLOAT -> Opcode.POW_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
"&=" -> {
when(valueDt) {
DataType.UBYTE, DataType.BYTE -> Opcode.BITAND_BYTE
DataType.UWORD, DataType.WORD -> Opcode.BITAND_WORD
else -> throw CompilerException("only byte/word possible")
}
}
"|=" -> {
when(valueDt) {
DataType.UBYTE, DataType.BYTE -> Opcode.BITOR_BYTE
DataType.UWORD, DataType.WORD -> Opcode.BITOR_WORD
else -> throw CompilerException("only byte/word possible")
}
}
"^=" -> {
when(valueDt) {
DataType.UBYTE, DataType.BYTE -> Opcode.BITXOR_BYTE
DataType.UWORD, DataType.WORD -> Opcode.BITXOR_WORD
else -> throw CompilerException("only byte/word possible")
}
}
else -> throw CompilerException("invalid aug assignment operator $aug_op")
}
prog.instr(opcode)
}
private fun translate(stmt: Return) {
// put the return values on the stack, in reversed order. The caller will process them.
for(value in stmt.values.reversed()) {

View File

@ -345,8 +345,8 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
}
}
fun instr(opcode: Opcode, arg: Value? = null, callLabel: String? = null) {
currentBlock.instructions.add(Instruction(opcode, arg, callLabel = callLabel))
fun instr(opcode: Opcode, arg: Value? = null, arg2: Value? = null, callLabel: String? = null, callLabel2: String? = null) {
currentBlock.instructions.add(Instruction(opcode, arg, arg2, callLabel, callLabel2))
}
fun label(labelname: String, asmProc: Boolean=false) {

View File

@ -195,7 +195,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
vardecls2asm(block)
out("")
val instructionPatternWindowSize = 6 // increase once patterns occur longer than this.
val instructionPatternWindowSize = 7 // increase once patterns occur longer than this.
var processed = 0
if(trace) println("BLOCK: ${block.scopedname} ${block.address ?: ""}")
@ -203,9 +203,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
if(trace) println("\t${ins[0].toString().trim()}")
if (processed == 0) {
processed = instr2asm(ins)
if (processed == 0)
// the instructions are not recognised yet and can't be translated into assembly
if (processed == 0) {
// the instructions are not recognised yet and can't be translated into assembly
throw CompilerException("no asm translation found for instruction pattern: $ins")
}
}
processed--
}
@ -3050,6 +3051,91 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
dex
"""
},
// push var byte & var byte
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.BITAND_BYTE, Opcode.POP_VAR_BYTE)) { segment ->
"""
lda ${segment[0].callLabel}
and ${segment[1].callLabel}
sta ${segment[3].callLabel}
"""
},
// push var byte | var byte
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.BITOR_BYTE, Opcode.POP_VAR_BYTE)) { segment ->
"""
lda ${segment[0].callLabel}
ora ${segment[1].callLabel}
sta ${segment[3].callLabel}
"""
},
// push var byte ^ var byte
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.BITXOR_BYTE, Opcode.POP_VAR_BYTE)) { segment ->
"""
lda ${segment[0].callLabel}
eor ${segment[1].callLabel}
sta ${segment[3].callLabel}
"""
},
// push var word & var word
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_VAR_WORD, Opcode.BITAND_WORD, Opcode.POP_VAR_WORD)) { segment ->
"""
lda ${segment[0].callLabel}
and ${segment[1].callLabel}
sta ${segment[3].callLabel}
lda ${segment[0].callLabel}+1
and ${segment[1].callLabel}+1
sta ${segment[3].callLabel}+1
"""
},
// push var word | var word
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_VAR_WORD, Opcode.BITOR_WORD, Opcode.POP_VAR_WORD)) { segment ->
"""
lda ${segment[0].callLabel}
ora ${segment[1].callLabel}
sta ${segment[3].callLabel}
lda ${segment[0].callLabel}+1
ora ${segment[1].callLabel}+1
sta ${segment[3].callLabel}+1
"""
},
// push var word ^ var word
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_VAR_WORD, Opcode.BITXOR_WORD, Opcode.POP_VAR_WORD)) { segment ->
"""
lda ${segment[0].callLabel}
eor ${segment[1].callLabel}
sta ${segment[3].callLabel}
lda ${segment[0].callLabel}+1
eor ${segment[1].callLabel}+1
sta ${segment[3].callLabel}+1
"""
},
// bytearray[consti3] = bytearray[consti1] ^ bytearray[consti2]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE,
Opcode.BITXOR_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment ->
val i1 = segment[5].arg!!.integerValue()
val i2 = segment[0].arg!!.integerValue()
val i3 = segment[2].arg!!.integerValue()
"""
lda ${segment[1].callLabel}+$i2
eor ${segment[3].callLabel}+$i3
sta ${segment[6].callLabel}+$i1
"""
},
// warray[consti3] = warray[consti1] ^ warray[consti2]
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD,
Opcode.BITXOR_WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
val i1 = segment[5].arg!!.integerValue()*2
val i2 = segment[0].arg!!.integerValue()*2
val i3 = segment[2].arg!!.integerValue()*2
"""
lda ${segment[1].callLabel}+$i2
eor ${segment[3].callLabel}+$i3
sta ${segment[6].callLabel}+$i1
lda ${segment[1].callLabel}+${i2+1}
eor ${segment[3].callLabel}+${i3+1}
sta ${segment[6].callLabel}+${i1+1}
"""
},
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.MKWORD)) { segment ->
"""

View File

@ -1,21 +1,30 @@
package prog8.compiler.target.c64
import prog8.compiler.toHex
fun optimizeAssembly(lines: MutableList<String>): Int {
var numberOfOptimizations = 0
var linesByTwo = getLinesBy(lines, 2)
var linesByFour = getLinesBy(lines, 4)
var removeLines = optimizeIncDec(linesByTwo)
var removeLines = optimizeUselessStackByteWrites(linesByFour)
if(removeLines.isNotEmpty()) {
for (i in removeLines.reversed())
lines.removeAt(i)
linesByTwo = getLinesBy(lines, 2)
linesByFour = getLinesBy(lines, 4)
numberOfOptimizations++
}
removeLines = optimizeStoreLoadSame(linesByTwo)
removeLines = optimizeIncDec(linesByFour)
if(removeLines.isNotEmpty()) {
for (i in removeLines.reversed())
lines.removeAt(i)
linesByFour = getLinesBy(lines, 4)
numberOfOptimizations++
}
removeLines = optimizeStoreLoadSame(linesByFour)
if(removeLines.isNotEmpty()) {
for (i in removeLines.reversed())
lines.removeAt(i)
@ -33,6 +42,24 @@ fun optimizeAssembly(lines: MutableList<String>): Int {
return numberOfOptimizations
}
fun optimizeUselessStackByteWrites(linesByFour: List<List<IndexedValue<String>>>): List<Int> {
// sta on stack, dex, inx, lda from stack -> eliminate this useless stack byte write
// this is a lot harder for word values because the instruction sequence varies.
val removeLines = mutableListOf<Int>()
for(lines in linesByFour) {
if(lines[0].value.trim()=="sta ${ESTACK_LO.toHex()},x" &&
lines[1].value.trim()=="dex" &&
lines[2].value.trim()=="inx" &&
lines[3].value.trim()=="lda ${ESTACK_LO.toHex()},x") {
removeLines.add(lines[0].index)
removeLines.add(lines[1].index)
removeLines.add(lines[2].index)
removeLines.add(lines[3].index)
}
}
return removeLines
}
fun optimizeSameAssignments(linesByFourteen: List<List<IndexedValue<String>>>): List<Int> {
// optimize sequential assignments of the same value to various targets (bytes, words, floats)
@ -102,10 +129,10 @@ private fun getLinesBy(lines: MutableList<String>, windowSize: Int) =
// all lines (that aren't empty or comments) in sliding pairs of 2
lines.withIndex().filter { it.value.isNotBlank() && !it.value.trimStart().startsWith(';') }.windowed(windowSize, partialWindows = false)
private fun optimizeStoreLoadSame(linesByTwo: List<List<IndexedValue<String>>>): List<Int> {
private fun optimizeStoreLoadSame(linesByFour: List<List<IndexedValue<String>>>): List<Int> {
// sta X + lda X, sty X + ldy X, stx X + ldx X -> the second instruction can be eliminated
val removeLines = mutableListOf<Int>()
for (pair in linesByTwo) {
for (pair in linesByFour) {
val first = pair[0].value.trimStart()
val second = pair[1].value.trimStart()

View File

@ -1,54 +1,71 @@
%import c64utils
%import c64flt
~ main {
sub start() {
word[8] rotatedx = [11,33,55,77,22,44,66,88]
word[8] rotatedy = [11,33,55,77,22,44,66,88]
word[8] rotatedz = [1,3,-5,7,2,4,-6,8]
ubyte ub1
ubyte ub2
byte b1
byte b2
uword uw1
uword uw2
word w1
word w2
printarray()
ubyte[3] uba
byte[3] ba
uword[3] uwa
word[3] wa
c64scr.print_ub(X)
c64.CHROUT('\n')
; ub1 = ub2 & 44
; b1 = b2 & 44
; uw1 = uw2 & 4444
; w1 = w2 & 4444
; ub1 = ub2 | 44
; b1 = b2 | 44
; uw1 = uw2 | 4444
; w1 = w2 | 4444
; ub1 = ub2 ^ 44
; b1 = b2 ^ 44
; uw1 = uw2 ^ 4444
; w1 = w2 ^ 4444
;
; ub1 = ub2 & ub1
; b1 = b2 & b1
; uw1 = uw2 & uw1
; w1 = w2 & w1
; ub1 = ub2 | ub1
; b1 = b2 | b1
; uw1 = uw2 | uw1
; w1 = w2 | w1
; ub1 = ub2 ^ ub1
; b1 = b2 ^ b1
; uw1 = uw2 ^ uw1
; w1 = w2 ^ w1
for ubyte sorti in 6 to 0 step -1 {
for ubyte i1 in 0 to sorti {
ubyte i2=i1+1
if(rotatedz[i2]>rotatedz[i1]) {
swap(rotatedx[i1], rotatedx[i2])
swap(rotatedy[i1], rotatedy[i2])
swap(rotatedz[i1], rotatedz[i2])
}
}
}
swap(ub1, ub2)
swap(b1, b2)
swap(uw1, uw2)
swap(w1, w2)
c64scr.print_ub(X)
c64.CHROUT('\n')
swap(uba[0], uba[1])
swap(ba[0], ba[1])
swap(uwa[0], uwa[1])
swap(wa[0], wa[1])
printarray()
; this goes without xor trick:
ubyte i1
ubyte i2
swap(uba[i1], uba[i2])
swap(ba[i1], ba[i2])
swap(uwa[i1], uwa[i2])
swap(wa[i1], wa[i2])
sub printarray() {
for word a in rotatedx {
c64scr.print_w(a)
c64.CHROUT(',')
}
c64.CHROUT('\n')
for word a in rotatedy {
c64scr.print_w(a)
c64.CHROUT(',')
}
c64.CHROUT('\n')
for word a in rotatedz {
c64scr.print_w(a)
c64.CHROUT(',')
}
c64.CHROUT('\n')
c64.CHROUT('\n')
}
swap(uba[1], ub1)
swap(uba[i1], ub1)
swap(uwa[1], uw1)
swap(uwa[i1], uw1)
}

View File

@ -1,4 +1,4 @@
// Generated from /home/irmen/Projects/prog8/parser/antlr/prog8.g4 by ANTLR 4.7.2
// Generated from ./parser/antlr/prog8.g4 by ANTLR 4.7.2
package prog8.parser;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream;

View File

@ -1,4 +1,4 @@
// Generated from /home/irmen/Projects/prog8/parser/antlr/prog8.g4 by ANTLR 4.7.2
// Generated from ./parser/antlr/prog8.g4 by ANTLR 4.7.2
package prog8.parser;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;