Live data from Hacker News

Reverse-engineering the division microcode in the Intel 8086 processor

righto.com

21–29 of 29 posts

Re: Reverse-engineering the division microcode in the Intel 8086 processor

#21
post #16

Earlier quoted context omitted.

>almost everything on a modern CPU uses "microcode" of some kind, although the term gets kind of hazy µOps are different from the kind of microcode described here. Older x86 CPUs basically had a "bytecode interpreter" in microcode ROM, every instruction (except for some trivial set/clear flag operations) would go to a specific entry point, and even something simple like addition would take at least two µ-instrs. The…

Edit: just saw your edit, that's something I'd never really thought about before - 8086 is the "purest" microcoded processor from the x86 series, in that every instruction runs through an actual interpreter rather than some form of fixed-function instruction issue unit! In the case of integer division, I think that it's also the "true" kind of microcoded instruction on many modern CPUs. That is to say, the instructio…

While division may still decode to multiple uOps, I seriously doubt that there's a loop in microcode on modern processors. The pipeline latency makes that infeasible.

The looping logic is almost certainly a bit of fixed function hardware in the execution unit.

Re: Reverse-engineering the division microcode in the Intel 8086 processor

#22
post #21
post #16

Earlier quoted context omitted.

Edit: just saw your edit, that's something I'd never really thought about before - 8086 is the "purest" microcoded processor from the x86 series, in that every instruction runs through an actual interpreter rather than some form of fixed-function instruction issue unit! In the case of integer division, I think that it's also the "true" kind of microcoded instruction on many modern CPUs. That is to say, the instructio…

While division may still decode to multiple uOps, I seriously doubt that there's a loop in microcode on modern processors. The pipeline latency makes that infeasible. The looping logic is almost certainly a bit of fixed function hardware in the execution unit.

Hmm. This gets into the fuzzy definition of "loop in microcode" depending on how you look at the system. I don't think the actual looping happens in microcode, that is, it's not like the ucode unit jumps to earlier ucode - this wouldn't make sense architecturally for a variety of reasons.

However, in the case of 64-bit integer division on mid-aged Intel processors (for example, Kaby Lake), I do think that division is both iterative and microcoded (versus fixed-function logic), but that the ucode emits an _unrolled_ loop into the scheduler.

IDIV with 64-bit operands on Kaby Lake takes 56/57 uOps (!) vs the still-huge 11 uOps for 32-bit IDIV. (for comparison, we're down to 5/4 uOps for 64-bit division on Alder Lake).

Re: Reverse-engineering the division microcode in the Intel 8086 processor

#23
post #22
post #21

Earlier quoted context omitted.

While division may still decode to multiple uOps, I seriously doubt that there's a loop in microcode on modern processors. The pipeline latency makes that infeasible. The looping logic is almost certainly a bit of fixed function hardware in the execution unit.

Hmm. This gets into the fuzzy definition of "loop in microcode" depending on how you look at the system. I don't think the actual looping happens in microcode, that is, it's not like the ucode unit jumps to earlier ucode - this wouldn't make sense architecturally for a variety of reasons. However, in the case of 64-bit integer division on mid-aged Intel processors (for example, Kaby Lake), I do think that division is…

Take a look at Agner Fog's https://www.agner.org/optimize/instruction_tables.pdf

For example, Zen4 64-bit DIV is listed as: 2 uOps, 10-18 cycles latency, 7-12 cycles inverse throughput.

This suggests uOps with variable execution lengths, i.e. iteration happening in the execution unit and not just a fixed unrolled loop streamed by the microcode part of the frontend.

You may be right that there were some CPUs that did the fixed unrolling, but it doesn't seem that common.

Re: Reverse-engineering the division microcode in the Intel 8086 processor

#24
post #23
post #22

Earlier quoted context omitted.

Hmm. This gets into the fuzzy definition of "loop in microcode" depending on how you look at the system. I don't think the actual looping happens in microcode, that is, it's not like the ucode unit jumps to earlier ucode - this wouldn't make sense architecturally for a variety of reasons. However, in the case of 64-bit integer division on mid-aged Intel processors (for example, Kaby Lake), I do think that division is…

Take a look at Agner Fog's https://www.agner.org/optimize/instruction_tables.pdf For example, Zen4 64-bit DIV is listed as: 2 uOps, 10-18 cycles latency, 7-12 cycles inverse throughput. This suggests uOps with variable execution lengths, i.e. iteration happening in the execution unit and not just a fixed unrolled loop streamed by the microcode part of the frontend. You may be right that there were some CPUs that did…

My understanding is that there can be both. That the execution pipes themselves on some implementations have a 'nanocode' for stuff like cordics and maybe division who's execution streams are kicked off from the one or two high level uOps that the instruction decoder emits.

Re: Reverse-engineering the division microcode in the Intel 8086 processor

#25
> Signed multiplication and division use an internal flag called F1 to keep track of the sign. The F1 flag is toggled by microcode through the CF1 (Complement F1) micro-instruction. The F1 flag is implemented with a flip-flop, along with a multiplexer to select the value. It is cleared when a new instruction starts, set by a REP prefix, and toggled by the CF1 micro-instruction.

Does this mean that one can run 'REP DIV' and get a negated quotient?

Re: Reverse-engineering the division microcode in the Intel 8086 processor

#26

> Signed multiplication and division use an internal flag called F1 to keep track of the sign. The F1 flag is toggled by microcode through the CF1 (Complement F1) micro-instruction. The F1 flag is implemented with a flip-flop, along with a multiplexer to select the value. It is cleared when a new instruction starts, set by a REP prefix, and toggled by the CF1 micro-instruction. Does this mean that one can run 'REP DI…

Yes, REP IDIV will negate the quotient. Andrew Jenner discusses that: https://www.reenigne.org/blog/8086-microcode-disassembled/

Re: Reverse-engineering the division microcode in the Intel 8086 processor

#28
post #10
post #9

Earlier quoted context omitted.

Pretty sure some of the low-end Cortex-M cores (M0 and M1) lacks instructions for division.

Good point, it's not in v6M, though it is in v8M baseline, which is the v8 equivalent. So M0, M0+ and M1 don't have it but I think everything else M-profile should.

Given that Ken said most ARM processors, the nerd sniping becomes: what percentage of all ARM cores are M0/M0+/M1. I'd guess a lot (maybe not half though). Don't all micro SD cards have a processor inside them? They're probably almost all ARM...

Re: Reverse-engineering the division microcode in the Intel 8086 processor

#29
post #26

> Signed multiplication and division use an internal flag called F1 to keep track of the sign. The F1 flag is toggled by microcode through the CF1 (Complement F1) micro-instruction. The F1 flag is implemented with a flip-flop, along with a multiplexer to select the value. It is cleared when a new instruction starts, set by a REP prefix, and toggled by the CF1 micro-instruction. Does this mean that one can run 'REP DI…

Yes, REP IDIV will negate the quotient. Andrew Jenner discusses that: https://www.reenigne.org/blog/8086-microcode-disassembled/

That's fascinating. Thanks for the pointer.
Post reply on HN