Main Menu

Z80 op-codes

Started by baggey, November 10, 2012, 12:05:31 PM

Previous topic - Next topic

baggey

#15
Well here's to my latest efforts i nearly have the first 255 op-codes ::)

Somethings going wrong here? My oo_codes are being displayed in playbasic IDE but not when i load them  ???

Right got it sorted  :P
Jesus was only famous because of his dad

kevin

#16
 Just picking through it, so some tips would...

   * When adding / increasing or decreasing a register, you'll need to mask the result so it falls within the 8bit or 16bit boundary.  
   * Use Boolean expressions for setting flags
   * If flags haven't change, don't include them.

 
 For example,
PlayBASIC Code: [Select]
op_4:  // INC B

nxtpc=1

if monitormode=true
if hex_or_dec = false
// Decimal representation
text progpos,placeopcodeslne,digits$(pc,5)
text progpos+70,placeopcodeslne,digits$(op_byte,3)
text progpos+270,placeopcodeslne,"INC B"
else
// Hex representation
text progpos,placeopcodeslne,right$(hex$(pc),4)
text progpos+70,placeopcodeslne,right$(hex$(op_byte),2)
text progpos+270,placeopcodeslne,"INC B"
endif
endif

if execute=true

regb++
regr++
if regb=0
fz=1
else
fz=0
endif

fh=(regb and 8)

if regb=127
fpv=1
else
fpv=0
endif

fs = fs ; S is set if result is negative; reset otherwise
fz = fz ; Z is set if result is zero; reset otherwise
fy = fy ; Unkown
fh = fh ; H is set if carry from bit3; reset otherwise
fx = fx ; Unkown
fp = fp ; P/V is set if b=127 before operation; reset otherwise
fn = 0 ; N is reset
fc = fc ; C is not affected

endif
exeTstates = 4
return ; DONE





 could be better expressed as

PlayBASIC Code: [Select]
op_4:  // INC B

nxtpc=1


; monitormode flag is a boolean (On or OFF), you can ditch the =TRUE
if monitormode
if hex_or_dec = false
// Decimal representation
text progpos,placeopcodeslne,digits$(pc,5)
text progpos+70,placeopcodeslne,digits$(op_byte,3)
text progpos+270,placeopcodeslne,"INC B"
else
// Hex representation
text progpos,placeopcodeslne,right$(hex$(pc),4)
text progpos+70,placeopcodeslne,right$(hex$(op_byte),2)
text progpos+270,placeopcodeslne,"INC B"
endif
endif

; execute flag is a boolean (On or OFF), you can ditch the =TRUE

if execute

;regb++

; 8bit version
regb=(regb+1) and 255 ; assuming it's 8bit.

; 16bit version
regb=(regb+1) and $ffff ; if it's 16bit,

;regr++
same for here for whatever this is.

;if regb=0
;fz=1
;else
;fz=0
;endif

; this is at least 2 instructions less than the above.
fz=regb=0

fh=(regb and 8)

;if regb=127
; fpv=1
;else
; fpv=0
;endif

pbv=(regb=127)


;fs = fs ; S is set if result is negative; reset otherwise
;fz = fz ; Z is set if result is zero; reset otherwise
;fy = fy ; Unkown
;fh = fh ; H is set if carry from bit3; reset otherwise
;fx = fx ; Unkown
;fp = fp ; P/V is set if b=127 before operation; reset otherwise
fn = 0 ; N is reset
;fc = fc ; C is not affected

endif

; if TState is the number of cycles per operation, then rather than set the value here, then add that value to the tally the main loop.
; just add the number cycles directly to the main tally, which is one operation less per instruction.
;exeTstates = 4

TotalCycles+=4


return ; DONE







baggey

#17
Cheer's

Started implementing these changes! Should, without a doubt speed things up!  ;)

Didn't realise this:-

PlayBASIC Code: [Select]
totalcycles=totalcycles+4




Could be this,

PlayBASIC Code: [Select]
totalcycles+=4

; So we could also have

totalcycles-=4

; Ive also changed this
totalclockcycles=totalclockcycles+redstates

; To this
totalclockcycles+=redtstate



Would this improve speed all over the maim emulation loop? I think it would do.

Also are there any other's?

CHECKING NEGATIVES !?

Ive realised ive missed Flag fs. In two's complement the bit7 is set for negative but in Dec its less than zero? How its represented i don't know!

But,

I assume i could use.  Fs=(regb and 127)

or try

Fs=(regb>127)

What do you think?

Right the first five op-codes look like this now!

PlayBASIC Code: [Select]
op_0:  // NOP

nxtpc=1

if monitormode

if hex_or_dec = false
// Decimal representation
text progpos,placeopcodeslne,digits$(pc,5)
text progpos+70,placeopcodeslne,digits$(op_byte,3)
text progpos+270,placeopcodeslne,"NOP"
else
// Hex representation
text progpos,placeopcodeslne,right$(hex$(pc),4)
text progpos+70,placeopcodeslne,right$(hex$(op_byte),2)
text progpos+270,placeopcodeslne,"NOP"
endif
endif

// Do nothing!

if execute

; This is an internal register to the Z80 CPU increased every ins.
regr++

; no flags affected
;fs = fs
;fz = fz
;fy = fy
;fh = fh
;fx = fx
;fp = fp
;fn = fn
;fc = fc

totalclockcycles+= 4
endif
return ; DONE Baggey


op_1: // LD BC,nn

nxtpc=3

if monitormode
address=pcptr+pc
lsb=peekbyte(pcptr+pc+1)
msb=peekbyte(pcptr+pc+2)
num=msb*256+lsb

if hex_or_dec = false
// Decimal representation
text progpos,placeopcodeslne,digits$(pc,5)
text progpos+70,placeopcodeslne,digits$(op_byte,3)
text progpos+120,placeopcodeslne,digits$(lsb,3)
text progpos+170,placeopcodeslne,digits$(msb,3)
text progpos+270,placeopcodeslne,"LD BC , "+digits$(num,5)
else
// Hex representation
text progpos,placeopcodeslne,right$(hex$(pc),4)
text progpos+70,placeopcodeslne,right$(hex$(op_byte),2)
text progpos+120,placeopcodeslne,right$(hex$(lsb),2)
text progpos+170,placeopcodeslne,right$(hex$(msb),2)
text progpos+270,placeopcodeslne,"LD BC , "+right$(hex$(num),4)
endif
endif

if execute

lsb=peekbyte(savepc+1)
msb=peekbyte(savepc+2)
regc=lsb
regb=msb
regbc=msb*256+lsb

; This is an internal register to the Z80 CPU increased every ins.
regr++

; no flags affected
;fs = fs
;fz = fz
;fy = fy ; Not used
;fh = fh
;fx = fx ; Not used
;fp = fp
;fn = fn
;fc = fc

totalclockcycles+= 10
endif
return ; DONE


op_2: // LD (BC),A

nxt_pc=1

if monitormode

if hex_or_dec = false
// Decimal representation
text progpos,placeopcodeslne,digits$(pc,5)
text progpos+70,placeopcodeslne,digits$(op_byte,3)
text progpos+120,placeopcodeslne,"LD ( BC ) , A"+digits$(num,5)
else
// Hex representation
text progpos,placeopcodeslne,right$(hex$(pc),4)
text progpos+70,placeopcodeslne,right$(hex$(op_byte),2)
text progpos+120,placeopcodeslne,"LD ( BC ) , A"+right$(hex$(num),4)
endif
endif

if execute
; memorybank positon bc will be loaded with the value of a
; we could have array postion (b*256)+c = a but i think banks are needed for speed
;rega=(regb*256)+regc ; a will loaded in to memory location poke bc,a
lsb=peekbyte(savepc+1)
pokebyte lsb,rega

; This is an internal register to the Z80 CPU increased every ins.
regr++

; no flags affected
;fs = fs
;fz = fz
;fy = fy
;fh = fh
;fx = fx
;fp = fp
;fn = fn
;fc = fc

endif
totalclockcycles+= 7
return ;done


op_3: // INC BC

nxt_pc=1

if monitormode

if hex_or_dec = false
// Decimal representation
text progpos,placeopcodeslne,digits$(pc,5)
text progpos+70,placeopcodeslne,digits$(op_byte,3)
text progpos+270,placeopcodeslne,"INC BC"
Login required to view complete source code


Nice and easy to read and understand as well  ;D


Also just noticed i need to add tempregb=regb AS it needs to be checkced before any operation is done!
Ending up like so:-

PlayBASIC Code: [Select]
op_4:  // INC B

nxtpc=1

if monitormode

if hex_or_dec = false
// Decimal representation
text progpos,placeopcodeslne,digits$(pc,5)
text progpos+70,placeopcodeslne,digits$(op_byte,3)
text progpos+270,placeopcodeslne,"INC B"
else
// Hex representation
text progpos,placeopcodeslne,right$(hex$(pc),4)
text progpos+70,placeopcodeslne,right$(hex$(op_byte),2)
text progpos+270,placeopcodeslne,"INC B"
endif
endif

if execute

tempregb=regb
; 8bit version
regb=(regb+1) and 255

; This is an internal register to the Z80 CPU increased every ins.
regr++

fs=(regb>127) ; S is set if result is negative; reset otherwise
fz=regb=0 ; Z is set if result is zero; reset otherwise
;fy = fy ; Unkown
fh=(regb and 8) ; H is set if carry from bit3; reset otherwise
;fx = fx ; Unkown
fp=(tempregb=127) ; P/V is set if b=127 before operation; reset otherwise
fn = 0 ; N is reset
;fc = fc ; C is not affected

endif
totalclockcycles+= 4
return ; DONE



Baggey
Jesus was only famous because of his dad

baggey

Here's how the cb_opcodes are coming on  :o

Kind regards Baggey
Jesus was only famous because of his dad

kevin


  Only flicked through it and there seems to be some redundant AND 255 laced through it.     

  If you AND a variable with an 8bit value, then the result can only be 8bit so there's no need to mask the result.

  so in code like this..

  B= (A and 16) and 255

  can be expressed as this,
   
  B= (A and 16)

  the AND will clear every bit in the result that's not 1, so it doesn't even matter with A is 16bit value or higher..




baggey

#20
Quote from: kevin on December 14, 2012, 09:18:57 AM

 Only flicked through it and there seems to be some redundant AND 255 laced through it.    

 If you AND a variable with an 8bit value, then the result can only be 8bit so there's no need to mask the result.

 so in code like this..

 B= (A and 16) and 255

 can be expressed as this,
 
 B= (A and 16)

 the AND will clear every bit in the result that's not 1, so it doesn't even matter with A is 16bit value or higher..





Hi Kevin,

I feel a Homer Simpson moment coming on here "DOPE"!

I Know your going to laugh! How can i tell when its 8bit, 16bit or 32bit?

I thought if i declare. Lets say b=254 its got to be 8bit or if i declare b=256 it would have to be 16bit!

Sorry if this sounds so stupid to you but. I thought that some of the commands where going through all 32bits wether we needed them to or not?
Thats why ive been anding with 255.

I was trying to be clever over something i didn't really get in the first place!

However thankyou for the Tips!

Baggey
Jesus was only famous because of his dad

kevin

#21
Quote
Sorry if this sounds so stupid to you but. I thought that some of the commands where going through all 32bits wether we needed them to or not?
Thats why ive been anding with 255.

 PB is 32bit, every operation is 32bit.  

 My point is if your emulating a CPU register called Wobble say (in some pretend cpu),  then obviously you'd  already know the size of this register up front.    If Wobble is 8bit, then care needs to taken in the emulation to ensure that calculation doesn't overflow it's 8bit bounds.  
 
 Then if you're emulating an move opcode that's moving between two registers of the same bits, then you don't need to mask anything.    They'll always be within legal range.   But what if you were moving a 16bit register to an 8bit register ?     Then clearly the 16bit value would need to have the high 8 bits masked off.


  8BitRegister = 16BitRegister and 255