[pypy-svn] r56991 - pypy/dist/pypy/lang/gameboy

cami at codespeak.net cami at codespeak.net
Tue Aug 5 10:24:41 CEST 2008


Author: cami
Date: Tue Aug  5 10:24:39 2008
New Revision: 56991

Added:
   pypy/dist/pypy/lang/gameboy/cpu.py
Modified:
   pypy/dist/pypy/lang/gameboy/gameboy_implementation.py
Log:
removed some debug statements from the cpu


Added: pypy/dist/pypy/lang/gameboy/cpu.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lang/gameboy/cpu.py	Tue Aug  5 10:24:39 2008
@@ -0,0 +1,1174 @@
+
+from pypy.lang.gameboy import constants
+from pypy.lang.gameboy.ram import *
+from pypy.lang.gameboy.interrupt import *
+
+from pypy.rlib.objectmodel import we_are_translated
+if not we_are_translated():
+    from pypy.lang.gameboy.debug import *
+
+# ---------------------------------------------------------------------------
+
+def process_2_complement(value):
+    # check if the left most bit is set
+    if (value >> 7) == 1:
+        return -((~value) & 0xFF) - 1
+    else :
+        return value
+# ---------------------------------------------------------------------------
+
+class AbstractRegister(object):
+    def get(self, use_cycles=True):
+        return 0xFF
+
+class Register(AbstractRegister):
+    
+    def __init__(self, cpu, value=0):
+        assert isinstance(cpu, CPU)
+        self.reset_value = self.value = value
+        self.cpu = cpu
+        if value != 0:
+            self.set(value)
+        
+    def reset(self):
+        self.value = self.reset_value
+        
+    def set(self, value, use_cycles=True):
+        self.value = value & 0xFF
+        if use_cycles:
+            self.cpu.cycles -= 1
+        
+    def get(self, use_cycles=True):
+        return self.value
+    
+    def add(self, value, use_cycles=True):
+        self.set(self.get(use_cycles)+value, use_cycles)
+        
+    def sub(self, value, use_cycles=True):
+        self.set(self.get(use_cycles)-value, use_cycles)
+    
+#------------------------------------------------------------------------------
+
+class DoubleRegister(AbstractRegister):
+    
+    def __init__(self, cpu, hi, lo, reset_value=0):
+        assert isinstance(cpu, CPU)
+        assert isinstance(lo, Register)
+        assert isinstance(hi, Register)
+        self.cpu = cpu
+        self.hi = hi
+        self.lo = lo
+        self.reset_value = reset_value
+        
+    def set(self, value, use_cycles=True):
+        value  = value & 0xFFFF
+        self.set_hi(value >> 8, use_cycles)
+        self.set_lo(value & 0xFF, use_cycles)
+        if use_cycles:
+            self.cpu.cycles += 1
+    
+    def set_hi_lo(self, hi, lo, use_cycles=True):
+        self.set_hi(hi, use_cycles)
+        self.set_lo(lo, use_cycles)
+            
+    def reset(self):
+        self.set(self.reset_value, use_cycles=False)
+            
+    def set_hi(self, hi=0, use_cycles=True):
+        self.hi.set(hi, use_cycles)
+    
+    def set_lo(self, lo=0, use_cycles=True):
+        self.lo.set(lo, use_cycles)
+        
+    def get(self, use_cycles=True):
+        return (self.hi.get(use_cycles)<<8) + self.lo.get(use_cycles)
+    
+    def get_hi(self, use_cycles=True):
+        return self.hi.get(use_cycles)
+        
+    def get_lo(self, use_cycles=True):
+        return self.lo.get(use_cycles)
+    
+    def inc(self, use_cycles=True):
+        self.set(self.get(use_cycles) +1, use_cycles=use_cycles)
+        if use_cycles:
+            self.cpu.cycles -= 1
+        
+    def dec(self, use_cycles=True):
+        self.set(self.get(use_cycles) - 1, use_cycles=use_cycles)
+        if use_cycles:
+            self.cpu.cycles -= 1
+        
+    def add(self, value, use_cycles=True):
+        self.set(self.get(use_cycles) + value, use_cycles=use_cycles)
+        if use_cycles:
+            self.cpu.cycles -= 2
+            
+    
+# ------------------------------------------------------------------------------
+
+class ImmediatePseudoRegister(Register):
+    
+        def __init__(self, cpu, hl):
+            assert isinstance(cpu, CPU)
+            self.cpu = cpu
+            self.hl = hl
+            
+        def set(self, value, use_cycles=True):
+            self.cpu.write(self.hl.get(use_cycles=use_cycles), value) # 2 + 0
+            if not use_cycles:
+                self.cpu.cycles += 2
+        
+        def get(self, use_cycles=True):
+            if not use_cycles:
+                self.cpu.cycles += 1
+            return self.cpu.read(self.hl.get(use_cycles=use_cycles)) # 1
+    
+# ------------------------------------------------------------------------------
+  
+class FlagRegister(Register):
+    
+    def __init__(self, cpu, reset_value):
+        assert isinstance(cpu, CPU)
+        self.cpu         = cpu
+        self.reset_value = reset_value
+        self.reset()
+         
+    def reset(self):
+        self.partial_reset()
+        
+    def partial_reset(self, keep_z=False, keep_n=False, keep_h=False, keep_c=False,\
+                keep_p=False, keep_s=False):
+        if not keep_z:
+            self.z_flag = False
+        if not keep_n:
+            self.n_flag = False
+        if not keep_h:
+            self.h_flag = False
+        if not keep_c:
+            self.c_flag = False
+        if not keep_p:
+            self.p_flag = False
+        if not keep_s:
+            self.s_flag = False
+        self.lower = 0x00
+            
+    def get(self, use_cycles=True):
+        value  = 0
+        value += (int(self.c_flag) << 4)
+        value += (int(self.h_flag) << 5)
+        value += (int(self.n_flag) << 6)
+        value += (int(self.z_flag) << 7)
+        return value + self.lower
+            
+    def set(self, value, use_cycles=True):
+        self.c_flag = bool(value & (1 << 4))
+        self.h_flag = bool(value & (1 << 5))
+        self.n_flag = bool(value & (1 << 6))
+        self.z_flag = bool(value & (1 << 7))
+        self.lower  = value & 0x0F
+        if use_cycles:
+            self.cpu.cycles -= 1
+        
+    def z_flag_compare(self, a, reset=False):
+        if reset:
+             self.reset()
+        if isinstance(a, (Register)):
+            a = a.get()
+        self.z_flag = ((a & 0xFF) == 0)
+            
+    def c_flag_compare(self, value, compare_and=0x01, reset=False):
+        if reset:
+             self.reset()
+        #print hex(value), hex(compare_and), (value & compare_and) != 0
+        self.c_flag = ((value & compare_and) != 0)
+
+    def h_flag_compare(self, value, a, inverted=False):
+        if inverted:
+            self.h_flag = ((value & 0x0F) < (a & 0x0F))
+        else:
+            self.h_flag = ((value & 0x0F) > (a & 0x0F))
+            
+    #def c_flag_compare(self, a, b):
+    #    self.c_flag = (a < b)
+        
+# # ------------------------------------------------------------------------------
+
+
+DEBUG_INSTRUCTION_COUNTER = 1
+
+class CPU(object):
+    """
+    PyGIRL GameBoy (TM) Emulator
+    
+    Central Unit Processor_a (Sharp LR35902 CPU)
+    """
+    def __init__(self, interrupt, memory):
+        assert isinstance(interrupt, Interrupt)
+        self.interrupt = interrupt
+        self.memory    = memory
+        self.ime       = False
+        self.halted    = False
+        self.cycles    = 0
+        self.ini_registers()
+        self.rom       = [0]
+        self.reset()
+
+    def ini_registers(self):
+        self.b   = Register(self)
+        self.c   = Register(self)
+        self.bc  = DoubleRegister(self, self.b, self.c, constants.RESET_BC)
+        
+        self.d   = Register(self)
+        self.e   = Register(self)
+        self.de  = DoubleRegister(self, self.d, self.e, constants.RESET_DE)
+
+        self.h   = Register(self)
+        self.l   = Register(self)
+        self.hl  = DoubleRegister(self, self.h, self.l, constants.RESET_HL)
+        
+        self.hli = ImmediatePseudoRegister(self, self.hl)
+        self.pc  = DoubleRegister(self, Register(self), Register(self), reset_value=constants.RESET_PC)
+        self.sp  = DoubleRegister(self, Register(self), Register(self), reset_value=constants.RESET_SP)
+        
+        self.a   = Register(self, constants.RESET_A)
+        self.f   = FlagRegister(self, constants.RESET_F)
+        self.af  = DoubleRegister(self, self.a, self.f)
+        
+
+    def reset(self):
+        self.reset_registers()
+        self.f.reset()
+        self.f.z_flag = True
+        self.ime      = False
+        self.halted   = False
+        self.cycles   = 0
+        self.instruction_counter        = 0
+        self.last_op_code               = -1
+        self.last_fetch_execute_op_code = -1
+        
+    def reset_registers(self):
+        self.a.reset()
+        self.f.reset()
+        self.bc.reset()
+        self.de.reset()
+        self.hl.reset()
+        self.sp.reset()
+        self.pc.reset()
+    
+    # ---------------------------------------------------------------
+
+    def get_af(self):
+        return self.af
+        
+    def get_a(self):
+        return self.a
+    
+    def get_f(self):
+        return self.f
+        
+    def get_bc(self):
+        return self.bc
+    
+    def get_b(self):
+        return self.b
+    
+    def get_c(self):
+        return self.c
+        
+    def get_de(self):
+        return self.de
+        
+    def get_d(self):
+        return self.d
+        
+    def get_e(self):
+        return self.e
+        
+    def get_hl(self):
+        return self.hl
+        
+    def get_hli(self):
+        return self.hli
+        
+    def get_h(self):
+        return self.h
+        
+    def get_l(self):
+        return self.l
+             
+    def get_sp(self):
+        return self.sp
+
+    def get_if(self):
+        val = 0x00
+        if self.ime:
+            val = 0x01
+        if self.halted:
+            val += 0x80
+        return val
+
+    def is_z(self):
+        """ zero flag"""
+        return self.f.z_flag
+
+    def is_c(self):
+        """ carry flag, true if the result did not fit in the register"""
+        return self.f.c_flag
+
+    def is_h(self):
+        """ half carry, carry from bit 3 to 4"""
+        return self.f.h_flag
+
+    def is_n(self):
+        """ subtract flag, true if the last operation was a subtraction"""
+        return self.f.n_flag
+    
+    def isS(self):
+        return self.f.s_flag
+    
+    def is_p(self):
+        return self.f.p_flag
+    
+    def is_not_z(self):
+        return not self.is_z()
+
+    def is_not_c(self):
+        return not self.is_c()
+    
+    def is_not_h(self):
+        return not self.is_h()
+
+    def is_not_n(self):
+        return not self.is_n()
+
+    def set_rom(self, banks):
+        self.rom = banks       
+    
+    # ---------------------------------------------------------------
+    
+    def emulate(self, ticks):
+        self.cycles += ticks
+        self.handle_pending_interrupts()
+        while self.cycles > 0:
+            self.execute(self.fetch())
+            
+    def emulate_step(self):
+        self.handle_pending_interrupts()
+        self.execute(self.fetch())
+        
+
+    def handle_pending_interrupts(self):
+        if self.halted:
+            self.update_interrupt_cycles()
+        if self.ime and self.interrupt.is_pending():
+            self.lower_pending_interrupt()
+            
+    def update_interrupt_cycles(self):
+        if self.interrupt.is_pending():
+            self.halted = False
+            self.cycles -= 4
+        elif self.cycles > 0:
+            self.cycles = 0
+        
+    def lower_pending_interrupt(self):
+        for flag in self.interrupt.interrupt_flags:
+            if flag.is_pending():
+                self.ime = False
+                self.call(flag.call_code, use_cycles=False)
+                flag.set_pending(False)
+                return
+
+    def fetch_execute(self):
+        op_code = self.fetch()
+        self.last_fetch_execute_op_code = op_code
+        FETCH_EXECUTE_OP_CODES[op_code](self)
+        
+        
+    def execute(self, op_code):
+        self.instruction_counter += 1
+        self.last_op_code = op_code
+        OP_CODES[op_code](self)
+        
+        
+    # -------------------------------------------------------------------
+        
+    def debug(self):
+        print "0xDD called"
+        
+    def read(self, hi, lo=None):
+        # memory Access, 1 cycle
+        address = hi
+        if lo is not None:
+            address = (hi << 8) + lo
+        self.cycles -= 1
+        return self.memory.read(address)
+
+    def write(self, address, data):
+        # 2 cycles
+        self.memory.write(address, data)
+        self.cycles -= 2
+
+    def fetch(self, use_cycles=True):
+        # Fetching  1 cycle
+        self.cycles += 1
+        if self.pc.get(use_cycles) <= 0x3FFF:
+            data =  self.rom[self.pc.get(use_cycles)]
+        else:
+            data = self.memory.read(self.pc.get(use_cycles))
+        self.pc.inc(use_cycles) # 2 cycles
+        return data
+    
+    def fetch_double_address(self):
+        lo = self.fetch() # 1 cycle
+        hi = self.fetch() # 1 cycle
+        return (hi << 8) + lo
+        
+    def fetch_double_register(self, register):
+        self.double_register_inverse_call(CPUFetchCaller(self), register)
+
+    def push(self, data, use_cycles=True):
+        # Stack, 2 cycles
+        self.sp.dec(use_cycles) # 2 cycles
+        self.memory.write(self.sp.get(use_cycles), data)
+        
+    def push_double_register(self, register, use_cycles=True):
+        # PUSH rr 4 cycles
+        self.push(register.get_hi(), use_cycles) # 2 cycles
+        self.push(register.get_lo(), use_cycles) # 2 cycles
+
+    def pop(self, use_cycles=True):
+        # 1 cycle
+        data = self.memory.read(self.sp.get())
+        self.sp.inc() # 2 cycles
+        self.cycles += 1
+        return data
+    
+    def pop_double_register(self, register):
+        # 3 cycles
+        self.double_register_inverse_call(CPUPopCaller(self), register)
+        
+    def double_register_inverse_call(self, getCaller, register):
+        b = getCaller.get() # 1 cycle
+        a = getCaller.get() # 1 cycle
+        register.set_hi_lo(a, b) # 2 cycles
+        self.cycles += 1
+        
+    def call(self, address, use_cycles=True):
+        # 4 cycles
+        self.push_double_register(self.pc, use_cycles)
+        self.pc.set(address, use_cycles=use_cycles)       # 1 cycle
+        if use_cycles:
+            self.cycles += 1
+        
+    def ld(self, getCaller, setCaller):
+        # 1 cycle
+        setCaller.set(getCaller.get()) # 1 cycle
+        
+    def load_fetch_register(self, register):
+        self.ld(CPUFetchCaller(self), RegisterCallWrapper(register))
+        
+    def store_hl_in_pc(self):
+        # LD PC,HL, 1 cycle
+        self.ld(DoubleRegisterCallWrapper(self.hl), 
+                DoubleRegisterCallWrapper(self.pc))
+        
+    def fetch_load(self, getCaller, setCaller):
+        self.ld(CPUFetchCaller(self), setCaller)
+
+    def add_a(self, getCaller, setCaller=None):
+        data = getCaller.get()
+        # ALU, 1 cycle
+        added = (self.a.get() + data) & 0xFF
+        self.add_sub_flag_finish(added, data)
+        
+    def add_hl(self, register):
+        # 2 cycles
+        data = register.get()
+        added = (self.hl.get() + data) # 1 cycle
+        self.f.partial_reset(keep_z=True)
+        self.f.h_flag = (((added ^ self.hl.get() ^ data) & 0x1000) != 0) 
+        self.f.c_flag = (added >= 0x10000 or added < 0)
+        self.hl.set(added & 0xFFFF)
+        self.cycles -= 1
+        
+    def add_a_with_carry(self, getCaller, setCaller=None):
+        # 1 cycle
+        data = getCaller.get()
+        s = self.a.get() + data + int(self.f.c_flag)
+        self.add_sub_flag_finish(s,data)
+
+    def subtract_with_carry_a(self, getCaller, setCaller=None):
+        # 1 cycle
+        data = getCaller.get()
+        s = self.a.get() - data - int(self.f.c_flag)
+        self.add_sub_flag_finish(s, data)
+        self.f.n_flag = True
+        
+    def add_sub_flag_finish(self, s, data):
+        self.f.reset()
+        # set the h flag if the 0x10 bit was affected
+        self.f.h_flag = (((s ^ self.a.get() ^ data) & 0x10) != 0)
+        self.f.c_flag = (s >= 0x100 or s < 0)
+        self.f.z_flag_compare(s)
+        self.a.set(s & 0xFF)  # 1 cycle
+        
+    def subtract_a(self, getCaller, setCaller=None):
+        # 1 cycle
+        data = getCaller.get()
+        self.compare_a_simple(data)
+        self.a.sub(data, False)
+ 
+    def fetch_subtract_a(self):
+        data = self.fetch()
+        # 1 cycle
+        self.compare_a_simple(data) # 1 cycle
+        self.a.sub(data, False)
+
+    def compare_a(self, getCaller, setCaller=None):
+        # 1 cycle
+        self.compare_a_simple(getCaller.get())
+        
+    def compare_a_simple(self, s):
+        s = (self.a.get() - s) & 0xFF
+        self.f.reset()
+        self.f.n_flag = True
+        self.f.z_flag_compare(s)
+        self.subtract_hc_flag_finish(s)
+        self.cycles -= 1
+            
+    def subtract_hc_flag_finish(self, data):
+        self.f.c_flag = (data > self.a.get())
+        self.f.h_flag_compare(data, self.a.get())
+        
+    def and_a(self, getCaller, setCaller=None):
+        # 1 cycle
+        self.a.set(self.a.get() & getCaller.get())  # 1 cycle
+        self.f.reset()
+        self.f.z_flag_compare(self.a.get())
+        self.f.h_flag = True
+
+    def xor_a(self, getCaller, setCaller=None):
+        # 1 cycle
+        self.a.set( self.a.get() ^ getCaller.get())  # 1 cycle
+        self.f.z_flag_compare(self.a.get(), reset=True)
+
+    def or_a(self, getCaller, setCaller=None):
+        # 1 cycle
+        self.a.set(self.a.get() | getCaller.get())  # 1 cycle
+        self.f.z_flag_compare(self.a.get(), reset=True)
+
+    def inc_double_register(self, register):
+        # INC rr
+        register.inc()
+
+    def dec_double_register(self, register):
+        # DEC rr
+        register.dec()
+
+    def inc(self, getCaller, setCaller):
+        # 1 cycle
+        data = (getCaller.get() + 1) & 0xFF
+        self.dec_inc_flag_finish(data, setCaller, 0x00)
+        
+    def dec(self, getCaller, setCaller):
+        # 1 cycle
+        data = (getCaller.get() - 1) & 0xFF
+        self.dec_inc_flag_finish(data, setCaller, 0x0F)
+        self.f.n_flag = True
+     
+    def dec_inc_flag_finish(self, data, setCaller, compare):
+        self.f.partial_reset(keep_c=True)
+        self.f.z_flag_compare(data)
+        self.f.h_flag = ((data & 0x0F) == compare)
+        setCaller.set(data) # 1 cycle
+
+    def rotate_left_circular(self, getCaller, setCaller):
+        # RLC 1 cycle
+        data = getCaller.get()
+        s = ((data << 1) & 0xFF) + ((data & 0x80) >> 7)
+        self.flags_and_setter_finish(s, data, setCaller, 0x80)
+        #self.cycles -= 1
+
+    def rotate_left_circular_a(self):
+        # RLCA rotate_left_circular_a 1 cycle
+        self.rotate_left_circular(RegisterCallWrapper(self.a), 
+                                  RegisterCallWrapper(self.a))
+
+    def rotate_left(self, getCaller, setCaller):
+        # 1 cycle
+        data = getCaller.get()
+        s = ((data & 0x7F) << 1) + int(self.f.c_flag)
+        self.flags_and_setter_finish(s, data, setCaller, 0x80) # 1 cycle
+
+    def rotate_left_a(self):
+        # RLA  1 cycle
+        self.rotate_left(RegisterCallWrapper(self.a), 
+                         RegisterCallWrapper(self.a))
+        
+    def rotate_right_circular(self, getCaller, setCaller):
+        data = getCaller.get()
+        # RRC 1 cycle
+        s = (data >> 1) + ((data & 0x01) << 7)
+        self.flags_and_setter_finish(s, data, setCaller) # 1 cycle
+   
+    def rotate_right_circular_a(self):
+        # RRCA 1 cycle
+        self.rotate_right_circular(RegisterCallWrapper(self.a), 
+                                   RegisterCallWrapper(self.a))
+
+    def rotate_right(self, getCaller, setCaller):
+        # 1 cycle
+        data = getCaller.get()
+        s = (data >> 1)
+        if self.f.c_flag:
+            s +=  0x80
+        self.flags_and_setter_finish(s, data, setCaller) # 1 cycle
+
+    def rotate_right_a(self):
+        # RRA 1 cycle
+        self.rotate_right(RegisterCallWrapper(self.a), 
+                          RegisterCallWrapper(self.a))
+   
+    def shift_left_arithmetic(self, getCaller, setCaller):
+        # 2 cycles
+        data = getCaller.get()
+        s = (data << 1) & 0xFF
+        self.flags_and_setter_finish(s, data, setCaller, 0x80) # 1 cycle
+
+    def shift_right_arithmetic(self, getCaller, setCaller):
+        data = getCaller.get()
+        # 1 cycle
+        s = (data >> 1) + (data & 0x80)
+        self.flags_and_setter_finish(s, data, setCaller) # 1 cycle
+
+    def shift_word_right_logical(self, getCaller, setCaller):
+        # 2 cycles
+        data = getCaller.get()
+        s = (data >> 1)
+        self.flags_and_setter_finish(s, data, setCaller) # 2 cycles
+         
+    def flags_and_setter_finish(self, s, data, setCaller, compare_and=0x01):
+        # 2 cycles
+        s &= 0xFF
+        self.f.reset()
+        self.f.z_flag_compare(s)
+        self.f.c_flag_compare(data, compare_and)
+        setCaller.set(s) # 1 cycle
+
+    def swap(self, getCaller, setCaller):
+        data = getCaller.get()
+        # 1 cycle
+        s = ((data << 4) + (data >> 4)) & 0xFF
+        self.f.z_flag_compare(s, reset=True)
+        setCaller.set(s)
+
+
+    def test_bit(self, getCaller, setCaller, n):
+        # 2 cycles
+        self.f.partial_reset(keep_c=True)
+        self.f.h_flag = True
+        self.f.z_flag = False
+        self.f.z_flag = ((getCaller.get() & (1 << n)) == 0)
+        self.cycles -= 1
+
+    def set_bit(self, getCaller, setCaller, n):
+        # 1 cycle
+        setCaller.set(getCaller.get() | (1 << n)) # 1 cycle
+        
+    def reset_bit(self, getCaller, setCaller, n):
+        # 1 cycle
+        setCaller.set(getCaller.get() & (~(1 << n))) # 1 cycle
+        
+    def store_fetched_memory_in_a(self):
+        # LD A,(nnnn), 4 cycles
+        self.a.set(self.read(self.fetch_double_address()))  # 1+1 + 2 cycles
+
+    def write_a_at_bc_address(self):
+        # 2 cycles
+        self.write(self.bc.get(), self.a.get())
+        
+    def write_a_at_de_address(self):
+        self.write(self.de.get(), self.a.get())
+           
+    def store_memory_at_bc_in_a(self):
+        self.a.set(self.read(self.bc.get()))
+
+    def store_memory_at_de_in_a(self):
+        self.a.set(self.read(self.de.get()))
+
+    def ld_dbRegisteri_A(self, register):
+        # LD (rr),A  2 cycles
+        self.write(register.get(), self.a.get()) # 2 cycles
+
+    def load_mem_sp(self):
+        # LD (nnnn),SP  5 cycles
+        address = self.fetch_double_address() # 2 cycles
+        self.write(address,       self.sp.get_lo())  # 2 cycles
+        self.write((address + 1), self.sp.get_hi()) # 2 cycles
+        self.cycles += 1
+
+    def store_a_at_fetched_address(self):
+        # LD (nnnn),A  4 cycles
+        self.write(self.fetch_double_address(), self.a.get()) # 2 cycles
+
+    def store_memory_at_axpanded_fetch_address_in_a(self):
+        # LDH A,(nn) 3 cycles
+        self.a.set(self.read(0xFF00 + self.fetch())) # 1+1+1 cycles
+        
+    def store_expanded_c_in_a(self):
+        # LDH A,(C) 2 cycles
+        self.a.set(self.read(0xFF00 + self.bc.get_lo())) # 1+2 cycles
+        
+    def load_and_increment_a_hli(self):
+        # loadAndIncrement A,(HL) 2 cycles
+        self.a.set(self.read(self.hl.get())) # 2 cycles
+        self.hl.inc()# 2 cycles
+        self.cycles += 2
+        
+    def load_and_decrement_a_hli(self):
+        # loadAndDecrement A,(HL)  2 cycles
+        self.a.set(self.read(self.hl.get())) # 2 cycles
+        self.hl.dec() # 2 cycles
+        self.cycles += 2
+        
+    def write_a_at_expanded_fetch_address(self):
+        # LDH (nn),A 3 cycles
+        self.write(0xFF00 + self.fetch(), self.a.get()) # 2 + 1 cycles
+
+    def write_a_at_expaded_c_address(self):
+        # LDH (C),A 2 cycles
+        self.write(0xFF00 + self.c.get(), self.a.get()) # 2 cycles
+        
+    def load_and_increment_hli_a(self):
+        # loadAndIncrement (HL),A 2 cycles
+        self.write(self.hl.get(), self.a.get()) # 2 cycles
+        self.hl.inc() # 2 cycles
+        self.cycles += 2
+
+    def load_and_decrement_hli_a(self):
+        # loadAndDecrement (HL),A  2 cycles
+        self.write(self.hl.get(), self.a.get()) # 2 cycles
+        self.hl.dec() # 2 cycles
+        self.cycles += 2
+
+    def store_hl_in_sp(self):
+        # LD SP,HL 2 cycles
+        self.sp.set(self.hl.get()) # 1 cycle
+        self.cycles -= 1
+
+    def complement_a(self):
+        # CPA
+        self.a.set(self.a.get() ^ 0xFF)
+        self.f.n_flag = True
+        self.f.h_flag = True
+
+    def decimal_adjust_a(self):
+        # DAA 1 cycle
+        delta = 0
+        if self.is_h(): 
+            delta |= 0x06
+        if self.is_c():
+            delta |= 0x60
+        if (self.a.get() & 0x0F) > 0x09:
+            delta |= 0x06
+            if (self.a.get() & 0xF0) > 0x80:
+                delta |= 0x60
+        if (self.a.get() & 0xF0) > 0x90:
+            delta |= 0x60
+        if not self.is_n():
+            self.a.set((self.a.get() + delta) & 0xFF) # 1 cycle
+        else:
+            self.a.set((self.a.get() - delta) & 0xFF) # 1 cycle
+        self.f.partial_reset(keep_n=True)
+        if delta >= 0x60:
+            self.f.c_flag = True
+        self.f.z_flag_compare(self.a.get())
+
+    def increment_sp_by_fetch(self):
+        # ADD SP,nn 4 cycles
+        self.sp.set(self.get_fetchadded_sp()) # 1+1 cycle
+        self.cycles -= 2
+
+    def store_fetch_added_sp_in_hl(self):
+        # LD HL,SP+nn   3  cycles
+        self.hl.set(self.get_fetchadded_sp()) # 1+1 cycle
+        self.cycles -= 1
+
+    def get_fetchadded_sp(self):
+        # 1 cycle
+        offset = process_2_complement(self.fetch()) # 1 cycle
+        s = (self.sp.get() + offset) & 0xFFFF
+        self.f.reset()
+        if (offset >= 0):
+            self.f.c_flag = (s < self.sp.get())
+            if (s & 0x0F00) < (self.sp.get() & 0x0F00):
+                self.f.h_flag = True
+        else:
+            self.f.c_flag = (s > self.sp.get())
+            if (s & 0x0F00) > (self.sp.get() & 0x0F00):
+                self.f.h_flag = True
+        return s
+    
+        
+    def complement_carry_flag(self):
+        # CCF/SCF
+        self.f.partial_reset(keep_z=True, keep_c=True)
+        self.f.c_flag = not self.f.c_flag
+
+    def set_carry_flag(self):
+        self.f.partial_reset(keep_z=True)
+        self.f.c_flag = True
+
+    def nop(self):
+        # NOP 1 cycle
+        self.cycles -= 1
+
+    def jump(self):
+        # JP nnnn, 4 cycles
+        self.pc.set(self.fetch_double_address()) # 1+2 cycles
+        self.cycles -= 1
+
+    def conditional_jump(self, cc):
+        # JP cc,nnnn 3,4 cycles
+        if cc:
+            self.jump() # 4 cycles
+        else:
+            self.pc.add(2) # 3 cycles
+
+    def relative_jump(self):
+        # JR +nn, 3 cycles
+        self.pc.add(process_2_complement(self.fetch())) # 3 + 1 cycles
+        self.cycles += 1
+
+    def relative_conditional_jump(self, cc):
+        # JR cc,+nn, 2,3 cycles
+        if cc:
+            self.relative_jump() # 3 cycles
+        else:
+            self.pc.inc() # 2 cycles
+    
+    def unconditional_call(self):
+        # CALL nnnn, 6 cycles
+        self.call(self.fetch_double_address())  # 4+2 cycles
+
+    def conditional_call(self, cc):
+        # CALL cc,nnnn, 3,6 cycles
+        if cc:
+            self.unconditional_call() # 6 cycles
+        else:
+            self.pc.add(2) # 3 cycles
+
+    def ret(self):
+        # RET 4 cycles
+        lo = self.pop() # 1 cycle
+        hi = self.pop() # 1 cycle
+        self.pc.set_hi_lo(hi, lo) # 2 cycles
+
+    def conditional_return(self, cc):
+        # RET cc 2,5 cycles
+        if cc:
+            self.ret() # 4 cycles
+            # FIXME maybe this should be the same
+            self.cycles -= 1
+        else:
+            self.cycles -= 2
+
+    def return_form_interrupt(self):
+        # RETI 4 cycles
+        self.ret() # 4 cycles
+        self.enable_interrupts() # 1 cycle + others
+        #self.cycles += 1
+
+    def restart(self, nn):
+        # RST nn 4 cycles
+        self.call(nn) # 4 cycles
+
+    def disable_interrups(self):
+        # DI/EI 1 cycle
+        self.ime     = False
+        self.cycles -= 1
+
+    def enable_interrupts(self):
+        # 1 cycle
+        self.ime = True
+        self.execute(self.fetch()) #  1
+        self.handle_pending_interrupts()
+
+    def halt(self):
+        # HALT/STOP
+        self.halted = True
+        # emulate bug when interrupts are pending
+        if not self.ime and self.interrupt.is_pending():
+            self.execute(self.memory.read(self.pc.get()))
+        self.handle_pending_interrupts()
+
+    def stop(self):
+        # 0 cycles
+        self.cycles += 1
+        self.fetch()
+
+# ------------------------------------------------------------------------------
+
+class CallWrapper(object):   
+    
+    def get(self, use_cycles=True):
+        raise Exception("called CallWrapper.get")
+        return 0
+    
+    def set(self, value, use_cycles=True):
+        raise Exception("called CallWrapper.set")
+        pass
+    
+class NumberCallWrapper(CallWrapper):
+    
+    def __init__(self, number):
+        self.number = number
+    
+    def get(self, use_cycles=True):
+        return self.number
+    
+    def set(self, value, use_cycles=True):
+        raise Exception("called CallWrapper.set")
+        pass
+        
+class RegisterCallWrapper(CallWrapper): 
+    def __init__(self, register):
+        self.register = register
+        
+    def get(self,  use_cycles=True):
+        return self.register.get(use_cycles)
+    
+    def set(self, value, use_cycles=True):
+        return self.register.set(value, use_cycles)
+
+
+class DoubleRegisterCallWrapper(CallWrapper):
+    def __init__(self, register):
+        self.register = register
+        
+    def get(self,  use_cycles=True):
+        return self.register.get(use_cycles)
+    
+    def set(self, value, use_cycles=True):
+        return self.register.set(value, use_cycles) 
+    
+    
+class CPUPopCaller(CallWrapper):
+    def __init__(self, cpu):
+        self.cpu = cpu
+        
+    def get(self,  use_cycles=True):
+        return self.cpu.pop(use_cycles)
+    
+    
+class CPUFetchCaller(CallWrapper):
+    def __init__(self, cpu):
+        self.cpu = cpu
+        
+    def get(self,  use_cycles=True):
+        return self.cpu.fetch(use_cycles)
+
+# op_code LOOKUP TABLE GENERATION -----------------------------------------------
+
+GROUPED_REGISTERS = [CPU.get_b, CPU.get_c, CPU.get_d,   CPU.get_e,
+                     CPU.get_h, CPU.get_l, CPU.get_hli, CPU.get_a]
+
+def create_group_op_codes(table):
+    op_codes =[]
+    for entry in table:
+        op_code   = entry[0]
+        step     = entry[1]
+        function = entry[2]
+        if len(entry) == 4:
+            for registerGetter in GROUPED_REGISTERS:
+                for n in entry[3]:
+                    op_codes.append((op_code, group_lambda(function, registerGetter, n)))
+                    op_code += step
+        if len(entry) == 5:
+            entryStep = entry[4]
+            for registerGetter in GROUPED_REGISTERS:
+                stepop_code = op_code
+                for n in entry[3]:
+                    op_codes.append((stepop_code, group_lambda(function, registerGetter, n)))
+                    stepop_code += entryStep
+                op_code+=step
+        else:
+            for registerGetter in GROUPED_REGISTERS:
+                op_codes.append((op_code,group_lambda(function, registerGetter)))
+                op_code += step
+    return op_codes
+
+def group_lambda(function, register_getter, value=None):
+    if value is None:
+        return lambda s: function(s, RegisterCallWrapper(register_getter(s)), 
+                               RegisterCallWrapper(register_getter(s)))
+    else:
+        return lambda s: function(s, RegisterCallWrapper(register_getter(s)), 
+                               RegisterCallWrapper(register_getter(s)), value)
+    
+def create_load_group_op_codes():
+    op_codes = []
+    op_code  = 0x40
+    for storeRegister in GROUPED_REGISTERS:
+        for loadRegister in GROUPED_REGISTERS:
+            if loadRegister != CPU.get_hli or storeRegister != CPU.get_hli:
+                op_codes.append((op_code, load_group_lambda(storeRegister, loadRegister)))
+            op_code += 1
+    return op_codes
+            
+def load_group_lambda(store_register, load_register):
+        return lambda s: CPU.ld(s, RegisterCallWrapper(load_register(s)),
+                                   RegisterCallWrapper(store_register(s)))
+    
+def create_register_op_codes(table):
+    op_codes = []
+    for entry in table:
+        op_code   = entry[0]
+        step     = entry[1]
+        function = entry[2]
+        for registerOrGetter in entry[3]:
+            op_codes.append((op_code, register_lambda(function, registerOrGetter)))
+            op_code += step
+    return op_codes
+
+def register_lambda(function, registerOrGetter):
+    if callable(registerOrGetter):
+        return lambda s: function(s, registerOrGetter(s))
+    else:
+        return lambda s: function(s, registerOrGetter)
+        
+        
+def initialize_op_code_table(table):
+    result = [None] * (0xFF+1)
+    for entry in  table:
+        if (entry is None) or (len(entry) == 0) or entry[-1] is None:
+            continue
+        if len(entry) == 2:
+            positions = [entry[0]]
+        else:
+            positions = range(entry[0], entry[1]+1)
+        for pos in positions:
+            result[pos] = entry[-1]
+    return result
+
+# op_code TABLES ---------------------------------------------------------------
+# Table with one to one mapping of simple OP Codes                
+FIRST_ORDER_OP_CODES = [
+    (0x00, CPU.nop),
+    (0x08, CPU.load_mem_sp),
+    (0x10, CPU.stop),
+    (0x18, CPU.relative_jump),
+    (0x02, CPU.write_a_at_bc_address),
+    (0x12, CPU.write_a_at_de_address),
+    (0x22, CPU.load_and_increment_hli_a),
+    (0x32, CPU.load_and_decrement_hli_a),
+    (0x0A, CPU.store_memory_at_bc_in_a),
+    (0x1A, CPU.store_memory_at_de_in_a),
+    (0x2A, CPU.load_and_increment_a_hli),
+    (0x3A, CPU.load_and_decrement_a_hli),
+    (0x07, CPU.rotate_left_circular_a),
+    (0x0F, CPU.rotate_right_circular_a),
+    (0x17, CPU.rotate_left_a),
+    (0x1F, CPU.rotate_right_a),
+    (0x27, CPU.decimal_adjust_a),
+    (0x2F, CPU.complement_a),
+    (0x37, CPU.set_carry_flag),
+    (0x3F, CPU.complement_carry_flag),
+    (0x76, CPU.halt),
+    (0xF3, CPU.disable_interrups),
+    (0xFB, CPU.enable_interrupts),
+    (0xE2, CPU.write_a_at_expaded_c_address),
+    (0xEA, CPU.store_a_at_fetched_address),
+    (0xF2, CPU.store_expanded_c_in_a),
+    (0xFA, CPU.store_fetched_memory_in_a),
+    (0xC3, CPU.jump),
+    (0xC9, CPU.ret),
+    (0xD9, CPU.return_form_interrupt),
+    (0xDD, CPU.debug),
+    (0xE9, CPU.store_hl_in_pc),
+    (0xF9, CPU.store_hl_in_sp),
+    (0xE0, CPU.write_a_at_expanded_fetch_address),
+    (0xE8, CPU.increment_sp_by_fetch),
+    (0xF0, CPU.store_memory_at_axpanded_fetch_address_in_a),
+    (0xF8, CPU.store_fetch_added_sp_in_hl),
+    (0xCB, CPU.fetch_execute),
+    (0xCD, CPU.unconditional_call),
+    (0xC6, lambda s: CPU.add_a(s,                 CPUFetchCaller(s))),
+    (0xCE, lambda s: CPU.add_a_with_carry(s,      CPUFetchCaller(s))),
+    (0xD6, CPU.fetch_subtract_a),
+    (0xDE, lambda s: CPU.subtract_with_carry_a(s, CPUFetchCaller(s))),
+    (0xE6, lambda s: CPU.and_a(s,                 CPUFetchCaller(s))),
+    (0xEE, lambda s: CPU.xor_a(s,                 CPUFetchCaller(s))),
+    (0xF6, lambda s: CPU.or_a(s,                  CPUFetchCaller(s))),
+    (0xFE, lambda s: CPU.compare_a(s,             CPUFetchCaller(s))),
+    (0xC7, lambda s: CPU.restart(s, 0x00)),
+    (0xCF, lambda s: CPU.restart(s, 0x08)),
+    (0xD7, lambda s: CPU.restart(s, 0x10)),
+    (0xDF, lambda s: CPU.restart(s, 0x18)),
+    (0xE7, lambda s: CPU.restart(s, 0x20)),
+    (0xEF, lambda s: CPU.restart(s, 0x28)),
+    (0xF7, lambda s: CPU.restart(s, 0x30)),
+    (0xFF, lambda s: CPU.restart(s, 0x38))
+]
+
+# Table for RegisterGroup OP Codes: (startAddress, delta, method)
+REGISTER_GROUP_OP_CODES = [
+    (0x04, 0x08, CPU.inc),
+    (0x05, 0x08, CPU.dec),    
+    (0x06, 0x08, CPU.load_fetch_register),
+    (0x80, 0x01, CPU.add_a),    
+    (0x88, 0x01, CPU.add_a_with_carry),    
+    (0x90, 0x01, CPU.subtract_a),    
+    (0x98, 0x01, CPU.subtract_with_carry_a),    
+    (0xA0, 0x01, CPU.and_a),    
+    (0xA8, 0x01, CPU.xor_a),    
+    (0xB0, 0x01, CPU.or_a),
+    (0xB8, 0x01, CPU.compare_a),
+    (0x06, 0x08, CPU.fetch_load)
+]    
+        
+
+REGISTER_SET_A    = [CPU.get_bc,   CPU.get_de, CPU.get_hl,   CPU.get_sp]
+REGISTER_SET_B    = [CPU.get_bc,   CPU.get_de, CPU.get_hl,   CPU.get_af]
+FLAG_REGISTER_SET = [CPU.is_not_z, CPU.is_z,   CPU.is_not_c, CPU.is_c]
+
+# Table for Register OP Codes: (startAddress, delta, method, registers)
+REGISTER_OP_CODES = [ 
+    (0x01, 0x10, CPU.fetch_double_register,     REGISTER_SET_A),
+    (0x09, 0x10, CPU.add_hl,                    REGISTER_SET_A),
+    (0x03, 0x10, CPU.inc_double_register,       REGISTER_SET_A),
+    (0x0B, 0x10, CPU.dec_double_register,       REGISTER_SET_A),
+    (0xC0, 0x08, CPU.conditional_return,        FLAG_REGISTER_SET),
+    (0xC2, 0x08, CPU.conditional_jump,          FLAG_REGISTER_SET),
+    (0xC4, 0x08, CPU.conditional_call,          FLAG_REGISTER_SET),
+    (0x20, 0x08, CPU.relative_conditional_jump, FLAG_REGISTER_SET),
+    (0xC1, 0x10, CPU.pop_double_register,       REGISTER_SET_B),
+    (0xC5, 0x10, CPU.push_double_register,      REGISTER_SET_B)
+]
+# Table for Second Order op_codes: (startAddress, delta, method, [args])
+SECOND_ORDER_REGISTER_GROUP_OP_CODES = [
+    (0x00, 0x01, CPU.rotate_left_circular),    
+    (0x08, 0x01, CPU.rotate_right_circular),    
+    (0x10, 0x01, CPU.rotate_left),    
+    (0x18, 0x01, CPU.rotate_right),    
+    (0x20, 0x01, CPU.shift_left_arithmetic),    
+    (0x28, 0x01, CPU.shift_right_arithmetic),    
+    (0x30, 0x01, CPU.swap),    
+    (0x38, 0x01, CPU.shift_word_right_logical),
+    (0x40, 0x01, CPU.test_bit,  range(0, 8), 0x08),    
+    (0xC0, 0x01, CPU.set_bit,   range(0, 8), 0x08),
+    (0x80, 0x01, CPU.reset_bit, range(0, 8), 0x08)         
+]
+
+# RAW op_code TABLE INITIALIZATION ----------------------------------------------
+
+FIRST_ORDER_OP_CODES  += create_register_op_codes(REGISTER_OP_CODES)
+FIRST_ORDER_OP_CODES  += create_group_op_codes(REGISTER_GROUP_OP_CODES)
+FIRST_ORDER_OP_CODES  += create_load_group_op_codes()
+SECOND_ORDER_OP_CODES  = create_group_op_codes(SECOND_ORDER_REGISTER_GROUP_OP_CODES)
+
+
+OP_CODES               = initialize_op_code_table(FIRST_ORDER_OP_CODES)
+FETCH_EXECUTE_OP_CODES = initialize_op_code_table(SECOND_ORDER_OP_CODES)
+

Modified: pypy/dist/pypy/lang/gameboy/gameboy_implementation.py
==============================================================================
--- pypy/dist/pypy/lang/gameboy/gameboy_implementation.py	(original)
+++ pypy/dist/pypy/lang/gameboy/gameboy_implementation.py	Tue Aug  5 10:24:39 2008
@@ -36,6 +36,8 @@
             while isRunning and self.handle_events():
                 self.emulate(constants.GAMEBOY_CLOCK >> 2)
                 #RSDL.Delay(1)
+        except Exception:
+            pass
         finally:
             self.handle_execution_error()
             lltype.free(self.event, flavor='raw')



More information about the Pypy-commit mailing list