mirror of
https://github.com/KarolS/millfork.git
synced 2026-04-22 00:17:03 +00:00
Many big important things:
– Add support for undocumented 8085 instructions – Convert undocumented 8085 instructions to 8086 – Add new CPU types and categorize CPU types correctly – Fix macro expansion in some situations – Improve 8080 optimizations – Improve documentation – Other improvements
This commit is contained in:
@@ -70,6 +70,32 @@ Original Z80 processors accidentally supported a bunch of extra undocumented ins
|
||||
Millfork will not emit them.
|
||||
The only exception is SLL, which will be emitted if it occurs in a handwritten assembly block.
|
||||
|
||||
## 8085
|
||||
|
||||
Since various assemblers use different mnemonics for undocumented opcodes,
|
||||
Millfork supports multiple mnemonics per opcode. The default one is given first:
|
||||
|
||||
Intel syntax | Zilog syntax
|
||||
**DSUB** | **DSUB**
|
||||
**ARHL**, RRHL | **SRA HL**
|
||||
**RLDE**, RDEL | **RL DE**
|
||||
**LDHI n** | **LD DE,(HL+n)**
|
||||
**LDSI n** | **LD DE,(SP+n)**
|
||||
**LHLX** | **LD HL,(DE)**
|
||||
**SHLX** | **LD (DE),HL**
|
||||
**JK n**, JX5 n | **JP K,n**; JP X5,n
|
||||
**JNK n**, JNX5 n | **JP NK,n**; JP NX5,n
|
||||
**RSTV**, OVRST8 | **RSTV**
|
||||
|
||||
|
||||
|
||||
#### Generation
|
||||
|
||||
If enabled, The compiler will only emit the following undocumented instructions from Millfork code:
|
||||
DSUB, LHLX, SHLX, LDSI, LDHI
|
||||
|
||||
The optimizer does not track the K and V flags. Use `JK`, `JNK` and `RSTV` with care.
|
||||
|
||||
## 8086
|
||||
|
||||
Undocumented instructions are not supported.
|
||||
|
||||
@@ -83,15 +83,16 @@ This may cause problems if the parameter table is stored next to a hardware regi
|
||||
Whether the compiler should allow for invalid characters in string/character literals that use the default encodings and replace them with alternatives.
|
||||
`.ini` equivalent: `lenient_encoding`. Default: yes on Apple II, no otherwise.
|
||||
|
||||
* `-fillegals`, `-fno-illegals` – Whether should emit illegal (undocumented) NMOS or Z80 opcodes.
|
||||
* `-fillegals`, `-fno-illegals` – Whether should emit illegal (undocumented) NMOS 6502, Intel 8085 or Z80 opcodes.
|
||||
`.ini` equivalent: `emit_illegals`.
|
||||
Default: no.
|
||||
|
||||
#### 6502-related
|
||||
|
||||
* `-fcmos-ops`, `-fno-cmos-ops` – Whether should emit CMOS opcodes.
|
||||
* `-fcmos-ops`, `-fno-cmos-ops` – Whether should emit 65C02 opcodes.
|
||||
`.ini` equivalent: `emit_cmos`.
|
||||
Default: yes if targeting a 65C02-compatible architecture, no otherwise.
|
||||
|
||||
* `-f65ce02-ops`, `-fno-65ce02-ops` – Whether should emit 65CE02 opcodes.
|
||||
`.ini` equivalent: `emit_65ce026`.
|
||||
Default: yes if targeting 65CE02, no otherwise.
|
||||
@@ -128,13 +129,21 @@ Use a software stack for stack variables.
|
||||
|
||||
#### 8080/Z80-related
|
||||
|
||||
* `-f8085-ops`, `-fno-8085-ops` – Whether should emit Intel 8085 opcodes.
|
||||
`.ini` equivalent: `emit_8085`.
|
||||
Default: yes if targeting Intel 8085 architecture, no otherwise.
|
||||
|
||||
* `-fz80-ops`, `-fno-z80-ops` – Whether should emit Z80 opcodes.
|
||||
`.ini` equivalents: `emit_z80` and `emit_x80`.
|
||||
Default: yes if targeting a Z80-compatible architecture, no otherwise.
|
||||
|
||||
* `-fshadow-irq`, `-fno-shadow-irq` –
|
||||
Whether the interrupt routines should make use of Z80 shadow registers.
|
||||
`.ini` equivalent: `use_shadow_registers_for_irq`. Default: yes on Z80, no otherwise.
|
||||
|
||||
* `-fuse-ix-for-stack`, `-fuse-iy-for-stack`, `-fno-use-index-for-stack` –
|
||||
Which of Z80 index registers should be used for accessing stack variables, if any.
|
||||
`.ini` equivalent: `ix_stack` and `iy_stack`. Default: IX on Z80 and 8086, no otherwise.
|
||||
`.ini` equivalent: `ix_stack` and `iy_stack`. Default: IX on Z80, no otherwise.
|
||||
|
||||
* `-fuse-ix-for-scratch`, `-fno-use-ix-for-scratch` –
|
||||
Allow using the IX register for other purposes.
|
||||
@@ -144,6 +153,11 @@ Allow using the IX register for other purposes.
|
||||
Allow using the IY register for other purposes.
|
||||
`.ini` equivalent: `iy_scratch`. Default: no.
|
||||
|
||||
#### 8086-related
|
||||
|
||||
Compiling to 8086 is based on translating from a mix of 8085 and Z80 instructions to 8086.
|
||||
See [the 8086 support disclaimer](./../lang/x86disclaimer.md).
|
||||
|
||||
## Optimization options
|
||||
|
||||
* `-O0` – Disable all optimizations except unused global symbol removal.
|
||||
|
||||
@@ -29,18 +29,21 @@ if a line ends with a backslash character, the value continues to the next line.
|
||||
|
||||
* `z80` (Zilog Z80)
|
||||
|
||||
* `strictz80` (Z80 without illegal instructions)
|
||||
|
||||
* `i8080` (Intel 8080)
|
||||
|
||||
* `i8085` (Intel 8085)
|
||||
|
||||
* `strict8085` (Intel 8085 without illegal instructions)
|
||||
|
||||
* `gameboy` (Sharp LR35902; experimental)
|
||||
|
||||
* `i8086` (Intel 8086; very experimental, very buggy and very, very incomplete –
|
||||
see the [8086 support disclaimer](../lang/x86disclaimer.md))
|
||||
|
||||
* `encoding` – default encoding for console I/O, one of
|
||||
`ascii`, `pet`/`petscii`, `petscr`/`cbmscr`, `atascii`, `bbc`, `jis`/`jisx`, `apple2`,
|
||||
`iso_de`, `iso_no`/`iso_dk`, `iso_se`/`iso_fi`, `iso_yu`. Default: `ascii`
|
||||
* `encoding` – default encoding for console I/O. Default: `ascii`.
|
||||
See [the list of available encodings](../lang/text.md).
|
||||
|
||||
* `screen_encoding` – default encoding for screencodes (literals with encoding specified as `scr`).
|
||||
Default: the same as `encoding`.
|
||||
@@ -51,12 +54,18 @@ Default: the same as `encoding`.
|
||||
|
||||
* `emit_illegals` – whether the compiler should emit illegal instructions, default `false`
|
||||
|
||||
* `emit_cmos` – whether the compiler should emit CMOS instructions, default is `true` on compatible processors and `false` elsewhere
|
||||
* `emit_cmos` – whether the compiler should emit 65C02 instructions, default is `true` on compatible processors and `false` elsewhere
|
||||
|
||||
* `emit_65816` – which 65816 instructions should the compiler emit, either `no`, `emulation` or `native`
|
||||
|
||||
* `decimal_mode` – whether the compiler should emit decimal instructions, default is `false` on `ricoh` and `strictricoh` and `true` elsewhere;
|
||||
if disabled, a software decimal mode will be used
|
||||
|
||||
* `emit_8085` – whether the compiler should emit Intel 8085 instructions, default is `true` on compatible processors and `false` elsewhere
|
||||
|
||||
* `emit_x80` – whether the compiler should emit instructions present on Sharp LR35902 and Z80, but absent on Intel 8080, default is `true` on compatible processors and `false` elsewhere
|
||||
|
||||
* `emit_z80` – whether the compiler should emit Zilog Z80 instructions not covered by `emit_x80`, default is `true` on compatible processors and `false` elsewhere
|
||||
|
||||
* `ro_arrays` – (deprecated) whether the compiler should warn upon array writes, default is `false`
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ The following features are defined based on the chosen CPU and compilation optio
|
||||
|
||||
* `ARCH_X86` – 1 if compiling for Intel 8086-like processor, 0 otherwise
|
||||
|
||||
* `CPU_65C02`, `CPU_65CE02`, `CPU_65816`, `CPU_HUC6280`, `CPU_8080`, `CPU_GAMEBOY`, `CPU_Z80`
|
||||
* `CPU_65C02`, `CPU_65CE02`, `CPU_65816`, `CPU_HUC6280`, `CPU_8080`, `CPU_8085`, `CPU_GAMEBOY`, `CPU_Z80`, `CPU_8086`
|
||||
– 1 if compiling for the exact given processor, 0 otherwise
|
||||
|
||||
* `CPU_6502` – 1 if compiling for any pre-65C02 6502-like processor, 0 otherwise
|
||||
@@ -48,8 +48,8 @@ The following features are defined based on the chosen CPU and compilation optio
|
||||
* `CPUFEATURE_DECIMAL_MODE` – 1 if decimal mode is enabled, 0 otherwise
|
||||
|
||||
* `CPUFEATURE_65C02`, `CPUFEATURE_65CE02`, `CPUFEATURE_HUC6280`, `CPUFEATURE_65816_EMULATION`, `CPUFEATURE_65816_NATIVE`,
|
||||
`CPUFEATURE_8080`, `CPUFEATURE_GAMEBOY`, `CPUFEATURE_Z80`,
|
||||
`CPUFEATURE_6502_ILLEGALS`, `CPUFEATURE_Z80_ILLEGALS` – 1 if given instruction subset is enabled, 0 otherwise
|
||||
`CPUFEATURE_8080`, `CPUFEATURE_8085`, `CPUFEATURE_GAMEBOY`, `CPUFEATURE_Z80`,
|
||||
`CPUFEATURE_6502_ILLEGALS`, `CPUFEATURE_8085_ILLEGALS`, `CPUFEATURE_Z80_ILLEGALS` – 1 if given instruction subset is enabled, 0 otherwise
|
||||
|
||||
* `OPTIMIZE_FOR_SIZE`, `OPTIMIZE_FOR_SPEED`, `OPTIMIZE_INLINE`, `OPTIMIZE_IPO`
|
||||
– 1 if given optimization setting is enabled, 0 otherwise
|
||||
@@ -58,13 +58,13 @@ The following features are defined based on the chosen CPU and compilation optio
|
||||
|
||||
* `USES_ZPREG` – 1 if the zeropage pseudoregister is used, 0 otherwise
|
||||
|
||||
* `ZPREG_SIZE` – size of the pseudoregister in bytes
|
||||
* `ZPREG_SIZE` – size of the pseudoregister in bytes, or 0 on platforms that don't use it
|
||||
|
||||
* `USES_IX_STACK`, `USES_IY_STACK` – 1 if given index register is used as a base pointer for stack-allocated variables, 0 otherwise
|
||||
|
||||
* `USES_SHADOW_REGISTERS` – 1 if interrupts preserve old registers in the shadow registers, 0 otherwise
|
||||
* `USES_SHADOW_REGISTERS` – 1 if interrupts preserve old registers in the shadow registers, 0 if they do it on stack
|
||||
|
||||
* `USES_SOFTWARE_STACK` – 1 if using software stack for variables, 0 otherwise
|
||||
* `USES_SOFTWARE_STACK` – 1 if using software stack for variables (6502-like targets only), 0 otherwise
|
||||
|
||||
### Commonly used features
|
||||
|
||||
@@ -152,6 +152,7 @@ To use such value in other files, consider this:
|
||||
### `#pragma`
|
||||
|
||||
Changes the behaviour of the parser for the current file.
|
||||
The change applies to the whole file, regardless of where the directive is located.
|
||||
|
||||
* `#pragma intel_syntax` – interpret assembly using Intel syntax
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
Millfork does not support Intel 8086 directly.
|
||||
Instead, it generates Intel 8080 code and translates it automatically to 8086 machine code.
|
||||
For convenience, Z80 instructions using `IX` are also translated.
|
||||
For convenience, most undocumented 8085 instructions and Z80 instructions using `IX` are also translated.
|
||||
|
||||
This means that:
|
||||
|
||||
@@ -12,8 +12,9 @@ This means that:
|
||||
|
||||
* there is no support for writing 8086 assembly;
|
||||
|
||||
* Millfork currently translates majority of Intel 8080 assembly instructions to 8086 machine code,
|
||||
so you can write 8080/Z80 assembly instead.
|
||||
* Millfork currently translates majority of Intel 8085 assembly instructions to 8086 machine code,
|
||||
so you can write 8080/Z80 assembly instead.
|
||||
Instructions `RST` (8080), `RIM`, `SIM` (8085), `RSTV`, `ARHL`, `RLDE` (8085 undocumented) are not supported.
|
||||
|
||||
For example, code like
|
||||
|
||||
@@ -41,6 +42,18 @@ is compiled to
|
||||
|
||||
Generated assembly output uses Intel 8086 syntax.
|
||||
|
||||
#### Configuring code generation
|
||||
|
||||
There are three options that influence the 8086 code generation:
|
||||
|
||||
* `ix_stack` (command line equivalent `-fuse-ix-for-stack` for enabling, `-fno-use-index-for-stack` for disabling)
|
||||
|
||||
* `emit_8085` (command line equivalent `-f8085-ops` for enabling, `-fno-8085-ops` for disabling)
|
||||
|
||||
* `emit_illegals` (command line equivalent `-fillegals` for enabling, `-fno-illegals` for disabling)
|
||||
|
||||
`emit_8085` and `emit_illegals` have effect only together.
|
||||
|
||||
#### Major deficiencies of generated code
|
||||
|
||||
* hardware multiplication is not used
|
||||
@@ -51,6 +64,9 @@ Generated assembly output uses Intel 8086 syntax.
|
||||
|
||||
* the overflow flag is not used
|
||||
|
||||
* signed comparisons are suboptimal and as buggy as on 8080
|
||||
(8085 has the undocumented K flag that could be used here, but Millfork does not use it)
|
||||
|
||||
* `DAS` is not used
|
||||
|
||||
* conditional jumps are never optimized to short 2-byte jumps and always use 5 bytes
|
||||
@@ -74,5 +90,15 @@ The registers are translated as following:
|
||||
SP → SP
|
||||
IX → BP
|
||||
|
||||
The `SI` register is used as a temporary register for holding the address in `LDAX`/`STAX`
|
||||
(`LD (DE),A`/`LD(BC),A`/`LD A,(DE)`/`LD A,(BC)` on Z80).
|
||||
The `SI` register is used as a temporary register for holding the address in 8080's `LDAX`/`STAX`
|
||||
(`LD (DE),A`/`LD(BC),A`/`LD A,(DE)`/`LD A,(BC)` on Z80)
|
||||
and 8085's undocumented `LDSI`/`SHLX`/`LHLX` (`LD DE,SP+n`/`LD (DE),HL`/`LD HL,(DE)` in Z80 syntax).
|
||||
|
||||
The `DI` register is currently not used.
|
||||
|
||||
#### Future development
|
||||
|
||||
There won't be any major future development related to 8086 support,
|
||||
unless a full 8086 backend that is independent from the 8080 backend is created.
|
||||
|
||||
The current solution was developed only as a proof of concept.
|
||||
|
||||
Reference in New Issue
Block a user