--- a/Include/internal/pycore_ceval.h
+++ b/Include/internal/pycore_ceval.h
@@ -199,7 +199,11 @@ extern void _PyEval_DeactivateOpCache(vo
 static inline int _Py_MakeRecCheck(PyThreadState *tstate)  {
     uintptr_t here_addr = _Py_get_machine_stack_pointer();
     _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
+#ifdef __hppa__
+    return here_addr > _tstate->c_stack_soft_limit;
+#else
     return here_addr < _tstate->c_stack_soft_limit;
+#endif
 }
 
 // Export for '_json' shared extension, used via _Py_EnterRecursiveCall()
@@ -231,7 +235,11 @@ static inline int _Py_ReachedRecursionLi
     uintptr_t here_addr = _Py_get_machine_stack_pointer();
     _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
     assert(_tstate->c_stack_hard_limit != 0);
+#ifdef __hppa__
+    return here_addr >= _tstate->c_stack_soft_limit;
+#else
     return here_addr <= _tstate->c_stack_soft_limit;
+#endif
 }
 
 static inline void _Py_LeaveRecursiveCall(void)  {
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -333,13 +333,21 @@ _Py_ReachedRecursionLimitWithMargin(PyTh
 {
     uintptr_t here_addr = _Py_get_machine_stack_pointer();
     _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
+#ifdef __hppa__
+    if (here_addr <= _tstate->c_stack_soft_limit - margin_count * _PyOS_STACK_MARGIN_BYTES) {
+#else
     if (here_addr > _tstate->c_stack_soft_limit + margin_count * _PyOS_STACK_MARGIN_BYTES) {
+#endif
         return 0;
     }
     if (_tstate->c_stack_hard_limit == 0) {
         _Py_InitializeRecursionLimits(tstate);
     }
+#ifdef __hppa__
+    return here_addr > _tstate->c_stack_soft_limit - margin_count * _PyOS_STACK_MARGIN_BYTES;
+#else
     return here_addr <= _tstate->c_stack_soft_limit + margin_count * _PyOS_STACK_MARGIN_BYTES;
+#endif
 }
 
 void
@@ -347,7 +355,11 @@ _Py_EnterRecursiveCallUnchecked(PyThread
 {
     uintptr_t here_addr = _Py_get_machine_stack_pointer();
     _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
+#ifdef __hppa__
+    if (here_addr > _tstate->c_stack_hard_limit) {
+#else
     if (here_addr < _tstate->c_stack_hard_limit) {
+#endif
         Py_FatalError("Unchecked stack overflow.");
     }
 }
@@ -455,6 +467,18 @@ _Py_InitializeRecursionLimits(PyThreadSt
     }
     if (err == 0) {
         uintptr_t base = ((uintptr_t)stack_addr) + guard_size;
+#ifdef __hppa__
+        _tstate->c_stack_top = base;
+#ifdef _Py_THREAD_SANITIZER
+        // Thread sanitizer crashes if we use a bit more than half the stack.
+        _tstate->c_stack_soft_limit = base + (stack_size / 2);
+#else
+        _tstate->c_stack_soft_limit = base + stack_size - _PyOS_STACK_MARGIN_BYTES * 2;
+#endif
+        _tstate->c_stack_hard_limit = base + stack_size - _PyOS_STACK_MARGIN_BYTES;
+        assert(here_addr > base);
+        assert(here_addr < _tstate->c_stack_soft_limit);
+#else
         _tstate->c_stack_top = base + stack_size;
 #ifdef _Py_THREAD_SANITIZER
         // Thread sanitizer crashes if we use a bit more than half the stack.
@@ -465,6 +489,7 @@ _Py_InitializeRecursionLimits(PyThreadSt
         _tstate->c_stack_hard_limit = base + _PyOS_STACK_MARGIN_BYTES;
         assert(_tstate->c_stack_soft_limit < here_addr);
         assert(here_addr < _tstate->c_stack_top);
+#endif
         return;
     }
 #  endif
@@ -483,9 +508,15 @@ _Py_CheckRecursiveCall(PyThreadState *ts
     uintptr_t here_addr = _Py_get_machine_stack_pointer();
     assert(_tstate->c_stack_soft_limit != 0);
     assert(_tstate->c_stack_hard_limit != 0);
+#ifdef __hppa__
+    if (here_addr > _tstate->c_stack_hard_limit) {
+        /* Overflowing while handling an overflow. Give up. */
+        int kbytes_used = (int)(here_addr - _tstate->c_stack_top)/1024;
+#else
     if (here_addr < _tstate->c_stack_hard_limit) {
         /* Overflowing while handling an overflow. Give up. */
         int kbytes_used = (int)(_tstate->c_stack_top - here_addr)/1024;
+#endif
         char buffer[80];
         snprintf(buffer, 80, "Unrecoverable stack overflow (used %d kB)%s", kbytes_used, where);
         Py_FatalError(buffer);
@@ -494,7 +525,11 @@ _Py_CheckRecursiveCall(PyThreadState *ts
         return 0;
     }
     else {
+#ifdef __hppa__
+        int kbytes_used = (int)(here_addr - _tstate->c_stack_top)/1024;
+#else
         int kbytes_used = (int)(_tstate->c_stack_top - here_addr)/1024;
+#endif
         tstate->recursion_headroom++;
         _PyErr_Format(tstate, PyExc_RecursionError,
                     "Stack overflow (used %d kB)%s",
