GE-115 Emulator
An Emulator of the General Electrics GE-115 computer
Functions
alu_dec.c File Reference

GE-130 packed/signed decimal ALU helpers. More...

#include "alu_dec.h"
#include <string.h>

Go to the source code of this file.

Functions

static int dec_sign_is_neg (uint8_t sign_nibble)
 Returns 1 if the sign nibble represents a negative value.
 
static uint8_t dec_get_digit (const uint8_t *mem, uint16_t packed_addr, int packed_bytes, int digit_idx)
 Extract a single decimal digit from a packed field.
 
static void dec_set_digit (uint8_t *mem, uint16_t packed_addr, int packed_bytes, int digit_idx, uint8_t digit)
 Set a single digit in a packed field (same indexing as dec_get_digit).
 
static uint8_t dec_get_sign (const uint8_t *mem, uint16_t packed_addr)
 Get the sign nibble of a packed field.
 
static void dec_set_sign (uint8_t *mem, uint16_t packed_addr, uint8_t sign)
 Set the sign nibble of a packed field.
 
static void dec_zero_digits (uint8_t *mem, uint16_t packed_addr, int packed_bytes)
 Clear all digits (not sign) in a packed field to zero.
 
static uint8_t dec_result_cc (int is_zero, uint8_t result_sign)
 Compute the CC value from a sign and whether the result is zero.
 
static int bcd_add_digits (uint8_t *result, const uint8_t *a, const uint8_t *b, int n_digits)
 BCD add two digit arrays (right-to-left, big-endian [0]=rightmost).
 
static int bcd_sub_digits (uint8_t *result, const uint8_t *a, const uint8_t *b, int n_digits)
 BCD subtract b from a (right-to-left).
 
static int bcd_cmp_digits (const uint8_t *a, const uint8_t *b, int n_digits)
 Compare two unsigned BCD digit arrays (big-endian: [n-1]=most-significant).
 
static int bcd_is_zero (const uint8_t *d, int n)
 Returns 1 if digit array is all zeros.
 
static void dec_read_digits (const uint8_t *mem, uint16_t packed_addr, int packed_bytes, uint8_t *digits, int n_digits)
 Read a packed field into a digit array (right-to-left, [0]=rightmost digit).
 
static void dec_write_digits (uint8_t *mem, uint16_t packed_addr, int packed_bytes, const uint8_t *digits, int n_digits)
 Write a digit array back into a packed field.
 
void alu_ap (struct ge *ge, uint16_t a, uint8_t alen, uint16_t b, uint8_t blen)
 AP 0xEA Add Packed: op1 = op1 + op2; CC set.
 
void alu_sp (struct ge *ge, uint16_t a, uint8_t alen, uint16_t b, uint8_t blen)
 SP 0xEB Subtract Packed: op1 = op1 - op2; CC set.
 
void alu_mp (struct ge *ge, uint16_t a, uint8_t alen, uint16_t b, uint8_t blen)
 MP 0xEC Multiply Packed: op1 = op1 * op2; CC set.
 
void alu_dp (struct ge *ge, uint16_t a, uint8_t alen, uint16_t b, uint8_t blen)
 DP 0xED Divide Packed: op1[left L1-L2 chars] = quotient, op1[right L2+1 chars] = remainder; CC set.
 
void alu_cmp (struct ge *ge, uint16_t a, uint8_t alen, uint16_t b, uint8_t blen)
 CMP 0xE9 Compare Packed (algebraic, no operand change); CC set.
 
void alu_mvp (struct ge *ge, uint16_t a, uint8_t alen, uint16_t b, uint8_t blen)
 MVP 0xE8 Move Packed: op1 = op2 (sign preserved from op2); CC set.
 
void alu_pk (struct ge *ge, uint16_t dst, uint8_t dlen, uint16_t src, uint8_t slen)
 PK 0xDA Pack: zoned op2 → packed op1 (no sign processing).
 
void alu_upk (struct ge *ge, uint16_t dst, uint8_t dlen, uint16_t src, uint8_t slen)
 UPK 0xD8 Unpack: packed op2 → zoned op1 (no sign processing; zone of each result byte is taken from the pre-existing zone in ge->mem).
 
void alu_pks (struct ge *ge, uint16_t dst, uint8_t dlen, uint16_t src, uint8_t slen)
 PKS 0xEE Pack with Sign: zoned op2 → packed op1; sign from zone of rightmost source byte (zone 0xA → negative, else positive).
 
void alu_upks (struct ge *ge, uint16_t dst, uint8_t dlen, uint16_t src, uint8_t slen)
 UPKS 0xEF Unpack with Sign: packed op2 → zoned op1; zone always 0x4.
 
void alu_edt (struct ge *ge, uint16_t pattern, uint8_t plen, uint16_t src)
 EDT 0xDE Edit packed source into pattern at op1.
 

Detailed Description

GE-130 packed/signed decimal ALU helpers.

Manual source: GE 130 P.D.S. (cpu_6.txt), specifically: §2.3.5 (packed operand format, sign codes, ~lines 3148-3169) §5.5.3.4 PK, §5.5.3.5 UPK, §5.5.3.6 EDT §5.6.1.1 AP, §5.6.1.2 SP, §5.6.1.3 MP, §5.6.1.4 DP §5.6.1.5 MVP, §5.6.1.6 CMP §5.6.2.1 PKS, §5.6.2.2 UPKS

OPERAND ADDRESSING CONVENTION Every function receives the address of the RIGHTMOST (highest-address, least-significant) byte. Length L means L+1 bytes = 2L+1 digits + sign. Processing goes right-to-left (rightmost byte first) exactly as the manual prescribes.

SIGN CODES (§2.3.5) 0xB or 0xD in low nibble of rightmost byte → negative anything else → positive Results always written as 0xC (+) or 0xD (-)

CONDITION CODE (§5.6.1, FA04/FA05) CC=0 overflow CC=1 result < 0 CC=2 result = 0 CC=3 result > 0

UNCERTAINTY NOTES MP / DP: The manual describes high-level constraints and the overflow rules. The digit-level multiplication/division algorithm is implemented here using standard BCD multi-precision arithmetic as described in §7 of the manual (DETAILED DESCRIPTION OF MP AND DP SEQUENCES) — that section is only in outline form in the available OCR. The implementation follows S/360-style packed-decimal semantics which are consistent with the GE-130 constraints given. Mark any MP/DP test results as "best-effort; verify against hardware traces." UPK: Manual says the zone of the result bytes is taken from the "pre-existing zone" in the destination field. This implementation preserves the high nibble of destination bytes. UPKS always uses zone 0x4 (confirmed in §5.6.2.2). EDT: Control char values SST=0x20, TSZ=0x21, RSZ=0x22 are verified in §5.5.3.6 ("code 00100000", "00100001", "00100010"). CC encoding follows §5.5.3.6 table (10=zero-suppress still active, 11=zero-suppress off).

Definition in file alu_dec.c.

Function Documentation

◆ alu_ap()

void alu_ap ( struct ge ge,
uint16_t  a,
uint8_t  alen,
uint16_t  b,
uint8_t  blen 
)

AP 0xEA Add Packed: op1 = op1 + op2; CC set.

Definition at line 253 of file alu_dec.c.

◆ alu_cmp()

void alu_cmp ( struct ge ge,
uint16_t  a,
uint8_t  alen,
uint16_t  b,
uint8_t  blen 
)

CMP 0xE9 Compare Packed (algebraic, no operand change); CC set.

Overflow if L1 < L2.

Definition at line 559 of file alu_dec.c.

◆ alu_dp()

void alu_dp ( struct ge ge,
uint16_t  a,
uint8_t  alen,
uint16_t  b,
uint8_t  blen 
)

DP 0xED Divide Packed: op1[left L1-L2 chars] = quotient, op1[right L2+1 chars] = remainder; CC set.

Overflow if: L1 <= L2, L2 > 7, divisor == 0, or result doesn't fit. On overflow, operation is NOT performed.

Definition at line 459 of file alu_dec.c.

◆ alu_edt()

void alu_edt ( struct ge ge,
uint16_t  pattern,
uint8_t  plen,
uint16_t  src 
)

EDT 0xDE Edit packed source into pattern at op1.

pattern: address of leftmost byte of pattern; plen = pattern length (bytes). src: address of RIGHTMOST byte of packed source field. Pattern control chars: 0x20 = SST (digit substitute + zero suppress), 0x21 = TSZ (digit substitute, ends zero suppress), 0x22 = RSZ (reset zero suppress start), other = insertion char (kept as-is). First byte of pattern is the fill character. CC: 1 0 = zero suppression still active (result = 0); 1 1 = active off. (manual §5.5.3.6 / §5.5.3.7 CC table; note "not possible" for 0/1.)

Definition at line 868 of file alu_dec.c.

◆ alu_mp()

void alu_mp ( struct ge ge,
uint16_t  a,
uint8_t  alen,
uint16_t  b,
uint8_t  blen 
)

MP 0xEC Multiply Packed: op1 = op1 * op2; CC set.

Constraints: blen <= 8, blen < alen; op1 must have ≥blen+1 leading zero digits; otherwise overflow (CC=0, operation not performed).

Definition at line 358 of file alu_dec.c.

◆ alu_mvp()

void alu_mvp ( struct ge ge,
uint16_t  a,
uint8_t  alen,
uint16_t  b,
uint8_t  blen 
)

MVP 0xE8 Move Packed: op1 = op2 (sign preserved from op2); CC set.

Definition at line 614 of file alu_dec.c.

◆ alu_pk()

void alu_pk ( struct ge ge,
uint16_t  dst,
uint8_t  dlen,
uint16_t  src,
uint8_t  slen 
)

PK 0xDA Pack: zoned op2 → packed op1 (no sign processing).

Definition at line 682 of file alu_dec.c.

◆ alu_pks()

void alu_pks ( struct ge ge,
uint16_t  dst,
uint8_t  dlen,
uint16_t  src,
uint8_t  slen 
)

PKS 0xEE Pack with Sign: zoned op2 → packed op1; sign from zone of rightmost source byte (zone 0xA → negative, else positive).

CC set.

Definition at line 761 of file alu_dec.c.

◆ alu_sp()

void alu_sp ( struct ge ge,
uint16_t  a,
uint8_t  alen,
uint16_t  b,
uint8_t  blen 
)

SP 0xEB Subtract Packed: op1 = op1 - op2; CC set.

Definition at line 324 of file alu_dec.c.

◆ alu_upk()

void alu_upk ( struct ge ge,
uint16_t  dst,
uint8_t  dlen,
uint16_t  src,
uint8_t  slen 
)

UPK 0xD8 Unpack: packed op2 → zoned op1 (no sign processing; zone of each result byte is taken from the pre-existing zone in ge->mem).

Definition at line 728 of file alu_dec.c.

◆ alu_upks()

void alu_upks ( struct ge ge,
uint16_t  dst,
uint8_t  dlen,
uint16_t  src,
uint8_t  slen 
)

UPKS 0xEF Unpack with Sign: packed op2 → zoned op1; zone always 0x4.

CC set (reflects sign/value of packed source).

Definition at line 804 of file alu_dec.c.

◆ bcd_add_digits()

static int bcd_add_digits ( uint8_t *  result,
const uint8_t *  a,
const uint8_t *  b,
int  n_digits 
)
static

BCD add two digit arrays (right-to-left, big-endian [0]=rightmost).

a_digits / b_digits: arrays of decimal digits (0-9), length = n_digits. Returns carry out (0 or 1).

Definition at line 170 of file alu_dec.c.

◆ bcd_cmp_digits()

static int bcd_cmp_digits ( const uint8_t *  a,
const uint8_t *  b,
int  n_digits 
)
static

Compare two unsigned BCD digit arrays (big-endian: [n-1]=most-significant).

Returns >0 if a>b, 0 if equal, <0 if a<b.

Definition at line 207 of file alu_dec.c.

◆ bcd_is_zero()

static int bcd_is_zero ( const uint8_t *  d,
int  n 
)
static

Returns 1 if digit array is all zeros.

Definition at line 219 of file alu_dec.c.

◆ bcd_sub_digits()

static int bcd_sub_digits ( uint8_t *  result,
const uint8_t *  a,
const uint8_t *  b,
int  n_digits 
)
static

BCD subtract b from a (right-to-left).

Assumes a >= b (unsigned). Returns 0 (no borrow should remain if a >= b).

Definition at line 186 of file alu_dec.c.

◆ dec_get_digit()

static uint8_t dec_get_digit ( const uint8_t *  mem,
uint16_t  packed_addr,
int  packed_bytes,
int  digit_idx 
)
static

Extract a single decimal digit from a packed field.

packed_addr = address of rightmost byte of packed field packed_bytes = total byte count (len+1) digit_idx = 0 = rightmost (most-significant of last byte hi nibble), 1 = next right-to-left, ... sign is NOT a digit

Digit layout within bytes (right to left, byte = packed_addr - byte_offset): byte 0 (rightmost): high nibble = digit[0], low nibble = sign byte 1: high nibble = digit[1], low nibble = digit[2] byte k>0: high nibble = digit[2k-1], low nibble = digit[2k]

Definition at line 76 of file alu_dec.c.

◆ dec_get_sign()

static uint8_t dec_get_sign ( const uint8_t *  mem,
uint16_t  packed_addr 
)
static

Get the sign nibble of a packed field.

Definition at line 132 of file alu_dec.c.

◆ dec_read_digits()

static void dec_read_digits ( const uint8_t *  mem,
uint16_t  packed_addr,
int  packed_bytes,
uint8_t *  digits,
int  n_digits 
)
static

Read a packed field into a digit array (right-to-left, [0]=rightmost digit).

Definition at line 230 of file alu_dec.c.

◆ dec_result_cc()

static uint8_t dec_result_cc ( int  is_zero,
uint8_t  result_sign 
)
static

Compute the CC value from a sign and whether the result is zero.

CC=1 neg, CC=2 zero, CC=3 pos — matching manual FA04/FA05 table.

Definition at line 158 of file alu_dec.c.

◆ dec_set_digit()

static void dec_set_digit ( uint8_t *  mem,
uint16_t  packed_addr,
int  packed_bytes,
int  digit_idx,
uint8_t  digit 
)
static

Set a single digit in a packed field (same indexing as dec_get_digit).

Definition at line 108 of file alu_dec.c.

◆ dec_set_sign()

static void dec_set_sign ( uint8_t *  mem,
uint16_t  packed_addr,
uint8_t  sign 
)
static

Set the sign nibble of a packed field.

Definition at line 138 of file alu_dec.c.

◆ dec_sign_is_neg()

static int dec_sign_is_neg ( uint8_t  sign_nibble)
static

Returns 1 if the sign nibble represents a negative value.

Definition at line 57 of file alu_dec.c.

◆ dec_write_digits()

static void dec_write_digits ( uint8_t *  mem,
uint16_t  packed_addr,
int  packed_bytes,
const uint8_t *  digits,
int  n_digits 
)
static

Write a digit array back into a packed field.

Sign is NOT written by this function.

Definition at line 241 of file alu_dec.c.

◆ dec_zero_digits()

static void dec_zero_digits ( uint8_t *  mem,
uint16_t  packed_addr,
int  packed_bytes 
)
static

Clear all digits (not sign) in a packed field to zero.

Definition at line 146 of file alu_dec.c.