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
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
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
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
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
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
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
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
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
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
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