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