Pārlūkot izejas kodu

Add the scalar instruction emitter (E04-S03).

Emit bounded documented instructions for scalar assignments, word and integer
arithmetic, comparisons, and short-circuit booleans, with checked forward
branch fixups. Add multiply and signed/unsigned divide helpers with a stable
divide-by-zero result, plus a reviewed golden byte stream and disassembly.

Generated with Codebuff 🤖
Co-Authored-By: Codebuff <noreply@codebuff.com>
main
Daniel Covington pirms 4 dienas
vecāks
revīzija
26422557ac
12 mainītis faili ar 1482 papildinājumiem un 0 dzēšanām
  1. +18
    -0
      newLang/docs/architecture.md
  2. +1
    -0
      newLang/docs/decisions.md
  3. +98
    -0
      newLang/planning/claims/E04-S03.md
  4. +16
    -0
      newLang/scripts/build-scalar-test.ps1
  5. +99
    -0
      newLang/scripts/verify-scalar-test.ps1
  6. +14
    -0
      newLang/src/common/arithmetic.inc
  7. +12
    -0
      newLang/src/common/codegen.inc
  8. +216
    -0
      newLang/src/compiler/codegen.s
  9. +169
    -0
      newLang/src/runtime/arithmetic.s
  10. +743
    -0
      newLang/tests/codegen/scalar-test.s
  11. +95
    -0
      newLang/tests/codegen/scalar.expected.dis
  12. +1
    -0
      newLang/tests/codegen/scalar.expected.hex

+ 18
- 0
newLang/docs/architecture.md Parādīt failu

@@ -406,6 +406,24 @@ generation relies on it.
`delete` through an interface uses the object pointer and its class descriptor, `delete` through an interface uses the object pointer and its class descriptor,
not the interface table, to find the optional destructor and object size. not the interface table, to find the optional destructor and object size.


### 7.6 Scalar code generation (E04-S03)

`src/compiler/codegen.s` emits documented 6502 instructions into a bounded
256-byte buffer. One-byte values are in A; two-byte values are A (low) and X
(high). The emitter provides immediate/absolute loads and stores, absolute
`ADC`/`SBC`/`CMP` operands, `JSR`, and forward relative branches with checked
fixups. Forward branches are limited to +0..+127 bytes; E04-S04 supplies the
control-flow and long-branch expansion.

Multiplication and signed/unsigned division use `src/runtime/arithmetic.s`.
Operands are in `ar_a`/`ar_b`, the result is A/X, and division leaves its
remainder in `ar_rem`. Division by zero sets provisional `ar_fault` to
`AR_FAULT_DIV0`, returns A=X=0 with C=1, and is mapped to the final runtime
fault namespace by E04-S05. The scalar fixture executes the emitted shapes,
checks short-circuit evaluation, and compares a reviewed golden byte stream
and da65 disassembly. Parser integration into statements and frames is
E04-S04's responsibility.

## 8. Heap and Ownership ## 8. Heap and Ownership


- The generated-program heap initially resides in the same RAM bank as program - The generated-program heap initially resides in the same RAM bank as program


+ 1
- 0
newLang/docs/decisions.md Parādīt failu

@@ -56,6 +56,7 @@ documented default. `Proposed` means a later change still needs approval.
| D127 | `return` with a value in a program is E151. A method that declares a result must end every path in `return`; an `if` satisfies this only when both branches do, a `while` never does, and a missing return is reported at `end` as E150. | Spec 7 permits `return` but does not say what a program return means; a program has no caller or result. Deterministic and observable, and lets E04 emit a single exit path. Implemented by `close_block` and `set_ret`. | | D127 | `return` with a value in a program is E151. A method that declares a result must end every path in `return`; an `if` satisfies this only when both branches do, a `while` never does, and a missing return is reported at `end` as E150. | Spec 7 permits `return` but does not say what a program return means; a program has no caller or result. Deterministic and observable, and lets E04 emit a single exit path. Implemented by `close_block` and `set_ret`. |
| D128 | The generated PRG container loads at `$1C01` with the same 12-byte BASIC 7 stub as the compiler and enters at `$1C0D`. Sections follow in ascending address order; gaps are zero-filled. `NAME.MAP` is CR-terminated text: `NOVA128 MAP 1`, `ENTRY hhhh`, then `SECTION name start size` in hex. Existing `NAME.PRG`/`NAME.MAP` is refused with E202 instead of overwritten; outputs created by the run are scratched on abort or failure. The higher generated-program map (banking, heap, software stack) remains E04-S02. | Gives E04-S01 a deterministic, testable container while preserving a previously successful build. Refusing an existing output is explicit; the user must erase it before recompiling. Implemented by `output.s`, `startup.s`, and `formats.inc`. | | D128 | The generated PRG container loads at `$1C01` with the same 12-byte BASIC 7 stub as the compiler and enters at `$1C0D`. Sections follow in ascending address order; gaps are zero-filled. `NAME.MAP` is CR-terminated text: `NOVA128 MAP 1`, `ENTRY hhhh`, then `SECTION name start size` in hex. Existing `NAME.PRG`/`NAME.MAP` is refused with E202 instead of overwritten; outputs created by the run are scratched on abort or failure. The higher generated-program map (banking, heap, software stack) remains E04-S02. | Gives E04-S01 a deterministic, testable container while preserving a previously successful build. Refusing an existing output is explicit; the user must erase it before recompiling. Implemented by `output.s`, `startup.s`, and `formats.inc`. |
| D129 | Generated code executes with CR `$0E` and IRQs masked, then restores the entry CR. The software stack is bank 0 `$B800-$BFFF`, growing down from `$C000`; `SP`/`FP` use `$FB-$FE`. A frame stores the previous FP at `FP`, arguments from `FP+2`, and locals below `FP`; callers push arguments right-to-left and discard them after return. Results are A or A/X. `frame_enter` reserves the old FP and locals transactionally, refuses when the 6502 stack pointer is below `$40`, and returns C=1/`FRAME_ERR_STACK` with `SP`/`FP` restored on overflow. | Makes recursion and nested calls testable without consuming BASIC's zero page or the compiler's private stack. The $40 hardware-stack guard prevents a JAM before the software bound, and the transactional failure lets callers unwind cleanly. The 2 KB software stack, guard threshold, and mapping install are provisional until codegen and later runtime stories. Implemented by `frames.s` and `frames.inc`. | | D129 | Generated code executes with CR `$0E` and IRQs masked, then restores the entry CR. The software stack is bank 0 `$B800-$BFFF`, growing down from `$C000`; `SP`/`FP` use `$FB-$FE`. A frame stores the previous FP at `FP`, arguments from `FP+2`, and locals below `FP`; callers push arguments right-to-left and discard them after return. Results are A or A/X. `frame_enter` reserves the old FP and locals transactionally, refuses when the 6502 stack pointer is below `$40`, and returns C=1/`FRAME_ERR_STACK` with `SP`/`FP` restored on overflow. | Makes recursion and nested calls testable without consuming BASIC's zero page or the compiler's private stack. The $40 hardware-stack guard prevents a JAM before the software bound, and the transactional failure lets callers unwind cleanly. The 2 KB software stack, guard threshold, and mapping install are provisional until codegen and later runtime stories. Implemented by `frames.s` and `frames.inc`. |
| D130 | Scalar codegen emits documented 6502 instructions into a bounded 256-byte buffer. Values are A (one byte) or A/X low/high (two bytes); assignments use absolute stores, comparisons produce a 0/1 byte, and forward branches use checked fixups. Multiplication and signed/unsigned division call runtime helpers with operands in `ar_a`/`ar_b`; results are A/X, division remainder is `ar_rem`, and division by zero sets provisional `ar_fault=AR_FAULT_DIV0`, A=X=0, C=1. E04-S04 owns parser-to-emitter integration, control flow, and long-branch expansion. | Gives the backend a small, directly testable instruction layer and a deterministic golden stream before the control-flow shell exists. The 256-byte buffer and forward-only branches are deliberate limits; E04-S05 maps the provisional arithmetic fault to the final R-code namespace. Implemented by `codegen.s`, `codegen.inc`, `arithmetic.s`, and `arithmetic.inc`. |


## Deferred ## Deferred




+ 98
- 0
newLang/planning/claims/E04-S03.md Parādīt failu

@@ -0,0 +1,98 @@
---
story: E04-S03
owner: e04_scalar
status: done
started: 2026-11-09
depends-on: [E04-S02]
---

# E04-S03 Claim

## Intended change

Add the scalar instruction emitter in `src/compiler/codegen.s` and the
provisional arithmetic helpers in `src/runtime/arithmetic.s`. The emitter
writes documented 6502 instructions into a bounded code buffer, supports
absolute loads/stores and arithmetic operands, immediates, calls, forward
branches with checked fixups, and returns the byte length for golden tests.

The x128 fixture drives the emitter directly (parser integration is E04-S04)
to build representative byte, word, integer, boolean, comparison, assignment,
and short-circuit shapes, copies the golden byte stream, and executes it. It
also calls the multiply/divide helpers, including unsigned and signed
division, and verifies that division by zero sets a stable fault result.

## File area

- `src/compiler/codegen.s` (new), `src/runtime/arithmetic.s` (new)
- `src/common/codegen.inc`, `src/common/arithmetic.inc` (new)
- `tests/codegen/scalar-test.s`
- `tests/codegen/scalar.expected.dis`, `tests/codegen/scalar.expected.hex`
- `scripts/build-scalar-test.ps1`, `scripts/verify-scalar-test.ps1`
- `docs/decisions.md`, `docs/architecture.md`
- `planning/claims/E04-S03.md`
- generated files under `build/`

## Acceptance evidence

- [x] Emits correct byte, word, integer, boolean, comparison, and assignment
code: the fixture executes byte assignment/widening, word addition, integer
subtraction, six comparisons, and boolean short-circuit shapes. Results:
`$5A`, `$0E`, `$2221`, `$ECBB`.
- [x] Short-circuit `and`/`or` avoids evaluating the unused operand: both
shapes leave `V_EVAL=0` while producing the correct `V_FLAG`.
- [x] Division by zero faults predictably: the generated call to `ar_div_u16`
returns C=1, sets `ar_fault=AR_FAULT_DIV0`, and stores a zero result.
- [x] Golden disassembly covers representative expression shapes: a reviewed
231-byte stream and canonical da65 listing are committed as
`tests/codegen/scalar.expected.hex` and `.dis`; the verifier compares both.

## Coordination notes

- E04-S02 is `done`; this story adds the scalar backend primitives but does not
integrate them into the parser/control-flow shell.
- D130 records the provisional scalar emitter interface and arithmetic helper
data flow.
- Runtime arithmetic faults use a provisional `AR_FAULT_DIV0` value until
E04-S05 freezes the R-code namespace.
- The fixture runs in the compiler mapping; its emitter buffer is writable BSS
below `$A000`. Generated code is executed directly in that buffer.

## Work log

- Added `cg_*` byte emitters, absolute operand forms, forward branch fixups,
and a 256-byte bounded buffer.
- Added 16-bit unsigned multiply, restoring unsigned divide, and signed divide
with truncation toward zero.
- Fixed ca65 operator precedence in the fixture macros: `#>addr+1` became
`(>addr)+1`, so high-byte operands pointed at `$1Cxx` instead of `$1Bxx`.
Parenthesized `#<(addr)`/`#>(addr)` fixed word high bytes and the apparent
OR-tail misalignment.
- Increased the fixup table to 32 entries because comparison branches remain
recorded after patching.
- Corrected fixture expectations: widened `$5A` is `$005A`, and the short-
circuit cases now set their left operands explicitly.

## Completion

- Tests run:
- `scripts/build-scalar-test.ps1`
- `scripts/verify-scalar-test.ps1 -Port 6530`
- `scripts/verify-output-test.ps1 -Port 6530 -RunPort 6531`
- `scripts/verify-frame-test.ps1 -Port 6530`
- `scripts/verify-diag-test.ps1 -Port 6530`
- `scripts/verify-parser-test.ps1 -Port 6530`
- `git diff --check`
- Results: scalar mailbox PASS, data `5A 0E 21 22 BB EC E0 01`;
golden 231 bytes; canonical disassembly and hex match committed files.
- Files changed: `src/compiler/codegen.s`, `src/runtime/arithmetic.s`,
`src/common/codegen.inc`, `src/common/arithmetic.inc`,
`tests/codegen/scalar-test.s`, golden expectations,
`scripts/build-scalar-test.ps1`, `scripts/verify-scalar-test.ps1`,
`docs/decisions.md`, `docs/architecture.md`, this claim.
- Remaining risks: parser/statement integration and long-branch expansion are
E04-S04; the emitter buffer is 255 bytes and only forward branches are
supported; signed remainder is a magnitude, not sign-extended; byte
multiply/divide and integer comparisons are not separately exercised; the
divide fault is provisional until E04-S05; generated code is currently
executed in the compiler mapping, not installed by a generated startup.

+ 16
- 0
newLang/scripts/build-scalar-test.ps1 Parādīt failu

@@ -0,0 +1,16 @@
# E04-S03: build the scalar emitter/arithmetic fixture.
[CmdletBinding()]
param()

$ErrorActionPreference = "Stop"
$project = Split-Path $PSScriptRoot -Parent
Import-Module (Join-Path $PSScriptRoot "lib\Nova128Test.psm1") -Force

$out = Join-Path $project "build\scalar-test"
$link = Invoke-Nova128Link -Name "scalar-test" -BuildDir $out `
-Config (Join-Path $project "cfg\compiler.cfg") -Sources @(
(Join-Path $project "src\compiler\codegen.s"),
(Join-Path $project "src\runtime\arithmetic.s"),
(Join-Path $project "tests\codegen\scalar-test.s"))

Write-Host ("built {0}" -f $link.Program)

+ 99
- 0
newLang/scripts/verify-scalar-test.ps1 Parādīt failu

@@ -0,0 +1,99 @@
# E04-S03: run the scalar emitter fixture, check results, capture golden bytes,
# disassemble them with da65, and compare committed expectations when present.
[CmdletBinding()]
param(
[int]$Port = 6530,
[int]$TimeoutSeconds = 90
)

$ErrorActionPreference = "Stop"
$project = Split-Path $PSScriptRoot -Parent
Import-Module (Join-Path $PSScriptRoot "lib\Nova128Test.psm1") -Force
& (Join-Path $PSScriptRoot "build-scalar-test.ps1")

$out = Join-Path $project "build\scalar-test"
$prg = Join-Path $out "scalar-test.prg"
$labels = Join-Path $out "scalar-test.lbl"
$session = Start-Nova128X128 -Autostart $prg -Port $Port `
-Screenshot (Join-Path $out "scalar-test-vicii.png")
try {
$mb = Wait-Nova128Mailbox $session -TimeoutSeconds $TimeoutSeconds
$lenAddr = Get-Nova128Label -Labels $labels -Name "golden_len"
$copyAddr = Get-Nova128Label -Labels $labels -Name "golden_copy"
$lenBytes = Read-Nova128Memory -Session $session -Address $lenAddr -Count 1
$goldenLen = [int]$lenBytes[0]
if ($goldenLen -eq 0) { throw "golden_len is zero" }
$golden = Read-Nova128Memory -Session $session -Address $copyAddr -Count $goldenLen
} finally {
Stop-Nova128X128 $session
}

Write-Host ('mailbox: ' + (($mb | ForEach-Object { $_.ToString('X2') }) -join ' '))
Write-Host ("results: byte={0:X2} cmp={1:X2} add={2:X2}{3:X2} sub={4:X2}{5:X2} mul={6:X2} fault={7}" -f `
$mb[8], $mb[9], $mb[11], $mb[10], $mb[13], $mb[12], $mb[14], $mb[15])

$failures = @()
if ($mb[2] -ne 0x03) { $failures += "producer $($mb[2]) is not a generated program" }
if ($mb[3] -ne 0xA5) { $failures += "fixture status is not PASS" }
if ($mb[4] -ne 0 -or $mb[5] -ne 0) { $failures += "code is $($mb[4] + 256 * $mb[5])" }
$want = [ordered]@{
byte = 0x5A
cmp = 0x0E
addLow = 0x21; addHigh = 0x22
subLow = 0xBB; subHigh = 0xEC
mulLow = 0xE0
fault = 1
}
if ($mb[8] -ne $want.byte) { $failures += ('byte assignment is {0:X2}, expected {1:X2}' -f $mb[8], $want.byte) }
if ($mb[9] -ne $want.cmp) { $failures += ('comparisons are {0:X2}, expected {1:X2}' -f $mb[9], $want.cmp) }
if ($mb[10] -ne $want.addLow -or $mb[11] -ne $want.addHigh) {
$failures += ('add is {0:X2}{1:X2}, expected {2:X2}{3:X2}' -f $mb[11], $mb[10], $want.addHigh, $want.addLow)
}
if ($mb[12] -ne $want.subLow -or $mb[13] -ne $want.subHigh) {
$failures += ('sub is {0:X2}{1:X2}, expected {2:X2}{3:X2}' -f $mb[13], $mb[12], $want.subHigh, $want.subLow)
}
if ($mb[14] -ne $want.mulLow) { $failures += ('mul low is {0:X2}, expected {1:X2}' -f $mb[14], $want.mulLow) }
if ($mb[15] -ne $want.fault) { $failures += "fault byte is $($mb[15]), expected 1" }

$binPath = Join-Path $out "scalar.golden.bin"
[IO.File]::WriteAllBytes($binPath, $golden)
$disPath = Join-Path $out "scalar.golden.dis"
$da65 = (Get-Command da65 -ErrorAction Stop).Source
& $da65 --cpu 6502 --start-addr 0000 -o $disPath $binPath 2>&1 | Out-Null
if ($LASTEXITCODE -ne 0) { throw "da65 failed on $binPath" }
# Remove da65's timestamp/path header so the committed listing is stable.
$disLines = Get-Content -LiteralPath $disPath | Where-Object {
$_.Trim() -ne "" -and -not $_.StartsWith(";")
}
[IO.File]::WriteAllText($disPath, (($disLines -join "`n") + "`n"))

$hex = (($golden | ForEach-Object { $_.ToString("X2") }) -join " ") + "`n"
$actualHex = Join-Path $out "scalar.golden.hex"
[IO.File]::WriteAllText($actualHex, $hex)
Write-Host "golden bytes: $goldenLen"
Write-Host "hex: $actualHex"
Write-Host "disassembly: $disPath"

$expectedHexPath = Join-Path $project "tests\codegen\scalar.expected.hex"
if (Test-Path -LiteralPath $expectedHexPath) {
$expectedHex = ([IO.File]::ReadAllText($expectedHexPath)).Trim()
if ($hex.Trim() -ne $expectedHex) {
$failures += "golden bytes differ from tests/codegen/scalar.expected.hex"
}
} else {
Write-Host "no tests/codegen/scalar.expected.hex yet"
}

$expectedDisPath = Join-Path $project "tests\codegen\scalar.expected.dis"
if (Test-Path -LiteralPath $expectedDisPath) {
$expectedDis = ([IO.File]::ReadAllText($expectedDisPath)).Replace("`r`n", "`n").TrimEnd()
$actualDis = ([IO.File]::ReadAllText($disPath)).Replace("`r`n", "`n").TrimEnd()
if ($actualDis -ne $expectedDis) {
$failures += "golden disassembly differs from tests/codegen/scalar.expected.dis"
}
} else {
Write-Host "no tests/codegen/scalar.expected.dis yet"
}

if ($failures) { throw ("scalar verification failed:`n " + ($failures -join "`n ")) }
Write-Host "verified scalar assignments, comparisons, short-circuit, arithmetic, and divide-by-zero"

+ 14
- 0
newLang/src/common/arithmetic.inc Parādīt failu

@@ -0,0 +1,14 @@
; arithmetic.inc - provisional runtime scalar arithmetic (E04-S03).
;
; The operands live in ar_a/ar_b. The 16-bit result is A (low), X (high).
; Division also leaves the remainder in ar_rem. On division by zero the helper
; sets ar_fault=AR_FAULT_DIV0, returns A=X=0 and C=1. E04-S05 maps this to the
; final stable R-code namespace.

.ifndef ARITHMETIC_INC
ARITHMETIC_INC = 1

AR_FAULT_NONE = 0
AR_FAULT_DIV0 = 1

.endif

+ 12
- 0
newLang/src/common/codegen.inc Parādīt failu

@@ -0,0 +1,12 @@
; codegen.inc - scalar instruction emitter limits (E04-S03).

.ifndef CODEGEN_INC
CODEGEN_INC = 1

CG_MAX = 255 ; bytes in the emitter buffer (len is 1 byte)
CG_FIX_MAX = 32 ; forward branches per buffer
CG_ERR_FULL = 1 ; buffer full
CG_ERR_FIX = 2 ; fixup table full or bad index
CG_ERR_RANGE = 3 ; relative branch out of range

.endif

+ 216
- 0
newLang/src/compiler/codegen.s Parādīt failu

@@ -0,0 +1,216 @@
; codegen.s - documented scalar instruction emitter (E04-S03).
;
; The emitter writes into cg_code, a 256-byte RAM buffer. cg_len is the byte
; count (0-254); every failure sets cg_err and returns C=1. It does not emit a
; whole function yet: parser/codegen integration is E04-S04.
;
; API:
; cg_init
; cg_put A = byte
; cg_lda_imm A = value
; cg_ldx_imm A = value
; cg_ora_imm A = value
; cg_lda_abs A/X = address
; cg_ldx_abs A/X = address
; cg_sta_abs A/X = address
; cg_stx_abs A/X = address
; cg_adc_abs A/X = address
; cg_sbc_abs A/X = address
; cg_cmp_abs A/X = address
; cg_jsr_abs A/X = address
; cg_clc, cg_sec, cg_rts
; cg_branch_fwd A = branch opcode; emits opcode + placeholder, returns
; C=0 and A = fixup index
; cg_patch_here A = fixup index; target is the current end of buffer
; cg_here returns A = current length
;
; Only forward relative branches within +0..+127 bytes are accepted. This is
; enough for the scalar shapes and gives E04-S04 the checked primitive it
; needs for a later long-branch expansion.

.setcpu "6502"
.include "../common/codegen.inc"

.export cg_init, cg_put, cg_here, cg_branch_fwd, cg_patch_here
.export cg_lda_imm, cg_ldx_imm, cg_ora_imm, cg_lda_abs, cg_ldx_abs
.export cg_sta_abs, cg_stx_abs, cg_adc_abs, cg_sbc_abs, cg_cmp_abs
.export cg_jsr_abs, cg_clc, cg_sec, cg_rts
.export cg_code, cg_len, cg_err

.segment "CODE"

cg_init:
lda #$00
sta cg_len
sta cg_err
sta cg_fix_count
clc
rts

cg_here:
lda cg_len
rts

; A = byte to append. C=1 on overflow.
cg_put:
ldy cg_len
cpy #CG_MAX
bcs @full
sta cg_code,y
inc cg_len
clc
rts
@full: lda #CG_ERR_FULL
sta cg_err
sec
rts

; Immediate forms.
cg_lda_imm:
pha
lda #$A9
jsr cg_put
bcs @out
pla
jmp cg_put
@out: pla
sec
rts

cg_ldx_imm:
pha
lda #$A2
jsr cg_put
bcs @out
pla
jmp cg_put
@out: pla
sec
rts

cg_ora_imm:
pha
lda #$09
jsr cg_put
bcs @out
pla
jmp cg_put
@out: pla
sec
rts

; Absolute-address forms. Each wrapper supplies the opcode in Y; the shared
; routine stores the address before Y is reused by cg_put.
cg_lda_abs:
ldy #$AD
jmp cg_emit_addr
cg_ldx_abs:
ldy #$AE
jmp cg_emit_addr
cg_sta_abs:
ldy #$8D
jmp cg_emit_addr
cg_stx_abs:
ldy #$8E
jmp cg_emit_addr
cg_adc_abs:
ldy #$6D
jmp cg_emit_addr
cg_sbc_abs:
ldy #$ED
jmp cg_emit_addr
cg_cmp_abs:
ldy #$CD
jmp cg_emit_addr
cg_jsr_abs:
ldy #$20
jmp cg_emit_addr

cg_emit_addr:
sta cg_addr
stx cg_addr+1
tya
jsr cg_put
bcs @out
lda cg_addr
jsr cg_put
bcs @out
lda cg_addr+1
jmp cg_put
@out: sec
rts

cg_clc:
lda #$18
jmp cg_put
cg_sec:
lda #$38
jmp cg_put
cg_rts:
lda #$60
jmp cg_put

; A = branch opcode; forward target must be patched later.
cg_branch_fwd:
sta cg_op
lda cg_fix_count
cmp #CG_FIX_MAX
bcs @fix_full
sta cg_idx
lda cg_op
jsr cg_put
bcs @out
lda cg_len
sta cg_pos
ldy cg_idx
sta cg_fixpos,y
inc cg_fix_count
lda #$00
jsr cg_put
bcs @out
lda cg_idx
clc
rts
@fix_full:
lda #CG_ERR_FIX
sta cg_err
sec
rts
@out: sec
rts

; A = fixup index. Patch its placeholder so the branch targets cg_len.
cg_patch_here:
cmp cg_fix_count
bcs @bad
tax
lda cg_len
sec
sbc cg_fixpos,x
sec
sbc #1
cmp #128
bcs @range
ldy cg_fixpos,x
sta cg_code,y
clc
rts
@bad: lda #CG_ERR_FIX
sta cg_err
sec
rts
@range: lda #CG_ERR_RANGE
sta cg_err
sec
rts

.segment "BSS"
cg_code: .res 256
cg_len: .res 1
cg_err: .res 1
cg_fix_count: .res 1
cg_fixpos: .res CG_FIX_MAX
cg_addr: .res 2
cg_op: .res 1
cg_idx: .res 1
cg_pos: .res 1

+ 169
- 0
newLang/src/runtime/arithmetic.s Parādīt failu

@@ -0,0 +1,169 @@
; arithmetic.s - provisional 16-bit scalar arithmetic (E04-S03).
;
; Operands: ar_a (left/dividend), ar_b (right/divisor), little-endian words.
; Results: A=low, X=high; division remainder in ar_rem.
; Multiplication wraps to 16 bits. Unsigned and signed division truncate toward
; zero. Division by zero sets ar_fault=AR_FAULT_DIV0, returns A=X=0 and C=1.
;
; The helpers modify ar_a and ar_b while shifting; callers must reload
; operands for a second operation. The signed remainder is left as a magnitude
; for now; quotient behavior is the tested contract.

.setcpu "6502"
.include "../common/arithmetic.inc"

.export ar_mul_u16, ar_div_u16, ar_div_i16
.export ar_a, ar_b, ar_rem, ar_fault

.segment "CODE"

; ar_a * ar_b -> A/X (low 16 bits).
ar_mul_u16:
lda #AR_FAULT_NONE
sta ar_fault
lda #$00
sta ar_res
sta ar_res+1
ldx #16
@loop: lda ar_b
and #$01
beq @noadd
clc
lda ar_res
adc ar_a
sta ar_res
lda ar_res+1
adc ar_a+1
sta ar_res+1
@noadd:
asl ar_a
rol ar_a+1
lsr ar_b+1
ror ar_b
dex
bne @loop
lda ar_res
ldx ar_res+1
rts

; ar_a / ar_b -> A/X, remainder ar_rem. C=1 on divide by zero.
ar_div_u16:
lda ar_b
ora ar_b+1
bne @nonzero
lda #AR_FAULT_DIV0
sta ar_fault
lda #$00
sta ar_rem
sta ar_rem+1
sta ar_res
sta ar_res+1
ldx #$00
sec
rts

@nonzero:
lda #$00
sta ar_rem
sta ar_rem+1
sta ar_res
sta ar_res+1
ldx #16
@loop:
; rem = (rem << 1) | (dividend >> 15)
asl ar_rem
rol ar_rem+1
asl ar_a
rol ar_a+1
bcc @nobit
inc ar_rem
@nobit:
; quotient <<= 1
asl ar_res
rol ar_res+1
; if rem >= divisor, subtract and set quotient bit 0
lda ar_rem+1
cmp ar_b+1
bcc @next
bne @sub
lda ar_rem
cmp ar_b
bcc @next
@sub: sec
lda ar_rem
sbc ar_b
sta ar_rem
lda ar_rem+1
sbc ar_b+1
sta ar_rem+1
inc ar_res
@next: dex
bne @loop
lda #AR_FAULT_NONE
sta ar_fault
lda ar_res
ldx ar_res+1
clc
rts

; Signed ar_a / ar_b -> A/X, quotient truncated toward zero.
ar_div_i16:
lda ar_b
ora ar_b+1
bne @nonzero
jmp ar_div_u16
@nonzero:
lda ar_a+1
eor ar_b+1
and #$80
sta ar_sign
jsr ar_abs_a
jsr ar_abs_b
jsr ar_div_u16
sta ar_res
stx ar_res+1
lda ar_sign
bpl @done
sec
lda #$00
sbc ar_res
sta ar_res
lda #$00
sbc ar_res+1
sta ar_res+1
@done: lda ar_res
ldx ar_res+1
clc
rts

ar_abs_a:
lda ar_a+1
bpl @done
sec
lda #$00
sbc ar_a
sta ar_a
lda #$00
sbc ar_a+1
sta ar_a+1
@done: rts

ar_abs_b:
lda ar_b+1
bpl @done
sec
lda #$00
sbc ar_b
sta ar_b
lda #$00
sbc ar_b+1
sta ar_b+1
@done: rts

.segment "BSS"
ar_a: .res 2
ar_b: .res 2
ar_rem: .res 2
ar_res: .res 2
ar_fault: .res 1
ar_sign: .res 1

+ 743
- 0
newLang/tests/codegen/scalar-test.s Parādīt failu

@@ -0,0 +1,743 @@
; E04-S03: scalar emitter and arithmetic fixture in x128.
;
; The fixture drives codegen.s directly (parser integration is E04-S04),
; executes the emitted shapes, copies the golden bytes to golden_copy, then
; tests the arithmetic helpers. It runs in the compiler/BASIC mapping; all
; variables and the code buffer are below $A000.
;
; Mailbox data:
; +0 byte assignment (5A)
; +1 comparison bit mask (EQ..GE, expected 0E with 5,7)
; +2/+3 word add ($2221)
; +4/+5 integer sub ($ECBB)
; +6 multiply result low ($2EE0 -> E0)
; +7 arithmetic fault (1 = divide by zero)
; Failure bits: 1 emitter/assignment, 2 add/sub, 4 comparisons,
; 8 short-circuit, 16 multiply, 32 unsigned divide, 64 signed divide,
; 128 divide-by-zero.

.setcpu "6502"
.include "../../src/common/c128.inc"
.include "../../src/common/mailbox.inc"
.include "../../src/common/codegen.inc"
.include "../../src/common/arithmetic.inc"

.import cg_init, cg_len, cg_err, cg_code, cg_here, cg_patch_here
.import cg_lda_imm, cg_ldx_imm, cg_ora_imm
.import cg_lda_abs, cg_ldx_abs, cg_sta_abs, cg_stx_abs
.import cg_adc_abs, cg_sbc_abs, cg_cmp_abs, cg_jsr_abs
.import cg_clc, cg_sec, cg_rts, cg_branch_fwd
.import ar_mul_u16, ar_div_u16, ar_div_i16, ar_a, ar_b, ar_rem, ar_fault

; Fixed bank-0 scratch variables (SCRATCH is unused by this fixture).
V_SRC = $1B00
V_DST = $1B01
V_WIDE = $1B02
V_ADD_A = $1B04
V_ADD_B = $1B06
V_ADD_R = $1B08
V_SUB_A = $1B0A
V_SUB_B = $1B0C
V_SUB_R = $1B0E
V_BYTE_A = $1B10
V_BYTE_B = $1B11
V_CMP = $1B12
V_FLAG = $1B13
V_EVAL = $1B14
V_MUL_A = $1B16
V_MUL_B = $1B18
V_MUL_R = $1B1A
V_DIV_A = $1B1C
V_DIV_B = $1B1E
V_DIV_R = $1B20
V_SDIV_A = $1B22
V_SDIV_B = $1B24
V_SDIV_R = $1B26

.macro EMIT_LDA addr
lda #<(addr)
ldx #>(addr)
jsr cg_lda_abs
.endmacro

.macro EMIT_LDX addr
lda #<(addr)
ldx #>(addr)
jsr cg_ldx_abs
.endmacro

.macro EMIT_STA addr
lda #<(addr)
ldx #>(addr)
jsr cg_sta_abs
.endmacro

.macro EMIT_STX addr
lda #<(addr)
ldx #>(addr)
jsr cg_stx_abs
.endmacro

.macro EMIT_ADC addr
lda #<(addr)
ldx #>(addr)
jsr cg_adc_abs
.endmacro

.macro EMIT_SBC addr
lda #<(addr)
ldx #>(addr)
jsr cg_sbc_abs
.endmacro

.macro EMIT_CMP addr
lda #<(addr)
ldx #>(addr)
jsr cg_cmp_abs
.endmacro

.macro EMIT_JSR addr
lda #<(addr)
ldx #>(addr)
jsr cg_jsr_abs
.endmacro

.macro EMIT_LDA_IMM value
lda #value
jsr cg_lda_imm
.endmacro

.macro EMIT_ORA_IMM value
lda #value
jsr cg_ora_imm
.endmacro

.macro EMIT_BIT value
EMIT_LDA V_CMP
EMIT_ORA_IMM value
EMIT_STA V_CMP
.endmacro

.segment "LOADADDR"
.word $1C01

.segment "EXEHDR"
.word basic_end
.word 10
.byte $9E
.byte "7181"
.byte $00
basic_end:
.word $0000

.segment "MAILBOX"
.res MB_SIZE

.segment "STARTUP"
.export test_entry
test_entry:
php
sei
ldx #MB_SIZE - 1
lda #$00
@clr: sta MB_BASE,x
dex
bpl @clr
lda #MB_MAGIC0_VALUE
sta MB_MAGIC0
lda #MB_MAGIC1_VALUE
sta MB_MAGIC1
lda #MB_PROD_PROGRAM
sta MB_PRODUCER
lda #MB_ST_RUNNING
sta MB_STATUS
lda #$00
sta fail_mask
sta MB_CODE
sta MB_CODE+1

jsr init_vars
jsr cg_init

; ---------------------------------------------------- golden shape 1: byte assignment
EMIT_LDA V_SRC
EMIT_STA V_DST
jsr cg_rts
lda cg_len
sta s2

; ---------------------------------------------------- shape 2: byte -> word widening
EMIT_LDA V_SRC
EMIT_STA V_WIDE
EMIT_LDA_IMM $00
EMIT_STA V_WIDE+1
jsr cg_rts
lda cg_len
sta s3

; ---------------------------------------------------- shape 3: word addition
EMIT_LDA V_ADD_A
jsr cg_clc
EMIT_ADC V_ADD_B
EMIT_STA V_ADD_R
EMIT_LDA V_ADD_A+1
EMIT_ADC V_ADD_B+1
EMIT_STA V_ADD_R+1
jsr cg_rts
lda cg_len
sta s4

; ---------------------------------------------------- shape 4: integer subtraction
EMIT_LDA V_SUB_A
jsr cg_sec
EMIT_SBC V_SUB_B
EMIT_STA V_SUB_R
EMIT_LDA V_SUB_A+1
EMIT_SBC V_SUB_B+1
EMIT_STA V_SUB_R+1
jsr cg_rts
lda cg_len
sta s5

; ---------------------------------------------------- shape 5: six comparisons
EMIT_LDA_IMM $00
EMIT_STA V_CMP

; EQ bit 1
EMIT_LDA V_BYTE_A
EMIT_CMP V_BYTE_B
lda #$D0 ; BNE skip
jsr cg_branch_fwd
sta fix_eq
EMIT_BIT $01
lda fix_eq
jsr cg_patch_here

; NE bit 2
EMIT_LDA V_BYTE_A
EMIT_CMP V_BYTE_B
lda #$F0 ; BEQ skip
jsr cg_branch_fwd
sta fix_ne
EMIT_BIT $02
lda fix_ne
jsr cg_patch_here

; LT bit 4
EMIT_LDA V_BYTE_A
EMIT_CMP V_BYTE_B
lda #$B0 ; BCS skip
jsr cg_branch_fwd
sta fix_lt
EMIT_BIT $04
lda fix_lt
jsr cg_patch_here

; LE bit 8: equal or below goes to set, above skips
EMIT_LDA V_BYTE_A
EMIT_CMP V_BYTE_B
lda #$F0 ; BEQ set
jsr cg_branch_fwd
sta fix_le1
lda #$90 ; BCC set
jsr cg_branch_fwd
sta fix_le2
lda #$B0 ; BCS skip
jsr cg_branch_fwd
sta fix_le3
lda fix_le1
jsr cg_patch_here
lda fix_le2
jsr cg_patch_here
EMIT_BIT $08
lda fix_le3
jsr cg_patch_here

; GT bit 16: equal or below skips
EMIT_LDA V_BYTE_A
EMIT_CMP V_BYTE_B
lda #$F0 ; BEQ skip
jsr cg_branch_fwd
sta fix_gt1
lda #$90 ; BCC skip
jsr cg_branch_fwd
sta fix_gt2
EMIT_BIT $10
lda fix_gt1
jsr cg_patch_here
lda fix_gt2
jsr cg_patch_here

; GE bit 32
EMIT_LDA V_BYTE_A
EMIT_CMP V_BYTE_B
lda #$90 ; BCC skip
jsr cg_branch_fwd
sta fix_ge
EMIT_BIT $20
lda fix_ge
jsr cg_patch_here
jsr cg_rts
lda cg_len
sta s6

; ---------------------------------------------------- shape 6: short-circuit AND
EMIT_LDA_IMM $00
EMIT_STA V_EVAL
EMIT_LDA V_BYTE_A
lda #$F0 ; BEQ false
jsr cg_branch_fwd
sta fix_and1
EMIT_LDA_IMM $01
EMIT_STA V_EVAL
EMIT_LDA V_BYTE_B
lda #$F0 ; BEQ false
jsr cg_branch_fwd
sta fix_and2
EMIT_LDA_IMM $01
EMIT_STA V_FLAG
jsr cg_rts
lda fix_and1
jsr cg_patch_here
lda fix_and2
jsr cg_patch_here
EMIT_LDA_IMM $00
EMIT_STA V_FLAG
jsr cg_rts
lda cg_len
sta s7

; ---------------------------------------------------- shape 7: short-circuit OR
EMIT_LDA_IMM $00
EMIT_STA V_EVAL
EMIT_LDA V_BYTE_A
lda #$D0 ; BNE true
jsr cg_branch_fwd
sta fix_or1
EMIT_LDA_IMM $01
EMIT_STA V_EVAL
EMIT_LDA V_BYTE_B
lda #$D0 ; BNE true
jsr cg_branch_fwd
sta fix_or2
EMIT_LDA_IMM $00
EMIT_STA V_FLAG
jsr cg_rts
lda fix_or1
jsr cg_patch_here
lda fix_or2
jsr cg_patch_here
EMIT_LDA_IMM $01
EMIT_STA V_FLAG
jsr cg_rts

lda cg_len
sta golden_len
jsr copy_golden
lda cg_err
beq @golden_ok
lda #$01
jsr fail
jmp @finish
@golden_ok:

; ---------------------------------------------------- run golden shapes
lda #$00
jsr run_code
lda V_DST
cmp #$5A
beq @s2
lda #$01
jsr fail
@s2: lda s2
jsr run_code
lda V_WIDE
cmp #$5A
bne @s2_bad
lda V_WIDE+1
bne @s2_bad
jmp @s3
@s2_bad:
lda #$01
jsr fail

@s3: lda s3
jsr run_code
lda V_ADD_R
cmp #$21
bne @s3_bad
lda V_ADD_R+1
cmp #$22
bne @s3_bad
jmp @s4
@s3_bad:
lda #$02
jsr fail

@s4: lda s4
jsr run_code
lda V_SUB_R
cmp #$BB
bne @s4_bad
lda V_SUB_R+1
cmp #$EC
bne @s4_bad
jmp @s5
@s4_bad:
lda #$02
jsr fail

@s5: lda s5
jsr run_code
lda V_CMP
cmp #$0E
beq @s6
lda #$04
jsr fail

@s6: lda #$00
sta V_BYTE_A
lda #$01
sta V_BYTE_B
lda s6
jsr run_code
lda V_FLAG
bne @s6_bad
lda V_EVAL
bne @s6_bad
jmp @s7
@s6_bad:
lda #$08
jsr fail

@s7: lda #$01
sta V_BYTE_A
lda #$00
sta V_BYTE_B
lda s7
jsr run_code
lda V_FLAG
cmp #$01
bne @s7_bad
lda V_EVAL
bne @s7_bad
jmp @arith
@s7_bad:
lda #$08
jsr fail

; ---------------------------------------------------- arithmetic helpers
@arith:
jsr cg_init
EMIT_LDA V_MUL_A
EMIT_STA ar_a
EMIT_LDA V_MUL_A+1
EMIT_STA ar_a+1
EMIT_LDA V_MUL_B
EMIT_STA ar_b
EMIT_LDA V_MUL_B+1
EMIT_STA ar_b+1
EMIT_JSR ar_mul_u16
EMIT_STA V_MUL_R
EMIT_STX V_MUL_R+1
jsr cg_rts
lda cg_err
beq @mul_run
lda #$10
jsr fail
jmp @div
@mul_run:
lda #$00
jsr run_code
lda V_MUL_R
cmp #$E0
bne @mul_bad
lda V_MUL_R+1
cmp #$2E
bne @mul_bad
jmp @div
@mul_bad:
lda #$10
jsr fail

@div: jsr cg_init
EMIT_LDA V_DIV_A
EMIT_STA ar_a
EMIT_LDA V_DIV_A+1
EMIT_STA ar_a+1
EMIT_LDA V_DIV_B
EMIT_STA ar_b
EMIT_LDA V_DIV_B+1
EMIT_STA ar_b+1
EMIT_JSR ar_div_u16
EMIT_STA V_DIV_R
EMIT_STX V_DIV_R+1
jsr cg_rts
lda cg_err
beq @div_run
lda #$20
jsr fail
jmp @sdiv
@div_run:
lda #$00
jsr run_code
bcs @div_bad
lda V_DIV_R
cmp #$8E
bne @div_bad
lda V_DIV_R+1
bne @div_bad
lda ar_rem
cmp #$06
bne @div_bad
lda ar_rem+1
bne @div_bad
jmp @sdiv
@div_bad:
lda #$20
jsr fail

@sdiv: jsr cg_init
EMIT_LDA V_SDIV_A
EMIT_STA ar_a
EMIT_LDA V_SDIV_A+1
EMIT_STA ar_a+1
EMIT_LDA V_SDIV_B
EMIT_STA ar_b
EMIT_LDA V_SDIV_B+1
EMIT_STA ar_b+1
EMIT_JSR ar_div_i16
EMIT_STA V_SDIV_R
EMIT_STX V_SDIV_R+1
jsr cg_rts
lda cg_err
beq @sdiv_run
lda #$40
jsr fail
jmp @divzero
@sdiv_run:
lda #$00
jsr run_code
bcs @sdiv_bad
lda V_SDIV_R
cmp #$F2
bne @sdiv_bad
lda V_SDIV_R+1
cmp #$FF
bne @sdiv_bad
jmp @divzero
@sdiv_bad:
lda #$40
jsr fail

@divzero:
lda #$00
sta V_DIV_B
sta V_DIV_B+1
jsr cg_init
EMIT_LDA V_DIV_A
EMIT_STA ar_a
EMIT_LDA V_DIV_A+1
EMIT_STA ar_a+1
EMIT_LDA V_DIV_B
EMIT_STA ar_b
EMIT_LDA V_DIV_B+1
EMIT_STA ar_b+1
EMIT_JSR ar_div_u16
EMIT_STA V_DIV_R
EMIT_STX V_DIV_R+1
jsr cg_rts
lda cg_err
beq @dz_run
lda #$80
jsr fail
jmp @finish
@dz_run:
lda #$00
jsr run_code
bcc @dz_bad
lda ar_fault
cmp #AR_FAULT_DIV0
bne @dz_bad
lda V_DIV_R
ora V_DIV_R+1
bne @dz_bad
jmp @finish
@dz_bad:
lda #$80
jsr fail

; ---------------------------------------------------- report
@finish:
lda V_DST
sta MB_DATA+0
lda V_CMP
sta MB_DATA+1
lda V_ADD_R
sta MB_DATA+2
lda V_ADD_R+1
sta MB_DATA+3
lda V_SUB_R
sta MB_DATA+4
lda V_SUB_R+1
sta MB_DATA+5
lda V_MUL_R
sta MB_DATA+6
lda ar_fault
sta MB_DATA+7
lda fail_mask
sta MB_CODE
lda #$00
sta MB_CODE+1
lda #MB_ST_FAIL
ldx fail_mask
bne @status
lda #MB_ST_PASS
@status:
sta MB_STATUS
ldy #$00
@print: lda message,y
beq @end
sty print_y
jsr CHROUT
ldy print_y
iny
bne @print
@end: plp
rts

; A = code-buffer offset. Patch a JSR operand and run the snippet.
run_code:
clc
adc #<cg_code
sta @target+1
lda #>cg_code
adc #0
sta @target+2
@target:
jsr $FFFF
rts

copy_golden:
ldx #$00
@copy: cpx golden_len
beq @done
lda cg_code,x
sta golden_copy,x
inx
bne @copy
@done: rts

init_vars:
lda #$5A
sta V_SRC
sta V_DST
lda #$00
sta V_WIDE
sta V_WIDE+1
sta V_CMP
sta V_FLAG
sta V_EVAL
sta ar_fault

lda #$34
sta V_ADD_A
lda #$12
sta V_ADD_A+1
lda #$ED
sta V_ADD_B
lda #$0F
sta V_ADD_B+1
lda #$00
sta V_ADD_R
sta V_ADD_R+1

lda #$00
sta V_SUB_A
lda #$10
sta V_SUB_A+1
lda #$45
sta V_SUB_B
lda #$23
sta V_SUB_B+1
lda #$00
sta V_SUB_R
sta V_SUB_R+1

lda #$05
sta V_BYTE_A
lda #$07
sta V_BYTE_B

lda #$2C
sta V_MUL_A
lda #$01
sta V_MUL_A+1
lda #$28
sta V_MUL_B
lda #$00
sta V_MUL_B+1
lda #$00
sta V_MUL_R
sta V_MUL_R+1

lda #$E8
sta V_DIV_A
lda #$03
sta V_DIV_A+1
lda #$07
sta V_DIV_B
lda #$00
sta V_DIV_B+1
lda #$00
sta V_DIV_R
sta V_DIV_R+1

lda #$9C
sta V_SDIV_A
lda #$FF
sta V_SDIV_A+1
lda #$07
sta V_SDIV_B
lda #$00
sta V_SDIV_B+1
lda #$00
sta V_SDIV_R
sta V_SDIV_R+1
rts

.segment "CODE"
fail:
ora fail_mask
sta fail_mask
rts

.segment "RODATA"
message: .byte "NOVA128 SCALAR TEST DONE", $0D, $00

.segment "BSS"
fail_mask: .res 1
print_y: .res 1
s2: .res 1
s3: .res 1
s4: .res 1
s5: .res 1
s6: .res 1
s7: .res 1
fix_eq: .res 1
fix_ne: .res 1
fix_lt: .res 1
fix_le1: .res 1
fix_le2: .res 1
fix_le3: .res 1
fix_gt1: .res 1
fix_gt2: .res 1
fix_ge: .res 1
fix_and1: .res 1
fix_and2: .res 1
fix_or1: .res 1
fix_or2: .res 1
.export golden_len
.export golden_copy
golden_len: .res 1
golden_copy: .res 256

+ 95
- 0
newLang/tests/codegen/scalar.expected.dis Parādīt failu

@@ -0,0 +1,95 @@
.setcpu "6502"
lda $1B00
sta $1B01
rts
lda $1B00
sta $1B02
lda #$00
sta $1B03
rts
lda $1B04
clc
adc $1B06
sta $1B08
lda $1B05
adc $1B07
sta $1B09
rts
lda $1B0A
sec
sbc $1B0C
sta $1B0E
lda $1B0B
sbc $1B0D
sta $1B0F
rts
lda #$00
sta $1B12
lda $1B10
cmp $1B11
bne L0050
lda $1B12
ora #$01
sta $1B12
L0050: lda $1B10
cmp $1B11
beq L0060
lda $1B12
ora #$02
sta $1B12
L0060: lda $1B10
cmp $1B11
bcs L0070
lda $1B12
ora #$04
sta $1B12
L0070: lda $1B10
cmp $1B11
beq L007C
bcc L007C
bcs L0084
L007C: lda $1B12
ora #$08
sta $1B12
L0084: lda $1B10
cmp $1B11
beq L0096
bcc L0096
lda $1B12
ora #$10
sta $1B12
L0096: lda $1B10
cmp $1B11
bcc L00A6
lda $1B12
ora #$20
sta $1B12
L00A6: rts
lda #$00
sta $1B14
lda $1B10
beq L00C1
lda #$01
sta $1B14
lda $1B11
beq L00C1
lda #$01
sta $1B13
rts
L00C1: lda #$00
sta $1B13
rts
lda #$00
sta $1B14
lda $1B10
bne L00E1
lda #$01
sta $1B14
lda $1B11
bne L00E1
lda #$00
sta $1B13
rts
L00E1: lda #$01
sta $1B13
rts

+ 1
- 0
newLang/tests/codegen/scalar.expected.hex Parādīt failu

@@ -0,0 +1 @@
AD 00 1B 8D 01 1B 60 AD 00 1B 8D 02 1B A9 00 8D 03 1B 60 AD 04 1B 18 6D 06 1B 8D 08 1B AD 05 1B 6D 07 1B 8D 09 1B 60 AD 0A 1B 38 ED 0C 1B 8D 0E 1B AD 0B 1B ED 0D 1B 8D 0F 1B 60 A9 00 8D 12 1B AD 10 1B CD 11 1B D0 08 AD 12 1B 09 01 8D 12 1B AD 10 1B CD 11 1B F0 08 AD 12 1B 09 02 8D 12 1B AD 10 1B CD 11 1B B0 08 AD 12 1B 09 04 8D 12 1B AD 10 1B CD 11 1B F0 04 90 02 B0 08 AD 12 1B 09 08 8D 12 1B AD 10 1B CD 11 1B F0 0A 90 08 AD 12 1B 09 10 8D 12 1B AD 10 1B CD 11 1B 90 08 AD 12 1B 09 20 8D 12 1B 60 A9 00 8D 14 1B AD 10 1B F0 10 A9 01 8D 14 1B AD 11 1B F0 06 A9 01 8D 13 1B 60 A9 00 8D 13 1B 60 A9 00 8D 14 1B AD 10 1B D0 10 A9 01 8D 14 1B AD 11 1B D0 06 A9 00 8D 13 1B 60 A9 01 8D 13 1B 60

Notiek ielāde…
Atcelt
Saglabāt

Powered by TurnKey Linux.