mirror of
https://github.com/irmen/prog8.git
synced 2025-11-23 14:17:51 +00:00
implement missing long typecasts
This commit is contained in:
@@ -1620,7 +1620,17 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
else -> throw AssemblyError("invalid reg")
|
else -> throw AssemblyError("invalid reg")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TODO("msw(expression) ${fcall.position} - use a temporary variable for now")
|
asmgen.assignExpressionToRegister(arg, RegisterOrPair.R0R1_32, true)
|
||||||
|
when(resultRegister) {
|
||||||
|
RegisterOrPair.AX -> asmgen.out(" lda cx16.r1 | ldx cx16.r1+1")
|
||||||
|
null, RegisterOrPair.AY -> asmgen.out(" lda cx16.r1 | ldy cx16.r1+1")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" ldx cx16.r1 | ldy cx16.r1+1")
|
||||||
|
in Cx16VirtualRegisters -> {
|
||||||
|
val regname = resultRegister.name.lowercase()
|
||||||
|
asmgen.out(" lda cx16.r1 | sta cx16.$regname | lda cx16.r1+1 | sta cx16.$regname+1")
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("invalid reg")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1643,7 +1653,19 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
else -> throw AssemblyError("invalid reg")
|
else -> throw AssemblyError("invalid reg")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TODO("lsw(expression) ${fcall.position} - use a temporary variable for now")
|
asmgen.assignExpressionToRegister(arg, RegisterOrPair.R0R1_32, true)
|
||||||
|
when(resultRegister) {
|
||||||
|
RegisterOrPair.AX -> asmgen.out(" lda cx16.r0 | ldx cx16.r0+1")
|
||||||
|
null, RegisterOrPair.AY -> asmgen.out(" lda cx16.r0 | ldy cx16.r0+1")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" ldx cx16.r0 | ldy cx16.r0+1")
|
||||||
|
in Cx16VirtualRegisters -> {
|
||||||
|
if(resultRegister!=RegisterOrPair.R0) {
|
||||||
|
val regname = resultRegister.name.lowercase()
|
||||||
|
asmgen.out(" lda cx16.r0 | sta cx16.$regname | lda cx16.r0+1 | sta cx16.$regname+1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("invalid reg")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2455,7 +2455,7 @@ $endLabel""")
|
|||||||
is PtArrayIndexer -> {
|
is PtArrayIndexer -> {
|
||||||
if(targetDt.isByte && valueDt.isWord) {
|
if(targetDt.isByte && valueDt.isWord) {
|
||||||
// just assign the lsb from the array value
|
// just assign the lsb from the array value
|
||||||
return assignCastViaLsbFunc(value, target)
|
return assignCastWordViaLsbFunc(value, target)
|
||||||
} else if(targetDt.isBool && valueDt.isWord) {
|
} else if(targetDt.isBool && valueDt.isWord) {
|
||||||
return assignWordToBool(value, target)
|
return assignWordToBool(value, target)
|
||||||
}
|
}
|
||||||
@@ -2513,7 +2513,7 @@ $endLabel""")
|
|||||||
if(parentTc!=null && parentTc.type.isUnsignedWord) {
|
if(parentTc!=null && parentTc.type.isUnsignedWord) {
|
||||||
// typecast a word value to ubyte and directly back to uword
|
// typecast a word value to ubyte and directly back to uword
|
||||||
// generate code for lsb(value) here instead of the ubyte typecast
|
// generate code for lsb(value) here instead of the ubyte typecast
|
||||||
return assignCastViaLsbFunc(value, target)
|
return assignCastWordViaLsbFunc(value, target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2545,7 +2545,7 @@ $endLabel""")
|
|||||||
else
|
else
|
||||||
// cast an uword to a byte register, do this via lsb(value)
|
// cast an uword to a byte register, do this via lsb(value)
|
||||||
// generate code for lsb(value) here instead of the ubyte typecast
|
// generate code for lsb(value) here instead of the ubyte typecast
|
||||||
assignCastViaLsbFunc(value, target)
|
assignCastWordViaLsbFunc(value, target)
|
||||||
}
|
}
|
||||||
RegisterOrPair.AX,
|
RegisterOrPair.AX,
|
||||||
RegisterOrPair.AY,
|
RegisterOrPair.AY,
|
||||||
@@ -2569,7 +2569,7 @@ $endLabel""")
|
|||||||
if(!(valueDt isAssignableTo targetDt)) {
|
if(!(valueDt isAssignableTo targetDt)) {
|
||||||
return if(valueDt.isWord && targetDt.isByte) {
|
return if(valueDt.isWord && targetDt.isByte) {
|
||||||
// word to byte, just take the lsb
|
// word to byte, just take the lsb
|
||||||
assignCastViaLsbFunc(value, target)
|
assignCastWordViaLsbFunc(value, target)
|
||||||
} else if(valueDt.isWord && targetDt.isBool) {
|
} else if(valueDt.isWord && targetDt.isBool) {
|
||||||
// word to bool
|
// word to bool
|
||||||
assignWordToBool(value, target)
|
assignWordToBool(value, target)
|
||||||
@@ -2582,6 +2582,12 @@ $endLabel""")
|
|||||||
} else if(valueDt.isByteOrBool && targetDt.isWord) {
|
} else if(valueDt.isByteOrBool && targetDt.isWord) {
|
||||||
// byte to word, just assign
|
// byte to word, just assign
|
||||||
assignExpressionToRegister(value, target.register!!, valueDt.isSigned)
|
assignExpressionToRegister(value, target.register!!, valueDt.isSigned)
|
||||||
|
} else if(valueDt.isLong && targetDt.isByte) {
|
||||||
|
// long to byte, just take the lsb
|
||||||
|
assignCastLongToByte(value, target)
|
||||||
|
} else if(valueDt.isLong && targetDt.isWord) {
|
||||||
|
// long to word, just take the lsw
|
||||||
|
assignCastViaLswFunc(value, target)
|
||||||
} else
|
} else
|
||||||
throw AssemblyError("can't cast $valueDt to $targetDt, this should have been checked in the astchecker")
|
throw AssemblyError("can't cast $valueDt to $targetDt, this should have been checked in the astchecker")
|
||||||
}
|
}
|
||||||
@@ -2664,7 +2670,24 @@ $endLabel""")
|
|||||||
asmgen.assignExpressionTo(origTypeCastExpression, target)
|
asmgen.assignExpressionTo(origTypeCastExpression, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assignCastViaLsbFunc(value: PtExpression, target: AsmAssignTarget) {
|
private fun assignCastLongToByte(value: PtExpression, target: AsmAssignTarget) {
|
||||||
|
// long to byte, can't use lsb() because that only works on words
|
||||||
|
when(value) {
|
||||||
|
is PtIdentifier -> {
|
||||||
|
val longvar = asmgen.asmVariableName(value)
|
||||||
|
asmgen.out(" lda $longvar")
|
||||||
|
assignRegisterByte(target, CpuRegister.A, true, false)
|
||||||
|
}
|
||||||
|
is PtNumber -> throw AssemblyError("casting a long number to byte should have been const-folded away ${value.position}")
|
||||||
|
else -> {
|
||||||
|
assignExpressionToRegister(value, RegisterOrPair.R0R1_32, true)
|
||||||
|
asmgen.out(" lda cx16.r0")
|
||||||
|
assignRegisterByte(target, CpuRegister.A, true, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun assignCastWordViaLsbFunc(value: PtExpression, target: AsmAssignTarget) {
|
||||||
val lsb = PtBuiltinFunctionCall("lsb", false, true, DataType.UBYTE, value.position)
|
val lsb = PtBuiltinFunctionCall("lsb", false, true, DataType.UBYTE, value.position)
|
||||||
lsb.parent = value.parent
|
lsb.parent = value.parent
|
||||||
lsb.add(value)
|
lsb.add(value)
|
||||||
@@ -2673,6 +2696,15 @@ $endLabel""")
|
|||||||
translateNormalAssignment(assign, value.definingISub())
|
translateNormalAssignment(assign, value.definingISub())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun assignCastViaLswFunc(value: PtExpression, target: AsmAssignTarget) {
|
||||||
|
val lsb = PtBuiltinFunctionCall("lsw", false, true, DataType.UWORD, value.position)
|
||||||
|
lsb.parent = value.parent
|
||||||
|
lsb.add(value)
|
||||||
|
val src = AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, DataType.UWORD, expression = lsb)
|
||||||
|
val assign = AsmAssignment(src, listOf(target), program.memsizer, value.position)
|
||||||
|
translateNormalAssignment(assign, value.definingISub())
|
||||||
|
}
|
||||||
|
|
||||||
private fun assignWordToBool(value: PtExpression, target: AsmAssignTarget) {
|
private fun assignWordToBool(value: PtExpression, target: AsmAssignTarget) {
|
||||||
assignExpressionToRegister(value, RegisterOrPair.AY, false)
|
assignExpressionToRegister(value, RegisterOrPair.AY, false)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
|
|||||||
@@ -686,7 +686,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
addInstr(result, IRInstruction(Opcode.CMPI, IRDataType.WORD, reg1=tr.resultReg, immediate = 0), null)
|
addInstr(result, IRInstruction(Opcode.CMPI, IRDataType.WORD, reg1=tr.resultReg, immediate = 0), null)
|
||||||
actualResultReg2 = loadStatusAsBooleanResult(Opcode.BSTNE, result)
|
actualResultReg2 = loadStatusAsBooleanResult(Opcode.BSTNE, result)
|
||||||
}
|
}
|
||||||
valueDt.isLong -> TODO("typecast long ${cast.position}")
|
valueDt.isLong -> {
|
||||||
|
addInstr(result, IRInstruction(Opcode.CMPI, IRDataType.LONG, reg1=tr.resultReg, immediate = 0), null)
|
||||||
|
actualResultReg2 = loadStatusAsBooleanResult(Opcode.BSTNE, result)
|
||||||
|
}
|
||||||
valueDt.isFloat -> {
|
valueDt.isFloat -> {
|
||||||
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
|
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
|
||||||
result += IRCodeChunk(null, null).also {
|
result += IRCodeChunk(null, null).also {
|
||||||
@@ -706,7 +709,12 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
|
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
|
||||||
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null)
|
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null)
|
||||||
}
|
}
|
||||||
BaseDataType.LONG -> TODO("cast UBYTE to LONG ${cast.position}")
|
BaseDataType.LONG -> {
|
||||||
|
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
|
||||||
|
val wordReg = codeGen.registers.next(IRDataType.WORD)
|
||||||
|
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.WORD, reg1=wordReg, reg2=tr.resultReg, immediate = 0), null)
|
||||||
|
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1=actualResultReg2, reg2=wordReg, immediate = 0), null)
|
||||||
|
}
|
||||||
BaseDataType.FLOAT -> {
|
BaseDataType.FLOAT -> {
|
||||||
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
|
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
|
||||||
addInstr(result, IRInstruction(Opcode.FTOUB, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null)
|
addInstr(result, IRInstruction(Opcode.FTOUB, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null)
|
||||||
@@ -723,7 +731,12 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
|
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
|
||||||
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null)
|
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null)
|
||||||
}
|
}
|
||||||
BaseDataType.LONG -> TODO("cast BYTE to LONG ${cast.position}")
|
BaseDataType.LONG -> {
|
||||||
|
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
|
||||||
|
val wordReg = codeGen.registers.next(IRDataType.WORD)
|
||||||
|
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.WORD, reg1=wordReg, reg2=tr.resultReg, immediate = 0), null)
|
||||||
|
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1=actualResultReg2, reg2=wordReg, immediate = 0), null)
|
||||||
|
}
|
||||||
BaseDataType.FLOAT -> {
|
BaseDataType.FLOAT -> {
|
||||||
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
|
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
|
||||||
addInstr(result, IRInstruction(Opcode.FTOSB, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null)
|
addInstr(result, IRInstruction(Opcode.FTOSB, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null)
|
||||||
@@ -746,7 +759,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
BaseDataType.WORD -> {
|
BaseDataType.WORD -> {
|
||||||
actualResultReg2 = tr.resultReg
|
actualResultReg2 = tr.resultReg
|
||||||
}
|
}
|
||||||
BaseDataType.LONG -> TODO("cast UWORD to LONG ${cast.position}")
|
BaseDataType.LONG -> {
|
||||||
|
actualResultReg2 = codeGen.registers.next(IRDataType.WORD)
|
||||||
|
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.WORD, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null)
|
||||||
|
}
|
||||||
BaseDataType.FLOAT -> {
|
BaseDataType.FLOAT -> {
|
||||||
actualResultReg2 = codeGen.registers.next(IRDataType.WORD)
|
actualResultReg2 = codeGen.registers.next(IRDataType.WORD)
|
||||||
addInstr(result, IRInstruction(Opcode.FTOUW, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null)
|
addInstr(result, IRInstruction(Opcode.FTOUW, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null)
|
||||||
@@ -772,7 +788,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
BaseDataType.UWORD -> {
|
BaseDataType.UWORD -> {
|
||||||
actualResultReg2 = tr.resultReg
|
actualResultReg2 = tr.resultReg
|
||||||
}
|
}
|
||||||
BaseDataType.LONG -> TODO("cast WORD to LONG ${cast.position}}")
|
BaseDataType.LONG -> {
|
||||||
|
actualResultReg2 = codeGen.registers.next(IRDataType.WORD)
|
||||||
|
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.WORD, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null)
|
||||||
|
}
|
||||||
BaseDataType.FLOAT -> {
|
BaseDataType.FLOAT -> {
|
||||||
actualResultReg2 = codeGen.registers.next(IRDataType.WORD)
|
actualResultReg2 = codeGen.registers.next(IRDataType.WORD)
|
||||||
addInstr(result, IRInstruction(Opcode.FTOSW, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null)
|
addInstr(result, IRInstruction(Opcode.FTOSW, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null)
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ Future Things and Ideas
|
|||||||
- fix the line, cols in Position, sometimes they count from 0 sometimes from 1
|
- fix the line, cols in Position, sometimes they count from 0 sometimes from 1
|
||||||
- is "checkAssignmentCompatible" redundant (gets called just 1 time!) when we also have "checkValueTypeAndRange" ?
|
- is "checkAssignmentCompatible" redundant (gets called just 1 time!) when we also have "checkValueTypeAndRange" ?
|
||||||
- enums?
|
- enums?
|
||||||
|
- fix the c64 multiplexer example
|
||||||
- romable: should we have a way to explicitly set the memory address for the BSS area (add a -varsaddress and -slabsaddress options?)
|
- romable: should we have a way to explicitly set the memory address for the BSS area (add a -varsaddress and -slabsaddress options?)
|
||||||
- romable: fix remaining codegens (some for loops, see ForLoopsAsmGen)
|
- romable: fix remaining codegens (some for loops, see ForLoopsAsmGen)
|
||||||
- Kotlin: can we use inline value classes in certain spots? (domain types instead of primitives)
|
- Kotlin: can we use inline value classes in certain spots? (domain types instead of primitives)
|
||||||
@@ -41,10 +42,10 @@ Future Things and Ideas
|
|||||||
Maybe this routine can be made more intelligent. See usesOtherRegistersWhileEvaluating() and argumentsViaRegisters().
|
Maybe this routine can be made more intelligent. See usesOtherRegistersWhileEvaluating() and argumentsViaRegisters().
|
||||||
- Does it make codegen easier if everything is an expression? Start with the PtProgram ast classes, change statements to expressions that have (new) VOID data type
|
- Does it make codegen easier if everything is an expression? Start with the PtProgram ast classes, change statements to expressions that have (new) VOID data type
|
||||||
- Can we support signed % (remainder) somehow?
|
- Can we support signed % (remainder) somehow?
|
||||||
- Multidimensional arrays and chained indexing, purely as syntactic sugar over regular arrays. Probaby only useful once we have typed pointers. (addressed in 'struct' branch)
|
- Two- or even multidimensional arrays and chained indexing, purely as syntactic sugar over regular arrays?
|
||||||
- make a form of "manual generics" possible like: varsub routine(T arg)->T where T is expanded to a specific type
|
- make a form of "manual generics" possible like: varsub routine(T arg)->T where T is expanded to a specific type
|
||||||
(this is already done hardcoded for several of the builtin functions)
|
(this is already done hardcoded for several of the builtin functions)
|
||||||
- [much work:] more support for (64tass) SEGMENTS in the prog8 syntax itself?
|
- more support for (64tass) SEGMENTS in the prog8 syntax itself? maybe %segment blah in blocks?
|
||||||
- ability to use a sub instead of only a var for @bank ? what for though? dynamic bank/overlay loading?
|
- ability to use a sub instead of only a var for @bank ? what for though? dynamic bank/overlay loading?
|
||||||
- Zig-like try-based error handling where the V flag could indicate error condition? and/or BRK to jump into monitor on failure? (has to set BRK vector for that) But the V flag is also set on certain normal instructions
|
- Zig-like try-based error handling where the V flag could indicate error condition? and/or BRK to jump into monitor on failure? (has to set BRK vector for that) But the V flag is also set on certain normal instructions
|
||||||
|
|
||||||
@@ -77,6 +78,7 @@ IR/VM
|
|||||||
- getting it in shape for code generation...: the IR file should be able to encode every detail about a prog8 program (the VM doesn't have to actually be able to run all of it though!)
|
- getting it in shape for code generation...: the IR file should be able to encode every detail about a prog8 program (the VM doesn't have to actually be able to run all of it though!)
|
||||||
- fix call() return value handling (... what's wrong with it again?)
|
- fix call() return value handling (... what's wrong with it again?)
|
||||||
- proper code gen for the CALLI instruction and that it (optionally) returns a word value that needs to be assigned to a reg
|
- proper code gen for the CALLI instruction and that it (optionally) returns a word value that needs to be assigned to a reg
|
||||||
|
- register reuse to reduce the number of required variables in memory eventually. But can only re-use a register if a) it's the same type and b) if the second occurrence is not called from the first occurrence (otherwise the value gets overwritten!)
|
||||||
- encode asmsub/extsub clobber info in the call , or maybe include these definitions in the p8ir file itself too. (return registers are already encoded in the CALL instruction)
|
- encode asmsub/extsub clobber info in the call , or maybe include these definitions in the p8ir file itself too. (return registers are already encoded in the CALL instruction)
|
||||||
- implement fast code paths for TODO("inplace split....
|
- implement fast code paths for TODO("inplace split....
|
||||||
- implement more TODOs in AssignmentGen
|
- implement more TODOs in AssignmentGen
|
||||||
@@ -161,6 +163,7 @@ Libraries
|
|||||||
Optimizations
|
Optimizations
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
- optimize inplaceLongShiftRight() for byte aligned cases
|
||||||
- more optimized operator handling of different types, for example uword a ^ byte b now does a type cast of b to word first
|
- more optimized operator handling of different types, for example uword a ^ byte b now does a type cast of b to word first
|
||||||
- optimize longEqualsValue() for const and variable operands to not assign needlessly to R0-R3.
|
- optimize longEqualsValue() for const and variable operands to not assign needlessly to R0-R3.
|
||||||
- optimize optimizedBitwiseExpr() for const and variable operands to not assign needlessly to R0-R3.
|
- optimize optimizedBitwiseExpr() for const and variable operands to not assign needlessly to R0-R3.
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ main {
|
|||||||
; TODO keep working with the previously sorted result instead of rewriting the list every time, makes sorting faster if not much changes in the Y positions
|
; TODO keep working with the previously sorted result instead of rewriting the list every time, makes sorting faster if not much changes in the Y positions
|
||||||
}
|
}
|
||||||
|
|
||||||
; TODO remove this simplistic anim but it's here to test the algorithms
|
; TODO remove this simplistic animation but it's here to test the algorithms
|
||||||
sprite = sprites[0]
|
sprite = sprites[0]
|
||||||
sprite.y++
|
sprite.y++
|
||||||
sort_ypositions[0] = sprites[0].y
|
sort_ypositions[0] = sprites[0].y
|
||||||
|
|||||||
@@ -3,19 +3,19 @@
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
long lv1 = 12345678
|
long @shared lv1 = -9999
|
||||||
|
txt.print_uw(lsw(lv1))
|
||||||
txt.print_l(lv1)
|
|
||||||
txt.spc()
|
txt.spc()
|
||||||
txt.print_uw(&lv1)
|
txt.print_w(lv1 as word)
|
||||||
txt.spc()
|
txt.spc()
|
||||||
txt.print_l(peekl(&lv1))
|
txt.print_uw(lv1 as uword)
|
||||||
txt.nl()
|
txt.spc()
|
||||||
|
txt.print_b(lv1 as byte)
|
||||||
pokel(&lv1, -6666666)
|
txt.spc()
|
||||||
sys.pushl(lv1)
|
txt.print_ub(lv1 as ubyte)
|
||||||
|
txt.spc()
|
||||||
long lv2 = sys.popl()
|
txt.print_w(msw(lv1 << 8) as word)
|
||||||
txt.print_l(lv2)
|
txt.spc()
|
||||||
|
txt.print_w(lsw(lv1 >> 8) as word)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user