def _band8(ins): ''' Pops top 2 operands out of the stack, and does 1st AND (bitwise) 2nd operand (top of the stack), pushes the result. 8 bit un/signed version ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2) is not None: op1, op2 = _int_ops(op1, op2) output = _8bit_oper(op1) if op2 == 0xFF: # X & 0xFF = X output.append('push af') return output if op2 == 0: # X and 0 = 0 output.append('xor a') output.append('push af') return output op1, op2 = tuple(ins.quad[2:]) output = _8bit_oper(op1, op2) output.append('and h') output.append('push af') REQUIRES.add('and8.asm') return output
def _xor8(ins): ''' Pops top 2 operands out of the stack, and checks if 1st operand XOR (logical) 2nd operand (top of the stack), pushes 0 if False, 1 if True. 8 bit un/signed version ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2) is not None: op1, op2 = _int_ops(op1, op2) output = _8bit_oper(op1) # True or X = not X if op2 == 0: # False xor X = X output.append('push af') return output output.append('sub 1') output.append('sbc a, a') output.append('push af') return output output = _8bit_oper(op1, op2) output.append('call __XOR8') output.append('push af') REQUIRES.add('xor8.asm') return output
def _and8(ins): ''' Pops top 2 operands out of the stack, and checks if 1st operand AND (logical) 2nd operand (top of the stack), pushes 0 if False, not 0 if True. 8 bit un/signed version ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2) is not None: op1, op2 = _int_ops(op1, op2) output = _8bit_oper(op1) # Pops the stack (if applicable) if op2 != 0: # X and True = X output.append('push af') return output # False and X = False output.append('xor a') output.append('push af') return output output = _8bit_oper(op1, op2) output.append('call __AND8') output.append('push af') REQUIRES.add('and8.asm') return output
def _bor8(ins): ''' pops top 2 operands out of the stack, and does OR (bitwise) with 1st and 2nd operand (top of the stack), pushes result. 8 bit un/signed version ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2) is not None: op1, op2 = _int_ops(op1, op2) output = _8bit_oper(op1) if op2 == 0: # X | 0 = X output.append('push af') return output if op2 == 0xFF: # X | 0xFF = 0xFF output.append('ld a, 0FFh') output.append('push af') return output op1, op2 = tuple(ins.quad[2:]) output = _8bit_oper(op1, op2) output.append('or h') output.append('push af') return output
def _or8(ins): ''' Pops top 2 operands out of the stack, and checks if 1st operand OR (logical) 2nd operand (top of the stack), pushes 0 if False, not 0 if True. 8 bit un/signed version ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2) is not None: op1, op2 = _int_ops(op1, op2) output = _8bit_oper(op1) if op2 == 0: # X or False = X output.append('push af') return output # X or True = True output.append('ld a, 1') # True output.append('push af') return output output = _8bit_oper(op1, op2) output.append('or h') output.append('push af') return output
def _bxor8(ins): ''' Pops top 2 operands out of the stack, and does 1st operand XOR (bitwise) 2nd operand (top of the stack), pushes the result 8 bit un/signed version ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2) is not None: op1, op2 = _int_ops(op1, op2) output = _8bit_oper(op1) if op2 == 0: # 0 xor X = X output.append('push af') return output if op2 == 0xFF: # X xor 0xFF = ~X output.append('cpl') output.append('push af') return output op1, op2 = tuple(ins.quad[2:]) output = _8bit_oper(op1, op2) output.append('xor h') output.append('push af') return output
def _and16(ins): ''' Compares & pops top 2 operands out of the stack, and checks if the 1st operand AND (logical) 2nd operand (top of the stack), pushes 0 if False, 1 if True. 16 bit un/signed version Optimizations: If any of the operators are constants: Returns either 0 or the other operand ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2) is not None: op1, op2 = _int_ops(op1, op2) output = _16bit_oper(op1) if op2 != 0: output.append('ld a, h') output.append('or l') output.append('push af') return output # X and True = X output = _16bit_oper(op1) output.append('xor a') # X and False = False output.append('push af') return output output = _16bit_oper(op1, op2) output.append('call __AND16') output.append('push af') REQUIRES.add('and16.asm') return output
def _and32(ins): ''' Compares & pops top 2 operands out of the stack, and checks if the 1st operand AND (Logical) 2nd operand (top of the stack). Pushes 0 if False, 1 if True. 32 bit un/signed version ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2): op1, op2 = _int_ops(op1, op2) if op2 == 0: # X and False = False if str(op1)[0] == 't': # a temporary term (stack) output = _32bit_oper(op1) # Remove op1 from the stack else: output = [] output.append('xor a') output.append('push af') return output # For X and TRUE = X we do nothing as we have to convert it to boolean # which is a rather expensive instruction output = _32bit_oper(op1, op2) output.append('call __AND32') output.append('push af') REQUIRES.add('and32.asm') return output
def _bxor16(ins): ''' Pops top 2 operands out of the stack, and performs 1st operand XOR (bitwise) 2nd operand (top of the stack), pushes result (16 bit in HL). 16 bit un/signed version Optimizations: If any of the operators are constants: Returns either 0 or the other operand ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2) is not None: op1, op2 = _int_ops(op1, op2) output = _16bit_oper(op1) if op2 == 0: # X ^ 0 = X output.append('push hl') return output if op2 == 0xFFFF: # X ^ 0xFFFF = bNOT X output.append('call __NEGHL') output.append('push hl') REQUIRES.add('neg16.asm') return output output = _16bit_oper(op1, op2) output.append('call __BXOR16') output.append('push hl') REQUIRES.add('bxor16.asm') return output
def _band16(ins): ''' Pops top 2 operands out of the stack, and performs 1st operand AND (bitwise) 2nd operand (top of the stack), pushes result (16 bit in HL). 16 bit un/signed version Optimizations: If any of the operators are constants: Returns either 0 or the other operand ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2) is not None: op1, op2 = _int_ops(op1, op2) if op2 == 0xFFFF: # X & 0xFFFF = X return [] if op2 == 0: # X & 0 = 0 output = _16bit_oper(op1) output.append('ld hl, 0') output.append('push hl') return output output = _16bit_oper(op1, op2) output.append('call __BAND16') output.append('push hl') REQUIRES.add('band16.asm') return output
def _mul32(ins): ''' Multiplies two last 32bit values on top of the stack and and returns the value on top of the stack Optimizations done: * If any operand is 1, do nothing * If any operand is 0, push 0 ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2): op1, op2 = _int_ops(op1, op2) output = _32bit_oper(op1) if op2 == 1: output.append('push de') output.append('push hl') return output # A * 1 = Nothing if op2 == 0: output.append('ld hl, 0') output.append('push hl') output.append('push hl') return output output = _32bit_oper(op1, op2) output.append('call __MUL32') # Inmmediate output.append('push de') output.append('push hl') REQUIRES.add('mul32.asm') return output
def _mul16(ins): ''' Multiplies tow last 16bit values on top of the stack and and returns the value on top of the stack Optimizations: * If any of the ops is ZERO, then do A = 0 ==> XOR A, cause A * 0 = 0 * A = 0 * If any ot the ops is ONE, do NOTHING A * 1 = 1 * A = A * If B is 2^n and B < 16 => Shift Right n ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2) is not None: # If any of the operands is constant op1, op2 = _int_ops(op1, op2) # put the constant one the 2nd output = _16bit_oper(op1) if op2 == 0: # A * 0 = 0 * A = 0 if op1[0] in ('_', '$'): output = [] # Optimization: Discard previous op if not from the stack output.append('ld hl, 0') output.append('push hl') return output if op2 == 1: # A * 1 = 1 * A == A => Do nothing output.append('push hl') return output if op2 == 0xFFFF: # This is the same as (-1) output.append('call __NEGHL') output.append('push hl') REQUIRES.add('neg16.asm') return output if is_2n(op2) and log2(op2) < 4: output.extend(['add hl, hl'] * int(log2(op2))) output.append('push hl') return output output.append('ld de, %i' % op2) else: if op2[0] == '_': # stack optimization op1, op2 = op2, op1 output = _16bit_oper(op1, op2) output.append('call __MUL16_FAST') # Inmmediate output.append('push hl') REQUIRES.add('mul16.asm') return output
def _mul8(ins): ''' Multiplies 2 las values from the stack. Optimizations: * If any of the ops is ZERO, then do A = 0 ==> XOR A, cause A * 0 = 0 * A = 0 * If any ot the ops is ONE, do NOTHING A * 1 = 1 * A = A ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2) is not None: op1, op2 = _int_ops(op1, op2) output = _8bit_oper(op1) if op2 == 1: # A * 1 = 1 * A = A output.append('push af') return output if op2 == 0: output.append('xor a') output.append('push af') return output if op2 == 2: # A * 2 == A SLA 1 output.append('add a, a') output.append('push af') return output if op2 == 4: # A * 4 == A SLA 2 output.append('add a, a') output.append('add a, a') output.append('push af') return output output.append('ld h, %i' % int8(op2)) else: if op2[0] == '_': # stack optimization op1, op2 = op2, op1 output = _8bit_oper(op1, op2) output.append('call __MUL8_FAST') # Inmmediate output.append('push af') REQUIRES.add('mul8.asm') return output
def _add8(ins): ''' Pops last 2 bytes from the stack and adds them. Then push the result onto the stack. Optimizations: * If any of the operands is ZERO, then do NOTHING: A + 0 = 0 + A = A * If any of the operands is 1, then INC is used * If any of the operands is -1 (255), then DEC is used ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2) is not None: op1, op2 = _int_ops(op1, op2) output = _8bit_oper(op1) if op2 == 0: # Nothing to add: A + 0 = A output.append('push af') return output op2 = int8(op2) if op2 == 1: # Adding 1 is just an inc output.append('inc a') output.append('push af') return output if op2 == 0xFF: # Adding 255 is just a dec output.append('dec a') output.append('push af') return output output.append('add a, %i' % int8(op2)) output.append('push af') return output if op2[0] == '_': # stack optimization op1, op2 = op2, op1 output = _8bit_oper(op1, op2) output.append('add a, h') output.append('push af') return output
def _add16(ins): ''' Pops last 2 bytes from the stack and adds them. Then push the result onto the stack. Optimizations: * If any of the operands is ZERO, then do NOTHING: A + 0 = 0 + A = A * If any of the operands is < 4, then INC is used * If any of the operands is > (65531) (-4), then DEC is used ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2) is not None: op1, op2 = _int_ops(op1, op2) op2 = int16(op2) output = _16bit_oper(op1) if op2 == 0: output.append('push hl') return output # ADD HL, 0 => NOTHING if op2 < 4: output.extend(['inc hl'] * op2) # ADD HL, 2 ==> inc hl; inc hl output.append('push hl') return output if op2 > 65531: # (between -4 and 0) output.extend(['dec hl'] * (0x10000 - op2)) output.append('push hl') return output output.append('ld de, %i' % op2) output.append('add hl, de') output.append('push hl') return output if op2[0] == '_': # stack optimization op1, op2 = op2, op1 output = _16bit_oper(op1, op2) output.append('add hl, de') output.append('push hl') return output
def _add32(ins): ''' Pops last 2 bytes from the stack and adds them. Then push the result onto the stack. Optimizations: * If any of the operands is ZERO, then do NOTHING: A + 0 = 0 + A = A ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2) is not None: o1, o2 = _int_ops(op1, op2) if int(o2) == 0: # A + 0 = 0 + A = A => Do Nothing output = _32bit_oper(o1) output.append('push de') output.append('push hl') return output if op1[0] == '_' and op2[0] != '_': op1, op2 = op2, op1 # swap them if op2[0] == '_': output = _32bit_oper(op1) output.append('ld bc, (%s)' % op2) output.append('add hl, bc') output.append('ex de, hl') output.append('ld bc, (%s + 2)' % op2) output.append('adc hl, bc') output.append('push hl') output.append('push de') return output output = _32bit_oper(op1, op2) output.append('pop bc') output.append('add hl, bc') output.append('ex de, hl') output.append('pop bc') output.append('adc hl, bc') output.append('push hl') # High and low parts are reversed output.append('push de') return output
def _xor16(ins): ''' Compares & pops top 2 operands out of the stack, and checks if the 1st operand XOR (logical) 2nd operand (top of the stack), pushes 0 if False, 1 if True. 16 bit un/signed version Optimizations: If any of the operators are constants: Returns either 0 or the other operand ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2) is not None: op1, op2 = _int_ops(op1, op2) output = _16bit_oper(op1) if op2 == 0: # X xor False = X output.append('ld a, h') output.append('or l') output.append('push af') return output # X xor True = NOT X output.append('ld a, h') output.append('or l') output.append('sub 1') output.append('sbc a, a') output.append('push af') return output output = _16bit_oper(ins.quad[2], ins.quad[3]) output.append('call __XOR16') output.append('push af') REQUIRES.add('xor16.asm') return output
def _or16(ins): ''' Compares & pops top 2 operands out of the stack, and checks if the 1st operand OR (logical) 2nd operand (top of the stack), pushes 0 if False, 1 if True. 16 bit un/signed version Optimizations: If any of the operators are constants: Returns either 0 or the other operand ''' op1, op2 = tuple(ins.quad[2:]) if _int_ops(op1, op2) is not None: op1, op2 = _int_ops(op1, op2) if op2 == 0: output = _16bit_oper(op1) output.append('ld a, h') output.append('or l') # Convert x to Boolean output.append('push af') return output # X or False = X output = _16bit_oper(op1) output.append('ld a, 0FFh') # X or True = True output.append('push af') return output output = _16bit_oper(ins.quad[2], ins.quad[3]) output.append('ld a, h') output.append('or l') output.append('or d') output.append('or e') output.append('push af') return output