Page 1 of 1

SYS functions cycles problem

Posted: 04 May 2024, 16:13
by Phibrizzo
Hello :)

Copy-Paste from another topic:
at67 wrote: 04 Apr 2023, 17:27 That looks to me like sync issues, meaning you've broken the firmware's video timing. I'd check all your SYS calls, make sure all the args/regs are correct and that you are calling the correct cycle count.

e.g. in your assembler do you do something like this for the cycle operand to the SYS opcode?

Code: Select all

        if((operand & 0x0001) || operand < 28 || operand > 284)
        {
            fprintf(stderr, "Assembler::sysHelper() : '%s:%d' : SYS operand '%d' must be an even constant in [28, 284]\n", filename.c_str(), lineNumber, operand);
            return uint8_t(operand);
        }

        return uint8_t((270 - operand / 2) & 0x00FF);
Full explanation is here: https://github.com/kervinck/gigatron-ro ... ctions.txt
SYS operand must be in 28-284, but some SYS function have definied smaller cycle operand.
Ex:
SYS_Out - 22
SYS_LSRW8 - 24
SYS_LSLW8 - 24

Where is the mistake?

Re: SYS functions cycles problem

Posted: 04 May 2024, 21:51
by at67
You've found a couple of issues here:

From SYS-functions.txt:

Code: Select all

Naming
------

The naming convention is: SYS_<CamelCase>[_v<V>]_<N>

With <N> the maximum number of clocks or cycles (not ticks!) the
function will need, counted from NEXT to NEXT. This duration <N>
must be passed to the 'SYS' vCPU instruction as operand, represented
as `270-max(14,<N>/2)'. In GCL you can just type `<N>!!', and the
compiler translates the operand for you. The gt1dump tool disassembles
and displays <N>.
Breaking this down, it means 256 - N/2 + 28/2, (28/2 = maxTicks in ROMv1 to ROMv5a).
The max() function is important as it forces all SYS cycle counts to be 28/2 or higher which produces a valid signed byte.
So now we have 256 - max(14, N/2) + 28/2.

Code: Select all

D = 270 - max(14, N/2)
From SYS-functions.txt:

Code: Select all

[Side note: One way to see the raw value of D is as the *excess*
number of ticks that vCPU must accommodate for, but represented as
a number <=0. By default vCPU already accounts for 28 cycles for
standard instructions.
Conclusion:
1) The check for operand < 28 in my code is confusing and possibly wrong if a max() call or if statement does not proceed it.
2) The error message in my code is confusing, see 1).

Re: SYS functions cycles problem

Posted: 04 May 2024, 22:34
by lb3361
Here is how this is written in GLCC.

The idea is that the byte that follows the SYS opcode should be a negative number whose magnitude is the number of additional ticks needed by the SYS function (in addition to the maxTicks ticks given to all vCPU ops).

Therefore the number of cycles given to SYS must always be positive and even. The max value is irrelevant because the actual max is the length of the longest time slice (about 148 in mode 1-3, 134 in mode 0). Anything longer will never run. This is in fact how opcode HALT works.

Code: Select all

def SYS(op):
    op = v(op)
    if not isinstance(op ,Unk):
        if op & 1 != 0 or op < 0 or op >= 284:
            error(f"illegal argument {op} for SYS opcode")
        # If maxTicks is not defined, use 14.
        # All ROMs should ensure that 14 works.
        maxTicks = 14
        if 'maxTicks' in rominfo:
            maxTicks = int(rominfo['maxTicks'])
        op = min(0, maxTicks - op // 2) & 0xff
    emit_op("SYS", op)