//
// FCPU Debugger
//

#include "stdio.h"
#include "fcpu.h"

void fcpu_vm_hello( void )
{
    printf( "******************************\n" );
    printf( "*                            *\n" );
    printf( "* F-CPU Virtual Machine V1.0 *\n" );
    printf( "*                            *\n" );
    printf( "******************************\n" );
    printf( "\n" );
}

void fcpu_vm_dump_cpu( PFCPUCPU p )
{
    char            buffer[ 128 ];
    unsigned long   ulLow;
    unsigned long   ulHigh;
    unsigned long   i;

    ulHigh = (unsigned long)( ( p->instr_ptr >> 32 ) & 0xFFFFFFFF );
    ulLow  = (unsigned long)( ( p->instr_ptr >>  0 ) & 0xFFFFFFFF );
        
    sprintf( buffer, "PC : %08X%08X", ulHigh, ulLow );
    printf( buffer );
    printf( "  " );
    printf( "\n" );

    for( i = 0; i < 63; i++ )
    {
        ulHigh = (unsigned long)( ( p->reg[ i + 1 ] >> 32 ) & 0xFFFFFFFF );
        ulLow  = (unsigned long)( ( p->reg[ i + 1 ] >>  0 ) & 0xFFFFFFFF );
        
        sprintf( buffer, "R%02X: %08X%08X", ( i + 1 ), ulHigh, ulLow );
        printf( buffer );
        printf( "  " );

        if( ( i % 3 ) == 2 )
            printf( "\n" );
    }
}

void fcpu_vm_load_asm( PFCPUCPU p, char* argv )
{
    FILE*   pfile;
    char    ch;
    char    line[ 1024 ];
    char    hexoc[ 32 ];
    long    i;
    octbyte o;
    octbyte a;

    pfile = fopen( argv, "r" );
    if( pfile )
    {
        i = 0;
        while( !feof( pfile ) )
        {
            ch = fgetc( pfile );
            if( ch != 13 )
            {
                if( ch == 10 )
                {
                    unsigned long ulD;

                    line[ i ] = 0;

                    fcpu_asm( p, line, &o, &a, 1L );
                    
                    ulD = (unsigned long)o;

                    sprintf( hexoc, "%08X", ulD );
                    printf( hexoc );
                    printf( "  " );
                    printf( line );
                    printf( "\n" );

                    i = 0;
                }
                else
                {
                    line[ i ] = ch;
                    if( i < ( sizeof( line ) - 1 ) )
                        i++;
                }
            }
        }
        fclose( pfile );
    }

    printf( "\n" );
}

void fcpu_vm_debug_cpu( PFCPUCPU p )
{
    char cmd;

    fcpu_reset( p );

    cmd = ' ';
    while( cmd != 'q' )
    {
        fcpu_vm_dump_cpu( p );

        printf( ">" );

        do {
            cmd = getchar();
        } while( ( cmd == 13 ) || ( cmd == 10 ) );

        printf( "\n" );

        if( cmd == '?' )
        {
            printf( "\n" );
            printf( "r : reset f-cpu\n" );
            printf( "s : single step one instruction\n" );
            printf( "g : go until HALT or exception\n" );
            printf( "\n" );
        }

        if( cmd == 'r' )
            fcpu_reset( p );
        
        if( cmd == 's' )
            fcpu_clock( p );
        
        if( cmd == 'g' )
        {
            do {
                fcpu_clock( p );
            } while( p->exception == FCPU_EXCEPTION_NONE );
        }
    }
}

void main( int argc, char* argv[] )
{
    FCPUCPU cpu;

    fcpu_vm_hello();

    if( argc > 1 )
        fcpu_vm_load_asm( &cpu, argv[1] );

    fcpu_vm_debug_cpu( &cpu );
}