{"id":7539831,"url":"https://github.com/FluBBaOfWard/WSCPUTest","last_synced_at":"2025-05-09T23:32:36.057Z","repository":{"id":203563762,"uuid":"487609894","full_name":"FluBBaOfWard/WSCpuTest","owner":"FluBBaOfWard","description":"Program for testing the WonderSwan CPU.","archived":false,"fork":false,"pushed_at":"2025-05-02T08:27:59.000Z","size":566,"stargazers_count":3,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-02T09:36:56.960Z","etag":null,"topics":["cpu-tester","wonderswan","x86-assembly"],"latest_commit_sha":null,"homepage":"","language":"Assembly","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FluBBaOfWard.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-05-01T18:17:59.000Z","updated_at":"2025-05-02T08:28:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"3123bd59-5d5a-4547-a72f-fe19126b0829","html_url":"https://github.com/FluBBaOfWard/WSCpuTest","commit_stats":null,"previous_names":["flubbaofward/wscputest"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FluBBaOfWard%2FWSCpuTest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FluBBaOfWard%2FWSCpuTest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FluBBaOfWard%2FWSCpuTest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FluBBaOfWard%2FWSCpuTest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FluBBaOfWard","download_url":"https://codeload.github.com/FluBBaOfWard/WSCpuTest/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253341969,"owners_count":21893547,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpu-tester","wonderswan","x86-assembly"],"created_at":"2024-04-08T00:09:01.315Z","updated_at":"2025-05-09T23:32:36.044Z","avatar_url":"https://github.com/FluBBaOfWard.png","language":"Assembly","funding_links":[],"categories":["Accuracy test ROMs"],"sub_categories":["Peripherals"],"readme":"# WonderSwan CPU Test V0.7.3 (20250502)\n\nThis is a CPU Test program for Bandai WonderSwan (Color/Crystal) \u0026 Benesse PocketChallenge V2.\n\n## How to use\n\nLoad the ROM in an emulator or flash it to a flashcart and put it in your WonderSwan.\nThe program will go through all the tests and then write \"Ok\".\nIf run in an emulator and it doesn't emulate the WonderSwan CPU correctly,\nthe program will stop at the first failure and print out intput value/flags and  expected value/flags (and exception for division). Press A to try the next value or B to try the next test.\nYou use the X1-X4 to navigate the menus, A to select an option, B to go back.\n\n## Building\n\nI use nasm \u003chttps://nasm.us/\u003e by running \"nasm -f bin -o WSCpuTest.wsc WSCpuTest.asm\".\n\n## How do the undefined flags / opcodes work?\n\nThe flags marked as Undefined in the manual are always modified by the instructions, the flags are never kept as they were before the instruction.\nMost undefined opcodes are just 1 byte NOPs, the FPO1 (0xD8 - 0xDF) opcodes are 2 bytes NOPs.\n\n## Differences between ASWAN \u0026 SPHINX(2)\n\nThere is one difference between the SOCs and that is the Zero flag during Unsigned Multiplication, it's allways cleared on ASWAN and allways set on SPHINX(2).\n\n## How the tests works\n\n### AND, OR, XOR \u0026 TEST\n\nAuxCarry, Carry \u0026 Overflow are always cleared.\nParity, Sign \u0026 Zero are set according to result.\n\n### NOT\n\nNo flags are changed, all bits of result are inverted.\n\n### INC/DEC\n\nCarry is not changed.\nAuxCarry, Overflow, Parity, Sign \u0026 Zero are all set according to result (same as ADD/SUB 1).\n\n### ADD\n\nAuxCarry, Carry, Overflow, Parity, Sign \u0026 Zero are all set according to result.\n\n### SUB\n\nAuxCarry, Carry, Overflow, Parity, Sign \u0026 Zero are all set according to result.\n\n### CMP\n\nAuxCarry, Carry, Overflow, Parity, Sign \u0026 Zero are all set according to result.\nSame as SUB except there is no result.\n\n### ADC/ADDC\n\n### SBB/SUBC\n\n### NEG\n\nAuxCarry, Carry, Overflow, Parity, Sign \u0026 Zero are all set according to result.\nIt's the same as doing a SUB with the destination set to 0.\n\n### ROL\n\n```text\nAuxCarry, Parity, Sign \u0026 Zero are not changed.\nOverflow is set to xor of Carry value and bit 7/15 of result.\nNormaly:\n    Carry is set if the last shifted out bit was 1, otherwise cleared.\nIf the argument is \u0026 0x1F = zero, ie. no shift is taking place:\n    Carry is not changed.\n```\n\n### ROR\n\n```text\nAuxCarry, Parity, Sign \u0026 Zero are not changed.\nOverflow is set to xor of bit 6/14 \u0026 7/15 of result.\nNormaly:\n    Carry is set if the last shifted out bit was 1, otherwise cleared.\nIf the argument is \u0026 0x1F = zero, ie. no shift is taking place:\n    Carry is not changed.\n```\n\n### RCL/ROLC\n\n```text\nAuxCarry, Parity, Sign \u0026 Zero are not changed.\nOverflow is set to xor of Carry value and bit 7/15 of result.\nNormaly:\n    Carry is set if the last shifted out bit was 1, otherwise cleared.\nIf the argument is \u0026 0x1F = zero, ie. no shift is taking place:\n    Carry is not changed.\n```\n\n### RCR/RORC\n\n```text\nAuxCarry, Parity, Sign \u0026 Zero are not changed.\nOverflow is set to xor of bit 6/14 \u0026 7/15 of result.\nNormaly:\n    Carry is set if the last shifted out bit was 1, otherwise cleared.\nIf the argument is \u0026 0x1F = zero, ie. no shift is taking place:\n    Carry is not changed.\n```\n\n### SHL\n\n```text\nAuxCarry is always cleared.\nParity, Sign \u0026 Zero are set according to result.\nOverflow is set to xor of Carry value and bit 7/15 of result.\nNormaly:\n    Carry is set if the last shifted out bit was 1, otherwise cleared.\nIf the argument is \u0026 0x1F = zero, ie. no shift is taking place:\n    Carry is not changed.\n```\n\n### SHR\n\n```text\nAuxCarry is always cleared.\nParity, Sign \u0026 Zero are set according to result.\nOverflow is set to xor of bit 6/14 \u0026 7/15 of result (only possible with shift of 0 or 1).\nNormaly:\n    Carry is set if the last shifted out bit was 1, otherwise cleared.\nIf the argument is \u0026 0x1F = zero, ie. no shift is taking place:\n    Carry is not changed.\n```\n\n### SAR / SHRA\n\n```text\nAuxCarry is always cleared.\nParity, Sign \u0026 Zero are set according to result.\nOverflow is set to xor of bit 6/14 \u0026 7/15 of result (only possible with shift of 0).\nNormaly:\n    Carry is set if the last shifted out bit was 1, otherwise cleared.\nIf the argument is \u0026 0x1F = zero, ie. no shift is taking place:\n    Carry is not changed.\n```\n\n### MUL / MULU (unsigned multiplication, 8x8/16x16)\n\n```text\nAuxCarry, Parity \u0026 Sign are always cleared.\nOn Color/Crystal: Zero is always set.\nOn Mono: Zero is always cleared.\nCarry \u0026 Overflow are set if the result doesn't fit in 8/16 bits for 8/16bit multiplies.\n```\n\n### IMUL / MUL (signed multiplication, 8x8/16x16)\n\n```text\nAuxCarry, Parity \u0026 Sign are always cleared.\nZero is always set.\nCarry \u0026 Overflow are set if the result doesn't fit in 8/16 bits for 8/16bit multiplies.\n```\n\n### DIV / DIVU (unsigned division, 16/8)\n\n```text\nNormaly:\n    AuxCarry, Parity \u0026 Sign are always cleared.\n    Carry \u0026 Overflow are from the last multiplication.\n    Zero is set when remainder is zero and bit 0 of result is set.\nIf division exception:\n    AuxCarry, Parity \u0026 Sign are always cleared.\n    Carry \u0026 Overflow are from the last multiplication.\n    Zero is set in some weird way (not tested).\n    AX/AW is not modified.\n```\n\n### DIV / DIVU (unsigned division, 32/16)\n\n```text\nNormaly:\n    AuxCarry, Carry, Overflow, Parity, \u0026 Sign are always cleared.\n    Zero is set when remainder is zero and bit 0 of result is set.\nIf division exception:\n    AuxCarry, Carry, Overflow, Parity, \u0026 Sign are always cleared.\n    Zero is set in some weird way (not tested).\n    AX/AW, DX/DW is not modified.\n```\n\n### IDIV / DIV (signed division, 16/8)\n\n```text\nIf dividing 0x8000 by 0x00 you will not get a division exception but a result of 0x0081.\nNormaly:\n    AuxCarry, Carry \u0026 Overflow are cleared.\n    Parity, Sign \u0026 Zero are set according to result (AL).\nIf division exception:\n    AuxCarry, Parity \u0026 Sign are always cleared.\n    Carry \u0026 Overflow are from the last multiplication.\n    Zero is set in some weird way (not tested).\n    AX/AW is not modified.\n```\n\n### IDIV / DIV (signed division, 32/16)\n\n```text\nIf dividing 0x80000000 by 0x0000 you will not get a division exception but a result of 0x00008001.\nNormaly:\n    AuxCarry, Carry, Overflow, Parity \u0026 Sign are all cleared.\n    Zero is set when remainder is zero and bit 0 of result is set.\nIf division exception:\n    AuxCarry, Carry, Overflow, Parity \u0026 Sign are all cleared.\n    Zero is set in some weird way (not tested).\n    AX/AW, DX/DW is not modified.\n```\n\n### AAM / CVTBD (8/8)\n\n```text\nThe AAM opcode is a 2 byte opcode, and the second byte can be any value not just 10. So it's basically a byte by byte divide though the result is in AH and remainder in AL.\nNormaly:\n    AuxCarry, Carry \u0026 Overflow are cleared.\n    Parity, Sign \u0026 Zero are set according to result (of AL, remainder).\nIf division exception:\n    AuxCarry, Parity \u0026 Sign are always cleared.\n    Carry \u0026 Overflow are from the last multiplication.\n    Zero is set if bit 6 or 7 of AL is set (AL \u003e 0x3F).\n    AL, AX/AW is not modified.\n```\n\n### AAD / CVTDB (8x8+8)\n\nThe AAD opcode just as the AAM opcode is a 2 byte opcode, and the second byte can be any value not just 10. So this is a byte by byte multiplication plus byte addition. The answear is only in AL, AH is always zero. Flags are calculated only from the add after the multiplication, the flags are exactly like a normal add.\n\n### DAA / ADJ4A\n\nAll flags are the same as a normal addition except that AuxCarry \u0026 Carry are never cleared.\n\n### DAS / ADJ4S\n\nCompare is done for AL \u003e 0x99 first and then lower nybble ((AL \u0026 0xF) \u003e 0x9).\nAuxCarry \u0026 Carry can only be set from the comparison, not the adjustment,\n(S, Z \u0026 V are set from the ajustment).\nSame calculation as DAA except it does a subtraction instead of an addition.\n\n### AAA / ADJBA\n\nOverflow is always cleared. Parity is always set.\nAuxCarry, Carry \u0026 Zero are set if AuxCarry is set before or (AL \u0026 0xF) \u003e 0x9.\nSign is set when AuxCarry (, Carry \u0026 Zero) is not set.\nAL is always masked to lower nybble.\n\n### AAS / ADJBS\n\nOverflow is always cleared.\nParity is always set.\nAuxCarry, Carry \u0026 Zero are set if AuxCarry is set before or (AL \u0026 0xF) \u003e 0x9.\nSign is set when AuxCarry (, Carry \u0026 Zero) is not set.\nAL is always masked to lower nybble.\n\n### PUSH/POP SP to/from stack\n\n```code\nPUSH SP\n{\n    SP      = SP - 2\n    [SS:SP] = SP\n}\n\nPOP SP\n{\n    SP = [SS:SP]\n}\n```\n\n## BOUND / CHKIND\n\nComparison of values are done with signed values.\n\n## Undefined opcodes\n\n### 0x0F\n\nThis opcode is not \"POP CS\" or Group3 it's just a 1 byte NOP (1 cycle).\n\n### 0x63, 0x64, 0x65, 0x66, 0x67\n\nThese opcodes doesn't do anything, they are just 1 byte NOPs (1 cycle).\n\n### 0x8C,0xF8 / 0x8E,0xF8\n\nThis is to test that bit 5 (0x20) does not affect which segment register is accessed.\n\n### 0x8D,0xC8 - 0x8D,0xCF (LEA cx)\n\n```text\nThis is the LEA instruction but with address mode set to register.\nIt doesn't use the registers directly but instead gives you a couple of new addressing modes.\nThe low 3 bits are mapped like this:\n0x0 = [ds:bx + ax]\n0x1 = [ds:bx + cx]\n0x2 = [ss:bp + dx]\n0x3 = [ss:bp + bx]\n0x4 = [ds:si + sp]\n0x5 = [ds:di + bp]\n0x6 = [ss:bp + si]\n0x7 = [ds:bx + di]\n```\n\n### 0x9B (WAIT / POLL)\n\nOn the WonderSwan it doesn't wait or cause exception, the POLL pin is probably held low at all times, works as a 1 byte NOP (9 cycles).\n\n### 0xC0,0xF0,0x## (SAL al, ##)\n\nThis doesn't work as Shift Arithmetic Left but instead zeros al.\n\n### 0xC1,0xF0,0x## (SAL ax, ##)\n\nThis doesn't work as Shift Arithmetic Left but instead zeros ax.\n\n### 0xC4,0xD8 - 0xC4,0xDF (LES bx)\n\nThis is the LES instruction but with address mode set to register. It doesn't use the registers directly but instead uses the same new addressing modes as LEA.\n\n### 0xC5,0xD8 - 0xC5,0xDF (LDS bx)\n\nThis is the LDS instruction but with address mode set to register. It doesn't use the registers directly but instead uses the same new addressing modes as LEA.\n\n### 0xD6 (SALC)\n\nThis is a one byte opcode called SALC, it sets AL to either 0x00 or 0xFF depending on if Carry is set or not (8 cycles). Though I couldn't get STC to set carry before the SALC...\n\n### 0xD8 - 0xDF\n\nThese opcodes are called FPO on other NEC Vx0 CPUs, used to communicate with an FPU. On the V30MZ they are 2 byte NOPs (1 cycle).\n\n### 0xF1\n\nIt doesn't look like it's a simple INT1 as I couldn't get a test to work, it looks like it might be BRKS from NEC V25/V35 or at least that it switches the MD flag. This app doesn't test it, if someone can write a test that works please contact me.\n\n### 0xF6,0xC8 / 0xF7,0xC8 (TEST)\n\nThis doesn't seem to change flags or registers (1 cycle).\n\n### 0xFE,0xD0 - 0xFE,0xF0\n\nDoes the same as 0xFF variants (CALL, BRA \u0026 PUSH).\n\n### 0xFF,0xF8 (PUSH AX?)\n\nThis doesn't seem to do anything.\n\n### 0xFF,0xD8 - 0xFF,0xDF (CALL far)\n\nThis is the CALL far instruction but with address mode set to register. It doesn't use the registers directly but instead uses the same new addressing modes as LEA. I can't really write out if it fails since people had different ideas on how it worked (ie where it called), the mostly likely event is that the rom locks, crashes or restarts if it fails.\n\n### 0xFF,0xE8 - 0xFF,0xEF (BRA/JMP far)\n\nThis is the BRA/JMP far instruction but with address mode set to register. It doesn't use the registers directly but instead uses the same new addressing modes as LEA. I can't really write out if it fails since people had different ideas on how it worked (ie where it branched), the mostly likely event is that the rom locks, crashes or restarts if it fails.\n\n## Controls\n\nUse WS X1-X4 to navigate the menus. A to select/continue failed test, B to go back/skip failed test.\n\n## Credits\n\nFredrik Ahlström\n\nTwitter @TheRealFluBBa\n\n\u003chttps://github.com/FluBBaOfWard/WSCpuTest\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFluBBaOfWard%2FWSCPUTest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FFluBBaOfWard%2FWSCPUTest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFluBBaOfWard%2FWSCPUTest/lists"}