Example #1
0
def _divf16(ins):
    ''' Divides 2 32bit (16.16) fixed point numbers. The result is pushed onto the stack.

        Optimizations:

         * If 2nd operand is 1, do nothing
         * If 2nd operand is -1, do NEG32
    '''
    op1, op2 = tuple(ins.quad[2:])

    if is_float(op2):
        if float(op2) == 1:
            output = _f16_oper(op1)
            output.append('push de')
            output.append('push hl')
            return output

        if float(op2) == -1:
            return _negf(ins)

    rev = not is_float(op1) and op1[0] != 't' and op2[0] == 't'
    
    output = _f16_oper(op1, op2, reversed = rev)
    output.append('call __DIVF16')
    output.append('push de')
    output.append('push hl')
    REQUIRES.add('divf16.asm')
    return output
Example #2
0
def _divf16(ins):
    ''' Divides 2 32bit (16.16) fixed point numbers. The result is pushed onto the stack.

        Optimizations:

         * If 2nd operand is 1, do nothing
         * If 2nd operand is -1, do NEG32
    '''
    op1, op2 = tuple(ins.quad[2:])

    if is_float(op2):
        if float(op2) == 1:
            output = _f16_oper(op1)
            output.append('push de')
            output.append('push hl')
            return output

        if float(op2) == -1:
            return _negf(ins)

    rev = not is_float(op1) and op1[0] != 't' and op2[0] == 't'

    output = _f16_oper(op1, op2, reversed=rev)
    output.append('call __DIVF16')
    output.append('push de')
    output.append('push hl')
    REQUIRES.add('divf16.asm')
    return output
Example #3
0
def _modf16(ins):
    ''' Reminder of div. 2 32bit (16.16) fixed point numbers. The result is pushed onto the stack.

        Optimizations:

         * If 2nd op is 1. Returns 0
    '''
    op1, op2 = tuple(ins.quad[2:])

    if is_int(op2):
        if int(op2) == 1:
            output = _f16b_opers(op1)
            output.append('ld hl, 0')
            output.append('push hl')
            output.append('push hl')
            return output    
        
    rev = not is_float(op1) and op1[0] != 't' and op2[0] == 't'

    output = _f16_oper(op1, op2, reversed = rev)
    output.append('call __MODF16')
    output.append('push de')
    output.append('push hl')
    REQUIRES.add('modf16.asm')
    return output
Example #4
0
def _modf16(ins):
    ''' Reminder of div. 2 32bit (16.16) fixed point numbers. The result is pushed onto the stack.

        Optimizations:

         * If 2nd op is 1. Returns 0
    '''
    op1, op2 = tuple(ins.quad[2:])

    if is_int(op2):
        if int(op2) == 1:
            output = _f16b_opers(op1)
            output.append('ld hl, 0')
            output.append('push hl')
            output.append('push hl')
            return output

    rev = not is_float(op1) and op1[0] != 't' and op2[0] == 't'

    output = _f16_oper(op1, op2, reversed=rev)
    output.append('call __MODF16')
    output.append('push de')
    output.append('push hl')
    REQUIRES.add('modf16.asm')
    return output
Example #5
0
def _f16_to_32bit(ins):
    ''' If any of the operands whithin the ins(truction) are numeric,
    convert them to its 32bit representation, otherwise leave them
    as they are.
    '''
    ins.quad = [x for x in ins.quad]
    for i in range(2, len(ins.quad)):
        if is_float(ins.quad[i]):
            de, hl = f16(ins.quad[i])
            ins.quad[i] = str((de << 16) | hl)

    ins.quad = tuple(ins.quad)
    return ins
Example #6
0
def _f16_to_32bit(ins):
    ''' If any of the operands whithin the ins(truction) are numeric,
    convert them to its 32bit representation, otherwise leave them
    as they are.
    '''
    ins.quad = [x for x in ins.quad]
    for i in range(2, len(ins.quad)):
        if is_float(ins.quad[i]):
            de, hl = f16(ins.quad[i])
            ins.quad[i] = str((de << 16) | hl)

    ins.quad = tuple(ins.quad)
    return ins
Example #7
0
def _powf(ins):
    ''' Exponentiation of 2 float values. The result is pushed onto the stack.
    '''
    op1, op2 = tuple(ins.quad[2:])

    if is_float(op2) and float(op2) == 1: # Nothing to do. A ^ 1 = A
        output = _float_oper(op1)
        output.extend(_fpush())
        return output

    output = _float_oper(op1, op2)
    output.append('call __POW')
    output.extend(_fpush())
    REQUIRES.add('pow.asm')
    return output
Example #8
0
def _divf(ins):
    ''' Divides 2 float values. The result is pushed onto the stack.
    '''
    op1, op2 = tuple(ins.quad[2:])

    if is_float(op2) and float(op2) == 1: # Nothing to do. A / 1 = A
        output = _float_oper(op1)
        output.extend(_fpush())
        return output

    output = _float_oper(op1, op2)
    output.append('call __DIVF')
    output.extend(_fpush())
    REQUIRES.add('divf.asm')
    return output
Example #9
0
def _subf(ins):
    ''' Subtract 2 float values. The result is pushed onto the stack.
    '''
    op1, op2 = tuple(ins.quad[2:])

    if is_float(op2) and float(op2) == 0: # Nothing to do: A - 0 = A
        output = _float_oper(op1)
        output.extend(_fpush())
        return output

    output = _float_oper(op1, op2)
    output.append('call __SUBF')
    output.extend(_fpush())
    REQUIRES.add('subf.asm')
    return output
Example #10
0
def _float_oper(op1, op2 = None):
    ''' Returns pop sequence for floating point operands
    1st operand in A DE BC, 2nd operand remains in the stack

    Unlike 8bit and 16bit version, this does not supports
    operands inversion. Since many of the instructions are implemented
    as functions, they must support this.

    However, if 1st operand is a number (immediate) or indirect, the stack
    will be rearranged, so it contains a 48 bit pushed parameter value for the
    subroutine to be called.
    '''
    output = []
    op = op2 if op2 is not None else op1

    indirect = (op[0] == '*')
    if indirect:
        op = op[1:]

    if is_float(op):
        op = float(op)

        if indirect:
            op = int(op) & 0xFFFF
            output.append('ld hl, (%i)' % op)
            output.append('call __ILOADF')
            REQUIRES.add('iloadf.asm')
        else:
            A, DE, BC = _float(op)
            output.append('ld a, %s' % A)
            output.append('ld de, %s' % DE)
            output.append('ld bc, %s' % BC)
    else:
        if indirect:
            if op[0] == '_':
                output.append('ld hl, (%s)' % op)
            else:
                output.append('pop hl')
                
            output.append('call __ILOADF')
            REQUIRES.add('iloadf.asm')
        else:
            if op[0] == '_':
                output.append('ld a, (%s)' % op)
                output.append('ld de, (%s + 1)' % op)
                output.append('ld bc, (%s + 3)' % op)
            else:
                output.extend(_fpop())

    if op2 is not None: 
        op = op1
        if is_float(op): # An float must be in the stack. Let's pushit
            A, DE, BC = _float(op)
            output.append('ld hl, %s' % BC)
            output.append('push hl')
            output.append('ld hl, %s' % DE)
            output.append('push hl')
            output.append('ld h, %s' % A)
            output.append('push hl')
        elif op[0] == '*': # Indirect
            op = op[1:]
            output.append('exx') # uses alternate set to put it on the stack
            output.append("ex af, af'")
            if is_int(op):
                op = int(op)
                output.append('ld hl, %i' % op)
            elif op[0] == '_':
                output.append('ld hl, (%s)' % op)
            else:
                output.append('pop hl')

            output.append('call __ILOADF')
            output.extend(_fpush())
            output.append("ex af, af'")
            output.append('exx')
            REQUIRES.add('iloadf.asm')
        elif op[0] == '_':
            if is_float(op2):
                tmp = output
                output = []
                output.append('ld hl, %s + 4' % op)
                '''
                output.append('ld hl, (%s + 3)' % op)
                output.append('push hl')            
                output.append('ld hl, (%s + 1)' % op)
                output.append('push hl')
                output.append('ld a, (%s)' % op)
                output.append('push af')            
                '''
                output.append('call __FP_PUSH_REV')
                output.extend(tmp)
                REQUIRES.add('pushf.asm')
            else:
                '''
                output.append('ld hl, (%s + 3)' % op)
                output.append('push hl')            
                output.append('ld hl, (%s + 1)' % op)
                output.append('push hl')
                output.append('ld hl, (%s - 1)' % op)
                output.append('push hl')            
                '''
                output.append('ld hl, %s + 4' % op)
                output.append('call __FP_PUSH_REV')
                REQUIRES.add('pushf.asm')
        else:
            pass # Else do nothing, and leave the op onto the stack

    return output
Example #11
0
def _f16_oper(op1, op2 = None, useBC = False, reversed = False):
    ''' Returns pop sequence for 32 bits operands
    1st operand in HLDE, 2nd operand remains in the stack

    Now it does support operands inversion calling __SWAP32.

    However, if 1st operand is integer (immediate) or indirect, the stack
    will be rearranged, so it contains a 32 bit pushed parameter value for the
    subroutine to be called.

    If preserveHL is True, then BC will be used instead of HL for lower part
    for the 1st operand.
    '''
    output = []

    if op1 is not None:
        op1 = str(op1)

    if op2 is not None:
        op2 = str(op2)

    op = op2 if op2 is not None else op1

    float1 = False # whether op1 (2nd operand) is float
    float2 = False # whether op1 (2nd operand) is float
    
    indirect = (op[0] == '*')
    if indirect:
        op = op[1:]

    immediate = (op[0] == '#')
    if immediate:
        op = op[1:]

    hl = 'hl' if not useBC and not indirect else 'bc'

    if is_float(op):
        float1 = True
        op = float(op)

        if indirect:
            op = int(op) & 0xFFFF
            if immediate:
                output.append('ld hl, %i' % op)
            else:
                output.append('ld hl, (%i)' % op)

            output.append('call __ILOAD32')
            REQUIRES.add('iload32.asm')

            if preserveHL:
                output.append('ld b, h')
                output.append('ld c, l')
        else:
            DE, HL = f16(op)
            output.append('ld de, %i' % DE)
            output.append('ld %s, %i' % (hl, HL))
    else:
        if op[0] == '_':
            if immediate:
                output.append('ld %s, %s' % (hl, op))
            else:
                output.append('ld %s, (%s)' % (hl, op))
        else:
            output.append('pop %s' % hl)

        if indirect:
            output.append('call __ILOAD32')
            REQUIRES.add('iload32.asm')

            if preserveHL:
                output.append('ld b, h')
                output.append('ld c, l')
        else:
            if op[0] == '_':
                output.append('ld de, (%s + 2)' % op)
            else:
                output.append('pop de')


    if op2 is not None:
        op = op1

        indirect = (op[0] == '*')
        if indirect:
            op = op[1:]

        immediate = (op[0] == '#')
        if immediate:
            op = op[1:]
        
        if is_float(op):
            float2 = True
            op = float(op)
    
            if indirect:
                op = int(op)
                output.append('exx')
                if immediate:
                    output.append('ld hl, %i' % (op & 0xFFFF))
                else:
                    output.append('ld hl, (%i)' % (op & 0xFFFF))
    
                output.append('call __ILOAD32')
                output.append('push de')
                output.append('push hl')
                output.append('exx')
                REQUIRES.add('iload32.asm')
            else:
                DE, HL = f16(op)
                output.append('ld bc, %i' % DE)
                output.append('push bc')
                output.append('ld bc, %i' % HL)
                output.append('push bc')
        else:
            if indirect:
                output.append('exx') # uses alternate set to put it on the stack
                if op[0] == '_':
                    if immediate:
                        output.append('ld hl, %s' % op)
                    else:
                        output.append('ld hl, (%s)' % op)
                else:
                    output.append('pop hl') # Pointers are only 16 bits ***

                output.append('call __ILOAD32')
                output.append('push de')
                output.append('push hl')
                output.append('exx')
                REQUIRES.add('iload32.asm')
            elif op[0] == '_': # an address
                if float1 or op1[0] == '_': # If previous op was constant, we can use hl in advance
                    tmp = output
                    output = []
                    output.append('ld hl, (%s + 2)' % op)
                    output.append('push hl')
                    output.append('ld hl, (%s)' % op)
                    output.append('push hl')
                    output.extend(tmp)
                else:
                    output.append('ld bc, (%s + 2)' % op)
                    output.append('push bc')
                    output.append('ld bc, (%s)' % op)
                    output.append('push bc')
            else:
                pass # 2nd operand remains in the stack


    if op2 is not None and reversed:
        output.append('call __SWAP32')
        REQUIRES.add('swap32.asm')

    return output
Example #12
0
def _f16_oper(op1, op2=None, useBC=False, reversed=False):
    ''' Returns pop sequence for 32 bits operands
    1st operand in HLDE, 2nd operand remains in the stack

    Now it does support operands inversion calling __SWAP32.

    However, if 1st operand is integer (immediate) or indirect, the stack
    will be rearranged, so it contains a 32 bit pushed parameter value for the
    subroutine to be called.

    If preserveHL is True, then BC will be used instead of HL for lower part
    for the 1st operand.
    '''
    output = []

    if op1 is not None:
        op1 = str(op1)

    if op2 is not None:
        op2 = str(op2)

    op = op2 if op2 is not None else op1

    float1 = False  # whether op1 (2nd operand) is float
    float2 = False  # whether op1 (2nd operand) is float

    indirect = (op[0] == '*')
    if indirect:
        op = op[1:]

    immediate = (op[0] == '#')
    if immediate:
        op = op[1:]

    hl = 'hl' if not useBC and not indirect else 'bc'

    if is_float(op):
        float1 = True
        op = float(op)

        if indirect:
            op = int(op) & 0xFFFF
            if immediate:
                output.append('ld hl, %i' % op)
            else:
                output.append('ld hl, (%i)' % op)

            output.append('call __ILOAD32')
            REQUIRES.add('iload32.asm')

            if preserveHL:
                output.append('ld b, h')
                output.append('ld c, l')
        else:
            DE, HL = f16(op)
            output.append('ld de, %i' % DE)
            output.append('ld %s, %i' % (hl, HL))
    else:
        if op[0] == '_':
            if immediate:
                output.append('ld %s, %s' % (hl, op))
            else:
                output.append('ld %s, (%s)' % (hl, op))
        else:
            output.append('pop %s' % hl)

        if indirect:
            output.append('call __ILOAD32')
            REQUIRES.add('iload32.asm')

            if preserveHL:
                output.append('ld b, h')
                output.append('ld c, l')
        else:
            if op[0] == '_':
                output.append('ld de, (%s + 2)' % op)
            else:
                output.append('pop de')

    if op2 is not None:
        op = op1

        indirect = (op[0] == '*')
        if indirect:
            op = op[1:]

        immediate = (op[0] == '#')
        if immediate:
            op = op[1:]

        if is_float(op):
            float2 = True
            op = float(op)

            if indirect:
                op = int(op)
                output.append('exx')
                if immediate:
                    output.append('ld hl, %i' % (op & 0xFFFF))
                else:
                    output.append('ld hl, (%i)' % (op & 0xFFFF))

                output.append('call __ILOAD32')
                output.append('push de')
                output.append('push hl')
                output.append('exx')
                REQUIRES.add('iload32.asm')
            else:
                DE, HL = f16(op)
                output.append('ld bc, %i' % DE)
                output.append('push bc')
                output.append('ld bc, %i' % HL)
                output.append('push bc')
        else:
            if indirect:
                output.append(
                    'exx')  # uses alternate set to put it on the stack
                if op[0] == '_':
                    if immediate:
                        output.append('ld hl, %s' % op)
                    else:
                        output.append('ld hl, (%s)' % op)
                else:
                    output.append('pop hl')  # Pointers are only 16 bits ***

                output.append('call __ILOAD32')
                output.append('push de')
                output.append('push hl')
                output.append('exx')
                REQUIRES.add('iload32.asm')
            elif op[0] == '_':  # an address
                if float1 or op1[
                        0] == '_':  # If previous op was constant, we can use hl in advance
                    tmp = output
                    output = []
                    output.append('ld hl, (%s + 2)' % op)
                    output.append('push hl')
                    output.append('ld hl, (%s)' % op)
                    output.append('push hl')
                    output.extend(tmp)
                else:
                    output.append('ld bc, (%s + 2)' % op)
                    output.append('push bc')
                    output.append('ld bc, (%s)' % op)
                    output.append('push bc')
            else:
                pass  # 2nd operand remains in the stack

    if op2 is not None and reversed:
        output.append('call __SWAP32')
        REQUIRES.add('swap32.asm')

    return output