Example #1
0
def _divi32(ins):
    ''' Divides 2 32bit signed integers. 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_int(op2):
        if int(op2) == 1:
            output = _32bit_oper(op1)
            output.append('push de')
            output.append('push hl')
            return output

        if int(op2) == -1:
            return _neg32(ins)

    rev = is_int(op1) or op1[0] == 't' or op2[0] != 't'
    output = _32bit_oper(op1, op2, rev)
    output.append('call __DIVI32')
    output.append('push de')
    output.append('push hl')
    REQUIRES.add('div32.asm')
    return output
Example #2
0
def _divi16(ins):
    ''' Divides 2 16bit signed integers. The result is pushed onto the stack.

    Optimizations:
      * If 2nd op is 1 then
        do nothing

      * If 2nd op is -1 then
        do NEG

      * If 2nd op is 2 then
        Shift Right Arithmetic
    '''
    op1, op2 = tuple(ins.quad[2:])
    if is_int(op1) and int(op1) == 0: # 0 / A = 0

            if op2[0] in ('_', '$'):
                output = [] # Optimization: Discard previous op if not from the stack
            else:
                output = _16bit_oper(op2) # Normalize stack

            output.append('ld hl, 0')
            output.append('push hl')
            return output

    if is_int(op2):
        op = int16(op2)
        output = _16bit_oper(op1)

        if op == 1:
            output.append('push hl')
            return output

        if op == -1:
            output.append('call __NEGHL')
            output.append('push hl')
            REQUIRES.add('neg16.asm')
            return output

        if op == 2:
            output.append('sra h')
            output.append('rr l')
            output.append('push hl')
            return output

        output.append('ld de, %i' % op)
    else:
        if op2[0] == '_': # Optimization when 2nd operand is an id
            rev = True
            op1, op2 = op2, op1
        else:
            rev = False
        output = _16bit_oper(op1, op2, rev)

    output.append('call __DIVI16')
    output.append('push hl')
    REQUIRES.add('div16.asm')
    return output
Example #3
0
def _shri8(ins):
    ''' Shift 8bit signed integer to the right. The result is pushed onto the stack.

    Optimizations:
      * If 1nd or 2nd op is 0 then
        do nothing

      * If 2nd op is < 4 then
        unroll loop
    '''
    op1, op2 = tuple(ins.quad[2:])

    if is_int(op2):
        op2 = int8(op2)

        output = _8bit_oper(op1)
        if op2 == 0:
            output.append('push af')
            return output

        if op2 < 4:
            output.extend(['sra a'] * op2)
            output.append('push af')
            return output

        label = tmp_label()
        output.append('ld b, %i' % int8(op2))
        output.append('%s:' % label)
        output.append('sra a')
        output.append('djnz %s' % label)
        output.append('push af')
        return output

    if is_int(op1) and int(op1) == 0:
        output = _8bit_oper(op2)
        output.append('xor a')
        output.append('push af')
        return output

    output = _8bit_oper(op1, op2, True)
    label = tmp_label()
    label2 = tmp_label()
    output.append('or a')
    output.append('ld b, a')
    output.append('ld a, h')
    output.append('jr z, %s' % label2)
    output.append('%s:' % label)
    output.append('sra a')
    output.append('djnz %s' % label)
    output.append('%s:' % label2)
    output.append('push af')
    return output
Example #4
0
def _shri8(ins):
    ''' Shift 8bit signed integer to the right. The result is pushed onto the stack.

    Optimizations:
      * If 1nd or 2nd op is 0 then
        do nothing

      * If 2nd op is < 4 then
        unroll loop
    '''
    op1, op2 = tuple(ins.quad[2:])

    if is_int(op2):
        op2 = int8(op2)

        output = _8bit_oper(op1)
        if op2 == 0:
            output.append('push af')
            return output

        if op2 < 4:
            output.extend(['sra a'] * op2)
            output.append('push af')
            return output

        label = tmp_label()
        output.append('ld b, %i' % int8(op2))
        output.append('%s:' % label)
        output.append('sra a')
        output.append('djnz %s' % label)
        output.append('push af')
        return output

    if is_int(op1) and int(op1) == 0:
        output = _8bit_oper(op2)
        output.append('xor a')
        output.append('push af')
        return output

    output = _8bit_oper(op1, op2, True)
    label = tmp_label()
    label2 = tmp_label()
    output.append('or a')
    output.append('ld b, a')
    output.append('ld a, h')
    output.append('jr z, %s' % label2)    
    output.append('%s:' % label)
    output.append('sra a')
    output.append('djnz %s' % label)
    output.append('%s:' % label2)
    output.append('push af')
    return output
Example #5
0
def _modi8(ins):
    ''' Reminder of div. 2 8bit unsigned integers. The result is pushed onto the stack.

    Optimizations:
      * If 2nd operands is 1 then
        returns 0

      * If 2nd operand = 2^n => do AND (2^n - 1)

    '''
    op1, op2 = tuple(ins.quad[2:])
    if is_int(op2):
        op2 = int8(op2)

        output = _8bit_oper(op1)
        if op2 == 1:
            if op1[0] == '_':
                output = [
                ]  # Optimization: Discard previous op if not from the stack

            output.append('xor a')
            output.append('push af')
            return output

        if is_2n(op2):
            output.append('and %i' % (op2 - 1))
            output.append('push af')
            return output

        output.append('ld h, %i' % int8(op2))
    else:
        if op2[0] == '_':  # Optimization when 2nd operand is an id
            if is_int(op1) and int(op1) == 0:
                output = [
                ]  # Optimization: Discard previous op if not from the stack
                output.append('xor a')
                output.append('push af')
                return output

            rev = True
            op1, op2 = op2, op1
        else:
            rev = False

        output = _8bit_oper(op1, op2, rev)

    output.append('call __MODI8_FAST')
    output.append('push af')
    REQUIRES.add('div8.asm')
    return output
Example #6
0
def _divi8(ins):
    ''' Divides 2 8bit signed integers. The result is pushed onto the stack.

    Optimizations:
      * If 2nd op is 1 then
        do nothing

      * If 2nd op is 2 then
        Shift Right Arithmetic
    '''
    op1, op2 = tuple(ins.quad[2:])
    if is_int(op2):
        op2 = int(op2) & 0xFF
        output = _8bit_oper(op1)

        if op2 == 1:
            output.append('push af')
            return output

        if op2 == -1:
            output.append('neg')
            output.append('push af')
            return output

        if op2 == 2:
            output.append('sra a')
            output.append('push af')
            return output

        output.append('ld h, %i' % int8(op2))
    else:
        if op2[0] == '_':  # Optimization when 2nd operand is an id
            if is_int(op1) and int(op1) == 0:
                output = [
                ]  # Optimization: Discard previous op if not from the stack
                output.append('xor a')
                output.append('push af')
                return output

            rev = True
            op1, op2 = op2, op1
        else:
            rev = False

        output = _8bit_oper(op1, op2, rev)

    output.append('call __DIVI8_FAST')
    output.append('push af')
    REQUIRES.add('div8.asm')
    return output
Example #7
0
def _divi8(ins):
    ''' Divides 2 8bit signed integers. The result is pushed onto the stack.

    Optimizations:
      * If 2nd op is 1 then
        do nothing

      * If 2nd op is 2 then
        Shift Right Arithmetic
    '''
    op1, op2 = tuple(ins.quad[2:])
    if is_int(op2):
        op2 = int(op2) & 0xFF
        output = _8bit_oper(op1)

        if op2 == 1:
            output.append('push af')
            return output

        if op2 == -1:
            output.append('neg')
            output.append('push af')
            return output

        if op2 == 2:
            output.append('sra a')
            output.append('push af')
            return output

        output.append('ld h, %i' % int8(op2))
    else:
        if op2[0] == '_': # Optimization when 2nd operand is an id
            if is_int(op1) and int(op1) == 0:
                output = [] # Optimization: Discard previous op if not from the stack
                output.append('xor a')
                output.append('push af')
                return output
    
            rev = True
            op1, op2 = op2, op1
        else:
            rev = False

        output = _8bit_oper(op1, op2, rev)

    output.append('call __DIVI8_FAST')
    output.append('push af')
    REQUIRES.add('div8.asm')
    return output
Example #8
0
def _modi8(ins):
    ''' Reminder of div. 2 8bit unsigned integers. The result is pushed onto the stack.

    Optimizations:
      * If 2nd operands is 1 then
        returns 0

      * If 2nd operand = 2^n => do AND (2^n - 1)

    '''
    op1, op2 = tuple(ins.quad[2:])
    if is_int(op2):
        op2 = int8(op2)

        output = _8bit_oper(op1)
        if op2 == 1:
            if op1[0] == '_':
                output = [] # Optimization: Discard previous op if not from the stack

            output.append('xor a')
            output.append('push af')
            return output

        if is_2n(op2):
            output.append('and %i' % (op2 - 1))
            output.append('push af')
            return output

        output.append('ld h, %i' % int8(op2))
    else:
        if op2[0] == '_': # Optimization when 2nd operand is an id
            if is_int(op1) and int(op1) == 0:
                output = [] # Optimization: Discard previous op if not from the stack
                output.append('xor a')
                output.append('push af')
                return output

            rev = True
            op1, op2 = op2, op1
        else:
            rev = False

        output = _8bit_oper(op1, op2, rev)

    output.append('call __MODI8_FAST')
    output.append('push af')
    REQUIRES.add('div8.asm')
    return output
Example #9
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 #10
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 #11
0
def _shl16(ins):
    ''' Logical/aritmetical left shift 16bit (un)signed integer.
    The result is pushed onto the stack.

    Optimizations:
      * If 2nd op is 0 then
        do nothing

      * If 2nd op is lower than 6
        unroll lop
    '''
    op1, op2 = tuple(ins.quad[2:])
    if is_int(op2):
        op = int16(op2)
        if op == 0:
            return []

        output = _16bit_oper(op1)
        if op < 6:
            output.extend(['add hl, hl'] * op)
            output.append('push hl')
            return output

        output.append('ld b, %i' % op)
    else:
        output = _8bit_oper(op2)
        output.append('ld b, a')
        output.extend(_16bit_oper(op1))

    label = tmp_label()
    output.append('%s:' % label)
    output.append('add hl, hl')
    output.append('djnz %s' % label)
    output.append('push hl')
    return output
Example #12
0
def _astore16(ins):
    ''' Stores 2º operand content into address of 1st operand.
    store16 a, x =>  *(&a) = x
    Use '*' for indirect store on 1st operand.
    '''
    output = _addr(ins.quad[1])
    op = ins.quad[2]

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

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

    if is_int(op):
        op = str(int(op) & 0xFFFF)  # Truncate to 16bit pointer

        if indirect:
            if immediate:
                output.append('ld de, (%s)' % op)
            else:
                output.append('ld de, (%s)' % op)
                output.append('call __LOAD_DE_DE')
                REQUIRES.add('lddede.asm')
        else:
            H = int(op) >> 8
            L = int(op) & 0xFF
            output.append('ld (hl), %i' % L)
            output.append('inc hl')
            output.append('ld (hl), %i' % H)
            return output

    elif op[0] == '_':
        if indirect:
            if immediate:
                output.append('ld de, (%s)' % op)  # redundant: *#_id == _id
            else:
                output.append('ld de, (%s)' % op)  # *_id
                output.append('call __LOAD_DE_DE')
                REQUIRES.add('lddede.asm')
        else:
            if immediate:
                output.append('ld de, %s' % op)
            else:
                output.append('ld de, (%s)' % op)
    else:
        output.append('pop de')

    output.append('ld (hl), e')
    output.append('inc hl')
    output.append('ld (hl), d')

    return output
Example #13
0
def _astore16(ins):
    ''' Stores 2º operand content into address of 1st operand.
    store16 a, x =>  *(&a) = x
    Use '*' for indirect store on 1st operand.
    '''
    output = _addr(ins.quad[1])
    op = ins.quad[2]

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

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

    if is_int(op):
        op = str(int(op) & 0xFFFF) # Truncate to 16bit pointer

        if indirect:
            if immediate:
                output.append('ld de, (%s)' % op)
            else:
                output.append('ld de, (%s)' % op)
                output.append('call __LOAD_DE_DE')
                REQUIRES.add('lddede.asm')
        else:
            H = int(op) >> 8
            L = int(op) & 0xFF
            output.append('ld (hl), %i' % L)
            output.append('inc hl')
            output.append('ld (hl), %i' % H)
            return output

    elif op[0] == '_':
        if indirect:
            if immediate:
                output.append('ld de, (%s)' % op) # redundant: *#_id == _id
            else:
                output.append('ld de, (%s)' % op) # *_id
                output.append('call __LOAD_DE_DE')
                REQUIRES.add('lddede.asm')
        else:
            if immediate:
                output.append('ld de, %s' % op)
            else:
                output.append('ld de, (%s)' % op)
    else:
        output.append('pop de')

    output.append('ld (hl), e')
    output.append('inc hl')
    output.append('ld (hl), d')

    return output
Example #14
0
def _sub16(ins):
    ''' Pops last 2 words from the stack and subtract them.
    Then push the result onto the stack. Top of the stack is
    subtracted Top -1

    Optimizations:
      * If 2nd op is ZERO,
        then do NOTHING: A - 0 = A

      * If any of the operands is < 4, then
        DEC is used

      * If any of the operands is > 65531 (-4..-1), then
        INC is used
    '''
    op1, op2 = tuple(ins.quad[2:4])

    if is_int(op2):
        op = int16(op2)
        output = _16bit_oper(op1)

        if op == 0:
            output.append('push hl')
            return output

        if op < 4:
            output.extend(['dec hl'] * op)
            output.append('push hl')
            return output

        if op > 65531:
            output.extend(['inc hl'] * (0x10000 - op))
            output.append('push hl')
            return output

        output.append('ld de, -%i' % op)
        output.append('add hl, de')
        output.append('push hl')
        return output

    if op2[0] == '_': # Optimization when 2nd operand is an id
        rev = True
        op1, op2 = op2, op1
    else:
        rev = False

    output = _16bit_oper(op1, op2, rev)
    output.append('or a')
    output.append('sbc hl, de')
    output.append('push hl')
    return output
Example #15
0
def _lei32(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand <= 2nd operand (top of the stack).
        Pushes 0 if False, 1 if True. 

        32 bit signed version
    '''
    op1, op2 = tuple(ins.quad[2:])
    rev = op1[0] != 't' and not is_int(op1) and op2[0] == 't'
    output = _32bit_oper(op1, op2, rev)
    output.append('call __LEI32')
    output.append('push af')
    REQUIRES.add('lei32.asm')
    return output
Example #16
0
def _astore8(ins):
    ''' Stores 2º operand content into address of 1st operand.
    1st operand is an array element. Dimensions are pushed into the 
    stack.
    Use '*' for indirect store on 1st operand (A pointer to an array)
    '''
    output = _addr(ins.quad[1])
    op = ins.quad[2]

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

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

    if is_int(op):
        if indirect:
            if immediate:
                op = str(int(op) & 0xFFFF)  # Truncate to 16bit pointer
                output.append('ld a, (%s)' % op)
            else:
                output.append('ld de, (%s)' % op)
                output.append('ld a, (de)')
        else:
            op = str(int(op) & 0xFF)  # Truncate to byte
            output.append('ld (hl), %s' % op)
            return output

    elif op[0] == '_':
        if indirect:
            if immediate:
                output.append('ld a, (%s)' %
                              op)  # Redundant case: *#_id == _id
            else:
                output.append('ld de, (%s)' % op)  # *_id
                output.append('ld a, (de)')
        else:
            if immediate:
                output.append('ld a, %s' % op)  # #_id
            else:
                output.append('ld a, (%s)' % op)  # _id
    else:
        output.append('pop af')  # tn

    output.append('ld (hl), a')

    return output
Example #17
0
def _sub32(ins):
    ''' Pops last 2 dwords from the stack and subtract them.
    Then push the result onto the stack.
    NOTE: The operation is TOP[0] = TOP[-1] - TOP[0]

    If TOP[0] is 0, nothing is done
    '''
    op1, op2 = tuple(ins.quad[2:])

    if is_int(op2):
        if int(op2) == 0: # A - 0 = A => Do Nothing
            output = _32bit_oper(op1)
            output.append('push de')
            output.append('push hl')
            return output

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

    output = _32bit_oper(op1, op2, rev)
    output.append('call __SUB32')
    output.append('push de')
    output.append('push hl')
    REQUIRES.add('sub32.asm')
    return output
Example #18
0
def _modi32(ins):
    ''' Reminder of div. 2 32bit signed integers. 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 = _32bit_oper(op1)
            output.append('ld hl, 0')
            output.append('push hl')
            output.append('push hl')
            return output    
        
    rev = is_int(op1) or op1[0] == 't' or op2[0] != 't'
    output = _32bit_oper(op1, op2, rev)
    output.append('call __MODI32')
    output.append('push de')
    output.append('push hl')
    REQUIRES.add('div32.asm')
    return output
Example #19
0
def _astore8(ins):
    ''' Stores 2º operand content into address of 1st operand.
    1st operand is an array element. Dimensions are pushed into the 
    stack.
    Use '*' for indirect store on 1st operand (A pointer to an array)
    '''
    output = _addr(ins.quad[1])
    op = ins.quad[2]

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

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

    if is_int(op):
        if indirect:
            if immediate:
                op = str(int(op) & 0xFFFF) # Truncate to 16bit pointer
                output.append('ld a, (%s)' % op)
            else:
                output.append('ld de, (%s)' % op)
                output.append('ld a, (de)')
        else:
            op = str(int(op) & 0xFF) # Truncate to byte
            output.append('ld (hl), %s' % op)
            return output

    elif op[0] == '_':
        if indirect:
            if immediate:
                output.append('ld a, (%s)' % op) # Redundant case: *#_id == _id
            else:
                output.append('ld de, (%s)' % op) # *_id
                output.append('ld a, (de)')
        else:
            if immediate:
                output.append('ld a, %s' % op) # #_id
            else:
                output.append('ld a, (%s)' % op) # _id
    else:        
        output.append('pop af') # tn

    output.append('ld (hl), a')

    return output
Example #20
0
def _gei32(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand >= 2nd operand (top of the stack).
        Pushes 0 if False, 1 if True. 

        32 bit signed version
    '''
    op1, op2 = tuple(ins.quad[2:])
    rev = op1[0] != 't' and not is_int(op1) and op2[0] == 't'
    output = _32bit_oper(op1, op2, rev)
    output.append('call __LTI32')  # A = (a < b)
    output.append('sub 1')         # Carry if !(a < b)
    output.append('sbc a, a')      # A = !(a < b) = (a >= b)
    output.append('push af')
    REQUIRES.add('lti32.asm')
    return output
Example #21
0
def _geu32(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand >= 2nd operand (top of the stack).
        Pushes 0 if False, 1 if True. 

        32 bit unsigned version
    '''
    op1, op2 = tuple(ins.quad[2:])
    rev = op1[0] != 't' and not is_int(op1) and op2[0] == 't'
    output = _32bit_oper(op1, op2, rev)
    output.append('call __SUB32')    # Carry if A < B
    output.append('ccf')        # Negates result => Carry if A >= B
    output.append('sbc a, a')
    output.append('push af')
    REQUIRES.add('sub32.asm')
    return output
Example #22
0
def _modi16(ins):
    ''' Reminder of div 2 16bit signed integers. The result is pushed onto the stack.

        Optimizations:
         * If 2nd operand is 1 => Return 0
         * If 2nd operand = 2^n => do AND (2^n - 1)
    '''
    op1, op2 = tuple(ins.quad[2:])

    if is_int(op2):
        op2 = int16(op2)
        output = _16bit_oper(op1)

        if op2 == 1:
            if op2[0] in ('_', '$'):
                output = [] # Optimization: Discard previous op if not from the stack

            output.append('ld hl, 0')
            output.append('push hl')
            return output

        if is_2n(op2):
            k = op2 - 1
            if op2 > 255: # only affects H
                output.append('ld a, h')
                output.append('and %i' % (k >> 8))
                output.append('ld h, a')
            else:
                output.append('ld h, 0') # High part goes 0
                output.append('ld a, l')
                output.append('and %i' % (k % 0xFF))
                output.append('ld l, a')

            output.append('push hl')
            return output

        output.append('ld de, %i' % op2)
    else:
        output = _16bit_oper(op1, op2)

    output.append('call __MODI16')
    output.append('push hl')
    REQUIRES.add('div16.asm')
    return output
Example #23
0
def _gtu32(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand > 2nd operand (top of the stack).
        Pushes 0 if False, 1 if True. 

        32 bit unsigned version
    '''
    op1, op2 = tuple(ins.quad[2:])
    rev = op1[0] != 't' and not is_int(op1) and op2[0] == 't'
    output = _32bit_oper(op1, op2, rev)
    output.append('pop bc')
    output.append('or a')
    output.append('sbc hl, bc')
    output.append('ex de, hl')
    output.append('pop de')
    output.append('sbc hl, de')
    output.append('sbc a, a')
    output.append('push af')
    return output
Example #24
0
def _shl32(ins):
    ''' Logical Left shift 32bit unsigned integers.
    The result is pushed onto the stack.

        Optimizations:

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

    if is_int(op2):
        output = _32bit_oper(op1)

        if int(op2) == 0:
            output.append('push de')
            output.append('push hl')
            return output

        if int(op2) > 1:
            label = tmp_label()
            output.append('ld b, %s' % op2)
            output.append('%s:' % label)
            output.append('call __SHL32')
            output.append('djnz %s' % label)
        else:
            output.append('call __SHL32')

        output.append('push de')
        output.append('push hl')
        REQUIRES.add('shl32.asm')
        return output

    output = _8bit_oper(op2)
    output.append('ld b, a')
    output.extend(_32bit_oper(op1))
    label = tmp_label()
    output.append('%s:' % label)
    output.append('call __SHL32')
    output.append('djnz %s' % label)
    output.append('push de')
    output.append('push hl')
    REQUIRES.add('shl32.asm')
    return output
Example #25
0
def _ne8(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand != 2nd operand (top of the stack).
        Pushes 0 if False, 1 if True.

        8 bit un/signed version
    '''
    if is_int(ins.quad[3]):
        output = _8bit_oper(ins.quad[2])
        n = int8(ins.quad[3])
        if n:
            if n == 1:
                output.append('dec a')
            else:
                output.append('sub %i' % int8(ins.quad[3]))
    else:
        output = _8bit_oper(ins.quad[2], ins.quad[3])
        output.append('sub h')

    output.append('push af')

    return output
Example #26
0
def _ne8(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand != 2nd operand (top of the stack).
        Pushes 0 if False, 1 if True.

        8 bit un/signed version
    '''
    if is_int(ins.quad[3]):
        output = _8bit_oper(ins.quad[2])
        n = int8(ins.quad[3])
        if n:
            if n == 1:
                output.append('dec a')
            else:
                output.append('sub %i' % int8(ins.quad[3]))
    else:
        output = _8bit_oper(ins.quad[2], ins.quad[3])
        output.append('sub h')

    output.append('push af')

    return output
Example #27
0
def _geu8(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand >= 2nd operand (top of the stack).
        Pushes 0 if False, 1 if True.

        8 bit unsigned version
    '''
    if is_int(ins.quad[3]):
        output = _8bit_oper(ins.quad[2])
        n = int8(ins.quad[3])
        if n:
            output.append('sub %i' % n)
        else:
            output.append('cp a')
    else:
        output = _8bit_oper(ins.quad[2], ins.quad[3])
        output.append('sub h')

    output.append('ccf')
    output.append('sbc a, a')
    output.append('push af')

    return output
Example #28
0
def _geu8(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand >= 2nd operand (top of the stack).
        Pushes 0 if False, 1 if True.

        8 bit unsigned version
    '''
    if is_int(ins.quad[3]):
        output = _8bit_oper(ins.quad[2])
        n = int8(ins.quad[3])
        if n:
            output.append('sub %i' % n)
        else:
            output.append('cp a')
    else:
        output = _8bit_oper(ins.quad[2], ins.quad[3])
        output.append('sub h')

    output.append('ccf')
    output.append('sbc a, a')
    output.append('push af')

    return output
Example #29
0
def _shri16(ins):
    ''' Arithmetical right shift 16bit signed integer.
    The result is pushed onto the stack.

    Optimizations:
      * If 2nd op is 0 then
        do nothing

      * If 2nd op is 1
        Shift Right Arithmetic
    '''
    op1, op2 = tuple(ins.quad[2:])
    if is_int(op2):
        op = int16(op2)
        if op == 0:
            return []

        output = _16bit_oper(op1)
        if op == 1:
            output.append('srl h')
            output.append('rr l')
            output.append('push hl')
            return output

        output.append('ld b, %i' % op)
    else:
        output = _8bit_oper(op2)
        output.append('ld b, a')
        output.extend(_16bit_oper(op1))

    label = tmp_label()
    output.append('%s:' % label)
    output.append('sra h')
    output.append('rr l')
    output.append('djnz %s' % label)
    output.append('push hl')
    return output
Example #30
0
def _sub8(ins):
    ''' Pops last 2 bytes from the stack and subtract them.
    Then push the result onto the stack. Top-1 of the stack is
    subtracted Top
    _sub8 t1, a, b === t1 <-- a - b

    Optimizations:
      * If 2nd op is ZERO,
        then do NOTHING: A - 0 = A

      * If 1st operand is 0, then
        just do a NEG

      * If any of the operands is 1, then
        DEC is used

      * If any of the operands is -1 (255), then
        INC is used
    '''

    op1, op2 = tuple(ins.quad[2:])
    if is_int(op2): # 2nd operand
        op2 = int8(op2)
        output = _8bit_oper(op1)

        if op2 == 0:
            output.append('push af')
            return output   # A - 0 = A

        op2 = int8(op2)

        if op2 == 1:    # A - 1 == DEC A
            output.append('dec a')
            output.append('push af')
            return output

        if op2 == 0xFF: # A - (-1) == INC A
            output.append('inc a')
            output.append('push af')
            return output

        output.append('sub %i' % op2)
        output.append('push af')
        return output

    if is_int(op1): # 1st operand is numeric?
        if int8(op1) == 0: # 0 - A = -A ==> NEG A
            output = _8bit_oper(op2)
            output.append('neg')
            output.append('push af')
            return output

    # At this point, even if 1st operand is numeric, proceed
    # normally

    if op2[0] == '_': # Optimization when 2nd operand is an id
        rev = True
        op1, op2 = op2, op1
    else:
        rev = False

    output = _8bit_oper(op1, op2, rev)
    output.append('sub h')
    output.append('push af')

    return output
Example #31
0
def _astorestr(ins):
    ''' Stores a string value into a memory address.
    It copies content of 2nd operand (string), into 1st, reallocating
    dynamic memory for the 1st str. These instruction DOES ALLOW
    immediate strings for the 2nd parameter, starting with '#'.
    '''
    output = _addr(ins.quad[1])
    op = ins.quad[2]

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

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

    temporal = op[0] != '$'
    if not temporal:
        op = op[1:]

    if is_int(op):
        op = str(int(op) & 0xFFFF)
        if indirect:
            if immediate:  # *#<addr> = ld hl, (number)
                output.append('ld de, (%s)' % op)
            else:
                output.append('ld de, (%s)' % op)
                output.append('call __LOAD_DE_DE')
                REQUIRES.add('lddede.asm')
        else:
            # Integer does not make sense here (unless it's a ptr)
            raise InvalidIC(str(ins))

            output.append('ld de, (%s)' % op)
    elif op[0] == '_':  # an identifier
        temporal = False  # Global var is not a temporary string

        if indirect:
            if immediate:  # *#_id = _id
                output.append('ld de, (%s)' % op)
            else:  # *_id
                output.append('ld de, (%s)' % op)
                output.append('call __LOAD_DE_DE')
                REQUIRES.add('lddede.asm')
        else:
            output.append('ld de, %s' % op)
    else:  # tn
        output.append('pop de')

        if indirect:
            output.append('call __LOAD_DE_DE')
            REQUIRES.add('lddede.asm')

    if not temporal:
        output.append('call __STORE_STR')
        REQUIRES.add('storestr.asm')
    else:  # A value already on dynamic memory
        output.append('call __STORE_STR2')
        REQUIRES.add('storestr2.asm')

    return output
Example #32
0
def _pstore8(ins):
    ''' Stores 2nd parameter at stack pointer (SP) + X, being
    X 1st parameter.

    1st operand must be a SIGNED integer.
    '''
    value = ins.quad[2]
    offset = ins.quad[1]
    indirect = offset[0] == '*'
    size = 0 
    if indirect:
        offset = offset[1:]
        size = 1

    I = int(offset)
    if I >= 0:
        I += 4 # Return Address + "push IX" 
        if not indirect:
            I += 1 # F flag ignored

    if is_int(value):
        output = []
    else:
        output = _8bit_oper(value)

    ix_changed = not (-128 + size <= I <= 127 - size) # Offset > 127 bytes. Need to change IX
    if ix_changed: # more than 1 byte
        output.append('push ix')
        output.append('pop hl')
        output.append('ld de, %i' % I)
        output.append('add hl, de')
        
    if indirect:
        if ix_changed:
            output.append('ld c, (hl)') 
            output.append('inc hl')
            output.append('ld h, (hl)')
            output.append('ld l, c')
        else:
            output.append('ld h, (ix%+i)' % (I + 1))
            output.append('ld l, (ix%+i)' % I)
        
        if is_int(value):
            output.append('ld (hl), %i' % int8(value))
        else:
            output.append('ld (hl), a')

        return output

    # direct store
    if ix_changed:
        if is_int(value):
            output.append('ld (hl), %i' % int8(value))
        else:
            output.append('ld (hl), a')

        return output

    if is_int(value):
        output.append('ld (ix%+i), %i' % (I, int8(value)))
    else:
        output.append('ld (ix%+i), a' % I)

    return output
Example #33
0
def _pstore16(ins):
    ''' Stores 2nd parameter at stack pointer (SP) + X, being
    X 1st parameter.

    1st operand must be a SIGNED integer.
    '''
    value = ins.quad[2]
    offset = ins.quad[1]
    indirect = offset[0] == '*'
    size = 1 
    if indirect:
        offset = offset[1:]

    I = int(offset)
    if I >= 0:
        I += 4 # Return Address + "push IX" 

    if is_int(value):
        output = []
    else:
        output = _16bit_oper(value)

    ix_changed = not (-128 + size <= I <= 127 - size) # Offset > 127 bytes. Need to change IX
        
    if indirect:
        if is_int(value):
            output.append('ld hl, %i' % int16(value))

        output.append('ld bc, %i' % I)
        output.append('call __PISTORE16')
        REQUIRES.add('istore16.asm')
        return output

    # direct store
    if ix_changed: # more than 1 byte
        if not is_int(value):
            output.append('ex de, hl')

        output.append('push ix')
        output.append('pop hl')
        output.append('ld bc, %i' % I)
        output.append('add hl, bc')

        if is_int(value):
            v = int16(value)
            output.append('ld (hl), %i' % (v & 0xFF))
            output.append('inc hl')
            output.append('ld (hl), %i' % (v >> 8))
            return output
        else:
            output.append('ld (hl), e')
            output.append('inc hl')
            output.append('ld (hl), d')
            return output

    if is_int(value):
        v = int16(value)
        output.append('ld (ix%+i), %i' % (I, v & 0xFF))
        output.append('ld (ix%+i), %i' % (I + 1, v >> 8))
    else:
        output.append('ld (ix%+i), l' % I)
        output.append('ld (ix%+i), h' % (I + 1))

    return output
Example #34
0
def _sub8(ins):
    ''' Pops last 2 bytes from the stack and subtract them.
    Then push the result onto the stack. Top-1 of the stack is
    subtracted Top
    _sub8 t1, a, b === t1 <-- a - b

    Optimizations:
      * If 2nd op is ZERO,
        then do NOTHING: A - 0 = A

      * If 1st operand is 0, then
        just do a NEG

      * If any of the operands is 1, then
        DEC is used

      * If any of the operands is -1 (255), then
        INC is used
    '''

    op1, op2 = tuple(ins.quad[2:])
    if is_int(op2):  # 2nd operand
        op2 = int8(op2)
        output = _8bit_oper(op1)

        if op2 == 0:
            output.append('push af')
            return output  # A - 0 = A

        op2 = int8(op2)

        if op2 == 1:  # A - 1 == DEC A
            output.append('dec a')
            output.append('push af')
            return output

        if op2 == 0xFF:  # A - (-1) == INC A
            output.append('inc a')
            output.append('push af')
            return output

        output.append('sub %i' % op2)
        output.append('push af')
        return output

    if is_int(op1):  # 1st operand is numeric?
        if int8(op1) == 0:  # 0 - A = -A ==> NEG A
            output = _8bit_oper(op2)
            output.append('neg')
            output.append('push af')
            return output

    # At this point, even if 1st operand is numeric, proceed
    # normally

    if op2[0] == '_':  # Optimization when 2nd operand is an id
        rev = True
        op1, op2 = op2, op1
    else:
        rev = False

    output = _8bit_oper(op1, op2, rev)
    output.append('sub h')
    output.append('push af')

    return output
Example #35
0
def _8bit_oper(op1, op2=None, reversed=False):
    ''' Returns pop sequence for 8 bits operands
    1st operand in H, 2nd operand in A (accumulator)

    For some operations (like comparisons), you can swap
    operands extraction by setting reversed = True
    '''
    output = []

    if op2 is not None and reversed:
        tmp = op1
        op1 = op2
        op2 = tmp

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

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

    if is_int(op):
        op = int(op)

        if indirect:
            output.append('ld a, (%i)' % op)
        else:
            if op == 0:
                output.append('xor a')
            else:
                output.append('ld a, %i' % int8(op))
    else:
        if immediate:
            if indirect:
                output.append('ld a, (%s)' % op)
            else:
                output.append('ld a, %s' % op)
        elif op[0] == '_':
            if indirect:
                output.append('ld bc, (%s)' % op)  # can't use HL
                output.append('ld a, (bc)')
            else:
                output.append('ld a, (%s)' % op)
        else:
            if immediate:
                output.append('ld a, %s' % op)
            elif indirect:
                output.append('pop bc')
                output.append('ld a, (bc)')
            else:
                output.append('pop af')

    if op2 is None:
        return output

    if not reversed:
        tmp = output
        output = []

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

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

    if is_int(op):
        op = int(op)

        if indirect:
            output.append('ld hl, (%i - 1)' % op)
        else:
            output.append('ld h, %i' % int8(op))
    else:
        if immediate:
            if indirect:
                output.append('ld hl, %s' % op)
                output.append('ld h, (hl)')
            else:
                output.append('ld h, %s' % op)
        elif op[0] == '_':
            if indirect:
                output.append('ld hl, (%s)' % op)
                output.append('ld h, (hl)' % op)
            else:
                output.append('ld hl, (%s - 1)' % op)
        else:
            output.append('pop hl')

        if indirect:
            output.append('ld b, (hl)')
            output.append('inc hl')
            output.append('ld h, (hl)')
            output.append('ld l, c')
            output.append('ld h, (hl)')

    if not reversed:
        output.extend(tmp)

    return output
Example #36
0
def _32bit_oper(op1, op2 = None, reversed = False, preserveHL = 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

    int1 = False # whether op1 (2nd operand) is integer
    int2 = False # whether op1 (2nd operand) is integer
    
    indirect = (op[0] == '*')
    if indirect:
        op = op[1:]

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

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

    if is_int(op):
        int1 = True
        op = int(op)

        if indirect:
            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 = int32(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_int(op):
            int2 = True
            op = int(op)
    
            if indirect:
                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 = int32(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 int1 or op1[0] == '_': # If previous op was integer, 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 #37
0
def _8bit_oper(op1, op2 = None, reversed = False):
    ''' Returns pop sequence for 8 bits operands
    1st operand in H, 2nd operand in A (accumulator)

    For some operations (like comparisons), you can swap
    operands extraction by setting reversed = True
    '''
    output = []

    if op2 is not None and reversed:
        tmp = op1
        op1 = op2
        op2 = tmp

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

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

    if is_int(op):
        op = int(op)

        if indirect:
            output.append('ld a, (%i)' % op)
        else:
            if op == 0:
                output.append('xor a')
            else:
                output.append('ld a, %i' % int8(op))
    else:
        if immediate:
            if indirect:
                output.append('ld a, (%s)' % op)
            else:
                output.append('ld a, %s' % op)
        elif op[0] == '_':
            if indirect:
                output.append('ld bc, (%s)' % op)  # can't use HL
                output.append('ld a, (bc)')
            else:
                output.append('ld a, (%s)' % op)
        else:
            if immediate:
                output.append('ld a, %s' % op)
            elif indirect:
                output.append('pop bc')
                output.append('ld a, (bc)')
            else:
                output.append('pop af')

    if op2 is None:
        return output

    if not reversed:
        tmp = output
        output = []

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

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

    if is_int(op):
        op = int(op)

        if indirect:
            output.append('ld hl, (%i - 1)' % op)
        else:
            output.append('ld h, %i' % int8(op))
    else:
        if immediate:
            if indirect:
                output.append('ld hl, %s' % op)
                output.append('ld h, (hl)')
            else:
                output.append('ld h, %s' % op)
        elif op[0] == '_':
            if indirect:
                output.append('ld hl, (%s)' % op)
                output.append('ld h, (hl)' % op)
            else:
                output.append('ld hl, (%s - 1)' % op)
        else:
            output.append('pop hl')

        if indirect:
            output.append('ld b, (hl)')
            output.append('inc hl')
            output.append('ld h, (hl)')
            output.append('ld l, c')
            output.append('ld h, (hl)')

    if not reversed:
        output.extend(tmp)

    return output
Example #38
0
def _16bit_oper(op1, op2 = None, reversed = False):
    ''' Returns pop sequence for 16 bits operands
    1st operand in HL, 2nd operand in DE

    For subtraction, division, etc. you can swap operators extraction order
    by setting reversed to True
    '''
    output = []

    if op1 is not None:
        op1 = str(op1) # always to str

    if op2 is not None:
        op2 = str(op2) # always to str

    if op2 is not None and reversed:
        op1, op2 = op2, op1

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

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

    if is_int(op):
        op = int(op)

        if indirect:
            output.append('ld hl, (%i)' % op)
        else:
            output.append('ld hl, %i' % int16(op))
    else:
        if immediate:
            if indirect:
                output.append('ld hl, (%s)' % op)
            else:
                output.append('ld hl, %s' % op)
        else:
            if op[0] == '_':
                output.append('ld hl, (%s)' % op)
            else:
                output.append('pop hl')
    
            if indirect:
                output.append('ld a, (hl)')
                output.append('inc hl')
                output.append('ld h, (hl)')
                output.append('ld l, a')

    if op2 is None:
        return output

    if not reversed:
        tmp = output
        output = []

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

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

    if is_int(op):
        op = int(op)

        if indirect:
            output.append('ld de, (%i)' % op)
        else:
            output.append('ld de, %i' % int16(op))
    else:
        if immediate:
            output.append('ld de, %s' % op)
        else:
            if op[0] == '_':
                output.append('ld de, (%s)' % op)
            else:
                output.append('pop de')
    
            if indirect:
                output.append('call __LOAD_DE_DE') # DE = (DE)
                REQUIRES.add('lddede.asm')

    if not reversed:
        output.extend(tmp)

    return output
Example #39
0
def _astorestr(ins):
    ''' Stores a string value into a memory address.
    It copies content of 2nd operand (string), into 1st, reallocating
    dynamic memory for the 1st str. These instruction DOES ALLOW
    immediate strings for the 2nd parameter, starting with '#'.
    '''
    output = _addr(ins.quad[1])
    op = ins.quad[2]

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

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

    temporal = op[0] != '$'
    if not temporal:
        op = op[1:]

    if is_int(op):
        op = str(int(op) & 0xFFFF)
        if indirect:
            if immediate:  # *#<addr> = ld hl, (number)
                output.append('ld de, (%s)' % op)
            else:
                output.append('ld de, (%s)' % op)
                output.append('call __LOAD_DE_DE')
                REQUIRES.add('lddede.asm')
        else: 
            # Integer does not make sense here (unless it's a ptr)
            raise InvalidIC(str(ins))

            output.append('ld de, (%s)' % op)
    elif op[0] == '_': # an identifier
        temporal = False # Global var is not a temporary string

        if indirect:
            if immediate: # *#_id = _id
                output.append('ld de, (%s)' % op)
            else: # *_id
                output.append('ld de, (%s)' % op)
                output.append('call __LOAD_DE_DE')
                REQUIRES.add('lddede.asm')
        else:
            output.append('ld de, %s' % op)
    else: # tn
        output.append('pop de')

        if indirect:
            output.append('call __LOAD_DE_DE')
            REQUIRES.add('lddede.asm')

    if not temporal:
        output.append('call __STORE_STR')
        REQUIRES.add('storestr.asm')
    else: # A value already on dynamic memory
        output.append('call __STORE_STR2')
        REQUIRES.add('storestr2.asm')

    return output