Hallo
Ich versuche gerade Ausgabe-Routinen für das Display zu beschleunigen.
Dafür habe ich 2 Sub-Routinen vorgesehen, die eine, um ein Byte auszugeben, die andere um ein Word auszugeben.
Die Deklaration sieht wie folgt aus:
Das funktioniert auch soweit.
Die eigentlichen Ausgaberoutinen werden aber dann erst von der Sub angesprungen. Diese erwarten dann die Daten in bestimmten Registern.
Dafür habe ich Aliasse definiert.
Alles anzeigen
Jetzt ist es aber so, dass wenn ich z.B. ein Datenbyte ausgeben möchte, macht es doch aus Performance-Gründen Sinn, das richtige Register in der Deklaration der Sub anzugeben.
Das erspart Rumschieben von Register und ist damit schneller.
Jetzt zum Problem.
Ich dachte, ich kann doch in der Deklaration auch den Alias des Registers nehmen. Wenn ich dann mal den Alias ändere, wird überall das neue Register verwendet.
Ist doch praktisch - dachte ich.
Die Routinen sehen dann so aus:
Die Routinen leiten also die Daten nur weiter an die Assembler-Routine.
Den Alias in der 1. Routine (TFT_Write_Data()) nimmt der Compiler an.
Wenn ich aber den Alias verwende, um ein Word zu übergeben, funktioniert das nicht.
Error : 218 Line : 63 Register must be in range from R16-R31 [R1[1110KKKKDDDDKKKK]] , in File : C:\Users\Michael\Documents\Projekte\Experimente\Temp\noname1.bas
Wieso geht der Alias, wenn ich Bytewerte übergebe, aber bei Word-Werten nicht? Ein Versehen? Bug?
Hier noch ein Auszug aus der Hilfe "Declare Sub"
Spoiler anzeigen
BYREG
Use BYREG to pass a copy of the variable using a register. The value will be passed to the register(s) you specify. When multiple bytes need to be passed, multiple registers will be used. Registers are named from R0-R31. When you pass a WORD to register R16, you will also use R17 since a word requires 2 bytes.
You can not pass strings. Only numeric variables and constants.
Using BYREG requires some knowledge of the routines you call. The current implementation does not protect already loaded registers. This means that when you pass multiple registers you could destroy some already loaded registers just because a parameter will destroy the register.
Example : declare Sub MySub(byreg R16 as Word, byreg R18 as long, byreg R22 as dword)
mysub 1000, var(J+100), var(j)
In this example, R16 and R17 are loaded, after this the array index of variable var() need to be calculated which uses the ML16 routine which uses R16-R21
Numeric constants and expression do not alter registers but functions might. A future version will track and protect registers.
Why would you want to use BYREG ? Using BYREG is equivalent to using ASM. It is intended to be used with ASM code inside subs. The FT800 include files use BYREG and BYSTACK.
Example from FT800:
Sub Stencilfunc(byreg r18 As Byte , Byreg r17 As Byte , Byreg R16 As Byte)
Cmd32 _stencilfunc(r18 , R17 , r16)
End Sub
Ich versuche gerade Ausgabe-Routinen für das Display zu beschleunigen.
Dafür habe ich 2 Sub-Routinen vorgesehen, die eine, um ein Byte auszugeben, die andere um ein Word auszugeben.
Die Deklaration sieht wie folgt aus:
Das funktioniert auch soweit.
Die eigentlichen Ausgaberoutinen werden aber dann erst von der Sub angesprungen. Diese erwarten dann die Daten in bestimmten Registern.
Dafür habe ich Aliasse definiert.
BASCOM-Quellcode
- ' verwendete Register
- rTmpH Alias r19
- rTmpL Alias r18
- ' Hier die angesprungenen Assembler-Routinen
- ' Datenword auf Bus schreiben
- ' rTmpL enthält H-Byte; rTmpH enthält L-Byte
- _tft_write_word:
- Reset PIN_CS
- Set PIN_RS
- Config PORT_DATA = Output
- !RCALL _tft_write_byte ' zuerst H-Byte ausgeben
- !MOV rTmpL,rTmpH ' L-Byte in Ausgaberegister
- !RJMP _tft_write_byte ' L-Byte ausgeben
- _tft_write_data:
- Reset PIN_CS
- Set PIN_RS
- _tft_write_byte:
- Reset PIN_WR
- !OUT PORT_DATA,rTmpL
- Set PIN_WR
- !RET
Das erspart Rumschieben von Register und ist damit schneller.
Jetzt zum Problem.
Ich dachte, ich kann doch in der Deklaration auch den Alias des Registers nehmen. Wenn ich dann mal den Alias ändere, wird überall das neue Register verwendet.
Ist doch praktisch - dachte ich.
Die Routinen sehen dann so aus:
Den Alias in der 1. Routine (TFT_Write_Data()) nimmt der Compiler an.
Wenn ich aber den Alias verwende, um ein Word zu übergeben, funktioniert das nicht.
Error : 218 Line : 63 Register must be in range from R16-R31 [R1[1110KKKKDDDDKKKK]] , in File : C:\Users\Michael\Documents\Projekte\Experimente\Temp\noname1.bas
Wieso geht der Alias, wenn ich Bytewerte übergebe, aber bei Word-Werten nicht? Ein Versehen? Bug?
Hier noch ein Auszug aus der Hilfe "Declare Sub"
BYREG
Use BYREG to pass a copy of the variable using a register. The value will be passed to the register(s) you specify. When multiple bytes need to be passed, multiple registers will be used. Registers are named from R0-R31. When you pass a WORD to register R16, you will also use R17 since a word requires 2 bytes.
You can not pass strings. Only numeric variables and constants.
Using BYREG requires some knowledge of the routines you call. The current implementation does not protect already loaded registers. This means that when you pass multiple registers you could destroy some already loaded registers just because a parameter will destroy the register.
Example : declare Sub MySub(byreg R16 as Word, byreg R18 as long, byreg R22 as dword)
mysub 1000, var(J+100), var(j)
In this example, R16 and R17 are loaded, after this the array index of variable var() need to be calculated which uses the ML16 routine which uses R16-R21
Numeric constants and expression do not alter registers but functions might. A future version will track and protect registers.
Why would you want to use BYREG ? Using BYREG is equivalent to using ASM. It is intended to be used with ASM code inside subs. The FT800 include files use BYREG and BYSTACK.
Example from FT800:
Sub Stencilfunc(byreg r18 As Byte , Byreg r17 As Byte , Byreg R16 As Byte)
Cmd32 _stencilfunc(r18 , R17 , r16)
End Sub