User Tools

Site Tools


spo600:6502_math

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
spo600:6502_math [2024/01/23 15:10] – [6502 Math] chrisspo600:6502_math [2025/01/23 22:27] (current) – [Multiplication and Division] chris
Line 1: Line 1:
 ======  6502 Math  ====== ======  6502 Math  ======
  
-The 6502 processor is limited to very simple math operations, and various processor flags affect these operations.+The [[6502]] processor is limited to very simple math operations, and various [[spo600:6502#registers|processor flags]] affect these operations.
  
 ====  Decimal Mode  ==== ====  Decimal Mode  ====
Line 9: Line 9:
 In binary mode, operations are performed on a single 8-bit value. Numbers may be treated as signed or unsigned (the math is the same). In binary mode, operations are performed on a single 8-bit value. Numbers may be treated as signed or unsigned (the math is the same).
  
-In decimal mode, the each byte is treated as two decimal digits - the lower 4 bits represent the lower digit, and the upper 4 bits represent the upper digit. Numbers are counted as positive, and values greater than 9 are invalid.+In decimal mode, the each byte is treated as two decimal digits - the lower 4 bits represent the lower digit, and the upper 4 bits represent the upper digit. Numbers are counted as positive, and digit values greater than 9 are invalid.
  
 Decimal mode is selected by setting the D (Decimal) flag in the [[6502#Registers|Status Register]] using the ''SED'' instruction, and binary mode is selected by clearing the D flag using the ''CLD'' instruction. Decimal mode is selected by setting the D (Decimal) flag in the [[6502#Registers|Status Register]] using the ''SED'' instruction, and binary mode is selected by clearing the D flag using the ''CLD'' instruction.
  
-The rest of this page deals with binary mode (decimal mode operates in mostly the same way).+The rest of this page deals with binary mode (decimal mode operates in mostly the same way). Note that decimal mode is only applicable to ''ADC'' and ''SBC'' instructions, and may not set some processor flags in an expected way.
  
 ====  Addition  ==== ====  Addition  ====
Line 62: Line 62:
 ====  Rotate Right/Left  ==== ====  Rotate Right/Left  ====
  
-The Rotate Right and Rotate Left (ROR/ROL) instructions are like the LSR/ASL instructions, except that the Carry flag is rotated into one end of the byte, and the bit from the other end is rotated into the Carry flag. For example, ROR will shift C into the high bit and the low bit into C. Therefore, it is possible to perform a multi-byte rotate by stringing together ROR or ROL instructions.+The Rotate Right and Rotate Left (ROR/ROL) instructions are like the LSR/ASL instructions, except that the Carry flag is rotated into one end of the byte, and the bit from the other end is rotated into the Carry flag. For example, ROR will shift C into the high bit and the low bit into C. Therefore, it is possible to perform a multi-byte rotate by stringing together ASL or LSR instructions with ROR or ROL instructions
 + 
 +For example, to perform a 16-bit right shift: 
 + 
 +1. Perform LSR on the high byte. The lowest bit will be placed in the carry flag. 
 + 
 +2. Perform ROR on the low byte. The carry flag, containing the lowest bit from the high byte, will be shifted in to the highest bit of the low byte. 
 + 
 +The original version of the 6502 had a bug in the ROR instruction, so it was removed from the initial documentation. The chip was revised within the first few months and all later versions of the 6502 implement the ROR instruction correctly.
  
 ====  Bitwise Operations  ==== ====  Bitwise Operations  ====
Line 69: Line 77:
  
 <code> <code>
-  ROR  Rotate right - 9-bit rotate (one byte plus C flag) 
-  ROL  Rotate left - 9-bit rotate left (one byte plus C flag) 
-  ASL  Arithmetic shift left - bit 7 -> C flag, bits 0:6 -> 1:7, 0 -> bit 0 
-  LSR  Logical shift right - bit 0 -> C flag, bits 7:1 -> 6:0, 0 -> bit 7 
   EOR  Exclusive-OR (sometimes written XOR in other languages)   EOR  Exclusive-OR (sometimes written XOR in other languages)
-  ORA  OR (accumulator)+  ORA  OR (Accumulator)
   AND  AND</code>   AND  AND</code>
  
 A NOT operation can be performed using EOR with an immediate value of #$FF, and this can be combined with ORA and AND instructions to build NOR and NAND operations. A NOT operation can be performed using EOR with an immediate value of #$FF, and this can be combined with ORA and AND instructions to build NOR and NAND operations.
  
-The BIT instruction performs a bitwise AND, sets the Z flag based on the result, and transfers bits 6 and 7 of the operand into the N and V flags.+In addition, the BIT instruction performs a bitwise AND, sets the Z flag based on the result, and transfers bits 6 and 7 of the operand into the N and V flags.
  
 ====  Multiplication and Division  ==== ====  Multiplication and Division  ====
  
-There are no multiplication or division instructions on the 6502; it is up to the programmer to provide the appropriate logic.+There are no multiplication or division instructions on the 6502; it is up to the programmer to provide the appropriate logic. Typical implementations use a combination of shifts and adds; for example, to multiply by 12, the original value shifted left three times (x8) can be added to the original value shifted left two times (x4). 
 + 
 +Here is a simple example subroutine which multiplies two 8-bit values, producing a 16-bit product as the result (this code can be tested on the [[6502 Emulator]]): 
 + 
 +<code>; multiply_8x8bit.6502 
 +
 +; Example of 8-bit x 8-bit multiply with 
 +; 16-bit result on a 6502 
 +;  
 +; This code uses shift-and-add 
 +
 +; Chris Tyler 2025-01-23 for the SPO600 course 
 +
 +; Copyright (C)2025 Seneca Polytechnic 
 +; Licensed under the terms of the GPLv2+ 
 +; See the file LICENSE for details 
 + 
 +; ######### MACRO DEFINITIONS 
 +; === ZERO-PAGE MEMORY LOCATIONS 
 + 
 +; INPUT PARAMETERS AND RESULT 
 +define M1       $10   ; MULTIPLICAND 1 
 + 
 +define M2       $11   ; MULTIPLICAND 2 
 + 
 +define RESULT   $12   ; RESULT 
 +define RESULT_L $12 
 +define RESULT_H $13 
 + 
 +; TEMPORARY COPIES OF M1, M2 
 +define T1       $20  ; 8 BIT VALUE 
 + 
 +define T2       $21  ; 16 BIT (FOR SHIFTING) 
 +define T2_L     $21 
 +define T2_H     $22 
 + 
 +; ######### TEST CODE 
 + 
 +; NOTE: THE NEXT TWO OPERANDS ARE IN DECIMAL! 
 +;       THIS IS DUE TO THE LACK OF $ 
 + 
 +  LDA #7      ; FIRST MULTIPLICAND 
 +  STA M1 
 + 
 +  LDA #9       ; SECOND MULTIPLICAND 
 +  STA M2 
 + 
 +  JSR MULTIPLY ; MULTIPLY THE VALUES 
 + 
 +  BRK          ; SEE 16 BIT RESULT AT 'RESULT' 
 + 
 +; ######### MULTIPLY SUBROUTINE 
 +; MULTIPLY THE CONTENTS OF M1 BY THE CONTENTS 
 +; OF M2 AND STORE THE RESULT IN 'RESULT' 
 +;  
 +; Operation: 
 +; 0. Multiplicand M1 is copied to temporary 
 +;    variable T1. Multiplicand M2 is copied to 
 +;    the 16-bit temporary variable T2. The 
 +;    RESULT is zeroed out. 
 +; 1. If either multiplicand is zero, the  
 +;    product is zero, so the routine returns 
 +;    immediately with RESULT=0. 
 +; 2. T1 is shifted right. If the bit shifted 
 +;    out (formerly bit 0) is a '1', then the  
 +;    value of T2 is added to the RESULT. 
 +; 4. If T1 is zero after the shift, the 
 +;    multiplication is complete and the routine 
 +;    returns. 
 +; 5. T2 is rotated left (multiplied by 2). 
 +; 6. Processing continues at step 2. 
 + 
 +MULTIPLY: 
 +  LDA #$00      ; ZERO OUT THE RESULT AND Tn_H 
 +  STA RESULT_L 
 +  STA RESULT_H 
 +  STA T2_H 
 + 
 +  LDA M1         ; COPY M1 TO T1 
 +  BEQ MULT_DONE  ; RESULT=0 IF M1==0 
 +  STA T1 
 + 
 +  LDA M2         ; COPY M2 TO T2 
 +  BEQ MULT_DONE  ; RESULT=0 IF M2==0 
 +  STA T2_L 
 + 
 +  JMP MULT_FIRST 
 + 
 +MULT_NEXT:   
 +  ASL T2_L       ; SHIFT T2 LEFT 
 +  ROL T2_H 
 + 
 +MULT_FIRST: 
 +  LSR T1         ; SHIFT T1 RIGHT 
 +  BEQ MULT_LAST  ; DO LAST BIT IF T1==0 
 +  BCC MULT_NEXT  ; IF BIT0 WAS 0, DO NEXT 
 + 
 +  LDA T2_L       ; IF BIT0 WAS 1: 
 +  CLC            ; T2 + RESULT-> RESULT 
 +  ADC RESULT_L 
 +  STA RESULT_L 
 +  LDA T2_H 
 +  ADC RESULT_H 
 +  STA RESULT_H 
 +  JMP MULT_NEXT 
 + 
 +MULT_LAST:       ; CODE IS REDUNDANT TO THE 
 +  LDA T2_L       ; PRECEEDING BLOCK, BUT  
 +  CLC            ; WE'VE AVOIDED A SECOND 
 +  ADC RESULT_L   ; COMPARISON OF T1 WITH #0 
 +  STA RESULT_L   ; THEREBY SAVING 6-7 CYCLES 
 +  LDA T2_H       ; PER LOOP ITERATION OR  
 +  ADC RESULT_H   ; 6-56 CYCLES TOTAL, AT A 
 +  STA RESULT_H   ; COST OF 13 ADDITIONAL BYTES 
 + 
 +MULT_DONE: 
 +  RTS 
 +</code>
  
 +This code is available in the [[spo600:6502_emulator_example_code#additional_examples|example repository]].
spo600/6502_math.1706022625.txt.gz · Last modified: 2024/04/16 18:10 (external edit)

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki