changeset 550:96489fb27dbf

Apart from the Z80 core, BlastEm now supports 32-bit x86
author Michael Pavone <pavone@retrodev.com>
date Wed, 19 Feb 2014 00:22:27 -0800
parents 32da1e0d5e55
children 16ee0937c676
files Makefile gen_x86.c gen_x86.h m68k_to_x86.c runtime_32.S
diffstat 5 files changed, 247 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Tue Feb 18 23:19:07 2014 -0800
+++ b/Makefile	Wed Feb 19 00:22:27 2014 -0800
@@ -22,8 +22,18 @@
 CPU:=$(shell uname -m)
 endif
 
+
+
 TRANSOBJS=gen_x86.o x86_backend.o mem.o
-M68KOBJS=68kinst.o m68k_to_x86.o runtime.o
+M68KOBJS=68kinst.o m68k_to_x86.o
+ifeq ($(CPU),x86_64)
+M68kOBJS+= runtime.o
+else
+ifeq ($(CPU),i686)
+M68KOBJS+= runtime_32.o
+endif
+endif
+
 Z80OBJS=z80inst.o z80_to_x86.o zruntime.o
 AUDIOOBJS=ym2612.o psg.o wave.o
 CONFIGOBJS=config.o tern.o util.o
--- a/gen_x86.c	Tue Feb 18 23:19:07 2014 -0800
+++ b/gen_x86.c	Wed Feb 19 00:22:27 2014 -0800
@@ -1756,7 +1756,7 @@
 			disp >>= 8;
 			*(out++) = disp;
 		} else {
-			printf("%p - %p = %lX\n", dest, out + 6, disp);
+			printf("%p - %p = %lX\n", dest, out + 6, (long)disp);
 			return NULL;
 		}
 	}
@@ -1781,7 +1781,7 @@
 			disp >>= 8;
 			*(out++) = disp;
 		} else {
-			printf("%p - %p = %lX\n", dest, out + 6, disp);
+			printf("%p - %p = %lX\n", dest, out + 6, (long)disp);
 			return NULL;
 		}
 	}
@@ -1813,7 +1813,7 @@
 		*(out++) = disp;
 	} else {
 		//TODO: Implement far call???
-		printf("%p - %p = %lX\n", fun, out + 5, disp);
+		printf("%p - %p = %lX\n", fun, out + 5, (long)disp);
 		return NULL;
 	}
 	return out;
--- a/gen_x86.h	Tue Feb 18 23:19:07 2014 -0800
+++ b/gen_x86.h	Wed Feb 19 00:22:27 2014 -0800
@@ -57,6 +57,12 @@
 	SZ_Q
 } x86_size;
 
+#ifdef X86_64
+#define SZ_PTR SZ_Q
+#else
+#define SZ_PTR SZ_D
+#endif
+
 enum {
 	MODE_REG_INDIRECT = 0,
 	MODE_REG_INDEXED = 4,
--- a/m68k_to_x86.c	Tue Feb 18 23:19:07 2014 -0800
+++ b/m68k_to_x86.c	Wed Feb 19 00:22:27 2014 -0800
@@ -3371,7 +3371,11 @@
 		break;
 	case M68K_ILLEGAL:
 		dst = call(dst, opts->save_context);
-		dst = mov_rr(dst, CONTEXT, RDI, SZ_Q);
+#ifdef X86_64
+		dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR);
+#else
+		dst = push_r(dst, CONTEXT);
+#endif
 		dst = call(dst, (uint8_t *)print_regs_exit);
 		break;
 	case M68K_MOVE_FROM_SR:
@@ -3606,7 +3610,11 @@
 		break;
 	case M68K_RESET:
 		dst = call(dst, opts->save_context);
-		dst = mov_rr(dst, CONTEXT, RDI, SZ_Q);
+#ifdef X86_64
+		dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR);
+#else
+		dst = push_r(dst, CONTEXT);
+#endif
 		dst = call(dst, (uint8_t *)print_regs_exit);
 		break;
 	case M68K_ROL:
@@ -4108,6 +4116,9 @@
 			}
 			if (address >= 0x400000 && address < 0xE00000) {
 				dst = xor_rr(dst, RDI, RDI, SZ_D);
+#ifdef X86_32
+				dst = push_r(dst, RDI);
+#endif
 				dst = call(dst, (uint8_t *)exit);
 				break;
 			}
@@ -4237,9 +4248,16 @@
 			uint8_t * rdst = options->retrans_stub = options->cur_code;
 			rdst = call(rdst, options->save_context);
 			rdst = push_r(rdst, CONTEXT);
+#ifdef X86_32
+			rdst = push_r(rdst, CONTEXT);
+			rdst = push_r(rdst, SCRATCH2);
+#endif
 			rdst = call(rdst, (uint8_t *)m68k_retranslate_inst);
+#ifdef X86_32
+			rdst = add_ir(rdst, 8, RSP, SZ_D);
+#endif
 			rdst = pop_r(rdst, CONTEXT);
-			rdst = mov_rr(rdst, RAX, SCRATCH1, SZ_Q);
+			rdst = mov_rr(rdst, RAX, SCRATCH1, SZ_PTR);
 			rdst = call(rdst, options->load_context);
 			rdst = jmp_r(rdst, SCRATCH1);
 			options->cur_code = rdst;
@@ -4275,10 +4293,18 @@
 		//Save context and call breakpoint handler
 		dst = call(dst, opts->save_context);
 		dst = push_r(dst, SCRATCH1);
-		dst = mov_rr(dst, CONTEXT, RDI, SZ_Q);
+#ifdef X86_64
+		dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR);
 		dst = mov_rr(dst, SCRATCH1, RSI, SZ_D);
+#else
+		dst = push_r(dst, SCRATCH1);
+		dst = push_r(dst, CONTEXT);
+#endif
 		dst = call(dst, bp_handler);
-		dst = mov_rr(dst, RAX, CONTEXT, SZ_Q);
+#ifdef X86_32
+		dst = add_ir(dst, 8, RSP, SZ_D);
+#endif
+		dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR);
 		//Restore context
 		dst = call(dst, opts->load_context);
 		dst = pop_r(dst, SCRATCH1);
@@ -4290,7 +4316,7 @@
 		*jmp_off = dst - (jmp_off+1);
 		//jump back to body of translated instruction
 		dst = pop_r(dst, SCRATCH1);
-		dst = add_ir(dst, check_int_size - (native-start_native), SCRATCH1, SZ_Q);
+		dst = add_ir(dst, check_int_size - (native-start_native), SCRATCH1, SZ_PTR);
 		dst = jmp_r(dst, SCRATCH1);
 		opts->cur_code = dst;
 	} else {
@@ -4375,10 +4401,11 @@
 		if(memmap[chunk].buffer && memmap[chunk].flags & access_flag) {
 			if (memmap[chunk].flags & MMAP_PTR_IDX) {
 				if (memmap[chunk].flags & MMAP_FUNC_NULL) {
-					dst = cmp_irdisp8(dst, 0, CONTEXT, offsetof(m68k_context, mem_pointers) + sizeof(void*) * memmap[chunk].ptr_index, SZ_Q);
+					dst = cmp_irdisp8(dst, 0, CONTEXT, offsetof(m68k_context, mem_pointers) + sizeof(void*) * memmap[chunk].ptr_index, SZ_PTR);
 					uint8_t * not_null = dst+1;
 					dst = jcc(dst, CC_NZ, dst+2);
 					dst = call(dst, opts->save_context);
+#ifdef X86_64
 					if (is_write) {
 						if (SCRATCH2 != RDI) {
 							dst = mov_rr(dst, SCRATCH2, RDI, SZ_D);
@@ -4395,12 +4422,23 @@
 					uint8_t *no_adjust = dst+1;
 					dst = jmp(dst, dst+2);
 					*adjust_rsp = dst - (adjust_rsp + 1);
-					dst = sub_ir(dst, 8, RSP, SZ_Q);
+					dst = sub_ir(dst, 8, RSP, SZ_PTR);
 					dst = call(dst, cfun);
-					dst = add_ir(dst, 8, RSP, SZ_Q);
+					dst = add_ir(dst, 8, RSP, SZ_PTR);
 					*no_adjust = dst - (no_adjust + 1);
+#else
 					if (is_write) {
-						dst = mov_rr(dst, RAX, CONTEXT, SZ_Q);
+						dst = push_r(dst, SCRATCH1);
+					} else {
+						dst = push_r(dst, CONTEXT);//save CONTEXT for later
+					}
+					dst = push_r(dst, CONTEXT);
+					dst = push_r(dst, is_write ? SCRATCH2 : SCRATCH1);
+					dst = call(dst, cfun);
+					dst = add_ir(dst, is_write ? 12 : 8, RSP, SZ_D);
+#endif
+					if (is_write) {
+						dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR);
 					} else {
 						dst = pop_r(dst, CONTEXT);
 						dst = mov_rr(dst, RAX, SCRATCH1, size);
@@ -4412,7 +4450,7 @@
 				if (size == SZ_B) {
 					dst = xor_ir(dst, 1, adr_reg, SZ_D);
 				}
-				dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, mem_pointers) + sizeof(void*) * memmap[chunk].ptr_index, adr_reg, SZ_Q);
+				dst = add_rdisp8r(dst, CONTEXT, offsetof(m68k_context, mem_pointers) + sizeof(void*) * memmap[chunk].ptr_index, adr_reg, SZ_PTR);
 				if (is_write) {
 					dst = mov_rrind(dst, SCRATCH1, SCRATCH2, size);
 
@@ -4442,21 +4480,21 @@
 						dst = shr_ir(dst, 8, SCRATCH1, SZ_W);
 					}
 				}
-				if ((int64_t)memmap[chunk].buffer <= 0x7FFFFFFF && (int64_t)memmap[chunk].buffer >= -2147483648) {
+				if ((intptr_t)memmap[chunk].buffer <= 0x7FFFFFFF && (intptr_t)memmap[chunk].buffer >= -2147483648) {
 					if (is_write) {
-						dst = mov_rrdisp32(dst, SCRATCH1, SCRATCH2, (int64_t)memmap[chunk].buffer, tmp_size);
+						dst = mov_rrdisp32(dst, SCRATCH1, SCRATCH2, (intptr_t)memmap[chunk].buffer, tmp_size);
 					} else {
-						dst = mov_rdisp32r(dst, SCRATCH1, (int64_t)memmap[chunk].buffer, SCRATCH1, tmp_size);
+						dst = mov_rdisp32r(dst, SCRATCH1, (intptr_t)memmap[chunk].buffer, SCRATCH1, tmp_size);
 					}
 				} else {
 					if (is_write) {
 						dst = push_r(dst, SCRATCH1);
-						dst = mov_ir(dst, (int64_t)memmap[chunk].buffer, SCRATCH1, SZ_Q);
-						dst = add_rr(dst, SCRATCH1, SCRATCH2, SZ_Q);
+						dst = mov_ir(dst, (intptr_t)memmap[chunk].buffer, SCRATCH1, SZ_PTR);
+						dst = add_rr(dst, SCRATCH1, SCRATCH2, SZ_PTR);
 						dst = pop_r(dst, SCRATCH1);
 						dst = mov_rrind(dst, SCRATCH1, SCRATCH2, tmp_size);
 					} else {
-						dst = mov_ir(dst, (int64_t)memmap[chunk].buffer, SCRATCH2, SZ_Q);
+						dst = mov_ir(dst, (intptr_t)memmap[chunk].buffer, SCRATCH2, SZ_PTR);
 						dst = mov_rindexr(dst, SCRATCH2, SCRATCH1, 1, SCRATCH1, tmp_size);
 					}
 				}
@@ -4476,14 +4514,22 @@
 				uint8_t * not_code = dst+1;
 				dst = jcc(dst, CC_NC, dst+2);
 				dst = call(dst, opts->save_context);
+#ifdef X86_32
+				dst = push_r(dst, CONTEXT);
+				dst = push_r(dst, SCRATCH2);
+#endif
 				dst = call(dst, (uint8_t *)m68k_handle_code_write);
-				dst = mov_rr(dst, RAX, CONTEXT, SZ_Q);
+#ifdef X86_32
+				dst = add_ir(dst, 8, RSP, SZ_D);
+#endif
+				dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR);
 				dst = call(dst, opts->load_context);
 				*not_code = dst - (not_code+1);
 			}
 			dst = retn(dst);
 		} else if (cfun) {
 			dst = call(dst, opts->save_context);
+#ifdef X86_64
 			if (is_write) {
 				if (SCRATCH2 != RDI) {
 					dst = mov_rr(dst, SCRATCH2, RDI, SZ_D);
@@ -4500,12 +4546,23 @@
 			uint8_t *no_adjust = dst+1;
 			dst = jmp(dst, dst+2);
 			*adjust_rsp = dst - (adjust_rsp + 1);
-			dst = sub_ir(dst, 8, RSP, SZ_Q);
+			dst = sub_ir(dst, 8, RSP, SZ_PTR);
 			dst = call(dst, cfun);
-			dst = add_ir(dst, 8, RSP, SZ_Q);
+			dst = add_ir(dst, 8, RSP, SZ_PTR);
 			*no_adjust = dst - (no_adjust+1);
+#else
 			if (is_write) {
-				dst = mov_rr(dst, RAX, CONTEXT, SZ_Q);
+				dst = push_r(dst, SCRATCH1);
+			} else {
+				dst = push_r(dst, CONTEXT);//save CONTEXT for later
+			}
+			dst = push_r(dst, CONTEXT);
+			dst = push_r(dst, is_write ? SCRATCH2 : SCRATCH1);
+			dst = call(dst, cfun);
+			dst = add_ir(dst, is_write ? 12 : 8, RSP, SZ_D);
+#endif
+			if (is_write) {
+				dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR);
 			} else {
 				dst = pop_r(dst, CONTEXT);
 				dst = mov_rr(dst, RAX, SCRATCH1, size);
@@ -4611,8 +4668,9 @@
 	dst = retn(dst);
 
 	opts->start_context = (start_fun)dst;
+#ifdef X86_64
 	if (SCRATCH2 != RDI) {
-		dst = mov_rr(dst, RDI, SCRATCH2, SZ_Q);
+		dst = mov_rr(dst, RDI, SCRATCH2, SZ_PTR);
 	}
 	//save callee save registers
 	dst = push_r(dst, RBP);
@@ -4620,24 +4678,49 @@
 	dst = push_r(dst, R13);
 	dst = push_r(dst, R14);
 	dst = push_r(dst, R15);
+#else
+	//save callee save registers
+	dst = push_r(dst, RBP);
+	dst = push_r(dst, RBX);
+	dst = push_r(dst, RSI);
+	dst = push_r(dst, RDI);
+
+	dst = mov_rdisp8r(dst, RSP, 20, SCRATCH2, SZ_D);
+	dst = mov_rdisp8r(dst, RSP, 24, CONTEXT, SZ_D);
+#endif
 	dst = call(dst, opts->load_context);
 	dst = call_r(dst, SCRATCH2);
 	dst = call(dst, opts->save_context);
+#ifdef X86_64
 	//restore callee save registers
 	dst = pop_r(dst, R15);
 	dst = pop_r(dst, R14);
 	dst = pop_r(dst, R13);
 	dst = pop_r(dst, R12);
 	dst = pop_r(dst, RBP);
+#else
+	dst = pop_r(dst, RDI);
+	dst = pop_r(dst, RSI);
+	dst = pop_r(dst, RBX);
+	dst = pop_r(dst, RBP);
+#endif
 	dst = retn(dst);
 
 	opts->native_addr = dst;
 	dst = call(dst, opts->save_context);
 	dst = push_r(dst, CONTEXT);
-	dst = mov_rr(dst, CONTEXT, RDI, SZ_Q); //move context to 1st arg reg
+#ifdef X86_64
+	dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR); //move context to 1st arg reg
 	dst = mov_rr(dst, SCRATCH1, RSI, SZ_D); //move address to 2nd arg reg
+#else
+	dst = push_r(dst, SCRATCH1);
+	dst = push_r(dst, CONTEXT);
+#endif
 	dst = call(dst, (uint8_t *)get_native_address_trans);
-	dst = mov_rr(dst, RAX, SCRATCH1, SZ_Q); //move result to scratch reg
+#ifdef X86_32
+	dst = add_ir(dst, 8, RSP, SZ_D);
+#endif
+	dst = mov_rr(dst, RAX, SCRATCH1, SZ_PTR); //move result to scratch reg
 	dst = pop_r(dst, CONTEXT);
 	dst = call(dst, opts->load_context);
 	dst = retn(dst);
@@ -4645,24 +4728,40 @@
 	opts->native_addr_and_sync = dst;
 	dst = call(dst, opts->save_context);
 	dst = push_r(dst, SCRATCH1);
-	dst = mov_rr(dst, CONTEXT, RDI, SZ_Q);
+#ifdef X86_64
+	dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR);
 	dst = xor_rr(dst, RSI, RSI, SZ_D);
-	dst = test_ir(dst, 8, RSP, SZ_Q); //check stack alignment
+	dst = test_ir(dst, 8, RSP, SZ_PTR); //check stack alignment
 	uint8_t * do_adjust_rsp = dst+1;
 	dst = jcc(dst, CC_NZ, dst+2);
 	dst = call(dst, (uint8_t *)sync_components);
 	uint8_t * no_adjust_rsp = dst+1;
 	dst = jmp(dst, dst+2);
 	*do_adjust_rsp = dst - (do_adjust_rsp+1);
-	dst = sub_ir(dst, 8, RSP, SZ_Q);
+	dst = sub_ir(dst, 8, RSP, SZ_PTR);
 	dst = call(dst, (uint8_t *)sync_components);
-	dst = add_ir(dst, 8, RSP, SZ_Q);
+	dst = add_ir(dst, 8, RSP, SZ_PTR);
 	*no_adjust_rsp = dst - (no_adjust_rsp+1);
 	dst = pop_r(dst, RSI);
 	dst = push_r(dst, RAX);
-	dst = mov_rr(dst, RAX, RDI, SZ_Q);
+	dst = mov_rr(dst, RAX, RDI, SZ_PTR);
 	dst = call(dst, (uint8_t *)get_native_address_trans);
-	dst = mov_rr(dst, RAX, SCRATCH1, SZ_Q); //move result to scratch reg
+#else
+	//TODO: Add support for pushing a constant in gen_x86
+	dst = xor_rr(dst, RAX, RAX, SZ_D);
+	dst = push_r(dst, RAX);
+	dst = push_r(dst, CONTEXT);
+	dst = call(dst, (uint8_t *)sync_components);
+	dst = add_ir(dst, 8, RSP, SZ_D);
+	dst = pop_r(dst, RSI); //restore saved address from SCRATCH1
+	dst = push_r(dst, RAX); //save context pointer for later
+	dst = push_r(dst, RSI); //2nd arg -- address
+	dst = push_r(dst, RAX); //1st arg -- context pointer
+	dst = call(dst, (uint8_t *)get_native_address_trans);
+	dst = add_ir(dst, 8, RSP, SZ_D);
+#endif
+
+	dst = mov_rr(dst, RAX, SCRATCH1, SZ_PTR); //move result to scratch reg
 	dst = pop_r(dst, CONTEXT);
 	dst = call(dst, opts->load_context);
 	dst = retn(dst);
@@ -4675,7 +4774,8 @@
 	dst = push_r(dst, SCRATCH1);
 	dst = push_r(dst, SCRATCH2);
 	dst = call(dst, opts->save_context);
-	dst = mov_rr(dst, CONTEXT, RDI, SZ_Q);
+#ifdef X86_64
+	dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR);
 	dst = xor_rr(dst, RSI, RSI, SZ_D);
 	dst = test_ir(dst, 8, RSP, SZ_D);
 	uint8_t *adjust_rsp = dst+1;
@@ -4684,11 +4784,19 @@
 	uint8_t *no_adjust = dst+1;
 	dst = jmp(dst, dst+2);
 	*adjust_rsp = dst - (adjust_rsp + 1);
-	dst = sub_ir(dst, 8, RSP, SZ_Q);
+	dst = sub_ir(dst, 8, RSP, SZ_PTR);
 	dst = call(dst, (uint8_t *)sync_components);
-	dst = add_ir(dst, 8, RSP, SZ_Q);
+	dst = add_ir(dst, 8, RSP, SZ_PTR);
 	*no_adjust = dst - (no_adjust+1);
-	dst = mov_rr(dst, RAX, CONTEXT, SZ_Q);
+#else
+	//TODO: Add support for pushing a constant in gen_x86
+	dst = xor_rr(dst, RAX, RAX, SZ_D);
+	dst = push_r(dst, RAX);
+	dst = push_r(dst, CONTEXT);
+	dst = call(dst, (uint8_t *)sync_components);
+	dst = add_ir(dst, 8, RSP, SZ_D);
+#endif
+	dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR);
 	dst = call(dst, opts->load_context);
 	dst = pop_r(dst, SCRATCH2);
 	dst = pop_r(dst, SCRATCH1);
@@ -4806,7 +4914,8 @@
 	skip_sync = dst+1;
 	dst = jcc(dst, CC_C, dst+2);
 	dst = call(dst, opts->save_context);
-	dst = mov_rr(dst, CONTEXT, RDI, SZ_Q);
+#ifdef X86_64
+	dst = mov_rr(dst, CONTEXT, RDI, SZ_PTR);
 	dst = mov_rr(dst, SCRATCH1, RSI, SZ_D);
 	dst = test_ir(dst, 8, RSP, SZ_D);
 	adjust_rsp = dst+1;
@@ -4815,11 +4924,17 @@
 	no_adjust = dst+1;
 	dst = jmp(dst, dst+2);
 	*adjust_rsp = dst - (adjust_rsp + 1);
-	dst = sub_ir(dst, 8, RSP, SZ_Q);
+	dst = sub_ir(dst, 8, RSP, SZ_PTR);
 	dst = call(dst, (uint8_t *)sync_components);
-	dst = add_ir(dst, 8, RSP, SZ_Q);
+	dst = add_ir(dst, 8, RSP, SZ_PTR);
 	*no_adjust = dst - (no_adjust+1);
-	dst = mov_rr(dst, RAX, CONTEXT, SZ_Q);
+#else
+	dst = push_r(dst, SCRATCH1);
+	dst = push_r(dst, CONTEXT);
+	dst = call(dst, (uint8_t *)sync_components);
+	dst = add_ir(dst, 8, RSP, SZ_D);
+#endif
+	dst = mov_rr(dst, RAX, CONTEXT, SZ_PTR);
 	dst = jmp(dst, opts->load_context);
 	*skip_sync = dst - (skip_sync+1);
 	dst = retn(dst);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime_32.S	Wed Feb 19 00:22:27 2014 -0800
@@ -0,0 +1,74 @@
+
+
+invalid_msg:
+	.asciz "Invalid instruction at %X\n"
+
+	.global m68k_invalid
+m68k_invalid:
+	push %ecx
+	push invalid_msg
+	xor %eax, %eax
+	call printf
+	push $1
+	call exit
+
+	.global bcd_add
+bcd_add:
+	xchg %eax, %edi
+
+	mov %cl, %ch
+	mov %al, %ah
+	and $0xF, %ch
+	and $0xF, %ah
+	and $0xF0, %cl
+	and $0xF0, %al
+	add %ah, %ch
+	cmp $10, %ch
+	jb no_adjust
+	add $6, %ch
+no_adjust:
+	add %ch, %al
+	add %al, %cl
+	mov $0, %ch
+	jc def_adjust
+	cmp $0xA0, %cl
+	jb no_adjust_h
+def_adjust:
+	add $0x60, %cl
+	mov $1, %ch
+no_adjust_h:
+
+	mov %edi, %eax
+	ret
+
+	.global bcd_sub
+bcd_sub:
+	xchg %eax, %edi
+
+	mov %cl, %ch
+	mov %al, %ah
+	and $0xF, %ch
+	and $0xF, %ah
+	and $0xF0, %cl
+	and $0xF0, %al
+	sub %ah, %ch
+	cmp $10, %ch
+	jb no_adjusts
+	sub $6, %ch
+no_adjusts:
+	add %ch, %cl
+	sub %al, %cl
+	mov $0, %ch
+	jc def_adjusts
+	cmp $0xA0, %cl
+	jb no_adjust_hs
+def_adjusts:
+	sub $0x60, %cl
+	mov $1, %ch
+no_adjust_hs:
+
+	mov %edi, %eax
+	ret
+
+
+