# HG changeset patch # User Pascal Bellard # Date 1690917096 0 # Node ID f1ad7cb7989b0e25c2715b1c983762fdaa648007 # Parent cb71c3a76f5a4cea5f1fd4dd013c661bfa067b78 Add zx0 (again) diff -r cb71c3a76f5a -r f1ad7cb7989b memtest/stuff/unzx0.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memtest/stuff/unzx0.S Tue Aug 01 19:11:36 2023 +0000 @@ -0,0 +1,134 @@ +#ifndef FLAT32 +// input ds:si=inStream, es:di=outStream +// output outStream[], ds:si, es:di + .code16 +#define BX %bx +#define SI %si +#define DI %di +#else +// input esi=inStream, edi=outStream +// output outStream[], ds:esi, es:edi + .code32 +#define BX %ebx +#define SI %esi +#define DI %edi +#endif + +// unzx0_8088.S - ZX0 decompressor for 8088 - 73 bytes - NASM +// +// inputs: +// * ds:si: start of compressed data +// * es:di: start of decompression buffer +// +// Copyright (C) 2021 Emmanuel Marty +// ZX0 compression (c) 2021 Einar Saukas, https://github.com/einar-saukas/ZX0 +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +zx0_decompress: + cld // make string operations go forward + movb $0x80, %al // initialize empty bit queue + // plus bit to roll into carry + stc + sbb BX, BX // initialize rep-offset to 1 + +.literals: + call .get_elias // read number of literals to copy + rep movsb // copy literal bytes + + addb %al, %al // shift bit queue, and high bit into carry + jc .get_offset // if 1: read offset, if 0: rep-match + + call .get_elias // read rep-match length (starts at 1) + +.macro norm ds,si,reg,reg2 + movw \si, \reg + andw $0xF, \si +# ifdef ONLY8086 + shrw $1, \reg + shrw $1, \reg + shrw $1, \reg + shrw $1, \reg +# else + shrw $4, \reg +# endif + addw \reg, \reg2 + movw \reg2, \ds +.endm + +.copy_match: +#if !defined(FLAT16) && !defined(FLAT32) + movw %ds, %dx + norm %ds, %si, %bp, %dx +#endif +#if !defined(FLAT16OUT) && !defined(FLAT32) + movw %es, %dx + norm %es, %di, %bp, %dx +#endif + push SI // save si (current pointer to compressed data) + lea (BX,DI), SI // point to destination in es:di + offset in bx +#if !defined(FLAT16OUT) && !defined(FLAT32) + pushw %ds + movw %es, %dx + cmpw %si, %di + ja .sameseg + subb $0x10, %dh +.sameseg: + norm %ds, %si, %bp, %dx + rep movsb // copy matched bytes + popw %ds +#else + rep movsb %es:(SI), %es:(DI) // copy matched bytes +#endif + pop SI // restore si + + addb %al, %al // read 'literal or match' bit + jnc .literals // if 0: go copy literals + +.get_offset: + movb $0xfe, %cl // initialize value to FEh + call .elias_loop // read high byte of match offset, set carry + incb %cl // obtain negative offset high byte + je .done // exit if EOD marker + + movb %cl, %bh // transfer negative high byte into bh + movw $1, %cx // initialize match length value to 1 + movb (%si), %bl // read low byte of offset + 1 bit of len + incw %si // inc instruction keep carry set + // set high bit that is shifted into bit 15 + rcrw $1, %bx // shift len bit into carry/offset in place + call .elias_bt // if len bit is set, no need for more + // else read rest of elias-encoded match length + incw %cx // fix match length + jmp .copy_match // go copy match + +.get_elias: + movw $1, %cx // initialize value to 1 +.elias_loop: + addb %al, %al // shift bit queue, and high bit into carry + jnz .got_bit // queue not empty, bits remain + lodsb // read 8 new bits + adcb %al, %al // shift bit queue, and high bit into carry +.got_bit: +.elias_bt: + jc .got_elias // done if control bit is 1 + addb %al, %al // read data bit + adcw %cx, %cx // shift into cx + jmp .elias_loop // keep reading +.got_elias: +.done: + ret diff -r cb71c3a76f5a -r f1ad7cb7989b memtest64/stuff/unzx0.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memtest64/stuff/unzx0.S Tue Aug 01 19:11:36 2023 +0000 @@ -0,0 +1,134 @@ +#ifndef FLAT32 +// input ds:si=inStream, es:di=outStream +// output outStream[], ds:si, es:di + .code16 +#define BX %bx +#define SI %si +#define DI %di +#else +// input esi=inStream, edi=outStream +// output outStream[], ds:esi, es:edi + .code32 +#define BX %ebx +#define SI %esi +#define DI %edi +#endif + +// unzx0_8088.S - ZX0 decompressor for 8088 - 73 bytes - NASM +// +// inputs: +// * ds:si: start of compressed data +// * es:di: start of decompression buffer +// +// Copyright (C) 2021 Emmanuel Marty +// ZX0 compression (c) 2021 Einar Saukas, https://github.com/einar-saukas/ZX0 +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +zx0_decompress: + cld // make string operations go forward + movb $0x80, %al // initialize empty bit queue + // plus bit to roll into carry + stc + sbb BX, BX // initialize rep-offset to 1 + +.literals: + call .get_elias // read number of literals to copy + rep movsb // copy literal bytes + + addb %al, %al // shift bit queue, and high bit into carry + jc .get_offset // if 1: read offset, if 0: rep-match + + call .get_elias // read rep-match length (starts at 1) + +.macro norm ds,si,reg,reg2 + movw \si, \reg + andw $0xF, \si +# ifdef ONLY8086 + shrw $1, \reg + shrw $1, \reg + shrw $1, \reg + shrw $1, \reg +# else + shrw $4, \reg +# endif + addw \reg, \reg2 + movw \reg2, \ds +.endm + +.copy_match: +#if !defined(FLAT16) && !defined(FLAT32) + movw %ds, %dx + norm %ds, %si, %bp, %dx +#endif +#if !defined(FLAT16OUT) && !defined(FLAT32) + movw %es, %dx + norm %es, %di, %bp, %dx +#endif + push SI // save si (current pointer to compressed data) + lea (BX,DI), SI // point to destination in es:di + offset in bx +#if !defined(FLAT16OUT) && !defined(FLAT32) + pushw %ds + movw %es, %dx + cmpw %si, %di + ja .sameseg + subb $0x10, %dh +.sameseg: + norm %ds, %si, %bp, %dx + rep movsb // copy matched bytes + popw %ds +#else + rep movsb %es:(SI), %es:(DI) // copy matched bytes +#endif + pop SI // restore si + + addb %al, %al // read 'literal or match' bit + jnc .literals // if 0: go copy literals + +.get_offset: + movb $0xfe, %cl // initialize value to FEh + call .elias_loop // read high byte of match offset, set carry + incb %cl // obtain negative offset high byte + je .done // exit if EOD marker + + movb %cl, %bh // transfer negative high byte into bh + movw $1, %cx // initialize match length value to 1 + movb (%si), %bl // read low byte of offset + 1 bit of len + incw %si // inc instruction keep carry set + // set high bit that is shifted into bit 15 + rcrw $1, %bx // shift len bit into carry/offset in place + call .elias_bt // if len bit is set, no need for more + // else read rest of elias-encoded match length + incw %cx // fix match length + jmp .copy_match // go copy match + +.get_elias: + movw $1, %cx // initialize value to 1 +.elias_loop: + addb %al, %al // shift bit queue, and high bit into carry + jnz .got_bit // queue not empty, bits remain + lodsb // read 8 new bits + adcb %al, %al // shift bit queue, and high bit into carry +.got_bit: +.elias_bt: + jc .got_elias // done if control bit is 1 + addb %al, %al // read data bit + adcw %cx, %cx // shift into cx + jmp .elias_loop // keep reading +.got_elias: +.done: + ret diff -r cb71c3a76f5a -r f1ad7cb7989b plop/stuff/unzx0.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plop/stuff/unzx0.S Tue Aug 01 19:11:36 2023 +0000 @@ -0,0 +1,134 @@ +#ifndef FLAT32 +// input ds:si=inStream, es:di=outStream +// output outStream[], ds:si, es:di + .code16 +#define BX %bx +#define SI %si +#define DI %di +#else +// input esi=inStream, edi=outStream +// output outStream[], ds:esi, es:edi + .code32 +#define BX %ebx +#define SI %esi +#define DI %edi +#endif + +// unzx0_8088.S - ZX0 decompressor for 8088 - 73 bytes - NASM +// +// inputs: +// * ds:si: start of compressed data +// * es:di: start of decompression buffer +// +// Copyright (C) 2021 Emmanuel Marty +// ZX0 compression (c) 2021 Einar Saukas, https://github.com/einar-saukas/ZX0 +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +zx0_decompress: + cld // make string operations go forward + movb $0x80, %al // initialize empty bit queue + // plus bit to roll into carry + stc + sbb BX, BX // initialize rep-offset to 1 + +.literals: + call .get_elias // read number of literals to copy + rep movsb // copy literal bytes + + addb %al, %al // shift bit queue, and high bit into carry + jc .get_offset // if 1: read offset, if 0: rep-match + + call .get_elias // read rep-match length (starts at 1) + +.macro norm ds,si,reg,reg2 + movw \si, \reg + andw $0xF, \si +# ifdef ONLY8086 + shrw $1, \reg + shrw $1, \reg + shrw $1, \reg + shrw $1, \reg +# else + shrw $4, \reg +# endif + addw \reg, \reg2 + movw \reg2, \ds +.endm + +.copy_match: +#if !defined(FLAT16) && !defined(FLAT32) + movw %ds, %dx + norm %ds, %si, %bp, %dx +#endif +#if !defined(FLAT16OUT) && !defined(FLAT32) + movw %es, %dx + norm %es, %di, %bp, %dx +#endif + push SI // save si (current pointer to compressed data) + lea (BX,DI), SI // point to destination in es:di + offset in bx +#if !defined(FLAT16OUT) && !defined(FLAT32) + pushw %ds + movw %es, %dx + cmpw %si, %di + ja .sameseg + subb $0x10, %dh +.sameseg: + norm %ds, %si, %bp, %dx + rep movsb // copy matched bytes + popw %ds +#else + rep movsb %es:(SI), %es:(DI) // copy matched bytes +#endif + pop SI // restore si + + addb %al, %al // read 'literal or match' bit + jnc .literals // if 0: go copy literals + +.get_offset: + movb $0xfe, %cl // initialize value to FEh + call .elias_loop // read high byte of match offset, set carry + incb %cl // obtain negative offset high byte + je .done // exit if EOD marker + + movb %cl, %bh // transfer negative high byte into bh + movw $1, %cx // initialize match length value to 1 + movb (%si), %bl // read low byte of offset + 1 bit of len + incw %si // inc instruction keep carry set + // set high bit that is shifted into bit 15 + rcrw $1, %bx // shift len bit into carry/offset in place + call .elias_bt // if len bit is set, no need for more + // else read rest of elias-encoded match length + incw %cx // fix match length + jmp .copy_match // go copy match + +.get_elias: + movw $1, %cx // initialize value to 1 +.elias_loop: + addb %al, %al // shift bit queue, and high bit into carry + jnz .got_bit // queue not empty, bits remain + lodsb // read 8 new bits + adcb %al, %al // shift bit queue, and high bit into carry +.got_bit: +.elias_bt: + jc .got_elias // done if control bit is 1 + addb %al, %al // read data bit + adcw %cx, %cx // shift into cx + jmp .elias_loop // keep reading +.got_elias: +.done: + ret