2022-08-27 11:06:44 +00:00
package prog8.intermediate
2022-03-18 23:57:35 +00:00
2023-05-12 21:26:36 +00:00
import prog8.code.core.RegisterOrStatusflag
2022-11-07 23:06:43 +00:00
import prog8.code.core.toHex
2022-03-18 23:57:35 +00:00
/ *
2022-08-27 11:22:38 +00:00
Intermediate Representation instructions for the IR Virtual machine .
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-03-18 23:57:35 +00:00
2022-08-27 11:22:38 +00:00
Specs of the virtual machine this will run on :
Program to execute is not stored in the system memory , it ' s just a separate list of instructions .
2022-03-23 00:52:01 +00:00
65536 virtual registers , 16 bits wide , can also be used as 8 bits . r0 - r65535
2023-11-20 22:19:08 +00:00
65536 virtual floating point registers ( 64 bits double precision ) fr0 - fr65535
2022-03-23 00:52:01 +00:00
65536 bytes of memory . Thus memory pointers ( addresses ) are limited to 16 bits .
2022-04-11 20:39:33 +00:00
Value stack , max 128 entries of 1 byte each .
2023-10-29 23:09:18 +00:00
Status flags : Carry , Zero , Negative . NOTE : status flags are only affected by the CMP instruction or explicit CLC / SEC ,
LOAD instructions DO affect the Z and N flags .
2024-01-25 23:12:04 +00:00
INC / DEC / NEG instructions DO affect the Z and N flags ,
2023-10-29 23:09:18 +00:00
other instructions only affect Z an N flags if the value in a result register is written .
2024-01-07 21:10:43 +00:00
See OpcodesThatSetStatusbits
2022-08-27 11:22:38 +00:00
2022-09-26 17:03:54 +00:00
Instruction set is mostly a load / store architecture , there are few instructions operating on memory directly .
2023-04-11 20:28:19 +00:00
2023-11-20 22:19:08 +00:00
Value types : integers ( . b = byte = 8 bits , . w = word = 16 bits ) and float ( . f = 64 bits ) . Omitting it defaults to b if the instruction requires a type .
2023-04-11 20:28:19 +00:00
Currently ther is NO support for 24 or 32 bits integers .
There is no distinction between signed and unsigned integers .
Instead , a different instruction is used if a distinction should be made ( for example div and divs ) .
2022-09-26 17:03:54 +00:00
Floating point operations are just 'f' typed regular instructions , however there are a few unique fp conversion instructions .
2022-03-18 23:57:35 +00:00
2023-05-09 19:04:31 +00:00
NOTE : Labels in source text should always start with an underscore .
2022-03-18 23:57:35 +00:00
2022-03-23 00:52:01 +00:00
LOAD / STORE
-- -- -- -- --
2022-04-24 22:10:12 +00:00
All have type b or w or f .
2022-03-18 23:57:35 +00:00
2023-04-26 23:26:25 +00:00
load reg1 , value - load immediate value into register . If you supply a symbol , loads the * address * of the symbol ! ( variable values are loaded from memory via the loadm instruction )
2022-04-24 22:10:12 +00:00
loadm reg1 , address - load reg1 with value at memory address
loadi reg1 , reg2 - load reg1 with value at memory indirect , memory pointed to by reg2
2023-09-06 00:44:04 +00:00
loadx reg1 , reg2 , address - load reg1 with value at memory address indexed by value in reg2 ( only the lsb part used for indexing )
loadix reg1 , reg2 , pointeraddr - load reg1 with value at memory indirect , pointed to by pointeraddr indexed by value in reg2 ( only the lsb part used for indexing )
2022-06-04 15:49:25 +00:00
loadr reg1 , reg2 - load reg1 with value in register reg2
2024-03-21 22:40:36 +00:00
loadha reg1 - load cpu hardware register A into reg1 . b
loadhx reg1 - load cpu hardware register X into reg1 . b
loadhy reg1 - load cpu hardware register Y into reg1 . b
loadhax reg1 - load cpu hardware register pair AX into reg1 . w
loadhay reg1 - load cpu hardware register pair AY into reg1 . w
loadhxy reg1 - load cpu hardware register pair XY into reg1 . w
2022-04-24 22:10:12 +00:00
storem reg1 , address - store reg1 at memory address
storei reg1 , reg2 - store reg1 at memory indirect , memory pointed to by reg2
2023-09-06 00:44:04 +00:00
storex reg1 , reg2 , address - store reg1 at memory address , indexed by value in reg2 ( only the lsb part used for indexing )
storeix reg1 , reg2 , pointeraddr - store reg1 at memory indirect , pointed to by pointeraddr indexed by value in reg2 ( only the lsb part used for indexing )
2022-05-11 13:13:44 +00:00
storezm address - store zero at memory address
2022-04-24 22:10:12 +00:00
storezi reg1 - store zero at memory pointed to by reg1
2023-09-06 00:44:04 +00:00
storezx reg1 , address - store zero at memory address , indexed by value in reg1 ( only the lsb part used for indexing )
2024-03-21 22:40:36 +00:00
storeha reg1 - store reg1 . b into cpu hardware register A
storehx reg1 - store reg1 . b into cpu hardware register X
storehy reg1 - store reg1 . b into cpu hardware register Y
storehax reg1 - store reg1 . w into cpu hardware register pair AX
storehay reg1 - store reg1 . w into cpu hardware register pair AY
storehxy reg1 - store reg1 . w into cpu hardware register pair XY
2022-03-18 23:57:35 +00:00
2022-03-23 00:52:01 +00:00
CONTROL FLOW
-- -- -- -- -- --
2023-07-07 16:25:05 +00:00
jump location - continue running at instruction at ' location ' ( label / memory address )
2024-02-22 10:35:54 +00:00
jumpi pointervar - continue running at memory address contained in the pointer variable ( indirect jump )
2023-09-18 21:22:03 +00:00
preparecall numparams - indicator that the next instructions are the param setup and function call / syscall with < numparams > parameters
2023-12-10 20:15:50 +00:00
calli reg1 - calls a subroutine ( without arguments and without return valus ) at memory addres in reg1 ( indirect jsr )
2023-07-07 20:35:05 +00:00
call label ( argument register list ) [ : resultreg . type ]
2023-05-12 21:26:36 +00:00
- calls a subroutine with the given arguments and return value ( optional ) .
save current instruction location + 1 , continue execution at instruction nr of the label .
the argument register list is positional and includes the datatype , ex . : r4 . b , r5 . w , fp1 . f
2023-05-14 14:48:48 +00:00
If the call is to a rom - routine , ' label ' will be a hexadecimal address instead such as $ ffd2
If the arguments should be passed in CPU registers , they ' ll have a @REGISTER postfix .
For example : call $ ffd2 ( r5 . b @A )
2023-09-18 21:22:03 +00:00
Always preceded by parameter setup and preparecall instructions
2023-07-07 20:35:05 +00:00
syscall number ( argument register list ) [ : resultreg . type ]
2023-05-12 21:26:36 +00:00
- do a systemcall identified by number , result value ( s ) are pushed on value stack by the syscall code so
will be POPped off into the given resultregister if any .
2023-09-18 21:22:03 +00:00
Always preceded by parameter setup and preparecall instructions
2023-03-12 20:54:59 +00:00
return - restore last saved instruction location and continue at that instruction . No return value .
2023-04-11 20:28:19 +00:00
returnr reg1 - like return , but also returns the value in reg1 to the caller
2022-03-18 23:57:35 +00:00
2022-03-23 00:52:01 +00:00
2023-05-12 21:26:36 +00:00
2022-09-29 16:18:11 +00:00
BRANCHING and CONDITIONALS
-- -- -- -- -- -- -- -- -- -- -- -- --
2022-04-08 22:49:23 +00:00
All have type b or w except the branches that only check status bits .
2022-03-23 00:52:01 +00:00
2023-05-01 21:00:51 +00:00
bstcc address - branch to location if Status bit Carry is clear
bstcs address - branch to location if Status bit Carry is set
bstne address - branch to location if Status bit Zero is clear
2022-09-26 23:50:00 +00:00
bsteq address - branch to location if Status bit Zero is set
2023-05-01 21:00:51 +00:00
bstpos address - branch to location if Status bit Negative is clear
bstneg address - branch to location if Status bit Negative is set
bstvc address - branch to location if Status bit Overflow is clear
bstvs address - branch to location if Status bit Overflow is set
2023-11-15 21:24:10 +00:00
( unsigned comparison branches : )
2023-04-09 19:08:35 +00:00
bgt reg1 , value , address - jump to location in program given by location , if reg1 > immediate value ( unsigned )
2023-05-01 21:00:51 +00:00
blt reg1 , value , address - jump to location in program given by location , if reg1 < immediate value ( unsigned )
2023-11-15 21:24:10 +00:00
bgtr reg1 , reg2 , address - jump to location in program given by location , if reg1 > reg2 ( unsigned )
' bltr ' reg1 , reg2 , address - jump to location in program given by location , if reg1 < reg2 ( unsigned ) == > use bgtr with swapped operands
2023-04-09 19:08:35 +00:00
bge reg1 , value , address - jump to location in program given by location , if reg1 >= immediate value ( unsigned )
2023-05-01 21:00:51 +00:00
ble reg1 , value , address - jump to location in program given by location , if reg1 <= immediate value ( unsigned )
2023-11-15 21:24:10 +00:00
bger reg1 , reg2 , address - jump to location in program given by location , if reg1 >= reg2 ( unsigned )
' bler ' reg1 , reg2 , address - jump to location in program given by location , if reg1 <= reg2 ( unsigned ) == > use bger with swapped operands
( signed comparison branches : )
bgts reg1 , value , address - jump to location in program given by location , if reg1 > immediate value ( signed )
blts reg1 , value , address - jump to location in program given by location , if reg1 < immediate value ( signed )
bgtsr reg1 , reg2 , address - jump to location in program given by location , if reg1 > reg2 ( signed )
' bltsr ' reg1 , reg2 , address - jump to location in program given by location , if reg1 < reg2 ( signed ) == > use bgtsr with swapped operands
bges reg1 , value , address - jump to location in program given by location , if reg1 >= immediate value ( signed )
2023-04-09 19:08:35 +00:00
bles reg1 , value , address - jump to location in program given by location , if reg1 <= immediate value ( signed )
2023-11-15 21:24:10 +00:00
bgesr reg1 , reg2 , address - jump to location in program given by location , if reg1 >= reg2 ( signed )
' blesr ' reg1 , reg2 , address - jump to location in program given by location , if reg1 <= reg2 ( signed ) == > use bgesr with swapped operands
2024-01-08 23:57:02 +00:00
scc reg1 - set reg1 = 1 if Carry flag is clear , else 0
scs reg1 - set reg1 = 1 if Carry flag is set , else 0
2023-07-09 20:51:16 +00:00
sz reg1 , reg2 - set reg1 = 1 if reg2 == 0 , else 0
snz reg1 , reg2 - set reg1 = 1 if reg2 != 0 , else 0
2023-07-20 21:58:52 +00:00
seq reg1 , reg2 , reg3 - set reg1 = 1 if reg2 == reg3 , else 0
sne reg1 , reg2 , reg3 - set reg1 = 1 if reg2 != reg3 , else 0
slt reg1 , reg2 , reg3 - set reg1 = 1 if reg2 < reg3 ( unsigned ) , else 0
slts reg1 , reg2 , reg3 - set reg1 = 1 if reg2 < reg3 ( signed ) , else 0
sle reg1 , reg2 , reg3 - set reg1 = 1 if reg2 <= reg3 ( unsigned ) , else 0
sles reg1 , reg2 , reg3 - set reg1 = 1 if reg2 <= reg3 ( signed ) , else 0
sgt reg1 , reg2 , reg3 - set reg1 = 1 if reg2 > reg3 ( unsigned ) , else 0
sgts reg1 , reg2 , reg3 - set reg1 = 1 if reg2 > reg3 ( signed ) , else 0
sge reg1 , reg2 , reg3 - set reg1 = 1 if reg2 >= reg3 ( unsigned ) , else 0
sges reg1 , reg2 , reg3 - set reg1 = 1 if reg2 >= reg3 ( signed ) , else 0
2023-07-09 20:51:16 +00:00
( note : on the M68k these instructions will set all bits to 1 ( so value = - 1 instead of 1 ) , but the boolean logic here requires it to be 0 or 1 in this IR )
2022-03-18 23:57:35 +00:00
2022-04-24 22:10:12 +00:00
ARITHMETIC
-- -- -- -- --
All have type b or w or f . Note : result types are the same as operand types ! E . g . byte * byte -> byte .
2022-03-18 23:57:35 +00:00
2023-07-08 20:42:11 +00:00
exts reg1 , reg2 - reg1 = signed extension of reg2 ( byte to word , or word to long ) ( note : unlike M68k , exts . b -> word and exts . w -> long . The latter is not yet implemented yet as we don ' t have longs yet )
ext reg1 , reg2 - reg1 = unsigned extension of reg2 ( which in practice just means clearing the MSB / MSW ) ( note : unlike M68k , ext . b -> word and ext . w -> long . The latter is not yet implemented yet as we don ' t have longs yet )
2022-03-23 00:52:01 +00:00
inc reg1 - reg1 = reg1 + 1
2022-03-30 21:40:39 +00:00
incm address - memory at address += 1
2022-03-23 00:52:01 +00:00
dec reg1 - reg1 = reg1 - 1
2022-03-30 21:40:39 +00:00
decm address - memory at address -= 1
2022-03-23 00:52:01 +00:00
neg reg1 - reg1 = sign negation of reg1
2022-05-18 20:15:42 +00:00
negm address - sign negate memory at address
2023-04-11 20:28:19 +00:00
addr reg1 , reg2 - reg1 += reg2
add reg1 , value - reg1 += value
addm reg1 , address - memory at address += reg1
subr reg1 , reg2 - reg1 -= reg2
sub reg1 , value - reg1 -= value
subm reg1 , address - memory at address -= reg1
2022-07-12 13:15:28 +00:00
mulr reg1 , reg2 - unsigned multiply reg1 *= reg2 note : byte * byte -> byte , no type extension to word !
mul reg1 , value - unsigned multiply reg1 *= value note : byte * byte -> byte , no type extension to word !
2022-05-19 21:15:22 +00:00
mulm reg1 , address - memory at address *= reg2 note : byte * byte -> byte , no type extension to word !
2022-07-12 13:15:28 +00:00
divr reg1 , reg2 - unsigned division reg1 /= reg2 note : division by zero yields max int $ ff / $ ffff
div reg1 , value - unsigned division reg1 /= value note : division by zero yields max int $ ff / $ ffff
2022-05-19 21:15:22 +00:00
divm reg1 , address - memory at address /= reg2 note : division by zero yields max int $ ff / $ ffff
2022-07-12 13:15:28 +00:00
divsr reg1 , reg2 - signed division reg1 /= reg2 note : division by zero yields max signed int 127 / 32767
divs reg1 , value - signed division reg1 /= value note : division by zero yields max signed int 127 / 32767
2022-05-19 21:15:22 +00:00
divsm reg1 , address - signed memory at address /= reg2 note : division by zero yields max signed int 127 / 32767
2022-07-12 13:15:28 +00:00
modr reg1 , reg2 - remainder ( modulo ) of unsigned division reg1 %= reg2 note : division by zero yields max signed int $ ff / $ ffff
mod reg1 , value - remainder ( modulo ) of unsigned division reg1 %= value note : division by zero yields max signed int $ ff / $ ffff
2023-04-10 13:23:20 +00:00
divmodr reg1 , reg2 - unsigned division reg1 / reg2 , storing division and remainder on value stack ( so need to be POPped off )
divmod reg1 , value - unsigned division reg1 / value , storing division and remainder on value stack ( so need to be POPped off )
2023-07-07 20:35:05 +00:00
sqrt reg1 , reg2 - reg1 is the square root of reg2 ( reg2 can be . w or . b , result type in reg1 is always . b ) you can also use it with floating point types , fpreg1 and fpreg2 ( result is also . f )
2023-08-13 22:50:40 +00:00
square reg1 , reg2 - reg1 is the square of reg2 ( reg2 can be . w or . b , result type in reg1 is always . b ) you can also use it with floating point types , fpreg1 and fpreg2 ( result is also . f )
2024-01-16 00:23:41 +00:00
sgn reg1 , reg2 - reg1 . b is the sign of reg2 ( or fpreg1 , if sgn . f ) ( 0. b , 1. b or - 1. b )
2022-04-18 17:59:48 +00:00
cmp reg1 , reg2 - set processor status bits C , N , Z according to comparison of reg1 with reg2 . ( semantics taken from 6502 / 68000 CMP instruction )
2023-07-14 21:17:29 +00:00
cmpi reg1 , value - set processor status bits C , N , Z according to comparison of reg1 with immediate value . ( semantics taken from 6502 / 68000 CMP instruction )
2022-03-23 00:52:01 +00:00
2022-04-08 22:49:23 +00:00
NOTE : because mul / div are constrained ( truncated ) to remain in 8 or 16 bits , there is NO NEED for separate signed / unsigned mul and div instructions . The result is identical .
2022-03-23 00:52:01 +00:00
2022-03-18 23:57:35 +00:00
2022-03-23 00:52:01 +00:00
LOGICAL / BITWISE
-- -- -- -- -- -- -- -
All have type b or w .
2022-03-18 23:57:35 +00:00
2022-07-12 13:54:35 +00:00
andr reg1 , reg2 - reg1 = reg1 bitwise and reg2
and reg1 , value - reg1 = reg1 bitwise and value
2022-08-07 15:43:40 +00:00
andm reg1 address - memory = memory bitwise and reg1
2022-07-12 13:54:35 +00:00
orr reg1 , reg2 - reg1 = reg1 bitwise or reg2
or reg1 , value - reg1 = reg1 bitwise or value
2022-08-07 15:43:40 +00:00
orm reg1 , address - memory = memory bitwise or reg1
2022-07-12 13:54:35 +00:00
xorr reg1 , reg2 - reg1 = reg1 bitwise xor reg2
xor reg1 , value - reg1 = reg1 bitwise xor value
2022-08-07 15:43:40 +00:00
xorm reg1 , address - memory = memory bitwise xor reg1
2022-06-28 23:13:08 +00:00
inv reg1 - reg1 = bitwise invert of reg1 ( all bits flipped )
2022-08-07 15:43:40 +00:00
invm address - memory = bitwise invert of that memory ( all bits flipped )
2022-05-11 20:35:02 +00:00
asrn reg1 , reg2 - reg1 = multi - shift reg1 right by reg2 bits ( signed ) + set Carry to shifted bit
2022-08-07 15:43:40 +00:00
lsrn reg1 , reg2 - reg1 = multi - shift reg1 right by reg2 bits + set Carry to shifted bit
2022-05-11 20:35:02 +00:00
lsln reg1 , reg2 - reg1 = multi - shift reg1 left by reg2 bits + set Carry to shifted bit
2022-08-07 15:43:40 +00:00
asrnm reg1 , address - multi - shift memory right by reg1 bits ( signed ) + set Carry to shifted bit
lsrnm reg1 , address - multi - shift memoryright by reg1 bits + set Carry to shifted bit
lslnm reg1 , address - multi - shift memory left by reg1 bits + set Carry to shifted bit
2022-04-10 22:25:00 +00:00
asr reg1 - shift reg1 right by 1 bits ( signed ) + set Carry to shifted bit
2022-08-07 15:43:40 +00:00
lsr reg1 - shift reg1 right by 1 bits + set Carry to shifted bit
2022-04-10 22:25:00 +00:00
lsl reg1 - shift reg1 left by 1 bits + set Carry to shifted bit
2022-08-07 15:43:40 +00:00
lsrm address - shift memory right by 1 bits + set Carry to shifted bit
asrm address - shift memory right by 1 bits ( signed ) + set Carry to shifted bit
lslm address - shift memory left by 1 bits + set Carry to shifted bit
2022-04-08 22:49:23 +00:00
ror reg1 - rotate reg1 right by 1 bits , not using carry + set Carry to shifted bit
roxr reg1 - rotate reg1 right by 1 bits , using carry + set Carry to shifted bit
2022-05-11 13:50:51 +00:00
rol reg1 - rotate reg1 left by 1 bits , not using carry + set Carry to shifted bit
roxl reg1 - rotate reg1 left by 1 bits , using carry , + set Carry to shifted bit
2022-05-23 18:26:44 +00:00
rorm address - rotate memory right by 1 bits , not using carry + set Carry to shifted bit
roxrm address - rotate memory right by 1 bits , using carry + set Carry to shifted bit
rolm address - rotate memory left by 1 bits , not using carry + set Carry to shifted bit
roxlm address - rotate memory left by 1 bits , using carry , + set Carry to shifted bit
2022-05-19 21:15:22 +00:00
2022-03-18 23:57:35 +00:00
2022-05-02 18:16:45 +00:00
FLOATING POINT CONVERSIONS AND FUNCTIONS
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2022-04-24 22:10:12 +00:00
ffromub fpreg1 , reg1 - fpreg1 = reg1 from usigned byte
ffromsb fpreg1 , reg1 - fpreg1 = reg1 from signed byte
ffromuw fpreg1 , reg1 - fpreg1 = reg1 from unsigned word
ffromsw fpreg1 , reg1 - fpreg1 = reg1 from signed word
ftoub reg1 , fpreg1 - reg1 = fpreg1 as unsigned byte
ftosb reg1 , fpreg1 - reg1 = fpreg1 as signed byte
ftouw reg1 , fpreg1 - reg1 = fpreg1 as unsigned word
ftosw reg1 , fpreg1 - reg1 = fpreg1 as signed word
2022-05-11 20:09:46 +00:00
fpow fpreg1 , fpreg2 - fpreg1 = fpreg1 to the power of fpreg2
2022-05-02 18:16:45 +00:00
fabs fpreg1 , fpreg2 - fpreg1 = abs ( fpreg2 )
2023-03-07 20:26:34 +00:00
fcomp reg1 , fpreg1 , fpreg2 - reg1 = result of comparison of fpreg1 and fpreg2 : 0. b = equal , 1. b = fpreg1 is greater , - 1. b = fpreg1 is smaller
2022-08-07 15:43:40 +00:00
fsin fpreg1 , fpreg2 - fpreg1 = sin ( fpreg2 )
fcos fpreg1 , fpreg2 - fpreg1 = cos ( fpreg2 )
ftan fpreg1 , fpreg2 - fpreg1 = tan ( fpreg2 )
fatan fpreg1 , fpreg2 - fpreg1 = atan ( fpreg2 )
fln fpreg1 , fpreg2 - fpreg1 = ln ( fpreg2 ) ; natural logarithm
flog fpreg1 , fpreg2 - fpreg1 = log ( fpreg2 ) ; base 2 logarithm
fround fpreg1 , fpreg2 - fpreg1 = round ( fpreg2 )
ffloor fpreg1 , fpreg2 - fpreg1 = floor ( fpreg2 )
fceil fpreg1 , fpreg2 - fpreg1 = ceil ( fpreg2 )
2022-04-24 22:10:12 +00:00
2022-03-18 23:57:35 +00:00
MISC
2022-03-23 00:52:01 +00:00
-- --
2022-03-18 23:57:35 +00:00
2022-04-24 22:10:12 +00:00
clc - clear Carry status bit
sec - set Carry status bit
nop - do nothing
breakpoint - trigger a breakpoint
msig [ b , w ] reg1 , reg2 - reg1 becomes the most significant byte ( or word ) of the word ( or int ) in reg2 ( . w not yet implemented ; requires 32 bits regs )
2023-10-28 03:44:47 +00:00
concat [ b , w ] reg1 , reg2 , reg3 - reg1 . w = ' concatenate ' two registers : lsb / lsw of reg2 ( as msb ) and lsb / lsw of reg3 ( as lsb ) into word or int ( int not yet implemented ; requires 32 bits regs )
2023-04-10 14:16:35 +00:00
push [ b , w , f ] reg1 - push value in reg1 on the stack
pop [ b , w , f ] reg1 - pop value from stack into reg1
2024-01-16 19:41:53 +00:00
pushst - push status register bits to stack
popst - pop status register bits from stack
2022-03-18 23:57:35 +00:00
* /
enum class Opcode {
NOP ,
2022-09-18 14:04:49 +00:00
LOAD , // note: LOAD <symbol> gets you the address of the symbol, whereas LOADM <symbol> would get you the value stored at that location
2022-03-18 23:57:35 +00:00
LOADM ,
LOADI ,
LOADX ,
2022-06-04 15:49:25 +00:00
LOADIX ,
2022-03-18 23:57:35 +00:00
LOADR ,
2024-03-21 22:40:36 +00:00
LOADHA ,
LOADHX ,
LOADHY ,
LOADHAX ,
LOADHAY ,
LOADHXY ,
2022-03-18 23:57:35 +00:00
STOREM ,
STOREI ,
STOREX ,
2022-06-06 12:18:12 +00:00
STOREIX ,
2022-05-11 13:13:44 +00:00
STOREZM ,
2022-03-18 23:57:35 +00:00
STOREZI ,
STOREZX ,
2024-03-21 22:40:36 +00:00
STOREHA ,
STOREHX ,
STOREHY ,
STOREHAX ,
STOREHAY ,
STOREHXY ,
2022-03-18 23:57:35 +00:00
JUMP ,
2023-07-07 16:25:05 +00:00
JUMPI ,
2023-09-18 21:22:03 +00:00
PREPARECALL ,
2023-12-10 20:15:50 +00:00
CALLI ,
2022-03-23 00:52:01 +00:00
CALL ,
2022-03-18 23:57:35 +00:00
SYSCALL ,
RETURN ,
2023-04-11 20:28:19 +00:00
RETURNR ,
2022-04-08 22:49:23 +00:00
BSTCC ,
BSTCS ,
2022-04-18 17:59:48 +00:00
BSTEQ ,
BSTNE ,
BSTNEG ,
BSTPOS ,
2022-09-30 13:27:03 +00:00
BSTVC ,
BSTVS ,
2023-04-09 19:08:35 +00:00
BGTR ,
2022-05-12 19:26:17 +00:00
BGT ,
2023-04-09 19:08:35 +00:00
BLT ,
BGTSR ,
2022-05-12 19:26:17 +00:00
BGTS ,
2023-04-09 19:08:35 +00:00
BLTS ,
BGER ,
2022-05-12 19:26:17 +00:00
BGE ,
2023-04-09 19:08:35 +00:00
BLE ,
BGESR ,
2022-05-12 19:26:17 +00:00
BGES ,
2023-04-09 19:08:35 +00:00
BLES ,
2024-01-08 23:57:02 +00:00
SCC ,
SCS ,
2022-12-28 20:19:38 +00:00
SZ ,
SNZ ,
2022-03-27 12:23:01 +00:00
SEQ ,
SNE ,
2022-12-27 18:33:28 +00:00
SLT ,
SLTS ,
2022-03-27 12:23:01 +00:00
SGT ,
SGTS ,
2022-12-27 18:33:28 +00:00
SLE ,
SLES ,
2022-03-27 12:23:01 +00:00
SGE ,
SGES ,
2022-03-18 23:57:35 +00:00
2022-03-23 00:52:01 +00:00
INC ,
2022-03-30 21:40:39 +00:00
INCM ,
2022-03-23 00:52:01 +00:00
DEC ,
2022-03-30 21:40:39 +00:00
DECM ,
2022-03-18 23:57:35 +00:00
NEG ,
2022-05-18 20:15:42 +00:00
NEGM ,
2022-07-12 13:15:28 +00:00
ADDR ,
2022-03-18 23:57:35 +00:00
ADD ,
2022-05-19 20:54:50 +00:00
ADDM ,
2022-07-12 13:15:28 +00:00
SUBR ,
2022-03-18 23:57:35 +00:00
SUB ,
2022-05-19 20:54:50 +00:00
SUBM ,
2022-07-12 13:15:28 +00:00
MULR ,
2022-03-18 23:57:35 +00:00
MUL ,
2022-05-19 20:54:50 +00:00
MULM ,
2022-07-12 13:15:28 +00:00
DIVR ,
2022-03-18 23:57:35 +00:00
DIV ,
2022-05-19 20:54:50 +00:00
DIVM ,
2022-07-12 13:15:28 +00:00
DIVSR ,
2022-05-19 20:08:22 +00:00
DIVS ,
2022-05-19 20:54:50 +00:00
DIVSM ,
2022-07-12 13:15:28 +00:00
MODR ,
2022-03-23 00:52:01 +00:00
MOD ,
2023-03-29 21:46:44 +00:00
DIVMODR ,
DIVMOD ,
2022-04-11 20:39:33 +00:00
SQRT ,
2023-08-13 22:50:40 +00:00
SQUARE ,
2022-04-11 20:39:33 +00:00
SGN ,
2022-04-18 17:59:48 +00:00
CMP ,
2023-07-14 21:17:29 +00:00
CMPI ,
2022-03-18 23:57:35 +00:00
EXT ,
EXTS ,
2022-07-12 13:54:35 +00:00
ANDR ,
2022-03-18 23:57:35 +00:00
AND ,
2022-05-20 17:43:21 +00:00
ANDM ,
2022-07-12 13:54:35 +00:00
ORR ,
2022-03-18 23:57:35 +00:00
OR ,
2022-05-20 17:43:21 +00:00
ORM ,
2022-07-12 13:54:35 +00:00
XORR ,
2022-03-18 23:57:35 +00:00
XOR ,
2022-05-18 20:15:42 +00:00
XORM ,
2022-06-28 23:13:08 +00:00
INV ,
INVM ,
2022-05-11 13:13:44 +00:00
ASRN ,
2022-05-23 18:10:37 +00:00
ASRNM ,
2022-05-11 13:13:44 +00:00
LSRN ,
2022-05-23 18:10:37 +00:00
LSRNM ,
2022-05-11 13:13:44 +00:00
LSLN ,
2022-05-23 18:10:37 +00:00
LSLNM ,
2022-05-11 13:50:51 +00:00
ASR ,
2022-05-23 18:10:37 +00:00
ASRM ,
2022-05-11 13:50:51 +00:00
LSR ,
2022-05-23 18:10:37 +00:00
LSRM ,
2022-05-11 13:50:51 +00:00
LSL ,
2022-05-23 18:10:37 +00:00
LSLM ,
2022-03-18 23:57:35 +00:00
ROR ,
2022-05-23 18:26:44 +00:00
RORM ,
2022-04-08 22:49:23 +00:00
ROXR ,
2022-05-23 18:26:44 +00:00
ROXRM ,
2022-03-18 23:57:35 +00:00
ROL ,
2022-05-23 18:26:44 +00:00
ROLM ,
2022-04-08 22:49:23 +00:00
ROXL ,
2022-05-23 18:26:44 +00:00
ROXLM ,
2022-03-18 23:57:35 +00:00
2022-04-24 22:10:12 +00:00
FFROMUB ,
FFROMSB ,
FFROMUW ,
FFROMSW ,
FTOUB ,
FTOSB ,
FTOUW ,
FTOSW ,
2022-05-02 18:16:45 +00:00
FPOW ,
FABS ,
FSIN ,
FCOS ,
FTAN ,
FATAN ,
FLN ,
FLOG ,
FROUND ,
FFLOOR ,
FCEIL ,
2022-05-11 15:07:21 +00:00
FCOMP ,
2022-04-24 22:10:12 +00:00
2022-04-08 22:49:23 +00:00
CLC ,
SEC ,
2022-03-23 00:52:01 +00:00
PUSH ,
POP ,
2024-01-16 19:41:53 +00:00
PUSHST ,
POPST ,
2022-04-10 22:25:00 +00:00
MSIG ,
2022-03-28 21:49:44 +00:00
CONCAT ,
2023-05-03 20:31:04 +00:00
BREAKPOINT
2022-03-18 23:57:35 +00:00
}
2024-01-07 21:10:43 +00:00
val OpcodesThatJump = arrayOf (
2022-10-25 20:57:04 +00:00
Opcode . JUMP ,
2023-07-07 16:25:05 +00:00
Opcode . JUMPI ,
2023-03-12 20:54:59 +00:00
Opcode . RETURN ,
2023-04-11 20:28:19 +00:00
Opcode . RETURNR
2022-10-25 20:57:04 +00:00
)
2024-01-07 21:10:43 +00:00
val OpcodesThatBranch = arrayOf (
2022-09-29 16:18:11 +00:00
Opcode . JUMP ,
2023-07-07 16:25:05 +00:00
Opcode . JUMPI ,
2022-09-29 16:18:11 +00:00
Opcode . RETURN ,
2023-04-11 20:28:19 +00:00
Opcode . RETURNR ,
2023-12-10 20:15:50 +00:00
Opcode . CALLI ,
2022-10-23 23:57:37 +00:00
Opcode . CALL ,
Opcode . SYSCALL ,
2022-09-29 16:18:11 +00:00
Opcode . BSTCC ,
Opcode . BSTCS ,
Opcode . BSTEQ ,
Opcode . BSTNE ,
Opcode . BSTNEG ,
Opcode . BSTPOS ,
2022-09-30 13:27:03 +00:00
Opcode . BSTVC ,
Opcode . BSTVS ,
2023-04-09 19:08:35 +00:00
Opcode . BGTR ,
2022-09-29 16:18:11 +00:00
Opcode . BGT ,
2023-04-09 19:08:35 +00:00
Opcode . BLT ,
Opcode . BGTSR ,
2022-09-29 16:18:11 +00:00
Opcode . BGTS ,
2023-04-09 19:08:35 +00:00
Opcode . BLTS ,
Opcode . BGER ,
2022-09-29 16:18:11 +00:00
Opcode . BGE ,
2023-04-09 19:08:35 +00:00
Opcode . BLE ,
Opcode . BGESR ,
Opcode . BGES ,
Opcode . BLES
2022-09-29 16:18:11 +00:00
)
2024-01-07 21:10:43 +00:00
val OpcodesThatSetStatusbitsIncludingCarry = arrayOf (
2023-07-14 21:17:29 +00:00
Opcode . CMP ,
Opcode . CMPI
)
2024-01-07 21:10:43 +00:00
val OpcodesThatSetStatusbitsButNotCarry = arrayOf (
2023-07-14 21:17:29 +00:00
Opcode . LOAD ,
Opcode . LOADM ,
Opcode . LOADI ,
Opcode . LOADX ,
Opcode . LOADIX ,
Opcode . LOADR ,
2024-03-21 22:40:36 +00:00
Opcode . LOADHA ,
Opcode . LOADHX ,
Opcode . LOADHY ,
Opcode . LOADHAX ,
Opcode . LOADHAY ,
Opcode . LOADHXY ,
2024-01-25 23:12:04 +00:00
Opcode . NEG ,
Opcode . NEGM ,
2023-07-14 21:17:29 +00:00
Opcode . INC ,
Opcode . INCM ,
Opcode . DEC ,
2024-01-07 21:10:43 +00:00
Opcode . DECM ,
Opcode . ANDM ,
Opcode . ANDR ,
Opcode . AND ,
Opcode . ORM ,
Opcode . ORR ,
Opcode . OR ,
Opcode . XORM ,
Opcode . XORR ,
2024-01-25 23:12:04 +00:00
Opcode . XOR ,
2023-07-14 21:17:29 +00:00
)
2024-01-07 21:10:43 +00:00
val OpcodesThatDependOnCarry = arrayOf (
Opcode . BSTCC ,
Opcode . BSTCS ,
Opcode . BSTPOS ,
Opcode . BSTNEG ,
Opcode . ROXL ,
Opcode . ROXLM ,
Opcode . ROXR ,
Opcode . ROXRM ,
)
2024-02-24 12:15:44 +00:00
val OpcodesThatSetRegFromStatusbits = arrayOf (
Opcode . SCC ,
Opcode . SCS ,
Opcode . SZ ,
Opcode . SNZ ,
Opcode . SEQ ,
Opcode . SNE ,
Opcode . SLT ,
Opcode . SLTS ,
Opcode . SGT ,
Opcode . SGTS ,
Opcode . SLE ,
Opcode . SLES ,
Opcode . SGE ,
Opcode . SGES
)
2023-11-16 20:33:43 +00:00
val OpcodesThatSetStatusbits = OpcodesThatSetStatusbitsButNotCarry + OpcodesThatSetStatusbitsIncludingCarry
2023-07-14 21:17:29 +00:00
2022-09-30 13:27:03 +00:00
enum class IRDataType {
2022-03-18 23:57:35 +00:00
BYTE ,
2022-04-24 22:10:12 +00:00
WORD ,
FLOAT
2022-03-23 00:52:01 +00:00
// TODO add INT (32-bit)? INT24 (24-bit)?
2022-03-18 23:57:35 +00:00
}
2022-08-07 15:43:40 +00:00
enum class OperandDirection {
2022-09-30 18:18:14 +00:00
UNUSED ,
2023-03-12 19:08:42 +00:00
READ ,
WRITE ,
READWRITE
2022-08-07 15:43:40 +00:00
}
2022-09-30 13:27:03 +00:00
data class InstructionFormat ( val datatype : IRDataType ? ,
2022-09-30 18:18:14 +00:00
val reg1 : OperandDirection ,
val reg2 : OperandDirection ,
2023-07-20 21:58:52 +00:00
val reg3 : OperandDirection ,
2022-09-30 18:18:14 +00:00
val fpReg1 : OperandDirection ,
val fpReg2 : OperandDirection ,
2023-04-09 13:06:40 +00:00
val address : OperandDirection ,
2023-05-12 21:26:36 +00:00
val immediate : Boolean ,
val funcCall : Boolean ,
val sysCall : Boolean ) {
2022-04-24 22:10:12 +00:00
companion object {
2022-09-30 13:27:03 +00:00
fun from ( spec : String ) : Map < IRDataType ? , InstructionFormat > {
val result = mutableMapOf < IRDataType ? , InstructionFormat > ( )
2022-04-24 22:10:12 +00:00
for ( part in spec . split ( '|' ) . map { it . trim ( ) } ) {
2022-09-30 18:18:14 +00:00
var reg1 = OperandDirection . UNUSED
var reg2 = OperandDirection . UNUSED
2023-07-20 21:58:52 +00:00
var reg3 = OperandDirection . UNUSED
2022-09-30 18:18:14 +00:00
var fpreg1 = OperandDirection . UNUSED
var fpreg2 = OperandDirection . UNUSED
2023-04-09 13:06:40 +00:00
var address = OperandDirection . UNUSED
var immediate = false
2022-04-24 22:10:12 +00:00
val splits = part . splitToSequence ( ',' ) . iterator ( )
val typespec = splits . next ( )
2023-05-12 21:26:36 +00:00
var funcCall = false
var sysCall = false
2022-04-24 22:10:12 +00:00
while ( splits . hasNext ( ) ) {
when ( splits . next ( ) ) {
2023-05-12 21:26:36 +00:00
" <r1 " -> reg1 = OperandDirection . READ
" >r1 " -> reg1 = OperandDirection . WRITE
" <>r1 " -> reg1 = OperandDirection . READWRITE
2023-03-12 19:08:42 +00:00
" <r2 " -> reg2 = OperandDirection . READ
2023-07-20 21:58:52 +00:00
" <r3 " -> reg3 = OperandDirection . READ
2023-05-12 21:26:36 +00:00
" <fr1 " -> fpreg1 = OperandDirection . READ
" >fr1 " -> fpreg1 = OperandDirection . WRITE
" <>fr1 " -> fpreg1 = OperandDirection . READWRITE
2023-03-12 19:08:42 +00:00
" <fr2 " -> fpreg2 = OperandDirection . READ
2023-04-09 13:06:40 +00:00
" >i " , " <>i " -> throw IllegalArgumentException ( " can't write into an immediate value " )
" <i " -> immediate = true
" <a " -> address = OperandDirection . READ
" >a " -> address = OperandDirection . WRITE
" <>a " -> address = OperandDirection . READWRITE
2023-05-12 21:26:36 +00:00
" call " -> funcCall = true
" syscall " -> sysCall = true
2022-04-24 22:10:12 +00:00
else -> throw IllegalArgumentException ( spec )
}
}
2023-04-09 13:06:40 +00:00
2022-04-24 22:10:12 +00:00
if ( typespec == " N " )
2023-07-20 21:58:52 +00:00
result [ null ] = InstructionFormat ( null , reg1 , reg2 , reg3 , fpreg1 , fpreg2 , address , immediate , funcCall , sysCall )
2022-04-24 22:10:12 +00:00
if ( 'B' in typespec )
2023-07-20 21:58:52 +00:00
result [ IRDataType . BYTE ] = InstructionFormat ( IRDataType . BYTE , reg1 , reg2 , reg3 , fpreg1 , fpreg2 , address , immediate , funcCall , sysCall )
2022-04-24 22:10:12 +00:00
if ( 'W' in typespec )
2023-07-20 21:58:52 +00:00
result [ IRDataType . WORD ] = InstructionFormat ( IRDataType . WORD , reg1 , reg2 , reg3 , fpreg1 , fpreg2 , address , immediate , funcCall , sysCall )
2022-04-24 22:10:12 +00:00
if ( 'F' in typespec )
2023-07-20 21:58:52 +00:00
result [ IRDataType . FLOAT ] = InstructionFormat ( IRDataType . FLOAT , reg1 , reg2 , reg3 , fpreg1 , fpreg2 , address , immediate , funcCall , sysCall )
2022-04-24 22:10:12 +00:00
}
return result
}
}
}
2022-03-18 23:57:35 +00:00
2022-08-07 15:43:40 +00:00
/ *
2023-03-12 19:08:42 +00:00
< X = X is not modified ( readonly value )
> X = X is overwritten with output value ( write value )
< > X = X is modified ( read + written )
2023-04-09 13:06:40 +00:00
where X is one of :
r0 .. . = integer register
fr0 .. . = fp register
a = memory address
i = immediate value
2022-08-07 15:43:40 +00:00
* /
2022-03-18 23:57:35 +00:00
val instructionFormats = mutableMapOf (
2022-04-24 22:10:12 +00:00
Opcode . NOP to InstructionFormat . from ( " N " ) ,
2023-04-09 13:06:40 +00:00
Opcode . LOAD to InstructionFormat . from ( " BW,>r1,<i | F,>fr1,<i " ) ,
Opcode . LOADM to InstructionFormat . from ( " BW,>r1,<a | F,>fr1,<a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . LOADI to InstructionFormat . from ( " BW,>r1,<r2 | F,>fr1,<r1 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . LOADX to InstructionFormat . from ( " BW,>r1,<r2,<a | F,>fr1,<r1,<a " ) ,
Opcode . LOADIX to InstructionFormat . from ( " BW,>r1,<r2,<a | F,>fr1,<r1,<a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . LOADR to InstructionFormat . from ( " BW,>r1,<r2 | F,>fr1,<fr2 " ) ,
2024-03-21 22:40:36 +00:00
Opcode . LOADHA to InstructionFormat . from ( " B,>r1 " ) ,
Opcode . LOADHA to InstructionFormat . from ( " B,>r1 " ) ,
Opcode . LOADHX to InstructionFormat . from ( " B,>r1 " ) ,
Opcode . LOADHY to InstructionFormat . from ( " B,>r1 " ) ,
Opcode . LOADHAX to InstructionFormat . from ( " W,>r1 " ) ,
Opcode . LOADHAY to InstructionFormat . from ( " W,>r1 " ) ,
Opcode . LOADHXY to InstructionFormat . from ( " W,>r1 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . STOREM to InstructionFormat . from ( " BW,<r1,>a | F,<fr1,>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . STOREI to InstructionFormat . from ( " BW,<r1,<r2 | F,<fr1,<r1 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . STOREX to InstructionFormat . from ( " BW,<r1,<r2,>a | F,<fr1,<r1,>a " ) ,
Opcode . STOREIX to InstructionFormat . from ( " BW,<r1,<r2,>a | F,<fr1,<r1,>a " ) ,
Opcode . STOREZM to InstructionFormat . from ( " BW,>a | F,>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . STOREZI to InstructionFormat . from ( " BW,<r1 | F,<r1 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . STOREZX to InstructionFormat . from ( " BW,<r1,>a | F,<r1,>a " ) ,
2024-03-21 22:40:36 +00:00
Opcode . STOREHA to InstructionFormat . from ( " B,<r1 " ) ,
Opcode . STOREHA to InstructionFormat . from ( " B,<r1 " ) ,
Opcode . STOREHX to InstructionFormat . from ( " B,<r1 " ) ,
Opcode . STOREHY to InstructionFormat . from ( " B,<r1 " ) ,
Opcode . STOREHAX to InstructionFormat . from ( " W,<r1 " ) ,
Opcode . STOREHAY to InstructionFormat . from ( " W,<r1 " ) ,
Opcode . STOREHXY to InstructionFormat . from ( " W,<r1 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . JUMP to InstructionFormat . from ( " N,<a " ) ,
2024-02-22 10:35:54 +00:00
Opcode . JUMPI to InstructionFormat . from ( " N,<a " ) ,
2023-09-18 21:22:03 +00:00
Opcode . PREPARECALL to InstructionFormat . from ( " N,<i " ) ,
2023-12-10 20:15:50 +00:00
Opcode . CALLI to InstructionFormat . from ( " N,<r1 " ) ,
2023-05-12 21:26:36 +00:00
Opcode . CALL to InstructionFormat . from ( " N,call " ) ,
Opcode . SYSCALL to InstructionFormat . from ( " N,syscall " ) ,
2022-04-24 22:10:12 +00:00
Opcode . RETURN to InstructionFormat . from ( " N " ) ,
2023-04-13 21:45:02 +00:00
Opcode . RETURNR to InstructionFormat . from ( " BW,>r1 | F,>fr1 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . BSTCC to InstructionFormat . from ( " N,<a " ) ,
Opcode . BSTCS to InstructionFormat . from ( " N,<a " ) ,
Opcode . BSTEQ to InstructionFormat . from ( " N,<a " ) ,
Opcode . BSTNE to InstructionFormat . from ( " N,<a " ) ,
Opcode . BSTNEG to InstructionFormat . from ( " N,<a " ) ,
Opcode . BSTPOS to InstructionFormat . from ( " N,<a " ) ,
Opcode . BSTVC to InstructionFormat . from ( " N,<a " ) ,
Opcode . BSTVS to InstructionFormat . from ( " N,<a " ) ,
2023-04-09 19:08:35 +00:00
Opcode . BGTR to InstructionFormat . from ( " BW,<r1,<r2,<a " ) ,
Opcode . BGT to InstructionFormat . from ( " BW,<r1,<i,<a " ) ,
Opcode . BLT to InstructionFormat . from ( " BW,<r1,<i,<a " ) ,
Opcode . BGTSR to InstructionFormat . from ( " BW,<r1,<r2,<a " ) ,
Opcode . BGTS to InstructionFormat . from ( " BW,<r1,<i,<a " ) ,
Opcode . BLTS to InstructionFormat . from ( " BW,<r1,<i,<a " ) ,
Opcode . BGER to InstructionFormat . from ( " BW,<r1,<r2,<a " ) ,
Opcode . BGE to InstructionFormat . from ( " BW,<r1,<i,<a " ) ,
Opcode . BLE to InstructionFormat . from ( " BW,<r1,<i,<a " ) ,
Opcode . BGESR to InstructionFormat . from ( " BW,<r1,<r2,<a " ) ,
Opcode . BGES to InstructionFormat . from ( " BW,<r1,<i,<a " ) ,
Opcode . BLES to InstructionFormat . from ( " BW,<r1,<i,<a " ) ,
2024-01-08 23:57:02 +00:00
Opcode . SCC to InstructionFormat . from ( " BW,>r1 " ) ,
Opcode . SCS to InstructionFormat . from ( " BW,>r1 " ) ,
2022-12-28 20:19:38 +00:00
Opcode . SZ to InstructionFormat . from ( " BW,>r1,<r2 " ) ,
Opcode . SNZ to InstructionFormat . from ( " BW,>r1,<r2 " ) ,
2023-07-20 21:58:52 +00:00
Opcode . SEQ to InstructionFormat . from ( " BW,<>r1,<r2,<r3 " ) ,
Opcode . SNE to InstructionFormat . from ( " BW,<>r1,<r2,<r3 " ) ,
Opcode . SLT to InstructionFormat . from ( " BW,<>r1,<r2,<r3 " ) ,
Opcode . SLTS to InstructionFormat . from ( " BW,<>r1,<r2,<r3 " ) ,
Opcode . SGT to InstructionFormat . from ( " BW,<>r1,<r2,<r3 " ) ,
Opcode . SGTS to InstructionFormat . from ( " BW,<>r1,<r2,<r3 " ) ,
Opcode . SLE to InstructionFormat . from ( " BW,<>r1,<r2,<r3 " ) ,
Opcode . SLES to InstructionFormat . from ( " BW,<>r1,<r2,<r3 " ) ,
Opcode . SGE to InstructionFormat . from ( " BW,<>r1,<r2,<r3 " ) ,
Opcode . SGES to InstructionFormat . from ( " BW,<>r1,<r2,<r3 " ) ,
2023-03-06 20:42:08 +00:00
Opcode . INC to InstructionFormat . from ( " BW,<>r1 | F,<>fr1 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . INCM to InstructionFormat . from ( " BW,<>a | F,<>a " ) ,
2023-03-06 20:42:08 +00:00
Opcode . DEC to InstructionFormat . from ( " BW,<>r1 | F,<>fr1 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . DECM to InstructionFormat . from ( " BW,<>a | F,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . NEG to InstructionFormat . from ( " BW,<>r1 | F,<>fr1 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . NEGM to InstructionFormat . from ( " BW,<>a | F,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . ADDR to InstructionFormat . from ( " BW,<>r1,<r2 | F,<>fr1,<fr2 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . ADD to InstructionFormat . from ( " BW,<>r1,<i | F,<>fr1,<i " ) ,
Opcode . ADDM to InstructionFormat . from ( " BW,<r1,<>a | F,<fr1,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . SUBR to InstructionFormat . from ( " BW,<>r1,<r2 | F,<>fr1,<fr2 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . SUB to InstructionFormat . from ( " BW,<>r1,<i | F,<>fr1,<i " ) ,
Opcode . SUBM to InstructionFormat . from ( " BW,<r1,<>a | F,<fr1,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . MULR to InstructionFormat . from ( " BW,<>r1,<r2 | F,<>fr1,<fr2 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . MUL to InstructionFormat . from ( " BW,<>r1,<i | F,<>fr1,<i " ) ,
Opcode . MULM to InstructionFormat . from ( " BW,<r1,<>a | F,<fr1,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . DIVR to InstructionFormat . from ( " BW,<>r1,<r2 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . DIV to InstructionFormat . from ( " BW,<>r1,<i " ) ,
Opcode . DIVM to InstructionFormat . from ( " BW,<r1,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . DIVSR to InstructionFormat . from ( " BW,<>r1,<r2 | F,<>fr1,<fr2 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . DIVS to InstructionFormat . from ( " BW,<>r1,<i | F,<>fr1,<i " ) ,
Opcode . DIVSM to InstructionFormat . from ( " BW,<r1,<>a | F,<fr1,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . SQRT to InstructionFormat . from ( " BW,>r1,<r2 | F,>fr1,<fr2 " ) ,
2023-08-13 22:50:40 +00:00
Opcode . SQUARE to InstructionFormat . from ( " BW,>r1,<r2 | F,>fr1,<fr2 " ) ,
2024-01-16 00:23:41 +00:00
Opcode . SGN to InstructionFormat . from ( " BW,>r1,<r2 | F,>r1,<fr1 " ) ,
2022-08-07 15:43:40 +00:00
Opcode . MODR to InstructionFormat . from ( " BW,<>r1,<r2 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . MOD to InstructionFormat . from ( " BW,<>r1,<i " ) ,
2023-03-29 21:46:44 +00:00
Opcode . DIVMODR to InstructionFormat . from ( " BW,<>r1,<r2 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . DIVMOD to InstructionFormat . from ( " BW,<>r1,<i " ) ,
2022-08-07 15:43:40 +00:00
Opcode . CMP to InstructionFormat . from ( " BW,<r1,<r2 " ) ,
2023-07-14 21:17:29 +00:00
Opcode . CMPI to InstructionFormat . from ( " BW,<r1,<i " ) ,
2023-07-08 20:42:11 +00:00
Opcode . EXT to InstructionFormat . from ( " BW,>r1,<r2 " ) ,
Opcode . EXTS to InstructionFormat . from ( " BW,>r1,<r2 " ) ,
2022-08-07 15:43:40 +00:00
Opcode . ANDR to InstructionFormat . from ( " BW,<>r1,<r2 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . AND to InstructionFormat . from ( " BW,<>r1,<i " ) ,
Opcode . ANDM to InstructionFormat . from ( " BW,<r1,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . ORR to InstructionFormat . from ( " BW,<>r1,<r2 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . OR to InstructionFormat . from ( " BW,<>r1,<i " ) ,
Opcode . ORM to InstructionFormat . from ( " BW,<r1,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . XORR to InstructionFormat . from ( " BW,<>r1,<r2 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . XOR to InstructionFormat . from ( " BW,<>r1,<i " ) ,
Opcode . XORM to InstructionFormat . from ( " BW,<r1,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . INV to InstructionFormat . from ( " BW,<>r1 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . INVM to InstructionFormat . from ( " BW,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . ASRN to InstructionFormat . from ( " BW,<>r1,<r2 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . ASRNM to InstructionFormat . from ( " BW,<r1,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . LSRN to InstructionFormat . from ( " BW,<>r1,<r2 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . LSRNM to InstructionFormat . from ( " BW,<r1,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . LSLN to InstructionFormat . from ( " BW,<>r1,<r2 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . LSLNM to InstructionFormat . from ( " BW,<r1,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . ASR to InstructionFormat . from ( " BW,<>r1 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . ASRM to InstructionFormat . from ( " BW,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . LSR to InstructionFormat . from ( " BW,<>r1 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . LSRM to InstructionFormat . from ( " BW,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . LSL to InstructionFormat . from ( " BW,<>r1 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . LSLM to InstructionFormat . from ( " BW,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . ROR to InstructionFormat . from ( " BW,<>r1 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . RORM to InstructionFormat . from ( " BW,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . ROXR to InstructionFormat . from ( " BW,<>r1 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . ROXRM to InstructionFormat . from ( " BW,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . ROL to InstructionFormat . from ( " BW,<>r1 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . ROLM to InstructionFormat . from ( " BW,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . ROXL to InstructionFormat . from ( " BW,<>r1 " ) ,
2023-04-09 13:06:40 +00:00
Opcode . ROXLM to InstructionFormat . from ( " BW,<>a " ) ,
2022-08-07 15:43:40 +00:00
Opcode . FFROMUB to InstructionFormat . from ( " F,>fr1,<r1 " ) ,
Opcode . FFROMSB to InstructionFormat . from ( " F,>fr1,<r1 " ) ,
Opcode . FFROMUW to InstructionFormat . from ( " F,>fr1,<r1 " ) ,
Opcode . FFROMSW to InstructionFormat . from ( " F,>fr1,<r1 " ) ,
Opcode . FTOUB to InstructionFormat . from ( " F,>r1,<fr1 " ) ,
Opcode . FTOSB to InstructionFormat . from ( " F,>r1,<fr1 " ) ,
Opcode . FTOUW to InstructionFormat . from ( " F,>r1,<fr1 " ) ,
Opcode . FTOSW to InstructionFormat . from ( " F,>r1,<fr1 " ) ,
Opcode . FPOW to InstructionFormat . from ( " F,<>fr1,<fr2 " ) ,
Opcode . FABS to InstructionFormat . from ( " F,>fr1,<fr2 " ) ,
Opcode . FCOMP to InstructionFormat . from ( " F,>r1,<fr1,<fr2 " ) ,
Opcode . FSIN to InstructionFormat . from ( " F,>fr1,<fr2 " ) ,
Opcode . FCOS to InstructionFormat . from ( " F,>fr1,<fr2 " ) ,
Opcode . FTAN to InstructionFormat . from ( " F,>fr1,<fr2 " ) ,
Opcode . FATAN to InstructionFormat . from ( " F,>fr1,<fr2 " ) ,
Opcode . FLN to InstructionFormat . from ( " F,>fr1,<fr2 " ) ,
Opcode . FLOG to InstructionFormat . from ( " F,>fr1,<fr2 " ) ,
Opcode . FROUND to InstructionFormat . from ( " F,>fr1,<fr2 " ) ,
Opcode . FFLOOR to InstructionFormat . from ( " F,>fr1,<fr2 " ) ,
Opcode . FCEIL to InstructionFormat . from ( " F,>fr1,<fr2 " ) ,
Opcode . MSIG to InstructionFormat . from ( " BW,>r1,<r2 " ) ,
2023-04-10 14:16:35 +00:00
Opcode . PUSH to InstructionFormat . from ( " BW,<r1 | F,<fr1 " ) ,
Opcode . POP to InstructionFormat . from ( " BW,>r1 | F,>fr1 " ) ,
2024-01-16 19:41:53 +00:00
Opcode . PUSHST to InstructionFormat . from ( " N " ) ,
Opcode . POPST to InstructionFormat . from ( " N " ) ,
2023-07-20 21:58:52 +00:00
Opcode . CONCAT to InstructionFormat . from ( " BW,<>r1,<r2,<r3 " ) ,
2022-04-24 22:10:12 +00:00
Opcode . CLC to InstructionFormat . from ( " N " ) ,
Opcode . SEC to InstructionFormat . from ( " N " ) ,
Opcode . BREAKPOINT to InstructionFormat . from ( " N " ) ,
2022-03-18 23:57:35 +00:00
)
2022-09-29 16:18:11 +00:00
2023-05-12 21:26:36 +00:00
class FunctionCallArgs (
var arguments : List < ArgumentSpec > ,
2024-03-22 23:20:12 +00:00
val returns : List < RegSpec >
2023-05-12 21:26:36 +00:00
) {
class RegSpec ( val dt : IRDataType , val registerNum : Int , val cpuRegister : RegisterOrStatusflag ? )
2024-01-05 12:32:16 +00:00
class ArgumentSpec ( val name : String , val address : Int ? , val reg : RegSpec ) {
init {
require ( address == null || address >= 0 ) {
" address must be >=0 "
}
}
}
2023-05-12 21:26:36 +00:00
}
2022-09-29 16:18:11 +00:00
data class IRInstruction (
val opcode : Opcode ,
2022-09-30 13:27:03 +00:00
val type : IRDataType ? = null ,
2022-09-29 16:18:11 +00:00
val reg1 : Int ? = null , // 0-$ffff
val reg2 : Int ? = null , // 0-$ffff
2023-07-20 21:58:52 +00:00
val reg3 : Int ? = null , // 0-$ffff
2022-09-29 16:18:11 +00:00
val fpReg1 : Int ? = null , // 0-$ffff
val fpReg2 : Int ? = null , // 0-$ffff
2023-04-09 13:06:40 +00:00
val immediate : Int ? = null , // 0-$ff or $ffff if word
2023-11-20 22:19:08 +00:00
val immediateFp : Double ? = null ,
2023-04-09 13:06:40 +00:00
val address : Int ? = null , // 0-$ffff
2023-05-03 20:31:04 +00:00
val labelSymbol : String ? = null , // symbolic label name as alternative to address (so only for Branch/jump/call Instructions!)
2024-01-13 12:55:16 +00:00
private val symbolOffset : Int ? = null , // offset to add on labelSymbol (used to index into an array variable)
2023-05-12 21:26:36 +00:00
var branchTarget : IRCodeChunkBase ? = null , // Will be linked after loading in IRProgram.linkChunks()! This is the chunk that the branch labelSymbol points to.
val fcallArgs : FunctionCallArgs ? = null // will be set for the CALL and SYSCALL instructions.
2022-10-06 22:34:56 +00:00
) {
2022-09-29 16:18:11 +00:00
// reg1 and fpreg1 can be IN/OUT/INOUT (all others are readonly INPUT)
// This knowledge is useful in IL assembly optimizers to see how registers are used.
val reg1direction : OperandDirection
2022-09-30 18:18:14 +00:00
val reg2direction : OperandDirection
2023-07-20 21:58:52 +00:00
val reg3direction : OperandDirection
2022-09-29 16:18:11 +00:00
val fpReg1direction : OperandDirection
2022-09-30 18:18:14 +00:00
val fpReg2direction : OperandDirection
2024-01-13 12:55:16 +00:00
val labelSymbolOffset = if ( symbolOffset == 0 ) null else symbolOffset
2022-09-29 16:18:11 +00:00
init {
2024-01-13 12:55:16 +00:00
if ( labelSymbol != null ) {
require ( labelSymbol . first ( ) != '_' ) { " label/symbol should not start with underscore $labelSymbol " }
require ( labelSymbol . all { it . isJavaIdentifierStart ( ) || it . isJavaIdentifierPart ( ) || it == '.' } ) {
" label/symbol contains invalid character $labelSymbol "
}
}
if ( labelSymbolOffset != null ) require ( labelSymbolOffset > 0 && labelSymbol != null ) { " labelsymbol offset inconsistency " }
2022-09-29 16:18:11 +00:00
require ( reg1 == null || reg1 in 0. . 65536 ) { " reg1 out of bounds " }
require ( reg2 == null || reg2 in 0. . 65536 ) { " reg2 out of bounds " }
2023-07-20 21:58:52 +00:00
require ( reg3 == null || reg3 in 0. . 65536 ) { " reg3 out of bounds " }
2022-09-29 16:18:11 +00:00
require ( fpReg1 == null || fpReg1 in 0. . 65536 ) { " fpReg1 out of bounds " }
require ( fpReg2 == null || fpReg2 in 0. . 65536 ) { " fpReg2 out of bounds " }
2023-03-13 23:45:41 +00:00
if ( reg1 != null && reg2 != null ) require ( reg1 != reg2 ) { " reg1 must not be same as reg2 " } // note: this is ok for fpRegs as these are always the same type
2023-07-20 21:58:52 +00:00
if ( reg1 != null && reg3 != null ) require ( reg1 != reg3 ) { " reg1 must not be same as reg3 " } // note: this is ok for fpRegs as these are always the same type
if ( reg2 != null && reg3 != null ) require ( reg2 != reg3 ) { " reg2 must not be same as reg3 " } // note: this is ok for fpRegs as these are always the same type
2022-09-29 16:18:11 +00:00
val formats = instructionFormats . getValue ( opcode )
require ( type != null || formats . containsKey ( null ) ) { " missing type " }
2022-09-30 18:18:14 +00:00
val format = formats . getOrElse ( type ) { throw IllegalArgumentException ( " type $type invalid for $opcode " ) }
if ( format . reg1 != OperandDirection . UNUSED ) require ( reg1 != null ) { " missing reg1 " }
if ( format . reg2 != OperandDirection . UNUSED ) require ( reg2 != null ) { " missing reg2 " }
2023-07-20 21:58:52 +00:00
if ( format . reg3 != OperandDirection . UNUSED ) require ( reg3 != null ) { " missing reg3 " }
2022-09-30 18:18:14 +00:00
if ( format . fpReg1 != OperandDirection . UNUSED ) require ( fpReg1 != null ) { " missing fpReg1 " }
if ( format . fpReg2 != OperandDirection . UNUSED ) require ( fpReg2 != null ) { " missing fpReg2 " }
if ( format . reg1 == OperandDirection . UNUSED ) require ( reg1 == null ) { " invalid reg1 " }
if ( format . reg2 == OperandDirection . UNUSED ) require ( reg2 == null ) { " invalid reg2 " }
2023-07-20 21:58:52 +00:00
if ( format . reg3 == OperandDirection . UNUSED ) require ( reg3 == null ) { " invalid reg3 " }
2022-09-30 18:18:14 +00:00
if ( format . fpReg1 == OperandDirection . UNUSED ) require ( fpReg1 == null ) { " invalid fpReg1 " }
if ( format . fpReg2 == OperandDirection . UNUSED ) require ( fpReg2 == null ) { " invalid fpReg2 " }
2023-04-09 13:06:40 +00:00
if ( format . immediate ) {
2023-05-12 21:26:36 +00:00
if ( type == IRDataType . FLOAT )
require ( immediateFp != null ) { " missing immediate fp value " }
else
require ( immediate != null || labelSymbol != null ) { " missing immediate value or labelsymbol " }
2023-04-09 13:06:40 +00:00
}
if ( type != IRDataType . FLOAT )
require ( fpReg1 == null && fpReg2 == null ) { " int instruction can't use fp reg " }
if ( format . address != OperandDirection . UNUSED )
require ( address != null || labelSymbol != null ) { " missing an address or labelsymbol " }
if ( format . immediate && ( immediate != null || immediateFp != null ) ) {
2023-04-10 14:16:35 +00:00
if ( opcode != Opcode . SYSCALL ) {
2023-04-10 11:44:05 +00:00
when ( type ) {
IRDataType . BYTE -> require ( immediate in - 128. . 255 ) { " immediate value out of range for byte: $immediate " }
IRDataType . WORD -> require ( immediate in - 32768. . 65535 ) { " immediate value out of range for word: $immediate " }
IRDataType . FLOAT , null -> { }
}
2023-04-09 13:06:40 +00:00
}
2022-09-29 16:18:11 +00:00
}
2023-05-17 21:03:59 +00:00
if ( format . immediate ) {
if ( opcode == Opcode . LOAD )
require ( immediate != null || immediateFp != null || labelSymbol != null ) { " missing immediate value or labelsymbol " }
else
require ( immediate != null || immediateFp != null ) { " missing immediate value " }
}
2024-01-05 12:32:16 +00:00
require ( address == null || address >= 0 ) {
" address must be >=0 "
}
2023-05-17 21:03:59 +00:00
2022-09-30 18:18:14 +00:00
reg1direction = format . reg1
reg2direction = format . reg2
2023-07-20 21:58:52 +00:00
reg3direction = format . reg3
2022-09-30 18:18:14 +00:00
fpReg1direction = format . fpReg1
fpReg2direction = format . fpReg2
2022-09-29 16:18:11 +00:00
2023-04-10 14:16:35 +00:00
if ( opcode == Opcode . SYSCALL ) {
2023-04-10 11:44:05 +00:00
require ( immediate != null ) {
" syscall needs immediate integer for the syscall number "
}
}
2022-10-02 13:54:46 +00:00
}
2022-09-30 18:18:14 +00:00
2022-10-02 13:54:46 +00:00
fun addUsedRegistersCounts (
2023-04-07 20:03:13 +00:00
readRegsCounts : MutableMap < Int , Int > ,
writeRegsCounts : MutableMap < Int , Int > ,
readFpRegsCounts : MutableMap < Int , Int > ,
writeFpRegsCounts : MutableMap < Int , Int > ,
regsTypes : MutableMap < Int , MutableSet < IRDataType > >
2022-10-02 13:54:46 +00:00
) {
when ( this . reg1direction ) {
2022-09-30 18:18:14 +00:00
OperandDirection . UNUSED -> { }
2023-04-07 20:03:13 +00:00
OperandDirection . READ -> {
readRegsCounts [ this . reg1 !! ] = readRegsCounts . getValue ( this . reg1 ) + 1
if ( type != null ) {
var types = regsTypes [ this . reg1 ]
if ( types == null ) types = mutableSetOf ( )
types += type
regsTypes [ this . reg1 ] = types
}
}
OperandDirection . WRITE -> {
writeRegsCounts [ this . reg1 !! ] = writeRegsCounts . getValue ( this . reg1 ) + 1
if ( type != null ) {
var types = regsTypes [ this . reg1 ]
if ( types == null ) types = mutableSetOf ( )
types += type
regsTypes [ this . reg1 ] = types
}
}
2023-03-12 19:08:42 +00:00
OperandDirection . READWRITE -> {
2023-04-07 20:03:13 +00:00
readRegsCounts [ this . reg1 !! ] = readRegsCounts . getValue ( this . reg1 ) + 1
if ( type != null ) {
var types = regsTypes [ this . reg1 ]
if ( types == null ) types = mutableSetOf ( )
types += type
regsTypes [ this . reg1 ] = types
}
writeRegsCounts [ this . reg1 ] = writeRegsCounts . getValue ( this . reg1 ) + 1
if ( type != null ) {
var types = regsTypes [ this . reg1 ]
if ( types == null ) types = mutableSetOf ( )
types += type
regsTypes [ this . reg1 ] = types
}
2022-09-30 18:18:14 +00:00
}
}
2022-10-02 13:54:46 +00:00
when ( this . reg2direction ) {
2022-09-30 18:18:14 +00:00
OperandDirection . UNUSED -> { }
2023-04-07 20:03:13 +00:00
OperandDirection . READ -> {
writeRegsCounts [ this . reg2 !! ] = writeRegsCounts . getValue ( this . reg2 ) + 1
if ( type != null ) {
var types = regsTypes [ this . reg2 ]
if ( types == null ) types = mutableSetOf ( )
types += type
regsTypes [ this . reg2 ] = types
}
}
2023-03-12 19:08:42 +00:00
else -> throw IllegalArgumentException ( " reg2 can only be read " )
2022-09-30 18:18:14 +00:00
}
2023-07-20 21:58:52 +00:00
when ( this . reg3direction ) {
OperandDirection . UNUSED -> { }
OperandDirection . READ -> {
writeRegsCounts [ this . reg3 !! ] = writeRegsCounts . getValue ( this . reg3 ) + 1
if ( type != null ) {
var types = regsTypes [ this . reg3 ]
if ( types == null ) types = mutableSetOf ( )
types += type
regsTypes [ this . reg3 ] = types
}
}
else -> throw IllegalArgumentException ( " reg3 can only be read " )
}
2022-10-02 13:54:46 +00:00
when ( this . fpReg1direction ) {
2022-09-30 18:18:14 +00:00
OperandDirection . UNUSED -> { }
2023-04-07 20:03:13 +00:00
OperandDirection . READ -> {
readFpRegsCounts [ this . fpReg1 !! ] = readFpRegsCounts . getValue ( this . fpReg1 ) + 1
}
OperandDirection . WRITE -> writeFpRegsCounts [ this . fpReg1 !! ] = writeFpRegsCounts . getValue ( this . fpReg1 ) + 1
2023-03-12 19:08:42 +00:00
OperandDirection . READWRITE -> {
2023-04-07 20:03:13 +00:00
readFpRegsCounts [ this . fpReg1 !! ] = readFpRegsCounts . getValue ( this . fpReg1 ) + 1
writeFpRegsCounts [ this . fpReg1 ] = writeFpRegsCounts . getValue ( this . fpReg1 ) + 1
2022-09-30 18:18:14 +00:00
}
}
2022-10-02 13:54:46 +00:00
when ( this . fpReg2direction ) {
2022-09-30 18:18:14 +00:00
OperandDirection . UNUSED -> { }
2023-04-07 20:03:13 +00:00
OperandDirection . READ -> readFpRegsCounts [ this . fpReg2 !! ] = readFpRegsCounts . getValue ( this . fpReg2 ) + 1
2023-03-12 19:08:42 +00:00
else -> throw IllegalArgumentException ( " fpReg2 can only be read " )
2022-09-30 18:18:14 +00:00
}
2023-05-18 11:51:13 +00:00
if ( fcallArgs != null ) {
2024-03-22 23:20:12 +00:00
fcallArgs . returns . forEach {
if ( it . dt == IRDataType . FLOAT )
writeFpRegsCounts [ it . registerNum ] = writeFpRegsCounts . getValue ( it . registerNum ) + 1
2023-05-18 11:51:13 +00:00
else {
writeRegsCounts [ it . registerNum ] = writeRegsCounts . getValue ( it . registerNum ) + 1
val types = regsTypes [ it . registerNum ]
2024-03-22 23:20:12 +00:00
if ( types == null ) {
2023-05-18 11:51:13 +00:00
regsTypes [ it . registerNum ] = mutableSetOf ( it . dt )
} else {
types += it . dt
regsTypes [ it . registerNum ] = types
}
}
}
fcallArgs . arguments . forEach {
if ( it . reg . dt == IRDataType . FLOAT )
readFpRegsCounts [ it . reg . registerNum ] = readFpRegsCounts . getValue ( it . reg . registerNum ) + 1
else {
readRegsCounts [ it . reg . registerNum ] = readRegsCounts . getValue ( it . reg . registerNum ) + 1
val types = regsTypes [ it . reg . registerNum ]
if ( types == null ) {
regsTypes [ it . reg . registerNum ] = mutableSetOf ( it . reg . dt )
} else {
types += it . reg . dt
regsTypes [ it . reg . registerNum ] = types
}
}
}
}
2022-09-29 16:18:11 +00:00
}
override fun toString ( ) : String {
val result = mutableListOf ( opcode . name . lowercase ( ) )
when ( type ) {
2022-09-30 13:27:03 +00:00
IRDataType . BYTE -> result . add ( " .b " )
IRDataType . WORD -> result . add ( " .w " )
IRDataType . FLOAT -> result . add ( " .f " )
2022-09-29 16:18:11 +00:00
else -> result . add ( " " )
}
2023-05-12 21:26:36 +00:00
if ( this . fcallArgs != null ) {
2023-05-14 14:48:48 +00:00
immediate ?. let { result . add ( it . toHex ( ) ) } // syscall
2024-01-13 12:55:16 +00:00
if ( labelSymbol != null ) {
// regular subroutine call
result . add ( labelSymbol )
if ( labelSymbolOffset != null )
result . add ( " + $labelSymbolOffset " )
}
2023-05-14 14:48:48 +00:00
address ?. let { result . add ( address . toHex ( ) ) } // romcall
2023-05-12 21:26:36 +00:00
result . add ( " ( " )
fcallArgs . arguments . forEach {
val location = if ( it . address == null ) {
if ( it . name . isBlank ( ) ) " " else it . name + " = "
} else " ${it.address} = "
2023-05-14 14:48:48 +00:00
val cpuReg = if ( it . reg . cpuRegister == null ) " " else {
if ( it . reg . cpuRegister . registerOrPair != null )
" @ " + it . reg . cpuRegister . registerOrPair . toString ( )
else
" @ " + it . reg . cpuRegister . statusflag . toString ( )
}
2023-05-12 21:26:36 +00:00
when ( it . reg . dt ) {
2023-05-14 14:48:48 +00:00
IRDataType . BYTE -> result . add ( " ${location} r ${it.reg.registerNum} .b $cpuReg , " )
IRDataType . WORD -> result . add ( " ${location} r ${it.reg.registerNum} .w $cpuReg , " )
IRDataType . FLOAT -> result . add ( " ${location} fr ${it.reg.registerNum} .f $cpuReg , " )
2023-05-12 21:26:36 +00:00
}
}
if ( result . last ( ) . endsWith ( ',' ) ) {
result . add ( result . removeLast ( ) . trimEnd ( ',' ) )
}
result . add ( " ) " )
2023-05-14 14:48:48 +00:00
val returns = fcallArgs . returns
2024-03-22 23:20:12 +00:00
if ( returns . isNotEmpty ( ) ) {
2023-05-12 21:26:36 +00:00
result . add ( " : " )
2024-03-22 23:20:12 +00:00
val resultParts = returns . map { returnspec ->
val cpuReg = if ( returnspec . cpuRegister == null ) " " else {
if ( returnspec . cpuRegister . registerOrPair != null )
returnspec . cpuRegister . registerOrPair . toString ( )
else
returnspec . cpuRegister . statusflag . toString ( )
2023-12-14 20:16:14 +00:00
}
2024-03-22 23:20:12 +00:00
if ( cpuReg . isEmpty ( ) ) {
when ( returnspec . dt ) {
IRDataType . BYTE -> " r ${returnspec.registerNum} .b "
IRDataType . WORD -> " r ${returnspec.registerNum} .w "
IRDataType . FLOAT -> " fr ${returnspec.registerNum} .f "
}
} else {
when ( returnspec . dt ) {
IRDataType . BYTE -> " r ${returnspec.registerNum} .b@ " + cpuReg
IRDataType . WORD -> " r ${returnspec.registerNum} .w@ " + cpuReg
IRDataType . FLOAT -> " r ${returnspec.registerNum} .f@ " + cpuReg
}
2023-12-14 20:16:14 +00:00
}
2023-05-12 21:26:36 +00:00
}
2024-03-22 23:20:12 +00:00
result . add ( resultParts . joinToString ( " , " ) )
2023-05-12 21:26:36 +00:00
}
} else {
reg1 ?. let {
result . add ( " r $it " )
result . add ( " , " )
}
reg2 ?. let {
result . add ( " r $it " )
result . add ( " , " )
}
2023-07-20 21:58:52 +00:00
reg3 ?. let {
result . add ( " r $it " )
result . add ( " , " )
}
2023-05-12 21:26:36 +00:00
fpReg1 ?. let {
result . add ( " fr $it " )
result . add ( " , " )
}
fpReg2 ?. let {
result . add ( " fr $it " )
result . add ( " , " )
}
immediate ?. let {
result . add ( it . toHex ( ) )
result . add ( " , " )
}
immediateFp ?. let {
result . add ( it . toString ( ) )
result . add ( " , " )
}
address ?. let {
result . add ( it . toHex ( ) )
result . add ( " , " )
}
labelSymbol ?. let {
result . add ( it )
2024-01-13 12:55:16 +00:00
if ( labelSymbolOffset != null )
result . add ( " + $labelSymbolOffset " )
2023-05-12 21:26:36 +00:00
}
2022-09-29 16:18:11 +00:00
}
if ( result . last ( ) == " , " )
result . removeLast ( )
return result . joinToString ( " " ) . trimEnd ( )
}
}